godot/thirdparty/mbedtls/library/ssl_msg.c

/*
 *  Generic SSL/TLS messaging layer functions
 *  (record layer + retransmission state machine)
 *
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 */
/*
 *  http://www.ietf.org/rfc/rfc2246.txt
 *  http://www.ietf.org/rfc/rfc4346.txt
 */

#include "common.h"

#if defined(MBEDTLS_SSL_TLS_C)

#include "mbedtls/platform.h"

#include "mbedtls/ssl.h"
#include "ssl_misc.h"
#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/version.h"
#include "constant_time_internal.h"
#include "mbedtls/constant_time.h"

#include <string.h>

#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa_util_internal.h"
#include "psa/crypto.h"
#endif

#if defined(MBEDTLS_X509_CRT_PARSE_C)
#include "mbedtls/oid.h"
#endif

#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Define a local translating function to save code size by not using too many
 * arguments in each translating place. */
static int local_err_translation(psa_status_t status)
{
    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
                                 ARRAY_LENGTH(psa_to_ssl_errors),
                                 psa_generic_status_to_mbedtls);
}
#define PSA_TO_MBEDTLS_ERR
#endif

#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)

#if defined(MBEDTLS_USE_PSA_CRYPTO)

#if defined(PSA_WANT_ALG_SHA_384)
#define MAX_HASH_BLOCK_LENGTH
#elif defined(PSA_WANT_ALG_SHA_256)
#define MAX_HASH_BLOCK_LENGTH
#else /* See check_config.h */
#define MAX_HASH_BLOCK_LENGTH
#endif

MBEDTLS_STATIC_TESTABLE
int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
                    psa_algorithm_t mac_alg,
                    const unsigned char *add_data,
                    size_t add_data_len,
                    const unsigned char *data,
                    size_t data_len_secret,
                    size_t min_data_len,
                    size_t max_data_len,
                    unsigned char *output)
{
    /*
     * This function breaks the HMAC abstraction and uses psa_hash_clone()
     * extension in order to get constant-flow behaviour.
     *
     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
     * concatenation, and okey/ikey are the XOR of the key with some fixed bit
     * patterns (see RFC 2104, sec. 2).
     *
     * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
     * hashing up to minlen, then cloning the context, and for each byte up
     * to maxlen finishing up the hash computation, keeping only the
     * correct result.
     *
     * Then we only need to compute HASH(okey + inner_hash) and we're done.
     */
    psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
    const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
    unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
    const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
    size_t hash_length;

    unsigned char aux_out[PSA_HASH_MAX_SIZE];
    psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
    size_t offset;
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;

    size_t mac_key_length;
    size_t i;

#define PSA_CHK

    /* Export MAC key
     * We assume key length is always exactly the output size
     * which is never more than the block size, thus we use block_size
     * as the key buffer size.
     */
    PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));

    /* Calculate ikey */
    for (i = 0; i < mac_key_length; i++) {
        key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
    }
    for (; i < block_size; ++i) {
        key_buf[i] = 0x36;
    }

    PSA_CHK(psa_hash_setup(&operation, hash_alg));

    /* Now compute inner_hash = HASH(ikey + msg) */
    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
    PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
    PSA_CHK(psa_hash_update(&operation, data, min_data_len));

    /* Fill the hash buffer in advance with something that is
     * not a valid hash (barring an attack on the hash and
     * deliberately-crafted input), in case the caller doesn't
     * check the return status properly. */
    memset(output, '!', hash_size);

    /* For each possible length, compute the hash up to that point */
    for (offset = min_data_len; offset <= max_data_len; offset++) {
        PSA_CHK(psa_hash_clone(&operation, &aux_operation));
        PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
                                PSA_HASH_MAX_SIZE, &hash_length));
        /* Keep only the correct inner_hash in the output buffer */
        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),
                             output, aux_out, NULL, hash_size);

        if (offset < max_data_len) {
            PSA_CHK(psa_hash_update(&operation, data + offset, 1));
        }
    }

    /* Abort current operation to prepare for final operation */
    PSA_CHK(psa_hash_abort(&operation));

    /* Calculate okey */
    for (i = 0; i < mac_key_length; i++) {
        key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
    }
    for (; i < block_size; ++i) {
        key_buf[i] = 0x5C;
    }

    /* Now compute HASH(okey + inner_hash) */
    PSA_CHK(psa_hash_setup(&operation, hash_alg));
    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
    PSA_CHK(psa_hash_update(&operation, output, hash_size));
    PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));

#undef PSA_CHK

cleanup:
    mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
    mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);

    psa_hash_abort(&operation);
    psa_hash_abort(&aux_operation);
    return PSA_TO_MBEDTLS_ERR(status);
}

#undef MAX_HASH_BLOCK_LENGTH

#else
MBEDTLS_STATIC_TESTABLE
int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
                    const unsigned char *add_data,
                    size_t add_data_len,
                    const unsigned char *data,
                    size_t data_len_secret,
                    size_t min_data_len,
                    size_t max_data_len,
                    unsigned char *output)
{}

#endif /* MBEDTLS_USE_PSA_CRYPTO */

#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */

static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl);

/*
 * Start a timer.
 * Passing millisecs = 0 cancels a running timer.
 */
void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs)
{}

/*
 * Return -1 is timer is expired, 0 if it isn't.
 */
int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
                                   unsigned char *buf,
                                   size_t len,
                                   mbedtls_record *rec);

int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl,
                             unsigned char *buf,
                             size_t buflen)
{}

#define SSL_DONT_FORCE_FLUSH
#define SSL_FORCE_FLUSH

#if defined(MBEDTLS_SSL_PROTO_DTLS)

/* Forward declarations for functions related to message buffering. */
static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
                                    uint8_t slot);
static void ssl_free_buffered_record(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_record(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_message(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_future_record(mbedtls_ssl_context *ssl,
                                    mbedtls_record const *rec);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl);

static size_t ssl_get_maximum_datagram_size(mbedtls_ssl_context const *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_remaining_space_in_datagram(mbedtls_ssl_context const *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_remaining_payload_in_datagram(mbedtls_ssl_context const *ssl)
{}

/*
 * Double the retransmit timeout value, within the allowed range,
 * returning -1 if the maximum value has already been reached.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_double_retransmit_timeout(mbedtls_ssl_context *ssl)
{}

static void ssl_reset_retransmit_timeout(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_PROTO_DTLS */

/*
 * Encryption/decryption functions
 */

#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3)

static size_t ssl_compute_padding_length(size_t len,
                                         size_t granularity)
{}

/* This functions transforms a (D)TLS plaintext fragment and a record content
 * type into an instance of the (D)TLSInnerPlaintext structure. This is used
 * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect
 * a record's content type.
 *
 *        struct {
 *            opaque content[DTLSPlaintext.length];
 *            ContentType real_type;
 *            uint8 zeros[length_of_padding];
 *        } (D)TLSInnerPlaintext;
 *
 *  Input:
 *  - `content`: The beginning of the buffer holding the
 *               plaintext to be wrapped.
 *  - `*content_size`: The length of the plaintext in Bytes.
 *  - `max_len`: The number of Bytes available starting from
 *               `content`. This must be `>= *content_size`.
 *  - `rec_type`: The desired record content type.
 *
 *  Output:
 *  - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure.
 *  - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure.
 *
 *  Returns:
 *  - `0` on success.
 *  - A negative error code if `max_len` didn't offer enough space
 *    for the expansion.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_build_inner_plaintext(unsigned char *content,
                                     size_t *content_size,
                                     size_t remaining,
                                     uint8_t rec_type,
                                     size_t pad)
{}

/* This function parses a (D)TLSInnerPlaintext structure.
 * See ssl_build_inner_plaintext() for details. */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_inner_plaintext(unsigned char const *content,
                                     size_t *content_size,
                                     uint8_t *rec_type)
{}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */

/* The size of the `add_data` structure depends on various
 * factors, namely
 *
 * 1) CID functionality disabled
 *
 * additional_data =
 *    8:                    seq_num +
 *    1:                       type +
 *    2:                    version +
 *    2:  length of inner plaintext +
 *
 * size = 13 bytes
 *
 * 2) CID functionality based on RFC 9146 enabled
 *
 * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length
 *      = 23 + CID-length
 *
 * 3) CID functionality based on legacy CID version
    according to draft-ietf-tls-dtls-connection-id-05
 *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
 *
 * size = 13 + 1 + CID-length
 *
 * More information about the CID usage:
 *
 * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the
 * size of the additional data structure is calculated as:
 *
 * additional_data =
 *    8:                    seq_num +
 *    1:                  tls12_cid +
 *    2:     DTLSCipherText.version +
 *    n:                        cid +
 *    1:                 cid_length +
 *    2: length_of_DTLSInnerPlaintext
 *
 * Per RFC 9146 the size of the add_data structure is calculated as:
 *
 * additional_data =
 *    8:        seq_num_placeholder +
 *    1:                  tls12_cid +
 *    1:                 cid_length +
 *    1:                  tls12_cid +
 *    2:     DTLSCiphertext.version +
 *    2:                      epoch +
 *    6:            sequence_number +
 *    n:                        cid +
 *    2: length_of_DTLSInnerPlaintext
 *
 */
static void ssl_extract_add_data_from_record(unsigned char *add_data,
                                             size_t *add_data_len,
                                             mbedtls_record *rec,
                                             mbedtls_ssl_protocol_version
                                             tls_version,
                                             size_t taglen)
{}

#if defined(MBEDTLS_SSL_HAVE_AEAD)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_transform_aead_dynamic_iv_is_explicit(
    mbedtls_ssl_transform const *transform)
{}

/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV )
 *
 * Concretely, this occurs in two variants:
 *
 * a) Fixed and dynamic IV lengths add up to total IV length, giving
 *       IV = fixed_iv || dynamic_iv
 *
 *    This variant is used in TLS 1.2 when used with GCM or CCM.
 *
 * b) Fixed IV lengths matches total IV length, giving
 *       IV = fixed_iv XOR ( 0 || dynamic_iv )
 *
 *    This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly.
 *
 * See also the documentation of mbedtls_ssl_transform.
 *
 * This function has the precondition that
 *
 *     dst_iv_len >= max( fixed_iv_len, dynamic_iv_len )
 *
 * which has to be ensured by the caller. If this precondition
 * violated, the behavior of this function is undefined.
 */
static void ssl_build_record_nonce(unsigned char *dst_iv,
                                   size_t dst_iv_len,
                                   unsigned char const *fixed_iv,
                                   size_t fixed_iv_len,
                                   unsigned char const *dynamic_iv,
                                   size_t dynamic_iv_len)
{}
#endif /* MBEDTLS_SSL_HAVE_AEAD */

int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
                            mbedtls_ssl_transform *transform,
                            mbedtls_record *rec,
                            int (*f_rng)(void *, unsigned char *, size_t),
                            void *p_rng)
{}

int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
                            mbedtls_ssl_transform *transform,
                            mbedtls_record *rec)
{}

#undef MAC_NONE
#undef MAC_PLAINTEXT
#undef MAC_CIPHERTEXT

/*
 * Fill the input message buffer by appending data to it.
 * The amount of data already fetched is in ssl->in_left.
 *
 * If we return 0, is it guaranteed that (at least) nb_want bytes are
 * available (from this read and/or a previous one). Otherwise, an error code
 * is returned (possibly EOF or WANT_READ).
 *
 * With stream transport (TLS) on success ssl->in_left == nb_want, but
 * with datagram transport (DTLS) on success ssl->in_left >= nb_want,
 * since we always read a whole datagram at once.
 *
 * For DTLS, it is up to the caller to set ssl->next_record_offset when
 * they're done reading a record.
 */
int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want)
{}

/*
 * Flush any data not yet written
 */
int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl)
{}

/*
 * Functions to handle the DTLS retransmission state machine
 */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
/*
 * Append current handshake message to current outgoing flight
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_flight_append(mbedtls_ssl_context *ssl)
{}

/*
 * Free the current flight of handshake messages
 */
void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight)
{}

/*
 * Swap transform_out and out_ctr with the alternative ones
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_swap_epochs(mbedtls_ssl_context *ssl)
{}

/*
 * Retransmit the current flight of messages.
 */
int mbedtls_ssl_resend(mbedtls_ssl_context *ssl)
{}

/*
 * Transmit or retransmit the current flight of messages.
 *
 * Need to remember the current message in case flush_output returns
 * WANT_WRITE, causing us to exit this function and come back later.
 * This function must be called until state is no longer SENDING.
 */
int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl)
{}

/*
 * To be called when the last message of an incoming flight is received.
 */
void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl)
{}

/*
 * To be called when the last message of an outgoing flight is send.
 */
void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_PROTO_DTLS */

/*
 * Handshake layer functions
 */
int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type,
                                    unsigned char **buf, size_t *buf_len)
{}

/*
 * Write (DTLS: or queue) current handshake (including CCS) message.
 *
 *  - fill in handshake headers
 *  - update handshake checksum
 *  - DTLS: save message for resending
 *  - then pass to the record layer
 *
 * DTLS: except for HelloRequest, messages are only queued, and will only be
 * actually sent when calling flight_transmit() or resend().
 *
 * Inputs:
 *  - ssl->out_msglen: 4 + actual handshake message len
 *      (4 is the size of handshake headers for TLS)
 *  - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
 *  - ssl->out_msg + 4: the handshake message body
 *
 * Outputs, ie state before passing to flight_append() or write_record():
 *   - ssl->out_msglen: the length of the record contents
 *      (including handshake headers but excluding record headers)
 *   - ssl->out_msg: the record contents (handshake headers + content)
 */
int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,
                                        int update_checksum,
                                        int force_flush)
{}

int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl,
                                     size_t buf_len, size_t msg_len)
{}

/*
 * Record layer functions
 */

/*
 * Write current record.
 *
 * Uses:
 *  - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
 *  - ssl->out_msglen: length of the record content (excl headers)
 *  - ssl->out_msg: record content
 */
int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush)
{}

#if defined(MBEDTLS_SSL_PROTO_DTLS)

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl)
{}

static uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl)
{}

static uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_hs_header(mbedtls_ssl_context const *ssl)
{}

/*
 * Mark bits in bitmask (used for DTLS HS reassembly)
 */
static void ssl_bitmask_set(unsigned char *mask, size_t offset, size_t len)
{}

/*
 * Check that bitmask is full
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_bitmask_check(unsigned char *mask, size_t len)
{}

/* msg_len does not include the handshake header */
static size_t ssl_get_reassembly_buffer_size(size_t msg_len,
                                             unsigned add_bitmap)
{}

#endif /* MBEDTLS_SSL_PROTO_DTLS */

static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
{}

int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
{}

int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl)
{}

/*
 * DTLS anti-replay: RFC 6347 4.1.2.6
 *
 * in_window is a field of bits numbered from 0 (lsb) to 63 (msb).
 * Bit n is set iff record number in_window_top - n has been seen.
 *
 * Usually, in_window_top is the last record number seen and the lsb of
 * in_window is set. The only exception is the initial state (record number 0
 * not seen yet).
 */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl)
{}

static inline uint64_t ssl_load_six_bytes(unsigned char *buf)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int mbedtls_ssl_dtls_record_replay_check(mbedtls_ssl_context *ssl, uint8_t *record_in_ctr)
{}

/*
 * Return 0 if sequence number is acceptable, -1 otherwise
 */
int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl)
{}

/*
 * Update replay window on new validated record
 */
void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */

#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
/*
 * Check if a datagram looks like a ClientHello with a valid cookie,
 * and if it doesn't, generate a HelloVerifyRequest message.
 * Both input and output include full DTLS headers.
 *
 * - if cookie is valid, return 0
 * - if ClientHello looks superficially valid but cookie is not,
 *   fill obuf and set olen, then
 *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
 * - otherwise return a specific error code
 */
MBEDTLS_CHECK_RETURN_CRITICAL
MBEDTLS_STATIC_TESTABLE
int mbedtls_ssl_check_dtls_clihlo_cookie(
    mbedtls_ssl_context *ssl,
    const unsigned char *cli_id, size_t cli_id_len,
    const unsigned char *in, size_t in_len,
    unsigned char *obuf, size_t buf_len, size_t *olen)
{}

/*
 * Handle possible client reconnect with the same UDP quadruplet
 * (RFC 6347 Section 4.2.8).
 *
 * Called by ssl_parse_record_header() in case we receive an epoch 0 record
 * that looks like a ClientHello.
 *
 * - if the input looks like a ClientHello without cookies,
 *   send back HelloVerifyRequest, then return 0
 * - if the input looks like a ClientHello with a valid cookie,
 *   reset the session of the current context, and
 *   return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
 * - if anything goes wrong, return a specific error code
 *
 * This function is called (through ssl_check_client_reconnect()) when an
 * unexpected record is found in ssl_get_next_record(), which will discard the
 * record if we return 0, and bubble up the return value otherwise (this
 * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected
 * errors, and is the right thing to do in both cases).
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_record_type(uint8_t record_type)
{}

/*
 * ContentType type;
 * ProtocolVersion version;
 * uint16 epoch;            // DTLS only
 * uint48 sequence_number;  // DTLS only
 * uint16 length;
 *
 * Return 0 if header looks sane (and, for DTLS, the record is expected)
 * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,
 * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.
 *
 * With DTLS, mbedtls_ssl_read_record() will:
 * 1. proceed with the record if this function returns 0
 * 2. drop only the current record if this function returns UNEXPECTED_RECORD
 * 3. return CLIENT_RECONNECT if this function return that value
 * 4. drop the whole datagram if this function returns anything else.
 * Point 2 is needed when the peer is resending, and we have already received
 * the first record from a datagram but are still waiting for the others.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
                                   unsigned char *buf,
                                   size_t len,
                                   mbedtls_record *rec)
{}


#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */

/*
 * If applicable, decrypt record content
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_prepare_record_content(mbedtls_ssl_context *ssl,
                                      mbedtls_record *rec)
{}

/*
 * Read a record.
 *
 * Silently ignore non-fatal alert (and for DTLS, invalid records as well,
 * RFC 6347 4.1.2.7) and continue reading until a valid record is found.
 *
 */

/* Helper functions for mbedtls_ssl_read_record(). */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_consume_current_message(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_next_record(mbedtls_ssl_context *ssl);
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl);

int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl,
                            unsigned update_hs_digest)
{}

#if defined(MBEDTLS_SSL_PROTO_DTLS)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_make_space(mbedtls_ssl_context *ssl,
                                 size_t desired)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_message(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_PROTO_DTLS */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl)
{}

#if defined(MBEDTLS_SSL_PROTO_DTLS)

static void ssl_free_buffered_record(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_record(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_future_record(mbedtls_ssl_context *ssl,
                                    mbedtls_record const *rec)
{}

#endif /* MBEDTLS_SSL_PROTO_DTLS */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_next_record(mbedtls_ssl_context *ssl)
{}

int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl)
{}

int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl)
{}

int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl,
                                   unsigned char level,
                                   unsigned char message)
{}

int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl)
{}

int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl)
{}

/* Once ssl->out_hdr as the address of the beginning of the
 * next outgoing record is set, deduce the other pointers.
 *
 * Note: For TLS, we save the implicit record sequence number
 *       (entering MAC computation) in the 8 bytes before ssl->out_hdr,
 *       and the caller has to make sure there's space for this.
 */

static size_t ssl_transform_get_explicit_iv_len(
    mbedtls_ssl_transform const *transform)
{}

void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl,
                                     mbedtls_ssl_transform *transform)
{}

/* Once ssl->in_hdr as the address of the beginning of the
 * next incoming record is set, deduce the other pointers.
 *
 * Note: For TLS, we save the implicit record sequence number
 *       (entering MAC computation) in the 8 bytes before ssl->in_hdr,
 *       and the caller has to make sure there's space for this.
 */

void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl)
{}

/*
 * Setup an SSL context
 */

void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl)
{}

/*
 * SSL get accessors
 */
size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl)
{}

int mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl)
{}


int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl)
{}

#if defined(MBEDTLS_SSL_RENEGOTIATION)
/*
 * Check record counters and renegotiate if they're above the limit.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_RENEGOTIATION */

#if defined(MBEDTLS_SSL_PROTO_TLS1_3)

#if defined(MBEDTLS_SSL_CLI_C)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_is_new_session_ticket(mbedtls_ssl_context *ssl)
{

    if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) ||
        (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) {
        return 0;
    }

    return 1;
}
#endif /* MBEDTLS_SSL_CLI_C */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
{

    MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message"));

#if defined(MBEDTLS_SSL_CLI_C)
    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
        if (ssl_tls13_is_new_session_ticket(ssl)) {
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
            MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
            if (mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(ssl->conf) ==
                MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED) {
                ssl->keep_current_message = 1;

                mbedtls_ssl_handshake_set_state(ssl,
                                                MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
                return MBEDTLS_ERR_SSL_WANT_READ;
            } else {
                MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, handling disabled."));
                return 0;
            }
#else
            MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, not supported."));
            return 0;
#endif
        }
    }
#endif /* MBEDTLS_SSL_CLI_C */

    /* Fail in all other cases. */
    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
/* This function is called from mbedtls_ssl_read() when a handshake message is
 * received after the initial handshake. In this context, handshake messages
 * may only be sent for the purpose of initiating renegotiations.
 *
 * This function is introduced as a separate helper since the handling
 * of post-handshake handshake messages changes significantly in TLS 1.3,
 * and having a helper function allows to distinguish between TLS <= 1.2 and
 * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read().
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
{}

/*
 * brief          Read at most 'len' application data bytes from the input
 *                buffer.
 *
 * param ssl      SSL context:
 *                - First byte of application data not read yet in the input
 *                  buffer located at address `in_offt`.
 *                - The number of bytes of data not read yet is `in_msglen`.
 * param buf      buffer that will hold the data
 * param len      maximum number of bytes to read
 *
 * note           The function updates the fields `in_offt` and `in_msglen`
 *                according to the number of bytes read.
 *
 * return         The number of bytes read.
 */
static int ssl_read_application_data(
    mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
{}

/*
 * Receive application data decrypted from the SSL layer
 */
int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
{}

#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA)
int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
                                unsigned char *buf, size_t len)
{
    if (ssl == NULL || (ssl->conf == NULL)) {
        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    }

    /*
     * The server may receive early data only while waiting for the End of
     * Early Data handshake message.
     */
    if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) ||
        (ssl->in_offt == NULL)) {
        return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA;
    }

    return ssl_read_application_data(ssl, buf, len);
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */

/*
 * Send application data to be encrypted by the SSL layer, taking care of max
 * fragment length and buffer size.
 *
 * According to RFC 5246 Section 6.2.1:
 *
 *      Zero-length fragments of Application data MAY be sent as they are
 *      potentially useful as a traffic analysis countermeasure.
 *
 * Therefore, it is possible that the input message length is 0 and the
 * corresponding return code is 0 on success.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_real(mbedtls_ssl_context *ssl,
                          const unsigned char *buf, size_t len)
{}

/*
 * Write application data (public-facing wrapper)
 */
int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len)
{}

#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
                                 const unsigned char *buf, size_t len)
{
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    const struct mbedtls_ssl_config *conf;
    uint32_t remaining;

    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data"));

    if (ssl == NULL || (conf = ssl->conf) == NULL) {
        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    }

    if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {
        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
    }

    if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) ||
        (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
        (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) {
        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
    }

    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
    }

    /*
     * If we are at the beginning of the handshake, the early data state being
     * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or
     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just
     * enough to be able to send early data if possible. That way, we can
     * guarantee that when starting the handshake with this function we will
     * send at least one record of early data. Note that when the state is
     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet
     * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data
     * as the early data outbound transform has not been set as we may have to
     * first send a dummy CCS in clear.
     */
    if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
        (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
        while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
               (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
            ret = mbedtls_ssl_handshake_step(ssl);
            if (ret != 0) {
                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret);
                return ret;
            }

            ret = mbedtls_ssl_flush_output(ssl);
            if (ret != 0) {
                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret);
                return ret;
            }
        }
        remaining = ssl->session_negotiate->max_early_data_size;
    } else {
        /*
         * If we are past the point where we can send early data or we have
         * already reached the maximum early data size, return immediatly.
         * Otherwise, progress the handshake as much as possible to not delay
         * it too much. If we reach a point where we can still send early data,
         * then we will send some.
         */
        if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
            (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) {
            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
        }

        remaining = ssl->session_negotiate->max_early_data_size -
                    ssl->total_early_data_size;

        if (remaining == 0) {
            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
        }

        ret = mbedtls_ssl_handshake(ssl);
        if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) {
            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
            return ret;
        }
    }

    if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
         (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED))
        || (remaining == 0)) {
        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
    }

    if (len > remaining) {
        len = remaining;
    }

    ret = ssl_write_real(ssl, buf, len);
    if (ret >= 0) {
        ssl->total_early_data_size += ret;
    }

    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret));

    return ret;
}
#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */

/*
 * Notify the peer that the connection is being closed
 */
int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl)
{}

void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform)
{}

void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl,
                                       mbedtls_ssl_transform *transform)
{}

void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl,
                                        mbedtls_ssl_transform *transform)
{}

#if defined(MBEDTLS_SSL_PROTO_DTLS)

void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl)
{}

static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
                                    uint8_t slot)
{}

#endif /* MBEDTLS_SSL_PROTO_DTLS */

/*
 * Convert version numbers to/from wire format
 * and, for DTLS, to/from TLS equivalent.
 *
 * For TLS this is the identity.
 * For DTLS, map as follows, then use 1's complement (v -> ~v):
 * 1.x <-> 3.x+1    for x != 0 (DTLS 1.2 based on TLS 1.2)
 *                  DTLS 1.0 is stored as TLS 1.1 internally
 */
void mbedtls_ssl_write_version(unsigned char version[2], int transport,
                               mbedtls_ssl_protocol_version tls_version)
{}

uint16_t mbedtls_ssl_read_version(const unsigned char version[2],
                                  int transport)
{}

/*
 * Send pending fatal alert.
 * 0,   No alert message.
 * !0,  if mbedtls_ssl_send_alert_message() returned in error, the error code it
 *      returned, ssl->alert_reason otherwise.
 */
int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl)
{}

/*
 * Set pending fatal alert flag.
 */
void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl,
                                  unsigned char alert_type,
                                  int alert_reason)
{}

#endif /* MBEDTLS_SSL_TLS_C */