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