diff options
Diffstat (limited to 'ssl/record')
-rw-r--r-- | ssl/record/methods/build.info | 12 | ||||
-rw-r--r-- | ssl/record/methods/recmethod_local.h | 142 | ||||
-rw-r--r-- | ssl/record/methods/ssl3_cbc.c | 504 | ||||
-rw-r--r-- | ssl/record/methods/ssl3_meth.c | 322 | ||||
-rw-r--r-- | ssl/record/methods/tls13_meth.c | 198 | ||||
-rw-r--r-- | ssl/record/methods/tls1_meth.c | 599 | ||||
-rw-r--r-- | ssl/record/methods/tls_common.c (renamed from ssl/record/methods/tlsrecord.c) | 1261 | ||||
-rw-r--r-- | ssl/record/methods/tlsany_meth.c | 50 | ||||
-rw-r--r-- | ssl/record/ssl3_record.c | 28 |
9 files changed, 1857 insertions, 1259 deletions
diff --git a/ssl/record/methods/build.info b/ssl/record/methods/build.info index 430a3a1fd5..dfe7d9c808 100644 --- a/ssl/record/methods/build.info +++ b/ssl/record/methods/build.info @@ -1,4 +1,10 @@ -LIBS=../libssl - SOURCE[../../../libssl]=\ - tlsrecord.c + tls_common.c ssl3_meth.c tls1_meth.c tls13_meth.c tlsany_meth.c + +# For shared builds we need to include the sources needed in providers +# (ssl3_cbc.c) in libssl as well. +IF[{- !$disabled{'deprecated-3.0'} -}] + SHARED_SOURCE[../../../libssl]=ssl3_cbc.c +ENDIF + +SOURCE[../../../providers/libdefault.a ../../../providers/libfips.a]=ssl3_cbc.c diff --git a/ssl/record/methods/recmethod_local.h b/ssl/record/methods/recmethod_local.h new file mode 100644 index 0000000000..ec4001587d --- /dev/null +++ b/ssl/record/methods/recmethod_local.h @@ -0,0 +1,142 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/bio.h> +#include <openssl/ssl.h> +#include <openssl/err.h> +#include "../../ssl_local.h" +#include "../record_local.h" + +/* Protocol version specific function pointers */ +struct record_functions_st +{ + int (*set_crypto_state)(OSSL_RECORD_LAYER *rl, int level, + 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, + const EVP_MD *md, + const SSL_COMP *comp, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s); + int (*cipher)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, + int sending, SSL_MAC_BUF *macs, size_t macsize, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s); + int (*mac)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, + int sending, /* TODO(RECLAYER): Remove me */SSL_CONNECTION *ssl); +}; + +struct ossl_record_layer_st +{ + OSSL_LIB_CTX *libctx; + const char *propq; + int isdtls; + int version; + int role; + int direction; + BIO *bio; + /* Types match the equivalent structures in the SSL object */ + uint64_t options; + /* + * TODO(RECLAYER): Should we take the opportunity to make this uint64_t + * even though upper layer continue to use uint32_t? + */ + uint32_t mode; + + /* read IO goes into here */ + SSL3_BUFFER rbuf; + /* each decoded record goes in here */ + SSL3_RECORD rrec[SSL_MAX_PIPELINES]; + + /* How many records have we got available in the rrec bufer */ + size_t num_recs; + + /* The record number in the rrec buffer that can be read next */ + size_t curr_rec; + + /* The number of records that have been released via tls_release_record */ + size_t num_released; + + /* Set to true if this is the first record in a connection */ + unsigned int is_first_record; + + /* where we are when reading */ + int rstate; + + /* used internally to point at a raw packet */ + unsigned char *packet; + size_t packet_length; + + int alert; + + /* + * Read as many input bytes as possible (for + * non-blocking reads) + * TODO(RECLAYER): Why isn't this just an option? + */ + int read_ahead; + + /* The number of consecutive empty records we have received */ + size_t empty_record_count; + + /* cryptographic state */ + EVP_CIPHER_CTX *enc_read_ctx; + /* TLSv1.3 static read IV */ + unsigned char read_iv[EVP_MAX_IV_LENGTH]; + /* used for mac generation */ + EVP_MD_CTX *read_hash; + /* uncompress */ + COMP_CTX *expand; + + /* Only used by SSLv3 */ + unsigned char mac_secret[EVP_MAX_MD_SIZE]; + + /* TLSv1.3 static IV */ + unsigned char iv[EVP_MAX_IV_LENGTH]; + + size_t taglen; + + /* Function pointers for version specific functions */ + /* Function pointers for version specific functions */ + struct record_functions_st *funcs; +}; + +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; + +void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason, + const char *fmt, ...); + +# define RLAYERfatal(rl, al, r) RLAYERfatal_data((rl), (al), (r), NULL) +# define RLAYERfatal_data \ + (ERR_new(), \ + ERR_set_debug(OPENSSL_FILE, OPENSSL_LINE, OPENSSL_FUNC), \ + ossl_rlayer_fatal) + +int ossl_set_tls_provider_parameters(OSSL_RECORD_LAYER *rl, + EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *ciph, + const EVP_MD *md, + SSL_CONNECTION *s); +/* ssl3_cbc.c */ +__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); +__owur int ssl3_cbc_digest_record(const EVP_MD *md, + unsigned char *md_out, + size_t *md_out_size, + const unsigned char *header, + const unsigned char *data, + size_t data_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + size_t mac_secret_length, char is_sslv3); diff --git a/ssl/record/methods/ssl3_cbc.c b/ssl/record/methods/ssl3_cbc.c new file mode 100644 index 0000000000..a254489769 --- /dev/null +++ b/ssl/record/methods/ssl3_cbc.c @@ -0,0 +1,504 @@ +/* + * Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * This file has no dependencies on the rest of libssl because it is shared + * with the providers. It contains functions for low level MAC calculations. + * Responsibility for this lies with the HMAC implementation 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. + */ + + +/* + * MD5 and SHA-1 low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +#include "recmethod_local.h" + +#include "internal/constant_time.h" +#include "internal/cryptlib.h" + +#include <openssl/evp.h> +#ifndef FIPS_MODULE +# include <openssl/md5.h> +#endif +#include <openssl/sha.h> + +# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +# define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +# define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ + *((c)++)=(unsigned char)(((l)>>48)&0xff), \ + *((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* + * MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's + * length field. (SHA-384/512 have 128-bit length.) + */ +#define MAX_HASH_BIT_COUNT_BYTES 16 + +/* + * MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support. + * Currently SHA-384/512 has a 128-byte block size and that's the largest + * supported by TLS.) + */ +#define MAX_HASH_BLOCK_SIZE 128 + +#ifndef FIPS_MODULE +/* + * u32toLE serializes an unsigned, 32-bit number (n) as four bytes at (p) in + * little-endian order. The value of p is advanced by four. + */ +# define u32toLE(n, p) \ + (*((p)++)=(unsigned char)(n), \ + *((p)++)=(unsigned char)(n>>8), \ + *((p)++)=(unsigned char)(n>>16), \ + *((p)++)=(unsigned char)(n>>24)) + +/* + * These functions serialize the state of a hash and thus perform the + * standard "final" operation without adding the padding and length that such + * a function typically does. + */ +static void tls1_md5_final_raw(void *ctx, unsigned char *md_out) +{ + MD5_CTX *md5 = ctx; + u32toLE(md5->A, md_out); + u32toLE(md5->B, md_out); + u32toLE(md5->C, md_out); + u32toLE(md5->D, md_out); +} +#endif /* FIPS_MODULE */ + +static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out) +{ + SHA_CTX *sha1 = ctx; + l2n(sha1->h0, md_out); + l2n(sha1->h1, md_out); + l2n(sha1->h2, md_out); + l2n(sha1->h3, md_out); + l2n(sha1->h4, md_out); +} + +static void tls1_sha256_final_raw(void *ctx, unsigned char *md_out) +{ + SHA256_CTX *sha256 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) { + l2n(sha256->h[i], md_out); + } +} + +static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out) +{ + SHA512_CTX *sha512 = ctx; + unsigned i; + + for (i = 0; i < 8; i++) { + l2n8(sha512->h[i], md_out); + } +} + +#undef LARGEST_DIGEST_CTX +#define LARGEST_DIGEST_CTX SHA512_CTX + +/*- + * ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS + * record. + * + * ctx: the EVP_MD_CTX from which we take the hash function. + * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. + * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. + * md_out_size: if non-NULL, the number of output bytes is written here. + * header: the 13-byte, TLS record header. + * data: the record data itself, less any preceding explicit IV. + * data_size: the secret, reported length of the data once the MAC and padding + * has been removed. + * data_plus_mac_plus_padding_size: the public length of the whole + * record, including MAC and padding. + * is_sslv3: non-zero if we are to use SSLv3. Otherwise, TLS. + * + * On entry: we know that data is data_plus_mac_plus_padding_size in length + * Returns 1 on success or 0 on error + */ +int ssl3_cbc_digest_record(const EVP_MD *md, + unsigned char *md_out, + size_t *md_out_size, + const unsigned char *header, + const unsigned char *data, + size_t data_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + size_t mac_secret_length, char is_sslv3) +{ + union { + OSSL_UNION_ALIGN; + unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; + } md_state; + void (*md_final_raw) (void *ctx, unsigned char *md_out); + void (*md_transform) (void *ctx, const unsigned char *block); + size_t md_size, md_block_size = 64; + size_t sslv3_pad_length = 40, header_length, variance_blocks, + len, max_mac_bytes, num_blocks, + num_starting_blocks, k, mac_end_offset, c, index_a, index_b; + size_t bits; /* at most 18 bits */ + unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmac_pad is the masked HMAC key. */ + unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE]; + unsigned char first_block[MAX_HASH_BLOCK_SIZE]; + unsigned char mac_out[EVP_MAX_MD_SIZE]; + size_t i, j; + unsigned md_out_size_u; + EVP_MD_CTX *md_ctx = NULL; + /* + * mdLengthSize is the number of bytes in the length field that + * terminates * the hash. + */ + size_t md_length_size = 8; + char length_is_big_endian = 1; + int ret = 0; + + /* + * This is a, hopefully redundant, check that allows us to forget about + * many possible overflows later in this function. + */ + if (!ossl_assert(data_plus_mac_plus_padding_size < 1024 * 1024)) + return 0; + + if (EVP_MD_is_a(md, "MD5")) { +#ifdef FIPS_MODULE + return 0; +#else + if (MD5_Init((MD5_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_md5_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))MD5_Transform; + md_size = 16; + sslv3_pad_length = 48; + length_is_big_endian = 0; +#endif + } else if (EVP_MD_is_a(md, "SHA1")) { + if (SHA1_Init((SHA_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha1_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA1_Transform; + md_size = 20; + } else if (EVP_MD_is_a(md, "SHA2-224")) { + if (SHA224_Init((SHA256_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha256_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA256_Transform; + md_size = 224 / 8; + } else if (EVP_MD_is_a(md, "SHA2-256")) { + if (SHA256_Init((SHA256_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha256_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA256_Transform; + md_size = 32; + } else if (EVP_MD_is_a(md, "SHA2-384")) { + if (SHA384_Init((SHA512_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha512_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA512_Transform; + md_size = 384 / 8; + md_block_size = 128; + md_length_size = 16; + } else if (EVP_MD_is_a(md, "SHA2-512")) { + if (SHA512_Init((SHA512_CTX *)md_state.c) <= 0) + return 0; + md_final_raw = tls1_sha512_final_raw; + md_transform = + (void (*)(void *ctx, const unsigned char *block))SHA512_Transform; + md_size = 64; + md_block_size = 128; + md_length_size = 16; + } else { + /* + * ssl3_cbc_record_digest_supported should have been called first to + * check that the hash function is supported. + */ + if (md_out_size != NULL) + *md_out_size = 0; + return ossl_assert(0); + } + + if (!ossl_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES) + || !ossl_assert(md_block_size <= MAX_HASH_BLOCK_SIZE) + || !ossl_assert(md_size <= EVP_MAX_MD_SIZE)) + return 0; + + header_length = 13; + if (is_sslv3) { + header_length = mac_secret_length + sslv3_pad_length + 8 /* sequence + * number */ + + 1 /* record type */ + + 2 /* record length */ ; + } + + /* + * variance_blocks is the number of blocks of the hash that we have to + * calculate in constant time because they could be altered by the + * padding value. In SSLv3, the padding must be minimal so the end of + * the plaintext varies by, at most, 15+20 = 35 bytes. (We conservatively + * assume that the MAC size varies from 0..20 bytes.) In case the 9 bytes + * of hash termination (0x80 + 64-bit length) don't fit in the final + * block, we say that the final two blocks can vary based on the padding. + * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not + * required to be minimal. Therefore we say that the final |variance_blocks| + * blocks can + * vary based on the padding. Later in the function, if the message is + * short and there obviously cannot be this many blocks then + * variance_blocks can be reduced. + */ + variance_blocks = is_sslv3 ? 2 : ( ((255 + 1 + md_size + md_block_size - 1) / md_block_size) + 1); + /* + * From now on we're dealing with the MAC, which conceptually has 13 + * bytes of `header' before the start of the data (TLS) or 71/75 bytes + * (SSLv3) + */ + len = data_plus_mac_plus_padding_size + header_length; + /* + * max_mac_bytes contains the maximum bytes of bytes in the MAC, + * including * |header|, assuming that there's no padding. + */ + max_mac_bytes = len - md_size - 1; + /* num_blocks is the maximum number of hash blocks. */ + num_blocks = + (max_mac_bytes + 1 + md_length_size + md_block_size - + 1) / md_block_size; + /* + * In order to calculate the MAC in constant time we have to handle the + * final blocks specially because the padding value could cause the end + * to appear somewhere in the final |variance_blocks| blocks and we can't + * leak where. However, |num_starting_blocks| worth of data can be hashed + * right away because no padding value can affect whether they are + * plaintext. + */ + num_starting_blocks = 0; + /* + * k is the starting byte offset into the conceptual header||data where + * we start processing. + */ + k = 0; + /* + * mac_end_offset is the index just past the end of the data to be MACed. + */ + mac_end_offset = data_size + header_length; + /* + * c is the index of the 0x80 byte in the final hash block that contains + * application data. + */ + c = mac_end_offset % md_block_size; + /* + * index_a is the hash block number that contains the 0x80 terminating + * value. + */ + index_a = mac_end_offset / md_block_size; + /* + * index_b is the hash block number that contains the 64-bit hash length, + * in bits. + */ + index_b = (mac_end_offset + md_length_size) / md_block_size; + /* + * bits is the hash-length in bits. It includes the additional hash block + * for the masked HMAC key, or whole of |header| in the case of SSLv3. + */ + + /* + * For SSLv3, if we're going to have any starting blocks then we need at + * least two because the header is larger than a single block. + */ + if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) { + num_starting_blocks = num_blocks - variance_blocks; + k = md_block_size * num_starting_blocks; + } + + bits = 8 * mac_end_offset; + if (!is_sslv3) { + /* + * Compute the initial HMAC block. For SSLv3, the padding and secret + * bytes are included in |header| because they take more than a + * single block. + */ + bits += 8 * md_block_size; + memset(hmac_pad, 0, md_block_size); + if (!ossl_assert(mac_secret_length <= sizeof(hmac_pad))) + return 0; + memcpy(hmac_pad, mac_secret, mac_secret_length); + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x36; + + md_transform(md_state.c, hmac_pad); + } + + if (length_is_big_endian) { + memset(length_bytes, 0, md_length_size - 4); + length_bytes[md_length_size - 4] = (unsigned char)(bits >> 24); + length_bytes[md_length_size - 3] = (unsigned char)(bits >> 16); + length_bytes[md_length_size - 2] = (unsigned char)(bits >> 8); + length_bytes[md_length_size - 1] = (unsigned char)bits; + } else { + memset(length_bytes, 0, md_length_size); + length_bytes[md_length_size - 5] = (unsigned char)(bits >> 24); + length_bytes[md_length_size - 6] = (unsigned char)(bits >> 16); + length_bytes[md_length_size - 7] = (unsigned char)(bits >> 8); + length_bytes[md_length_size - 8] = (unsigned char)bits; + } + + if (k > 0) { + if (is_sslv3) { + size_t overhang; + + /* + * The SSLv3 header is larger than a single block. overhang is + * the number of bytes beyond a single block that the header + * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no + * ciphersuites in SSLv3 that are not SHA1 or MD5 based and + * therefore we can be confident that the header_length will be + * greater than |md_block_size|. However we add a sanity check just + * in case + */ + if (header_length <= md_block_size) { + /* Should never happen */ + return 0; + } + overhang = header_length - md_block_size; + md_transform(md_state.c, header); + memcpy(first_block, header + md_block_size, overhang); + memcpy(first_block + overhang, data, md_block_size - overhang); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size - 1; i++) + md_transform(md_state.c, data + md_block_size * i - overhang); + } else { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block + 13, data, md_block_size - 13); + md_transform(md_state.c, first_block); + for (i = 1; i < k / md_block_size; i++) + md_transform(md_state.c, data + md_block_size * i - 13); + } + } + + memset(mac_out, 0, sizeof(mac_out)); + + /* + * We now process the final hash blocks. For each block, we construct it + * in constant time. If the |i==index_a| then we'll include the 0x80 + * bytes and zero pad etc. For each block we selectively copy it, in + * constant time, to |mac_out|. + */ + for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks; + i++) { + unsigned char block[MAX_HASH_BLOCK_SIZE]; + unsigned char is_block_a = constant_time_eq_8_s(i, index_a); + unsigned char is_block_b = constant_time_eq_8_s(i, index_b); + for (j = 0; j < md_block_size; j++) { + unsigned char b = 0, is_past_c, is_past_cp1; + if (k < header_length) + b = header[k]; + else if (k < data_plus_mac_plus_padding_size + header_length) + b = data[k - header_length]; + k++; + + is_past_c = is_block_a & constant_time_ge_8_s(j, c); + is_past_cp1 = is_block_a & constant_time_ge_8_s(j, c + 1); + /* + * If this is the block containing the end of the application + * data, and we are at the offset for the 0x80 value, then + * overwrite b with 0x80. + */ + b = constant_time_select_8(is_past_c, 0x80, b); + /* + * If this block contains the end of the application data + * and we're past the 0x80 value then just write zero. + */ + b = b & ~is_past_cp1; + /* + * If this is index_b (the final block), but not index_a (the end + * of the data), then the 64-bit length didn't fit into index_a + * and we're having to add an extra block of zeros. + */ + b &= ~is_block_b | is_block_a; + + /* + * The final bytes of one of the blocks contains the length. + */ + if (j >= md_block_size - md_length_size) { + /* If this is index_b, write a length byte. */ + b = constant_time_select_8(is_block_b, + length_bytes[j - + (md_block_size - + md_length_size)], b); + } + block[j] = b; + } + + md_transform(md_state.c, block); + md_final_raw(md_state.c, block); + /* If this is index_b, copy the hash value to |mac_out|. */ + for (j = 0; j < md_size; j++) + mac_out[j] |= block[j] & is_block_b; + } + + md_ctx = EVP_MD_CTX_new(); + if (md_ctx == NULL) + goto err; + + if (EVP_DigestInit_ex(md_ctx, md, NULL /* engine */ ) <= 0) + goto err; + if (is_sslv3) { + /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */ + memset(hmac_pad, 0x5c, sslv3_pad_length); + + if (EVP_DigestUpdate(md_ctx, mac_secret, mac_secret_length) <= 0 + || EVP_DigestUpdate(md_ctx, hmac_pad, sslv3_pad_length) <= 0 + || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) + goto err; + } else { + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x6a; + + if (EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size) <= 0 + || EVP_DigestUpdate(md_ctx, mac_out, md_size) <= 0) + goto err; + } + ret = EVP_DigestFinal(md_ctx, md_out, &md_out_size_u); + if (ret && md_out_size) + *md_out_size = md_out_size_u; + + ret = 1; + err: + EVP_MD_CTX_free(md_ctx); + return ret; +} diff --git a/ssl/record/methods/ssl3_meth.c b/ssl/record/methods/ssl3_meth.c new file mode 100644 index 0000000000..8ad3e3221d --- /dev/null +++ b/ssl/record/methods/ssl3_meth.c @@ -0,0 +1,322 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/evp.h> +#include <openssl/core_names.h> +#include "../../ssl_local.h" +#include "../record_local.h" +#include "recmethod_local.h" + +/* TODO(RECLAYER): Handle OPENSSL_NO_COMP */ +static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, + 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, + const EVP_MD *md, + const SSL_COMP *comp, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s) +{ + EVP_CIPHER_CTX *ciph_ctx; + + if (md == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + if ((rl->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); + return 0; + } + ciph_ctx = rl->enc_read_ctx; + + rl->read_hash = EVP_MD_CTX_new(); + if (rl->read_hash == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_COMP + if (comp != NULL) { + rl->expand = COMP_CTX_new(comp->method); + if (rl->expand == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, + SSL_R_COMPRESSION_LIBRARY_ERROR); + return 0; + } + } +#endif + + if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, iv)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (EVP_CIPHER_get0_provider(ciph) != NULL + && !ossl_set_tls_provider_parameters(rl, ciph_ctx, ciph, md, s)) { + /* RLAYERfatal already called */ + return 0; + } + + if (mackeylen > sizeof(rl->mac_secret)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(rl->mac_secret, mackey, mackeylen); + + return 1; +} + +/* + * ssl3_cipher encrypts/decrypts |n_recs| records in |inrecs|. Calls RLAYERfatal + * on internal error, but not otherwise. It is the responsibility of the caller + * to report a bad_record_mac + * + * Returns: + * 0: if the record is publicly invalid, or an internal error + * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised) + */ +static int ssl3_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs, + int sending, SSL_MAC_BUF *mac, size_t macsize, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) +{ + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + size_t l, i; + size_t bs; + const EVP_CIPHER *enc; + int provided; + + rec = inrecs; + /* + * We shouldn't ever be called with more than one record in the SSLv3 case + */ + if (n_recs != 1) + return 0; + if (sending) { + ds = s->enc_write_ctx; + if (s->enc_write_ctx == NULL) + enc = NULL; + else + enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx); + } else { + ds = rl->enc_read_ctx; + if (rl->enc_read_ctx == NULL) + enc = NULL; + else + enc = EVP_CIPHER_CTX_get0_cipher(rl->enc_read_ctx); + } + + provided = (EVP_CIPHER_get0_provider(enc) != NULL); + + l = rec->length; + bs = EVP_CIPHER_CTX_get_block_size(ds); + + /* COMPRESS */ + + 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 */ + l += i; + /* + * the last of these zero bytes will be overwritten with the + * padding length. + */ + memset(&rec->input[rec->length], 0, i); + rec->length += i; + rec->input[l - 1] = (unsigned char)(i - 1); + } + + if (!sending) { + if (l == 0 || l % bs != 0) { + /* Publicly invalid */ + return 0; + } + /* otherwise, rec->length >= bs */ + } + + if (provided) { + int outlen; + + 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 */ + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + } else { + if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) { + /* Shouldn't happen */ + RLAYERfatal(rl, 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, + rl->libctx); + } + + return 1; +} + +static const unsigned char ssl3_pad_1[48] = { + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 +}; + +static const unsigned char ssl3_pad_2[48] = { + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c +}; + +static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, + int sending, SSL_CONNECTION *ssl) +{ + unsigned char *mac_sec, *seq; + const EVP_MD_CTX *hash; + unsigned char *p, rec_char; + size_t md_size; + size_t npad; + int t; + + if (sending) { + mac_sec = &(ssl->s3.write_mac_secret[0]); + seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer); + hash = ssl->write_hash; + } else { + mac_sec = &(rl->mac_secret[0]); + seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer); + hash = rl->read_hash; + } + + 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_get_mode(rl->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 + * are hashing because that gives an attacker a timing-oracle. + */ + + /*- + * npad is, at most, 48 bytes and that's with MD5: + * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. + * + * With SHA-1 (the largest hash speced for SSLv3) the hash size + * goes up 4, but npad goes down by 8, resulting in a smaller + * total size. + */ + unsigned char header[75]; + size_t j = 0; + memcpy(header + j, mac_sec, md_size); + j += md_size; + memcpy(header + j, ssl3_pad_1, npad); + j += npad; + memcpy(header + j, seq, 8); + j += 8; + header[j++] = rec->type; + header[j++] = (unsigned char)(rec->length >> 8); + header[j++] = (unsigned char)(rec->length & 0xff); + + /* Final param == is SSLv3 */ + if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash), + md, &md_size, + header, rec->input, + 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 :-) */ + EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); + + if (md_ctx == NULL) + return 0; + + rec_char = rec->type; + p = md; + s2n(rec->length, p); + if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 + || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 + || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0 + || EVP_DigestUpdate(md_ctx, seq, 8) <= 0 + || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0 + || EVP_DigestUpdate(md_ctx, md, 2) <= 0 + || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0 + || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0 + || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 + || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 + || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0 + || EVP_DigestUpdate(md_ctx, md, md_size) <= 0 + || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) { + EVP_MD_CTX_free(md_ctx); + return 0; + } + + EVP_MD_CTX_free(md_ctx); + } + + ssl3_record_sequence_update(seq); + return 1; +} + +struct record_functions_st ssl_3_0_funcs = { + ssl3_set_crypto_state, + ssl3_cipher, + ssl3_mac +}; diff --git a/ssl/record/methods/tls13_meth.c b/ssl/record/methods/tls13_meth.c new file mode 100644 index 0000000000..aaee322ae7 --- /dev/null +++ b/ssl/record/methods/tls13_meth.c @@ -0,0 +1,198 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/evp.h> +#include <openssl/core_names.h> +#include "../../ssl_local.h" +#include "../record_local.h" +#include "recmethod_local.h" + +static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, + 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, + const EVP_MD *md, + const SSL_COMP *comp, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s) +{ + EVP_CIPHER_CTX *ciph_ctx; + int mode; + + if (ivlen > sizeof(rl->iv)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(rl->iv, iv, ivlen); + + ciph_ctx = rl->enc_read_ctx = EVP_CIPHER_CTX_new(); + if (ciph_ctx == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); + return 0; + } + + RECORD_LAYER_reset_read_sequence(&s->rlayer); + rl->taglen = taglen; + + mode = EVP_CIPHER_get_mode(ciph); + + if (EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, NULL, NULL) <= 0 + || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL) <= 0 + || (mode == EVP_CIPH_CCM_MODE + && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, NULL) <= 0) + || EVP_DecryptInit_ex(ciph_ctx, NULL, NULL, key, NULL) <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB); + return 0; + } + + return 1; +} + +static int tls13_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, + int sending, SSL_MAC_BUF *mac, size_t macsize, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) +{ + EVP_CIPHER_CTX *ctx; + unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; + size_t ivlen, offset, loop, hdrlen; + unsigned char *staticiv; + unsigned char *seq; + int lenu, lenf; + SSL3_RECORD *rec = &recs[0]; + WPACKET wpkt; + const EVP_CIPHER *cipher; + int mode; + + if (n_recs != 1) { + /* Should not happen */ + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (sending) { + ctx = s->enc_write_ctx; + staticiv = s->write_iv; + seq = RECORD_LAYER_get_write_sequence(&s->rlayer); + } else { + ctx = rl->enc_read_ctx; + staticiv = rl->iv; + seq = RECORD_LAYER_get_read_sequence(&s->rlayer); + } + + cipher = EVP_CIPHER_CTX_get0_cipher(ctx); + if (cipher == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + mode = EVP_CIPHER_get_mode(cipher); + + /* + * If we're sending an alert and ctx != NULL then we must be forcing + * plaintext alerts. If we're reading and ctx != NULL then we allow + * plaintext alerts at certain points in the handshake. If we've got this + * far then we have already validated that a plaintext alert is ok here. + */ + if (ctx == NULL || rec->type == SSL3_RT_ALERT) { + memmove(rec->data, rec->input, rec->length); + rec->input = rec->data; + return 1; + } + + ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + + if (!sending) { + /* + * Take off tag. There must be at least one byte of content type as + * well as the tag + */ + if (rec->length < rl->taglen + 1) + return 0; + rec->length -= rl->taglen; + } + + /* Set up IV */ + if (ivlen < SEQ_NUM_SIZE) { + /* Should not happen */ + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + offset = ivlen - SEQ_NUM_SIZE; + memcpy(iv, staticiv, offset); + for (loop = 0; loop < SEQ_NUM_SIZE; loop++) + iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; + + /* Increment the sequence counter */ + for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { + ++seq[loop - 1]; + if (seq[loop - 1] != 0) + break; + } + if (loop == 0) { + /* Sequence has wrapped */ + return 0; + } + + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 + || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + rl->taglen, + rec->data + rec->length) <= 0)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* Set up the AAD */ + if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) + || !WPACKET_put_bytes_u8(&wpkt, rec->type) + || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version) + || !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen) + || !WPACKET_get_total_written(&wpkt, &hdrlen) + || hdrlen != SSL3_RT_HEADER_LENGTH + || !WPACKET_finish(&wpkt)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + WPACKET_cleanup(&wpkt); + return 0; + } + + /* + * For CCM we must explicitly set the total plaintext length before we add + * any AAD. + */ + if ((mode == EVP_CIPH_CCM_MODE + && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, + (unsigned int)rec->length) <= 0) + || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, + sizeof(recheader)) <= 0 + || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, + (unsigned int)rec->length) <= 0 + || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 + || (size_t)(lenu + lenf) != rec->length) { + return 0; + } + if (sending) { + /* Add the tag */ + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen, + rec->data + rec->length) <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + rec->length += rl->taglen; + } + + return 1; +} + +struct record_functions_st tls_1_3_funcs = { + tls13_set_crypto_state, + tls13_cipher, + NULL +}; diff --git a/ssl/record/methods/tls1_meth.c b/ssl/record/methods/tls1_meth.c new file mode 100644 index 0000000000..9a77eec492 --- /dev/null +++ b/ssl/record/methods/tls1_meth.c @@ -0,0 +1,599 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/evp.h> +#include <openssl/core_names.h> +#include <openssl/rand.h> +#include "../../ssl_local.h" +#include "../record_local.h" +#include "recmethod_local.h" + +/* TODO(RECLAYER): Handle OPENSSL_NO_COMP */ +static int tls1_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, + 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, + const EVP_MD *md, + const SSL_COMP *comp, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s) +{ + EVP_CIPHER_CTX *ciph_ctx; + EVP_PKEY *mac_key; + + if (level != OSSL_RECORD_PROTECTION_LEVEL_APPLICATION) + return 0; + + if (s->ext.use_etm) + s->s3.flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + else + s->s3.flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; + + if (s->s3.tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) + s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; + else + s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; + + if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE) + s->mac_flags |= SSL_MAC_FLAG_READ_MAC_TLSTREE; + else + s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE; + + if ((rl->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); + return 0; + } + + ciph_ctx = rl->enc_read_ctx; + + rl->read_hash = EVP_MD_CTX_new(); + if (rl->read_hash == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } +#ifndef OPENSSL_NO_COMP + if (comp != NULL) { + rl->expand = COMP_CTX_new(comp->method); + if (rl->expand == NULL) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, + SSL_R_COMPRESSION_LIBRARY_ERROR); + return 0; + } + } +#endif + /* + * this is done by dtls1_reset_seq_numbers for DTLS + */ + if (!rl->isdtls) + RECORD_LAYER_reset_read_sequence(&s->rlayer); + + /* + * If we have an AEAD Cipher, then there is no separate MAC, so we can skip + * setting up the MAC key. + */ + if (!(EVP_CIPHER_get_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER)) { + if (mactype == EVP_PKEY_HMAC) { + mac_key = EVP_PKEY_new_raw_private_key_ex(rl->libctx, "HMAC", + rl->propq, mackey, + mackeylen); + } else { + /* + * If its not HMAC then the only other types of MAC we support are + * the GOST MACs, so we need to use the old style way of creating + * a MAC key. + */ + mac_key = EVP_PKEY_new_mac_key(mactype, NULL, mackey, + (int)mackeylen); + } + if (mac_key == NULL + || EVP_DigestSignInit_ex(rl->read_hash, NULL, EVP_MD_get0_name(md), + rl->libctx, rl->propq, mac_key, + NULL) <= 0) { + EVP_PKEY_free(mac_key); + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + EVP_PKEY_free(mac_key); + } + + if (EVP_CIPHER_get_mode(ciph) == EVP_CIPH_GCM_MODE) { + if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, NULL) + || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_GCM_SET_IV_FIXED, + (int)ivlen, iv) <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } else if (EVP_CIPHER_get_mode(ciph) == EVP_CIPH_CCM_MODE) { + if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, NULL, NULL) + || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, + NULL) <= 0 + || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, + (int)taglen, NULL) <= 0 + || EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_CCM_SET_IV_FIXED, + (int)ivlen, iv) <= 0 + /* + * TODO(RECLAYER): Why do we defer setting the key until here? + * why not in the initial EVP_DecryptInit_ex() call? + */ + || !EVP_DecryptInit_ex(ciph_ctx, NULL, NULL, key, NULL)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } else { + if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, iv)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ + if ((EVP_CIPHER_get_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 + && mackeylen != 0 + && EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_MAC_KEY, + (int)mackeylen, mackey) <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + if (EVP_CIPHER_get0_provider(ciph) != NULL + && !ossl_set_tls_provider_parameters(rl, ciph_ctx, ciph, md, s)) { + /* RLAYERfatal already called */ + return 0; + } + + return 1; +} + +#define MAX_PADDING 256 +/*- + * tls1_cipher 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: 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) + */ +static int tls1_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, + int sending, SSL_MAC_BUF *macs, size_t macsize, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) +{ + 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, tmpr, provided; + size_t bs, ctr, padnum, loop; + unsigned char padval; + 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); + SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); + + if (n_recs == 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (sending) { + int ivlen; + + if (EVP_MD_CTX_get0_md(s->write_hash)) { + int n = EVP_MD_CTX_get_size(s->write_hash); + if (!ossl_assert(n >= 0)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + ds = s->enc_write_ctx; + if (!ossl_assert(s->enc_write_ctx)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + 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_get_mode(enc) == EVP_CIPH_CBC_MODE) + ivlen = EVP_CIPHER_get_iv_length(enc); + else + ivlen = 0; + if (ivlen > 1) { + for (ctr = 0; ctr < n_recs; ctr++) { + if (recs[ctr].data != recs[ctr].input) { + /* + * we can't write into the input stream: Can this ever + * happen?? (steve) + */ + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } else if (RAND_bytes_ex(sctx->libctx, recs[ctr].input, + ivlen, 0) <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + } else { + if (EVP_MD_CTX_get0_md(rl->read_hash)) { + int n = EVP_MD_CTX_get_size(rl->read_hash); + if (!ossl_assert(n >= 0)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + ds = rl->enc_read_ctx; + if (!ossl_assert(rl->enc_read_ctx)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + enc = EVP_CIPHER_CTX_get0_cipher(rl->enc_read_ctx); + } + + if ((s->session == NULL) || (enc == NULL)) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + 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_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 + */ + RLAYERfatal(rl, 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_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) + : RECORD_LAYER_get_read_sequence(&s->rlayer); + + if (SSL_CONNECTION_IS_DTLS(s)) { + /* DTLS does not support pipelining */ + unsigned char dtlsseq[8], *p = dtlsseq; + + s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) : + DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p); + memcpy(p, &seq[2], 6); + memcpy(buf[ctr], dtlsseq, 8); + } else { + memcpy(buf[ctr], seq, 8); + for (i = 7; i >= 0; i--) { /* increment */ + ++seq[i]; + if (seq[i] != 0) + break; + } + } + + buf[ctr][8] = recs[ctr].type; + buf[ctr][9] = (unsigned char)(rl->version >> 8); + buf[ctr][10] = (unsigned char)(rl->version); + buf[ctr][11] = (unsigned char)(recs[ctr].length >> 8); + buf[ctr][12] = (unsigned char)(recs[ctr].length & 0xff); + pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, buf[ctr]); + if (pad <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (sending) { + reclen[ctr] += pad; + recs[ctr].length += pad; + } + + } 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) { + RLAYERfatal(rl, 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); + for (loop = reclen[ctr]; loop < reclen[ctr] + padnum; loop++) + recs[ctr].input[loop] = padval; + reclen[ctr] += padnum; + recs[ctr].length += padnum; + } + + if (!sending) { + 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) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE); + return 0; + } + /* Set the input buffers */ + for (ctr = 0; ctr < n_recs; ctr++) { + data[ctr] = recs[ctr].input; + } + if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS, + (int)n_recs, data) <= 0 + || EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS, + (int)n_recs, reclen) <= 0) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE); + return 0; + } + } + + if (!SSL_CONNECTION_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) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + } + + if (provided) { + int outlen; + + /* Provided cipher - we do not support pipelining on this path */ + if (n_recs > 1) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + 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 */ + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, + ERR_R_INTERNAL_ERROR); + return 0; + } + } + } + } 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, + sctx->libctx)) + return 0; + } + } + } + return 1; +} + +static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, + int sending, SSL_CONNECTION *ssl) +{ + unsigned char *seq; + EVP_MD_CTX *hash; + size_t md_size; + 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 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); + hash = ssl->write_hash; + } else { + seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer); + hash = rl->read_hash; + } + + t = EVP_MD_CTX_get_size(hash); + if (!ossl_assert(t >= 0)) + return 0; + md_size = t; + + /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ + if (stream_mac) { + mac_ctx = hash; + } else { + hmac = EVP_MD_CTX_new(); + if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) { + goto end; + } + mac_ctx = hmac; + } + + if (!rl->isdtls + && tlstree_mac + && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) { + goto end; + } + + if (rl->isdtls) { + unsigned char dtlsseq[8], *p = dtlsseq; + + s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) : + DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p); + memcpy(p, &seq[2], 6); + + memcpy(header, dtlsseq, 8); + } else + memcpy(header, seq, 8); + + header[8] = rec->type; + header[9] = (unsigned char)(ssl->version >> 8); + header[10] = (unsigned char)(ssl->version); + header[11] = (unsigned char)(rec->length >> 8); + header[12] = (unsigned char)(rec->length & 0xff); + + if (!sending && !SSL_READ_ETM(ssl) + && EVP_CIPHER_CTX_get_mode(rl->enc_read_ctx) == EVP_CIPH_CBC_MODE + && ssl3_cbc_record_digest_supported(mac_ctx)) { + OSSL_PARAM tls_hmac_params[2], *p = tls_hmac_params; + + *p++ = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, + &rec->orig_len); + *p++ = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(mac_ctx), + tls_hmac_params)) { + goto end; + } + } + + 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; + } + + 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_CONNECTION_IS_DTLS(ssl)) { + for (i = 7; i >= 0; i--) { + ++seq[i]; + if (seq[i] != 0) + break; + } + } + 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; +} + +/* TLSv1.0, TLSv1.1 and TLSv1.2 all use the same funcs */ +struct record_functions_st tls_1_funcs = { + tls1_set_crypto_state, + tls1_cipher, + tls1_mac +}; diff --git a/ssl/record/methods/tlsrecord.c b/ssl/record/methods/tls_common.c index d12b38ce39..b693fcf5db 100644 --- a/ssl/record/methods/tlsrecord.c +++ b/ssl/record/methods/tls_common.c @@ -11,113 +11,16 @@ #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/core_names.h> -#include <openssl/rand.h> #include "internal/e_os.h" #include "internal/packet.h" #include "../../ssl_local.h" #include "../record_local.h" - -/* Protocol version specific function pointers */ -struct record_functions_st -{ - int (*set_crypto_state)(OSSL_RECORD_LAYER *rl, int level, - 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, - const EVP_MD *md, - const SSL_COMP *comp, - /* TODO(RECLAYER): Remove me */ - SSL_CONNECTION *s); - int (*cipher)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, - int sending, SSL_MAC_BUF *macs, size_t macsize, - /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s); - int (*mac)(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, - int sending, /* TODO(RECLAYER): Remove me */SSL_CONNECTION *ssl); -}; - -struct ossl_record_layer_st -{ - OSSL_LIB_CTX *libctx; - const char *propq; - int isdtls; - int version; - int role; - int direction; - BIO *bio; - /* Types match the equivalent structures in the SSL object */ - uint64_t options; - /* - * TODO(RECLAYER): Should we take the opportunity to make this uint64_t - * even though upper layer continue to use uint32_t? - */ - uint32_t mode; - - /* read IO goes into here */ - SSL3_BUFFER rbuf; - /* each decoded record goes in here */ - SSL3_RECORD rrec[SSL_MAX_PIPELINES]; - - /* How many records have we got available in the rrec bufer */ - size_t num_recs; - - /* The record number in the rrec buffer that can be read next */ - size_t curr_rec; - - /* The number of records that have been released via tls_release_record */ - size_t num_released; - - /* Set to true if this is the first record in a connection */ - unsigned int is_first_record; - - /* where we are when reading */ - int rstate; - - /* used internally to point at a raw packet */ - unsigned char *packet; - size_t packet_length; - - int alert; - - /* - * Read as many input bytes as possible (for - * non-blocking reads) - * TODO(RECLAYER): Why isn't this just an option? - */ - int read_ahead; - - /* The number of consecutive empty records we have received */ - size_t empty_record_count; - - /* cryptographic state */ - EVP_CIPHER_CTX *enc_read_ctx; - /* TLSv1.3 static read IV */ - unsigned char read_iv[EVP_MAX_IV_LENGTH]; - /* used for mac generation */ - EVP_MD_CTX *read_hash; - /* uncompress */ - COMP_CTX *expand; - - /* Only used by SSLv3 */ - unsigned char mac_secret[EVP_MAX_MD_SIZE]; - - /* TLSv1.3 static IV */ - unsigned char iv[EVP_MAX_IV_LENGTH]; - - size_t taglen; - - /* Function pointers for version specific functions */ - /* Function pointers for version specific functions */ - struct record_functions_st *funcs; -}; +#include "recmethod_local.h" # define SSL_AD_NO_ALERT -1 -static void rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason, - const char *fmt, ...) +void ossl_rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason, + const char *fmt, ...) { va_list args; @@ -128,18 +31,11 @@ static void rlayer_fatal(OSSL_RECORD_LAYER *rl, int al, int reason, rl->alert = al; } - -# define RLAYERfatal(rl, al, r) RLAYERfatal_data((rl), (al), (r), NULL) -# define RLAYERfatal_data \ - (ERR_new(), \ - ERR_set_debug(OPENSSL_FILE, OPENSSL_LINE, OPENSSL_FUNC), \ - rlayer_fatal) - -static int tls_provider_set_tls_parameters(OSSL_RECORD_LAYER *rl, - EVP_CIPHER_CTX *ctx, - const EVP_CIPHER *ciph, - const EVP_MD *md, - SSL_CONNECTION *s) +int ossl_set_tls_provider_parameters(OSSL_RECORD_LAYER *rl, + EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *ciph, + const EVP_MD *md, + SSL_CONNECTION *s) { /* * Provided cipher, the TLS padding/MAC removal is performed provider @@ -174,1136 +70,25 @@ static int tls_provider_set_tls_parameters(OSSL_RECORD_LAYER *rl, return 1; } -static int tls_any_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, - 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, - const EVP_MD *md, - const SSL_COMP *comp, - /* TODO(RECLAYER): Remove me */ - SSL_CONNECTION *s) -{ - if (level != OSSL_RECORD_PROTECTION_LEVEL_NONE) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - /* No crypto protection at the "NONE" level so nothing to be done */ - - return 1; -} - -/* TODO(RECLAYER): Handle OPENSSL_NO_COMP */ -static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, - 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, - const EVP_MD *md, - const SSL_COMP *comp, - /* TODO(RECLAYER): Remove me */ - SSL_CONNECTION *s) -{ - EVP_CIPHER_CTX *ciph_ctx; - - if (md == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if ((rl->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - return 0; - } - ciph_ctx = rl->enc_read_ctx; - - rl->read_hash = EVP_MD_CTX_new(); - if (rl->read_hash == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } -#ifndef OPENSSL_NO_COMP - if (comp != NULL) { - rl->expand = COMP_CTX_new(comp->method); - if (rl->expand == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, - SSL_R_COMPRESSION_LIBRARY_ERROR); - return 0; - } - } -#endif - - if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, iv)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (EVP_CIPHER_get0_provider(ciph) != NULL - && !tls_provider_set_tls_parameters(rl, ciph_ctx, ciph, md, s)) { - /* RLAYERfatal already called */ - return 0; - } - - if (mackeylen > sizeof(rl->mac_secret)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - memcpy(rl->mac_secret, mackey, mackeylen); - - return 1; -} - -/* TODO(RECLAYER): Handle OPENSSL_NO_COMP */ -static int tls1_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, - 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, - const EVP_MD *md, - const SSL_COMP *comp, - /* TODO(RECLAYER): Remove me */ - SSL_CONNECTION *s) -{ - EVP_CIPHER_CTX *ciph_ctx; - EVP_PKEY *mac_key; - - if (level != OSSL_RECORD_PROTECTION_LEVEL_APPLICATION) - return 0; - - if (s->ext.use_etm) - s->s3.flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; - else - s->s3.flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC_READ; - - if (s->s3.tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC) - s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM; - else - s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; - - if (s->s3.tmp.new_cipher->algorithm2 & TLS1_TLSTREE) - s->mac_flags |= SSL_MAC_FLAG_READ_MAC_TLSTREE; - else - s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_TLSTREE; - - if ((rl->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - return 0; - } - - ciph_ctx = rl->enc_read_ctx; - - rl->read_hash = EVP_MD_CTX_new(); - if (rl->read_hash == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } -#ifndef OPENSSL_NO_COMP - if (comp != NULL) { - rl->expand = COMP_CTX_new(comp->method); - if (rl->expand == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, - SSL_R_COMPRESSION_LIBRARY_ERROR); - return 0; - } - } -#endif - /* - * this is done by dtls1_reset_seq_numbers for DTLS - */ - if (!rl->isdtls) - RECORD_LAYER_reset_read_sequence(&s->rlayer); - - /* - * If we have an AEAD Cipher, then there is no separate MAC, so we can skip - * setting up the MAC key. - */ - if (!(EVP_CIPHER_get_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER)) { - if (mactype == EVP_PKEY_HMAC) { - mac_key = EVP_PKEY_new_raw_private_key_ex(rl->libctx, "HMAC", - rl->propq, mackey, - mackeylen); - } else { - /* - * If its not HMAC then the only other types of MAC we support are - * the GOST MACs, so we need to use the old style way of creating - * a MAC key. - */ - mac_key = EVP_PKEY_new_mac_key(mactype, NULL, mackey, - (int)mackeylen); - } - if (mac_key == NULL - || EVP_DigestSignInit_ex(rl->read_hash, NULL, EVP_MD_get0_name(md), - rl->libctx, rl->propq, mac_key, - NULL) <= 0) { - EVP_PKEY_free(mac_key); - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - EVP_PKEY_free(mac_key); - } - - if (EVP_CIPHER_get_mode(ciph) == EVP_CIPH_GCM_MODE) { - if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, NULL) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_GCM_SET_IV_FIXED, - (int)ivlen, iv)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } else if (EVP_CIPHER_get_mode(ciph) == EVP_CIPH_CCM_MODE) { - if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, NULL, NULL) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, - NULL) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, - (int)taglen, NULL) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_CCM_SET_IV_FIXED, - (int)ivlen, iv) - /* - * TODO(RECLAYER): Why do we defer setting the key until here? - * why not in the initial EVP_DecryptInit_ex() call? - */ - || !EVP_DecryptInit_ex(ciph_ctx, NULL, NULL, key, NULL)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } else { - if (!EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, key, iv)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */ - if ((EVP_CIPHER_get_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 - && mackeylen != 0 - && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_MAC_KEY, - (int)mackeylen, mackey)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - if (EVP_CIPHER_get0_provider(ciph) != NULL - && !tls_provider_set_tls_parameters(rl, ciph_ctx, ciph, md, s)) { - /* RLAYERfatal already called */ - return 0; - } - - return 1; -} - -static int tls13_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, - 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, - const EVP_MD *md, - const SSL_COMP *comp, - /* TODO(RECLAYER): Remove me */ - SSL_CONNECTION *s) -{ - EVP_CIPHER_CTX *ciph_ctx; - int mode; - - if (ivlen > sizeof(rl->iv)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - memcpy(rl->iv, iv, ivlen); - - ciph_ctx = rl->enc_read_ctx = EVP_CIPHER_CTX_new(); - if (ciph_ctx == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); - return 0; - } - - RECORD_LAYER_reset_read_sequence(&s->rlayer); - rl->taglen = taglen; - - mode = EVP_CIPHER_get_mode(ciph); - - if (EVP_DecryptInit_ex(ciph_ctx, ciph, NULL, NULL, NULL) <= 0 - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL) - || (mode == EVP_CIPH_CCM_MODE - && !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, NULL)) - || EVP_DecryptInit_ex(ciph_ctx, NULL, NULL, key, NULL) <= 0) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB); - return 0; - } - - return 1; -} - -static int tls_any_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, - int sending, SSL_MAC_BUF *macs, size_t macsize, - /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) -{ - size_t ctr; - - for (ctr = 0; ctr < n_recs; ctr++) { - memmove(recs[ctr].data, recs[ctr].input, recs[ctr].length); - recs[ctr].input = recs[ctr].data; - } - - return 1; -} - -/*- - * 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: if the record is publicly invalid, or an internal error - * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised) - */ -static int ssl3_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *inrecs, size_t n_recs, - int sending, SSL_MAC_BUF *mac, size_t macsize, - /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) -{ - SSL3_RECORD *rec; - EVP_CIPHER_CTX *ds; - size_t l, i; - size_t bs; - const EVP_CIPHER *enc; - int provided; - - rec = inrecs; - /* - * We shouldn't ever be called with more than one record in the SSLv3 case - */ - if (n_recs != 1) - return 0; - if (sending) { - ds = s->enc_write_ctx; - if (s->enc_write_ctx == NULL) - enc = NULL; - else - enc = EVP_CIPHER_CTX_get0_cipher(s->enc_write_ctx); - } else { - ds = rl->enc_read_ctx; - if (rl->enc_read_ctx == NULL) - enc = NULL; - else - enc = EVP_CIPHER_CTX_get0_cipher(rl->enc_read_ctx); - } - - provided = (EVP_CIPHER_get0_provider(enc) != NULL); - - l = rec->length; - bs = EVP_CIPHER_CTX_get_block_size(ds); - - /* COMPRESS */ - - 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 */ - l += i; - /* - * the last of these zero bytes will be overwritten with the - * padding length. - */ - memset(&rec->input[rec->length], 0, i); - rec->length += i; - rec->input[l - 1] = (unsigned char)(i - 1); - } - - if (!sending) { - if (l == 0 || l % bs != 0) { - /* Publicly invalid */ - return 0; - } - /* otherwise, rec->length >= bs */ - } - - if (provided) { - int outlen; - - 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 */ - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - } else { - if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) { - /* Shouldn't happen */ - RLAYERfatal(rl, 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, - rl->libctx); - } - - return 1; -} - -#define MAX_PADDING 256 -/*- - * tls1_cipher 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: 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) +/* + * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function + * which ssl3_cbc_digest_record supports. */ -static int tls1_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, - int sending, SSL_MAC_BUF *macs, size_t macsize, - /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) -{ - 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, tmpr, provided; - size_t bs, ctr, padnum, loop; - unsigned char padval; - 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); - SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s); - - if (n_recs == 0) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (sending) { - int ivlen; - - if (EVP_MD_CTX_get0_md(s->write_hash)) { - int n = EVP_MD_CTX_get_size(s->write_hash); - if (!ossl_assert(n >= 0)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - ds = s->enc_write_ctx; - if (!ossl_assert(s->enc_write_ctx)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - 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_get_mode(enc) == EVP_CIPH_CBC_MODE) - ivlen = EVP_CIPHER_get_iv_length(enc); - else - ivlen = 0; - if (ivlen > 1) { - for (ctr = 0; ctr < n_recs; ctr++) { - if (recs[ctr].data != recs[ctr].input) { - /* - * we can't write into the input stream: Can this ever - * happen?? (steve) - */ - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } else if (RAND_bytes_ex(sctx->libctx, recs[ctr].input, - ivlen, 0) <= 0) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - } - } else { - if (EVP_MD_CTX_get0_md(rl->read_hash)) { - int n = EVP_MD_CTX_get_size(rl->read_hash); - if (!ossl_assert(n >= 0)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - ds = rl->enc_read_ctx; - if (!ossl_assert(rl->enc_read_ctx)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - enc = EVP_CIPHER_CTX_get0_cipher(rl->enc_read_ctx); - } - - if ((s->session == NULL) || (enc == NULL)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - 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_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 - */ - RLAYERfatal(rl, 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_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) - : RECORD_LAYER_get_read_sequence(&s->rlayer); - - if (SSL_CONNECTION_IS_DTLS(s)) { - /* DTLS does not support pipelining */ - unsigned char dtlsseq[8], *p = dtlsseq; - - s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&s->rlayer) : - DTLS_RECORD_LAYER_get_r_epoch(&s->rlayer), p); - memcpy(p, &seq[2], 6); - memcpy(buf[ctr], dtlsseq, 8); - } else { - memcpy(buf[ctr], seq, 8); - for (i = 7; i >= 0; i--) { /* increment */ - ++seq[i]; - if (seq[i] != 0) - break; - } - } - - buf[ctr][8] = recs[ctr].type; - buf[ctr][9] = (unsigned char)(rl->version >> 8); - buf[ctr][10] = (unsigned char)(rl->version); - buf[ctr][11] = (unsigned char)(recs[ctr].length >> 8); - buf[ctr][12] = (unsigned char)(recs[ctr].length & 0xff); - pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, - EVP_AEAD_TLS1_AAD_LEN, buf[ctr]); - if (pad <= 0) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (sending) { - reclen[ctr] += pad; - recs[ctr].length += pad; - } - - } 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) { - RLAYERfatal(rl, 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); - for (loop = reclen[ctr]; loop < reclen[ctr] + padnum; loop++) - recs[ctr].input[loop] = padval; - reclen[ctr] += padnum; - recs[ctr].length += padnum; - } - - if (!sending) { - 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) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE); - return 0; - } - /* Set the input buffers */ - for (ctr = 0; ctr < n_recs; ctr++) { - data[ctr] = recs[ctr].input; - } - if (EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_BUFS, - (int)n_recs, data) <= 0 - || EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_SET_PIPELINE_INPUT_LENS, - (int)n_recs, reclen) <= 0) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, SSL_R_PIPELINE_FAILURE); - return 0; - } - } - - if (!SSL_CONNECTION_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) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - } - - if (provided) { - int outlen; - - /* Provided cipher - we do not support pipelining on this path */ - if (n_recs > 1) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - 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 */ - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, - ERR_R_INTERNAL_ERROR); - return 0; - } - } - } - } 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, - sctx->libctx)) - return 0; - } - } - } - return 1; -} - -static int tls13_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, size_t n_recs, - int sending, SSL_MAC_BUF *mac, size_t macsize, - /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) +char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) { - EVP_CIPHER_CTX *ctx; - unsigned char iv[EVP_MAX_IV_LENGTH], recheader[SSL3_RT_HEADER_LENGTH]; - size_t ivlen, offset, loop, hdrlen; - unsigned char *staticiv; - unsigned char *seq; - int lenu, lenf; - SSL3_RECORD *rec = &recs[0]; - WPACKET wpkt; - const EVP_CIPHER *cipher; - int mode; - - if (n_recs != 1) { - /* Should not happen */ - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (sending) { - ctx = s->enc_write_ctx; - staticiv = s->write_iv; - seq = RECORD_LAYER_get_write_sequence(&s->rlayer); - } else { - ctx = rl->enc_read_ctx; - staticiv = rl->iv; - seq = RECORD_LAYER_get_read_sequence(&s->rlayer); - } - - cipher = EVP_CIPHER_CTX_get0_cipher(ctx); - if (cipher == NULL) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - mode = EVP_CIPHER_get_mode(cipher); - - /* - * If we're sending an alert and ctx != NULL then we must be forcing - * plaintext alerts. If we're reading and ctx != NULL then we allow - * plaintext alerts at certain points in the handshake. If we've got this - * far then we have already validated that a plaintext alert is ok here. - */ - if (ctx == NULL || rec->type == SSL3_RT_ALERT) { - memmove(rec->data, rec->input, rec->length); - rec->input = rec->data; + 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; - } - - ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); - - if (!sending) { - /* - * Take off tag. There must be at least one byte of content type as - * well as the tag - */ - if (rec->length < rl->taglen + 1) - return 0; - rec->length -= rl->taglen; - } - - /* Set up IV */ - if (ivlen < SEQ_NUM_SIZE) { - /* Should not happen */ - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - offset = ivlen - SEQ_NUM_SIZE; - memcpy(iv, staticiv, offset); - for (loop = 0; loop < SEQ_NUM_SIZE; loop++) - iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; - - /* Increment the sequence counter */ - for (loop = SEQ_NUM_SIZE; loop > 0; loop--) { - ++seq[loop - 1]; - if (seq[loop - 1] != 0) - break; - } - if (loop == 0) { - /* Sequence has wrapped */ - return 0; - } - - if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, sending) <= 0 - || (!sending && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, - rl->taglen, - rec->data + rec->length) <= 0)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - - /* Set up the AAD */ - if (!WPACKET_init_static_len(&wpkt, recheader, sizeof(recheader), 0) - || !WPACKET_put_bytes_u8(&wpkt, rec->type) - || !WPACKET_put_bytes_u16(&wpkt, rec->rec_version) - || !WPACKET_put_bytes_u16(&wpkt, rec->length + rl->taglen) - || !WPACKET_get_total_written(&wpkt, &hdrlen) - || hdrlen != SSL3_RT_HEADER_LENGTH - || !WPACKET_finish(&wpkt)) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - WPACKET_cleanup(&wpkt); - return 0; - } - - /* - * For CCM we must explicitly set the total plaintext length before we add - * any AAD. - */ - if ((mode == EVP_CIPH_CCM_MODE - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) - || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, - sizeof(recheader)) <= 0 - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 - || (size_t)(lenu + lenf) != rec->length) { - return 0; - } - if (sending) { - /* Add the tag */ - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, rl->taglen, - rec->data + rec->length) <= 0) { - RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); - return 0; - } - rec->length += rl->taglen; - } - - return 1; -} - -static const unsigned char ssl3_pad_1[48] = { - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 -}; - -static const unsigned char ssl3_pad_2[48] = { - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, - 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c -}; - -static int ssl3_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, - int sending, SSL_CONNECTION *ssl) -{ - unsigned char *mac_sec, *seq; - const EVP_MD_CTX *hash; - unsigned char *p, rec_char; - size_t md_size; - size_t npad; - int t; - - if (sending) { - mac_sec = &(ssl->s3.write_mac_secret[0]); - seq = RECORD_LAYER_get_write_sequence(&ssl->rlayer); - hash = ssl->write_hash; - } else { - mac_sec = &(rl->mac_secret[0]); - seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer); - hash = rl->read_hash; - } - - 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_get_mode(rl->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 - * are hashing because that gives an attacker a timing-oracle. - */ - - /*- - * npad is, at most, 48 bytes and that's with MD5: - * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75. - * - * With SHA-1 (the largest hash speced for SSLv3) the hash size - * goes up 4, but npad goes down by 8, resulting in a smaller - * total size. - */ - unsigned char header[75]; - size_t j = 0; - memcpy(header + j, mac_sec, md_size); - j += md_size; - memcpy(header + j, ssl3_pad_1, npad); - j += npad; - memcpy(header + j, seq, 8); - j += 8; - header[j++] = rec->type; - header[j++] = (unsigned char)(rec->length >> 8); - header[j++] = (unsigned char)(rec->length & 0xff); - - /* Final param == is SSLv3 */ - if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash), - md, &md_size, - header, rec->input, - 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 :-) */ - EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); - - if (md_ctx == NULL) - return 0; - - rec_char = rec->type; - p = md; - s2n(rec->length, p); - if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 - || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 - || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0 - || EVP_DigestUpdate(md_ctx, seq, 8) <= 0 - || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0 - || EVP_DigestUpdate(md_ctx, md, 2) <= 0 - || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0 - || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0 - || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0 - || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0 - || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0 - || EVP_DigestUpdate(md_ctx, md, md_size) <= 0 - || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) { - EVP_MD_CTX_free(md_ctx); - return 0; - } - - EVP_MD_CTX_free(md_ctx); - } - - ssl3_record_sequence_update(seq); - return 1; -} - -static int tls1_mac(OSSL_RECORD_LAYER *rl, SSL3_RECORD *rec, unsigned char *md, - int sending, SSL_CONNECTION *ssl) -{ - unsigned char *seq; - EVP_MD_CTX *hash; - size_t md_size; - 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 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); - hash = ssl->write_hash; - } else { - seq = RECORD_LAYER_get_read_sequence(&ssl->rlayer); - hash = rl->read_hash; - } - - t = EVP_MD_CTX_get_size(hash); - if (!ossl_assert(t >= 0)) + default: return 0; - md_size = t; - - /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */ - if (stream_mac) { - mac_ctx = hash; - } else { - hmac = EVP_MD_CTX_new(); - if (hmac == NULL || !EVP_MD_CTX_copy(hmac, hash)) { - goto end; - } - mac_ctx = hmac; } - - if (!rl->isdtls - && tlstree_mac - && EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_TLSTREE, 0, seq) <= 0) { - goto end; - } - - if (rl->isdtls) { - unsigned char dtlsseq[8], *p = dtlsseq; - - s2n(sending ? DTLS_RECORD_LAYER_get_w_epoch(&ssl->rlayer) : - DTLS_RECORD_LAYER_get_r_epoch(&ssl->rlayer), p); - memcpy(p, &seq[2], 6); - - memcpy(header, dtlsseq, 8); - } else - memcpy(header, seq, 8); - - header[8] = rec->type; - header[9] = (unsigned char)(ssl->version >> 8); - header[10] = (unsigned char)(ssl->version); - header[11] = (unsigned char)(rec->length >> 8); - header[12] = (unsigned char)(rec->length & 0xff); - - if (!sending && !SSL_READ_ETM(ssl) - && EVP_CIPHER_CTX_get_mode(rl->enc_read_ctx) == EVP_CIPH_CBC_MODE - && ssl3_cbc_record_digest_supported(mac_ctx)) { - OSSL_PARAM tls_hmac_params[2], *p = tls_hmac_params; - - *p++ = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, - &rec->orig_len); - *p++ = OSSL_PARAM_construct_end(); - - if (!EVP_PKEY_CTX_set_params(EVP_MD_CTX_get_pkey_ctx(mac_ctx), - tls_hmac_params)) { - goto end; - } - } - - 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; - } - - 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_CONNECTION_IS_DTLS(ssl)) { - for (i = 7; i >= 0; i--) { - ++seq[i]; - if (seq[i] != 0) - break; - } - } - 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; } -struct record_functions_st tls_any_funcs = { - tls_any_set_crypto_state, - tls_any_cipher, - NULL -}; - -struct record_functions_st tls_1_3_funcs = { - tls13_set_crypto_state, - tls13_cipher, - NULL -}; - -struct record_functions_st tls_1_2_funcs = { - tls1_set_crypto_state, - tls1_cipher, - tls1_mac -}; - -struct record_functions_st tls_1_1_funcs = { - tls1_set_crypto_state, - tls1_cipher, - tls1_mac -}; - -struct record_functions_st tls_1_0_funcs = { - tls1_set_crypto_state, - tls1_cipher, - tls1_mac -}; - -struct record_functions_st ssl_3_0_funcs = { - ssl3_set_crypto_state, - ssl3_cipher, - ssl3_mac -}; - static int tls_set1_bio(OSSL_RECORD_LAYER *rl, BIO *bio); static int rlayer_allow_compression(OSSL_RECORD_LAYER *rl) @@ -2396,13 +1181,9 @@ static OSSL_RECORD_LAYER *tls_new_record_layer(OSSL_LIB_CTX *libctx, rl->funcs = &tls_1_3_funcs; break; case TLS1_2_VERSION: - rl->funcs = &tls_1_2_funcs; - break; case TLS1_1_VERSION: - rl->funcs = &tls_1_1_funcs; - break; case TLS1_VERSION: - rl->funcs = &tls_1_0_funcs; + rl->funcs = &tls_1_funcs; break; case SSL3_VERSION: rl->funcs = &ssl_3_0_funcs; diff --git a/ssl/record/methods/tlsany_meth.c b/ssl/record/methods/tlsany_meth.c new file mode 100644 index 0000000000..12273549ce --- /dev/null +++ b/ssl/record/methods/tlsany_meth.c @@ -0,0 +1,50 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/evp.h> +#include "../../ssl_local.h" +#include "../record_local.h" +#include "recmethod_local.h" + +static int tls_any_set_crypto_state(OSSL_RECORD_LAYER *rl, int level, + 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, + const EVP_MD *md, + const SSL_COMP *comp, + /* TODO(RECLAYER): Remove me */ + SSL_CONNECTION *s) +{ + if (level != OSSL_RECORD_PROTECTION_LEVEL_NONE) { + RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* No crypto protection at the "NONE" level so nothing to be done */ + + return 1; +} + +static int tls_any_cipher(OSSL_RECORD_LAYER *rl, SSL3_RECORD *recs, + size_t n_recs, int sending, SSL_MAC_BUF *macs, + size_t macsize, + /* TODO(RECLAYER): Remove me */ SSL_CONNECTION *s) +{ + return 1; +} + +struct record_functions_st tls_any_funcs = { + tls_any_set_crypto_state, + tls_any_cipher, + NULL +}; diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index fa9ef0e2c0..87bfd62bd9 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -604,23 +604,19 @@ int tls1_enc(SSL_CONNECTION *s, SSL3_RECORD *recs, size_t n_recs, int sending, } /* - * ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function - * which ssl3_cbc_digest_record supports. + * TODO(RECLAYER): Remove me: now declared in + * ssl/record/methods/recmethod_local.h */ -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; - } -} +char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); +int ssl3_cbc_digest_record(const EVP_MD *md, + unsigned char *md_out, + size_t *md_out_size, + const unsigned char *header, + const unsigned char *data, + size_t data_size, + size_t data_plus_mac_plus_padding_size, + const unsigned char *mac_secret, + size_t mac_secret_length, char is_sslv3); int n_ssl3_mac(SSL_CONNECTION *sc, SSL3_RECORD *rec, unsigned char *md, int sending) |