/* seed1 through seed5 are virtually concatenated */ static int tls1_PRF(long digest_mask, const void *seed1, int seed1_len, const void *seed2, int seed2_len, const void *seed3, int seed3_len, const void *seed4, int seed4_len, const void *seed5, int seed5_len, const unsigned char *sec, int slen, unsigned char *out1, unsigned char *out2, int olen) { int len,i,idx,count; const unsigned char *S1; long m; const EVP_MD *md; int ret = 0; /* Count number of digests and partition sec evenly */ count=0; for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++; } len=slen/count; if (count == 1) slen = 0; S1=sec; memset(out1,0,olen); for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) { if (!md) { SSLerr(SSL_F_TLS1_PRF, SSL_R_UNSUPPORTED_DIGEST_TYPE); goto err; } if (!tls1_P_hash(md ,S1,len+(slen&1), seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len, out2,olen)) goto err; S1+=len; for (i=0; i<olen; i++) { out1[i]^=out2[i]; } } } ret = 1; err: return ret; }
int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, size_t secret_len, const char *label, size_t label_len, const uint8_t *seed1, size_t seed1_len, const uint8_t *seed2, size_t seed2_len) { if (out_len == 0) { return 1; } memset(out, 0, out_len); uint32_t algorithm_prf = ssl_get_algorithm_prf(s); if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) { /* If using the MD5/SHA1 PRF, |secret| is partitioned between SHA-1 and * MD5, MD5 first. */ size_t secret_half = secret_len - (secret_len / 2); if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half, (const uint8_t *)label, label_len, seed1, seed1_len, seed2, seed2_len)) { return 0; } /* Note that, if |secret_len| is odd, the two halves share a byte. */ secret = secret + (secret_len - secret_half); secret_len = secret_half; } if (!tls1_P_hash(out, out_len, ssl_get_handshake_digest(algorithm_prf), secret, secret_len, (const uint8_t *)label, label_len, seed1, seed1_len, seed2, seed2_len)) { return 0; } return 1; }
int tls13_advance_key_schedule(SSL *ssl, const uint8_t *in, size_t len) { SSL_HANDSHAKE *hs = ssl->s3->hs; const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); return HKDF_extract(hs->secret, &hs->hash_len, digest, in, len, hs->secret, hs->hash_len); }
const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session, const SSL *ssl) { uint16_t version; if (!ssl->method->version_from_wire(&version, session->ssl_version)) { return NULL; } return ssl_get_handshake_digest(session->cipher->algorithm_prf, version); }
int tls1_final_finish_mac(SSL *s, const char *str, int slen, unsigned char *out) { unsigned int i; EVP_MD_CTX ctx; unsigned char buf[2*EVP_MAX_MD_SIZE]; unsigned char *q,buf2[12]; int idx; long mask; int err=0; const EVP_MD *md; q=buf; if (s->s3->handshake_buffer) if (!ssl3_digest_cached_records(s)) return 0; EVP_MD_CTX_init(&ctx); for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++) { if (mask & s->s3->tmp.new_cipher->algorithm2) { int hashsize = EVP_MD_size(md); if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf))) { /* internal error: 'buf' is too small for this cipersuite! */ err = 1; } else { EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]); EVP_DigestFinal_ex(&ctx,q,&i); if (i != (unsigned int)hashsize) /* can't really happen */ err = 1; q+=i; } } } if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2, str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0, s->session->master_key,s->session->master_key_length, out,buf2,sizeof buf2)) err = 1; EVP_MD_CTX_cleanup(&ctx); if (err) return 0; else return sizeof buf2; }
int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, const uint8_t *context, size_t context_len, int use_context) { if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) { return 0; } /* Exporters may not be used in the middle of a renegotiation. */ if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) { return 0; } if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) { return tls13_export_keying_material(ssl, out, out_len, label, label_len, context, context_len, use_context); } size_t seed_len = 2 * SSL3_RANDOM_SIZE; if (use_context) { if (context_len >= 1u << 16) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return 0; } seed_len += 2 + context_len; } uint8_t *seed = OPENSSL_malloc(seed_len); if (seed == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); return 0; } OPENSSL_memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE); OPENSSL_memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE); if (use_context) { seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8); seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len; OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len); } const EVP_MD *digest = ssl_get_handshake_digest( SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl)); if (digest == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key, SSL_get_session(ssl)->master_key_length, label, label_len, seed, seed_len, NULL, 0); OPENSSL_free(seed); return ret; }
int ssl3_digest_cached_records( SSL *s, enum should_free_handshake_buffer_t should_free_handshake_buffer) { int i; long mask; const EVP_MD *md; const uint8_t *hdata; size_t hdatalen; /* Allocate handshake_dgst array */ ssl3_free_digest_list(s); s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); if (s->s3->handshake_dgst == NULL) { OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_R_MALLOC_FAILURE); return 0; } memset(s->s3->handshake_dgst, 0, SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen)) { OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, SSL_R_BAD_HANDSHAKE_LENGTH); return 0; } /* Loop through bits of algorithm2 field and create MD_CTX-es */ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) { if ((mask & ssl_get_algorithm2(s)) && md) { s->s3->handshake_dgst[i] = EVP_MD_CTX_create(); if (s->s3->handshake_dgst[i] == NULL) { OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP); return 0; } if (!EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL)) { EVP_MD_CTX_destroy(s->s3->handshake_dgst[i]); s->s3->handshake_dgst[i] = NULL; OPENSSL_PUT_ERROR(SSL, ssl3_digest_cached_records, ERR_LIB_EVP); return 0; } EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen); } else { s->s3->handshake_dgst[i] = NULL; } } if (should_free_handshake_buffer == free_handshake_buffer) { /* Free handshake_buffer BIO */ BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; } return 1; }
/* derive_secret derives a secret of length |len| and writes the result in |out| * with the given label and the current base secret and most recently-saved * handshake context. It returns one on success and zero on error. */ static int derive_secret(SSL *ssl, uint8_t *out, size_t len, const uint8_t *label, size_t label_len) { SSL_HANDSHAKE *hs = ssl->s3->hs; const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); uint8_t context_hashes[2 * EVP_MAX_MD_SIZE]; size_t context_hashes_len; if (!tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len)) { return 0; } return hkdf_expand_label(out, digest, hs->secret, hs->hash_len, label, label_len, context_hashes, context_hashes_len, len); }
int ssl3_digest_cached_records(SSL *s) { int i; long mask; const EVP_MD *md; long hdatalen; void *hdata; /* Allocate handshake_dgst array */ ssl3_free_digest_list(s); s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *)); hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata); if (hdatalen <= 0) { SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); return 0; } /* Loop through bitso of algorithm2 field and create MD_CTX-es */ for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) { if ((mask & ssl_get_algorithm2(s)) && md) { s->s3->handshake_dgst[i]=EVP_MD_CTX_create(); #ifdef OPENSSL_FIPS if (EVP_MD_nid(md) == NID_md5) { EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i], EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); } #endif EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL); EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen); } else { s->s3->handshake_dgst[i]=NULL; } } if (!(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { /* Free handshake_buffer BIO */ BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; } return 1; }
int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, const uint8_t *context, size_t context_len, int use_context) { const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); const uint8_t *hash = NULL; size_t hash_len = 0; if (use_context) { hash = context; hash_len = context_len; } return hkdf_expand_label(out, digest, ssl->s3->exporter_secret, ssl->s3->exporter_secret_len, (const uint8_t *)label, label_len, hash, hash_len, out_len); }
int ssl3_digest_cached_records(SSL *s, int keep) { int i; long mask; const EVP_MD *md; long hdatalen; void *hdata; if (s->s3->handshake_dgst == NULL) { /* Allocate handshake_dgst array */ s->s3->handshake_dgst = OPENSSL_malloc(sizeof(*s->s3->handshake_dgst) * SSL_MAX_DIGEST); if (s->s3->handshake_dgst == NULL) { SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, ERR_R_MALLOC_FAILURE); return 0; } hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata); if (hdatalen <= 0) { SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); return 0; } /* Loop through bits of algorithm2 field and create MD_CTX-es */ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) { if ((mask & ssl_get_algorithm2(s)) && md) { s->s3->handshake_dgst[i] = EVP_MD_CTX_create(); if (EVP_MD_nid(md) == NID_md5) { EVP_MD_CTX_set_flags(s->s3->handshake_dgst[i], EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); } EVP_DigestInit_ex(s->s3->handshake_dgst[i], md, NULL); EVP_DigestUpdate(s->s3->handshake_dgst[i], hdata, hdatalen); } else { s->s3->handshake_dgst[i] = NULL; } } } if (keep == 0) { BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; } return 1; }
int ssl3_init_handshake_hash(SSL *ssl) { ssl3_free_handshake_hash(ssl); uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl); if (!init_digest_with_data(&ssl->s3->handshake_hash, ssl_get_handshake_digest(algorithm_prf), ssl->s3->handshake_buffer)) { return 0; } if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT && !init_digest_with_data(&ssl->s3->handshake_md5, EVP_md5(), ssl->s3->handshake_buffer)) { return 0; } return 1; }
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) { if (ssl3_protocol_version(ssl) == SSL3_VERSION) { return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key, SSL_get_session(ssl)->master_key_length, TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE); } const EVP_MD *digest = ssl_get_handshake_digest( SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl)); if (digest == NULL) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return 0; } return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key, SSL_get_session(ssl)->master_key_length, TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE); }
int ssl3_digest_cached_records(SSL *s) { int i; long mask; const EVP_MD *md; long hdatalen; void *hdata; /* Allocate handshake_dgst array */ ssl3_free_digest_list(s); s->s3->handshake_dgst = OPENSSL_malloc(SSL_MAX_DIGEST * sizeof(EVP_MD_CTX *)); memset(s->s3->handshake_dgst,0,SSL_MAX_DIGEST *sizeof(EVP_MD_CTX *)); hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,&hdata); if (hdatalen <= 0) { SSLerr(SSL_F_SSL3_DIGEST_CACHED_RECORDS, SSL_R_BAD_HANDSHAKE_LENGTH); return 0; } /* Loop through bitso of algorithm2 field and create MD_CTX-es */ for (i=0;ssl_get_handshake_digest(i,&mask,&md); i++) { if ((mask & s->s3->tmp.new_cipher->algorithm2) && md) { s->s3->handshake_dgst[i]=EVP_MD_CTX_create(); EVP_DigestInit_ex(s->s3->handshake_dgst[i],md,NULL); EVP_DigestUpdate(s->s3->handshake_dgst[i],hdata,hdatalen); } else { s->s3->handshake_dgst[i]=NULL; } } /* Free handshake_buffer BIO */ BIO_free(s->s3->handshake_buffer); s->s3->handshake_buffer = NULL; return 1; }
int tls13_finished_mac(SSL *ssl, uint8_t *out, size_t *out_len, int is_server) { SSL_HANDSHAKE *hs = ssl->s3->hs; const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); uint8_t key[EVP_MAX_MD_SIZE]; size_t key_len = EVP_MD_size(digest); uint8_t *traffic_secret; const char *label; if (is_server) { label = "server finished"; if (ssl->server) { traffic_secret = ssl->s3->write_traffic_secret; } else { traffic_secret = ssl->s3->read_traffic_secret; } } else { label = "client finished"; if (!ssl->server) { traffic_secret = ssl->s3->write_traffic_secret; } else { traffic_secret = ssl->s3->read_traffic_secret; } } uint8_t context_hashes[2 * EVP_MAX_MD_SIZE]; size_t context_hashes_len; unsigned len; if (!hkdf_expand_label(key, digest, traffic_secret, hs->hash_len, (const uint8_t *)label, strlen(label), NULL, 0, hs->hash_len) || !tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len) || HMAC(digest, key, key_len, context_hashes, context_hashes_len, out, &len) == NULL) { return 0; } *out_len = len; return 1; }
int tls13_init_key_schedule(SSL *ssl, const uint8_t *resumption_ctx, size_t resumption_ctx_len) { SSL_HANDSHAKE *hs = ssl->s3->hs; const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); hs->hash_len = EVP_MD_size(digest); /* Save the hash of the resumption context. */ unsigned resumption_hash_len; if (!EVP_Digest(resumption_ctx, resumption_ctx_len, hs->resumption_hash, &resumption_hash_len, digest, NULL)) { return 0; } /* Initialize the secret to the zero key. */ memset(hs->secret, 0, hs->hash_len); /* Initialize the rolling hashes and release the handshake buffer. */ if (!ssl3_init_handshake_hash(ssl)) { return 0; } ssl3_free_handshake_buffer(ssl); return 1; }
static enum ssl_hs_wait_t do_select_parameters(SSL *ssl, SSL_HANDSHAKE *hs) { /* Call |cert_cb| to update server certificates if required. */ if (ssl->cert->cert_cb != NULL) { int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg); if (rv == 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } if (rv < 0) { hs->state = state_select_parameters; return ssl_hs_x509_lookup; } } struct ssl_early_callback_ctx client_hello; if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } const SSL_CIPHER *cipher = ssl3_choose_cipher(ssl, &client_hello, ssl_get_cipher_preferences(ssl)); if (cipher == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); return ssl_hs_error; } ssl->s3->new_session->cipher = cipher; ssl->s3->tmp.new_cipher = cipher; ssl->method->received_flight(ssl); /* The PRF hash is now known. Set up the key schedule and hash the * ClientHello. */ size_t hash_len = EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl))); if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } /* Resolve PSK and incorporate it into the secret. */ if (!resolve_psk_secret(ssl)) { return ssl_hs_error; } /* Resolve ECDHE and incorporate it into the secret. */ int need_retry; if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) { if (need_retry) { hs->state = state_send_hello_retry_request; return ssl_hs_ok; } return ssl_hs_error; } hs->state = state_send_server_hello; return ssl_hs_ok; }
static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) { if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) { return ssl_hs_error; } CBS cbs, server_random, extensions; uint16_t server_wire_version; uint16_t cipher_suite; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u16(&cbs, &server_wire_version) || !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) || !CBS_get_u16(&cbs, &cipher_suite) || !CBS_get_u16_length_prefixed(&cbs, &extensions) || CBS_len(&cbs) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return ssl_hs_error; } if (server_wire_version != ssl->version) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); return ssl_hs_error; } /* Parse out the extensions. */ int have_key_share = 0; CBS key_share; while (CBS_len(&extensions) != 0) { uint16_t type; CBS extension; if (!CBS_get_u16(&extensions, &type) || !CBS_get_u16_length_prefixed(&extensions, &extension)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } switch (type) { case TLSEXT_TYPE_key_share: if (have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } key_share = extension; have_key_share = 1; break; default: OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); return ssl_hs_error; } } assert(ssl->s3->have_version); memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); ssl->hit = 0; if (!ssl_get_new_session(ssl, 0)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite); if (cipher == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } /* Check if the cipher is disabled. */ if ((cipher->algorithm_mkey & ssl->cert->mask_k) || (cipher->algorithm_auth & ssl->cert->mask_a) || SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) || SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl) || !sk_SSL_CIPHER_find(ssl_get_ciphers_by_id(ssl), NULL, cipher)) { OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } ssl->session->cipher = cipher; ssl->s3->tmp.new_cipher = cipher; /* The PRF hash is now known. Set up the key schedule. */ static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0}; size_t hash_len = EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl))); if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } /* Resolve PSK and incorporate it into the secret. */ if (cipher->algorithm_auth == SSL_aPSK) { /* TODO(davidben): Support PSK. */ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return ssl_hs_error; } else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } /* Resolve ECDHE and incorporate it into the secret. */ if (cipher->algorithm_mkey == SSL_kECDHE) { if (!have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION); return ssl_hs_error; } uint8_t *dhe_secret; size_t dhe_secret_len; uint8_t alert = SSL_AD_DECODE_ERROR; if (!ext_key_share_parse_serverhello(ssl, &dhe_secret, &dhe_secret_len, &alert, &key_share)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len); OPENSSL_free(dhe_secret); if (!ok) { return ssl_hs_error; } } else { if (have_key_share) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); return ssl_hs_error; } if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) { return ssl_hs_error; } } /* If there was no HelloRetryRequest, the version negotiation logic has * already hashed the message. */ if (ssl->s3->hs->retry_group != 0 && !ssl->method->hash_current_message(ssl)) { return ssl_hs_error; } if (!tls13_set_handshake_traffic(ssl)) { return ssl_hs_error; } hs->state = state_process_encrypted_extensions; return ssl_hs_read_message; }
int tls1_prf(SSL *s, uint8_t *out, size_t out_len, const uint8_t *secret, size_t secret_len, const char *label, size_t label_len, const uint8_t *seed1, size_t seed1_len, const uint8_t *seed2, size_t seed2_len) { size_t idx, len, count, i; const uint8_t *S1; long m; const EVP_MD *md; int ret = 0; uint8_t *tmp; if (out_len == 0) { return 1; } /* Allocate a temporary buffer. */ tmp = OPENSSL_malloc(out_len); if (tmp == NULL) { OPENSSL_PUT_ERROR(SSL, tls1_prf, ERR_R_MALLOC_FAILURE); return 0; } /* Count number of digests and partition |secret| evenly. */ count = 0; for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) { count++; } } /* TODO(davidben): The only case where count isn't 1 is the old MD5/SHA-1 * combination. The logic around multiple handshake digests can probably be * simplified. */ assert(count == 1 || count == 2); len = secret_len / count; if (count == 1) { secret_len = 0; } S1 = secret; memset(out, 0, out_len); for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { if ((m << TLS1_PRF_DGST_SHIFT) & ssl_get_algorithm2(s)) { /* If |count| is 2 and |secret_len| is odd, |secret| is partitioned into * two halves with an overlapping byte. */ if (!tls1_P_hash(tmp, out_len, md, S1, len + (secret_len & 1), (const uint8_t *)label, label_len, seed1, seed1_len, seed2, seed2_len)) { goto err; } S1 += len; for (i = 0; i < out_len; i++) { out[i] ^= tmp[i]; } } } ret = 1; err: OPENSSL_cleanse(tmp, out_len); OPENSSL_free(tmp); return ret; }
static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; /* The short record header extension is incompatible with early data. */ if (ssl->s3->skip_early_data && ssl->s3->short_header) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); return ssl_hs_error; } SSL_CLIENT_HELLO client_hello; if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } /* Negotiate the cipher suite. */ ssl->s3->tmp.new_cipher = choose_tls13_cipher(ssl, &client_hello); if (ssl->s3->tmp.new_cipher == NULL) { OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); return ssl_hs_error; } /* Decode the ticket if we agree on a PSK key exchange mode. */ uint8_t alert = SSL_AD_DECODE_ERROR; SSL_SESSION *session = NULL; CBS pre_shared_key, binders; if (hs->accept_psk_mode && ssl_client_hello_get_extension(&client_hello, &pre_shared_key, TLSEXT_TYPE_pre_shared_key)) { /* Verify that the pre_shared_key extension is the last extension in * ClientHello. */ if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) != client_hello.extensions + client_hello.extensions_len) { OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; } if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &session, &binders, &alert, &pre_shared_key)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } } if (session != NULL && !ssl_session_is_resumable(ssl, session)) { SSL_SESSION_free(session); session = NULL; } /* Set up the new session, either using the original one as a template or * creating a fresh one. */ if (session == NULL) { if (!ssl_get_new_session(hs, 1 /* server */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher; /* On new sessions, stash the SNI value in the session. */ if (hs->hostname != NULL) { OPENSSL_free(ssl->s3->new_session->tlsext_hostname); ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname); if (ssl->s3->new_session->tlsext_hostname == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } } } else { /* Check the PSK binder. */ if (!tls13_verify_psk_binder(ssl, session, &binders)) { SSL_SESSION_free(session); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR); return ssl_hs_error; } /* Only authentication information carries over in TLS 1.3. */ ssl->s3->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY); if (ssl->s3->new_session == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } ssl->s3->session_reused = 1; SSL_SESSION_free(session); /* Resumption incorporates fresh key material, so refresh the timeout. */ ssl_session_renew_timeout(ssl, ssl->s3->new_session, ssl->initial_ctx->session_psk_dhe_timeout); } if (ssl->ctx->dos_protection_cb != NULL && ssl->ctx->dos_protection_cb(&client_hello) == 0) { /* Connection rejected for DOS reasons. */ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was * deferred. Complete it now. */ if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } /* The PRF hash is now known. Set up the key schedule and hash the * ClientHello. */ size_t hash_len = EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl))); if (!tls13_init_key_schedule(hs) || !ssl_hash_current_message(ssl)) { return ssl_hs_error; } /* Incorporate the PSK into the running secret. */ if (ssl->s3->session_reused) { if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key, ssl->s3->new_session->master_key_length)) { return ssl_hs_error; } } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) { return ssl_hs_error; } ssl->method->received_flight(ssl); /* Resolve ECDHE and incorporate it into the secret. */ int need_retry; if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) { if (need_retry) { hs->tls13_state = state_send_hello_retry_request; return ssl_hs_ok; } return ssl_hs_error; } hs->tls13_state = state_send_server_hello; return ssl_hs_ok; }
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type, enum evp_aead_direction_t direction, const uint8_t *traffic_secret, size_t traffic_secret_len) { if (traffic_secret_len > 0xff) { OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); return 0; } const char *phase; switch (type) { case type_early_handshake: phase = "early handshake key expansion, "; break; case type_early_data: phase = "early application data key expansion, "; break; case type_handshake: phase = "handshake key expansion, "; break; case type_data: phase = "application data key expansion, "; break; default: return 0; } size_t phase_len = strlen(phase); const char *purpose = "client write key"; if ((ssl->server && direction == evp_aead_seal) || (!ssl->server && direction == evp_aead_open)) { purpose = "server write key"; } size_t purpose_len = strlen(purpose); /* The longest label has length 38 (type_early_data) + 16 (either purpose * value). */ uint8_t label[38 + 16]; size_t label_len = phase_len + purpose_len; if (label_len > sizeof(label)) { assert(0); return 0; } memcpy(label, phase, phase_len); memcpy(label + phase_len, purpose, purpose_len); /* Look up cipher suite properties. */ const EVP_AEAD *aead; const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)); size_t mac_secret_len, fixed_iv_len; if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len, ssl->session->cipher, ssl3_protocol_version(ssl))) { return 0; } /* Derive the key. */ size_t key_len = EVP_AEAD_key_length(aead); uint8_t key[EVP_AEAD_MAX_KEY_LENGTH]; if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label, label_len, NULL, 0, key_len)) { return 0; } /* The IV's label ends in "iv" instead of "key". */ if (label_len < 3) { assert(0); return 0; } label_len--; label[label_len - 2] = 'i'; label[label_len - 1] = 'v'; /* Derive the IV. */ size_t iv_len = EVP_AEAD_nonce_length(aead); uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH]; if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label, label_len, NULL, 0, iv_len)) { return 0; } SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(direction, ssl3_protocol_version(ssl), ssl->session->cipher, key, key_len, NULL, 0, iv, iv_len); if (traffic_aead == NULL) { return 0; } if (direction == evp_aead_open) { if (!ssl->method->set_read_state(ssl, traffic_aead)) { return 0; } } else { if (!ssl->method->set_write_state(ssl, traffic_aead)) { return 0; } } /* Save the traffic secret. */ if (direction == evp_aead_open) { memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len); ssl->s3->read_traffic_secret_len = traffic_secret_len; } else { memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len); ssl->s3->write_traffic_secret_len = traffic_secret_len; } return 1; }