X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Ft1_enc.c;h=28471c2c829ac66e770481832efaab3c6e917ab3;hp=3614b8a30ec78f856c60fb6d6358be1e1fdaab4d;hb=daddd9a950e491c31f9500d5e570bc7eb96b2823;hpb=d135da51922dc756ab42643099de96728891f1d4 diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 3614b8a30e..28471c2c82 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -159,68 +159,73 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, unsigned char *out, int olen) { int chunk; - unsigned int j; - HMAC_CTX ctx; - HMAC_CTX ctx_tmp; + size_t j; + EVP_MD_CTX ctx, ctx_tmp, ctx_init; + EVP_PKEY *mac_key; unsigned char A1[EVP_MAX_MD_SIZE]; - unsigned int A1_len; + size_t A1_len; int ret = 0; chunk=EVP_MD_size(md); OPENSSL_assert(chunk >= 0); - HMAC_CTX_init(&ctx); - HMAC_CTX_init(&ctx_tmp); - if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL)) + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_init(&ctx_tmp); + EVP_MD_CTX_init(&ctx_init); + EVP_MD_CTX_set_flags(&ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len); + if (!mac_key) goto err; - if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL)) + if (!EVP_DigestSignInit(&ctx_init,NULL,md, NULL, mac_key)) goto err; - if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len)) + if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init)) goto err; - if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len)) + if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len)) goto err; - if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len)) + if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len)) goto err; - if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len)) + if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len)) goto err; - if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len)) + if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len)) goto err; - if (!HMAC_Final(&ctx,A1,&A1_len)) + if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len)) + goto err; + if (!EVP_DigestSignFinal(&ctx,A1,&A1_len)) goto err; for (;;) { - if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */ - goto err; - if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */ + /* Reinit mac contexts */ + if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init)) goto err; - if (!HMAC_Update(&ctx,A1,A1_len)) + if (!EVP_DigestSignUpdate(&ctx,A1,A1_len)) goto err; - if (!HMAC_Update(&ctx_tmp,A1,A1_len)) + if (olen>chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp,&ctx)) goto err; - if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len)) + if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len)) goto err; - if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len)) + if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len)) goto err; - if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len)) + if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len)) goto err; - if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len)) + if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len)) goto err; - if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len)) + if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len)) goto err; if (olen > chunk) { - if (!HMAC_Final(&ctx,out,&j)) + if (!EVP_DigestSignFinal(&ctx,out,&j)) goto err; out+=j; olen-=j; - if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */ + /* calc the next A1 value */ + if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len)) goto err; } else /* last one */ { - if (!HMAC_Final(&ctx,A1,&A1_len)) + if (!EVP_DigestSignFinal(&ctx,A1,&A1_len)) goto err; memcpy(out,A1,olen); break; @@ -228,8 +233,10 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, } ret = 1; err: - HMAC_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&ctx_tmp); + EVP_PKEY_free(mac_key); + EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_cleanup(&ctx_tmp); + EVP_MD_CTX_cleanup(&ctx_init); OPENSSL_cleanse(A1,sizeof(A1)); return ret; } @@ -257,6 +264,8 @@ static int tls1_PRF(long digest_mask, if ((m<s3->tmp.new_cipher->algorithm2, + 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, @@ -351,7 +360,7 @@ int tls1_change_cipher_state(SSL *s, int which) { int i; for (i=0; is3->tmp.key_block_length; i++) - printf("%02x", key_block[i]); printf("\n"); + printf("%02x", s->s3->tmp.key_block[i]); printf("\n"); } #endif /* KSSL_DEBUG */ @@ -359,7 +368,7 @@ int tls1_change_cipher_state(SSL *s, int which) { if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; - else + else s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; if (s->enc_read_ctx != NULL) @@ -404,15 +413,20 @@ int tls1_change_cipher_state(SSL *s, int which) 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) + if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) reuse_dd = 1; - else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) + else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == NULL) goto err; - else - /* make sure it's intialized in case we exit later with an error */ - EVP_CIPHER_CTX_init(s->enc_write_ctx); dd= s->enc_write_ctx; - mac_ctx = ssl_replace_hash(&s->write_hash,NULL); + 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) { @@ -446,7 +460,11 @@ int tls1_change_cipher_state(SSL *s, int which) 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); */ - k=EVP_CIPHER_iv_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)) { @@ -475,10 +493,14 @@ int tls1_change_cipher_state(SSL *s, int which) } memcpy(mac_secret,ms,i); - 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); + + 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; zmsg_callback) + { + int wh = which & SSL3_CC_WRITE ? TLS1_RT_CRYPTO_WRITE : 0; + if (*mac_secret_size) + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC, + mac_secret, *mac_secret_size, + s, s->msg_callback_arg); + if (c->key_len) + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY, + key, c->key_len, + s, s->msg_callback_arg); + if (k) + { + if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE) + wh |= TLS1_RT_CRYPTO_FIXED_IV; + else + wh |= TLS1_RT_CRYPTO_IV; + s->msg_callback(2, s->version, wh, iv, k, + s, s->msg_callback_arg); + } + } +#endif + #ifdef TLS_DEBUG printf("which = %04X\nkey=",which); { int z; for (z=0; zs3->tmp.key_block_length != 0) return(1); - if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp)) + if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp, SSL_USE_ETM(s))) { SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return(0); @@ -637,19 +695,28 @@ err: return(ret); } +/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record's padding is valid / the encryption was successful. + * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, + * an internal error occurred. + */ int tls1_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; - int bs,i,ii,j,k,n=0; + int bs,i,j,k,pad=0,ret,mac_size=0; const EVP_CIPHER *enc; if (send) { if (EVP_MD_CTX_md(s->write_hash)) { - n=EVP_MD_CTX_size(s->write_hash); + int n=EVP_MD_CTX_size(s->write_hash); OPENSSL_assert(n >= 0); } ds=s->enc_write_ctx; @@ -661,19 +728,20 @@ int tls1_enc(SSL *s, int send) int ivlen; enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); /* For TLSv1.1 and later explicit IV */ - if (s->version >= TLS1_1_VERSION) + if (SSL_USE_EXPLICIT_IV(s) + && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) ivlen = EVP_CIPHER_iv_length(enc); else ivlen = 0; if (ivlen > 1) { if ( rec->data != rec->input) - /* we can't write into the input stream: - * Can this ever happen?? (steve) - */ - fprintf(stderr, - "%s:%d: rec->data != rec->input\n", - __FILE__, __LINE__); + /* we can't write into the input stream: + * Can this ever happen?? (steve) + */ + fprintf(stderr, + "%s:%d: rec->data != rec->input\n", + __FILE__, __LINE__); else if (RAND_bytes(rec->input, ivlen) <= 0) return -1; } @@ -683,7 +751,7 @@ int tls1_enc(SSL *s, int send) { if (EVP_MD_CTX_md(s->read_hash)) { - n=EVP_MD_CTX_size(s->read_hash); + int n=EVP_MD_CTX_size(s->read_hash); OPENSSL_assert(n >= 0); } ds=s->enc_read_ctx; @@ -698,18 +766,54 @@ int tls1_enc(SSL *s, int send) printf("tls1_enc(%d)\n", send); #endif /* KSSL_DEBUG */ - if ((s->session == NULL) || (ds == NULL) || - (enc == NULL)) + if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) { memmove(rec->data,rec->input,rec->length); rec->input=rec->data; + ret = 1; } else { l=rec->length; bs=EVP_CIPHER_block_size(ds->cipher); - if ((bs != 1) && send) + if (EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER) + { + unsigned char buf[13],*seq; + + seq = send?s->s3->write_sequence:s->s3->read_sequence; + + if (SSL_IS_DTLS(s)) + { + unsigned char dtlsseq[9],*p=dtlsseq; + + s2n(send?s->d1->w_epoch:s->d1->r_epoch,p); + memcpy(p,&seq[2],6); + memcpy(buf,dtlsseq,8); + } + else + { + memcpy(buf,seq,8); + for (i=7; i>=0; i--) /* increment */ + { + ++seq[i]; + if (seq[i] != 0) break; + } + } + + buf[8]=rec->type; + buf[9]=(unsigned char)(s->version>>8); + buf[10]=(unsigned char)(s->version); + buf[11]=rec->length>>8; + buf[12]=rec->length&0xff; + pad=EVP_CIPHER_CTX_ctrl(ds,EVP_CTRL_AEAD_TLS1_AAD,13,buf); + if (send) + { + l+=pad; + rec->length+=pad; + } + } + else if ((bs != 1) && send) { i=bs-((int)l%bs); @@ -730,13 +834,13 @@ int tls1_enc(SSL *s, int send) #ifdef KSSL_DEBUG { - unsigned long ui; + unsigned long ui; printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n", - ds,rec->data,rec->input,l); + ds,rec->data,rec->input,l); printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n", - ds->buf_len, ds->cipher->key_len, - DES_KEY_SZ, DES_SCHEDULE_SZ, - ds->cipher->iv_len); + ds->buf_len, ds->cipher->key_len, + DES_KEY_SZ, DES_SCHEDULE_SZ, + ds->cipher->iv_len); printf("\t\tIV: "); for (i=0; icipher->iv_len; i++) printf("%02X", ds->iv[i]); printf("\n"); @@ -749,74 +853,41 @@ int tls1_enc(SSL *s, int send) if (!send) { if (l == 0 || l%bs != 0) - { - SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); return 0; - } } - EVP_Cipher(ds,rec->data,rec->input,l); + i = EVP_Cipher(ds,rec->data,rec->input,l); + if ((EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_CUSTOM_CIPHER) + ?(i<0) + :(i==0)) + return -1; /* AEAD can fail to verify MAC */ + if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send) + { + rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN; + rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN; + rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + } #ifdef KSSL_DEBUG { - unsigned long i; - printf("\trec->data="); + unsigned long i; + printf("\trec->data="); for (i=0; idata[i]); printf("\n"); - } + printf(" %02x", rec->data[i]); printf("\n"); + } #endif /* KSSL_DEBUG */ + ret = 1; + if (!SSL_USE_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) + mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) - { - ii=i=rec->data[l-1]; /* padding_length */ - i++; - /* NB: if compression is in operation the first packet - * may not be of even length so the padding bug check - * cannot be performed. This bug workaround has been - * around since SSLeay so hopefully it is either fixed - * now or no buggy implementation supports compression - * [steve] - */ - if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) - && !s->expand) - { - /* First packet is even in size, so check */ - if ((memcmp(s->s3->read_sequence, - "\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1)) - s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; - if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) - i--; - } - /* TLS 1.0 does not bound the number of padding bytes by the block size. - * All of them must have value 'padding_length'. */ - if (i > (int)rec->length) - { - /* Incorrect padding. SSLerr() and ssl3_alert are done - * by caller: we don't want to reveal whether this is - * a decryption error or a MAC verification failure - * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ - return -1; - } - for (j=(int)(l-i); j<(int)l; j++) - { - if (rec->data[j] != ii) - { - /* Incorrect padding */ - return -1; - } - } - rec->length -=i; - if (s->version >= TLS1_1_VERSION) - { - rec->data += bs; /* skip the explicit IV */ - rec->input += bs; - rec->length -= bs; - } - } + ret = tls1_cbc_remove_padding(s, rec, bs, mac_size); + if (pad && !send) + rec->length -= pad; } - return(1); + return ret; } + int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) { unsigned int ret; @@ -869,26 +940,27 @@ int tls1_final_finish_mac(SSL *s, for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++) { - if (mask & s->s3->tmp.new_cipher->algorithm2) + if (mask & ssl_get_algorithm2(s)) { int hashsize = EVP_MD_size(md); - if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf))) + EVP_MD_CTX *hdgst = s->s3->handshake_dgst[idx]; + if (!hdgst || 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 */ + if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) || + !EVP_DigestFinal_ex(&ctx,q,&i) || + (i != (unsigned int)hashsize)) err = 1; - q+=i; + q+=hashsize; } } } - if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2, + if (!tls1_PRF(ssl_get_algorithm2(s), 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)) @@ -909,7 +981,7 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) size_t md_size; int i; EVP_MD_CTX hmac, *mac_ctx; - unsigned char buf[5]; + unsigned char header[13]; int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM)); int t; @@ -930,12 +1002,6 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) OPENSSL_assert(t >= 0); md_size=t; - buf[0]=rec->type; - buf[1]=(unsigned char)(ssl->version>>8); - buf[2]=(unsigned char)(ssl->version); - buf[3]=rec->length>>8; - buf[4]=rec->length&0xff; - /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ if (stream_mac) { @@ -947,24 +1013,58 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send) mac_ctx = &hmac; } - if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER) + if (SSL_IS_DTLS(ssl)) { unsigned char dtlsseq[8],*p=dtlsseq; s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); memcpy (p,&seq[2],6); - EVP_DigestSignUpdate(mac_ctx,dtlsseq,8); + memcpy(header, dtlsseq, 8); } else - EVP_DigestSignUpdate(mac_ctx,seq,8); + memcpy(header, seq, 8); + + header[8]=rec->type; + header[9]=(unsigned char)(ssl->version>>8); + header[10]=(unsigned char)(ssl->version); + header[11]=(rec->length)>>8; + header[12]=(rec->length)&0xff; - EVP_DigestSignUpdate(mac_ctx,buf,5); - EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); - t=EVP_DigestSignFinal(mac_ctx,md,&md_size); - OPENSSL_assert(t > 0); + if (!send && !SSL_USE_ETM(ssl) && + EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(mac_ctx)) + { + /* This is a CBC-encrypted record. We must avoid leaking any + * timing-side channel information about how many blocks of + * data we are hashing because that gives an attacker a + * timing-oracle. */ + ssl3_cbc_digest_record( + mac_ctx, + md, &md_size, + header, rec->input, + rec->length + md_size, rec->orig_len, + ssl->s3->read_mac_secret, + ssl->s3->read_mac_secret_size, + 0 /* not SSLv3 */); + } + else + { + EVP_DigestSignUpdate(mac_ctx,header,sizeof(header)); + EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); + t=EVP_DigestSignFinal(mac_ctx,md,&md_size); + OPENSSL_assert(t > 0); +#ifdef OPENSSL_FIPS + if (!send && !SSL_USE_ETM(ssl) && FIPS_mode()) + tls_fips_digest_extra( + ssl->enc_read_ctx, + mac_ctx, rec->input, + rec->length, rec->orig_len); +#endif + } - if (!stream_mac) EVP_MD_CTX_cleanup(&hmac); + if (!stream_mac) + EVP_MD_CTX_cleanup(&hmac); #ifdef TLS_DEBUG printf("sec="); {unsigned int z; for (z=0; zversion != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER) + if (!SSL_IS_DTLS(ssl)) { for (i=7; i>=0; i--) { @@ -998,6 +1098,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, const void *co = NULL, *so = NULL; int col = 0, sol = 0; + #ifdef KSSL_DEBUG printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len); #endif /* KSSL_DEBUG */ @@ -1014,7 +1115,7 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, } #endif - tls1_PRF(s->s3->tmp.new_cipher->algorithm2, + tls1_PRF(ssl_get_algorithm2(s), TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE, s->s3->client_random,SSL3_RANDOM_SIZE, co, col, @@ -1022,6 +1123,34 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, so, sol, p,len, s->session->master_key,buff,sizeof buff); +#ifdef SSL_DEBUG + fprintf(stderr, "Premaster Secret:\n"); + BIO_dump_fp(stderr, (char *)p, len); + fprintf(stderr, "Client Random:\n"); + BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE); + fprintf(stderr, "Server Random:\n"); + BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE); + fprintf(stderr, "Master Secret:\n"); + BIO_dump_fp(stderr, (char *)s->session->master_key, SSL3_MASTER_SECRET_SIZE); +#endif + +#ifdef OPENSSL_SSL_TRACE_CRYPTO + if (s->msg_callback) + { + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_PREMASTER, + p, len, s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_CLIENT_RANDOM, + s->s3->client_random, SSL3_RANDOM_SIZE, + s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_SERVER_RANDOM, + s->s3->server_random, SSL3_RANDOM_SIZE, + s, s->msg_callback_arg); + s->msg_callback(2, s->version, TLS1_RT_CRYPTO_MASTER, + s->session->master_key, + SSL3_MASTER_SECRET_SIZE, + s, s->msg_callback_arg); + } +#endif #ifdef KSSL_DEBUG printf ("tls1_generate_master_secret() complete\n"); @@ -1029,6 +1158,95 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, return(SSL3_MASTER_SECRET_SIZE); } +int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, const unsigned char *context, + size_t contextlen, int use_context) + { + unsigned char *buff; + unsigned char *val = NULL; + size_t vallen, currentvalpos; + int rv; + +#ifdef KSSL_DEBUG + printf ("tls1_export_keying_material(%p,%p,%d,%s,%d,%p,%d)\n", s, out, olen, label, llen, p, plen); +#endif /* KSSL_DEBUG */ + + buff = OPENSSL_malloc(olen); + if (buff == NULL) goto err2; + + /* construct PRF arguments + * we construct the PRF argument ourself rather than passing separate + * values into the TLS PRF to ensure that the concatenation of values + * does not create a prohibited label. + */ + vallen = llen + SSL3_RANDOM_SIZE * 2; + if (use_context) + { + vallen += 2 + contextlen; + } + + val = OPENSSL_malloc(vallen); + if (val == NULL) goto err2; + currentvalpos = 0; + memcpy(val + currentvalpos, (unsigned char *) label, llen); + currentvalpos += llen; + memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE); + currentvalpos += SSL3_RANDOM_SIZE; + memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE); + currentvalpos += SSL3_RANDOM_SIZE; + + if (use_context) + { + val[currentvalpos] = (contextlen >> 8) & 0xff; + currentvalpos++; + val[currentvalpos] = contextlen & 0xff; + currentvalpos++; + if ((contextlen > 0) || (context != NULL)) + { + memcpy(val + currentvalpos, context, contextlen); + } + } + + /* disallow prohibited labels + * note that SSL3_RANDOM_SIZE > max(prohibited label len) = + * 15, so size of val > max(prohibited label len) = 15 and the + * comparisons won't have buffer overflow + */ + if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST, + TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1; + if (memcmp(val, TLS_MD_SERVER_FINISH_CONST, + TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1; + if (memcmp(val, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1; + if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST, + TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1; + + rv = tls1_PRF(s->s3->tmp.new_cipher->algorithm2, + val, vallen, + NULL, 0, + NULL, 0, + NULL, 0, + NULL, 0, + s->session->master_key,s->session->master_key_length, + out,buff,olen); + +#ifdef KSSL_DEBUG + printf ("tls1_export_keying_material() complete\n"); +#endif /* KSSL_DEBUG */ + goto ret; +err1: + SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); + rv = 0; + goto ret; +err2: + SSLerr(SSL_F_TLS1_EXPORT_KEYING_MATERIAL, ERR_R_MALLOC_FAILURE); + rv = 0; +ret: + if (buff != NULL) OPENSSL_free(buff); + if (val != NULL) OPENSSL_free(val); + return(rv); + } + int tls1_alert_code(int code) { switch (code) @@ -1070,27 +1288,3 @@ int tls1_alert_code(int code) default: return(-1); } } - -int SSL_tls1_key_exporter(SSL *s, unsigned char *label, int label_len, - unsigned char *context, int context_len, - unsigned char *out, int olen) - { - unsigned char *tmp; - int rv; - - tmp = OPENSSL_malloc(olen); - - if (!tmp) - return 0; - - rv = tls1_PRF(s->s3->tmp.new_cipher->algorithm2, - label, label_len, - s->s3->client_random,SSL3_RANDOM_SIZE, - s->s3->server_random,SSL3_RANDOM_SIZE, - context, context_len, NULL, 0, - s->session->master_key, s->session->master_key_length, - out, tmp, olen); - - OPENSSL_free(tmp); - return rv; - }