Commit 7da160b0 authored by Matt Caswell's avatar Matt Caswell
Browse files

Move ServerHello extension construction into the new extensions framework



This lays the foundation for a later move to have the extensions built and
placed into the correct message for TLSv1.3 (e.g. ServerHello or
EncryptedExtensions).

Perl changes reviewed by Richard Levitte. Non-perl changes reviewed by Rich
Salz

Reviewed-by: default avatarRich Salz <rsalz@openssl.org>
Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent 25670f3e
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2275,10 +2275,22 @@ int ERR_load_SSL_strings(void);
# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST                373
# define SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET           428
# define SSL_F_TLS_CONSTRUCT_NEXT_PROTO                   426
# define SSL_F_TLS_CONSTRUCT_SERVER_ALPN                  451
# define SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE           374
# define SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG         452
# define SSL_F_TLS_CONSTRUCT_SERVER_DONE                  375
# define SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS         453
# define SSL_F_TLS_CONSTRUCT_SERVER_EMS                   454
# define SSL_F_TLS_CONSTRUCT_SERVER_ETM                   455
# define SSL_F_TLS_CONSTRUCT_SERVER_HELLO                 376
# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE          377
# define SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE             456
# define SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG        457
# define SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE           458
# define SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME           459
# define SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET        460
# define SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST        461
# define SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP              462
# define SSL_F_TLS_GET_MESSAGE_BODY                       351
# define SSL_F_TLS_GET_MESSAGE_HEADER                     387
# define SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE            445
+21 −0
Original line number Diff line number Diff line
@@ -282,13 +282,34 @@ static ERR_STRING_DATA SSL_str_functs[] = {
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET),
     "tls_construct_new_session_ticket"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_NEXT_PROTO), "tls_construct_next_proto"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_ALPN), "tls_construct_server_alpn"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE),
     "tls_construct_server_certificate"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG),
     "tls_construct_server_cryptopro_bug"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_DONE), "tls_construct_server_done"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS),
     "tls_construct_server_ec_pt_formats"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_EMS), "tls_construct_server_ems"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_ETM), "tls_construct_server_etm"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_HELLO),
     "tls_construct_server_hello"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE),
     "tls_construct_server_key_exchange"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE),
     "tls_construct_server_key_share"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG),
     "tls_construct_server_next_proto_neg"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE),
     "tls_construct_server_renegotiate"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME),
     "tls_construct_server_server_name"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET),
     "tls_construct_server_session_ticket"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST),
     "tls_construct_server_status_request"},
    {ERR_FUNC(SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP),
     "tls_construct_server_use_srtp"},
    {ERR_FUNC(SSL_F_TLS_GET_MESSAGE_BODY), "tls_get_message_body"},
    {ERR_FUNC(SSL_F_TLS_GET_MESSAGE_HEADER), "tls_get_message_header"},
    {ERR_FUNC(SSL_F_TLS_PARSE_CLIENTHELLO_KEY_SHARE),
+3 −3
Original line number Diff line number Diff line
@@ -2064,6 +2064,8 @@ __owur int tls1_set_groups(unsigned char **pext, size_t *pextlen,
                           int *curves, size_t ncurves);
__owur int tls1_set_groups_list(unsigned char **pext, size_t *pextlen,
                                const char *str);
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
                         size_t *num_formats);
__owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
__owur EVP_PKEY *ssl_generate_pkey_curve(int id);
#  endif                        /* OPENSSL_NO_EC */
@@ -2076,18 +2078,17 @@ __owur int tls1_get_curvelist(SSL *s, int sess, const unsigned char **pcurves,
                               size_t *num_curves);

__owur int ssl_add_clienthello_tlsext(SSL *s, WPACKET *pkt, int *al);
__owur int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al);
void ssl_set_default_md(SSL *s);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur int ssl_check_clienthello_tlsext_late(SSL *s, int *al);
__owur int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt);
__owur int ssl_prepare_clienthello_tlsext(SSL *s);
__owur int ssl_prepare_serverhello_tlsext(SSL *s);
__owur RAW_EXTENSION *tls_get_extension_by_type(RAW_EXTENSION *exts,
                                                size_t numexts,
                                                unsigned int type);
__owur int tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
                                      SSL_SESSION **ret);
__owur int tls_use_ticket(SSL *s);

__owur int tls12_get_sigandhash(WPACKET *pkt, const EVP_PKEY *pk,
                                const EVP_MD *md);
@@ -2116,7 +2117,6 @@ __owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,

__owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
__owur int ssl_add_serverhello_renegotiate_ext(SSL *s, WPACKET *pkt);
__owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
__owur long ssl_get_algorithm2(SSL *s);
__owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
+35 −16
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_renegotiate,
        tls_parse_clienthello_renegotiate,
        NULL,
        NULL,
        tls_construct_server_renegotiate,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_SSL3_ALLOWED
        | EXT_TLS1_2_AND_BELOW_ONLY
@@ -40,7 +40,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_server_name,
        tls_parse_clienthello_server_name,
        NULL,
        NULL,
        tls_construct_server_server_name,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO
@@ -60,7 +60,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_ec_point_formats,
        tls_parse_clienthello_ec_pt_formats,
        NULL,
        NULL,
        tls_construct_server_ec_pt_formats,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
@@ -68,7 +68,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_supported_groups,
        tls_parse_clienthello_supported_groups,
        NULL,
        NULL,
        NULL /* TODO(TLS1.3): Need to add this */,
        NULL,
        EXT_CLIENT_HELLO
        | /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO
@@ -78,7 +78,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_session_ticket,
        tls_parse_clienthello_session_ticket,
        NULL,
        NULL,
        tls_construct_server_session_ticket,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
@@ -94,7 +94,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_status_request,
        tls_parse_clienthello_status_request,
        NULL,
        NULL,
        tls_construct_server_status_request,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | /*EXT_TLS1_3_CERTIFICATE*/EXT_TLS1_3_SERVER_HELLO
@@ -104,7 +104,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_next_proto_neg,
        tls_parse_clienthello_npn,
        NULL,
        NULL,
        tls_construct_server_next_proto_neg,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
@@ -113,25 +113,27 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_application_layer_protocol_negotiation,
        tls_parse_clienthello_alpn,
        NULL,
        NULL,
        tls_construct_server_alpn,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | /*EXT_TLS1_3_ENCRYPTED_EXTENSIONS*/EXT_TLS1_3_SERVER_HELLO
    },
#ifndef OPENSSL_NO_SRTP
    {
        TLSEXT_TYPE_use_srtp,
        tls_parse_clienthello_use_srtp,
        NULL,
        NULL,
        tls_construct_server_use_srtp,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO
        | EXT_TLS1_3_ENCRYPTED_EXTENSIONS | EXT_DTLS_ONLY
    },
#endif
    {
        TLSEXT_TYPE_encrypt_then_mac,
        tls_parse_clienthello_etm,
        NULL,
        NULL,
        tls_construct_server_etm,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
@@ -153,7 +155,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_extended_master_secret,
        tls_parse_clienthello_ems,
        NULL,
        NULL,
        tls_construct_server_ems,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    },
@@ -179,11 +181,23 @@ static const EXTENSION_DEFINITION ext_defs[] = {
        TLSEXT_TYPE_key_share,
        tls_parse_clienthello_key_share,
        NULL,
        NULL,
        tls_construct_server_key_share,
        NULL,
        EXT_CLIENT_HELLO | EXT_TLS1_3_SERVER_HELLO
        | EXT_TLS1_3_HELLO_RETRY_REQUEST | EXT_TLS_IMPLEMENTATION_ONLY
        | EXT_TLS1_3_ONLY
    },
    {
        /*
         * Special unsolicited ServerHello extension only used when
         * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set
         */
        TLSEXT_TYPE_cryptopro_bug,
        NULL,
        NULL,
        tls_construct_server_cryptopro_bug,
        NULL,
        EXT_TLS1_2_SERVER_HELLO | EXT_TLS1_2_AND_BELOW_ONLY
    }
};

@@ -440,15 +454,21 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
    size_t loop;
    int addcustom = 0;

    /*
     * Normally if something goes wrong during construction its an internal
     * error. We can always override this later.
     */
    *al = SSL_AD_INTERNAL_ERROR;

    if (!WPACKET_start_sub_packet_u16(pkt)
               /*
                * If extensions are of zero length then we don't even add the
                * extensions length bytes to a ClientHello
                * extensions length bytes to a ClientHello/ServerHello in SSLv3
                */
            || ((context & EXT_CLIENT_HELLO) != 0
            || ((context & (EXT_CLIENT_HELLO | EXT_TLS1_2_SERVER_HELLO)) != 0
               && s->version == SSL3_VERSION
               && !WPACKET_set_flags(pkt,
                                     WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
        return 0;
    }
@@ -504,7 +524,6 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
    }

    if (!WPACKET_close(pkt)) {
        *al = SSL_AD_INTERNAL_ERROR;
        SSLerr(SSL_F_TLS_CONSTRUCT_EXTENSIONS, ERR_R_INTERNAL_ERROR);
        return 0;
    }
+370 −0
Original line number Diff line number Diff line
@@ -647,3 +647,373 @@ int tls_parse_clienthello_ems(SSL *s, PACKET *pkt, int *al)

    return 1;
}

/*
 * Process the ALPN extension in a ClientHello.
 * al: a pointer to the alert value to send in the event of a failure.
 * returns 1 on success, 0 on error.
 */
static int tls1_alpn_handle_client_hello_late(SSL *s, int *al)
{
    const unsigned char *selected = NULL;
    unsigned char selected_len = 0;

    if (s->ctx->alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
        int r = s->ctx->alpn_select_cb(s, &selected, &selected_len,
                                       s->s3->alpn_proposed,
                                       (unsigned int)s->s3->alpn_proposed_len,
                                       s->ctx->alpn_select_cb_arg);

        if (r == SSL_TLSEXT_ERR_OK) {
            OPENSSL_free(s->s3->alpn_selected);
            s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
            if (s->s3->alpn_selected == NULL) {
                *al = SSL_AD_INTERNAL_ERROR;
                return 0;
            }
            s->s3->alpn_selected_len = selected_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
            /* ALPN takes precedence over NPN. */
            s->s3->next_proto_neg_seen = 0;
#endif
        } else {
            *al = SSL_AD_NO_APPLICATION_PROTOCOL;
            return 0;
        }
    }

    return 1;
}

/*
 * Upon success, returns 1.
 * Upon failure, returns 0 and sets |al| to the appropriate fatal alert.
 */
int ssl_check_clienthello_tlsext_late(SSL *s, int *al)
{
    s->tlsext_status_expected = 0;

    /*
     * If status request then ask callback what to do. Note: this must be
     * called after servername callbacks in case the certificate has changed,
     * and must be called after the cipher has been chosen because this may
     * influence which certificate is sent
     */
    if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb) {
        int ret;
        CERT_PKEY *certpkey;
        certpkey = ssl_get_server_send_pkey(s);
        /* If no certificate can't return certificate status */
        if (certpkey != NULL) {
            /*
             * Set current certificate to one we will use so SSL_get_certificate
             * et al can pick it up.
             */
            s->cert->key = certpkey;
            ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
            switch (ret) {
                /* We don't want to send a status request response */
            case SSL_TLSEXT_ERR_NOACK:
                s->tlsext_status_expected = 0;
                break;
                /* status request response should be sent */
            case SSL_TLSEXT_ERR_OK:
                if (s->tlsext_ocsp_resp)
                    s->tlsext_status_expected = 1;
                break;
                /* something bad happened */
            case SSL_TLSEXT_ERR_ALERT_FATAL:
            default:
                *al = SSL_AD_INTERNAL_ERROR;
                return 0;
            }
        }
    }

    if (!tls1_alpn_handle_client_hello_late(s, al)) {
        return 0;
    }

    return 1;
}

/* Add the server's renegotiation binding */
int tls_construct_server_renegotiate(SSL *s, WPACKET *pkt, int *al)
{
    if (!s->s3->send_connection_binding)
        return 1;

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
            || !WPACKET_start_sub_packet_u16(pkt)
            || !WPACKET_start_sub_packet_u8(pkt)
            || !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
                               s->s3->previous_client_finished_len)
            || !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
                               s->s3->previous_server_finished_len)
            || !WPACKET_close(pkt)
            || !WPACKET_close(pkt)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_RENEGOTIATE, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

int tls_construct_server_server_name(SSL *s, WPACKET *pkt, int *al)
{
    if (s->hit || s->servername_done != 1
            || s->session->tlsext_hostname == NULL)
        return 1;

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
            || !WPACKET_put_bytes_u16(pkt, 0)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_SERVER_NAME, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

#ifndef OPENSSL_NO_EC
int tls_construct_server_ec_pt_formats(SSL *s, WPACKET *pkt, int *al)
{
    unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
    unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
    int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
    using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
    const unsigned char *plist;
    size_t plistlen;

    if (!using_ecc)
        return 1;

    tls1_get_formatlist(s, &plist, &plistlen);

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
            || !WPACKET_start_sub_packet_u16(pkt)
            || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
            || !WPACKET_close(pkt)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}
#endif

int tls_construct_server_session_ticket(SSL *s, WPACKET *pkt, int *al)
{
    if (!s->tlsext_ticket_expected || !tls_use_ticket(s)) {
        s->tlsext_ticket_expected = 0;
        return 1;
    }

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
            || !WPACKET_put_bytes_u16(pkt, 0)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

int tls_construct_server_status_request(SSL *s, WPACKET *pkt, int *al)
{
    if (!s->tlsext_status_expected)
        return 1;

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
            || !WPACKET_put_bytes_u16(pkt, 0)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}


#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_construct_server_next_proto_neg(SSL *s, WPACKET *pkt, int *al)
{
    const unsigned char *npa;
    unsigned int npalen;
    int ret;
    int next_proto_neg_seen = s->s3->next_proto_neg_seen;

    s->s3->next_proto_neg_seen = 0;
    if (!next_proto_neg_seen || s->ctx->next_protos_advertised_cb == NULL)
        return 1;

    ret = s->ctx->next_protos_advertised_cb(s, &npa, &npalen,
                                      s->ctx->next_protos_advertised_cb_arg);
    if (ret == SSL_TLSEXT_ERR_OK) {
        if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
                || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
            SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_NEXT_PROTO_NEG,
                   ERR_R_INTERNAL_ERROR);
            return 0;
        }
        s->s3->next_proto_neg_seen = 1;
    }

    return 1;
}
#endif

int tls_construct_server_alpn(SSL *s, WPACKET *pkt, int *al)
{
    if (s->s3->alpn_selected == NULL)
        return 1;

    if (!WPACKET_put_bytes_u16(pkt,
                TLSEXT_TYPE_application_layer_protocol_negotiation)
            || !WPACKET_start_sub_packet_u16(pkt)
            || !WPACKET_start_sub_packet_u16(pkt)
            || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
                                      s->s3->alpn_selected_len)
            || !WPACKET_close(pkt)
            || !WPACKET_close(pkt)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_ALPN, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

#ifndef OPENSSL_NO_SRTP
int tls_construct_server_use_srtp(SSL *s, WPACKET *pkt, int *al)
{
    if (s->srtp_profile == NULL)
        return 1;
        
    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
            || !WPACKET_start_sub_packet_u16(pkt)
            || !WPACKET_put_bytes_u16(pkt, 2)
            || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
            || !WPACKET_put_bytes_u8(pkt, 0)
            || !WPACKET_close(pkt)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_USE_SRTP, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}
#endif

int tls_construct_server_etm(SSL *s, WPACKET *pkt, int *al)
{
    if ((s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) == 0)
        return 1;

    /*
     * Don't use encrypt_then_mac if AEAD or RC4 might want to disable
     * for other cases too.
     */
    if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
        || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
        || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
        || s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
        s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
        return 1;
    }

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
            || !WPACKET_put_bytes_u16(pkt, 0)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_ETM, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

int tls_construct_server_ems(SSL *s, WPACKET *pkt, int *al)
{
    if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
        return 1;

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
            || !WPACKET_put_bytes_u16(pkt, 0)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_EMS, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

int tls_construct_server_key_share(SSL *s, WPACKET *pkt, int *al)
{
    unsigned char *encodedPoint;
    size_t encoded_pt_len = 0;
    EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;

    if (s->hit)
        return 1;

    if (ckey == NULL) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
            || !WPACKET_start_sub_packet_u16(pkt)
            || !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    skey = ssl_generate_pkey(ckey);
    if (skey == NULL) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    /* Generate encoding of server key */
    encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
    if (encoded_pt_len == 0) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_EC_LIB);
        EVP_PKEY_free(skey);
        return 0;
    }

    if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
            || !WPACKET_close(pkt)) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
        EVP_PKEY_free(skey);
        OPENSSL_free(encodedPoint);
        return 0;
    }
    OPENSSL_free(encodedPoint);

    /* This causes the crypto state to be updated based on the derived keys */
    s->s3->tmp.pkey = skey;
    if (ssl_derive(s, skey, ckey, 1) == 0) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_SHARE, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}

int tls_construct_server_cryptopro_bug(SSL *s, WPACKET *pkt, int *al)
{
    const unsigned char cryptopro_ext[36] = {
        0xfd, 0xe8,         /* 65000 */
        0x00, 0x20,         /* 32 bytes length */
        0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
        0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
        0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
        0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
    };

    if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
         && (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
            || (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
        return 1;

    if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
        SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return 1;
}
Loading