ssl/*: remove SSL3_RECORD->orig_len to restore binary compatibility.
[openssl.git] / ssl / d1_pkt.c
index 4dc091a20ec8ca114454bdb2df8d10886ae98189..0ad8b5f5590e4936134e28135d4dede948ac8238 100644 (file)
@@ -179,7 +179,6 @@ static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
 static int dtls1_buffer_record(SSL *s, record_pqueue *q,
        unsigned char *priority);
 static int dtls1_process_record(SSL *s);
-static void dtls1_clear_timeouts(SSL *s);
 
 /* copy buffered record into SSL structure */
 static int
@@ -377,15 +376,11 @@ static int
 dtls1_process_record(SSL *s)
 {
        int i,al;
-       int clear=0;
        int enc_err;
        SSL_SESSION *sess;
        SSL3_RECORD *rr;
-       unsigned int mac_size;
+       unsigned int mac_size, orig_len;
        unsigned char md[EVP_MAX_MD_SIZE];
-       int decryption_failed_or_bad_record_mac = 0;
-       unsigned char *mac = NULL;
-
 
        rr= &(s->s3->rrec);
        sess = s->session;
@@ -415,14 +410,19 @@ dtls1_process_record(SSL *s)
 
        /* decrypt in place in 'rr->input' */
        rr->data=rr->input;
+       orig_len=rr->length;
 
        enc_err = s->method->ssl3_enc->enc(s,0);
-       if (enc_err <= 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)
                {
-               /* To minimize information leaked via timing, we will always
-                * perform all computations before discarding the message.
-                */
-               decryption_failed_or_bad_record_mac = 1;
+               /* For DTLS we simply ignore bad packets. */
+               rr->length = 0;
+               s->packet_length = 0;
+               goto err;
                }
 
 #ifdef TLS_DEBUG
@@ -432,45 +432,59 @@ printf("\n");
 #endif
 
        /* r->length is now the compressed data plus mac */
-       if (    (sess == NULL) ||
-               (s->enc_read_ctx == NULL) ||
-               (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 */
-               int t;
-               t=EVP_MD_CTX_size(s->read_hash);
-               OPENSSL_assert(t >= 0);
-               mac_size=t;
-
-               if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
+               /* 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);
+
+               /* 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 (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 &&
+                    orig_len < mac_size+1))
                        {
-#if 0 /* OK only for stream ciphers (then rr->length is visible from ciphertext anyway) */
-                       al=SSL_AD_RECORD_OVERFLOW;
-                       SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG);
+                       al=SSL_AD_DECODE_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_LENGTH_TOO_SHORT);
                        goto f_err;
-#else
-                       decryption_failed_or_bad_record_mac = 1;
-#endif                 
                        }
-               /* check the MAC for rr->input (it's in mac_size bytes at the tail) */
-               if (rr->length >= mac_size)
+
+               if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE)
                        {
+                       /* We update the length so that the TLS header bytes
+                        * can be constructed correctly but we need to extract
+                        * the MAC in constant time from within the record,
+                        * without leaking the contents of the padding bytes.
+                        * */
+                       mac = mac_tmp;
+                       ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len);
                        rr->length -= mac_size;
-                       mac = &rr->data[rr->length];
                        }
                else
-                       rr->length = 0;
-               i=s->method->ssl3_enc->mac(s,md,0);
-               if (i < 0 || mac == NULL || memcmp(md, mac, mac_size) != 0)
                        {
-                       decryption_failed_or_bad_record_mac = 1;
+                       /* 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;
+                       mac = &rr->data[rr->length];
                        }
+
+               i=s->method->ssl3_enc->mac(s,md,0 /* not send */);
+               if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
+                       enc_err = -1;
+               if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+mac_size)
+                       enc_err = -1;
                }
 
-       if (decryption_failed_or_bad_record_mac)
+       if (enc_err < 0)
                {
                /* decryption failed, silently discard message */
                rr->length = 0;
@@ -698,7 +712,6 @@ again:
                goto again;   /* get another record */
                }
 
-       dtls1_clear_timeouts(s);  /* done waiting */
        return(1);
 
        }
@@ -1250,6 +1263,9 @@ start:
                 */
                if (msg_hdr.type == SSL3_MT_FINISHED)
                        {
+                       if (dtls1_check_timeout_num(s) < 0)
+                               return -1;
+
                        dtls1_retransmit_buffered_messages(s);
                        rr->length = 0;
                        goto start;
@@ -1873,10 +1889,3 @@ dtls1_reset_seq_numbers(SSL *s, int rw)
 
        memset(seq, 0x00, seq_bytes);
        }
-
-
-static void
-dtls1_clear_timeouts(SSL *s)
-       {
-       memset(&(s->d1->timeout), 0x00, sizeof(struct dtls1_timeout_st));
-       }