quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

mps_reader.h (16990B)


      1 /*
      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 
    116 struct mbedtls_mps_reader;
    117 typedef struct mbedtls_mps_reader mbedtls_mps_reader;
    118 
    119 /*
    120  * Structure definitions
    121  */
    122 
    123 struct 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  */
    241 int 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  */
    253 int 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  */
    278 int 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  */
    297 int 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  */
    340 int 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  */
    364 int mbedtls_mps_reader_commit(mbedtls_mps_reader *reader);
    365 
    366 #endif /* MBEDTLS_READER_H */