Move buffered_app_data from s->d1 to s->rlayer.d
[openssl.git] / ssl / record / d1_pkt.c
index 5ad46324544107fcdcb3cf38423b809d58d2daad..76bea7a29b42d7398dbb892b4acf5d6736e920ed 100644 (file)
 #include <openssl/pqueue.h>
 #include <openssl/rand.h>
 
-/* mod 128 saturating subtract of two 64-bit values in big-endian order */
-static int satsub64be(const unsigned char *v1, const unsigned char *v2)
+
+int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
 {
-    int ret, sat, brw, i;
-
-    if (sizeof(long) == 8)
-        do {
-            const union {
-                long one;
-                char little;
-            } is_endian = {
-                1
-            };
-            long l;
-
-            if (is_endian.little)
-                break;
-            /* not reached on little-endians */
-            /*
-             * following test is redundant, because input is always aligned,
-             * but I take no chances...
-             */
-            if (((size_t)v1 | (size_t)v2) & 0x7)
-                break;
-
-            l = *((long *)v1);
-            l -= *((long *)v2);
-            if (l > 128)
-                return 128;
-            else if (l < -128)
-                return -128;
-            else
-                return (int)l;
-        } while (0);
-
-    ret = (int)v1[7] - (int)v2[7];
-    sat = 0;
-    brw = ret >> 8;             /* brw is either 0 or -1 */
-    if (ret & 0x80) {
-        for (i = 6; i >= 0; i--) {
-            brw += (int)v1[i] - (int)v2[i];
-            sat |= ~brw;
-            brw >>= 8;
+    DTLS_RECORD_LAYER *d;
+    
+    if ((d = OPENSSL_malloc(sizeof *d)) == NULL) {
+        return (0);
+    }
+
+
+    rl->d = d;
+
+    d->unprocessed_rcds.q = pqueue_new();
+    d->processed_rcds.q = pqueue_new();
+    d->buffered_app_data.q = pqueue_new();
+
+    if (!d->unprocessed_rcds.q || !d->processed_rcds.q
+        || !d->buffered_app_data.q) {
+        if (d->unprocessed_rcds.q)
+            pqueue_free(d->unprocessed_rcds.q);
+        if (d->processed_rcds.q)
+            pqueue_free(d->processed_rcds.q);
+        if (d->buffered_app_data.q)
+            pqueue_free(d->buffered_app_data.q);
+        OPENSSL_free(d);
+        rl->d = NULL;
+        return (0);
+    }
+
+    return 1;
+}
+
+void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl)
+{
+    DTLS_RECORD_LAYER_clear(rl);
+    pqueue_free(rl->d->unprocessed_rcds.q);
+    pqueue_free(rl->d->processed_rcds.q);
+    pqueue_free(rl->d->buffered_app_data.q);
+    OPENSSL_free(rl->d);
+    rl->d = NULL;
+}
+
+void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl)
+{
+    DTLS_RECORD_LAYER *d;
+    pitem *item = NULL;
+    DTLS1_RECORD_DATA *rdata;
+    pqueue unprocessed_rcds;
+    pqueue processed_rcds;
+    pqueue buffered_app_data;
+
+    d = rl->d;
+    
+    while ((item = pqueue_pop(d->unprocessed_rcds.q)) != NULL) {
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        if (rdata->rbuf.buf) {
+            OPENSSL_free(rdata->rbuf.buf);
         }
-    } else {
-        for (i = 6; i >= 0; i--) {
-            brw += (int)v1[i] - (int)v2[i];
-            sat |= brw;
-            brw >>= 8;
+        OPENSSL_free(item->data);
+        pitem_free(item);
+    }
+
+    while ((item = pqueue_pop(d->processed_rcds.q)) != NULL) {
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        if (rdata->rbuf.buf) {
+            OPENSSL_free(rdata->rbuf.buf);
+        }
+        OPENSSL_free(item->data);
+        pitem_free(item);
+    }
+
+    while ((item = pqueue_pop(d->buffered_app_data.q)) != NULL) {
+        rdata = (DTLS1_RECORD_DATA *)item->data;
+        if (rdata->rbuf.buf) {
+            OPENSSL_free(rdata->rbuf.buf);
         }
+        OPENSSL_free(item->data);
+        pitem_free(item);
     }
-    brw <<= 8;                  /* brw is either 0 or -256 */
 
-    if (sat & 0xff)
-        return brw | 0x80;
-    else
-        return brw + (ret & 0xFF);
+    unprocessed_rcds = d->unprocessed_rcds.q;
+    processed_rcds = d->processed_rcds.q;
+    buffered_app_data = d->buffered_app_data.q;
+    memset(d, 0, sizeof *d);
+    d->unprocessed_rcds.q = unprocessed_rcds;
+    d->processed_rcds.q = processed_rcds;
+    d->buffered_app_data.q = buffered_app_data;
 }
 
 static int have_handshake_fragment(SSL *s, int type, unsigned char *buf,
@@ -199,7 +229,7 @@ static int dtls1_copy_record(SSL *s, pitem *item)
     memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));
 
     /* Set proper sequence number for mac calculation */
-    memcpy(&(s->s3->read_sequence[2]), &(rdata->packet[5]), 6);
+    memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
 
     return (1);
 }
@@ -293,25 +323,25 @@ int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
  */
 #define dtls1_get_unprocessed_record(s) \
                    dtls1_retrieve_buffered_record((s), \
-                   &((s)->d1->unprocessed_rcds))
+                   &((s)->rlayer.d->unprocessed_rcds))
 
 
 int dtls1_process_buffered_records(SSL *s)
 {
     pitem *item;
 
-    item = pqueue_peek(s->d1->unprocessed_rcds.q);
+    item = pqueue_peek(s->rlayer.d->unprocessed_rcds.q);
     if (item) {
         /* Check if epoch is current. */
-        if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
+        if (s->rlayer.d->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
             return (1);         /* Nothing to do. */
 
         /* Process all the records. */
-        while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
+        while (pqueue_peek(s->rlayer.d->unprocessed_rcds.q)) {
             dtls1_get_unprocessed_record(s);
             if (!dtls1_process_record(s))
                 return (0);
-            if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
+            if (dtls1_buffer_record(s, &(s->rlayer.d->processed_rcds),
                 SSL3_RECORD_get_seq_num(&s->rlayer.rrec)) < 0)
                 return -1;
         }
@@ -321,8 +351,8 @@ int dtls1_process_buffered_records(SSL *s)
      * sync epoch numbers once all the unprocessed records have been
      * processed
      */
-    s->d1->processed_rcds.epoch = s->d1->r_epoch;
-    s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
+    s->rlayer.d->processed_rcds.epoch = s->rlayer.d->r_epoch;
+    s->rlayer.d->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
 
     return (1);
 }
@@ -383,7 +413,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         return ret;
 
     /*
-     * Now s->d1->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE.
+     * Now s->rlayer.d->handshake_fragment_len == 0 if
+     * type == SSL3_RT_HANDSHAKE.
      */
 
 #ifndef OPENSSL_NO_SCTP
@@ -427,7 +458,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
      */
     if (s->state == SSL_ST_OK && rr->length == 0) {
         pitem *item;
-        item = pqueue_pop(s->d1->buffered_app_data.q);
+        item = pqueue_pop(s->rlayer.d->buffered_app_data.q);
         if (item) {
 #ifndef OPENSSL_NO_SCTP
             /* Restore bio_dgram_sctp_rcvinfo struct */
@@ -450,7 +481,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         goto start;
 
     /* get new packet if necessary */
-    if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) {
+    if ((rr->length == 0) || (s->rlayer.rstate == SSL_ST_READ_BODY)) {
         ret = dtls1_get_record(s);
         if (ret <= 0) {
             ret = dtls1_read_failed(s, ret);
@@ -477,8 +508,8 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
          * the packets were reordered on their way, so buffer the application
          * data for later processing rather than dropping the connection.
          */
-        if (dtls1_buffer_record(s, &(s->d1->buffered_app_data), rr->seq_num) <
-            0) {
+        if (dtls1_buffer_record(s, &(s->rlayer.d->buffered_app_data),
+            rr->seq_num) < 0) {
             SSLerr(SSL_F_DTLS1_READ_BYTES, ERR_R_INTERNAL_ERROR);
             return -1;
         }
@@ -522,7 +553,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             rr->length -= n;
             rr->off += n;
             if (rr->length == 0) {
-                s->rstate = SSL_ST_READ_HEADER;
+                s->rlayer.rstate = SSL_ST_READ_HEADER;
                 rr->off = 0;
             }
         }
@@ -570,13 +601,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         unsigned int *dest_len = NULL;
 
         if (rr->type == SSL3_RT_HANDSHAKE) {
-            dest_maxlen = sizeof s->d1->handshake_fragment;
-            dest = s->d1->handshake_fragment;
-            dest_len = &s->d1->handshake_fragment_len;
+            dest_maxlen = sizeof s->rlayer.d->handshake_fragment;
+            dest = s->rlayer.d->handshake_fragment;
+            dest_len = &s->rlayer.d->handshake_fragment_len;
         } else if (rr->type == SSL3_RT_ALERT) {
-            dest_maxlen = sizeof(s->d1->alert_fragment);
-            dest = s->d1->alert_fragment;
-            dest_len = &s->d1->alert_fragment_len;
+            dest_maxlen = sizeof(s->rlayer.d->alert_fragment);
+            dest = s->rlayer.d->alert_fragment;
+            dest_len = &s->rlayer.d->alert_fragment_len;
         }
 #ifndef OPENSSL_NO_HEARTBEATS
         else if (rr->type == TLS1_RT_HEARTBEAT) {
@@ -629,7 +660,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
                  */
                 FIX ME
 #endif
-                 s->rstate = SSL_ST_READ_HEADER;
+                 s->rlayer.rstate = SSL_ST_READ_HEADER;
                 rr->length = 0;
                 goto start;
             }
@@ -644,21 +675,21 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     }
 
     /*-
-     * s->d1->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
-     * s->d1->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
+     * s->rlayer.d->handshake_fragment_len == 12  iff  rr->type == SSL3_RT_HANDSHAKE;
+     * s->rlayer.d->alert_fragment_len == 7      iff  rr->type == SSL3_RT_ALERT.
      * (Possibly rr is 'empty' now, i.e. rr->length may be 0.)
      */
 
     /* If we are a client, check for an incoming 'Hello Request': */
     if ((!s->server) &&
-        (s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
-        (s->d1->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
+        (s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+        (s->rlayer.d->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
         (s->session != NULL) && (s->session->cipher != NULL)) {
-        s->d1->handshake_fragment_len = 0;
+        s->rlayer.d->handshake_fragment_len = 0;
 
-        if ((s->d1->handshake_fragment[1] != 0) ||
-            (s->d1->handshake_fragment[2] != 0) ||
-            (s->d1->handshake_fragment[3] != 0)) {
+        if ((s->rlayer.d->handshake_fragment[1] != 0) ||
+            (s->rlayer.d->handshake_fragment[2] != 0) ||
+            (s->rlayer.d->handshake_fragment[3] != 0)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
             goto err;
@@ -670,7 +701,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
 
         if (s->msg_callback)
             s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
-                            s->d1->handshake_fragment, 4, s,
+                            s->rlayer.d->handshake_fragment, 4, s,
                             s->msg_callback_arg);
 
         if (SSL_is_init_finished(s) &&
@@ -715,15 +746,16 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
         goto start;
     }
 
-    if (s->d1->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
-        int alert_level = s->d1->alert_fragment[0];
-        int alert_descr = s->d1->alert_fragment[1];
+    if (s->rlayer.d->alert_fragment_len >= DTLS1_AL_HEADER_LENGTH) {
+        int alert_level = s->rlayer.d->alert_fragment[0];
+        int alert_descr = s->rlayer.d->alert_fragment[1];
 
-        s->d1->alert_fragment_len = 0;
+        s->rlayer.d->alert_fragment_len = 0;
 
         if (s->msg_callback)
             s->msg_callback(0, s->version, SSL3_RT_ALERT,
-                            s->d1->alert_fragment, 2, s, s->msg_callback_arg);
+                            s->rlayer.d->alert_fragment, 2, s,
+                            s->msg_callback_arg);
 
         if (s->info_callback != NULL)
             cb = s->info_callback;
@@ -762,7 +794,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
             if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE) {
                 unsigned short seq;
                 unsigned int frag_off;
-                unsigned char *p = &(s->d1->alert_fragment[2]);
+                unsigned char *p = &(s->rlayer.d->alert_fragment[2]);
 
                 n2s(p, seq);
                 n2l3(p, frag_off);
@@ -874,13 +906,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
     /*
      * Unexpected handshake message (Client Hello, or protocol violation)
      */
-    if ((s->d1->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
+    if ((s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH) &&
         !s->in_handshake) {
         struct hm_header_st msg_hdr;
 
         /* this may just be a stale retransmit */
         dtls1_get_message_header(rr->data, &msg_hdr);
-        if (rr->epoch != s->d1->r_epoch) {
+        if (rr->epoch != s->rlayer.d->r_epoch) {
             rr->length = 0;
             goto start;
         }
@@ -997,24 +1029,25 @@ have_handshake_fragment(SSL *s, int type, unsigned char *buf,
                         int len, int peek)
 {
 
-    if ((type == SSL3_RT_HANDSHAKE) && (s->d1->handshake_fragment_len > 0))
+    if ((type == SSL3_RT_HANDSHAKE)
+            && (s->rlayer.d->handshake_fragment_len > 0))
         /* (partially) satisfy request from storage */
     {
-        unsigned char *src = s->d1->handshake_fragment;
+        unsigned char *src = s->rlayer.d->handshake_fragment;
         unsigned char *dst = buf;
         unsigned int k, n;
 
         /* peek == 0 */
         n = 0;
-        while ((len > 0) && (s->d1->handshake_fragment_len > 0)) {
+        while ((len > 0) && (s->rlayer.d->handshake_fragment_len > 0)) {
             *dst++ = *src++;
             len--;
-            s->d1->handshake_fragment_len--;
+            s->rlayer.d->handshake_fragment_len--;
             n++;
         }
         /* move any remaining fragment bytes: */
-        for (k = 0; k < s->d1->handshake_fragment_len; k++)
-            s->d1->handshake_fragment[k] = *src++;
+        for (k = 0; k < s->rlayer.d->handshake_fragment_len; k++)
+            s->rlayer.d->handshake_fragment[k] = *src++;
         return n;
     }
 
@@ -1172,14 +1205,14 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
 
     /* there's only one epoch between handshake and app data */
 
-    s2n(s->d1->w_epoch, pseq);
+    s2n(s->rlayer.d->w_epoch, pseq);
 
     /* XDTLS: ?? */
     /*
      * else s2n(s->d1->handshake_epoch, pseq);
      */
 
-    memcpy(pseq, &(s->s3->write_sequence[2]), 6);
+    memcpy(pseq, &(s->rlayer.write_sequence[2]), 6);
     pseq += 6;
     s2n(wr->length, pseq);
 
@@ -1194,7 +1227,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     wr->type = type;            /* not needed but helps for debugging */
     wr->length += DTLS1_RT_HEADER_LENGTH;
 
-    ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+    ssl3_record_sequence_update(&(s->rlayer.write_sequence[0]));
 
     if (create_empty_fragment) {
         /*
@@ -1212,10 +1245,10 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
      * memorize arguments so that ssl3_write_pending can detect bad write
      * retries later
      */
-    s->s3->wpend_tot = len;
-    s->s3->wpend_buf = buf;
-    s->s3->wpend_type = type;
-    s->s3->wpend_ret = len;
+    s->rlayer.wpend_tot = len;
+    s->rlayer.wpend_buf = buf;
+    s->rlayer.wpend_type = type;
+    s->rlayer.wpend_ret = len;
 
     /* we now just need to write the buffer */
     return ssl3_write_pending(s, type, buf, len);
@@ -1223,48 +1256,6 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
     return -1;
 }
 
-int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
-{
-    int cmp;
-    unsigned int shift;
-    const unsigned char *seq = s->s3->read_sequence;
-
-    cmp = satsub64be(seq, bitmap->max_seq_num);
-    if (cmp > 0) {
-        SSL3_RECORD_set_seq_num(&s->rlayer.rrec, seq);
-        return 1;               /* this record in new */
-    }
-    shift = -cmp;
-    if (shift >= sizeof(bitmap->map) * 8)
-        return 0;               /* stale, outside the window */
-    else if (bitmap->map & (1UL << shift))
-        return 0;               /* record previously received */
-
-    SSL3_RECORD_set_seq_num(&s->rlayer.rrec, seq);
-    return 1;
-}
-
-void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap)
-{
-    int cmp;
-    unsigned int shift;
-    const unsigned char *seq = s->s3->read_sequence;
-
-    cmp = satsub64be(seq, bitmap->max_seq_num);
-    if (cmp > 0) {
-        shift = cmp;
-        if (shift < sizeof(bitmap->map) * 8)
-            bitmap->map <<= shift, bitmap->map |= 1UL;
-        else
-            bitmap->map = 1UL;
-        memcpy(bitmap->max_seq_num, seq, 8);
-    } else {
-        shift = -cmp;
-        if (shift < sizeof(bitmap->map) * 8)
-            bitmap->map |= 1UL << shift;
-    }
-}
-
 DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
                                       unsigned int *is_next_epoch)
 {
@@ -1272,14 +1263,14 @@ DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
     *is_next_epoch = 0;
 
     /* In current epoch, accept HM, CCS, DATA, & ALERT */
-    if (rr->epoch == s->d1->r_epoch)
-        return &s->d1->bitmap;
+    if (rr->epoch == s->rlayer.d->r_epoch)
+        return &s->rlayer.d->bitmap;
 
     /* Only HM and ALERT messages can be from the next epoch */
-    else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
-             (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
+    else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
+            (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
         *is_next_epoch = 1;
-        return &s->d1->next_bitmap;
+        return &s->rlayer.d->next_bitmap;
     }
 
     return NULL;
@@ -1288,18 +1279,19 @@ DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
 void dtls1_reset_seq_numbers(SSL *s, int rw)
 {
     unsigned char *seq;
-    unsigned int seq_bytes = sizeof(s->s3->read_sequence);
+    unsigned int seq_bytes = sizeof(s->rlayer.read_sequence);
 
     if (rw & SSL3_CC_READ) {
-        seq = s->s3->read_sequence;
-        s->d1->r_epoch++;
-        memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
-        memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+        seq = s->rlayer.read_sequence;
+        s->rlayer.d->r_epoch++;
+        memcpy(&(s->rlayer.d->bitmap), &(s->rlayer.d->next_bitmap),
+            sizeof(DTLS1_BITMAP));
+        memset(&(s->rlayer.d->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
     } else {
-        seq = s->s3->write_sequence;
+        seq = s->rlayer.write_sequence;
         memcpy(s->d1->last_write_sequence, seq,
-               sizeof(s->s3->write_sequence));
-        s->d1->w_epoch++;
+               sizeof(s->rlayer.write_sequence));
+        s->rlayer.d->w_epoch++;
     }
 
     memset(seq, 0x00, seq_bytes);