EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, 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)) && (s->session->ext.ecpointformats != NULL); const unsigned char *plist; size_t plistlen; if (!using_ecc) return EXT_RETURN_NOT_SENT; 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_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
/* * Given a |secret|; a |label| of length |labellen|; and a |hash| of the * handshake messages, derive a new secret |outlen| bytes long and store it in * the location pointed to be |out|. The |hash| value may be NULL. Returns 1 on * success 0 on failure. */ static int tls13_hkdf_expand(SSL *s, const unsigned char *secret, const unsigned char *label, size_t labellen, const unsigned char *hash, unsigned char *out, size_t outlen) { const unsigned char label_prefix[] = "TLS 1.3, "; const EVP_MD *md = ssl_handshake_md(s); EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); int ret; size_t hkdflabellen; size_t hashlen; /* * 2 bytes for length of whole HkdfLabel + 1 byte for length of combined * prefix and label + bytes for the label itself + bytes for the hash */ unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) + + sizeof(label_prefix) + TLS13_MAX_LABEL_LEN + EVP_MAX_MD_SIZE]; WPACKET pkt; if (pctx == NULL) return 0; hashlen = EVP_MD_size(md); if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0) || !WPACKET_put_bytes_u16(&pkt, outlen) || !WPACKET_start_sub_packet_u8(&pkt) || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1) || !WPACKET_memcpy(&pkt, label, labellen) || !WPACKET_close(&pkt) || !WPACKET_sub_memcpy_u8(&pkt, hash, (hash == NULL) ? 0 : hashlen) || !WPACKET_get_total_written(&pkt, &hkdflabellen) || !WPACKET_finish(&pkt)) { WPACKET_cleanup(&pkt); return 0; } ret = EVP_PKEY_derive_init(pctx) <= 0 || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) <= 0 || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0 || EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0 || EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0 || EVP_PKEY_derive(pctx, out, &outlen) <= 0; EVP_PKEY_CTX_free(pctx); return ret == 0; }
int tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, int *al) { /* Add RI if renegotiating */ if (!s->renegotiate) return 1; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished, s->s3->previous_client_finished_len) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int tls_construct_stoc_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_STOC_ALPN, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { if (s->s3->alpn_selected == NULL) return EXT_RETURN_NOT_SENT; 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_STOC_ALPN, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
int tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt, int *al) { const unsigned char *pformats; size_t num_formats; if (!use_ecc(s)) return 1; /* Add TLS extension ECPointFormats to the ClientHello message */ tls1_get_formatlist(s, &pformats, &num_formats); if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats) /* Sub-packet for formats extension */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
/* * Given a |secret|; a |label| of length |labellen|; and |data| of length * |datalen| (e.g. typically a hash of the handshake messages), derive a new * secret |outlen| bytes long and store it in the location pointed to be |out|. * The |data| value may be zero length. Any errors will be treated as fatal if * |fatal| is set. Returns 1 on success 0 on failure. */ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret, const unsigned char *label, size_t labellen, const unsigned char *data, size_t datalen, unsigned char *out, size_t outlen, int fatal) { static const unsigned char label_prefix[] = "tls13 "; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); int ret; size_t hkdflabellen; size_t hashlen; /* * 2 bytes for length of derived secret + 1 byte for length of combined * prefix and label + bytes for the label itself + 1 byte length of hash * + bytes for the hash itself */ unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) + + sizeof(label_prefix) + TLS13_MAX_LABEL_LEN + 1 + EVP_MAX_MD_SIZE]; WPACKET pkt; if (pctx == NULL) return 0; if (labellen > TLS13_MAX_LABEL_LEN) { if (fatal) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); } else { /* * Probably we have been called from SSL_export_keying_material(), * or SSL_export_keying_material_early(). */ SSLerr(SSL_F_TLS13_HKDF_EXPAND, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); } EVP_PKEY_CTX_free(pctx); return 0; } hashlen = EVP_MD_size(md); if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0) || !WPACKET_put_bytes_u16(&pkt, outlen) || !WPACKET_start_sub_packet_u8(&pkt) || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1) || !WPACKET_memcpy(&pkt, label, labellen) || !WPACKET_close(&pkt) || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen) || !WPACKET_get_total_written(&pkt, &hkdflabellen) || !WPACKET_finish(&pkt)) { EVP_PKEY_CTX_free(pctx); WPACKET_cleanup(&pkt); if (fatal) SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); else SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); return 0; } ret = EVP_PKEY_derive_init(pctx) <= 0 || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) <= 0 || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0 || EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0 || EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0 || EVP_PKEY_derive(pctx, out, &outlen) <= 0; EVP_PKEY_CTX_free(pctx); if (ret != 0) { if (fatal) SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); else SSLerr(SSL_F_TLS13_HKDF_EXPAND, ERR_R_INTERNAL_ERROR); } return ret == 0; }