aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssl/ssl/record/ssl3_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssl/ssl/record/ssl3_record.c')
-rw-r--r--crypto/openssl/ssl/record/ssl3_record.c1217
1 files changed, 517 insertions, 700 deletions
diff --git a/crypto/openssl/ssl/record/ssl3_record.c b/crypto/openssl/ssl/record/ssl3_record.c
index da549995e070..d6c0cf346723 100644
--- a/crypto/openssl/ssl/record/ssl3_record.c
+++ b/crypto/openssl/ssl/record/ssl3_record.c
@@ -1,15 +1,16 @@
/*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "../ssl_local.h"
-#include "internal/constant_time.h"
+#include <openssl/trace.h>
#include <openssl/rand.h>
+#include <openssl/core_names.h>
#include "record_local.h"
#include "internal/cryptlib.h"
@@ -114,8 +115,7 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
if (!s->server && sess->ext.max_early_data == 0) {
if (!ossl_assert(s->psksession != NULL
&& s->psksession->ext.max_early_data > 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_EARLY_DATA_COUNT_OK,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
sess = s->psksession;
@@ -131,7 +131,7 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
if (max_early_data == 0) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+ SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
@@ -140,7 +140,7 @@ int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send)
if (s->early_data_count + length > max_early_data) {
SSLfatal(s, send ? SSL_AD_INTERNAL_ERROR : SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_EARLY_DATA_COUNT_OK, SSL_R_TOO_MUCH_EARLY_DATA);
+ SSL_R_TOO_MUCH_EARLY_DATA);
return 0;
}
s->early_data_count += length;
@@ -181,12 +181,13 @@ int ssl3_get_record(SSL *s)
unsigned char *p;
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int version;
- size_t mac_size;
+ size_t mac_size = 0;
int imac_size;
size_t num_recs = 0, max_recs, j;
PACKET pkt, sslv2pkt;
- size_t first_rec_len;
int using_ktls;
+ SSL_MAC_BUF *macbufs = NULL;
+ int ret = -1;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
rbuf = RECORD_LAYER_get_rbuf(&s->rlayer);
@@ -221,17 +222,14 @@ int ssl3_get_record(SSL *s)
switch (errno) {
case EBADMSG:
SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
- SSL_F_SSL3_GET_RECORD,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
break;
case EMSGSIZE:
SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
- SSL_F_SSL3_GET_RECORD,
SSL_R_PACKET_LENGTH_TOO_LONG);
break;
case EINVAL:
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
break;
default:
@@ -245,15 +243,13 @@ int ssl3_get_record(SSL *s)
p = RECORD_LAYER_get_packet(&s->rlayer);
if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer),
RECORD_LAYER_get_packet_length(&s->rlayer))) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
sslv2pkt = pkt;
if (!PACKET_get_net_2_len(&sslv2pkt, &sslv2len)
|| !PACKET_get_1(&sslv2pkt, &type)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
/*
@@ -278,33 +274,35 @@ int ssl3_get_record(SSL *s)
if (thisrr->length > SSL3_BUFFER_get_len(rbuf)
- SSL2_RT_HEADER_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
if (thisrr->length < MIN_SSL2_RECORD_LEN) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return -1;
}
} else {
/* SSLv3+ style record */
- if (s->msg_callback)
- s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
- s->msg_callback_arg);
/* Pull apart the header into the SSL3_RECORD */
if (!PACKET_get_1(&pkt, &type)
|| !PACKET_get_net_2(&pkt, &version)
|| !PACKET_get_net_2_len(&pkt, &thisrr->length)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
+ if (s->msg_callback)
+ s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s,
+ s->msg_callback_arg);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, ERR_R_INTERNAL_ERROR);
return -1;
}
thisrr->type = type;
thisrr->rec_version = version;
+ if (s->msg_callback)
+ s->msg_callback(0, version, SSL3_RT_HEADER, p, 5, s,
+ s->msg_callback_arg);
+
/*
* Lets check version. In TLSv1.3 we only check this field
* when encryption is occurring (see later check). For the
@@ -326,7 +324,7 @@ int ssl3_get_record(SSL *s)
* shouldn't send a fatal alert back. We'll just
* end.
*/
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -335,7 +333,7 @@ int ssl3_get_record(SSL *s)
*/
s->version = (unsigned short)version;
}
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -349,22 +347,20 @@ int ssl3_get_record(SSL *s)
strncmp((char *)p, "POST ", 5) == 0 ||
strncmp((char *)p, "HEAD ", 5) == 0 ||
strncmp((char *)p, "PUT ", 4) == 0) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
- SSL_R_HTTP_REQUEST);
+ SSLfatal(s, SSL_AD_NO_ALERT, SSL_R_HTTP_REQUEST);
return -1;
} else if (strncmp((char *)p, "CONNE", 5) == 0) {
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_HTTPS_PROXY_REQUEST);
return -1;
}
/* Doesn't look like TLS - don't send an alert */
- SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_NO_ALERT,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
} else {
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_SSL3_GET_RECORD,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -380,11 +376,11 @@ int ssl3_get_record(SSL *s)
|| s->statem.enc_read_state
!= ENC_READ_STATE_ALLOW_PLAIN_ALERTS)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE);
+ SSL_R_BAD_RECORD_TYPE);
return -1;
}
if (thisrr->rec_version != TLS1_2_VERSION) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_R_WRONG_VERSION_NUMBER);
return -1;
}
@@ -392,7 +388,7 @@ int ssl3_get_record(SSL *s)
if (thisrr->length >
SSL3_BUFFER_get_len(rbuf) - SSL3_RT_HEADER_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_PACKET_LENGTH_TOO_LONG);
return -1;
}
@@ -409,7 +405,7 @@ int ssl3_get_record(SSL *s)
len = SSL3_RT_MAX_ENCRYPTED_LENGTH;
if (thisrr->length > len) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
@@ -430,7 +426,7 @@ int ssl3_get_record(SSL *s)
len = SSL3_BUFFER_get_left(rbuf);
if (thisrr->length > len) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return -1;
}
@@ -501,8 +497,8 @@ int ssl3_get_record(SSL *s)
&& thisrr->type == SSL3_RT_APPLICATION_DATA
&& SSL_USE_EXPLICIT_IV(s)
&& s->enc_read_ctx != NULL
- && (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx))
- & EVP_CIPH_FLAG_PIPELINE)
+ && (EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx))
+ & EVP_CIPH_FLAG_PIPELINE) != 0
&& ssl3_record_app_data_waiting(s));
if (num_recs == 1
@@ -513,7 +509,7 @@ int ssl3_get_record(SSL *s)
* CCS messages must be exactly 1 byte long, containing the value 0x01
*/
if (thisrr->length != 1 || thisrr->data[0] != 0x01) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_INVALID_CCS_MESSAGE);
return -1;
}
@@ -525,7 +521,7 @@ int ssl3_get_record(SSL *s)
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_R_UNEXPECTED_CCS_MESSAGE);
return -1;
}
@@ -538,180 +534,134 @@ int ssl3_get_record(SSL *s)
if (using_ktls)
goto skip_decryption;
+ if (s->read_hash != NULL) {
+ const EVP_MD *tmpmd = EVP_MD_CTX_get0_md(s->read_hash);
+
+ 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);
+ return -1;
+ }
+ mac_size = (size_t)imac_size;
+ }
+ }
+
/*
* If in encrypt-then-mac mode calculate mac from encrypted record. All
* the details below are public so no timing details can leak.
*/
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
- /* TODO(size_t): convert this to do size_t properly */
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (!ossl_assert(imac_size >= 0 && imac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_LIB_EVP);
- return -1;
- }
- mac_size = (size_t)imac_size;
+
for (j = 0; j < num_recs; j++) {
thisrr = &rr[j];
if (thisrr->length < mac_size) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return -1;
}
thisrr->length -= mac_size;
mac = thisrr->data + thisrr->length;
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
if (i == 0 || CRYPTO_memcmp(md, mac, mac_size) != 0) {
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
- SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return -1;
}
}
+ /*
+ * We've handled the mac now - there is no MAC inside the encrypted
+ * record
+ */
+ mac_size = 0;
}
- first_rec_len = rr[0].length;
+ if (mac_size > 0) {
+ macbufs = OPENSSL_zalloc(sizeof(*macbufs) * num_recs);
+ if (macbufs == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
+ }
- enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0);
+ ERR_set_mark();
+ enc_err = s->method->ssl3_enc->enc(s, rr, num_recs, 0, macbufs, mac_size);
/*-
* enc_err is:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding is valid
- * -1: if the padding is invalid
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or ETM decryption failed.
+ * 1: Success or MTE decryption failed (MAC will be randomised)
*/
if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* SSLfatal() already got called */
- return -1;
+ ERR_clear_last_mark();
+ goto end;
}
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
/*
- * Valid early_data that we cannot decrypt might fail here as
- * publicly invalid. We treat it like an empty record.
+ * Valid early_data that we cannot decrypt will fail here. We treat
+ * it like an empty record.
+ */
+
+ /*
+ * Remove any errors from the stack. Decryption failures are normal
+ * behaviour.
*/
+ ERR_pop_to_mark();
thisrr = &rr[0];
if (!early_data_count_ok(s, thisrr->length,
EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
/* SSLfatal() already called */
- return -1;
+ goto end;
}
thisrr->length = 0;
thisrr->read = 1;
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
RECORD_LAYER_reset_read_sequence(&s->rlayer);
- return 1;
+ ret = 1;
+ goto end;
}
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
- SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
- return -1;
- }
-#ifdef SSL_DEBUG
- printf("dec %lu\n", (unsigned long)rr[0].length);
- {
- size_t z;
- for (z = 0; z < rr[0].length; z++)
- printf("%02X%c", rr[0].data[z], ((z + 1) % 16) ? ' ' : '\n');
+ ERR_clear_last_mark();
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ goto end;
+ } else {
+ ERR_clear_last_mark();
}
- printf("\n");
-#endif
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "dec %lu\n", (unsigned long)rr[0].length);
+ BIO_dump_indent(trc_out, rr[0].data, rr[0].length, 4);
+ } OSSL_TRACE_END(TLS);
/* r->length is now the compressed data plus mac */
- if ((sess != NULL) &&
- (s->enc_read_ctx != NULL) &&
- (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL)) {
+ if ((sess != NULL)
+ && (s->enc_read_ctx != NULL)
+ && (!SSL_READ_ETM(s) && EVP_MD_CTX_get0_md(s->read_hash) != NULL)) {
/* s->read_hash != NULL => mac_size != -1 */
- unsigned char *mac = NULL;
- unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-
- mac_size = EVP_MD_CTX_size(s->read_hash);
- if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
- return -1;
- }
for (j = 0; j < num_recs; j++) {
+ SSL_MAC_BUF *thismb = &macbufs[j];
thisrr = &rr[j];
- /*
- * orig_len is the length of the record before any padding was
- * removed. This is public information, as is the MAC in use,
- * therefore we can safely process the record in a different amount
- * of time if it's too short to possibly contain a MAC.
- */
- if (thisrr->orig_len < mac_size ||
- /* CBC records must have a padding length byte too. */
- (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- thisrr->orig_len < mac_size + 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL3_GET_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
- return -1;
- }
-
- if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
- /*
- * We update the length so that the TLS header bytes can be
- * constructed correctly but we need to extract the MAC in
- * constant time from within the record, without leaking the
- * contents of the padding bytes.
- */
- mac = mac_tmp;
- if (!ssl3_cbc_copy_mac(mac_tmp, thisrr, mac_size)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_GET_RECORD,
- ERR_R_INTERNAL_ERROR);
- return -1;
- }
- thisrr->length -= mac_size;
- } else {
- /*
- * In this case there's no padding, so |rec->orig_len| equals
- * |rec->length| and we checked that there's enough bytes for
- * |mac_size| above.
- */
- thisrr->length -= mac_size;
- mac = &thisrr->data[thisrr->length];
- }
i = s->method->ssl3_enc->mac(s, thisrr, md, 0 /* not send */ );
- if (i == 0 || mac == NULL
- || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0)
- enc_err = -1;
+ if (i == 0 || thismb == NULL || thismb->mac == NULL
+ || CRYPTO_memcmp(md, thismb->mac, (size_t)mac_size) != 0)
+ enc_err = 0;
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
- enc_err = -1;
+ enc_err = 0;
}
}
- if (enc_err < 0) {
+ if (enc_err == 0) {
if (ossl_statem_in_error(s)) {
/* We already called SSLfatal() */
- return -1;
- }
- if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
- /*
- * We assume this is unreadable early_data - we treat it like an
- * empty record
- */
-
- /*
- * The record length may have been modified by the mac check above
- * so we use the previously saved value
- */
- if (!early_data_count_ok(s, first_rec_len,
- EARLY_DATA_CIPHERTEXT_OVERHEAD, 0)) {
- /* SSLfatal() already called */
- return -1;
- }
-
- thisrr = &rr[0];
- thisrr->length = 0;
- thisrr->read = 1;
- RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
- RECORD_LAYER_reset_read_sequence(&s->rlayer);
- return 1;
+ goto end;
}
/*
* A separate 'decryption_failed' alert was introduced with TLS 1.0,
@@ -720,9 +670,9 @@ int ssl3_get_record(SSL *s)
* not reveal which kind of error occurred -- this might become
* visible to an attacker (e.g. via a logfile)
*/
- SSLfatal(s, SSL_AD_BAD_RECORD_MAC, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
- return -1;
+ goto end;
}
skip_decryption:
@@ -733,14 +683,14 @@ int ssl3_get_record(SSL *s)
/* thisrr->length is now just compressed */
if (s->expand != NULL) {
if (thisrr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
- return -1;
+ goto end;
}
if (!ssl3_do_uncompress(s, thisrr)) {
- SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_F_SSL3_GET_RECORD,
+ SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE,
SSL_R_BAD_DECOMPRESSION);
- return -1;
+ goto end;
}
}
@@ -758,9 +708,8 @@ int ssl3_get_record(SSL *s)
if (thisrr->length == 0
|| thisrr->type != SSL3_RT_APPLICATION_DATA) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
- SSL_F_SSL3_GET_RECORD, SSL_R_BAD_RECORD_TYPE);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+ goto end;
}
/* Strip trailing padding */
@@ -774,9 +723,8 @@ int ssl3_get_record(SSL *s)
if (thisrr->type != SSL3_RT_APPLICATION_DATA
&& thisrr->type != SSL3_RT_ALERT
&& thisrr->type != SSL3_RT_HANDSHAKE) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_BAD_RECORD_TYPE);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_RECORD_TYPE);
+ goto end;
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_INNER_CONTENT_TYPE,
@@ -791,9 +739,8 @@ int ssl3_get_record(SSL *s)
&& (thisrr->type == SSL3_RT_HANDSHAKE
|| thisrr->type == SSL3_RT_ALERT)
&& thisrr->length == 0) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_BAD_LENGTH);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_BAD_LENGTH);
+ goto end;
}
/*
@@ -805,9 +752,8 @@ int ssl3_get_record(SSL *s)
* limit in the kernel.
*/
if (thisrr->length > SSL3_RT_MAX_PLAIN_LENGTH && !using_ktls) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return -1;
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
}
/*
@@ -817,9 +763,8 @@ int ssl3_get_record(SSL *s)
*/
if (s->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& thisrr->length > GET_MAX_FRAGMENT_LENGTH(s->session)) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_SSL3_GET_RECORD,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return -1;
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
}
thisrr->off = 0;
@@ -836,9 +781,8 @@ int ssl3_get_record(SSL *s)
RECORD_LAYER_inc_empty_record_count(&s->rlayer);
if (RECORD_LAYER_get_empty_record_count(&s->rlayer)
> MAX_EMPTY_RECORDS) {
- SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_SSL3_GET_RECORD,
- SSL_R_RECORD_TOO_SMALL);
- return -1;
+ SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_R_RECORD_TOO_SMALL);
+ goto end;
}
} else {
RECORD_LAYER_reset_empty_record_count(&s->rlayer);
@@ -850,12 +794,21 @@ int ssl3_get_record(SSL *s)
if (thisrr->type == SSL3_RT_APPLICATION_DATA
&& !early_data_count_ok(s, thisrr->length, 0, 0)) {
/* SSLfatal already called */
- return -1;
+ goto end;
}
}
RECORD_LAYER_set_numrpipes(&s->rlayer, num_recs);
- return 1;
+ ret = 1;
+ end:
+ if (macbufs != NULL) {
+ for (j = 0; j < num_recs; j++) {
+ if (macbufs[j].alloced)
+ OPENSSL_free(macbufs[j].mac);
+ }
+ OPENSSL_free(macbufs);
+ }
+ return ret;
}
int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
@@ -870,7 +823,6 @@ int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr)
if (rr->comp == NULL)
return 0;
- /* TODO(size_t): Convert this call */
i = COMP_expand_block(ssl->expand, rr->comp,
SSL3_RT_MAX_PLAIN_LENGTH, rr->data, (int)rr->length);
if (i < 0)
@@ -887,7 +839,6 @@ int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
#ifndef OPENSSL_NO_COMP
int i;
- /* TODO(size_t): Convert this call */
i = COMP_compress_block(ssl->compress, wr->data,
(int)(wr->length + SSL3_RT_MAX_COMPRESSED_OVERHEAD),
wr->input, (int)wr->length);
@@ -902,23 +853,21 @@ int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr)
}
/*-
- * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Will call
- * SSLfatal() for internal errors, but not otherwise.
+ * ssl3_enc encrypts/decrypts |n_recs| records in |inrecs|. Calls SSLfatal on
+ * internal error, but not otherwise. It is the responsibility of the caller to
+ * report a bad_record_mac
*
* Returns:
- * 0: (in non-constant time) if the record is publicly invalid (i.e. too
- * short etc).
- * 1: if the record's padding is valid / the encryption was successful.
- * -1: if the record's padding is invalid or, if sending, an internal error
- * occurred.
+ * 0: if the record is publicly invalid, or an internal error
+ * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
*/
-int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
+int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending,
+ SSL_MAC_BUF *mac, size_t macsize)
{
SSL3_RECORD *rec;
EVP_CIPHER_CTX *ds;
size_t l, i;
- size_t bs, mac_size = 0;
- int imac_size;
+ size_t bs;
const EVP_CIPHER *enc;
rec = inrecs;
@@ -932,26 +881,31 @@ int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
if (s->enc_write_ctx == NULL)
enc = NULL;
else
- enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
} else {
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
- enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
memmove(rec->data, rec->input, rec->length);
rec->input = rec->data;
} else {
+ int provided = (EVP_CIPHER_get0_provider(enc) != NULL);
+
l = rec->length;
- /* TODO(size_t): Convert this call */
- bs = EVP_CIPHER_CTX_block_size(ds);
+ bs = EVP_CIPHER_CTX_get_block_size(ds);
/* COMPRESS */
- if ((bs != 1) && sending) {
+ if ((bs != 1) && sending && !provided) {
+ /*
+ * We only do this for legacy ciphers. Provided ciphers add the
+ * padding on the provider side.
+ */
i = bs - (l % bs);
/* we need to add 'i-1' padding bytes */
@@ -966,67 +920,96 @@ int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending)
}
if (!sending) {
- if (l == 0 || l % bs != 0)
+ if (l == 0 || l % bs != 0) {
+ /* Publicly invalid */
return 0;
+ }
/* otherwise, rec->length >= bs */
}
- /* TODO(size_t): Convert this call */
- if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1)
- return -1;
+ if (EVP_CIPHER_get0_provider(enc) != NULL) {
+ int outlen;
- if (EVP_MD_CTX_md(s->read_hash) != NULL) {
- /* TODO(size_t): convert me */
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (imac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input,
+ (unsigned int)l))
+ return 0;
+ rec->length = outlen;
+
+ if (!sending && mac != NULL) {
+ /* Now get a pointer to the MAC */
+ OSSL_PARAM params[2], *p = params;
+
+ /* Get the MAC */
+ mac->alloced = 0;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
+ (void **)&mac->mac,
+ macsize);
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_CIPHER_CTX_get_params(ds, params)) {
+ /* Shouldn't normally happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
- mac_size = (size_t)imac_size;
+ } else {
+ if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) {
+ /* Shouldn't happen */
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!sending)
+ return ssl3_cbc_remove_padding_and_mac(&rec->length,
+ rec->orig_len,
+ rec->data,
+ (mac != NULL) ? &mac->mac : NULL,
+ (mac != NULL) ? &mac->alloced : NULL,
+ bs,
+ macsize,
+ s->ctx->libctx);
}
- if ((bs != 1) && !sending)
- return ssl3_cbc_remove_padding(rec, bs, mac_size);
}
return 1;
}
#define MAX_PADDING 256
/*-
- * tls1_enc encrypts/decrypts |n_recs| in |recs|. Will call SSLfatal() for
- * internal errors, but not otherwise.
+ * tls1_enc encrypts/decrypts |n_recs| in |recs|. Calls SSLfatal on internal
+ * error, but not otherwise. It is the responsibility of the caller to report
+ * a bad_record_mac - if appropriate (DTLS just drops the record).
*
* Returns:
- * 0: (in non-constant time) if the record is publicly invalid (i.e. too
- * short etc).
- * 1: if the record's padding is valid / the encryption was successful.
- * -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
- * an internal error occurred.
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or Encrypt-then-mac decryption failed.
+ * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
*/
-int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
+int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
+ SSL_MAC_BUF *macs, size_t macsize)
{
EVP_CIPHER_CTX *ds;
size_t reclen[SSL_MAX_PIPELINES];
unsigned char buf[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN];
- int i, pad = 0, ret, tmpr;
- size_t bs, mac_size = 0, ctr, padnum, loop;
+ unsigned char *data[SSL_MAX_PIPELINES];
+ int i, pad = 0, tmpr;
+ size_t bs, ctr, padnum, loop;
unsigned char padval;
- int imac_size;
const EVP_CIPHER *enc;
+ int tlstree_enc = sending ? (s->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
+ : (s->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
if (n_recs == 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
}
if (sending) {
- if (EVP_MD_CTX_md(s->write_hash)) {
- int n = EVP_MD_CTX_size(s->write_hash);
+ if (EVP_MD_CTX_get0_md(s->write_hash)) {
+ int n = EVP_MD_CTX_get_size(s->write_hash);
if (!ossl_assert(n >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
ds = s->enc_write_ctx;
@@ -1034,11 +1017,12 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
enc = NULL;
else {
int ivlen;
- enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
+
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx);
/* For TLSv1.1 and later explicit IV */
if (SSL_USE_EXPLICIT_IV(s)
- && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
- ivlen = EVP_CIPHER_iv_length(enc);
+ && EVP_CIPHER_get_mode(enc) == EVP_CIPH_CBC_MODE)
+ ivlen = EVP_CIPHER_get_iv_length(enc);
else
ivlen = 0;
if (ivlen > 1) {
@@ -1048,31 +1032,29 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
* we can't write into the input stream: Can this ever
* happen?? (steve)
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
- } else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
+ } else if (RAND_bytes_ex(s->ctx->libctx, recs[ctr].input,
+ ivlen, 0) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
}
}
} else {
- if (EVP_MD_CTX_md(s->read_hash)) {
- int n = EVP_MD_CTX_size(s->read_hash);
+ if (EVP_MD_CTX_get0_md(s->read_hash)) {
+ int n = EVP_MD_CTX_get_size(s->read_hash);
if (!ossl_assert(n >= 0)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
ds = s->enc_read_ctx;
if (s->enc_read_ctx == NULL)
enc = NULL;
else
- enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
+ enc = EVP_CIPHER_CTX_get0_cipher(s->enc_read_ctx);
}
if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) {
@@ -1080,27 +1062,27 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length);
recs[ctr].input = recs[ctr].data;
}
- ret = 1;
} else {
- bs = EVP_CIPHER_block_size(EVP_CIPHER_CTX_cipher(ds));
+ int provided = (EVP_CIPHER_get0_provider(enc) != NULL);
+
+ bs = EVP_CIPHER_get_block_size(EVP_CIPHER_CTX_get0_cipher(ds));
if (n_recs > 1) {
- if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
- & EVP_CIPH_FLAG_PIPELINE)) {
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
+ & EVP_CIPH_FLAG_PIPELINE) == 0) {
/*
* We shouldn't have been called with pipeline data if the
* cipher doesn't support pipelining
*/
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- SSL_R_PIPELINE_FAILURE);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
+ return 0;
}
}
for (ctr = 0; ctr < n_recs; ctr++) {
reclen[ctr] = recs[ctr].length;
- if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
- & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
+ & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) {
unsigned char *seq;
seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
@@ -1131,9 +1113,8 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
EVP_AEAD_TLS1_AAD_LEN, buf[ctr]);
if (pad <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
if (sending) {
@@ -1141,15 +1122,18 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
recs[ctr].length += pad;
}
- } else if ((bs != 1) && sending) {
+ } else if ((bs != 1) && sending && !provided) {
+ /*
+ * We only do this for legacy ciphers. Provided ciphers add the
+ * padding on the provider side.
+ */
padnum = bs - (reclen[ctr] % bs);
/* Add weird padding of up to 256 bytes */
if (padnum > MAX_PADDING) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
/* we need to add 'padnum' padding bytes of value padval */
padval = (unsigned char)(padnum - 1);
@@ -1160,22 +1144,21 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
}
if (!sending) {
- if (reclen[ctr] == 0 || reclen[ctr] % bs != 0)
+ if (reclen[ctr] == 0 || reclen[ctr] % bs != 0) {
+ /* Publicly invalid */
return 0;
+ }
}
}
if (n_recs > 1) {
- unsigned char *data[SSL_MAX_PIPELINES];
-
/* Set the output buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
data[ctr] = recs[ctr].data;
}
if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS,
(int)n_recs, data) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- SSL_R_PIPELINE_FAILURE);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
+ return 0;
}
/* Set the input buffers */
for (ctr = 0; ctr < n_recs; ctr++) {
@@ -1185,69 +1168,156 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
(int)n_recs, data) <= 0
|| EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS,
(int)n_recs, reclen) <= 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- SSL_R_PIPELINE_FAILURE);
- return -1;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE);
+ return 0;
}
}
- /* TODO(size_t): Convert this call */
- tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
- (unsigned int)reclen[0]);
- if ((EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ds))
- & EVP_CIPH_FLAG_CUSTOM_CIPHER)
- ? (tmpr < 0)
- : (tmpr == 0))
- return -1; /* AEAD can fail to verify MAC */
-
- if (sending == 0) {
- if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
- }
- } else if (EVP_CIPHER_mode(enc) == EVP_CIPH_CCM_MODE) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
- recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
- }
+ if (!SSL_IS_DTLS(s) && tlstree_enc) {
+ unsigned char *seq;
+ int decrement_seq = 0;
+
+ /*
+ * When sending, seq is incremented after MAC calculation.
+ * So if we are in ETM mode, we use seq 'as is' in the ctrl-function.
+ * Otherwise we have to decrease it in the implementation
+ */
+ if (sending && !SSL_WRITE_ETM(s))
+ decrement_seq = 1;
+
+ seq = sending ? RECORD_LAYER_get_write_sequence(&s->rlayer)
+ : RECORD_LAYER_get_read_sequence(&s->rlayer);
+ if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_TLSTREE, decrement_seq, seq) <= 0) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
}
- ret = 1;
- if (!SSL_READ_ETM(s) && EVP_MD_CTX_md(s->read_hash) != NULL) {
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (imac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
- ERR_R_INTERNAL_ERROR);
- return -1;
+ if (provided) {
+ int outlen;
+
+ /* Provided cipher - we do not support pipelining on this path */
+ if (n_recs > 1) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ return 0;
}
- mac_size = (size_t)imac_size;
- }
- if ((bs != 1) && !sending) {
- int tmpret;
- for (ctr = 0; ctr < n_recs; ctr++) {
- tmpret = tls1_cbc_remove_padding(s, &recs[ctr], bs, mac_size);
- /*
- * If tmpret == 0 then this means publicly invalid so we can
- * short circuit things here. Otherwise we must respect constant
- * time behaviour.
- */
- if (tmpret == 0)
- return 0;
- ret = constant_time_select_int(constant_time_eq_int(tmpret, 1),
- ret, -1);
+
+ if (!EVP_CipherUpdate(ds, recs[0].data, &outlen, recs[0].input,
+ (unsigned int)reclen[0]))
+ return 0;
+ recs[0].length = outlen;
+
+ /*
+ * The length returned from EVP_CipherUpdate above is the actual
+ * payload length. We need to adjust the data/input ptr to skip over
+ * any explicit IV
+ */
+ if (!sending) {
+ if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
+ recs[0].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[0].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
+ recs[0].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[0].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
+ recs[0].data += bs;
+ recs[0].input += bs;
+ recs[0].orig_len -= bs;
+ }
+
+ /* Now get a pointer to the MAC (if applicable) */
+ if (macs != NULL) {
+ OSSL_PARAM params[2], *p = params;
+
+ /* Get the MAC */
+ macs[0].alloced = 0;
+
+ *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
+ (void **)&macs[0].mac,
+ macsize);
+ *p = OSSL_PARAM_construct_end();
+
+ if (!EVP_CIPHER_CTX_get_params(ds, params)) {
+ /* Shouldn't normally happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ }
}
- }
- if (pad && !sending) {
- for (ctr = 0; ctr < n_recs; ctr++) {
- recs[ctr].length -= pad;
+ } else {
+ /* Legacy cipher */
+
+ tmpr = EVP_Cipher(ds, recs[0].data, recs[0].input,
+ (unsigned int)reclen[0]);
+ if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ds))
+ & EVP_CIPH_FLAG_CUSTOM_CIPHER) != 0
+ ? (tmpr < 0)
+ : (tmpr == 0)) {
+ /* AEAD can fail to verify MAC */
+ return 0;
+ }
+
+ if (!sending) {
+ for (ctr = 0; ctr < n_recs; ctr++) {
+ /* Adjust the record to remove the explicit IV/MAC/Tag */
+ if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_GCM_MODE) {
+ recs[ctr].data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+ } else if (EVP_CIPHER_get_mode(enc) == EVP_CIPH_CCM_MODE) {
+ recs[ctr].data += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].input += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ recs[ctr].length -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+ } else if (bs != 1 && SSL_USE_EXPLICIT_IV(s)) {
+ if (recs[ctr].length < bs)
+ return 0;
+ recs[ctr].data += bs;
+ recs[ctr].input += bs;
+ recs[ctr].length -= bs;
+ recs[ctr].orig_len -= bs;
+ }
+
+ /*
+ * If using Mac-then-encrypt, then this will succeed but
+ * with a random MAC if padding is invalid
+ */
+ if (!tls1_cbc_remove_padding_and_mac(&recs[ctr].length,
+ recs[ctr].orig_len,
+ recs[ctr].data,
+ (macs != NULL) ? &macs[ctr].mac : NULL,
+ (macs != NULL) ? &macs[ctr].alloced
+ : NULL,
+ bs,
+ pad ? (size_t)pad : macsize,
+ (EVP_CIPHER_get_flags(enc)
+ & EVP_CIPH_FLAG_AEAD_CIPHER) != 0,
+ s->ctx->libctx))
+ return 0;
+ }
}
}
}
- return ret;
+ return 1;
+}
+
+/*
+ * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
+ * which ssl3_cbc_digest_record supports.
+ */
+char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
+{
+ switch (EVP_MD_CTX_get_type(ctx)) {
+ case NID_md5:
+ case NID_sha1:
+ case NID_sha224:
+ case NID_sha256:
+ case NID_sha384:
+ case NID_sha512:
+ return 1;
+ default:
+ return 0;
+ }
}
int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
@@ -1260,24 +1330,27 @@ int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
int t;
if (sending) {
- mac_sec = &(ssl->s3->write_mac_secret[0]);
+ mac_sec = &(ssl->s3.write_mac_secret[0]);
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
hash = ssl->write_hash;
} else {
- mac_sec = &(ssl->s3->read_mac_secret[0]);
+ mac_sec = &(ssl->s3.read_mac_secret[0]);
seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer);
hash = ssl->read_hash;
}
- t = EVP_MD_CTX_size(hash);
- if (t < 0)
+ t = EVP_MD_CTX_get_size(hash);
+ if (t <= 0)
return 0;
md_size = t;
npad = (48 / md_size) * md_size;
- if (!sending &&
- EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- ssl3_cbc_record_digest_supported(hash)) {
+ if (!sending
+ && EVP_CIPHER_CTX_get_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE
+ && ssl3_cbc_record_digest_supported(hash)) {
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+ return 0;
+#else
/*
* This is a CBC-encrypted record. We must avoid leaking any
* timing-side channel information about how many blocks of data we
@@ -1305,12 +1378,13 @@ int n_ssl3_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
header[j++] = (unsigned char)(rec->length & 0xff);
/* Final param == is SSLv3 */
- if (ssl3_cbc_digest_record(hash,
+ if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash),
md, &md_size,
header, rec->input,
- rec->length + md_size, rec->orig_len,
+ rec->length, rec->orig_len,
mac_sec, md_size, 1) <= 0)
return 0;
+#endif
} else {
unsigned int md_size_u;
/* Chop the digest off the end :-) */
@@ -1354,9 +1428,12 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
int i;
EVP_MD_CTX *hmac = NULL, *mac_ctx;
unsigned char header[13];
- int stream_mac = (sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
- : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM));
+ int stream_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM)
+ : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_STREAM);
+ int tlstree_mac = sending ? (ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_TLSTREE)
+ : (ssl->mac_flags & SSL_MAC_FLAG_READ_MAC_TLSTREE);
int t;
+ int ret = 0;
if (sending) {
seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer);
@@ -1366,7 +1443,7 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
hash = ssl->read_hash;
}
- t = EVP_MD_CTX_size(hash);
+ t = EVP_MD_CTX_get_size(hash);
if (!ossl_assert(t >= 0))
return 0;
md_size = t;
@@ -1377,12 +1454,15 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
} else {
hmac = EVP_MD_CTX_new();
if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) {
- EVP_MD_CTX_free(hmac);
- return 0;
+ goto end;
}
mac_ctx = hmac;
}
+ if (!SSL_IS_DTLS(ssl) && tlstree_mac && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) {
+ goto end;
+ }
+
if (SSL_IS_DTLS(ssl)) {
unsigned char dtlsseq[8], *p = dtlsseq;
@@ -1400,52 +1480,33 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
header[11] = (unsigned char)(rec->length >> 8);
header[12] = (unsigned char)(rec->length & 0xff);
- if (!sending && !SSL_READ_ETM(ssl) &&
- EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- ssl3_cbc_record_digest_supported(mac_ctx)) {
- /*
- * This is a CBC-encrypted record. We must avoid leaking any
- * timing-side channel information about how many blocks of data we
- * are hashing because that gives an attacker a timing-oracle.
- */
- /* Final param == not SSLv3 */
- if (ssl3_cbc_digest_record(mac_ctx,
- md, &md_size,
- header, rec->input,
- rec->length + md_size, rec->orig_len,
- ssl->s3->read_mac_secret,
- ssl->s3->read_mac_secret_size, 0) <= 0) {
- EVP_MD_CTX_free(hmac);
- return 0;
- }
- } else {
- /* TODO(size_t): Convert these calls */
- if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
- || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
- || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
- EVP_MD_CTX_free(hmac);
- return 0;
- }
- }
+ if (!sending && !SSL_READ_ETM(ssl)
+ && EVP_CIPHER_CTX_get_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE
+ && ssl3_cbc_record_digest_supported(mac_ctx)) {
+ OSSL_PARAM tls_hmac_params[2], *p = tls_hmac_params;
- EVP_MD_CTX_free(hmac);
+ *p++ = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE,
+ &rec->orig_len);
+ *p++ = OSSL_PARAM_construct_end();
-#ifdef SSL_DEBUG
- fprintf(stderr, "seq=");
- {
- int z;
- for (z = 0; z < 8; z++)
- fprintf(stderr, "%02X ", seq[z]);
- fprintf(stderr, "\n");
+ if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(mac_ctx),
+ tls_hmac_params)) {
+ goto end;
+ }
}
- fprintf(stderr, "rec=");
- {
- size_t z;
- for (z = 0; z < rec->length; z++)
- fprintf(stderr, "%02X ", rec->data[z]);
- fprintf(stderr, "\n");
+
+ if (EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)) <= 0
+ || EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length) <= 0
+ || EVP_DigestSignFinal(mac_ctx, md, &md_size) <= 0) {
+ goto end;
}
-#endif
+
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "seq:\n");
+ BIO_dump_indent(trc_out, seq, 8, 4);
+ BIO_printf(trc_out, "rec:\n");
+ BIO_dump_indent(trc_out, rec->data, rec->length, 4);
+ } OSSL_TRACE_END(TLS);
if (!SSL_IS_DTLS(ssl)) {
for (i = 7; i >= 0; i--) {
@@ -1454,220 +1515,14 @@ int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int sending)
break;
}
}
-#ifdef SSL_DEBUG
- {
- unsigned int z;
- for (z = 0; z < md_size; z++)
- fprintf(stderr, "%02X ", md[z]);
- fprintf(stderr, "\n");
- }
-#endif
- return 1;
-}
-
-/*-
- * ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
- * record in |rec| by updating |rec->length| in constant time.
- *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding was valid
- * -1: otherwise.
- */
-int ssl3_cbc_remove_padding(SSL3_RECORD *rec,
- size_t block_size, size_t mac_size)
-{
- size_t padding_length;
- size_t good;
- const size_t overhead = 1 /* padding length byte */ + mac_size;
-
- /*
- * These lengths are all public so we can test them in non-constant time.
- */
- if (overhead > rec->length)
- return 0;
-
- padding_length = rec->data[rec->length - 1];
- good = constant_time_ge_s(rec->length, padding_length + overhead);
- /* SSLv3 requires that the padding is minimal. */
- good &= constant_time_ge_s(block_size, padding_length + 1);
- rec->length -= good & (padding_length + 1);
- return constant_time_select_int_s(good, 1, -1);
-}
-
-/*-
- * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
- * record in |rec| in constant time and returns 1 if the padding is valid and
- * -1 otherwise. It also removes any explicit IV from the start of the record
- * without leaking any timing about whether there was enough space after the
- * padding was removed.
- *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding was valid
- * -1: otherwise.
- */
-int tls1_cbc_remove_padding(const SSL *s,
- SSL3_RECORD *rec,
- size_t block_size, size_t mac_size)
-{
- size_t good;
- size_t padding_length, to_check, i;
- const size_t overhead = 1 /* padding length byte */ + mac_size;
- /* Check if version requires explicit IV */
- if (SSL_USE_EXPLICIT_IV(s)) {
- /*
- * These lengths are all public so we can test them in non-constant
- * time.
- */
- if (overhead + block_size > rec->length)
- return 0;
- /* We can now safely skip explicit IV */
- rec->data += block_size;
- rec->input += block_size;
- rec->length -= block_size;
- rec->orig_len -= block_size;
- } else if (overhead > rec->length)
- return 0;
-
- padding_length = rec->data[rec->length - 1];
-
- if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) &
- EVP_CIPH_FLAG_AEAD_CIPHER) {
- /* padding is already verified */
- rec->length -= padding_length + 1;
- return 1;
- }
-
- good = constant_time_ge_s(rec->length, overhead + padding_length);
- /*
- * The padding consists of a length byte at the end of the record and
- * then that many bytes of padding, all with the same value as the length
- * byte. Thus, with the length byte included, there are i+1 bytes of
- * padding. We can't check just |padding_length+1| bytes because that
- * leaks decrypted information. Therefore we always have to check the
- * maximum amount of padding possible. (Again, the length of the record
- * is public information so we can use it.)
- */
- to_check = 256; /* maximum amount of padding, inc length byte. */
- if (to_check > rec->length)
- to_check = rec->length;
-
- for (i = 0; i < to_check; i++) {
- unsigned char mask = constant_time_ge_8_s(padding_length, i);
- unsigned char b = rec->data[rec->length - 1 - i];
- /*
- * The final |padding_length+1| bytes should all have the value
- * |padding_length|. Therefore the XOR should be zero.
- */
- good &= ~(mask & (padding_length ^ b));
- }
-
- /*
- * If any of the final |padding_length+1| bytes had the wrong value, one
- * or more of the lower eight bits of |good| will be cleared.
- */
- good = constant_time_eq_s(0xff, good & 0xff);
- rec->length -= good & (padding_length + 1);
-
- return constant_time_select_int_s(good, 1, -1);
-}
-
-/*-
- * ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
- * constant time (independent of the concrete value of rec->length, which may
- * vary within a 256-byte window).
- *
- * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to
- * this function.
- *
- * On entry:
- * rec->orig_len >= md_size
- * md_size <= EVP_MAX_MD_SIZE
- *
- * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with
- * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into
- * a single or pair of cache-lines, then the variable memory accesses don't
- * actually affect the timing. CPUs with smaller cache-lines [if any] are
- * not multi-core and are not considered vulnerable to cache-timing attacks.
- */
-#define CBC_MAC_ROTATE_IN_PLACE
-
-int ssl3_cbc_copy_mac(unsigned char *out,
- const SSL3_RECORD *rec, size_t md_size)
-{
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
- unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
- unsigned char *rotated_mac;
-#else
- unsigned char rotated_mac[EVP_MAX_MD_SIZE];
-#endif
-
- /*
- * mac_end is the index of |rec->data| just after the end of the MAC.
- */
- size_t mac_end = rec->length;
- size_t mac_start = mac_end - md_size;
- size_t in_mac;
- /*
- * scan_start contains the number of bytes that we can ignore because the
- * MAC's position can only vary by 255 bytes.
- */
- size_t scan_start = 0;
- size_t i, j;
- size_t rotate_offset;
-
- if (!ossl_assert(rec->orig_len >= md_size
- && md_size <= EVP_MAX_MD_SIZE))
- return 0;
-
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
- rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
-#endif
-
- /* This information is public so it's safe to branch based on it. */
- if (rec->orig_len > md_size + 255 + 1)
- scan_start = rec->orig_len - (md_size + 255 + 1);
-
- in_mac = 0;
- rotate_offset = 0;
- memset(rotated_mac, 0, md_size);
- for (i = scan_start, j = 0; i < rec->orig_len; i++) {
- size_t mac_started = constant_time_eq_s(i, mac_start);
- size_t mac_ended = constant_time_lt_s(i, mac_end);
- unsigned char b = rec->data[i];
-
- in_mac |= mac_started;
- in_mac &= mac_ended;
- rotate_offset |= j & mac_started;
- rotated_mac[j++] |= b & in_mac;
- j &= constant_time_lt_s(j, md_size);
- }
-
- /* Now rotate the MAC */
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
- j = 0;
- for (i = 0; i < md_size; i++) {
- /* in case cache-line is 32 bytes, touch second line */
- ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
- out[j++] = rotated_mac[rotate_offset++];
- rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
- }
-#else
- memset(out, 0, md_size);
- rotate_offset = md_size - rotate_offset;
- rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
- for (i = 0; i < md_size; i++) {
- for (j = 0; j < md_size; j++)
- out[j] |= rotated_mac[i] & constant_time_eq_8_s(j, rotate_offset);
- rotate_offset++;
- rotate_offset &= constant_time_lt_s(rotate_offset, md_size);
- }
-#endif
-
- return 1;
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "md:\n");
+ BIO_dump_indent(trc_out, md, md_size, 4);
+ } OSSL_TRACE_END(TLS);
+ ret = 1;
+ end:
+ EVP_MD_CTX_free(hmac);
+ return ret;
}
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
@@ -1677,9 +1532,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
SSL_SESSION *sess;
SSL3_RECORD *rr;
int imac_size;
- size_t mac_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;
rr = RECORD_LAYER_get_rrec(&s->rlayer);
sess = s->session;
@@ -1704,8 +1561,7 @@ int dtls1_process_record(SSL *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_F_DTLS1_PROCESS_RECORD,
- SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_ENCRYPTED_LENGTH_TOO_LONG);
return 0;
}
@@ -1713,142 +1569,104 @@ int dtls1_process_record(SSL *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 (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);
+ return 0;
+ }
+ mac_size = (size_t)imac_size;
+ }
+ }
+
if (SSL_READ_ETM(s) && s->read_hash) {
unsigned char *mac;
- mac_size = EVP_MD_CTX_size(s->read_hash);
- if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
+
if (rr->orig_len < mac_size) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_LENGTH_TOO_SHORT);
return 0;
}
rr->length -= mac_size;
mac = rr->data + rr->length;
i = s->method->ssl3_enc->mac(s, 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_F_DTLS1_PROCESS_RECORD,
- SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+ SSLfatal(s, SSL_AD_BAD_RECORD_MAC,
+ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
return 0;
}
+ /*
+ * We've handled the mac now - there is no MAC inside the encrypted
+ * record
+ */
+ mac_size = 0;
}
- enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0);
+ /*
+ * Set a mark around the packet decryption attempt. This is DTLS, so
+ * bad packets are just ignored, and we don't want to leave stray
+ * errors in the queue from processing bogus junk that we ignored.
+ */
+ ERR_set_mark();
+ enc_err = s->method->ssl3_enc->enc(s, rr, 1, 0, &macbuf, mac_size);
+
/*-
* enc_err is:
- * 0: (in non-constant time) if the record is publicly invalid.
- * 1: if the padding is valid
- * -1: if the padding is invalid
+ * 0: if the record is publicly invalid, or an internal error, or AEAD
+ * decryption failed, or ETM decryption failed.
+ * 1: Success or MTE decryption failed (MAC will be randomised)
*/
if (enc_err == 0) {
+ ERR_pop_to_mark();
if (ossl_statem_in_error(s)) {
/* SSLfatal() got called */
- return 0;
+ goto end;
}
/* For DTLS we simply ignore bad packets. */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
- return 0;
- }
-#ifdef SSL_DEBUG
- printf("dec %ld\n", rr->length);
- {
- size_t z;
- for (z = 0; z < rr->length; z++)
- printf("%02X%c", rr->data[z], ((z + 1) % 16) ? ' ' : '\n');
+ goto end;
}
- printf("\n");
-#endif
+ ERR_clear_last_mark();
+ OSSL_TRACE_BEGIN(TLS) {
+ BIO_printf(trc_out, "dec %zd\n", rr->length);
+ BIO_dump_indent(trc_out, rr->data, rr->length, 4);
+ } 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_md(s->read_hash) != NULL)) {
+ 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 */
- unsigned char *mac = NULL;
- unsigned char mac_tmp[EVP_MAX_MD_SIZE];
-
- /* TODO(size_t): Convert this to do size_t properly */
- imac_size = EVP_MD_CTX_size(s->read_hash);
- if (imac_size < 0) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_LIB_EVP);
- return 0;
- }
- mac_size = (size_t)imac_size;
- if (!ossl_assert(mac_size <= EVP_MAX_MD_SIZE)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- /*
- * orig_len is the length of the record before any padding was
- * removed. This is public information, as is the MAC in use,
- * therefore we can safely process the record in a different amount
- * of time if it's too short to possibly contain a MAC.
- */
- if (rr->orig_len < mac_size ||
- /* CBC records must have a padding length byte too. */
- (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE &&
- rr->orig_len < mac_size + 1)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- SSL_R_LENGTH_TOO_SHORT);
- return 0;
- }
-
- if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) {
- /*
- * We update the length so that the TLS header bytes can be
- * constructed correctly but we need to extract the MAC in
- * constant time from within the record, without leaking the
- * contents of the padding bytes.
- */
- mac = mac_tmp;
- if (!ssl3_cbc_copy_mac(mac_tmp, rr, mac_size)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PROCESS_RECORD,
- ERR_R_INTERNAL_ERROR);
- return 0;
- }
- rr->length -= mac_size;
- } else {
- /*
- * In this case there's no padding, so |rec->orig_len| equals
- * |rec->length| and we checked that there's enough bytes for
- * |mac_size| above.
- */
- rr->length -= mac_size;
- mac = &rr->data[rr->length];
- }
i = s->method->ssl3_enc->mac(s, rr, md, 0 /* not send */ );
- if (i == 0 || mac == NULL
- || CRYPTO_memcmp(md, mac, mac_size) != 0)
- enc_err = -1;
+ if (i == 0 || macbuf.mac == NULL
+ || CRYPTO_memcmp(md, macbuf.mac, mac_size) != 0)
+ enc_err = 0;
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_size)
- enc_err = -1;
+ enc_err = 0;
}
- if (enc_err < 0) {
+ if (enc_err == 0) {
/* decryption failed, silently discard message */
rr->length = 0;
RECORD_LAYER_reset_packet_length(&s->rlayer);
- return 0;
+ goto end;
}
/* r->length is now just compressed */
if (s->expand != NULL) {
if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH) {
- SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_F_DTLS1_PROCESS_RECORD,
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW,
SSL_R_COMPRESSED_LENGTH_TOO_LONG);
- return 0;
+ goto end;
}
if (!ssl3_do_uncompress(s, rr)) {
- SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE,
- SSL_F_DTLS1_PROCESS_RECORD, SSL_R_BAD_DECOMPRESSION);
- return 0;
+ SSLfatal(s, SSL_AD_DECOMPRESSION_FAILURE, SSL_R_BAD_DECOMPRESSION);
+ goto end;
}
}
@@ -1858,19 +1676,18 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
/* 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_F_DTLS1_PROCESS_RECORD,
- SSL_R_DATA_LENGTH_TOO_LONG);
- return 0;
+ SSLfatal(s, SSL_AD_RECORD_OVERFLOW, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto end;
}
rr->off = 0;
/*-
* So at this point the following is true
- * ssl->s3->rrec.type is the type of record
- * ssl->s3->rrec.length == number of bytes in record
- * ssl->s3->rrec.off == offset to first valid byte
- * ssl->s3->rrec.data == where to take bytes from, increment
- * after use :-).
+ * ssl->s3.rrec.type is the type of record
+ * ssl->s3.rrec.length == number of bytes in record
+ * ssl->s3.rrec.off == offset to first valid byte
+ * ssl->s3.rrec.data == where to take bytes from, increment
+ * after use :-).
*/
/* we have pulled in a full packet so zero things */
@@ -1879,7 +1696,11 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
/* Mark receipt of record. */
dtls1_record_bitmap_update(s, bitmap);
- return 1;
+ ret = 1;
+ end:
+ if (macbuf.alloced)
+ OPENSSL_free(macbuf.mac);
+ return ret;
}
/*
@@ -1894,9 +1715,9 @@ int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
* It will return <= 0 if more data is needed, normally due to an error
* or non-blocking IO.
* When it finishes, one packet has been decoded and can be found in
- * ssl->s3->rrec.type - is the type of record
- * ssl->s3->rrec.data, - data
- * ssl->s3->rrec.length, - number of bytes
+ * ssl->s3.rrec.type - is the type of record
+ * ssl->s3.rrec.data - data
+ * ssl->s3.rrec.length - number of bytes
*/
/* used only by dtls1_read_bytes */
int dtls1_get_record(SSL *s)
@@ -2051,10 +1872,6 @@ int dtls1_get_record(SSL *s)
if (!BIO_dgram_is_sctp(SSL_get_rbio(s))) {
#endif
/* Check whether this is a repeat, or aged record. */
- /*
- * TODO: Does it make sense to have replay protection in epoch 0 where
- * we have no integrity negotiated yet?
- */
if (!dtls1_record_replay_check(s, bitmap)) {
rr->length = 0;
rr->read = 1;