godot/thirdparty/mbedtls/library/ssl_tls12_server.c

/*
 *  TLS server-side functions
 *
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 */

#include "common.h"

#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)

#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 "constant_time_internal.h"
#include "mbedtls/constant_time.h"

#include <string.h>

#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. */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \
    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
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
#endif

#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
#endif

#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#endif

#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl,
                                        const unsigned char *info,
                                        size_t ilen)
{}

void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf,
                                   mbedtls_ssl_cookie_write_t *f_cookie_write,
                                   mbedtls_ssl_cookie_check_t *f_cookie_check,
                                   void *p_cookie)
{}
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */

#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,
                                        const unsigned char *buf,
                                        size_t len)
{}

#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
/*
 * Function for parsing a supported groups (TLS 1.3) or supported elliptic
 * curves (TLS 1.2) extension.
 *
 * The "extension_data" field of a supported groups extension contains a
 * "NamedGroupList" value (TLS 1.3 RFC8446):
 *      enum {
 *          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
 *          x25519(0x001D), x448(0x001E),
 *          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
 *          ffdhe6144(0x0103), ffdhe8192(0x0104),
 *          ffdhe_private_use(0x01FC..0x01FF),
 *          ecdhe_private_use(0xFE00..0xFEFF),
 *          (0xFFFF)
 *      } NamedGroup;
 *      struct {
 *          NamedGroup named_group_list<2..2^16-1>;
 *      } NamedGroupList;
 *
 * The "extension_data" field of a supported elliptic curves extension contains
 * a "NamedCurveList" value (TLS 1.2 RFC 8422):
 * enum {
 *      deprecated(1..22),
 *      secp256r1 (23), secp384r1 (24), secp521r1 (25),
 *      x25519(29), x448(30),
 *      reserved (0xFE00..0xFEFF),
 *      deprecated(0xFF01..0xFF02),
 *      (0xFFFF)
 *  } NamedCurve;
 * struct {
 *      NamedCurve named_curve_list<2..2^16-1>
 *  } NamedCurveList;
 *
 * The TLS 1.3 supported groups extension was defined to be a compatible
 * generalization of the TLS 1.2 supported elliptic curves extension. They both
 * share the same extension identifier.
 *
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl,
                                             const unsigned char *buf,
                                             size_t len)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */

#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl,
                                  const unsigned char *buf,
                                  size_t len)
{
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;

#if defined(MBEDTLS_USE_PSA_CRYPTO)
    if (ssl->handshake->psa_pake_ctx_is_ok != 1)
#else
    if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0)
#endif /* MBEDTLS_USE_PSA_CRYPTO */
    {
        MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension"));
        return 0;
    }

#if defined(MBEDTLS_USE_PSA_CRYPTO)
    if ((ret = mbedtls_psa_ecjpake_read_round(
             &ssl->handshake->psa_pake_ctx, buf, len,
             MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) {
        psa_destroy_key(ssl->handshake->psa_pake_password);
        psa_pake_abort(&ssl->handshake->psa_pake_ctx);

        MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret);
        mbedtls_ssl_send_alert_message(
            ssl,
            MBEDTLS_SSL_ALERT_LEVEL_FATAL,
            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);

        return ret;
    }
#else
    if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx,
                                              buf, len)) != 0) {
        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret);
        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                       MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER);
        return ret;
    }
#endif /* MBEDTLS_USE_PSA_CRYPTO */

    /* Only mark the extension as OK when we're sure it is */
    ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK;

    return 0;
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */

#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl,
                                             const unsigned char *buf,
                                             size_t len)
{}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */

#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl,
                             const unsigned char *buf,
                             size_t len)
{}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */

#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len)
{}
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */

#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl,
                                     const unsigned char *buf,
                                     size_t len)
{}
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */

#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,
                                        unsigned char *buf,
                                        size_t len)
{}
#endif /* MBEDTLS_SSL_SESSION_TICKETS */

#if defined(MBEDTLS_SSL_DTLS_SRTP)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl,
                                  const unsigned char *buf,
                                  size_t len)
{
    mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET;
    size_t i, j;
    size_t profile_length;
    uint16_t mki_length;
    /*! 2 bytes for profile length and 1 byte for mki len */
    const size_t size_of_lengths = 3;

    /* If use_srtp is not configured, just ignore the extension */
    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
        (ssl->conf->dtls_srtp_profile_list == NULL) ||
        (ssl->conf->dtls_srtp_profile_list_len == 0)) {
        return 0;
    }

    /* RFC5764 section 4.1.1
     * uint8 SRTPProtectionProfile[2];
     *
     * struct {
     *   SRTPProtectionProfiles SRTPProtectionProfiles;
     *   opaque srtp_mki<0..255>;
     * } UseSRTPData;

     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
     */

    /*
     * Min length is 5: at least one protection profile(2 bytes)
     *                  and length(2 bytes) + srtp_mki length(1 byte)
     * Check here that we have at least 2 bytes of protection profiles length
     * and one of srtp_mki length
     */
    if (len < size_of_lengths) {
        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
        return MBEDTLS_ERR_SSL_DECODE_ERROR;
    }

    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;

    /* first 2 bytes are protection profile length(in bytes) */
    profile_length = (buf[0] << 8) | buf[1];
    buf += 2;

    /* The profile length cannot be bigger than input buffer size - lengths fields */
    if (profile_length > len - size_of_lengths ||
        profile_length % 2 != 0) { /* profiles are 2 bytes long, so the length must be even */
        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
        return MBEDTLS_ERR_SSL_DECODE_ERROR;
    }
    /*
     * parse the extension list values are defined in
     * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
     */
    for (j = 0; j < profile_length; j += 2) {
        uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1];
        client_protection = mbedtls_ssl_check_srtp_profile_value(protection_profile_value);

        if (client_protection != MBEDTLS_TLS_SRTP_UNSET) {
            MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s",
                                      mbedtls_ssl_get_srtp_profile_as_string(
                                          client_protection)));
        } else {
            continue;
        }
        /* check if suggested profile is in our list */
        for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) {
            if (client_protection == ssl->conf->dtls_srtp_profile_list[i]) {
                ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
                MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s",
                                          mbedtls_ssl_get_srtp_profile_as_string(
                                              client_protection)));
                break;
            }
        }
        if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET) {
            break;
        }
    }
    buf += profile_length; /* buf points to the mki length */
    mki_length = *buf;
    buf++;

    if (mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ||
        mki_length + profile_length + size_of_lengths != len) {
        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
        return MBEDTLS_ERR_SSL_DECODE_ERROR;
    }

    /* Parse the mki only if present and mki is supported locally */
    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED &&
        mki_length > 0) {
        ssl->dtls_srtp_info.mki_len = mki_length;

        memcpy(ssl->dtls_srtp_info.mki_value, buf, mki_length);

        MBEDTLS_SSL_DEBUG_BUF(3, "using mki",  ssl->dtls_srtp_info.mki_value,
                              ssl->dtls_srtp_info.mki_len);
    }

    return 0;
}
#endif /* MBEDTLS_SSL_DTLS_SRTP */

/*
 * Auxiliary functions for ServerHello parsing and related actions
 */

#if defined(MBEDTLS_X509_CRT_PARSE_C)
/*
 * Return 0 if the given key uses one of the acceptable curves, -1 otherwise
 */
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_key_curve(mbedtls_pk_context *pk,
                               uint16_t *curves_tls_id)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED */

/*
 * Try picking a certificate for this ciphersuite,
 * return 0 on success and -1 on failure.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_pick_cert(mbedtls_ssl_context *ssl,
                         const mbedtls_ssl_ciphersuite_t *ciphersuite_info)
{}
#endif /* MBEDTLS_X509_CRT_PARSE_C */

/*
 * Check if a given ciphersuite is suitable for use with our config/keys/etc
 * Sets ciphersuite_info only if the suite matches.
 */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id,
                                 const mbedtls_ssl_ciphersuite_t **ciphersuite_info)
{}

/* This function doesn't alert on errors that happen early during
   ClientHello parsing because they might indicate that the client is
   not talking SSL/TLS at all and would not understand our alert. */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_hello(mbedtls_ssl_context *ssl)
{}

#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
static void ssl_write_cid_ext(mbedtls_ssl_context *ssl,
                              unsigned char *buf,
                              size_t *olen)
{}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */

#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl,
                                           unsigned char *buf,
                                           size_t *olen)
{}
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */

#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
static void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl,
                                      unsigned char *buf,
                                      size_t *olen)
{}
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */

#if defined(MBEDTLS_SSL_SESSION_TICKETS)
static void ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,
                                         unsigned char *buf,
                                         size_t *olen)
{}
#endif /* MBEDTLS_SSL_SESSION_TICKETS */

static void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,
                                        unsigned char *buf,
                                        size_t *olen)
{}

#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
static void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,
                                              unsigned char *buf,
                                              size_t *olen)
{}
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */

#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
                                                  unsigned char *buf,
                                                  size_t *olen)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */

#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
                                       unsigned char *buf,
                                       size_t *olen)
{
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    unsigned char *p = buf;
    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
    size_t kkpp_len;

    *olen = 0;

    /* Skip costly computation if not needed */
    if (ssl->handshake->ciphersuite_info->key_exchange !=
        MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
        return;
    }

    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, ecjpake kkpp extension"));

    if (end - p < 4) {
        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
        return;
    }

    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0);
    p += 2;

#if defined(MBEDTLS_USE_PSA_CRYPTO)
    ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
                                          p + 2, (size_t) (end - p - 2), &kkpp_len,
                                          MBEDTLS_ECJPAKE_ROUND_ONE);
    if (ret != 0) {
        psa_destroy_key(ssl->handshake->psa_pake_password);
        psa_pake_abort(&ssl->handshake->psa_pake_ctx);
        MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret);
        return;
    }
#else
    ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx,
                                          p + 2, (size_t) (end - p - 2), &kkpp_len,
                                          ssl->conf->f_rng, ssl->conf->p_rng);
    if (ret != 0) {
        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret);
        return;
    }
#endif /* MBEDTLS_USE_PSA_CRYPTO */

    MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0);
    p += 2;

    *olen = kkpp_len + 4;
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */

#if defined(MBEDTLS_SSL_DTLS_SRTP) && defined(MBEDTLS_SSL_PROTO_DTLS)
static void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl,
                                   unsigned char *buf,
                                   size_t *olen)
{
    size_t mki_len = 0, ext_len = 0;
    uint16_t profile_value = 0;
    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;

    *olen = 0;

    if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
        (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET)) {
        return;
    }

    MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding use_srtp extension"));

    if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) {
        mki_len = ssl->dtls_srtp_info.mki_len;
    }

    /* The extension total size is 9 bytes :
     * - 2 bytes for the extension tag
     * - 2 bytes for the total size
     * - 2 bytes for the protection profile length
     * - 2 bytes for the protection profile
     * - 1 byte for the mki length
     * +  the actual mki length
     * Check we have enough room in the output buffer */
    if ((size_t) (end - buf) < mki_len + 9) {
        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
        return;
    }

    /* extension */
    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0);
    /*
     * total length 5 and mki value: only one profile(2 bytes)
     *              and length(2 bytes) and srtp_mki  )
     */
    ext_len = 5 + mki_len;
    MBEDTLS_PUT_UINT16_BE(ext_len, buf, 2);

    /* protection profile length: 2 */
    buf[4] = 0x00;
    buf[5] = 0x02;
    profile_value = mbedtls_ssl_check_srtp_profile_value(
        ssl->dtls_srtp_info.chosen_dtls_srtp_profile);
    if (profile_value != MBEDTLS_TLS_SRTP_UNSET) {
        MBEDTLS_PUT_UINT16_BE(profile_value, buf, 6);
    } else {
        MBEDTLS_SSL_DEBUG_MSG(1, ("use_srtp extension invalid profile"));
        return;
    }

    buf[8] = mki_len & 0xFF;
    memcpy(&buf[9], ssl->dtls_srtp_info.mki_value, mki_len);

    *olen = 9 + mki_len;
}
#endif /* MBEDTLS_SSL_DTLS_SRTP */

#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */

static void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
{}

#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
{
    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
        ssl->handshake->ciphersuite_info;

    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request"));

    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request"));
        ssl->state++;
        return 0;
    }

    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */

#if (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED))
#if defined(MBEDTLS_USE_PSA_CRYPTO)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
{
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
    mbedtls_pk_context *pk;
    mbedtls_pk_type_t pk_type;
    psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
    unsigned char buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
    size_t key_len;
#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
    uint16_t tls_id = 0;
    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
    mbedtls_ecp_group_id grp_id;
    mbedtls_ecp_keypair *key;
#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */

    pk = mbedtls_ssl_own_key(ssl);

    if (pk == NULL) {
        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
    }

    pk_type = mbedtls_pk_get_type(pk);

    switch (pk_type) {
        case MBEDTLS_PK_OPAQUE:
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
        case MBEDTLS_PK_ECKEY:
        case MBEDTLS_PK_ECKEY_DH:
        case MBEDTLS_PK_ECDSA:
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
            if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
                return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
            }

            /* Get the attributes of the key previously parsed by PK module in
             * order to extract its type and length (in bits). */
            status = psa_get_key_attributes(pk->priv_id, &key_attributes);
            if (status != PSA_SUCCESS) {
                ret = PSA_TO_MBEDTLS_ERR(status);
                goto exit;
            }
            ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes);
            ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes);

#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
            if (pk_type != MBEDTLS_PK_OPAQUE) {
                /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK
                 * module and only have ECDSA capabilities. Since we need
                 * them for ECDH later, we export and then re-import them with
                 * proper flags and algorithm. Of course We also set key's type
                 * and bits that we just got above. */
                key_attributes = psa_key_attributes_init();
                psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
                psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
                psa_set_key_type(&key_attributes,
                                 PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));
                psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);

                status = psa_export_key(pk->priv_id, buf, sizeof(buf), &key_len);
                if (status != PSA_SUCCESS) {
                    ret = PSA_TO_MBEDTLS_ERR(status);
                    goto exit;
                }
                status = psa_import_key(&key_attributes, buf, key_len,
                                        &ssl->handshake->xxdh_psa_privkey);
                if (status != PSA_SUCCESS) {
                    ret = PSA_TO_MBEDTLS_ERR(status);
                    goto exit;
                }

                /* Set this key as owned by the TLS library: it will be its duty
                 * to clear it exit. */
                ssl->handshake->xxdh_psa_privkey_is_external = 0;

                ret = 0;
                break;
            }
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */

            /* Opaque key is created by the user (externally from Mbed TLS)
             * so we assume it already has the right algorithm and flags
             * set. Just copy its ID as reference. */
            ssl->handshake->xxdh_psa_privkey = pk->priv_id;
            ssl->handshake->xxdh_psa_privkey_is_external = 1;
            ret = 0;
            break;

#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
        case MBEDTLS_PK_ECKEY:
        case MBEDTLS_PK_ECKEY_DH:
        case MBEDTLS_PK_ECDSA:
            key = mbedtls_pk_ec_rw(*pk);
            grp_id = mbedtls_pk_get_ec_group_id(pk);
            if (grp_id == MBEDTLS_ECP_DP_NONE) {
                return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
            }
            tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
            if (tls_id == 0) {
                /* This elliptic curve is not supported */
                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
            }

            /* If the above conversion to TLS ID was fine, then also this one will
               be, so there is no need to check the return value here */
            mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,
                                                       &ssl->handshake->xxdh_psa_bits);

            ssl->handshake->xxdh_psa_type = key_type;

            key_attributes = psa_key_attributes_init();
            psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
            psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
            psa_set_key_type(&key_attributes,
                             PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));
            psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);

            ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf));
            if (ret != 0) {
                mbedtls_platform_zeroize(buf, sizeof(buf));
                break;
            }

            status = psa_import_key(&key_attributes, buf, key_len,
                                    &ssl->handshake->xxdh_psa_privkey);
            if (status != PSA_SUCCESS) {
                ret = PSA_TO_MBEDTLS_ERR(status);
                mbedtls_platform_zeroize(buf, sizeof(buf));
                break;
            }

            mbedtls_platform_zeroize(buf, sizeof(buf));
            ret = 0;
            break;
#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */
        default:
            ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
    }

exit:
    psa_reset_key_attributes(&key_attributes);
    mbedtls_platform_zeroize(buf, sizeof(buf));

    return ret;
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
          MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */

#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
    defined(MBEDTLS_SSL_ASYNC_PRIVATE)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_resume_server_key_exchange(mbedtls_ssl_context *ssl,
                                          size_t *signature_len)
{
    /* Append the signature to ssl->out_msg, leaving 2 bytes for the
     * signature length which will be added in ssl_write_server_key_exchange
     * after the call to ssl_prepare_server_key_exchange.
     * ssl_write_server_key_exchange also takes care of incrementing
     * ssl->out_msglen. */
    unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
    size_t sig_max_len = (ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
                          - sig_start);
    int ret = ssl->conf->f_async_resume(ssl,
                                        sig_start, signature_len, sig_max_len);
    if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
        ssl->handshake->async_in_progress = 0;
        mbedtls_ssl_set_async_operation_data(ssl, NULL);
    }
    MBEDTLS_SSL_DEBUG_RET(2, "ssl_resume_server_key_exchange", ret);
    return ret;
}
#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) &&
          defined(MBEDTLS_SSL_ASYNC_PRIVATE) */

/* Prepare the ServerKeyExchange message, up to and including
 * calculating the signature if any, but excluding formatting the
 * signature and sending the message. */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl,
                                           size_t *signature_len)
{}

/* Prepare the ServerKeyExchange message and send it. For ciphersuites
 * that do not include a ServerKeyExchange message, do nothing. Either
 * way, if successful, move on to the next step in the SSL state
 * machine. */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_hello_done(mbedtls_ssl_context *ssl)
{}

#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
    defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char **p,
                                      const unsigned char *end)
{
    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
    size_t n;

    /*
     * Receive G^Y mod P, premaster = (G^Y)^X mod P
     */
    if (*p + 2 > end) {
        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
        return MBEDTLS_ERR_SSL_DECODE_ERROR;
    }

    n = MBEDTLS_GET_UINT16_BE(*p, 0);
    *p += 2;

    if (*p + n > end) {
        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
        return MBEDTLS_ERR_SSL_DECODE_ERROR;
    }

    if ((ret = mbedtls_dhm_read_public(&ssl->handshake->dhm_ctx, *p, n)) != 0) {
        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_read_public", ret);
        return MBEDTLS_ERR_SSL_DECODE_ERROR;
    }

    *p += n;

    MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY);

    return ret;
}
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
          MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */

#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) ||                           \
    defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)

#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_resume_decrypt_pms(mbedtls_ssl_context *ssl,
                                  unsigned char *peer_pms,
                                  size_t *peer_pmslen,
                                  size_t peer_pmssize)
{
    int ret = ssl->conf->f_async_resume(ssl,
                                        peer_pms, peer_pmslen, peer_pmssize);
    if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
        ssl->handshake->async_in_progress = 0;
        mbedtls_ssl_set_async_operation_data(ssl, NULL);
    }
    MBEDTLS_SSL_DEBUG_RET(2, "ssl_decrypt_encrypted_pms", ret);
    return ret;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_decrypt_encrypted_pms(mbedtls_ssl_context *ssl,
                                     const unsigned char *p,
                                     const unsigned char *end,
                                     unsigned char *peer_pms,
                                     size_t *peer_pmslen,
                                     size_t peer_pmssize)
{}

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
                                   const unsigned char *p,
                                   const unsigned char *end,
                                   size_t pms_offset)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
          MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */

#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char **p,
                                         const unsigned char *end)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */

MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
{}

#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)
{
    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
        ssl->handshake->ciphersuite_info;

    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify"));

    if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) {
        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify"));
        ssl->state++;
        return 0;
    }

    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */

#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)
{}
#endif /* MBEDTLS_SSL_SESSION_TICKETS */

/*
 * SSL handshake -- server side -- single step
 */
int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl)
{}

void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order)
{}

#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */