summaryrefslogtreecommitdiff
path: root/ssl/record
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-06-10 15:34:04 +0100
committerMatt Caswell <matt@openssl.org>2020-07-06 09:26:09 +0100
commitf0237a6c6266535e105d6778ca7c34a080b88e92 (patch)
treee1bb25c344d5d25608e9a96d271dc197e67c8d78 /ssl/record
parentebacd57bee1baef6236a518a0eec3135d593f47a (diff)
downloadopenssl-new-f0237a6c6266535e105d6778ca7c34a080b88e92.tar.gz
Remove SSL dependencies from tls_pad.c
Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12288)
Diffstat (limited to 'ssl/record')
-rw-r--r--ssl/record/record_local.h17
-rw-r--r--ssl/record/ssl3_record.c30
-rw-r--r--ssl/record/tls_pad.c165
3 files changed, 135 insertions, 77 deletions
diff --git a/ssl/record/record_local.h b/ssl/record/record_local.h
index dc92732243..9047c23fd5 100644
--- a/ssl/record/record_local.h
+++ b/ssl/record/record_local.h
@@ -107,16 +107,21 @@ void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num);
int ssl3_get_record(SSL *s);
__owur int ssl3_do_compress(SSL *ssl, SSL3_RECORD *wr);
__owur int ssl3_do_uncompress(SSL *ssl, SSL3_RECORD *rr);
-__owur int ssl3_cbc_remove_padding_and_mac(SSL *s,
- SSL3_RECORD *rec,
+__owur int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
unsigned char **mac,
int *alloced,
- size_t block_size, size_t mac_size);
-__owur int tls1_cbc_remove_padding_and_mac(const SSL *s,
- SSL3_RECORD *rec,
+ size_t block_size, size_t mac_size,
+ OPENSSL_CTX *libctx);
+__owur int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
unsigned char **mac,
int *alloced,
- size_t block_size, size_t mac_size);
+ size_t block_size, size_t mac_size,
+ int aead,
+ OPENSSL_CTX *libctx);
int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
__owur int dtls1_get_record(SSL *s);
int early_data_count_ok(SSL *s, size_t length, size_t overhead, int send);
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index 55a3a3b6e6..5efa77a5b3 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -904,11 +904,14 @@ int ssl3_enc(SSL *s, SSL3_RECORD *inrecs, size_t n_recs, int sending,
}
if (!sending)
- return !ssl3_cbc_remove_padding_and_mac(s, rec,
- (mac != NULL) ? &mac->mac : NULL,
- (mac != NULL) ? &mac->alloced : NULL,
- bs,
- macsize);
+ 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);
}
return 1;
}
@@ -1166,15 +1169,28 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
if (!sending) {
for (ctr = 0; ctr < n_recs; ctr++) {
+ 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(s, &recs[ctr],
+ 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,
- macsize))
+ macsize,
+ (EVP_CIPHER_CTX_flags(s->enc_read_ctx)
+ & EVP_CIPH_FLAG_AEAD_CIPHER) != 0,
+ s->ctx->libctx))
return 0;
}
}
diff --git a/ssl/record/tls_pad.c b/ssl/record/tls_pad.c
index 2e6a6e8971..9f698483f1 100644
--- a/ssl/record/tls_pad.c
+++ b/ssl/record/tls_pad.c
@@ -8,35 +8,70 @@
*/
#include <openssl/rand.h>
+#include <openssl/evp.h>
#include "internal/constant_time.h"
#include "internal/cryptlib.h"
-#include "../ssl_local.h"
-#include "record_local.h"
-static int ssl3_cbc_copy_mac(const SSL *s,
- SSL3_RECORD *rec,
+/*
+ * This file has no dependencies on the rest of libssl because it is shared
+ * with the providers. It contains functions for low level CBC TLS padding
+ * removal. Responsibility for this lies with the cipher implementations in the
+ * providers. However there are legacy code paths in libssl which also need to
+ * do this. In time those legacy code paths can be removed and this file can be
+ * moved out of libssl.
+ */
+
+static int ssl3_cbc_copy_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
unsigned char **mac,
int *alloced,
size_t block_size,
size_t mac_size,
- size_t good);
+ size_t good,
+ OPENSSL_CTX *libctx);
+
+int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ OPENSSL_CTX *libctx);
+
+int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
+ unsigned char **mac,
+ int *alloced,
+ size_t block_size, size_t mac_size,
+ int aead,
+ OPENSSL_CTX *libctx);
/*-
* ssl3_cbc_remove_padding removes padding from the decrypted, SSLv3, CBC
- * record in |rec| by updating |rec->length| in constant time. It also extracts
- * the MAC from the underlying record.
+ * record in |recdata| by updating |reclen| in constant time. It also extracts
+ * the MAC from the underlying record and places a pointer to it in |mac|. The
+ * MAC data can either be newly allocated memory, or a pointer inside the
+ * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
+ * set to 0.
*
+ * origreclen: the original record length before any changes were made
* block_size: the block size of the cipher used to encrypt the record.
+ * mac_size: the size of the MAC to be extracted
+ * aead: 1 if an AEAD cipher is in use, or 0 otherwise
* returns:
* 0: if the record is publicly invalid.
* 1: if the record is publicly valid. If the padding removal fails then the
* MAC returned is random.
*/
-int ssl3_cbc_remove_padding_and_mac(SSL *s,
- SSL3_RECORD *rec,
+int ssl3_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
unsigned char **mac,
int *alloced,
- size_t block_size, size_t mac_size)
+ size_t block_size, size_t mac_size,
+ OPENSSL_CTX *libctx)
{
size_t padding_length;
size_t good;
@@ -45,71 +80,70 @@ int ssl3_cbc_remove_padding_and_mac(SSL *s,
/*
* These lengths are all public so we can test them in non-constant time.
*/
- if (overhead > rec->length)
+ if (overhead > *reclen)
return 0;
- padding_length = rec->data[rec->length - 1];
- good = constant_time_ge_s(rec->length, padding_length + overhead);
+ padding_length = recdata[*reclen - 1];
+ good = constant_time_ge_s(*reclen, 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);
+ *reclen -= good & (padding_length + 1);
- return ssl3_cbc_copy_mac(s, rec, mac, alloced, block_size, mac_size, good);
+ return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
+ block_size, mac_size, good, libctx);
}
/*-
- * tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
- * record in |rec| in constant time. 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, as well as extracting the embedded MAC
- * (also in constant time). For Mac-then-encrypt, if the padding is invalid then
- * a success result will occur and a randomised MAC will be returned.
+ * tls1_cbc_remove_padding_and_mac removes padding from the decrypted, TLS, CBC
+ * record in |recdata| by updating |reclen| in constant time. It also extracts
+ * the MAC from the underlying record and places a pointer to it in |mac|. The
+ * MAC data can either be newly allocated memory, or a pointer inside the
+ * |recdata| buffer. If allocated then |*alloced| is set to 1, otherwise it is
+ * set to 0.
*
+ * origreclen: the original record length before any changes were made
* block_size: the block size of the cipher used to encrypt the record.
+ * mac_size: the size of the MAC to be extracted
+ * aead: 1 if an AEAD cipher is in use, or 0 otherwise
* returns:
- * 0: if the record is publicly invalid, or an internal error
- * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
+ * 0: if the record is publicly invalid.
+ * 1: if the record is publicly valid. If the padding removal fails then the
+ * MAC returned is random.
*/
-int tls1_cbc_remove_padding_and_mac(const SSL *s,
- SSL3_RECORD *rec,
+int tls1_cbc_remove_padding_and_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
unsigned char **mac,
int *alloced,
- size_t block_size, size_t mac_size)
+ size_t block_size, size_t mac_size,
+ int aead,
+ OPENSSL_CTX *libctx)
{
- size_t good;
+ size_t good = -1;
size_t padding_length, to_check, i;
size_t overhead = ((block_size == 1) ? 0 : 1) /* padding length byte */
- + (SSL_USE_EXPLICIT_IV(s) ? block_size : 0)
+ mac_size;
/*
* These lengths are all public so we can test them in non-constant
* time.
*/
- if (overhead > rec->length)
+ if (overhead > *reclen)
return 0;
if (block_size != 1) {
- if (SSL_USE_EXPLICIT_IV(s)) {
- rec->data += block_size;
- rec->input += block_size;
- rec->length -= block_size;
- rec->orig_len -= block_size;
- overhead -= block_size;
- }
- padding_length = rec->data[rec->length - 1];
+ padding_length = recdata[*reclen - 1];
- if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(s->enc_read_ctx)) &
- EVP_CIPH_FLAG_AEAD_CIPHER) {
+ if (aead) {
/* padding is already verified and we don't need to check the MAC */
- rec->length -= padding_length + 1 + mac_size;
+ *reclen -= padding_length + 1 + mac_size;
*mac = NULL;
*alloced = 0;
return 1;
}
- good = constant_time_ge_s(rec->length, overhead + padding_length);
+ good = constant_time_ge_s(*reclen, 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
@@ -120,12 +154,12 @@ int tls1_cbc_remove_padding_and_mac(const SSL *s,
* 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;
+ if (to_check > *reclen)
+ to_check = *reclen;
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];
+ unsigned char b = recdata[*reclen - 1 - i];
/*
* The final |padding_length+1| bytes should all have the value
* |padding_length|. Therefore the XOR should be zero.
@@ -138,20 +172,21 @@ int tls1_cbc_remove_padding_and_mac(const SSL *s,
* 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);
+ *reclen -= good & (padding_length + 1);
}
- return ssl3_cbc_copy_mac(s, rec, mac, alloced, block_size, mac_size, good);
+ return ssl3_cbc_copy_mac(reclen, origreclen, recdata, mac, alloced,
+ block_size, mac_size, good, libctx);
}
/*-
- * 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_copy_mac copies |md_size| bytes from the end of the record in
+ * |recdata| to |*mac| in constant time (independent of the concrete value of
+ * the record length |reclen|, which may vary within a 256-byte window).
*
* On entry:
- * rec->orig_len >= md_size
- * md_size <= EVP_MAX_MD_SIZE
+ * origreclen >= mac_size
+ * mac_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
@@ -161,13 +196,15 @@ int tls1_cbc_remove_padding_and_mac(const SSL *s,
*/
#define CBC_MAC_ROTATE_IN_PLACE
-static int ssl3_cbc_copy_mac(const SSL *s,
- SSL3_RECORD *rec,
+static int ssl3_cbc_copy_mac(size_t *reclen,
+ size_t origreclen,
+ unsigned char *recdata,
unsigned char **mac,
int *alloced,
size_t block_size,
size_t mac_size,
- size_t good)
+ size_t good,
+ OPENSSL_CTX *libctx)
{
#if defined(CBC_MAC_ROTATE_IN_PLACE)
unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
@@ -179,9 +216,9 @@ static int ssl3_cbc_copy_mac(const SSL *s,
unsigned char *out;
/*
- * mac_end is the index of |rec->data| just after the end of the MAC.
+ * mac_end is the index of |recdata| just after the end of the MAC.
*/
- size_t mac_end = rec->length;
+ size_t mac_end = *reclen;
size_t mac_start = mac_end - mac_size;
size_t in_mac;
/*
@@ -192,7 +229,7 @@ static int ssl3_cbc_copy_mac(const SSL *s,
size_t i, j;
size_t rotate_offset;
- if (!ossl_assert(rec->orig_len >= mac_size
+ if (!ossl_assert(origreclen >= mac_size
&& mac_size <= EVP_MAX_MD_SIZE))
return 0;
@@ -204,19 +241,19 @@ static int ssl3_cbc_copy_mac(const SSL *s,
return 1;
}
- rec->length -= mac_size;
+ *reclen -= mac_size;
if (block_size == 1) {
/* There's no padding so the position of the MAC is fixed */
if (mac != NULL)
- *mac = &rec->data[rec->length];
+ *mac = &recdata[*reclen];
if (alloced != NULL)
*alloced = 0;
return 1;
}
/* Create the random MAC we will emit if padding is bad */
- if (!RAND_bytes_ex(s->ctx->libctx, randmac, mac_size))
+ if (!RAND_bytes_ex(libctx, randmac, mac_size))
return 0;
if (!ossl_assert(mac != NULL && alloced != NULL))
@@ -231,16 +268,16 @@ static int ssl3_cbc_copy_mac(const SSL *s,
#endif
/* This information is public so it's safe to branch based on it. */
- if (rec->orig_len > mac_size + 255 + 1)
- scan_start = rec->orig_len - (mac_size + 255 + 1);
+ if (origreclen > mac_size + 255 + 1)
+ scan_start = origreclen - (mac_size + 255 + 1);
in_mac = 0;
rotate_offset = 0;
memset(rotated_mac, 0, mac_size);
- for (i = scan_start, j = 0; i < rec->orig_len; i++) {
+ for (i = scan_start, j = 0; i < origreclen; 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];
+ unsigned char b = recdata[i];
in_mac |= mac_started;
in_mac &= mac_ended;