mirror of
https://github.com/openssl/openssl.git
synced 2025-01-18 13:44:20 +08:00
Remove reliance on the SSL object from the DTLS read record layer code
Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/18132)
This commit is contained in:
parent
eddb067e2c
commit
222cf410d5
@ -849,7 +849,7 @@ int DTLSv1_listen(SSL *ssl, BIO_ADDR *client)
|
||||
|
||||
/* Buffer the record in the processed_rcds queue */
|
||||
/* TODO(RECLAYER): This is nasty and reaches inside the record layer. FIXME */
|
||||
if (!dtls_buffer_listen_record(s, reclen, seq, align))
|
||||
if (!dtls_buffer_listen_record(s->rrl, reclen, seq, align))
|
||||
return -1;
|
||||
|
||||
ret = 1;
|
||||
|
@ -36,12 +36,11 @@ static int satsub64be(const unsigned char *v1, const unsigned char *v2)
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
static int dtls1_record_replay_check(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
static int dtls1_record_replay_check(OSSL_RECORD_LAYER *rl, DTLS1_BITMAP *bitmap)
|
||||
{
|
||||
int cmp;
|
||||
unsigned int shift;
|
||||
const unsigned char *seq = s->rlayer.read_sequence;
|
||||
OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
|
||||
const unsigned char *seq = rl->sequence;
|
||||
|
||||
cmp = satsub64be(seq, bitmap->max_seq_num);
|
||||
if (cmp > 0) {
|
||||
@ -58,11 +57,12 @@ static int dtls1_record_replay_check(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void dtls1_record_bitmap_update(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
static void dtls1_record_bitmap_update(OSSL_RECORD_LAYER *rl,
|
||||
DTLS1_BITMAP *bitmap)
|
||||
{
|
||||
int cmp;
|
||||
unsigned int shift;
|
||||
const unsigned char *seq = RECORD_LAYER_get_read_sequence(&s->rlayer);
|
||||
const unsigned char *seq = rl->sequence;
|
||||
|
||||
cmp = satsub64be(seq, bitmap->max_seq_num);
|
||||
if (cmp > 0) {
|
||||
@ -79,14 +79,15 @@ static void dtls1_record_bitmap_update(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
}
|
||||
}
|
||||
|
||||
static DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
|
||||
static DTLS1_BITMAP *dtls1_get_bitmap(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rr,
|
||||
unsigned int *is_next_epoch)
|
||||
{
|
||||
OSSL_RECORD_LAYER *rl = s->rrl;
|
||||
SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
|
||||
|
||||
*is_next_epoch = 0;
|
||||
|
||||
/* In current epoch, accept HM, CCS, DATA, & ALERT */
|
||||
if (rr->epoch == s->rlayer.d->r_epoch)
|
||||
if (rr->epoch == rl->epoch)
|
||||
return &s->rlayer.d->bitmap;
|
||||
|
||||
/*
|
||||
@ -94,8 +95,8 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
|
||||
* have already processed all of the unprocessed records from the last
|
||||
* epoch
|
||||
*/
|
||||
else if (rr->epoch == (unsigned long)(s->rlayer.d->r_epoch + 1) &&
|
||||
rl->unprocessed_rcds.epoch != s->rlayer.d->r_epoch &&
|
||||
else if (rr->epoch == (unsigned long)(rl->epoch + 1) &&
|
||||
rl->unprocessed_rcds.epoch != rl->epoch &&
|
||||
(rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
|
||||
*is_next_epoch = 1;
|
||||
return &s->rlayer.d->next_bitmap;
|
||||
@ -104,32 +105,27 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL_CONNECTION *s, SSL3_RECORD *rr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
static int dtls1_process_record(OSSL_RECORD_LAYER *rl, DTLS1_BITMAP *bitmap)
|
||||
{
|
||||
int i;
|
||||
int enc_err;
|
||||
SSL_SESSION *sess;
|
||||
SSL3_RECORD *rr;
|
||||
int imac_size;
|
||||
size_t mac_size = 0;
|
||||
unsigned char md[EVP_MAX_MD_SIZE];
|
||||
size_t max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
|
||||
SSL_MAC_BUF macbuf = { NULL, 0 };
|
||||
int ret = 0;
|
||||
OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
|
||||
SSL *ssl = SSL_CONNECTION_GET_SSL(s);
|
||||
|
||||
rr = &rl->rrec[0];
|
||||
sess = s->session;
|
||||
|
||||
/*
|
||||
* At this point, s->rlayer.packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
|
||||
* and we have that many bytes in s->rlayer.packet
|
||||
* At this point, rl->packet_length == SSL3_RT_HEADER_LNGTH + rr->length,
|
||||
* and we have that many bytes in rl->packet
|
||||
*/
|
||||
rr->input = &(s->rrlmethod->get0_packet(s->rrl)[DTLS1_RT_HEADER_LENGTH]);
|
||||
rr->input = &(rl->packet[DTLS1_RT_HEADER_LENGTH]);
|
||||
|
||||
/*
|
||||
* ok, we can now read from 's->rlayer.packet' data into 'rr'. rr->input
|
||||
* ok, we can now read from 'rl->packet' data into 'rr'. rr->input
|
||||
* points at rr->length bytes, which need to be copied into rr->data by
|
||||
* either the decryption or by the decompression. When the data is 'copied'
|
||||
* into the rr->data buffer, rr->input will be pointed at the new buffer
|
||||
@ -142,7 +138,7 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
|
||||
/* check is not needed I believe */
|
||||
if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) {
|
||||
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
|
||||
RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -150,32 +146,32 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
rr->data = rr->input;
|
||||
rr->orig_len = rr->length;
|
||||
|
||||
if (s->read_hash != NULL) {
|
||||
const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
|
||||
if (rl->md_ctx != NULL) {
|
||||
const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(rl->md_ctx);
|
||||
|
||||
if (tmpmd != NULL) {
|
||||
imac_size = EVP_MD_get_size(tmpmd);
|
||||
if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
|
||||
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
|
||||
return 0;
|
||||
}
|
||||
mac_size = (size_t)imac_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_READ_ETM(s) && s->read_hash) {
|
||||
if (rl->use_etm && rl->md_ctx) {
|
||||
unsigned char *mac;
|
||||
|
||||
if (rr->orig_len < mac_size) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
|
||||
RLAYERfatal(rl, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
|
||||
return 0;
|
||||
}
|
||||
rr->length -= mac_size;
|
||||
mac = rr->data + rr->length;
|
||||
i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
|
||||
i = rl->funcs->mac(rl, rr, md, 0 /* not send */);
|
||||
if (i == 0 || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) {
|
||||
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
|
||||
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
|
||||
RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC,
|
||||
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
@ -191,7 +187,7 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
* errors in the queue from processing bogus junk that we ignored.
|
||||
*/
|
||||
ERR_set_mark();
|
||||
enc_err = ssl->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
|
||||
enc_err = rl->funcs->cipher(rl, rr, 1, 0, &macbuf, mac_size);
|
||||
|
||||
/*-
|
||||
* enc_err is:
|
||||
@ -201,13 +197,13 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
*/
|
||||
if (enc_err == 0) {
|
||||
ERR_pop_to_mark();
|
||||
if (ossl_statem_in_error(s)) {
|
||||
if (rl->alert != 0) {
|
||||
/* SSLfatal() got called */
|
||||
goto end;
|
||||
}
|
||||
/* For DTLS we simply ignore bad packets. */
|
||||
rr->length = 0;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto end;
|
||||
}
|
||||
ERR_clear_last_mark();
|
||||
@ -217,13 +213,12 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
} OSSL_TRACE_END(TLS);
|
||||
|
||||
/* r->length is now the compressed data plus mac */
|
||||
if ((sess != NULL)
|
||||
&& !SSL_READ_ETM(s)
|
||||
&& (s->enc_read_ctx != NULL)
|
||||
&& (EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
|
||||
/* s->read_hash != NULL => mac_size != -1 */
|
||||
if (!rl->use_etm
|
||||
&& (rl->enc_ctx != NULL)
|
||||
&& (EVP_MD_CTX_get0_md(rl->md_ctx) != NULL)) {
|
||||
/* rl->md_ctx != NULL => mac_size != -1 */
|
||||
|
||||
i = ssl->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
|
||||
i = rl->funcs->mac(rl, rr, md, 0 /* not send */ );
|
||||
if (i == 0 || macbuf.mac == NULL
|
||||
|| CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
|
||||
enc_err = 0;
|
||||
@ -234,33 +229,33 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
if (enc_err == 0) {
|
||||
/* decryption failed, silently discard message */
|
||||
rr->length = 0;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* r->length is now just compressed */
|
||||
if (s->expand != NULL) {
|
||||
if (rl->expand != NULL) {
|
||||
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
|
||||
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
|
||||
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
|
||||
RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW,
|
||||
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
|
||||
goto end;
|
||||
}
|
||||
if (!ssl3_do_uncompress(s, rr)) {
|
||||
SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
|
||||
if (!tls_do_uncompress(rl, rr)) {
|
||||
RLAYERfatal(rl, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* use current Max Fragment Length setting if applicable */
|
||||
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
|
||||
max_plain_length = GET_MAX_FRAGMENT_LENGTH(s->session);
|
||||
|
||||
/* send overflow if the plaintext is too long now it has passed MAC */
|
||||
if (rr->length > max_plain_length) {
|
||||
SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
|
||||
/*
|
||||
* Check if the received packet overflows the current Max Fragment
|
||||
* Length setting.
|
||||
*/
|
||||
if (rl->max_frag_len > 0 && rr->length > rl->max_frag_len) {
|
||||
RLAYERfatal(rl, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
rr->off = 0;
|
||||
/*-
|
||||
* So at this point the following is true
|
||||
@ -272,10 +267,10 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
*/
|
||||
|
||||
/* we have pulled in a full packet so zero things */
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
|
||||
/* Mark receipt of record. */
|
||||
dtls1_record_bitmap_update(s, bitmap);
|
||||
dtls1_record_bitmap_update(rl, bitmap);
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
@ -284,12 +279,11 @@ static int dtls1_process_record(SSL_CONNECTION *s, DTLS1_BITMAP *bitmap)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dtls_rlayer_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
|
||||
static int dtls_rlayer_buffer_record(OSSL_RECORD_LAYER *rl, record_pqueue *queue,
|
||||
unsigned char *priority)
|
||||
{
|
||||
DTLS_RLAYER_RECORD_DATA *rdata;
|
||||
pitem *item;
|
||||
OSSL_RECORD_LAYER *rl = (OSSL_RECORD_LAYER *)s->rrl;
|
||||
|
||||
/* Limit the size of the queue to prevent DOS attacks */
|
||||
if (pqueue_size(queue->q) >= 100)
|
||||
@ -300,22 +294,24 @@ static int dtls_rlayer_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
|
||||
if (rdata == NULL || item == NULL) {
|
||||
OPENSSL_free(rdata);
|
||||
pitem_free(item);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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));
|
||||
rdata->packet = rl->packet;
|
||||
rdata->packet_length = rl->packet_length;
|
||||
memcpy(&(rdata->rbuf), &rl->rbuf, sizeof(SSL3_BUFFER));
|
||||
memcpy(&(rdata->rrec), &rl->rrec[0], sizeof(SSL3_RECORD));
|
||||
|
||||
item->data = rdata;
|
||||
|
||||
s->rrlmethod->set0_packet(s->rrl, NULL, 0);
|
||||
memset(s->rrlmethod->get0_rbuf(s->rrl), 0, sizeof(SSL3_BUFFER));
|
||||
rl->packet = NULL;
|
||||
rl->packet_length = 0;
|
||||
memset(&rl->rbuf, 0, sizeof(SSL3_BUFFER));
|
||||
memset(&rl->rrec[0], 0, sizeof(rl->rrec[0]));
|
||||
|
||||
if (!ssl3_setup_buffers(s)) {
|
||||
|
||||
if (!rlayer_setup_read_buffer(rl)) {
|
||||
/* SSLfatal() already called */
|
||||
OPENSSL_free(rdata->rbuf.buf);
|
||||
OPENSSL_free(rdata);
|
||||
@ -337,18 +333,18 @@ static int dtls_rlayer_buffer_record(SSL_CONNECTION *s, record_pqueue *queue,
|
||||
static int dtls_copy_rlayer_record(OSSL_RECORD_LAYER *rl, pitem *item)
|
||||
{
|
||||
DTLS_RLAYER_RECORD_DATA *rdata;
|
||||
SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
|
||||
|
||||
rdata = (DTLS_RLAYER_RECORD_DATA *)item->data;
|
||||
|
||||
SSL3_BUFFER_release(s->rrlmethod->get0_rbuf(s->rrl));
|
||||
SSL3_BUFFER_release(&rl->rbuf);
|
||||
|
||||
s->rrlmethod->set0_packet(s->rrl, rdata->packet, rdata->packet_length);
|
||||
memcpy(s->rrlmethod->get0_rbuf(s->rrl), &(rdata->rbuf), sizeof(SSL3_BUFFER));
|
||||
rl->packet = rdata->packet;
|
||||
rl->packet_length = rdata->packet_length;
|
||||
memcpy(&rl->rbuf, &(rdata->rbuf), sizeof(SSL3_BUFFER));
|
||||
memcpy(&rl->rrec[0], &(rdata->rrec), sizeof(SSL3_RECORD));
|
||||
|
||||
/* Set proper sequence number for mac calculation */
|
||||
memcpy(&(s->rlayer.read_sequence[2]), &(rdata->packet[5]), 6);
|
||||
memcpy(&(rl->sequence[2]), &(rdata->packet[5]), 6);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -371,7 +367,7 @@ static int dtls_retrieve_rlayer_buffered_record(OSSL_RECORD_LAYER *rl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
|
||||
static int dtls_process_rlayer_buffered_records(OSSL_RECORD_LAYER *rl)
|
||||
{
|
||||
pitem *item;
|
||||
SSL3_BUFFER *rb;
|
||||
@ -379,17 +375,16 @@ static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
|
||||
DTLS1_BITMAP *bitmap;
|
||||
unsigned int is_next_epoch;
|
||||
int replayok = 1;
|
||||
OSSL_RECORD_LAYER *rl = s->rrl;
|
||||
|
||||
item = pqueue_peek(rl->unprocessed_rcds.q);
|
||||
if (item) {
|
||||
/* Check if epoch is current. */
|
||||
if (rl->unprocessed_rcds.epoch != s->rlayer.d->r_epoch)
|
||||
if (rl->unprocessed_rcds.epoch != rl->epoch)
|
||||
return 1; /* Nothing to do. */
|
||||
|
||||
rr = rl->rrec;
|
||||
|
||||
rb = s->rrlmethod->get0_rbuf(s->rrl);
|
||||
rb = &rl->rbuf;
|
||||
|
||||
if (SSL3_BUFFER_get_left(rb) > 0) {
|
||||
/*
|
||||
@ -404,19 +399,19 @@ static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
|
||||
/* Process all the records. */
|
||||
while (pqueue_peek(rl->unprocessed_rcds.q)) {
|
||||
dtls_retrieve_rlayer_buffered_record(rl, &(rl->unprocessed_rcds));
|
||||
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
|
||||
bitmap = dtls1_get_bitmap(rl, rr, &is_next_epoch);
|
||||
if (bitmap == NULL) {
|
||||
/*
|
||||
* Should not happen. This will only ever be NULL when the
|
||||
* current record is from a different epoch. But that cannot
|
||||
* be the case because we already checked the epoch above
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
/* Only do replay check if no SCTP bio */
|
||||
if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
|
||||
if (!BIO_dgram_is_sctp(rl->bio))
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
@ -425,21 +420,21 @@ static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
|
||||
* we might have updated the window since then due to
|
||||
* records we subsequently processed.
|
||||
*/
|
||||
replayok = dtls1_record_replay_check(s, bitmap);
|
||||
replayok = dtls1_record_replay_check(rl, bitmap);
|
||||
}
|
||||
|
||||
if (!replayok || !dtls1_process_record(s, bitmap)) {
|
||||
if (ossl_statem_in_error(s)) {
|
||||
/* dtls1_process_record called SSLfatal() */
|
||||
if (!replayok || !dtls1_process_record(rl, bitmap)) {
|
||||
if (rl->alert != 0) {
|
||||
/* dtls1_process_record called RLAYERfatal() */
|
||||
return 0;
|
||||
}
|
||||
/* dump this record */
|
||||
rr->length = 0;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dtls_rlayer_buffer_record(s, &(rl->processed_rcds),
|
||||
if (dtls_rlayer_buffer_record(rl, &(rl->processed_rcds),
|
||||
SSL3_RECORD_get_seq_num(&rl->rrec[0])) < 0) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
@ -451,16 +446,17 @@ static int dtls_process_rlayer_buffered_records(SSL_CONNECTION *s)
|
||||
* sync epoch numbers once all the unprocessed records have been
|
||||
* processed
|
||||
*/
|
||||
rl->processed_rcds.epoch = s->rlayer.d->r_epoch;
|
||||
rl->unprocessed_rcds.epoch = s->rlayer.d->r_epoch + 1;
|
||||
rl->processed_rcds.epoch = rl->epoch;
|
||||
rl->unprocessed_rcds.epoch = rl->epoch + 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq, size_t off)
|
||||
/* TODO(RECLAYER): FIXME. This is called directly from d1_lib.c. It should not be */
|
||||
int dtls_buffer_listen_record(OSSL_RECORD_LAYER *rl, size_t len,
|
||||
unsigned char *seq, size_t off)
|
||||
{
|
||||
SSL3_RECORD *rr;
|
||||
OSSL_RECORD_LAYER *rl = s->rrl;
|
||||
|
||||
rr = &rl->rrec[0];
|
||||
memset(rr, 0, sizeof(SSL3_RECORD));
|
||||
@ -470,11 +466,11 @@ int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
|
||||
memcpy(rr->seq_num, seq, sizeof(rr->seq_num));
|
||||
rr->off = off;
|
||||
|
||||
s->rrlmethod->set0_packet(s->rrl, s->rrlmethod->get0_rbuf(s->rrl)->buf,
|
||||
DTLS1_RT_HEADER_LENGTH + len);
|
||||
rr->data = s->rrlmethod->get0_packet(s->rrl) + DTLS1_RT_HEADER_LENGTH;
|
||||
rl->packet = rl->rbuf.buf;
|
||||
rl->packet_length = DTLS1_RT_HEADER_LENGTH + len;
|
||||
rr->data = rl->packet + DTLS1_RT_HEADER_LENGTH;
|
||||
|
||||
if (dtls_rlayer_buffer_record(s, &(rl->processed_rcds),
|
||||
if (dtls_rlayer_buffer_record(rl, &(rl->processed_rcds),
|
||||
SSL3_RECORD_get_seq_num(rr)) <= 0) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
@ -493,7 +489,7 @@ int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
|
||||
* ssl->s3.rrec.length - number of bytes
|
||||
*/
|
||||
/* used only by dtls1_read_bytes */
|
||||
static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
{
|
||||
int ssl_major, ssl_minor;
|
||||
int rret;
|
||||
@ -518,7 +514,7 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
* The epoch may have changed. If so, process all the pending records.
|
||||
* This is a non-blocking operation.
|
||||
*/
|
||||
if (!dtls_process_rlayer_buffered_records(s)) {
|
||||
if (!dtls_process_rlayer_buffered_records(rl)) {
|
||||
/* SSLfatal() already called */
|
||||
return OSSL_RECORD_RETURN_FATAL;
|
||||
}
|
||||
@ -532,11 +528,10 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
/* get something from the wire */
|
||||
|
||||
/* check if we have the header */
|
||||
if ((RECORD_LAYER_get_rstate(&s->rlayer) != SSL_ST_READ_BODY) ||
|
||||
(s->rrlmethod->get_packet_length(s->rrl) < DTLS1_RT_HEADER_LENGTH)) {
|
||||
rret = s->rrlmethod->read_n(s->rrl, DTLS1_RT_HEADER_LENGTH,
|
||||
SSL3_BUFFER_get_len(s->rrlmethod->get0_rbuf(s->rrl)),
|
||||
0, 1, &n);
|
||||
if ((rl->rstate != SSL_ST_READ_BODY) ||
|
||||
(rl->packet_length < DTLS1_RT_HEADER_LENGTH)) {
|
||||
rret = rl->funcs->read_n(rl, DTLS1_RT_HEADER_LENGTH,
|
||||
SSL3_BUFFER_get_len(&rl->rbuf), 0, 1, &n);
|
||||
/* read timeout is handled by dtls1_read_bytes */
|
||||
if (rret < OSSL_RECORD_RETURN_SUCCESS) {
|
||||
/* SSLfatal() already called if appropriate */
|
||||
@ -544,18 +539,17 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
}
|
||||
|
||||
/* this packet contained a partial record, dump it */
|
||||
if (s->rrlmethod->get_packet_length(s->rrl) != DTLS1_RT_HEADER_LENGTH) {
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
if (rl->packet_length != DTLS1_RT_HEADER_LENGTH) {
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY);
|
||||
rl->rstate = SSL_ST_READ_BODY;
|
||||
|
||||
p = s->rrlmethod->get0_packet(s->rrl);
|
||||
p = rl->packet;
|
||||
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
|
||||
ssl, s->msg_callback_arg);
|
||||
rl->msg_callback(0, 0, SSL3_RT_HEADER, p, DTLS1_RT_HEADER_LENGTH,
|
||||
rl->cbarg);
|
||||
|
||||
/* Pull apart the header into the DTLS1_RECORD */
|
||||
rr->type = *(p++);
|
||||
@ -566,7 +560,7 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
/* sequence number is 64 bits, with top 2 bytes = epoch */
|
||||
n2s(p, rr->epoch);
|
||||
|
||||
memcpy(&(RECORD_LAYER_get_read_sequence(&s->rlayer)[2]), p, 6);
|
||||
memcpy(&(rl->sequence[2]), p, 6);
|
||||
p += 6;
|
||||
|
||||
n2s(p, rr->length);
|
||||
@ -576,21 +570,24 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
* Lets check the version. We tolerate alerts that don't have the exact
|
||||
* version number (e.g. because of protocol version errors)
|
||||
*/
|
||||
if (!s->first_packet && rr->type != SSL3_RT_ALERT) {
|
||||
if (version != s->version) {
|
||||
if (!rl->is_first_record && rr->type != SSL3_RT_ALERT) {
|
||||
if (version != rl->version) {
|
||||
/* unexpected version, silently discard */
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
if ((version & 0xff00) != (s->version & 0xff00)) {
|
||||
|
||||
if (ssl_major !=
|
||||
(rl->version == DTLS_ANY_VERSION ? DTLS1_VERSION_MAJOR
|
||||
: rl->version >> 8)) {
|
||||
/* wrong version, silently discard record */
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
@ -598,66 +595,70 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
/* record too long, silently discard it */
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* If received packet overflows own-client Max Fragment Length setting */
|
||||
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
|
||||
&& rr->length > GET_MAX_FRAGMENT_LENGTH(s->session) + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
|
||||
|
||||
/*
|
||||
* If received packet overflows maximum possible fragment length then
|
||||
* silently discard it
|
||||
*/
|
||||
if (rl->max_frag_len > 0
|
||||
&& rr->length > rl->max_frag_len + SSL3_RT_MAX_ENCRYPTED_OVERHEAD) {
|
||||
/* record too long, silently discard it */
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* now s->rlayer.rstate == SSL_ST_READ_BODY */
|
||||
/* now rl->rstate == SSL_ST_READ_BODY */
|
||||
}
|
||||
|
||||
/* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */
|
||||
/* rl->rstate == SSL_ST_READ_BODY, get and decode the data */
|
||||
|
||||
if (rr->length >
|
||||
s->rrlmethod->get_packet_length(s->rrl) - DTLS1_RT_HEADER_LENGTH) {
|
||||
/* now s->rlayer.packet_length == DTLS1_RT_HEADER_LENGTH */
|
||||
rl->packet_length - DTLS1_RT_HEADER_LENGTH) {
|
||||
/* now rl->packet_length == DTLS1_RT_HEADER_LENGTH */
|
||||
more = rr->length;
|
||||
rret = s->rrlmethod->read_n(s->rrl, more, more, 1, 1, &n);
|
||||
rret = rl->funcs->read_n(rl, more, more, 1, 1, &n);
|
||||
/* this packet contained a partial record, dump it */
|
||||
if (rret < OSSL_RECORD_RETURN_SUCCESS || n != more) {
|
||||
if (ossl_statem_in_error(s)) {
|
||||
/* read_n() called SSLfatal() */
|
||||
if (rl->alert != 0) {
|
||||
/* read_n() called RLAYERfatal() */
|
||||
return OSSL_RECORD_RETURN_FATAL;
|
||||
}
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/*
|
||||
* now n == rr->length, and s->rlayer.packet_length ==
|
||||
* DTLS1_RT_HEADER_LENGTH + rr->length
|
||||
* now n == rr->length,
|
||||
* and rl->packet_length == DTLS1_RT_HEADER_LENGTH + rr->length
|
||||
*/
|
||||
}
|
||||
/* set state for later operations */
|
||||
RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER);
|
||||
rl->rstate = SSL_ST_READ_HEADER;
|
||||
|
||||
/* match epochs. NULL means the packet is dropped on the floor */
|
||||
bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
|
||||
bitmap = dtls1_get_bitmap(rl, rr, &is_next_epoch);
|
||||
if (bitmap == NULL) {
|
||||
rr->length = 0;
|
||||
s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
|
||||
rl->packet_length = 0; /* dump this record */
|
||||
goto again; /* get another record */
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
/* Only do replay check if no SCTP bio */
|
||||
if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
|
||||
if (!BIO_dgram_is_sctp(rl->bio)) {
|
||||
#endif
|
||||
/* Check whether this is a repeat, or aged record. */
|
||||
if (!dtls1_record_replay_check(s, bitmap)) {
|
||||
if (!dtls1_record_replay_check(rl, bitmap)) {
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
|
||||
rl->packet_length = 0; /* dump this record */
|
||||
goto again; /* get another record */
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
@ -677,7 +678,7 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
*/
|
||||
if (is_next_epoch) {
|
||||
if ((SSL_in_init(ssl) || ossl_statem_get_in_handshake(s))) {
|
||||
if (dtls_rlayer_buffer_record (s,
|
||||
if (dtls_rlayer_buffer_record(rl,
|
||||
&(rl->unprocessed_rcds),
|
||||
rr->seq_num) < 0) {
|
||||
/* SSLfatal() already called */
|
||||
@ -686,18 +687,18 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
}
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl);
|
||||
rl->packet_length = 0;
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (!dtls1_process_record(s, bitmap)) {
|
||||
if (ossl_statem_in_error(s)) {
|
||||
/* dtls1_process_record() called SSLfatal */
|
||||
if (!dtls1_process_record(rl, bitmap)) {
|
||||
if (rl->alert != 0) {
|
||||
/* dtls1_process_record() called RLAYERfatal */
|
||||
return OSSL_RECORD_RETURN_FATAL;
|
||||
}
|
||||
rr->length = 0;
|
||||
rr->read = 1;
|
||||
s->rrlmethod->reset_packet_length(s->rrl); /* dump this record */
|
||||
rl->packet_length = 0; /* dump this record */
|
||||
goto again; /* get another record */
|
||||
}
|
||||
|
||||
@ -706,22 +707,6 @@ static int dtls_get_more_records(OSSL_RECORD_LAYER *rl)
|
||||
|
||||
}
|
||||
|
||||
static int dtls_set_protocol_version(OSSL_RECORD_LAYER *rl, int version)
|
||||
{
|
||||
rl->version = version;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct record_functions_st dtls_funcs = {
|
||||
NULL,
|
||||
NULL,
|
||||
dtls_get_more_records,
|
||||
NULL,
|
||||
NULL,
|
||||
dtls_set_protocol_version,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int dtls_free(OSSL_RECORD_LAYER *rl)
|
||||
{
|
||||
pitem *item;
|
||||
@ -752,9 +737,9 @@ static int dtls_free(OSSL_RECORD_LAYER *rl)
|
||||
|
||||
static int
|
||||
dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
|
||||
int role, int direction, int level, unsigned char *key,
|
||||
size_t keylen, unsigned char *iv, size_t ivlen,
|
||||
unsigned char *mackey, size_t mackeylen,
|
||||
int role, int direction, int level, unsigned int epoch,
|
||||
unsigned char *key, size_t keylen, unsigned char *iv,
|
||||
size_t ivlen, unsigned char *mackey, size_t mackeylen,
|
||||
const EVP_CIPHER *ciph, size_t taglen,
|
||||
/* TODO(RECLAYER): This probably should not be an int */
|
||||
int mactype,
|
||||
@ -786,9 +771,34 @@ dtls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
|
||||
}
|
||||
|
||||
(*retrl)->isdtls = 1;
|
||||
(*retrl)->funcs = &dtls_funcs;
|
||||
(*retrl)->epoch = epoch;
|
||||
|
||||
return OSSL_RECORD_RETURN_SUCCESS;
|
||||
switch (vers) {
|
||||
case DTLS_ANY_VERSION:
|
||||
(*retrl)->funcs = &dtls_any_funcs;
|
||||
break;
|
||||
case DTLS1_2_VERSION:
|
||||
case DTLS1_VERSION:
|
||||
case DTLS1_BAD_VER:
|
||||
(*retrl)->funcs = &dtls_1_funcs;
|
||||
break;
|
||||
default:
|
||||
/* Should not happen */
|
||||
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
|
||||
ret = OSSL_RECORD_RETURN_FATAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = (*retrl)->funcs->set_crypto_state(*retrl, level, key, keylen, iv,
|
||||
ivlen, mackey, mackeylen, ciph,
|
||||
taglen, mactype, md, comp);
|
||||
|
||||
err:
|
||||
if (ret != OSSL_RECORD_RETURN_SUCCESS) {
|
||||
OPENSSL_free(*retrl);
|
||||
*retrl = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const OSSL_RECORD_METHOD ossl_dtls_record_method = {
|
||||
|
@ -483,9 +483,9 @@ static struct record_functions_st ossl_ktls_funcs = {
|
||||
|
||||
static int
|
||||
ktls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
|
||||
int role, int direction, int level, unsigned char *key,
|
||||
size_t keylen, unsigned char *iv, size_t ivlen,
|
||||
unsigned char *mackey, size_t mackeylen,
|
||||
int role, int direction, int level, unsigned int epoch,
|
||||
unsigned char *key, size_t keylen, unsigned char *iv,
|
||||
size_t ivlen, unsigned char *mackey, size_t mackeylen,
|
||||
const EVP_CIPHER *ciph, size_t taglen,
|
||||
/* TODO(RECLAYER): This probably should not be an int */
|
||||
int mactype,
|
||||
|
@ -68,6 +68,8 @@ struct ossl_record_layer_st
|
||||
int role;
|
||||
int direction;
|
||||
int level;
|
||||
/* DTLS only */
|
||||
unsigned int epoch;
|
||||
|
||||
/*
|
||||
* A BIO containing any data read in the previous epoch that was destined
|
||||
@ -200,6 +202,8 @@ extern struct record_functions_st ssl_3_0_funcs;
|
||||
extern struct record_functions_st tls_1_funcs;
|
||||
extern struct record_functions_st tls_1_3_funcs;
|
||||
extern struct record_functions_st tls_any_funcs;
|
||||
extern struct record_functions_st dtls_1_funcs;
|
||||
extern struct record_functions_st dtls_any_funcs;
|
||||
|
||||
void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
|
||||
const char *fmt, ...);
|
||||
@ -211,7 +215,8 @@ void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason,
|
||||
ossl_rlayer_fatal)
|
||||
|
||||
# define RLAYER_USE_EXPLICIT_IV(rl) ((rl)->version == TLS1_1_VERSION \
|
||||
|| (rl)->version == TLS1_2_VERSION)
|
||||
|| (rl)->version == TLS1_2_VERSION \
|
||||
|| (rl)->isdtls)
|
||||
|
||||
int ossl_set_tls_provider_parameters(OSSL_RECORD_LAYER *rl,
|
||||
EVP_CIPHER_CTX *ctx,
|
||||
@ -232,9 +237,11 @@ __owur int ssl3_cbc_digest_record(const EVP_MD *md,
|
||||
int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
|
||||
int clearold, size_t *readbytes);
|
||||
int tls_get_more_records(OSSL_RECORD_LAYER *rl);
|
||||
int dtls_get_more_records(OSSL_RECORD_LAYER *rl);
|
||||
|
||||
int tls_default_set_protocol_version(OSSL_RECORD_LAYER *rl, int version);
|
||||
int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *re);
|
||||
int tls_do_uncompress(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec);
|
||||
int tls_default_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec);
|
||||
int tls13_common_post_process_record(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec);
|
||||
|
||||
@ -281,3 +288,4 @@ void tls_set0_packet(OSSL_RECORD_LAYER *rl, unsigned char *packet,
|
||||
size_t packetlen);
|
||||
size_t tls_get_packet_length(OSSL_RECORD_LAYER *rl);
|
||||
void tls_reset_packet_length(OSSL_RECORD_LAYER *rl);
|
||||
int rlayer_setup_read_buffer(OSSL_RECORD_LAYER *rl);
|
@ -148,6 +148,8 @@ static int tls1_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
|
||||
size_t bs, ctr, padnum, loop;
|
||||
unsigned char padval;
|
||||
const EVP_CIPHER *enc;
|
||||
/* TODO(RECLAYER): FIXME */
|
||||
SSL_CONNECTION *s = (SSL_CONNECTION *)rl->cbarg;
|
||||
|
||||
if (n_recs == 0) {
|
||||
RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
@ -226,7 +228,6 @@ static int tls1_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
|
||||
seq = rl->sequence;
|
||||
|
||||
if (rl->isdtls) {
|
||||
#if 0
|
||||
/* TODO(RECLAYER): FIXME */
|
||||
/* DTLS does not support pipelining */
|
||||
unsigned char dtlsseq[8], *p = dtlsseq;
|
||||
@ -235,7 +236,6 @@ static int tls1_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs,
|
||||
DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p);
|
||||
memcpy(p, &seq[2], 6);
|
||||
memcpy(buf[ctr], dtlsseq, 8);
|
||||
#endif
|
||||
} else {
|
||||
memcpy(buf[ctr], seq, 8);
|
||||
for (i = 7; i >= 0; i--) { /* increment */
|
||||
@ -452,6 +452,8 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
|
||||
unsigned char header[13];
|
||||
int t;
|
||||
int ret = 0;
|
||||
/* TODO(RECLAYER): FIXME */
|
||||
SSL_CONNECTION *ssl = (SSL_CONNECTION *)rl->cbarg;
|
||||
|
||||
hash = rl->md_ctx;
|
||||
|
||||
@ -477,7 +479,6 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
|
||||
}
|
||||
|
||||
if (rl->isdtls) {
|
||||
#if 0
|
||||
/* TODO(RECLAYER): FIX ME */
|
||||
unsigned char dtlsseq[8], *p = dtlsseq;
|
||||
|
||||
@ -486,7 +487,6 @@ static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md,
|
||||
memcpy(p, &seq[2], 6);
|
||||
|
||||
memcpy(header, dtlsseq, 8);
|
||||
#endif
|
||||
} else
|
||||
memcpy(header, seq, 8);
|
||||
|
||||
@ -552,3 +552,14 @@ struct record_functions_st tls_1_funcs = {
|
||||
tls_default_validate_record_header,
|
||||
tls_default_post_process_record
|
||||
};
|
||||
|
||||
struct record_functions_st dtls_1_funcs = {
|
||||
tls1_set_crypto_state,
|
||||
tls_default_read_n,
|
||||
dtls_get_more_records,
|
||||
tls1_cipher,
|
||||
tls1_mac,
|
||||
tls_default_set_protocol_version,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
@ -95,7 +95,7 @@ static int rlayer_allow_compression(OSSL_RECORD_LAYER *rl)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int rlayer_setup_read_buffer(OSSL_RECORD_LAYER *rl)
|
||||
int rlayer_setup_read_buffer(OSSL_RECORD_LAYER *rl)
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t len, align = 0, headerlen;
|
||||
@ -879,7 +879,7 @@ int tls_default_validate_record_header(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tls_do_uncompress(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
|
||||
int tls_do_uncompress(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec)
|
||||
{
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
int i;
|
||||
@ -1156,9 +1156,9 @@ tls_int_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
|
||||
|
||||
static int
|
||||
tls_new_record_layer(OSSL_LIB_CTX *libctx, const char *propq, int vers,
|
||||
int role, int direction, int level, unsigned char *key,
|
||||
size_t keylen, unsigned char *iv, size_t ivlen,
|
||||
unsigned char *mackey, size_t mackeylen,
|
||||
int role, int direction, int level, unsigned int epoch,
|
||||
unsigned char *key, size_t keylen, unsigned char *iv,
|
||||
size_t ivlen, unsigned char *mackey, size_t mackeylen,
|
||||
const EVP_CIPHER *ciph, size_t taglen,
|
||||
/* TODO(RECLAYER): This probably should not be an int */
|
||||
int mactype,
|
||||
|
@ -151,3 +151,23 @@ struct record_functions_st tls_any_funcs = {
|
||||
tls_validate_record_header,
|
||||
tls_default_post_process_record
|
||||
};
|
||||
|
||||
static int dtls_any_set_protocol_version(OSSL_RECORD_LAYER *rl, int vers)
|
||||
{
|
||||
if (rl->version != DTLS_ANY_VERSION && rl->version != vers)
|
||||
return 0;
|
||||
rl->version = vers;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct record_functions_st dtls_any_funcs = {
|
||||
tls_any_set_crypto_state,
|
||||
tls_default_read_n,
|
||||
dtls_get_more_records,
|
||||
tls_any_cipher,
|
||||
NULL,
|
||||
dtls_any_set_protocol_version,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
@ -1892,6 +1892,11 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
|
||||
for (;;) {
|
||||
int rlret;
|
||||
BIO *prev = s->rrlnext;
|
||||
unsigned int epoch = 0;;
|
||||
|
||||
if (SSL_CONNECTION_IS_DTLS(s)
|
||||
&& level != OSSL_RECORD_PROTECTION_LEVEL_NONE)
|
||||
epoch = DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer) + 1; /* new epoch */
|
||||
|
||||
s->rrlnext = BIO_new(BIO_s_mem());
|
||||
|
||||
@ -1903,12 +1908,12 @@ int ssl_set_new_record_layer(SSL_CONNECTION *s, int version,
|
||||
|
||||
rlret = s->rrlmethod->new_record_layer(sctx->libctx, sctx->propq,
|
||||
version, s->server, direction,
|
||||
level, key, keylen, iv, ivlen,
|
||||
mackey, mackeylen, ciph, taglen,
|
||||
mactype, md, comp, prev, s->rbio,
|
||||
s->rrlnext, NULL, NULL, settings,
|
||||
options, rlayer_dispatch, s,
|
||||
&s->rrl);
|
||||
level, epoch, key, keylen, iv,
|
||||
ivlen, mackey, mackeylen, ciph,
|
||||
taglen, mactype, md, comp, prev,
|
||||
s->rbio, s->rrlnext, NULL, NULL,
|
||||
settings, options,
|
||||
rlayer_dispatch, s, &s->rrl);
|
||||
BIO_free(prev);
|
||||
switch (rlret) {
|
||||
case OSSL_RECORD_RETURN_FATAL:
|
||||
|
@ -274,8 +274,8 @@ __owur int dtls1_write_bytes(SSL_CONNECTION *s, int type, const void *buf,
|
||||
int do_dtls1_write(SSL_CONNECTION *s, int type, const unsigned char *buf,
|
||||
size_t len, int create_empty_fragment, size_t *written);
|
||||
void dtls1_reset_seq_numbers(SSL_CONNECTION *s, int rw);
|
||||
int dtls_buffer_listen_record(SSL_CONNECTION *s, size_t len, unsigned char *seq,
|
||||
size_t off);
|
||||
int dtls_buffer_listen_record(OSSL_RECORD_LAYER *rl, size_t len,
|
||||
unsigned char *seq, size_t off);
|
||||
void ssl_release_record(SSL_CONNECTION *s, TLS_RECORD *rr);
|
||||
|
||||
# define HANDLE_RLAYER_RETURN(s, ret) \
|
||||
|
@ -146,7 +146,9 @@ struct ossl_record_method_st {
|
||||
int (*new_record_layer)(OSSL_LIB_CTX *libctx,
|
||||
const char *propq, int vers,
|
||||
int role, int direction,
|
||||
int level, unsigned char *key,
|
||||
int level,
|
||||
unsigned int epoch,
|
||||
unsigned char *key,
|
||||
size_t keylen,
|
||||
unsigned char *iv,
|
||||
size_t ivlen,
|
||||
|
@ -665,7 +665,7 @@ int ossl_ssl_connection_reset(SSL *s)
|
||||
* assign it.
|
||||
*/
|
||||
if (!ssl_set_new_record_layer(sc,
|
||||
TLS_ANY_VERSION,
|
||||
SSL_CONNECTION_IS_DTLS(sc) ? DTLS_ANY_VERSION : TLS_ANY_VERSION,
|
||||
OSSL_RECORD_DIRECTION_READ,
|
||||
OSSL_RECORD_PROTECTION_LEVEL_NONE,
|
||||
NULL, 0, NULL, 0, NULL, 0, NULL, 0,
|
||||
|
@ -2196,9 +2196,21 @@ int ssl_set_client_hello_version(SSL_CONNECTION *s)
|
||||
|
||||
s->version = ver_max;
|
||||
|
||||
/* TLS1.3 always uses TLS1.2 in the legacy_version field */
|
||||
if (!SSL_CONNECTION_IS_DTLS(s) && ver_max > TLS1_2_VERSION)
|
||||
if (SSL_CONNECTION_IS_DTLS(s)) {
|
||||
if (ver_max == DTLS1_BAD_VER) {
|
||||
/*
|
||||
* Even though this is technically before version negotiation,
|
||||
* because we have asked for DTLS1_BAD_VER we will never negotiate
|
||||
* anything else, and this has impacts on the record layer for when
|
||||
* we read the ServerHello. So we need to tell the record layer
|
||||
* about this immediately.
|
||||
*/
|
||||
s->rrlmethod->set_protocol_version(s->rrl, ver_max);
|
||||
}
|
||||
} else if (ver_max > TLS1_2_VERSION) {
|
||||
/* TLS1.3 always uses TLS1.2 in the legacy_version field */
|
||||
ver_max = TLS1_2_VERSION;
|
||||
}
|
||||
|
||||
s->client_version = ver_max;
|
||||
return 0;
|
||||
|
59
ssl/t1_enc.c
59
ssl/t1_enc.c
@ -242,55 +242,18 @@ int tls1_change_cipher_state(SSL_CONNECTION *s, int which)
|
||||
else
|
||||
s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE;
|
||||
|
||||
if (SSL_CONNECTION_IS_DTLS(s)) {
|
||||
if (s->enc_read_ctx != NULL) {
|
||||
reuse_dd = 1;
|
||||
} else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
} else {
|
||||
/*
|
||||
* make sure it's initialised in case we exit later with an error
|
||||
*/
|
||||
EVP_CIPHER_CTX_reset(s->enc_read_ctx);
|
||||
}
|
||||
dd = s->enc_read_ctx;
|
||||
mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
|
||||
if (mac_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
COMP_CTX_free(s->expand);
|
||||
s->expand = NULL;
|
||||
if (comp != NULL) {
|
||||
s->expand = COMP_CTX_new(comp->method);
|
||||
if (s->expand == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_R_COMPRESSION_LIBRARY_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* this is done by dtls1_reset_seq_numbers for DTLS
|
||||
*/
|
||||
if (!SSL_CONNECTION_IS_DTLS(s))
|
||||
RECORD_LAYER_reset_read_sequence(&s->rlayer);
|
||||
} else {
|
||||
if (!ssl_set_new_record_layer(s, s->version,
|
||||
OSSL_RECORD_DIRECTION_READ,
|
||||
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
|
||||
key, cl, iv, (size_t)k, mac_secret,
|
||||
mac_secret_size, c, taglen, mac_type,
|
||||
m, comp)) {
|
||||
/* SSLfatal already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TODO(RECLAYER): Temporary - remove me */
|
||||
goto skip_ktls;
|
||||
if (!ssl_set_new_record_layer(s, s->version,
|
||||
OSSL_RECORD_DIRECTION_READ,
|
||||
OSSL_RECORD_PROTECTION_LEVEL_APPLICATION,
|
||||
key, cl, iv, (size_t)k, mac_secret,
|
||||
mac_secret_size, c, taglen, mac_type,
|
||||
m, comp)) {
|
||||
/* SSLfatal already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TODO(RECLAYER): Temporary - remove me */
|
||||
goto skip_ktls;
|
||||
} else {
|
||||
s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
|
||||
if (s->ext.use_etm)
|
||||
|
Loading…
Reference in New Issue
Block a user