Skip to content

Commit

Permalink
Transfer the functionality from ssl3_read_n to the new record layer
Browse files Browse the repository at this point in the history
This transfers the low level function ssl3_read_n to the new record layer.
We temporarily make the read_n function a top level record layer function.
Eventually, in later commits in this refactor, we will remove it as a top
level function and it will just be called from read_record.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #18132)
  • Loading branch information
mattcaswell committed Aug 18, 2022
1 parent 0c974fc commit e2d5742
Show file tree
Hide file tree
Showing 17 changed files with 660 additions and 254 deletions.
2 changes: 2 additions & 0 deletions crypto/err/openssl.txt
Expand Up @@ -1351,6 +1351,7 @@ SSL_R_EXCESSIVE_MESSAGE_SIZE:152:excessive message size
SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received
SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message
SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch
SSL_R_FAILED_TO_GET_PARAMETER:316:failed to get parameter
SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async
SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello
SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs
Expand Down Expand Up @@ -1457,6 +1458,7 @@ SSL_R_PSK_NO_CLIENT_CB:224:psk no client cb
SSL_R_PSK_NO_SERVER_CB:225:psk no server cb
SSL_R_READ_BIO_NOT_SET:211:read bio not set
SSL_R_READ_TIMEOUT_EXPIRED:312:read timeout expired
SSL_R_RECORD_LAYER_FAILURE:313:record layer failure
SSL_R_RECORD_LENGTH_MISMATCH:213:record length mismatch
SSL_R_RECORD_TOO_SMALL:298:record too small
SSL_R_RENEGOTIATE_EXT_TOO_LONG:335:renegotiate ext too long
Expand Down
7 changes: 7 additions & 0 deletions include/openssl/core_names.h
Expand Up @@ -555,6 +555,13 @@ extern "C" {
/* OSSL_DECODER input type if a decoder is used by the store */
#define OSSL_STORE_PARAM_INPUT_TYPE "input-type" /* UTF8_STRING */


/* Libssl record layer */

#define OSSL_LIBSSL_RECORD_LAYER_PARAM_OPTIONS "options"
#define OSSL_LIBSSL_RECORD_LAYER_PARAM_MODE "mode"
#define OSSL_LIBSSL_RECORD_LAYER_PARAM_READ_AHEAD "read_ahead"

# ifdef __cplusplus
}
# endif
Expand Down
4 changes: 3 additions & 1 deletion include/openssl/sslerr.h
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
Expand Down Expand Up @@ -119,6 +119,7 @@
# define SSL_R_EXTENSION_NOT_RECEIVED 279
# define SSL_R_EXTRA_DATA_IN_MESSAGE 153
# define SSL_R_EXT_LENGTH_MISMATCH 163
# define SSL_R_FAILED_TO_GET_PARAMETER 316
# define SSL_R_FAILED_TO_INIT_ASYNC 405
# define SSL_R_FRAGMENTED_CLIENT_HELLO 401
# define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154
Expand Down Expand Up @@ -222,6 +223,7 @@
# define SSL_R_PSK_NO_SERVER_CB 225
# define SSL_R_READ_BIO_NOT_SET 211
# define SSL_R_READ_TIMEOUT_EXPIRED 312
# define SSL_R_RECORD_LAYER_FAILURE 313
# define SSL_R_RECORD_LENGTH_MISMATCH 213
# define SSL_R_RECORD_TOO_SMALL 298
# define SSL_R_RENEGOTIATE_EXT_TOO_LONG 335
Expand Down
4 changes: 2 additions & 2 deletions ssl/d1_lib.c
Expand Up @@ -490,13 +490,13 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client)
/* ERR_raise() already called */
return -1;
}
buf = RECORD_LAYER_get_rbuf(&s->rlayer)->buf;
buf = s->rrlmethod->get0_rbuf(s->rrl)->buf;
wbuf = RECORD_LAYER_get_wbuf(&s->rlayer)[0].buf;
#if defined(SSL3_ALIGN_PAYLOAD)
# if SSL3_ALIGN_PAYLOAD != 0
/*
* Using SSL3_RT_HEADER_LENGTH here instead of DTLS1_RT_HEADER_LENGTH for
* consistency with ssl3_read_n. In practice it should make no difference
* consistency with read_n. In practice it should make no difference
* for sensible values of SSL3_ALIGN_PAYLOAD because the difference between
* SSL3_RT_HEADER_LENGTH and DTLS1_RT_HEADER_LENGTH is exactly 8
*/
Expand Down
2 changes: 1 addition & 1 deletion ssl/ktls.c
Expand Up @@ -20,7 +20,7 @@
*/
static int count_unprocessed_records(SSL_CONNECTION *s)
{
SSL3_BUFFER *rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
SSL3_BUFFER *rbuf = s->rrlmethod->get0_rbuf(s->rrl);
PACKET pkt, subpkt;
int count = 0;

Expand Down
28 changes: 13 additions & 15 deletions ssl/record/rec_layer_d1.c
Expand Up @@ -130,11 +130,10 @@ static int dtls1_copy_record(SSL_CONNECTION *s, pitem *item)

rdata = (DTLS1_RECORD_DATA *)item->data;

SSL3_BUFFER_release(&s->rlayer.rbuf);
SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));

s->rlayer.packet = rdata->packet;
s->rlayer.packet_length = rdata->packet_length;
memcpy(&s->rlayer.rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
s->rrlmethod->set0_packet(s->rrl, rdata->packet, rdata->packet_length);
memcpy(s->rrlmethod->get0_rbuf(s->rrl), &(rdata->rbuf), sizeof(SSL3_BUFFER));
memcpy(&s->rlayer.rrec, &(rdata->rrec), sizeof(SSL3_RECORD));

/* Set proper sequence number for mac calculation */
Expand Down Expand Up @@ -165,9 +164,9 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
return -1;
}

rdata->packet = s->rlayer.packet;
rdata->packet_length = s->rlayer.packet_length;
memcpy(&(rdata->rbuf), &s->rlayer.rbuf, sizeof(SSL3_BUFFER));
rdata->packet = s->rrlmethod->get0_packet(s->rrl);
rdata->packet_length = s->rrlmethod->get_packet_length(s->rrl);
memcpy(&(rdata->rbuf), s->rrlmethod->get0_rbuf(s->rrl), sizeof(SSL3_BUFFER));
memcpy(&(rdata->rrec), &s->rlayer.rrec, sizeof(SSL3_RECORD));

item->data = rdata;
Expand All @@ -182,9 +181,8 @@ int dtls1_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
}
#endif

s->rlayer.packet = NULL;
s->rlayer.packet_length = 0;
memset(&s->rlayer.rbuf, 0, sizeof(s->rlayer.rbuf));
s->rrlmethod->set0_packet(s->rrl, NULL, 0);
memset(s->rrlmethod->get0_rbuf(s->rrl), 0, sizeof(SSL3_BUFFER));
memset(&s->rlayer.rrec, 0, sizeof(s->rlayer.rrec));

if (!ssl3_setup_buffers(s)) {
Expand Down Expand Up @@ -247,7 +245,7 @@ int dtls1_process_buffered_records(SSL_CONNECTION *s)

rr = RECORD_LAYER_get_rrec(&s->rlayer);

rb = RECORD_LAYER_get_rbuf(&s->rlayer);
rb = s->rrlmethod->get0_rbuf(s->rrl);

if (SSL3_BUFFER_get_left(rb) > 0) {
/*
Expand Down Expand Up @@ -293,7 +291,7 @@ int dtls1_process_buffered_records(SSL_CONNECTION *s)
}
/* dump this record */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
s->rrlmethod->reset_packet_length(s->rrl);
continue;
}

Expand Down Expand Up @@ -356,7 +354,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
if (sc == NULL)
return -1;

if (!SSL3_BUFFER_is_initialised(&sc->rlayer.rbuf)) {
if (!SSL3_BUFFER_is_initialised(sc->rrlmethod->get0_rbuf(sc->rrl))) {
/* Not initialized yet */
if (!ssl3_setup_buffers(sc)) {
/* SSLfatal() already called */
Expand Down Expand Up @@ -689,7 +687,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
if (!(sc->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(&sc->rlayer.rbuf) == 0) {
if (SSL3_BUFFER_get_left(sc->rrlmethod->get0_rbuf(sc->rrl)) == 0) {
/* no read-ahead left? */
BIO *bio;

Expand Down Expand Up @@ -725,7 +723,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
return -1;

if (!(sc->mode & SSL_MODE_AUTO_RETRY)) {
if (SSL3_BUFFER_get_left(&sc->rlayer.rbuf) == 0) {
if (SSL3_BUFFER_get_left(sc->rrlmethod->get0_rbuf(sc->rrl)) == 0) {
/* no read-ahead left? */
BIO *bio;
/*
Expand Down
185 changes: 2 additions & 183 deletions ssl/record/rec_layer_s3.c
Expand Up @@ -152,8 +152,7 @@ void SSL_set_default_read_buffer_len(SSL *s, size_t len)

if (sc == NULL)
return;

SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&sc->rlayer), len);
SSL3_BUFFER_set_default_len(sc->rrlmethod->get0_rbuf(sc->rrl), len);
}

const char *SSL_rstate_string_long(const SSL *s)
Expand Down Expand Up @@ -194,186 +193,6 @@ const char *SSL_rstate_string(const SSL *s)
}
}

/*
* Return values are as per SSL_read()
*/
int ssl3_read_n(SSL_CONNECTION *s, size_t n, size_t max, int extend,
int clearold, size_t *readbytes)
{
/*
* If extend == 0, obtain new n-byte packet; if extend == 1, increase
* packet by another n bytes. The packet will be in the sub-array of
* s->rlayer.rbuf.buf specified by s->rlayer.packet and
* s->rlayer.packet_length. (If s->rlayer.read_ahead is set, 'max' bytes may
* be stored in rbuf [plus s->rlayer.packet_length bytes if extend == 1].)
* if clearold == 1, move the packet to the start of the buffer; if
* clearold == 0 then leave any old packets where they were
*/
size_t len, left, align = 0;
unsigned char *pkt;
SSL3_BUFFER *rb;

if (n == 0)
return 0;

rb = &s->rlayer.rbuf;
if (rb->buf == NULL)
if (!ssl3_setup_read_buffer(s)) {
/* SSLfatal() already called */
return -1;
}

left = rb->left;
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH;
align = SSL3_ALIGN_PAYLOAD - 1 - ((align - 1) % SSL3_ALIGN_PAYLOAD);
#endif

if (!extend) {
/* start with empty packet ... */
if (left == 0)
rb->offset = align;
else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) {
/*
* check if next packet length is large enough to justify payload
* alignment...
*/
pkt = rb->buf + rb->offset;
if (pkt[0] == SSL3_RT_APPLICATION_DATA
&& (pkt[3] << 8 | pkt[4]) >= 128) {
/*
* Note that even if packet is corrupted and its length field
* is insane, we can only be led to wrong decision about
* whether memmove will occur or not. Header values has no
* effect on memmove arguments and therefore no buffer
* overrun can be triggered.
*/
memmove(rb->buf + align, pkt, left);
rb->offset = align;
}
}
s->rlayer.packet = rb->buf + rb->offset;
s->rlayer.packet_length = 0;
/* ... now we can act as if 'extend' was set */
}

len = s->rlayer.packet_length;
pkt = rb->buf + align;
/*
* Move any available bytes to front of buffer: 'len' bytes already
* pointed to by 'packet', 'left' extra ones at the end
*/
if (s->rlayer.packet != pkt && clearold == 1) {
memmove(pkt, s->rlayer.packet, len + left);
s->rlayer.packet = pkt;
rb->offset = len + align;
}

/*
* For DTLS/UDP reads should not span multiple packets because the read
* operation returns the whole packet at once (as long as it fits into
* the buffer).
*/
if (SSL_CONNECTION_IS_DTLS(s)) {
if (left == 0 && extend)
return 0;
if (left > 0 && n > left)
n = left;
}

/* if there is enough in the buffer from a previous read, take some */
if (left >= n) {
s->rlayer.packet_length += n;
rb->left = left - n;
rb->offset += n;
*readbytes = n;
return 1;
}

/* else we need to read more data */

if (n > rb->len - rb->offset) {
/* does not happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}

/*
* Ktls always reads full records.
* Also, we always act like read_ahead is set for DTLS.
*/
if (!BIO_get_ktls_recv(s->rbio) && !s->rlayer.read_ahead
&& !SSL_CONNECTION_IS_DTLS(s)) {
/* ignore max parameter */
max = n;
} else {
if (max < n)
max = n;
if (max > rb->len - rb->offset)
max = rb->len - rb->offset;
}

while (left < n) {
size_t bioread = 0;
int ret;

/*
* Now we have len+left bytes at the front of s->s3.rbuf.buf and
* need to read in more until we have len+n (up to len+max if
* possible)
*/

clear_sys_error();
if (s->rbio != NULL) {
s->rwstate = SSL_READING;
ret = BIO_read(s->rbio, pkt + len + left, max - left);
if (ret >= 0)
bioread = ret;
if (ret <= 0
&& !BIO_should_retry(s->rbio)
&& BIO_eof(s->rbio)) {
if (s->options & SSL_OP_IGNORE_UNEXPECTED_EOF) {
SSL_set_shutdown(SSL_CONNECTION_GET_SSL(s),
SSL_RECEIVED_SHUTDOWN);
s->s3.warn_alert = SSL_AD_CLOSE_NOTIFY;
} else {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_UNEXPECTED_EOF_WHILE_READING);
}
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_READ_BIO_NOT_SET);
ret = -1;
}

if (ret <= 0) {
rb->left = left;
if ((s->mode & SSL_MODE_RELEASE_BUFFERS) != 0
&& !SSL_CONNECTION_IS_DTLS(s))
if (len + left == 0)
ssl3_release_read_buffer(s);
return ret;
}
left += bioread;
/*
* reads should *never* span multiple packets for DTLS because the
* underlying transport protocol is message oriented as opposed to
* byte oriented as in the TLS case.
*/
if (SSL_CONNECTION_IS_DTLS(s)) {
if (n > left)
n = left; /* makes the while condition false */
}
}

/* done reading, now the book-keeping */
rb->offset += n;
rb->left = left - n;
s->rlayer.packet_length += n;
s->rwstate = SSL_NOTHING;
*readbytes = n;
return 1;
}

/*
* Call this to write data in records of type 'type' It will return <= 0 if
Expand Down Expand Up @@ -1321,7 +1140,7 @@ int ssl3_read_bytes(SSL *ssl, int type, int *recvd_type, unsigned char *buf,

is_tls13 = SSL_CONNECTION_IS_TLS13(s);

rbuf = &s->rlayer.rbuf;
rbuf = s->rrlmethod->get0_rbuf(s->rrl);

if (!SSL3_BUFFER_is_initialised(rbuf)) {
/* Not initialized yet */
Expand Down
3 changes: 0 additions & 3 deletions ssl/record/record_local.h
Expand Up @@ -36,9 +36,6 @@
#define RECORD_LAYER_clear_first_record(rl) ((rl)->is_first_record = 0)
#define DTLS_RECORD_LAYER_get_r_epoch(rl) ((rl)->d->r_epoch)

__owur int ssl3_read_n(SSL_CONNECTION *s, size_t n, size_t max, int extend,
int clearold, size_t *readbytes);

DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
unsigned int *is_next_epoch);
int dtls1_process_buffered_records(SSL_CONNECTION *s);
Expand Down

0 comments on commit e2d5742

Please sign in to comment.