blob: 3193a5e334e329998680de0fddcd848beb1b5677 [file] [log] [blame]
Tom Rini0344c602024-10-08 13:56:50 -06001/*
2 * Copyright The Mbed TLS Contributors
3 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
4 */
5
6/**
7 * \file mps_reader.h
8 *
9 * \brief This file defines reader objects, which together with their
10 * sibling writer objects form the basis for the communication
11 * between the various layers of the Mbed TLS messaging stack,
12 * as well as the communication between the messaging stack and
13 * the (D)TLS handshake protocol implementation.
14 *
15 * Readers provide a means of transferring incoming data from
16 * a 'producer' providing it in chunks of arbitrary size, to
17 * a 'consumer' which fetches and processes it in chunks of
18 * again arbitrary, and potentially different, size.
19 *
20 * Readers can thus be seen as datagram-to-stream converters,
21 * and they abstract away the following two tasks from the user:
22 * 1. The pointer arithmetic of stepping through a producer-
23 * provided chunk in smaller chunks.
24 * 2. The merging of incoming data chunks in case the
25 * consumer requests data in larger chunks than what the
26 * producer provides.
27 *
28 * The basic abstract flow of operation is the following:
29 * - Initially, the reader is in 'producing mode'.
30 * - The producer hands an incoming data buffer to the reader,
31 * moving it from 'producing' to 'consuming' mode.
32 * - The consumer subsequently fetches and processes the buffer
33 * content. Once that's done -- or partially done and a consumer's
34 * request can't be fulfilled -- the producer revokes the reader's
35 * access to the incoming data buffer, putting the reader back to
36 * producing mode.
37 * - The producer subsequently gathers more incoming data and hands
38 * it to the reader until it switches back to consuming mode
39 * if enough data is available for the last consumer request to
40 * be satisfiable.
41 * - Repeat the above.
42 *
43 * The abstract states of the reader from the producer's and
44 * consumer's perspective are as follows:
45 *
46 * - From the perspective of the consumer, the state of the
47 * reader consists of the following:
48 * - A byte stream representing (concatenation of) the data
49 * received through calls to mbedtls_mps_reader_get(),
50 * - A marker within that byte stream indicating which data
51 * can be considered processed, and hence need not be retained,
52 * when the reader is passed back to the producer via
53 * mbedtls_mps_reader_reclaim().
54 * The marker is set via mbedtls_mps_reader_commit()
55 * which places it at the end of the current byte stream.
56 * The consumer need not be aware of the distinction between consumer
57 * and producer mode, because it only interfaces with the reader
58 * when the latter is in consuming mode.
59 *
60 * - From the perspective of the producer, the reader's state is one of:
61 * - Attached: The reader is in consuming mode.
62 * - Unset: No incoming data buffer is currently managed by the reader,
63 * and all previously handed incoming data buffers have been
64 * fully processed. More data needs to be fed into the reader
65 * via mbedtls_mps_reader_feed().
66 *
67 * - Accumulating: No incoming data buffer is currently managed by the
68 * reader, but some data from the previous incoming data
69 * buffer hasn't been processed yet and is internally
70 * held back.
71 * The Attached state belongs to consuming mode, while the Unset and
72 * Accumulating states belong to producing mode.
73 *
74 * Transitioning from the Unset or Accumulating state to Attached is
75 * done via successful calls to mbedtls_mps_reader_feed(), while
76 * transitioning from Attached to either Unset or Accumulating (depending
77 * on what has been processed) is done via mbedtls_mps_reader_reclaim().
78 *
79 * The following diagram depicts the producer-state progression:
80 *
81 * +------------------+ reclaim
82 * | Unset +<-------------------------------------+ get
83 * +--------|---------+ | +------+
84 * | | | |
85 * | | | |
86 * | feed +---------+---+--+ |
87 * +--------------------------------------> <---+
88 * | Attached |
89 * +--------------------------------------> <---+
90 * | feed, enough data available +---------+---+--+ |
91 * | to serve previous consumer request | | |
92 * | | | |
93 * +--------+---------+ | +------+
94 * +----> Accumulating |<-------------------------------------+ commit
95 * | +---+--------------+ reclaim, previous read request
96 * | | couldn't be fulfilled
97 * | |
98 * +--------+
99 * feed, need more data to serve
100 * previous consumer request
101 * |
102 * |
103 * producing mode | consuming mode
104 * |
105 *
106 */
107
108#ifndef MBEDTLS_READER_H
109#define MBEDTLS_READER_H
110
111#include <stdio.h>
112
113#include "mps_common.h"
114#include "mps_error.h"
115
116struct mbedtls_mps_reader;
117typedef struct mbedtls_mps_reader mbedtls_mps_reader;
118
119/*
120 * Structure definitions
121 */
122
123struct mbedtls_mps_reader {
124 unsigned char *frag; /*!< The fragment of incoming data managed by
125 * the reader; it is provided to the reader
126 * through mbedtls_mps_reader_feed(). The reader
127 * does not own the fragment and does not
128 * perform any allocation operations on it,
129 * but does have read and write access to it.
130 *
131 * The reader is in consuming mode if
132 * and only if \c frag is not \c NULL. */
133 mbedtls_mps_stored_size_t frag_len;
134 /*!< The length of the current fragment.
135 * Must be 0 if \c frag == \c NULL. */
136 mbedtls_mps_stored_size_t commit;
137 /*!< The offset of the last commit, relative
138 * to the first byte in the fragment, if
139 * no accumulator is present. If an accumulator
140 * is present, it is viewed as a prefix to the
141 * current fragment, and this variable contains
142 * an offset from the beginning of the accumulator.
143 *
144 * This is only used when the reader is in
145 * consuming mode, i.e. \c frag != \c NULL;
146 * otherwise, its value is \c 0. */
147 mbedtls_mps_stored_size_t end;
148 /*!< The offset of the end of the last chunk
149 * passed to the user through a call to
150 * mbedtls_mps_reader_get(), relative to the first
151 * byte in the fragment, if no accumulator is
152 * present. If an accumulator is present, it is
153 * viewed as a prefix to the current fragment, and
154 * this variable contains an offset from the
155 * beginning of the accumulator.
156 *
157 * This is only used when the reader is in
158 * consuming mode, i.e. \c frag != \c NULL;
159 * otherwise, its value is \c 0. */
160 mbedtls_mps_stored_size_t pending;
161 /*!< The amount of incoming data missing on the
162 * last call to mbedtls_mps_reader_get().
163 * In particular, it is \c 0 if the last call
164 * was successful.
165 * If a reader is reclaimed after an
166 * unsuccessful call to mbedtls_mps_reader_get(),
167 * this variable is used to have the reader
168 * remember how much data should be accumulated
169 * so that the call to mbedtls_mps_reader_get()
170 * succeeds next time.
171 * This is only used when the reader is in
172 * consuming mode, i.e. \c frag != \c NULL;
173 * otherwise, its value is \c 0. */
174
175 /* The accumulator is only needed if we need to be able to pause
176 * the reader. A few bytes could be saved by moving this to a
177 * separate struct and using a pointer here. */
178
179 unsigned char *acc; /*!< The accumulator is used to gather incoming
180 * data if a read-request via mbedtls_mps_reader_get()
181 * cannot be served from the current fragment. */
182 mbedtls_mps_stored_size_t acc_len;
183 /*!< The total size of the accumulator. */
184 mbedtls_mps_stored_size_t acc_available;
185 /*!< The number of bytes currently gathered in
186 * the accumulator. This is both used in
187 * producing and in consuming mode:
188 * While producing, it is increased until
189 * it reaches the value of \c acc_remaining below.
190 * While consuming, it is used to judge if a
191 * get request can be served from the
192 * accumulator or not.
193 * Must not be larger than \c acc_len. */
194 union {
195 mbedtls_mps_stored_size_t acc_remaining;
196 /*!< This indicates the amount of data still
197 * to be gathered in the accumulator. It is
198 * only used in producing mode.
199 * Must be at most acc_len - acc_available. */
200 mbedtls_mps_stored_size_t frag_offset;
201 /*!< If an accumulator is present and in use, this
202 * field indicates the offset of the current
203 * fragment from the beginning of the
204 * accumulator. If no accumulator is present
205 * or the accumulator is not in use, this is \c 0.
206 * It is only used in consuming mode.
207 * Must not be larger than \c acc_available. */
208 } acc_share;
209};
210
211/*
212 * API organization:
213 * A reader object is usually prepared and maintained
214 * by some lower layer and passed for usage to an upper
215 * layer, and the API naturally splits according to which
216 * layer is supposed to use the respective functions.
217 */
218
219/*
220 * Maintenance API (Lower layer)
221 */
222
223/**
224 * \brief Initialize a reader object
225 *
226 * \param reader The reader to be initialized.
227 * \param acc The buffer to be used as a temporary accumulator
228 * in case get requests through mbedtls_mps_reader_get()
229 * exceed the buffer provided by mbedtls_mps_reader_feed().
230 * This buffer is owned by the caller and exclusive use
231 * for reading and writing is given to the reader for the
232 * duration of the reader's lifetime. It is thus the caller's
233 * responsibility to maintain (and not touch) the buffer for
234 * the lifetime of the reader, and to properly zeroize and
235 * free the memory after the reader has been destroyed.
236 * \param acc_len The size in Bytes of \p acc.
237 *
238 * \return \c 0 on success.
239 * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
240 */
241int mbedtls_mps_reader_init(mbedtls_mps_reader *reader,
242 unsigned char *acc,
243 mbedtls_mps_size_t acc_len);
244
245/**
246 * \brief Free a reader object
247 *
248 * \param reader The reader to be freed.
249 *
250 * \return \c 0 on success.
251 * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
252 */
253int mbedtls_mps_reader_free(mbedtls_mps_reader *reader);
254
255/**
256 * \brief Pass chunk of data for the reader to manage.
257 *
258 * \param reader The reader context to use. The reader must be
259 * in producing mode.
260 * \param buf The buffer to be managed by the reader.
261 * \param buflen The size in Bytes of \p buffer.
262 *
263 * \return \c 0 on success. In this case, the reader will be
264 * moved to consuming mode and obtains read access
265 * of \p buf until mbedtls_mps_reader_reclaim()
266 * is called. It is the responsibility of the caller
267 * to ensure that the \p buf persists and is not changed
268 * between successful calls to mbedtls_mps_reader_feed()
269 * and mbedtls_mps_reader_reclaim().
270 * \return \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is
271 * required to fulfill a previous request to mbedtls_mps_reader_get().
272 * In this case, the reader remains in producing mode and
273 * takes no ownership of the provided buffer (an internal copy
274 * is made instead).
275 * \return Another negative \c MBEDTLS_ERR_READER_XXX error code on
276 * different kinds of failures.
277 */
278int mbedtls_mps_reader_feed(mbedtls_mps_reader *reader,
279 unsigned char *buf,
280 mbedtls_mps_size_t buflen);
281
282/**
283 * \brief Reclaim reader's access to the current input buffer.
284 *
285 * \param reader The reader context to use. The reader must be
286 * in consuming mode.
287 * \param paused If not \c NULL, the integer at address \p paused will be
288 * modified to indicate whether the reader has been paused
289 * (value \c 1) or not (value \c 0). Pausing happens if there
290 * is uncommitted data and a previous request to
291 * mbedtls_mps_reader_get() has exceeded the bounds of the
292 * input buffer.
293 *
294 * \return \c 0 on success.
295 * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
296 */
297int mbedtls_mps_reader_reclaim(mbedtls_mps_reader *reader,
298 int *paused);
299
300/*
301 * Usage API (Upper layer)
302 */
303
304/**
305 * \brief Request data from the reader.
306 *
307 * \param reader The reader context to use. The reader must
308 * be in consuming mode.
309 * \param desired The desired amount of data to be read, in Bytes.
310 * \param buffer The address to store the buffer pointer in.
311 * This must not be \c NULL.
312 * \param buflen The address to store the actual buffer
313 * length in, or \c NULL.
314 *
315 * \return \c 0 on success. In this case, \c *buf holds the
316 * address of a buffer of size \c *buflen
317 * (if \c buflen != \c NULL) or \c desired
318 * (if \c buflen == \c NULL). The user has read access
319 * to the buffer and guarantee of stability of the data
320 * until the next call to mbedtls_mps_reader_reclaim().
321 * \return #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough
322 * data available to serve the get request. In this case, the
323 * reader remains intact and in consuming mode, and the consumer
324 * should retry the call after a successful cycle of
325 * mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed().
326 * If, after such a cycle, the consumer requests a different
327 * amount of data, the result is implementation-defined;
328 * progress is guaranteed only if the same amount of data
329 * is requested after a mbedtls_mps_reader_reclaim() and
330 * mbedtls_mps_reader_feed() cycle.
331 * \return Another negative \c MBEDTLS_ERR_READER_XXX error
332 * code for different kinds of failure.
333 *
334 * \note Passing \c NULL as \p buflen is a convenient way to
335 * indicate that fragmentation is not tolerated.
336 * It's functionally equivalent to passing a valid
337 * address as buflen and checking \c *buflen == \c desired
338 * afterwards.
339 */
340int mbedtls_mps_reader_get(mbedtls_mps_reader *reader,
341 mbedtls_mps_size_t desired,
342 unsigned char **buffer,
343 mbedtls_mps_size_t *buflen);
344
345/**
346 * \brief Mark data obtained from mbedtls_mps_reader_get() as processed.
347 *
348 * This call indicates that all data received from prior calls to
349 * mbedtls_mps_reader_get() has been or will have been
350 * processed when mbedtls_mps_reader_reclaim() is called,
351 * and thus need not be backed up.
352 *
353 * This function has no user observable effect until
354 * mbedtls_mps_reader_reclaim() is called. In particular,
355 * buffers received from mbedtls_mps_reader_get() remain
356 * valid until mbedtls_mps_reader_reclaim() is called.
357 *
358 * \param reader The reader context to use.
359 *
360 * \return \c 0 on success.
361 * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
362 *
363 */
364int mbedtls_mps_reader_commit(mbedtls_mps_reader *reader);
365
366#endif /* MBEDTLS_READER_H */