/* * 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_supported_versions(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { int currv, min_version, max_version, reason; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u8(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, ERR_R_INTERNAL_ERROR); return 0; } reason = ssl_get_client_min_max_version(s, &min_version, &max_version); if (reason != 0) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason); return 0; } /* * TODO(TLS1.3): There is some discussion on the TLS list as to wheter * we should include versions <TLS1.2. For the moment we do. To be * reviewed later. */ for (currv = max_version; currv >= min_version; currv--) { /* TODO(TLS1.3): Remove this first if clause prior to release!! */ if (currv == TLS1_3_VERSION) { if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, ERR_R_INTERNAL_ERROR); return 0; } } else if (!WPACKET_put_bytes_u16(pkt, currv)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, ERR_R_INTERNAL_ERROR); return 0; } } if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
/* * Add the server's renegotiation binding */ int tls_construct_stoc_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_STOC_RENEGOTIATE, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int tls_construct_ctos_srp(SSL *s, WPACKET *pkt, int *al) { /* Add SRP username if there is one */ if (s->srp_ctx.login == NULL) return 1; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp) /* Sub-packet for SRP extension */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u8(pkt) /* login must not be zero...internal error if so */ || !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH) || !WPACKET_memcpy(pkt, s->srp_ctx.login, strlen(s->srp_ctx.login)) || !WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SRP, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
/* * Add the server's renegotiation binding */ EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { if (!s->s3->send_connection_binding) return EXT_RETURN_NOT_SENT; 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_STOC_RENEGOTIATE, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
/* * Construct a psk_kex_modes extension. We only have two modes we know about * at this stage, so we send both. */ int tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 /* * TODO(TLS1.3): Do we want this list to be configurable? For now we always * just send both supported modes */ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u8(pkt) || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE) || !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE) || !WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR); return 0; } s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE; #endif 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; }