Merge branch 'OpenSSL_1_0_2-stable' into pre-aead
[oweals/openssl.git] / ssl / s3_pkt.c
index b2e5dc188231f4dac8ed5bb1e60a3bfc7cb94a3b..02a5f9df756c25968d1571d7df3e2bac827bb9bc 100644 (file)
@@ -180,7 +180,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
        /* For DTLS/UDP reads should not span multiple packets
         * because the read operation returns the whole packet
         * at once (as long as it fits into the buffer). */
-       if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+       if (SSL_IS_DTLS(s))
                {
                if (left > 0 && n > left)
                        n = left;
@@ -248,7 +248,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
                        {
                        rb->left = left;
                        if (s->mode & SSL_MODE_RELEASE_BUFFERS &&
-                           SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
+                               !SSL_IS_DTLS(s))
                                if (len+left == 0)
                                        ssl3_release_read_buffer(s);
                        return(i);
@@ -257,7 +257,7 @@ int ssl3_read_n(SSL *s, int n, int max, int extend)
                /* reads should *never* span multiple packets for DTLS because
                 * the underlying transport protocol is message oriented as opposed
                 * to byte oriented as in the TLS case. */
-               if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER)
+               if (SSL_IS_DTLS(s))
                        {
                        if (n > left)
                                n = left; /* makes the while condition false */
@@ -290,8 +290,7 @@ static int ssl3_get_record(SSL *s)
        unsigned char *p;
        unsigned char md[EVP_MAX_MD_SIZE];
        short version;
-       unsigned mac_size;
-       int clear=0;
+       unsigned mac_size, orig_len;
        size_t extra;
 
        rr= &(s->s3->rrec);
@@ -403,10 +402,15 @@ fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length);
        rr->data=rr->input;
 
        enc_err = s->method->ssl3_enc->enc(s,0);
+       /* enc_err is:
+        *    0: (in non-constant time) if the record is publically invalid.
+        *    1: if the padding is valid
+        *    -1: if the padding is invalid */
        if (enc_err == 0)
                {
-               /* SSLerr() and ssl3_send_alert() have been called */
-               goto err;
+               al=SSL_AD_DECRYPTION_FAILED;
+               SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
+               goto f_err;
                }
 
 #ifdef TLS_DEBUG
@@ -416,28 +420,28 @@ printf("\n");
 #endif
 
        /* r->length is now the compressed data plus mac */
-       if (    (sess == NULL) ||
-               (s->enc_read_ctx == NULL) ||
-               (EVP_MD_CTX_md(s->read_hash) == NULL))
-               clear=1;
-
-       if (!clear)
+       if ((sess != NULL) &&
+           (s->enc_read_ctx != NULL) &&
+           (EVP_MD_CTX_md(s->read_hash) != NULL))
                {
-               /* !clear => s->read_hash != NULL => mac_size != -1 */
+               /* s->read_hash != NULL => mac_size != -1 */
                unsigned char *mac = NULL;
                unsigned char mac_tmp[EVP_MAX_MD_SIZE];
                mac_size=EVP_MD_CTX_size(s->read_hash);
                OPENSSL_assert(mac_size <= EVP_MAX_MD_SIZE);
 
+               /* kludge: *_cbc_remove_padding passes padding length in rr->type */
+               orig_len = rr->length+((unsigned int)rr->type>>8);
+
                /* orig_len is the length of the record before any padding was
                 * removed. This is public information, as is the MAC in use,
                 * therefore we can safely process the record in a different
                 * amount of time if it's too short to possibly contain a MAC.
                 */
-               if (rr->orig_len < mac_size ||
+               if (orig_len < mac_size ||
                    /* CBC records must have a padding length byte too. */
                    (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
-                    rr->orig_len < mac_size+1))
+                    orig_len < mac_size+1))
                        {
                        al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
@@ -452,12 +456,12 @@ printf("\n");
                         * without leaking the contents of the padding bytes.
                         * */
                        mac = mac_tmp;
-                       ssl3_cbc_copy_mac(mac_tmp, rr, mac_size);
+                       ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
                        rr->length -= mac_size;
                        }
                else
                        {
-                       /* In this case there's no padding, so |rec->orig_len|
+                       /* In this case there's no padding, so |orig_len|
                         * equals |rec->length| and we checked that there's
                         * enough bytes for |mac_size| above. */
                        rr->length -= mac_size;
@@ -755,8 +759,8 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        /* field where we are to write out packet length */
        plen=p; 
        p+=2;
-       /* Explicit IV length, block ciphers and TLS version 1.1 or later */
-       if (s->enc_write_ctx && s->version >= TLS1_1_VERSION)
+       /* Explicit IV length, block ciphers appropriate version flag */
+       if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s))
                {
                int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
                if (mode == EVP_CIPH_CBC_MODE)
@@ -893,7 +897,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                        wb->left=0;
                        wb->offset+=i;
                        if (s->mode & SSL_MODE_RELEASE_BUFFERS &&
-                           SSL_version(s) != DTLS1_VERSION && SSL_version(s) != DTLS1_BAD_VER)
+                               !SSL_IS_DTLS(s))
                                ssl3_release_write_buffer(s);
                        s->rwstate=SSL_NOTHING;
                        return(s->s3->wpend_ret);