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; }
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 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; }
static int tls1_generate_key_block(SSL *s, unsigned char *km, unsigned char *tmp, int num) { int ret; ret = tls1_PRF(ssl_get_algorithm2(s), TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, s->s3->client_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, s->session->master_key,s->session->master_key_length, km,tmp,num); #ifdef KSSL_DEBUG printf("tls1_generate_key_block() ==> %d byte master_key =\n\t", s->session->master_key_length); { int i; for (i=0; i < s->session->master_key_length; i++) { printf("%02X", s->session->master_key[i]); } printf("\n"); } #endif /* KSSL_DEBUG */ return ret; }
int tls1_change_cipher_state(SSL *s, int which) { static const unsigned char empty[]=""; unsigned char *p,*mac_secret; unsigned char *exp_label; unsigned char tmp1[EVP_MAX_KEY_LENGTH]; unsigned char tmp2[EVP_MAX_KEY_LENGTH]; unsigned char iv1[EVP_MAX_IV_LENGTH*2]; unsigned char iv2[EVP_MAX_IV_LENGTH*2]; unsigned char *ms,*key,*iv; int client_write; EVP_CIPHER_CTX *dd; const EVP_CIPHER *c; #ifndef OPENSSL_NO_COMP const SSL_COMP *comp; #endif const EVP_MD *m; int mac_type; int *mac_secret_size; EVP_MD_CTX *mac_ctx; EVP_PKEY *mac_key; int is_export,n,i,j,k,exp_label_len,cl; int reuse_dd = 0; is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher); c=s->s3->tmp.new_sym_enc; m=s->s3->tmp.new_hash; mac_type = s->s3->tmp.new_mac_pkey_type; #ifndef OPENSSL_NO_COMP comp=s->s3->tmp.new_compression; #endif #ifdef KSSL_DEBUG printf("tls1_change_cipher_state(which= %d) w/\n", which); printf("\talg= %ld/%ld, comp= %p\n", s->s3->tmp.new_cipher->algorithm_mkey, s->s3->tmp.new_cipher->algorithm_auth, comp); printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c); printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n", c->nid,c->block_size,c->key_len,c->iv_len); printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length); { int i; for (i=0; i<s->s3->tmp.key_block_length; i++) printf("%02x", s->s3->tmp.key_block[i]); printf("\n"); } #endif /* KSSL_DEBUG */ if (which & SSL3_CC_READ) { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; else s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; if (s->enc_read_ctx != NULL) reuse_dd = 1; else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) goto err; else /* make sure it's intialized in case we exit later with an error */ EVP_CIPHER_CTX_init(s->enc_read_ctx); dd= s->enc_read_ctx; mac_ctx=ssl_replace_hash(&s->read_hash,NULL); #ifndef OPENSSL_NO_COMP if (s->expand != NULL) { COMP_CTX_free(s->expand); s->expand=NULL; } if (comp != NULL) { s->expand=COMP_CTX_new(comp->method); if (s->expand == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } if (s->s3->rrec.comp == NULL) s->s3->rrec.comp=(unsigned char *) OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH); if (s->s3->rrec.comp == NULL) goto err; } #endif /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ if (s->version != DTLS1_VERSION) memset(&(s->s3->read_sequence[0]),0,8); mac_secret= &(s->s3->read_mac_secret[0]); mac_secret_size=&(s->s3->read_mac_secret_size); } else { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM; else s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM; if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) reuse_dd = 1; else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == NULL) goto err; dd= s->enc_write_ctx; if (SSL_IS_DTLS(s)) { mac_ctx = EVP_MD_CTX_create(); if (!mac_ctx) goto err; s->write_hash = mac_ctx; } else mac_ctx = ssl_replace_hash(&s->write_hash,NULL); #ifndef OPENSSL_NO_COMP if (s->compress != NULL) { COMP_CTX_free(s->compress); s->compress=NULL; } if (comp != NULL) { s->compress=COMP_CTX_new(comp->method); if (s->compress == NULL) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR); goto err2; } } #endif /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */ if (s->version != DTLS1_VERSION) memset(&(s->s3->write_sequence[0]),0,8); mac_secret= &(s->s3->write_mac_secret[0]); mac_secret_size = &(s->s3->write_mac_secret_size); } if (reuse_dd) EVP_CIPHER_CTX_cleanup(dd); p=s->s3->tmp.key_block; i=*mac_secret_size=s->s3->tmp.new_mac_secret_size; cl=EVP_CIPHER_key_length(c); j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ? cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl; /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */ /* If GCM mode only part of IV comes from PRF */ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) k = EVP_GCM_TLS_FIXED_IV_LEN; else k=EVP_CIPHER_iv_length(c); if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) || (which == SSL3_CHANGE_CIPHER_SERVER_READ)) { ms= &(p[ 0]); n=i+i; key= &(p[ n]); n+=j+j; iv= &(p[ n]); n+=k+k; exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST; exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE; client_write=1; } else { n=i; ms= &(p[ n]); n+=i+j; key= &(p[ n]); n+=j+k; iv= &(p[ n]); n+=k; exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST; exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE; client_write=0; } if (n > s->s3->tmp.key_block_length) { SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR); goto err2; } memcpy(mac_secret,ms,i); if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER)) { mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,*mac_secret_size); EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key); EVP_PKEY_free(mac_key); } #ifdef TLS_DEBUG printf("which = %04X\nmac key=",which); { int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); } #endif if (is_export) { /* In here I set both the read and write key/iv to the * same value since only the correct one will be used :-). */ if (!tls1_PRF(ssl_get_algorithm2(s), exp_label,exp_label_len, s->s3->client_random,SSL3_RANDOM_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, key,j,tmp1,tmp2,EVP_CIPHER_key_length(c))) goto err2; key=tmp1; if (k > 0) { if (!tls1_PRF(ssl_get_algorithm2(s), TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE, s->s3->client_random,SSL3_RANDOM_SIZE, s->s3->server_random,SSL3_RANDOM_SIZE, NULL,0,NULL,0, empty,0,iv1,iv2,k*2)) goto err2; if (client_write) iv=iv1; else iv= &(iv1[k]); } } s->session->key_arg_length=0; #ifdef KSSL_DEBUG { int i; printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n"); printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]); printf("\n"); printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]); printf("\n"); } #endif /* KSSL_DEBUG */ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) { EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE)); EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv); } else EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size) EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY, *mac_secret_size,mac_secret); #ifdef TLS_DEBUG printf("which = %04X\nkey=",which); { int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); } printf("\niv="); { int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); } printf("\n"); #endif OPENSSL_cleanse(tmp1,sizeof(tmp1)); OPENSSL_cleanse(tmp2,sizeof(tmp1)); OPENSSL_cleanse(iv1,sizeof(iv1)); OPENSSL_cleanse(iv2,sizeof(iv2)); return(1); err: SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE); err2: return(0); }
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; }