typo
[openssl.git] / ssl / s3_enc.c
index 0ddfe19..f1b2641 100644 (file)
@@ -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);
        }
@@ -713,7 +730,7 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
        EVP_MD_CTX md_ctx;
        const EVP_MD_CTX *hash;
        unsigned char *p,rec_char;
-       unsigned int md_size;
+       size_t md_size;
        int npad;
        int t;
 
@@ -738,28 +755,68 @@ int n_ssl3_mac(SSL *ssl, unsigned char *md, int send)
        md_size=t;
        npad=(48/md_size)*md_size;
 
-       /* 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);
-
-       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);
@@ -794,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++)
@@ -815,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);
        }