summaryrefslogtreecommitdiff
path: root/thirdparty/mbedtls/library/mps_reader.h
blob: 427c1bd254f9e605e95dd86cfe5b765c7191e159 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/*
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
 *  not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  This file is part of mbed TLS (https://tls.mbed.org)
 */

/**
 * \file mps_reader.h
 *
 * \brief This file defines reader objects, which together with their
 *        sibling writer objects form the basis for the communication
 *        between the various layers of the Mbed TLS messaging stack,
 *        as well as the communication between the messaging stack and
 *        the (D)TLS handshake protocol implementation.
 *
 * Readers provide a means of transferring incoming data from
 * a 'producer' providing it in chunks of arbitrary size, to
 * a 'consumer' which fetches and processes it in chunks of
 * again arbitrary, and potentially different, size.
 *
 * Readers can thus be seen as datagram-to-stream converters,
 * and they abstract away the following two tasks from the user:
 * 1. The pointer arithmetic of stepping through a producer-
 *    provided chunk in smaller chunks.
 * 2. The merging of incoming data chunks in case the
 *    consumer requests data in larger chunks than what the
 *    producer provides.
 *
 * The basic abstract flow of operation is the following:
 * - Initially, the reader is in 'producing mode'.
 * - The producer hands an incoming data buffer to the reader,
 *   moving it from 'producing' to 'consuming' mode.
 * - The consumer subsequently fetches and processes the buffer
 *   content. Once that's done -- or partially done and a consumer's
 *   request can't be fulfilled -- the producer revokes the reader's
 *   access to the incoming data buffer, putting the reader back to
 *   producing mode.
 * - The producer subsequently gathers more incoming data and hands
 *   it to the reader until it switches back to consuming mode
 *   if enough data is available for the last consumer request to
 *   be satisfiable.
 * - Repeat the above.
 *
 * The abstract states of the reader from the producer's and
 * consumer's perspective are as follows:
 *
 * - From the perspective of the consumer, the state of the
 *   reader consists of the following:
 *   - A byte stream representing (concatenation of) the data
 *     received through calls to mbedtls_mps_reader_get(),
 *   - A marker within that byte stream indicating which data
 *     can be considered processed, and hence need not be retained,
 *     when the reader is passed back to the producer via
 *     mbedtls_mps_reader_reclaim().
 *     The marker is set via mbedtls_mps_reader_commit()
 *     which places it at the end of the current byte stream.
 *   The consumer need not be aware of the distinction between consumer
 *   and producer mode, because it only interfaces with the reader
 *   when the latter is in consuming mode.
 *
 * - From the perspective of the producer, the reader's state is one of:
 *   - Attached: The reader is in consuming mode.
 *   - Unset: No incoming data buffer is currently managed by the reader,
 *            and all previously handed incoming data buffers have been
 *            fully processed. More data needs to be fed into the reader
 *            via mbedtls_mps_reader_feed().
 *
 *   - Accumulating: No incoming data buffer is currently managed by the
 *                   reader, but some data from the previous incoming data
 *                   buffer hasn't been processed yet and is internally
 *                   held back.
 *   The Attached state belongs to consuming mode, while the Unset and
 *   Accumulating states belong to producing mode.
 *
 * Transitioning from the Unset or Accumulating state to Attached is
 * done via successful calls to mbedtls_mps_reader_feed(), while
 * transitioning from Attached to either Unset or Accumulating (depending
 * on what has been processed) is done via mbedtls_mps_reader_reclaim().
 *
 * The following diagram depicts the producer-state progression:
 *
 *        +------------------+             reclaim
 *        |      Unset       +<-------------------------------------+       get
 *        +--------|---------+                                      |   +------+
 *                 |                                                |   |      |
 *                 |                                                |   |      |
 *                 |                feed                  +---------+---+--+   |
 *                 +-------------------------------------->                <---+
 *                                                        |    Attached    |
 *                 +-------------------------------------->                <---+
 *                 |     feed, enough data available      +---------+---+--+   |
 *                 |     to serve previous consumer request         |   |      |
 *                 |                                                |   |      |
 *        +--------+---------+                                      |   +------+
 *   +---->   Accumulating   |<-------------------------------------+    commit
 *   |    +---+--------------+      reclaim, previous read request
 *   |        |                        couldn't be fulfilled
 *   |        |
 *   +--------+
 *     feed, need more data to serve
 *     previous consumer request
 *                                         |
 *                                         |
 *               producing mode            |           consuming mode
 *                                         |
 *
 */

#ifndef MBEDTLS_READER_H
#define MBEDTLS_READER_H

#include <stdio.h>

#include "mps_common.h"
#include "mps_error.h"

struct mbedtls_mps_reader;
typedef struct mbedtls_mps_reader mbedtls_mps_reader;

/*
 * Structure definitions
 */

struct mbedtls_mps_reader
{
    unsigned char *frag;  /*!< The fragment of incoming data managed by
                           *   the reader; it is provided to the reader
                           *   through mbedtls_mps_reader_feed(). The reader
                           *   does not own the fragment and does not
                           *   perform any allocation operations on it,
                           *   but does have read and write access to it.
                           *
                           *   The reader is in consuming mode if
                           *   and only if \c frag is not \c NULL.          */
    mbedtls_mps_stored_size_t frag_len;
                          /*!< The length of the current fragment.
                           *   Must be 0 if \c frag == \c NULL.             */
    mbedtls_mps_stored_size_t commit;
                          /*!< The offset of the last commit, relative
                           *   to the first byte in the fragment, if
                           *   no accumulator is present. If an accumulator
                           *   is present, it is viewed as a prefix to the
                           *   current fragment, and this variable contains
                           *   an offset from the beginning of the accumulator.
                           *
                           *   This is only used when the reader is in
                           *   consuming mode, i.e. \c frag != \c NULL;
                           *   otherwise, its value is \c 0.                */
    mbedtls_mps_stored_size_t end;
                          /*!< The offset of the end of the last chunk
                           *   passed to the user through a call to
                           *   mbedtls_mps_reader_get(), relative to the first
                           *   byte in the fragment, if no accumulator is
                           *   present. If an accumulator is present, it is
                           *   viewed as a prefix to the current fragment, and
                           *   this variable contains an offset from the
                           *   beginning of the accumulator.
                           *
                           *   This is only used when the reader is in
                           *   consuming mode, i.e. \c frag != \c NULL;
                           *   otherwise, its value is \c 0.                */
    mbedtls_mps_stored_size_t pending;
                          /*!< The amount of incoming data missing on the
                           *   last call to mbedtls_mps_reader_get().
                           *   In particular, it is \c 0 if the last call
                           *   was successful.
                           *   If a reader is reclaimed after an
                           *   unsuccessful call to mbedtls_mps_reader_get(),
                           *   this variable is used to have the reader
                           *   remember how much data should be accumulated
                           *   so that the call to mbedtls_mps_reader_get()
                           *   succeeds next time.
                           *   This is only used when the reader is in
                           *   consuming mode, i.e. \c frag != \c NULL;
                           *   otherwise, its value is \c 0.                */

    /* The accumulator is only needed if we need to be able to pause
     * the reader. A few bytes could be saved by moving this to a
     * separate struct and using a pointer here. */

    unsigned char *acc;   /*!< The accumulator is used to gather incoming
                           *   data if a read-request via mbedtls_mps_reader_get()
                           *   cannot be served from the current fragment.   */
    mbedtls_mps_stored_size_t acc_len;
                           /*!< The total size of the accumulator.           */
    mbedtls_mps_stored_size_t acc_available;
                          /*!< The number of bytes currently gathered in
                           *   the accumulator. This is both used in
                           *   producing and in consuming mode:
                           *   While producing, it is increased until
                           *   it reaches the value of \c acc_remaining below.
                           *   While consuming, it is used to judge if a
                           *   get request can be served from the
                           *   accumulator or not.
                           *   Must not be larger than \c acc_len.           */
    union
    {
        mbedtls_mps_stored_size_t acc_remaining;
                              /*!< This indicates the amount of data still
                               *   to be gathered in the accumulator. It is
                               *   only used in producing mode.
                               *   Must be at most acc_len - acc_available.  */
        mbedtls_mps_stored_size_t frag_offset;
                              /*!< If an accumulator is present and in use, this
                               *   field indicates the offset of the current
                               *   fragment from the beginning of the
                               *   accumulator. If no accumulator is present
                               *   or the accumulator is not in use, this is \c 0.
                               *   It is only used in consuming mode.
                               *   Must not be larger than \c acc_available. */
    } acc_share;
};

/*
 * API organization:
 * A reader object is usually prepared and maintained
 * by some lower layer and passed for usage to an upper
 * layer, and the API naturally splits according to which
 * layer is supposed to use the respective functions.
 */

/*
 * Maintenance API (Lower layer)
 */

/**
 * \brief           Initialize a reader object
 *
 * \param reader    The reader to be initialized.
 * \param acc       The buffer to be used as a temporary accumulator
 *                  in case get requests through mbedtls_mps_reader_get()
 *                  exceed the buffer provided by mbedtls_mps_reader_feed().
 *                  This buffer is owned by the caller and exclusive use
 *                  for reading and writing is given to the reader for the
 *                  duration of the reader's lifetime. It is thus the caller's
 *                  responsibility to maintain (and not touch) the buffer for
 *                  the lifetime of the reader, and to properly zeroize and
 *                  free the memory after the reader has been destroyed.
 * \param acc_len   The size in Bytes of \p acc.
 *
 * \return          \c 0 on success.
 * \return          A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
 */
int mbedtls_mps_reader_init( mbedtls_mps_reader *reader,
                             unsigned char *acc,
                             mbedtls_mps_size_t acc_len );

/**
 * \brief           Free a reader object
 *
 * \param reader    The reader to be freed.
 *
 * \return          \c 0 on success.
 * \return          A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
 */
int mbedtls_mps_reader_free( mbedtls_mps_reader *reader );

/**
 * \brief           Pass chunk of data for the reader to manage.
 *
 * \param reader    The reader context to use. The reader must be
 *                  in producing mode.
 * \param buf       The buffer to be managed by the reader.
 * \param buflen    The size in Bytes of \p buffer.
 *
 * \return          \c 0 on success. In this case, the reader will be
 *                  moved to consuming mode and obtains read access
 *                  of \p buf until mbedtls_mps_reader_reclaim()
 *                  is called. It is the responsibility of the caller
 *                  to ensure that the \p buf persists and is not changed
 *                  between successful calls to mbedtls_mps_reader_feed()
 *                  and mbedtls_mps_reader_reclaim().
 * \return          \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is
 *                  required to fulfill a previous request to mbedtls_mps_reader_get().
 *                  In this case, the reader remains in producing mode and
 *                  takes no ownership of the provided buffer (an internal copy
 *                  is made instead).
 * \return          Another negative \c MBEDTLS_ERR_READER_XXX error code on
 *                  different kinds of failures.
 */
int mbedtls_mps_reader_feed( mbedtls_mps_reader *reader,
                             unsigned char *buf,
                             mbedtls_mps_size_t buflen );

/**
 * \brief           Reclaim reader's access to the current input buffer.
 *
 * \param reader    The reader context to use. The reader must be
 *                  in consuming mode.
 * \param paused    If not \c NULL, the integer at address \p paused will be
 *                  modified to indicate whether the reader has been paused
 *                  (value \c 1) or not (value \c 0). Pausing happens if there
 *                  is uncommitted data and a previous request to
 *                  mbedtls_mps_reader_get() has exceeded the bounds of the
 *                  input buffer.
 *
 * \return          \c 0 on success.
 * \return          A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
 */
int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *reader,
                                int *paused );

/*
 * Usage API (Upper layer)
 */

/**
 * \brief           Request data from the reader.
 *
 * \param reader    The reader context to use. The reader must
 *                  be in consuming mode.
 * \param desired   The desired amount of data to be read, in Bytes.
 * \param buffer    The address to store the buffer pointer in.
 *                  This must not be \c NULL.
 * \param buflen    The address to store the actual buffer
 *                  length in, or \c NULL.
 *
 * \return          \c 0 on success. In this case, \c *buf holds the
 *                  address of a buffer of size \c *buflen
 *                  (if \c buflen != \c NULL) or \c desired
 *                  (if \c buflen == \c NULL). The user has read access
 *                  to the buffer and guarantee of stability of the data
 *                  until the next call to mbedtls_mps_reader_reclaim().
 * \return          #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough
 *                  data available to serve the get request. In this case, the
 *                  reader remains intact and in consuming mode, and the consumer
 *                  should retry the call after a successful cycle of
 *                  mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed().
 *                  If, after such a cycle, the consumer requests a different
 *                  amount of data, the result is implementation-defined;
 *                  progress is guaranteed only if the same amount of data
 *                  is requested after a mbedtls_mps_reader_reclaim() and
 *                  mbedtls_mps_reader_feed() cycle.
 * \return          Another negative \c MBEDTLS_ERR_READER_XXX error
 *                  code for different kinds of failure.
 *
 * \note            Passing \c NULL as \p buflen is a convenient way to
 *                  indicate that fragmentation is not tolerated.
 *                  It's functionally equivalent to passing a valid
 *                  address as buflen and checking \c *buflen == \c desired
 *                  afterwards.
 */
int mbedtls_mps_reader_get( mbedtls_mps_reader *reader,
                            mbedtls_mps_size_t desired,
                            unsigned char **buffer,
                            mbedtls_mps_size_t *buflen );

/**
 * \brief         Mark data obtained from mbedtls_mps_reader_get() as processed.
 *
 *                This call indicates that all data received from prior calls to
 *                mbedtls_mps_reader_get() has been or will have been
 *                processed when mbedtls_mps_reader_reclaim() is called,
 *                and thus need not be backed up.
 *
 *                This function has no user observable effect until
 *                mbedtls_mps_reader_reclaim() is called. In particular,
 *                buffers received from mbedtls_mps_reader_get() remain
 *                valid until mbedtls_mps_reader_reclaim() is called.
 *
 * \param reader  The reader context to use.
 *
 * \return        \c 0 on success.
 * \return        A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
 *
 */
int mbedtls_mps_reader_commit( mbedtls_mps_reader *reader );

#endif /* MBEDTLS_READER_H */