Remove some unneeded columns from dialog.
[oweals/openssl.git] / ssl / d1_pkt.c
index 892b8897088c0091eb73445f2dcb11619428b3ca..377696deac0bd2706464fe7a807169a9c5cfd399 100644 (file)
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/pqueue.h>
+#include <openssl/rand.h>
 
 static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
        int len, int peek);
@@ -197,7 +198,13 @@ dtls1_buffer_record(SSL *s, record_pqueue *queue, PQ_64BIT priority)
        memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER));
        memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD));
        
-       ssl3_setup_buffers(s);
+       if (!ssl3_setup_buffers(s))
+               {
+               SSLerr(SSL_F_DTLS1_BUFFER_RECORD, ERR_R_INTERNAL_ERROR);
+               OPENSSL_free(rdata);
+               pitem_free(item);
+               return(0);
+               }
        
        return(1);
     }
@@ -480,9 +487,9 @@ int dtls1_get_record(SSL *s)
        SSL3_RECORD *rr;
        SSL_SESSION *sess;
        unsigned char *p;
-       short version;
+       unsigned short version;
        DTLS1_BITMAP *bitmap;
-    unsigned int is_next_epoch;
+       unsigned int is_next_epoch;
 
        rr= &(s->s3->rrec);
        sess=s->session;
@@ -518,7 +525,7 @@ again:
                ssl_minor= *(p++);
                version=(ssl_major<<8)|ssl_minor;
 
-        /* sequence number is 64 bits, with top 2 bytes = epoch */ 
+               /* sequence number is 64 bits, with top 2 bytes = epoch */ 
                n2s(p,rr->epoch);
 
                memcpy(&(s->s3->read_sequence[2]), p, 6);
@@ -527,13 +534,9 @@ again:
                n2s(p,rr->length);
 
                /* Lets check version */
-               if (s->first_packet)
+               if (!s->first_packet)
                        {
-                       s->first_packet=0;
-                       }
-               else
-                       {
-                       if (version != s->version)
+                       if (version != s->version && version != DTLS1_BAD_VER)
                                {
                                SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
                                /* Send back error using their
@@ -544,7 +547,8 @@ again:
                                }
                        }
 
-               if ((version & 0xff00) != (DTLS1_VERSION & 0xff00))
+               if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
+                   (version & 0xff00) != (DTLS1_BAD_VER & 0xff00))
                        {
                        SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
                        goto err;
@@ -557,6 +561,7 @@ again:
                        goto f_err;
                        }
 
+               s->client_version = version;
                /* now s->rstate == SSL_ST_READ_BODY */
                }
 
@@ -790,8 +795,14 @@ start:
                        dest = s->d1->alert_fragment;
                        dest_len = &s->d1->alert_fragment_len;
                        }
-               else    /* else it's a CCS message */
-                       OPENSSL_assert(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC);
+                /* else it's a CCS message, or it's wrong */
+                else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
+                        {
+                          /* Not certain if this is the right error handling */
+                          al=SSL_AD_UNEXPECTED_MESSAGE;
+                          SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+                          goto f_err;
+                        }
 
 
                if (dest_maxlen > 0)
@@ -965,47 +976,40 @@ start:
                }
 
        if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
-        {
-        struct ccs_header_st ccs_hdr;
+               {
+               struct ccs_header_st ccs_hdr;
 
                dtls1_get_ccs_header(rr->data, &ccs_hdr);
 
-               if ( ccs_hdr.seq == s->d1->handshake_read_seq)
-                       {
-                       /* 'Change Cipher Spec' is just a single byte, so we know
-                        * exactly what the record payload has to look like */
-                       /* XDTLS: check that epoch is consistent */
-                       if (    (rr->length != DTLS1_CCS_HEADER_LENGTH) || 
-                               (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
-                               {
-                               i=SSL_AD_ILLEGAL_PARAMETER;
-                               SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
-                               goto err;
-                               }
-                       
-                       rr->length=0;
-                       
-                       if (s->msg_callback)
-                               s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
-                                       rr->data, 1, s, s->msg_callback_arg);
-                       
-                       s->s3->change_cipher_spec=1;
-                       if (!ssl3_do_change_cipher_spec(s))
-                               goto err;
-                       
-                       /* do this whenever CCS is processed */
-                       dtls1_reset_seq_numbers(s, SSL3_CC_READ);
-                       
-                       /* handshake read seq is reset upon handshake completion */
-                       s->d1->handshake_read_seq++;
-                       
-                       goto start;
-                       }
-               else
+               /* 'Change Cipher Spec' is just a single byte, so we know
+                * exactly what the record payload has to look like */
+               /* XDTLS: check that epoch is consistent */
+               if (    (s->client_version == DTLS1_BAD_VER && rr->length != 3) ||
+                       (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) || 
+                       (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
                        {
-                       rr->length = 0;
-                       goto start;
+                       i=SSL_AD_ILLEGAL_PARAMETER;
+                       SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
+                       goto err;
                        }
+
+               rr->length=0;
+
+               if (s->msg_callback)
+                       s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
+                               rr->data, 1, s, s->msg_callback_arg);
+
+               s->s3->change_cipher_spec=1;
+               if (!ssl3_do_change_cipher_spec(s))
+                       goto err;
+
+               /* do this whenever CCS is processed */
+               dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+               if (s->client_version == DTLS1_BAD_VER)
+                       s->d1->handshake_read_seq++;
+
+               goto start;
                }
 
        /* Unexpected handshake message (Client Hello, or protocol violation) */
@@ -1333,8 +1337,12 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
        *(p++)=type&0xff;
        wr->type=type;
 
-       *(p++)=(s->version>>8);
-       *(p++)=s->version&0xff;
+       if (s->client_version == DTLS1_BAD_VER)
+               *(p++) = DTLS1_BAD_VER>>8,
+               *(p++) = DTLS1_BAD_VER&0xff;
+       else
+               *(p++)=(s->version>>8),
+               *(p++)=s->version&0xff;
 
        /* field where we are to write out packet epoch, seq num and len */
        pseq=p; 
@@ -1389,8 +1397,14 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
 
 
        /* ssl3_enc can only have an error on read */
-       wr->length += bs;  /* bs != 0 in case of CBC.  The enc fn provides
-                                               * the randomness */ 
+       if (bs) /* bs != 0 in case of CBC */
+               {
+               RAND_pseudo_bytes(p,bs);
+               /* master IV and last CBC residue stand for
+                * the rest of randomness */
+               wr->length += bs;
+               }
+
        s->method->ssl3_enc->enc(s,1);
 
        /* record length after mac and block padding */