Create a dlts_write_records() function

In preparation for moving the DTLS code to use the new write record layer
architecture we first restructure the code to create a dtls_write_records()
function that mirrors the functionality that the record layer will provide.

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19424)
This commit is contained in:
Matt Caswell 2022-10-06 14:16:01 +01:00
parent 22d6e8547f
commit 88bf978eb1
1 changed files with 76 additions and 55 deletions

View 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)