Changes from 1.0.0-stable.
[openssl.git] / ssl / s3_pkt.c
index 07dd4b23d5204b6840c2b01e4af48d449ebafe76..c04401a88dc424d860623d73d44ed7d7ccd47595 100644 (file)
@@ -272,7 +272,7 @@ static int ssl3_get_record(SSL *s)
        unsigned char *p;
        unsigned char md[EVP_MAX_MD_SIZE];
        short version;
-       unsigned int mac_size;
+       int mac_size;
        int clear=0;
        size_t extra;
        int decryption_failed_or_bad_record_mac = 0;
@@ -412,7 +412,9 @@ printf("\n");
 
        if (!clear)
                {
+               /* !clear => s->read_hash != NULL => mac_size != -1 */
                mac_size=EVP_MD_CTX_size(s->read_hash);
+               OPENSSL_assert(mac_size >= 0);
 
                if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size)
                        {
@@ -425,7 +427,7 @@ printf("\n");
 #endif                 
                        }
                /* check the MAC for rr->input (it's in mac_size bytes at the tail) */
-               if (rr->length >= mac_size)
+               if (rr->length >= (unsigned int)mac_size)
                        {
                        rr->length -= mac_size;
                        mac = &rr->data[rr->length];
@@ -443,7 +445,7 @@ printf("\n");
 #endif
                        }
                i=s->method->ssl3_enc->mac(s,md,0);
-               if (mac == NULL || memcmp(md, mac, mac_size) != 0)
+               if (i < 0 || mac == NULL || memcmp(md, mac, (size_t)mac_size) != 0)
                        {
                        decryption_failed_or_bad_record_mac = 1;
                        }
@@ -648,7 +650,11 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        if (clear)
                mac_size=0;
        else
+               {
                mac_size=EVP_MD_CTX_size(s->write_hash);
+               if (mac_size < 0)
+                       goto err;
+               }
 
        /* 'create_empty_fragment' is true only when this function calls itself */
        if (!clear && !create_empty_fragment && !s->s3->empty_fragment_done)
@@ -746,7 +752,8 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
 
        if (mac_size != 0)
                {
-               s->method->ssl3_enc->mac(s,&(p[wr->length]),1);
+               if (s->method->ssl3_enc->mac(s,&(p[wr->length]),1) < 0)
+                       goto err;
                wr->length+=mac_size;
                wr->input=p;
                wr->data=p;
@@ -828,8 +835,15 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
                        s->rwstate=SSL_NOTHING;
                        return(s->s3->wpend_ret);
                        }
-               else if (i <= 0)
+               else if (i <= 0) {
+                       if (s->version == DTLS1_VERSION) {
+                               /* For DTLS, just drop it. That's kind of the wh
+ole
+                                  point in using a datagram service */
+                               wb->left = 0;
+                       }
                        return(i);
+               }
                wb->offset+=i;
                wb->left-=i;
                }
@@ -1302,6 +1316,13 @@ int ssl3_do_change_cipher_spec(SSL *s)
 
        if (s->s3->tmp.key_block == NULL)
                {
+               if (s->session == NULL) 
+                       {
+                       /* might happen if dtls1_read_bytes() calls this */
+                       SSLerr(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC,SSL_R_CCS_RECEIVED_EARLY);
+                       return (0);
+                       }
+
                s->session->cipher=s->s3->tmp.new_cipher;
                if (!s->method->ssl3_enc->setup_key_block(s)) return(0);
                }
@@ -1329,13 +1350,13 @@ int ssl3_do_change_cipher_spec(SSL *s)
        return(1);
        }
 
-void ssl3_send_alert(SSL *s, int level, int desc)
+int ssl3_send_alert(SSL *s, int level, int desc)
        {
        /* Map tls/ssl alert value to correct one */
        desc=s->method->ssl3_enc->alert_value(desc);
        if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION)
                desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */
-       if (desc < 0) return;
+       if (desc < 0) return -1;
        /* If a fatal one, remove from cache */
        if ((level == 2) && (s->session != NULL))
                SSL_CTX_remove_session(s->ctx,s->session);
@@ -1344,9 +1365,10 @@ void ssl3_send_alert(SSL *s, int level, int desc)
        s->s3->send_alert[0]=level;
        s->s3->send_alert[1]=desc;
        if (s->s3->wbuf.left == 0) /* data still being written out? */
-               s->method->ssl_dispatch_alert(s);
+               return s->method->ssl_dispatch_alert(s);
        /* else data is still being written out, we will get written
         * some time in the future */
+       return -1;
        }
 
 int ssl3_dispatch_alert(SSL *s)