virtualx-engine/thirdparty/mbedtls/library/mps_reader.h
Fabio Alessandrelli d76a26e086
Bump mbedTLS version to 2.28.0 (new LTS).
Keep applying the windows entropy patch (UWP support).
Remove no longer needed padlock patch.
Update thirdparty README to reflect changes, and new source inclusion
criteria.

(cherry picked from commit e375cbd094)
2022-01-19 14:03:03 +01:00

382 lines
18 KiB
C++

/*
* 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 */