X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_enc.c;h=f1b264185362599d990685c61b20429d806434ca;hp=00faadf8984ef0151b915f38e13fbf811f7d294c;hb=cb2182676bdf652070bc272a3896d957763a4324;hpb=220bd84911bd25518259f68568fd724309d71e62 diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c index 00faadf898..f1b2641853 100644 --- a/ssl/s3_enc.c +++ b/ssl/s3_enc.c @@ -170,6 +170,7 @@ static int ssl3_generate_key_block(SSL *s, unsigned char *km, int num) #endif k=0; EVP_MD_CTX_init(&m5); + EVP_MD_CTX_set_flags(&m5, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); EVP_MD_CTX_init(&s1); for (i=0; (int)is3->tmp.new_compression->method; #endif - key_block=s->s3->tmp.key_block; if (which & SSL3_CC_READ) { @@ -375,6 +375,27 @@ int ssl3_change_cipher_state(SSL *s, int which) EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE)); +#ifdef OPENSSL_SSL_TRACE_CRYPTO + if (s->msg_callback) + { + + int wh = which & SSL3_CC_WRITE ? + TLS1_RT_CRYPTO_WRITE : TLS1_RT_CRYPTO_READ; + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC, + mac_secret, EVP_MD_size(m), + 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) + { + s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_IV, + iv, k, s, s->msg_callback_arg); + } + } +#endif + OPENSSL_cleanse(&(exp_key[0]),sizeof(exp_key)); OPENSSL_cleanse(&(exp_iv[0]),sizeof(exp_iv)); EVP_MD_CTX_cleanup(&md); @@ -397,7 +418,7 @@ int ssl3_setup_key_block(SSL *s) if (s->s3->tmp.key_block_length != 0) return(1); - if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL,&comp)) + if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL,&comp, 0)) { SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE); return(0); @@ -466,12 +487,21 @@ void ssl3_cleanup_key_block(SSL *s) s->s3->tmp.key_block_length=0; } +/* ssl3_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 is invalid or, if sending, an internal error + * occurred. + */ int ssl3_enc(SSL *s, int send) { SSL3_RECORD *rec; EVP_CIPHER_CTX *ds; unsigned long l; - int bs,i; + int bs,i,mac_size=0; const EVP_CIPHER *enc; if (send) @@ -512,6 +542,9 @@ int ssl3_enc(SSL *s, int send) /* we need to add 'i-1' padding bytes */ l+=i; + /* the last of these zero bytes will be overwritten + * with the padding length. */ + memset(&rec->input[rec->length], 0, i); rec->length+=i; rec->input[l-1]=(i-1); } @@ -519,32 +552,16 @@ int ssl3_enc(SSL *s, int send) if (!send) { if (l == 0 || l%bs != 0) - { - SSLerr(SSL_F_SSL3_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED); return 0; - } /* otherwise, rec->length >= bs */ } EVP_Cipher(ds,rec->data,rec->input,l); + if (EVP_MD_CTX_md(s->read_hash) != NULL) + mac_size = EVP_MD_CTX_size(s->read_hash); if ((bs != 1) && !send) - { - i=rec->data[l-1]+1; - /* SSL 3.0 bounds the number of padding bytes by the block size; - * padding bytes (except the last one) are arbitrary */ - if (i > bs) - { - /* 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; - } - /* now i <= bs <= rec->length */ - rec->length-=i; - } + return ssl3_cbc_remove_padding(s, rec, bs, mac_size); } return(1); } @@ -569,12 +586,12 @@ void ssl3_free_digest_list(SSL *s) OPENSSL_free(s->s3->handshake_dgst); s->s3->handshake_dgst=NULL; } - + void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len) { - if (s->s3->handshake_buffer) + if (s->s3->handshake_buffer && !(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { BIO_write (s->s3->handshake_buffer,(void *)buf,len); } @@ -611,9 +628,16 @@ int ssl3_digest_cached_records(SSL *s) /* 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) + 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); } @@ -622,9 +646,12 @@ int ssl3_digest_cached_records(SSL *s) s->s3->handshake_dgst[i]=NULL; } } - /* Free handshake_buffer BIO */ - BIO_free(s->s3->handshake_buffer); - s->s3->handshake_buffer = 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; } @@ -655,7 +682,7 @@ static int ssl3_handshake_mac(SSL *s, int md_nid, if (!ssl3_digest_cached_records(s)) return 0; - /* Search for djgest of specified type in the handshake_dgst + /* Search for digest of specified type in the handshake_dgst * array*/ for (i=0;itype; - EVP_DigestUpdate(&md_ctx,&rec_char,1); - p=md; - s2n(rec->length,p); - EVP_DigestUpdate(&md_ctx,md,2); - EVP_DigestUpdate(&md_ctx,rec->input,rec->length); - EVP_DigestFinal_ex( &md_ctx,md,NULL); - - EVP_MD_CTX_copy_ex( &md_ctx,hash); - EVP_DigestUpdate(&md_ctx,mac_sec,md_size); - EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); - EVP_DigestUpdate(&md_ctx,md,md_size); - EVP_DigestFinal_ex( &md_ctx,md,&md_size); - - EVP_MD_CTX_cleanup(&md_ctx); + if (!send && + EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(hash)) + { + /* 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. */ + + /* npad is, at most, 48 bytes and that's with MD5: + * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. + * + * With SHA-1 (the largest hash speced for SSLv3) the hash size + * goes up 4, but npad goes down by 8, resulting in a smaller + * total size. */ + unsigned char header[75]; + unsigned j = 0; + memcpy(header+j, mac_sec, md_size); + j += md_size; + memcpy(header+j, ssl3_pad_1, npad); + j += npad; + memcpy(header+j, seq, 8); + j += 8; + header[j++] = rec->type; + header[j++] = rec->length >> 8; + header[j++] = rec->length & 0xff; + + ssl3_cbc_digest_record( + hash, + md, &md_size, + header, rec->input, + rec->length + md_size, rec->orig_len, + mac_sec, md_size, + 1 /* is SSLv3 */); + } + else + { + unsigned int md_size_u; + /* Chop the digest off the end :-) */ + EVP_MD_CTX_init(&md_ctx); + + EVP_MD_CTX_copy_ex( &md_ctx,hash); + EVP_DigestUpdate(&md_ctx,mac_sec,md_size); + EVP_DigestUpdate(&md_ctx,ssl3_pad_1,npad); + EVP_DigestUpdate(&md_ctx,seq,8); + rec_char=rec->type; + EVP_DigestUpdate(&md_ctx,&rec_char,1); + p=md; + s2n(rec->length,p); + EVP_DigestUpdate(&md_ctx,md,2); + EVP_DigestUpdate(&md_ctx,rec->input,rec->length); + EVP_DigestFinal_ex( &md_ctx,md,NULL); + + EVP_MD_CTX_copy_ex( &md_ctx,hash); + EVP_DigestUpdate(&md_ctx,mac_sec,md_size); + EVP_DigestUpdate(&md_ctx,ssl3_pad_2,npad); + EVP_DigestUpdate(&md_ctx,md,md_size); + EVP_DigestFinal_ex( &md_ctx,md,&md_size_u); + md_size = md_size_u; + + EVP_MD_CTX_cleanup(&md_ctx); + } ssl3_record_sequence_update(seq); return(md_size); @@ -783,6 +851,9 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, EVP_MD_CTX ctx; int i,ret=0; unsigned int n; +#ifdef OPENSSL_SSL_TRACE_CRYPTO + unsigned char *tmpout = out; +#endif EVP_MD_CTX_init(&ctx); for (i=0; i<3; i++) @@ -804,6 +875,23 @@ int ssl3_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, ret+=n; } EVP_MD_CTX_cleanup(&ctx); + +#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, + tmpout, SSL3_MASTER_SECRET_SIZE, + s, s->msg_callback_arg); + } +#endif return(ret); }