Create a dlts_write_records() function
[openssl.git] / ssl / record / rec_layer_d1.c
index 1d857bead5714097f074e470431caf293cca7c86..d1563ea43c2ec85cf0380f58f3ae319e599a3068 100644 (file)
@@ -713,45 +713,18 @@ static int ssl3_write_pending(SSL_CONNECTION *s, int type,
     }
 }
 
-int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
-                   size_t len, size_t *written)
+static int dtls_write_records(SSL_CONNECTION *sc, OSSL_RECORD_TEMPLATE *tmpl,
+                              size_t numtmpl)
 {
     unsigned char *p, *pseq;
-    int i, mac_size, clear = 0;
-    size_t prefix_len = 0;
+    int mac_size, clear = 0;
+    size_t prefix_len = 0, written;
     int eivlen;
     SSL3_RECORD wr;
-    SSL3_BUFFER *wb;
+    SSL3_BUFFER *wb = sc->rlayer.wbuf;
     SSL_SESSION *sess;
     SSL *s = SSL_CONNECTION_GET_SSL(sc);
 
-    wb = &sc->rlayer.wbuf[0];
-
-    /*
-     * DTLS writes whole datagrams, so there can't be anything left in
-     * the buffer.
-     */
-    if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) {
-        SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
-
-    /* If we have an alert to send, lets send it */
-    if (sc->s3.alert_dispatch) {
-        i = s->method->ssl_dispatch_alert(s);
-        if (i <= 0)
-            return i;
-        /* if it went, fall through and send more stuff */
-    }
-
-    if (len == 0)
-        return 0;
-
-    if (len > ssl_get_max_send_fragment(sc)) {
-        SSLfatal(sc, SSL_AD_INTERNAL_ERROR, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
-        return 0;
-    }
-
     sess = sc->session;
 
     if ((sess == NULL)
@@ -774,21 +747,10 @@ int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
 
     /* write the header */
 
-    *(p++) = type & 0xff;
-    SSL3_RECORD_set_type(&wr, type);
-    /*
-     * Special case: for hello verify request, client version 1.0 and we
-     * haven't decided which version to use yet send back using version 1.0
-     * header: otherwise some clients will ignore it.
-     */
-    if (s->method->version == DTLS_ANY_VERSION &&
-        sc->max_proto_version != DTLS1_BAD_VER) {
-        *(p++) = DTLS1_VERSION >> 8;
-        *(p++) = DTLS1_VERSION & 0xff;
-    } else {
-        *(p++) = sc->version >> 8;
-        *(p++) = sc->version & 0xff;
-    }
+    *(p++) = tmpl->type & 0xff;
+    SSL3_RECORD_set_type(&wr, tmpl->type);
+    *(p++) = tmpl->version >> 8;
+    *(p++) = tmpl->version & 0xff;
 
     /* field where we are to write out packet epoch, seq num and len */
     pseq = p;
@@ -818,8 +780,8 @@ int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
 
     /* lets setup the record stuff. */
     SSL3_RECORD_set_data(&wr, p + eivlen); /* make room for IV in case of CBC */
-    SSL3_RECORD_set_length(&wr, len);
-    SSL3_RECORD_set_input(&wr, (unsigned char *)buf);
+    SSL3_RECORD_set_length(&wr, tmpl->buflen);
+    SSL3_RECORD_set_input(&wr, (unsigned char *)tmpl->buf);
 
     /*
      * we now 'read' from wr.input, wr.length bytes into wr.data
@@ -894,7 +856,7 @@ int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
      * we should now have wr.data pointing to the encrypted data, which is
      * wr->length long
      */
-    SSL3_RECORD_set_type(&wr, type); /* not needed but helps for debugging */
+    SSL3_RECORD_set_type(&wr, tmpl->type); /* not needed but helps for debugging */
     SSL3_RECORD_add_length(&wr, DTLS1_RT_HEADER_LENGTH);
 
     ssl3_record_sequence_update(&(sc->rlayer.write_sequence[0]));
@@ -907,13 +869,72 @@ int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
      * memorize arguments so that ssl3_write_pending can detect bad write
      * retries later
      */
-    sc->rlayer.wpend_tot = len;
-    sc->rlayer.wpend_buf = buf;
-    sc->rlayer.wpend_type = type;
-    sc->rlayer.wpend_ret = len;
+    sc->rlayer.wpend_tot = tmpl->buflen;
+    sc->rlayer.wpend_buf = tmpl->buf;
+    sc->rlayer.wpend_type = tmpl->type;
+    sc->rlayer.wpend_ret = tmpl->buflen;
 
     /* we now just need to write the buffer. Calls SSLfatal() as required. */
-    return ssl3_write_pending(sc, type, buf, len, written);
+    return ssl3_write_pending(sc, tmpl->type, tmpl->buf, tmpl->buflen, &written);
+}
+
+int do_dtls1_write(SSL_CONNECTION *sc, int type, const unsigned char *buf,
+                   size_t len, size_t *written)
+{
+    int i;
+    OSSL_RECORD_TEMPLATE tmpl;
+    SSL *s = SSL_CONNECTION_GET_SSL(sc);
+    SSL3_BUFFER *wb;
+    int ret;
+
+    wb = &sc->rlayer.wbuf[0];
+
+    /*
+     * DTLS writes whole datagrams, so there can't be anything left in
+     * the buffer.
+     */
+    /* TODO(RECLAYER): Remove me */
+    if (!ossl_assert(SSL3_BUFFER_get_left(wb) == 0)) {
+        SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    /* If we have an alert to send, lets send it */
+    if (sc->s3.alert_dispatch) {
+        i = s->method->ssl_dispatch_alert(s);
+        if (i <= 0)
+            return i;
+        /* if it went, fall through and send more stuff */
+    }
+
+    if (len == 0)
+        return 0;
+
+    if (len > ssl_get_max_send_fragment(sc)) {
+        SSLfatal(sc, SSL_AD_INTERNAL_ERROR, SSL_R_EXCEEDS_MAX_FRAGMENT_SIZE);
+        return 0;
+    }
+
+    tmpl.type = type;
+    /*
+     * Special case: for hello verify request, client version 1.0 and we
+     * haven't decided which version to use yet send back using version 1.0
+     * header: otherwise some clients will ignore it.
+     */
+    if (s->method->version == DTLS_ANY_VERSION
+            && sc->max_proto_version != DTLS1_BAD_VER)
+        tmpl.version = DTLS1_VERSION;
+    else
+        tmpl.version = sc->version;
+    tmpl.buf = buf;
+    tmpl.buflen = len;
+
+    ret = dtls_write_records(sc, &tmpl, 1);
+
+    if (ret > 0)
+        *written = (int)len;
+
+    return ret;
 }
 
 void dtls1_reset_seq_numbers(SSL_CONNECTION *s, int rw)