diff --git a/Package.swift b/Package.swift index b10f1192..95e407df 100644 --- a/Package.swift +++ b/Package.swift @@ -22,7 +22,7 @@ import PackageDescription // Sources/CNIOBoringSSL directory. The source repository is at // https://boringssl.googlesource.com/boringssl. // -// BoringSSL Commit: 04b3213d43492b6c9e0434d8e2a4530a9938f958 +// BoringSSL Commit: ab7811ee8751ea699b22095caa70246f641ed3a2 let package = Package( name: "swift-nio-ssl", diff --git a/Sources/CNIOBoringSSL/crypto/asn1/a_bool.c b/Sources/CNIOBoringSSL/crypto/asn1/a_bool.c index 49622b89..2868472e 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/a_bool.c +++ b/Sources/CNIOBoringSSL/crypto/asn1/a_bool.c @@ -78,7 +78,7 @@ int i2d_ASN1_BOOLEAN(int a, unsigned char **pp) } ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL); - *p = (unsigned char)a; + *p = a ? 0xff : 0x00; /* * If a new buffer was allocated, just return it back. diff --git a/Sources/CNIOBoringSSL/crypto/asn1/a_type.c b/Sources/CNIOBoringSSL/crypto/asn1/a_type.c index 6432d9ad..499dafd1 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/a_type.c +++ b/Sources/CNIOBoringSSL/crypto/asn1/a_type.c @@ -66,18 +66,28 @@ int ASN1_TYPE_get(const ASN1_TYPE *a) { - if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL)) - return (a->type); - else - return (0); + if (a->type == V_ASN1_BOOLEAN || a->type == V_ASN1_NULL || + a->value.ptr != NULL) { + return a->type; + } + return 0; } -void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) +const void *asn1_type_value_as_pointer(const ASN1_TYPE *a) { - if (a->value.ptr != NULL) { - ASN1_TYPE **tmp_a = &a; - ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL); + if (a->type == V_ASN1_BOOLEAN) { + return a->value.boolean ? (void *)0xff : NULL; + } + if (a->type == V_ASN1_NULL) { + return NULL; } + return a->value.ptr; +} + +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) +{ + ASN1_TYPE **tmp_a = &a; + ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL); a->type = type; if (type == V_ASN1_BOOLEAN) a->value.boolean = value ? 0xff : 0; diff --git a/Sources/CNIOBoringSSL/crypto/asn1/asn1_lib.c b/Sources/CNIOBoringSSL/crypto/asn1/asn1_lib.c index a72da392..cc0cf78e 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/asn1_lib.c +++ b/Sources/CNIOBoringSSL/crypto/asn1/asn1_lib.c @@ -370,8 +370,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) { - if (str->data) - OPENSSL_free(str->data); + OPENSSL_free(str->data); str->data = data; str->length = len; } diff --git a/Sources/CNIOBoringSSL/crypto/asn1/asn1_locl.h b/Sources/CNIOBoringSSL/crypto/asn1/asn1_locl.h index 8b0af77b..c74539e2 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/asn1_locl.h +++ b/Sources/CNIOBoringSSL/crypto/asn1/asn1_locl.h @@ -126,6 +126,11 @@ int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it); +/* asn1_type_value_as_pointer returns |a|'s value in pointer form. This is + * usually the value object but, for BOOLEAN values, is 0 or 0xff cast to + * a pointer. */ +const void *asn1_type_value_as_pointer(const ASN1_TYPE *a); + #if defined(__cplusplus) } /* extern C */ diff --git a/Sources/CNIOBoringSSL/crypto/asn1/tasn_enc.c b/Sources/CNIOBoringSSL/crypto/asn1/tasn_enc.c index a503acbb..1f12cd15 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/tasn_enc.c +++ b/Sources/CNIOBoringSSL/crypto/asn1/tasn_enc.c @@ -569,7 +569,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, if (!*tbool && !it->size) return -1; } - c = (unsigned char)*tbool; + c = *tbool ? 0xff : 0x00; cont = &c; len = 1; break; diff --git a/Sources/CNIOBoringSSL/crypto/asn1/tasn_fre.c b/Sources/CNIOBoringSSL/crypto/asn1/tasn_fre.c index 0ca8d081..688a97d2 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/tasn_fre.c +++ b/Sources/CNIOBoringSSL/crypto/asn1/tasn_fre.c @@ -192,7 +192,7 @@ void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it) ASN1_TYPE *typ = (ASN1_TYPE *)*pval; utype = typ->type; pval = &typ->value.asn1_value; - if (!*pval) + if (utype != V_ASN1_BOOLEAN && !*pval) return; } else if (it->itype == ASN1_ITYPE_MSTRING) { utype = -1; diff --git a/Sources/CNIOBoringSSL/crypto/cipher_extra/e_tls.c b/Sources/CNIOBoringSSL/crypto/cipher_extra/e_tls.c index ae29259e..67c79187 100644 --- a/Sources/CNIOBoringSSL/crypto/cipher_extra/e_tls.c +++ b/Sources/CNIOBoringSSL/crypto/cipher_extra/e_tls.c @@ -343,7 +343,7 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE && EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) { if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len, - ad_fixed, out, data_plus_mac_len, total, + ad_fixed, out, data_len, total, tls_ctx->mac_key, tls_ctx->mac_key_len)) { OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); return 0; @@ -406,14 +406,6 @@ static int aead_aes_128_cbc_sha1_tls_implicit_iv_init( EVP_sha1(), 1); } -static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx, - const uint8_t *key, size_t key_len, - size_t tag_len, - enum evp_aead_direction_t dir) { - return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(), - EVP_sha256(), 0); -} - static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, enum evp_aead_direction_t dir) { @@ -428,22 +420,6 @@ static int aead_aes_256_cbc_sha1_tls_implicit_iv_init( EVP_sha1(), 1); } -static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx, - const uint8_t *key, size_t key_len, - size_t tag_len, - enum evp_aead_direction_t dir) { - return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), - EVP_sha256(), 0); -} - -static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx, - const uint8_t *key, size_t key_len, - size_t tag_len, - enum evp_aead_direction_t dir) { - return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(), - EVP_sha384(), 0); -} - static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len, @@ -513,23 +489,6 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = { aead_tls_tag_len, }; -static const EVP_AEAD aead_aes_128_cbc_sha256_tls = { - SHA256_DIGEST_LENGTH + 16, // key len (SHA256 + AES128) - 16, // nonce len (IV) - 16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256) - SHA256_DIGEST_LENGTH, // max tag length - 0, // seal_scatter_supports_extra_in - - NULL, // init - aead_aes_128_cbc_sha256_tls_init, - aead_tls_cleanup, - aead_tls_open, - aead_tls_seal_scatter, - NULL, // open_gather - NULL, // get_iv - aead_tls_tag_len, -}; - static const EVP_AEAD aead_aes_256_cbc_sha1_tls = { SHA_DIGEST_LENGTH + 32, // key len (SHA1 + AES256) 16, // nonce len (IV) @@ -564,40 +523,6 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = { aead_tls_tag_len, }; -static const EVP_AEAD aead_aes_256_cbc_sha256_tls = { - SHA256_DIGEST_LENGTH + 32, // key len (SHA256 + AES256) - 16, // nonce len (IV) - 16 + SHA256_DIGEST_LENGTH, // overhead (padding + SHA256) - SHA256_DIGEST_LENGTH, // max tag length - 0, // seal_scatter_supports_extra_in - - NULL, // init - aead_aes_256_cbc_sha256_tls_init, - aead_tls_cleanup, - aead_tls_open, - aead_tls_seal_scatter, - NULL, // open_gather - NULL, // get_iv - aead_tls_tag_len, -}; - -static const EVP_AEAD aead_aes_256_cbc_sha384_tls = { - SHA384_DIGEST_LENGTH + 32, // key len (SHA384 + AES256) - 16, // nonce len (IV) - 16 + SHA384_DIGEST_LENGTH, // overhead (padding + SHA384) - SHA384_DIGEST_LENGTH, // max tag length - 0, // seal_scatter_supports_extra_in - - NULL, // init - aead_aes_256_cbc_sha384_tls_init, - aead_tls_cleanup, - aead_tls_open, - aead_tls_seal_scatter, - NULL, // open_gather - NULL, // get_iv - aead_tls_tag_len, -}; - static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = { SHA_DIGEST_LENGTH + 24, // key len (SHA1 + 3DES) 8, // nonce len (IV) @@ -657,10 +582,6 @@ const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void) { return &aead_aes_128_cbc_sha1_tls_implicit_iv; } -const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void) { - return &aead_aes_128_cbc_sha256_tls; -} - const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void) { return &aead_aes_256_cbc_sha1_tls; } @@ -669,14 +590,6 @@ const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) { return &aead_aes_256_cbc_sha1_tls_implicit_iv; } -const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void) { - return &aead_aes_256_cbc_sha256_tls; -} - -const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) { - return &aead_aes_256_cbc_sha384_tls; -} - const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) { return &aead_des_ede3_cbc_sha1_tls; } diff --git a/Sources/CNIOBoringSSL/crypto/cipher_extra/internal.h b/Sources/CNIOBoringSSL/crypto/cipher_extra/internal.h index f07d9999..87319566 100644 --- a/Sources/CNIOBoringSSL/crypto/cipher_extra/internal.h +++ b/Sources/CNIOBoringSSL/crypto/cipher_extra/internal.h @@ -99,6 +99,17 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in, // which EVP_tls_cbc_digest_record supports. int EVP_tls_cbc_record_digest_supported(const EVP_MD *md); +// EVP_sha1_final_with_secret_suffix computes the result of hashing |len| bytes +// from |in| to |ctx| and writes the resulting hash to |out|. |len| is treated +// as secret and must be at most |max_len|, which is treated as public. |in| +// must point to a buffer of at least |max_len| bytes. It returns one on success +// and zero if inputs are too long. +// +// This function is exported for unit tests. +OPENSSL_EXPORT int EVP_sha1_final_with_secret_suffix( + SHA_CTX *ctx, uint8_t out[SHA_DIGEST_LENGTH], const uint8_t *in, size_t len, + size_t max_len); + // EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS // record. // @@ -108,8 +119,8 @@ int EVP_tls_cbc_record_digest_supported(const EVP_MD *md); // md_out_size: the number of output bytes is written here. // header: the 13-byte, TLS record header. // data: the record data itself -// data_plus_mac_size: the secret, reported length of the data and MAC -// once the padding has been removed. +// data_size: the secret, reported length of the data once the padding and MAC +// have been removed. // data_plus_mac_plus_padding_size: the public length of the whole // record, including padding. // @@ -119,7 +130,7 @@ int EVP_tls_cbc_record_digest_supported(const EVP_MD *md); // padding too. ) int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out, size_t *md_out_size, const uint8_t header[13], - const uint8_t *data, size_t data_plus_mac_size, + const uint8_t *data, size_t data_size, size_t data_plus_mac_plus_padding_size, const uint8_t *mac_secret, unsigned mac_secret_length); diff --git a/Sources/CNIOBoringSSL/crypto/cipher_extra/tls_cbc.c b/Sources/CNIOBoringSSL/crypto/cipher_extra/tls_cbc.c index 5b858742..eb3b79f5 100644 --- a/Sources/CNIOBoringSSL/crypto/cipher_extra/tls_cbc.c +++ b/Sources/CNIOBoringSSL/crypto/cipher_extra/tls_cbc.c @@ -62,15 +62,6 @@ #include "../fipsmodule/cipher/internal.h" -// 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 - int EVP_tls_cbc_remove_padding(crypto_word_t *out_padding_ok, size_t *out_len, const uint8_t *in, size_t in_len, size_t block_size, size_t mac_size) { @@ -183,134 +174,110 @@ void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in, OPENSSL_memcpy(out, rotated_mac, md_size); } -// u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in -// big-endian order. The value of p is advanced by four. -#define u32toBE(n, p) \ - do { \ - *((p)++) = (uint8_t)((n) >> 24); \ - *((p)++) = (uint8_t)((n) >> 16); \ - *((p)++) = (uint8_t)((n) >> 8); \ - *((p)++) = (uint8_t)((n)); \ - } while (0) - -// u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in -// big-endian order. The value of p is advanced by eight. -#define u64toBE(n, p) \ - do { \ - *((p)++) = (uint8_t)((n) >> 56); \ - *((p)++) = (uint8_t)((n) >> 48); \ - *((p)++) = (uint8_t)((n) >> 40); \ - *((p)++) = (uint8_t)((n) >> 32); \ - *((p)++) = (uint8_t)((n) >> 24); \ - *((p)++) = (uint8_t)((n) >> 16); \ - *((p)++) = (uint8_t)((n) >> 8); \ - *((p)++) = (uint8_t)((n)); \ - } while (0) - -typedef union { - SHA_CTX sha1; - SHA256_CTX sha256; - SHA512_CTX sha512; -} HASH_CTX; - -static void tls1_sha1_transform(HASH_CTX *ctx, const uint8_t *block) { - SHA1_Transform(&ctx->sha1, block); -} +int EVP_sha1_final_with_secret_suffix(SHA_CTX *ctx, + uint8_t out[SHA_DIGEST_LENGTH], + const uint8_t *in, size_t len, + size_t max_len) { + // Bound the input length so |total_bits| below fits in four bytes. This is + // redundant with TLS record size limits. This also ensures |input_idx| below + // does not overflow. + size_t max_len_bits = max_len << 3; + if (ctx->Nh != 0 || + (max_len_bits >> 3) != max_len || // Overflow + ctx->Nl + max_len_bits < max_len_bits || + ctx->Nl + max_len_bits > UINT32_MAX) { + return 0; + } -static void tls1_sha256_transform(HASH_CTX *ctx, const uint8_t *block) { - SHA256_Transform(&ctx->sha256, block); -} + // We need to hash the following into |ctx|: + // + // - ctx->data[:ctx->num] + // - in[:len] + // - A 0x80 byte + // - However many zero bytes are needed to pad up to a block. + // - Eight bytes of length. + size_t num_blocks = (ctx->num + len + 1 + 8 + SHA_CBLOCK - 1) >> 6; + size_t last_block = num_blocks - 1; + size_t max_blocks = (ctx->num + max_len + 1 + 8 + SHA_CBLOCK - 1) >> 6; + + // The bounds above imply |total_bits| fits in four bytes. + size_t total_bits = ctx->Nl + (len << 3); + uint8_t length_bytes[4]; + length_bytes[0] = (uint8_t)(total_bits >> 24); + length_bytes[1] = (uint8_t)(total_bits >> 16); + length_bytes[2] = (uint8_t)(total_bits >> 8); + length_bytes[3] = (uint8_t)total_bits; + + // We now construct and process each expected block in constant-time. + uint8_t block[SHA_CBLOCK] = {0}; + uint32_t result[5] = {0}; + // input_idx is the index into |in| corresponding to the current block. + // However, we allow this index to overflow beyond |max_len|, to simplify the + // 0x80 byte. + size_t input_idx = 0; + for (size_t i = 0; i < max_blocks; i++) { + // Fill |block| with data from the partial block in |ctx| and |in|. We copy + // as if we were hashing up to |max_len| and then zero the excess later. + size_t block_start = 0; + if (i == 0) { + OPENSSL_memcpy(block, ctx->data, ctx->num); + block_start = ctx->num; + } + if (input_idx < max_len) { + size_t to_copy = SHA_CBLOCK - block_start; + if (to_copy > max_len - input_idx) { + to_copy = max_len - input_idx; + } + OPENSSL_memcpy(block + block_start, in + input_idx, to_copy); + } -static void tls1_sha512_transform(HASH_CTX *ctx, const uint8_t *block) { - SHA512_Transform(&ctx->sha512, block); -} + // Zero any bytes beyond |len| and add the 0x80 byte. + for (size_t j = block_start; j < SHA_CBLOCK; j++) { + // input[idx] corresponds to block[j]. + size_t idx = input_idx + j - block_start; + // The barriers on |len| are not strictly necessary. However, without + // them, GCC compiles this code by incorporating |len| into the loop + // counter and subtracting it out later. This is still constant-time, but + // it frustrates attempts to validate this. + uint8_t is_in_bounds = constant_time_lt_8(idx, value_barrier_w(len)); + uint8_t is_padding_byte = constant_time_eq_8(idx, value_barrier_w(len)); + block[j] &= is_in_bounds; + block[j] |= 0x80 & is_padding_byte; + } -// 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_sha1_final_raw(HASH_CTX *ctx, uint8_t *md_out) { - SHA_CTX *sha1 = &ctx->sha1; - u32toBE(sha1->h[0], md_out); - u32toBE(sha1->h[1], md_out); - u32toBE(sha1->h[2], md_out); - u32toBE(sha1->h[3], md_out); - u32toBE(sha1->h[4], md_out); -} + input_idx += SHA_CBLOCK - block_start; -static void tls1_sha256_final_raw(HASH_CTX *ctx, uint8_t *md_out) { - SHA256_CTX *sha256 = &ctx->sha256; - for (unsigned i = 0; i < 8; i++) { - u32toBE(sha256->h[i], md_out); + // Fill in the length if this is the last block. + crypto_word_t is_last_block = constant_time_eq_w(i, last_block); + for (size_t j = 0; j < 4; j++) { + block[SHA_CBLOCK - 4 + j] |= is_last_block & length_bytes[j]; + } + + // Process the block and save the hash state if it is the final value. + SHA1_Transform(ctx, block); + for (size_t j = 0; j < 5; j++) { + result[j] |= is_last_block & ctx->h[j]; + } } -} -static void tls1_sha512_final_raw(HASH_CTX *ctx, uint8_t *md_out) { - SHA512_CTX *sha512 = &ctx->sha512; - for (unsigned i = 0; i < 8; i++) { - u64toBE(sha512->h[i], md_out); + // Write the output. + for (size_t i = 0; i < 5; i++) { + CRYPTO_store_u32_be(out + 4 * i, result[i]); } + return 1; } int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) { - switch (EVP_MD_type(md)) { - case NID_sha1: - case NID_sha256: - case NID_sha384: - return 1; - - default: - return 0; - } + return EVP_MD_type(md) == NID_sha1; } int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out, size_t *md_out_size, const uint8_t header[13], - const uint8_t *data, size_t data_plus_mac_size, + const uint8_t *data, size_t data_size, size_t data_plus_mac_plus_padding_size, const uint8_t *mac_secret, unsigned mac_secret_length) { - HASH_CTX md_state; - void (*md_final_raw)(HASH_CTX *ctx, uint8_t *md_out); - void (*md_transform)(HASH_CTX *ctx, const uint8_t *block); - unsigned md_size, md_block_size = 64, md_block_shift = 6; - // md_length_size is the number of bytes in the length field that terminates - // the hash. - unsigned md_length_size = 8; - - // Bound the acceptable input so we can forget about many possible overflows - // later in this function. This is redundant with the record size limits in - // TLS. - if (data_plus_mac_plus_padding_size >= 1024 * 1024) { - assert(0); - return 0; - } - - switch (EVP_MD_type(md)) { - case NID_sha1: - SHA1_Init(&md_state.sha1); - md_final_raw = tls1_sha1_final_raw; - md_transform = tls1_sha1_transform; - md_size = SHA_DIGEST_LENGTH; - break; - - case NID_sha256: - SHA256_Init(&md_state.sha256); - md_final_raw = tls1_sha256_final_raw; - md_transform = tls1_sha256_transform; - md_size = SHA256_DIGEST_LENGTH; - break; - - case NID_sha384: - SHA384_Init(&md_state.sha512); - md_final_raw = tls1_sha512_final_raw; - md_transform = tls1_sha512_transform; - md_size = SHA384_DIGEST_LENGTH; - md_block_size = 128; - md_block_shift = 7; - md_length_size = 16; - break; - - default: + if (EVP_MD_type(md) != NID_sha1) { // EVP_tls_cbc_record_digest_supported should have been called first to // check that the hash function is supported. assert(0); @@ -318,175 +285,54 @@ int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out, return 0; } - assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES); - assert(md_block_size <= MAX_HASH_BLOCK_SIZE); - assert(md_block_size == (1u << md_block_shift)); - assert(md_size <= EVP_MAX_MD_SIZE); - - static const size_t kHeaderLength = 13; - - // kVarianceBlocks 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. - // - // 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 |kVarianceBlocks| - // blocks can vary based on the padding and on the hash used. This value - // must be derived from public information. - const size_t kVarianceBlocks = - ( 255 + 1 + // maximum padding bytes + padding length - md_size + // length of hash's output - md_block_size - 1 // ceiling - ) / md_block_size - + 1; // the 0x80 marker and the encoded message length could or not - // require an extra block; since the exact value depends on the - // message length; thus, one extra block is always added to run - // in constant time. - - // From now on we're dealing with the MAC, which conceptually has 13 - // bytes of `header' before the start of the data. - size_t len = data_plus_mac_plus_padding_size + kHeaderLength; - // max_mac_bytes contains the maximum bytes of bytes in the MAC, including - // |header|, assuming that there's no padding. - size_t max_mac_bytes = len - md_size - 1; - // num_blocks is the maximum number of hash blocks. - size_t 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 |kVarianceBlocks| 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. - size_t num_starting_blocks = 0; - // k is the starting byte offset into the conceptual header||data where - // we start processing. - size_t k = 0; - // mac_end_offset is the index just past the end of the data to be MACed. - size_t mac_end_offset = data_plus_mac_size + kHeaderLength - md_size; - // c is the index of the 0x80 byte in the final hash block that contains - // application data. - size_t c = mac_end_offset & (md_block_size - 1); - // index_a is the hash block number that contains the 0x80 terminating value. - size_t index_a = mac_end_offset >> md_block_shift; - // index_b is the hash block number that contains the 64-bit hash length, in - // bits. - size_t index_b = (mac_end_offset + md_length_size) >> md_block_shift; - - if (num_blocks > kVarianceBlocks) { - num_starting_blocks = num_blocks - kVarianceBlocks; - k = md_block_size * num_starting_blocks; + if (mac_secret_length > SHA_CBLOCK) { + // HMAC pads small keys with zeros and hashes large keys down. This function + // should never reach the large key case. + assert(0); + return 0; } - // bits is the hash-length in bits. It includes the additional hash - // block for the masked HMAC key. - size_t bits = 8 * mac_end_offset; // at most 18 bits to represent - // Compute the initial HMAC block. - bits += 8 * md_block_size; - // hmac_pad is the masked HMAC key. - uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE]; - OPENSSL_memset(hmac_pad, 0, md_block_size); - assert(mac_secret_length <= sizeof(hmac_pad)); + uint8_t hmac_pad[SHA_CBLOCK]; + OPENSSL_memset(hmac_pad, 0, sizeof(hmac_pad)); OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length); - for (size_t i = 0; i < md_block_size; i++) { + for (size_t i = 0; i < SHA_CBLOCK; i++) { hmac_pad[i] ^= 0x36; } - md_transform(&md_state, hmac_pad); - - // The length check means |bits| fits in four bytes. - uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES]; - OPENSSL_memset(length_bytes, 0, md_length_size - 4); - length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24); - length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16); - length_bytes[md_length_size - 2] = (uint8_t)(bits >> 8); - length_bytes[md_length_size - 1] = (uint8_t)bits; - - if (k > 0) { - // k is a multiple of md_block_size. - uint8_t first_block[MAX_HASH_BLOCK_SIZE]; - OPENSSL_memcpy(first_block, header, 13); - OPENSSL_memcpy(first_block + 13, data, md_block_size - 13); - md_transform(&md_state, first_block); - for (size_t i = 1; i < k / md_block_size; i++) { - md_transform(&md_state, data + md_block_size * i - 13); - } - } - - uint8_t mac_out[EVP_MAX_MD_SIZE]; - OPENSSL_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 (size_t i = num_starting_blocks; - i <= num_starting_blocks + kVarianceBlocks; i++) { - uint8_t block[MAX_HASH_BLOCK_SIZE]; - uint8_t is_block_a = constant_time_eq_8(i, index_a); - uint8_t is_block_b = constant_time_eq_8(i, index_b); - for (size_t j = 0; j < md_block_size; j++) { - uint8_t b = 0; - if (k < kHeaderLength) { - b = header[k]; - } else if (k < data_plus_mac_plus_padding_size + kHeaderLength) { - b = data[k - kHeaderLength]; - } - k++; - - uint8_t is_past_c = is_block_a & constant_time_ge_8(j, c); - uint8_t is_past_cp1 = is_block_a & constant_time_ge_8(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 the the block containing 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; - } + SHA_CTX ctx; + SHA1_Init(&ctx); + SHA1_Update(&ctx, hmac_pad, SHA_CBLOCK); + SHA1_Update(&ctx, header, 13); - md_transform(&md_state, block); - md_final_raw(&md_state, block); - // If this is index_b, copy the hash value to |mac_out|. - for (size_t j = 0; j < md_size; j++) { - mac_out[j] |= block[j] & is_block_b; - } + // There are at most 256 bytes of padding, so we can compute the public + // minimum length for |data_size|. + size_t min_data_size = 0; + if (data_plus_mac_plus_padding_size > SHA_DIGEST_LENGTH + 256) { + min_data_size = data_plus_mac_plus_padding_size - SHA_DIGEST_LENGTH - 256; } - EVP_MD_CTX md_ctx; - EVP_MD_CTX_init(&md_ctx); - if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) { - EVP_MD_CTX_cleanup(&md_ctx); + // Hash the public minimum length directly. This reduces the number of blocks + // that must be computed in constant-time. + SHA1_Update(&ctx, data, min_data_size); + + // Hash the remaining data without leaking |data_size|. + uint8_t mac_out[SHA_DIGEST_LENGTH]; + if (!EVP_sha1_final_with_secret_suffix( + &ctx, mac_out, data + min_data_size, data_size - min_data_size, + data_plus_mac_plus_padding_size - min_data_size)) { return 0; } // Complete the HMAC in the standard manner. - for (size_t i = 0; i < md_block_size; i++) { + SHA1_Init(&ctx); + for (size_t i = 0; i < SHA_CBLOCK; i++) { hmac_pad[i] ^= 0x6a; } - EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size); - EVP_DigestUpdate(&md_ctx, mac_out, md_size); - unsigned md_out_size_u; - EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u); - *md_out_size = md_out_size_u; - EVP_MD_CTX_cleanup(&md_ctx); - + SHA1_Update(&ctx, hmac_pad, SHA_CBLOCK); + SHA1_Update(&ctx, mac_out, SHA_DIGEST_LENGTH); + SHA1_Final(md_out, &ctx); + *md_out_size = SHA_DIGEST_LENGTH; return 1; } diff --git a/Sources/CNIOBoringSSL/crypto/err/err_data.c b/Sources/CNIOBoringSSL/crypto/err/err_data.c index 17baf113..5c3bd615 100644 --- a/Sources/CNIOBoringSSL/crypto/err/err_data.c +++ b/Sources/CNIOBoringSSL/crypto/err/err_data.c @@ -76,54 +76,54 @@ const uint32_t kOpenSSLReasonValues[] = { 0xc3b00f7, 0xc3b88e3, 0x10320854, - 0x103295b6, - 0x103315c2, - 0x103395db, - 0x103415ee, + 0x103295ca, + 0x103315d6, + 0x103395ef, + 0x10341602, 0x10348f34, 0x10350c6d, - 0x10359601, - 0x1036162b, - 0x1036963e, - 0x1037165d, - 0x10379676, - 0x1038168b, - 0x103896a9, - 0x103916b8, - 0x103996d4, - 0x103a16ef, - 0x103a96fe, - 0x103b171a, - 0x103b9735, - 0x103c175b, + 0x10359615, + 0x1036163f, + 0x10369652, + 0x10371671, + 0x1037968a, + 0x1038169f, + 0x103896bd, + 0x103916cc, + 0x103996e8, + 0x103a1703, + 0x103a9712, + 0x103b172e, + 0x103b9749, + 0x103c176f, 0x103c80f7, - 0x103d176c, - 0x103d9780, - 0x103e179f, - 0x103e97ae, - 0x103f17c5, - 0x103f97d8, + 0x103d1780, + 0x103d9794, + 0x103e17b3, + 0x103e97c2, + 0x103f17d9, + 0x103f97ec, 0x10400c31, - 0x104097eb, - 0x10411809, - 0x1041981c, - 0x10421836, - 0x10429846, - 0x1043185a, - 0x10439870, - 0x10441888, - 0x1044989d, - 0x104518b1, - 0x104598c3, + 0x104097ff, + 0x1041181d, + 0x10419830, + 0x1042184a, + 0x1042985a, + 0x1043186e, + 0x10439884, + 0x1044189c, + 0x104498b1, + 0x104518c5, + 0x104598d7, 0x1046060a, 0x1046895c, - 0x104718d8, - 0x104798ef, - 0x10481904, - 0x10489912, + 0x104718ec, + 0x10479903, + 0x10481918, + 0x10489926, 0x10490e80, - 0x1049974c, - 0x104a1616, + 0x10499760, + 0x104a162a, 0x14320c14, 0x14328c22, 0x14330c31, @@ -140,50 +140,51 @@ const uint32_t kOpenSSLReasonValues[] = { 0x18358feb, 0x18361000, 0x18369014, - 0x18371038, - 0x1837904e, - 0x18381062, - 0x18389072, + 0x1837104c, + 0x18379062, + 0x18381076, + 0x18389086, 0x18390a82, - 0x18399082, - 0x183a10a8, - 0x183a90ce, + 0x18399096, + 0x183a10bc, + 0x183a90e2, 0x183b0c8c, - 0x183b911d, - 0x183c112f, - 0x183c913a, - 0x183d114a, - 0x183d915b, - 0x183e116c, - 0x183e917e, - 0x183f11a7, - 0x183f91c0, - 0x184011d8, + 0x183b9131, + 0x183c1143, + 0x183c914e, + 0x183d115e, + 0x183d916f, + 0x183e1180, + 0x183e9192, + 0x183f11bb, + 0x183f91d4, + 0x184011ec, 0x184086e2, - 0x184110f1, - 0x184190bc, - 0x184210db, + 0x18411105, + 0x184190d0, + 0x184210ef, 0x18428c79, - 0x18431097, - 0x18439103, + 0x184310ab, + 0x18439117, 0x18440fc9, - 0x20321212, - 0x203291ff, - 0x2432121e, + 0x18449038, + 0x20321226, + 0x20329213, + 0x24321232, 0x243289a2, - 0x24331230, - 0x2433923d, - 0x2434124a, - 0x2434925c, - 0x2435126b, - 0x24359288, - 0x24361295, - 0x243692a3, - 0x243712b1, - 0x243792bf, - 0x243812c8, - 0x243892d5, - 0x243912e8, + 0x24331244, + 0x24339251, + 0x2434125e, + 0x24349270, + 0x2435127f, + 0x2435929c, + 0x243612a9, + 0x243692b7, + 0x243712c5, + 0x243792d3, + 0x243812dc, + 0x243892e9, + 0x243912fc, 0x28320c61, 0x28328c8c, 0x28330c31, @@ -192,47 +193,47 @@ const uint32_t kOpenSSLReasonValues[] = { 0x283480b9, 0x283500f7, 0x28358c79, - 0x2c3230e6, - 0x2c3292ff, - 0x2c3330f4, - 0x2c33b106, - 0x2c34311a, - 0x2c34b12c, - 0x2c353147, - 0x2c35b159, - 0x2c363189, + 0x2c3231de, + 0x2c329313, + 0x2c3331ec, + 0x2c33b1fe, + 0x2c343212, + 0x2c34b224, + 0x2c35323f, + 0x2c35b251, + 0x2c363281, 0x2c36833a, - 0x2c373196, - 0x2c37b1c2, - 0x2c3831e7, - 0x2c38b1fe, - 0x2c39321c, - 0x2c39b22c, - 0x2c3a323e, - 0x2c3ab252, - 0x2c3b3263, - 0x2c3bb282, - 0x2c3c1311, - 0x2c3c9327, - 0x2c3d3296, - 0x2c3d9340, - 0x2c3e32b3, - 0x2c3eb2c1, - 0x2c3f32d9, - 0x2c3fb2f1, - 0x2c40331b, - 0x2c409212, - 0x2c41332c, - 0x2c41b33f, - 0x2c4211d8, - 0x2c42b350, + 0x2c37328e, + 0x2c37b2ba, + 0x2c3832df, + 0x2c38b2f6, + 0x2c393314, + 0x2c39b324, + 0x2c3a3336, + 0x2c3ab34a, + 0x2c3b335b, + 0x2c3bb37a, + 0x2c3c1325, + 0x2c3c933b, + 0x2c3d338e, + 0x2c3d9354, + 0x2c3e33ab, + 0x2c3eb3b9, + 0x2c3f33d1, + 0x2c3fb3e9, + 0x2c403413, + 0x2c409226, + 0x2c413424, + 0x2c41b437, + 0x2c4211ec, + 0x2c42b448, 0x2c43072f, - 0x2c43b274, - 0x2c4431d5, - 0x2c44b2fe, - 0x2c45316c, - 0x2c45b1a8, - 0x2c46320c, + 0x2c43b36c, + 0x2c4432cd, + 0x2c44b3f6, + 0x2c453264, + 0x2c45b2a0, + 0x2c463304, 0x30320000, 0x30328015, 0x3033001f, @@ -368,248 +369,255 @@ const uint32_t kOpenSSLReasonValues[] = { 0x3c418d74, 0x3c420e80, 0x3c428e0a, - 0x403219a4, - 0x403299ba, - 0x403319e8, - 0x403399f2, - 0x40341a09, - 0x40349a27, - 0x40351a37, - 0x40359a49, - 0x40361a56, - 0x40369a62, - 0x40371a77, - 0x40379a89, - 0x40381a94, - 0x40389aa6, + 0x403219b8, + 0x403299ce, + 0x403319fc, + 0x40339a06, + 0x40341a1d, + 0x40349a3b, + 0x40351a4b, + 0x40359a5d, + 0x40361a6a, + 0x40369a76, + 0x40371a8b, + 0x40379a9d, + 0x40381aa8, + 0x40389aba, 0x40390f34, - 0x40399ab6, - 0x403a1ac9, - 0x403a9aea, - 0x403b1afb, - 0x403b9b0b, + 0x40399aca, + 0x403a1add, + 0x403a9afe, + 0x403b1b0f, + 0x403b9b1f, 0x403c0071, 0x403c8090, - 0x403d1b6c, - 0x403d9b82, - 0x403e1b91, - 0x403e9bc9, - 0x403f1be3, - 0x403f9c0b, - 0x40401c20, - 0x40409c34, - 0x40411c6f, - 0x40419c8a, - 0x40421ca3, - 0x40429cb6, - 0x40431cca, - 0x40439ce2, - 0x40441cf9, + 0x403d1b80, + 0x403d9b96, + 0x403e1ba5, + 0x403e9bdd, + 0x403f1bf7, + 0x403f9c1f, + 0x40401c34, + 0x40409c48, + 0x40411c83, + 0x40419c9e, + 0x40421cb7, + 0x40429cca, + 0x40431cde, + 0x40439d0c, + 0x40441d23, 0x404480b9, - 0x40451d0e, - 0x40459d20, - 0x40461d44, - 0x40469d64, - 0x40471d72, - 0x40479d99, - 0x40481e0a, - 0x40489e3d, - 0x40491e54, - 0x40499e6e, - 0x404a1e85, - 0x404a9ea3, - 0x404b1ebb, - 0x404b9ee8, - 0x404c1efe, - 0x404c9f10, - 0x404d1f31, - 0x404d9f6a, - 0x404e1f7e, - 0x404e9f8b, - 0x404f1fd2, - 0x404fa018, - 0x4050206f, - 0x4050a083, - 0x405120b6, - 0x405220c6, - 0x4052a0ea, - 0x40532102, - 0x4053a115, - 0x4054212a, - 0x4054a14d, - 0x40552178, - 0x4055a1b5, - 0x405621da, - 0x4056a1f3, - 0x4057220b, - 0x4057a21e, - 0x40582233, - 0x4058a25a, - 0x40592289, - 0x4059a2b6, - 0x405a22ca, - 0x405aa2da, - 0x405b22f2, - 0x405ba303, - 0x405c2316, - 0x405ca355, - 0x405d2362, - 0x405da387, - 0x405e23c5, + 0x40451d38, + 0x40459d4a, + 0x40461d6e, + 0x40469d8e, + 0x40471d9c, + 0x40479dc3, + 0x40481e34, + 0x40489ee1, + 0x40491ef8, + 0x40499f12, + 0x404a1f29, + 0x404a9f47, + 0x404b1f5f, + 0x404b9f8c, + 0x404c1fa2, + 0x404c9fb4, + 0x404d1fd5, + 0x404da00e, + 0x404e2022, + 0x404ea02f, + 0x404f20ac, + 0x404fa0f2, + 0x40502149, + 0x4050a15d, + 0x40512190, + 0x405221a0, + 0x4052a1c4, + 0x405321dc, + 0x4053a1ef, + 0x40542204, + 0x4054a227, + 0x40552252, + 0x4055a28f, + 0x405622b4, + 0x4056a2cd, + 0x405722e5, + 0x4057a2f8, + 0x4058230d, + 0x4058a334, + 0x40592363, + 0x4059a390, + 0x405a23a4, + 0x405aa3b4, + 0x405b23cc, + 0x405ba3dd, + 0x405c23f0, + 0x405ca42f, + 0x405d243c, + 0x405da461, + 0x405e249f, 0x405e8ac0, - 0x405f23e6, - 0x405fa3f3, - 0x40602401, - 0x4060a423, - 0x40612484, - 0x4061a4bc, - 0x406224d3, - 0x4062a4e4, - 0x40632531, - 0x4063a546, - 0x4064255d, - 0x4064a589, - 0x406525a4, - 0x4065a5bb, - 0x406625d3, - 0x4066a5fd, - 0x40672628, - 0x4067a66d, - 0x406826b5, - 0x4068a6d6, - 0x40692708, - 0x4069a736, - 0x406a2757, - 0x406aa777, - 0x406b28ff, - 0x406ba922, - 0x406c2938, - 0x406cac29, - 0x406d2c58, - 0x406dac80, - 0x406e2cae, - 0x406eacfb, - 0x406f2d54, - 0x406fad8c, - 0x40702d9f, - 0x4070adbc, + 0x405f24c0, + 0x405fa4cd, + 0x406024db, + 0x4060a4fd, + 0x4061255e, + 0x4061a596, + 0x406225ad, + 0x4062a5be, + 0x4063260b, + 0x4063a620, + 0x40642637, + 0x4064a663, + 0x4065267e, + 0x4065a695, + 0x406626ad, + 0x4066a6d7, + 0x40672702, + 0x4067a747, + 0x4068278f, + 0x4068a7b0, + 0x406927e2, + 0x4069a810, + 0x406a2831, + 0x406aa851, + 0x406b29d9, + 0x406ba9fc, + 0x406c2a12, + 0x406cad03, + 0x406d2d32, + 0x406dad5a, + 0x406e2d88, + 0x406eadd5, + 0x406f2e2e, + 0x406fae66, + 0x40702e79, + 0x4070ae96, 0x4071080f, - 0x4071adce, - 0x40722de1, - 0x4072ae17, - 0x40732e2f, - 0x40739511, - 0x40742e43, - 0x4074ae5d, - 0x40752e6e, - 0x4075ae82, - 0x40762e90, - 0x407692d5, - 0x40772eb5, - 0x4077aed7, - 0x40782ef2, - 0x4078af2b, - 0x40792f42, - 0x4079af58, - 0x407a2f84, - 0x407aaf97, - 0x407b2fac, - 0x407bafbe, - 0x407c2fef, - 0x407caff8, - 0x407d26f1, - 0x407da028, - 0x407e2f07, - 0x407ea26a, - 0x407f1d86, - 0x407f9ed2, - 0x40801fe2, - 0x40809dae, - 0x408120d8, - 0x40819fbc, - 0x40822c99, - 0x40829b17, - 0x40832245, - 0x4083a56e, - 0x40841dc2, - 0x4084a2a2, - 0x40852327, - 0x4085a44b, - 0x408623a7, - 0x4086a042, - 0x40872cdf, - 0x4087a499, - 0x40881b55, - 0x4088a680, - 0x40891ba4, - 0x40899b31, - 0x408a2970, - 0x408a9929, - 0x408b2fd3, - 0x408bad69, - 0x408c2337, - 0x408c9961, - 0x408d1e23, - 0x408d9df4, - 0x408e1f53, - 0x408ea195, - 0x408f2694, - 0x408fa467, - 0x40902649, - 0x4090a379, - 0x40912958, - 0x40919987, - 0x40921bf1, - 0x4092ad1a, - 0x40932dfa, - 0x4093a053, - 0x40941dd6, - 0x4094a989, - 0x409524f5, - 0x4095af64, - 0x40962cc6, - 0x40969ffb, - 0x4097209e, - 0x40979fa2, - 0x40981c51, - 0x4098a509, - 0x40992d36, - 0x4099a1c2, - 0x409a215b, - 0x409a9945, - 0x41f4282a, - 0x41f928bc, - 0x41fe27af, - 0x41feaa65, - 0x41ff2b7a, - 0x42032843, - 0x42082865, - 0x4208a8a1, - 0x42092793, - 0x4209a8db, - 0x420a27ea, - 0x420aa7ca, - 0x420b280a, - 0x420ba883, - 0x420c2b96, - 0x420ca999, - 0x420d2a4c, - 0x420daa83, - 0x42122a9d, - 0x42172b5d, - 0x4217aadf, - 0x421c2b01, - 0x421f2abc, - 0x42212c0e, - 0x42262b40, - 0x422b2bec, - 0x422baa27, - 0x422c2bce, - 0x422ca9da, - 0x422d29b3, - 0x422dabad, - 0x422e2a06, - 0x42302b1c, + 0x4071aea8, + 0x40722ebb, + 0x4072aef1, + 0x40732f09, + 0x40739525, + 0x40742f1d, + 0x4074af37, + 0x40752f48, + 0x4075af5c, + 0x40762f6a, + 0x407692e9, + 0x40772f8f, + 0x4077afcf, + 0x40782fea, + 0x4078b023, + 0x4079303a, + 0x4079b050, + 0x407a307c, + 0x407ab08f, + 0x407b30a4, + 0x407bb0b6, + 0x407c30e7, + 0x407cb0f0, + 0x407d27cb, + 0x407da102, + 0x407e2fff, + 0x407ea344, + 0x407f1db0, + 0x407f9f76, + 0x408020bc, + 0x40809dd8, + 0x408121b2, + 0x4081a060, + 0x40822d73, + 0x40829b2b, + 0x4083231f, + 0x4083a648, + 0x40841dec, + 0x4084a37c, + 0x40852401, + 0x4085a525, + 0x40862481, + 0x4086a11c, + 0x40872db9, + 0x4087a573, + 0x40881b69, + 0x4088a75a, + 0x40891bb8, + 0x40899b45, + 0x408a2a4a, + 0x408a993d, + 0x408b30cb, + 0x408bae43, + 0x408c2411, + 0x408c9975, + 0x408d1ec7, + 0x408d9e1e, + 0x408e1ff7, + 0x408ea26f, + 0x408f276e, + 0x408fa541, + 0x40902723, + 0x4090a453, + 0x40912a32, + 0x4091999b, + 0x40921c05, + 0x4092adf4, + 0x40932ed4, + 0x4093a12d, + 0x40941e00, + 0x4094aa63, + 0x409525cf, + 0x4095b05c, + 0x40962da0, + 0x4096a0d5, + 0x40972178, + 0x4097a046, + 0x40981c65, + 0x4098a5e3, + 0x40992e10, + 0x4099a29c, + 0x409a2235, + 0x409a9959, + 0x409b1e4d, + 0x409b9e78, + 0x409c2fb1, + 0x409c9ea0, + 0x409d2091, + 0x409da076, + 0x409e1cf6, + 0x41f42904, + 0x41f92996, + 0x41fe2889, + 0x41feab3f, + 0x41ff2c54, + 0x4203291d, + 0x4208293f, + 0x4208a97b, + 0x4209286d, + 0x4209a9b5, + 0x420a28c4, + 0x420aa8a4, + 0x420b28e4, + 0x420ba95d, + 0x420c2c70, + 0x420caa73, + 0x420d2b26, + 0x420dab5d, + 0x42122b77, + 0x42172c37, + 0x4217abb9, + 0x421c2bdb, + 0x421f2b96, + 0x42212ce8, + 0x42262c1a, + 0x422b2cc6, + 0x422bab01, + 0x422c2ca8, + 0x422caab4, + 0x422d2a8d, + 0x422dac87, + 0x422e2ae0, + 0x42302bf6, 0x4432073a, 0x44328749, 0x44330755, @@ -627,106 +635,106 @@ const uint32_t kOpenSSLReasonValues[] = { 0x4439080f, 0x4439881d, 0x443a0830, - 0x483212ff, - 0x48329311, - 0x48331327, - 0x48339340, - 0x4c321365, - 0x4c329375, - 0x4c331388, - 0x4c3393a8, + 0x48321313, + 0x48329325, + 0x4833133b, + 0x48339354, + 0x4c321379, + 0x4c329389, + 0x4c33139c, + 0x4c3393bc, 0x4c3400b9, 0x4c3480f7, - 0x4c3513b4, - 0x4c3593c2, - 0x4c3613de, - 0x4c369404, - 0x4c371413, - 0x4c379421, - 0x4c381436, - 0x4c389442, - 0x4c391462, - 0x4c39948c, - 0x4c3a14a5, - 0x4c3a94be, + 0x4c3513c8, + 0x4c3593d6, + 0x4c3613f2, + 0x4c369418, + 0x4c371427, + 0x4c379435, + 0x4c38144a, + 0x4c389456, + 0x4c391476, + 0x4c3994a0, + 0x4c3a14b9, + 0x4c3a94d2, 0x4c3b060a, - 0x4c3b94d7, - 0x4c3c14e9, - 0x4c3c94f8, - 0x4c3d1511, + 0x4c3b94eb, + 0x4c3c14fd, + 0x4c3c950c, + 0x4c3d1525, 0x4c3d8c54, - 0x4c3e157e, - 0x4c3e9520, - 0x4c3f15a0, - 0x4c3f92d5, - 0x4c401536, - 0x4c409351, - 0x4c41156e, - 0x4c4193f1, - 0x4c42155a, - 0x50323362, - 0x5032b371, - 0x5033337c, - 0x5033b38c, - 0x503433a5, - 0x5034b3bf, - 0x503533cd, - 0x5035b3e3, - 0x503633f5, - 0x5036b40b, - 0x50373424, - 0x5037b437, - 0x5038344f, - 0x5038b460, - 0x50393475, - 0x5039b489, - 0x503a34a9, - 0x503ab4bf, - 0x503b34d7, - 0x503bb4e9, - 0x503c3505, - 0x503cb51c, - 0x503d3535, - 0x503db54b, - 0x503e3558, - 0x503eb56e, - 0x503f3580, + 0x4c3e1592, + 0x4c3e9534, + 0x4c3f15b4, + 0x4c3f92e9, + 0x4c40154a, + 0x4c409365, + 0x4c411582, + 0x4c419405, + 0x4c42156e, + 0x5032345a, + 0x5032b469, + 0x50333474, + 0x5033b484, + 0x5034349d, + 0x5034b4b7, + 0x503534c5, + 0x5035b4db, + 0x503634ed, + 0x5036b503, + 0x5037351c, + 0x5037b52f, + 0x50383547, + 0x5038b558, + 0x5039356d, + 0x5039b581, + 0x503a35a1, + 0x503ab5b7, + 0x503b35cf, + 0x503bb5e1, + 0x503c35fd, + 0x503cb614, + 0x503d362d, + 0x503db643, + 0x503e3650, + 0x503eb666, + 0x503f3678, 0x503f8388, - 0x50403593, - 0x5040b5a3, - 0x504135bd, - 0x5041b5cc, - 0x504235e6, - 0x5042b603, - 0x50433613, - 0x5043b623, - 0x50443632, + 0x5040368b, + 0x5040b69b, + 0x504136b5, + 0x5041b6c4, + 0x504236de, + 0x5042b6fb, + 0x5043370b, + 0x5043b71b, + 0x5044372a, 0x5044843e, - 0x50453646, - 0x5045b664, - 0x50463677, - 0x5046b68d, - 0x5047369f, - 0x5047b6b4, - 0x504836da, - 0x5048b6e8, - 0x504936fb, - 0x5049b710, - 0x504a3726, - 0x504ab736, - 0x504b3756, - 0x504bb769, - 0x504c378c, - 0x504cb7ba, - 0x504d37cc, - 0x504db7e9, - 0x504e3804, - 0x504eb820, - 0x504f3832, - 0x504fb849, - 0x50503858, + 0x5045373e, + 0x5045b75c, + 0x5046376f, + 0x5046b785, + 0x50473797, + 0x5047b7ac, + 0x504837d2, + 0x5048b7e0, + 0x504937f3, + 0x5049b808, + 0x504a381e, + 0x504ab82e, + 0x504b384e, + 0x504bb861, + 0x504c3884, + 0x504cb8b2, + 0x504d38c4, + 0x504db8e1, + 0x504e38fc, + 0x504eb918, + 0x504f392a, + 0x504fb941, + 0x50503950, 0x505086fe, - 0x5051386b, + 0x50513963, 0x58320f72, 0x68320f34, 0x68328c8c, @@ -767,22 +775,22 @@ const uint32_t kOpenSSLReasonValues[] = { 0x783d8b59, 0x783e0aaf, 0x783e8a61, - 0x7c3211ee, - 0x80321404, + 0x7c321202, + 0x80321418, 0x80328090, - 0x803330b5, + 0x803331ad, 0x803380b9, - 0x803430c4, - 0x8034b02c, - 0x8035304a, - 0x8035b0d8, - 0x8036308c, - 0x8036b03b, - 0x8037307e, - 0x8037b019, - 0x8038309f, - 0x8038b05b, - 0x80393070, + 0x803431bc, + 0x8034b124, + 0x80353142, + 0x8035b1d0, + 0x80363184, + 0x8036b133, + 0x80373176, + 0x8037b111, + 0x80383197, + 0x8038b153, + 0x80393168, }; const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]); @@ -1004,6 +1012,7 @@ const char kOpenSSLReasonStringData[] = "EXPECTING_AN_RSA_KEY\0" "EXPECTING_A_DSA_KEY\0" "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0" + "INVALID_BUFFER_SIZE\0" "INVALID_DIGEST_LENGTH\0" "INVALID_DIGEST_TYPE\0" "INVALID_KEYBITS\0" @@ -1158,6 +1167,7 @@ const char kOpenSSLReasonStringData[] = "CLIENTHELLO_TLSEXT\0" "CONNECTION_REJECTED\0" "CONNECTION_TYPE_NOT_SET\0" + "COULD_NOT_PARSE_HINTS\0" "CUSTOM_EXTENSION_ERROR\0" "DATA_LENGTH_TOO_LONG\0" "DECRYPTION_FAILED\0" @@ -1172,6 +1182,9 @@ const char kOpenSSLReasonStringData[] = "DUPLICATE_SIGNATURE_ALGORITHM\0" "EARLY_DATA_NOT_IN_USE\0" "ECC_CERT_NOT_FOR_SIGNING\0" + "ECH_SERVER_CONFIG_AND_PRIVATE_KEY_MISMATCH\0" + "ECH_SERVER_CONFIG_UNSUPPORTED_EXTENSION\0" + "ECH_SERVER_WOULD_HAVE_NO_RETRY_CONFIGS\0" "EMPTY_HELLO_RETRY_REQUEST\0" "EMS_STATE_INCONSISTENT\0" "ENCRYPTED_LENGTH_TOO_LONG\0" @@ -1190,6 +1203,8 @@ const char kOpenSSLReasonStringData[] = "INAPPROPRIATE_FALLBACK\0" "INCONSISTENT_CLIENT_HELLO\0" "INVALID_ALPN_PROTOCOL\0" + "INVALID_ALPN_PROTOCOL_LIST\0" + "INVALID_CLIENT_HELLO_INNER\0" "INVALID_COMMAND\0" "INVALID_COMPRESSION_LIST\0" "INVALID_DELEGATED_CREDENTIAL\0" @@ -1336,6 +1351,7 @@ const char kOpenSSLReasonStringData[] = "UNKNOWN_STATE\0" "UNSAFE_LEGACY_RENEGOTIATION_DISABLED\0" "UNSUPPORTED_COMPRESSION_ALGORITHM\0" + "UNSUPPORTED_ECH_SERVER_CONFIG\0" "UNSUPPORTED_ELLIPTIC_CURVE\0" "UNSUPPORTED_PROTOCOL\0" "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\0" diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/bn/internal.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/bn/internal.h index 8fcc18ee..a06bd474 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/bn/internal.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/bn/internal.h @@ -297,7 +297,7 @@ void bn_mul_comba4(BN_ULONG r[8], const BN_ULONG a[4], const BN_ULONG b[4]); void bn_mul_comba8(BN_ULONG r[16], const BN_ULONG a[8], const BN_ULONG b[8]); // bn_sqr_comba8 sets |r| to |a|^2. -void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[4]); +void bn_sqr_comba8(BN_ULONG r[16], const BN_ULONG a[8]); // bn_sqr_comba4 sets |r| to |a|^2. void bn_sqr_comba4(BN_ULONG r[8], const BN_ULONG a[4]); diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/cipher/e_aes.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/cipher/e_aes.c index e7865be8..8f9fe0db 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/cipher/e_aes.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/cipher/e_aes.c @@ -141,10 +141,22 @@ typedef struct { static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, const uint8_t *iv, int enc) { - int ret, mode; + int ret; EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data; + const int mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK; + + if (mode == EVP_CIPH_CTR_MODE) { + switch (ctx->key_len) { + case 16: + boringssl_fips_inc_counter(fips_counter_evp_aes_128_ctr); + break; + + case 32: + boringssl_fips_inc_counter(fips_counter_evp_aes_256_ctr); + break; + } + } - mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK; if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { if (hwaes_capable()) { ret = aes_hw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks); @@ -353,6 +365,17 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key, if (!iv && !key) { return 1; } + + switch (ctx->key_len) { + case 16: + boringssl_fips_inc_counter(fips_counter_evp_aes_128_gcm); + break; + + case 32: + boringssl_fips_inc_counter(fips_counter_evp_aes_256_gcm); + break; + } + if (key) { OPENSSL_memset(&gctx->gcm, 0, sizeof(gctx->gcm)); gctx->ctr = aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm.gcm_key, NULL, key, diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digests.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digests.c index cffe1d76..fcc5d9e9 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digests.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digests.c @@ -247,13 +247,21 @@ static void sha512_256_init(EVP_MD_CTX *ctx) { CHECK(SHA512_256_Init(ctx->md_data)); } +static void sha512_256_update(EVP_MD_CTX *ctx, const void *data, size_t count) { + CHECK(SHA512_256_Update(ctx->md_data, data, count)); +} + +static void sha512_256_final(EVP_MD_CTX *ctx, uint8_t *md) { + CHECK(SHA512_256_Final(md, ctx->md_data)); +} + DEFINE_METHOD_FUNCTION(EVP_MD, EVP_sha512_256) { out->type = NID_sha512_256; out->md_size = SHA512_256_DIGEST_LENGTH; out->flags = 0; out->init = sha512_256_init; - out->update = sha512_update; - out->final = sha512_final; + out->update = sha512_256_update; + out->final = sha512_256_final; out->block_size = 128; out->ctx_size = sizeof(SHA512_CTX); } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/md32_common.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/md32_common.h index 861d9ef6..34b0a4ba 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/md32_common.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/md32_common.h @@ -136,44 +136,6 @@ extern "C" { #error "HASH_MAKE_STRING must be defined!" #endif -#if defined(DATA_ORDER_IS_BIG_ENDIAN) - -#define HOST_c2l(c, l) \ - do { \ - (l) = (((uint32_t)(*((c)++))) << 24); \ - (l) |= (((uint32_t)(*((c)++))) << 16); \ - (l) |= (((uint32_t)(*((c)++))) << 8); \ - (l) |= (((uint32_t)(*((c)++)))); \ - } while (0) - -#define HOST_l2c(l, c) \ - do { \ - *((c)++) = (uint8_t)(((l) >> 24) & 0xff); \ - *((c)++) = (uint8_t)(((l) >> 16) & 0xff); \ - *((c)++) = (uint8_t)(((l) >> 8) & 0xff); \ - *((c)++) = (uint8_t)(((l)) & 0xff); \ - } while (0) - -#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) - -#define HOST_c2l(c, l) \ - do { \ - (l) = (((uint32_t)(*((c)++)))); \ - (l) |= (((uint32_t)(*((c)++))) << 8); \ - (l) |= (((uint32_t)(*((c)++))) << 16); \ - (l) |= (((uint32_t)(*((c)++))) << 24); \ - } while (0) - -#define HOST_l2c(l, c) \ - do { \ - *((c)++) = (uint8_t)(((l)) & 0xff); \ - *((c)++) = (uint8_t)(((l) >> 8) & 0xff); \ - *((c)++) = (uint8_t)(((l) >> 16) & 0xff); \ - *((c)++) = (uint8_t)(((l) >> 24) & 0xff); \ - } while (0) - -#endif // DATA_ORDER - int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) { const uint8_t *data = data_; @@ -247,13 +209,12 @@ int HASH_FINAL(uint8_t out[HASH_DIGEST_LENGTH], HASH_CTX *c) { // Append a 64-bit length to the block and process it. uint8_t *p = c->data + HASH_CBLOCK - 8; #if defined(DATA_ORDER_IS_BIG_ENDIAN) - HOST_l2c(c->Nh, p); - HOST_l2c(c->Nl, p); + CRYPTO_store_u32_be(p, c->Nh); + CRYPTO_store_u32_be(p + 4, c->Nl); #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN) - HOST_l2c(c->Nl, p); - HOST_l2c(c->Nh, p); + CRYPTO_store_u32_le(p, c->Nl); + CRYPTO_store_u32_le(p + 4, c->Nh); #endif - assert(p == c->data + HASH_CBLOCK); HASH_BLOCK_DATA_ORDER(c->h, c->data, 1); c->num = 0; OPENSSL_memset(c->data, 0, HASH_CBLOCK); diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/is_fips.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/is_fips.c deleted file mode 100644 index 0fb74d8e..00000000 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/is_fips.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2017, Google Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -#include - - -// This file exists in order to give the fipsmodule target, in non-FIPS mode, -// something to compile. - -int FIPS_mode(void) { -#if defined(BORINGSSL_FIPS) && !defined(OPENSSL_ASAN) - return 1; -#else - return 0; -#endif -} - -int FIPS_mode_set(int on) { return on == FIPS_mode(); } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/md4/md4.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/md4/md4.c index 206c440e..ac1dd3a4 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/md4/md4.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/md4/md4.c @@ -92,17 +92,16 @@ void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num); #define HASH_UPDATE MD4_Update #define HASH_TRANSFORM MD4_Transform #define HASH_FINAL MD4_Final -#define HASH_MAKE_STRING(c, s) \ - do { \ - uint32_t ll; \ - ll = (c)->h[0]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[1]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[2]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[3]; \ - HOST_l2c(ll, (s)); \ +#define HASH_MAKE_STRING(c, s) \ + do { \ + CRYPTO_store_u32_le((s), (c)->h[0]); \ + (s) += 4; \ + CRYPTO_store_u32_le((s), (c)->h[1]); \ + (s) += 4; \ + CRYPTO_store_u32_le((s), (c)->h[2]); \ + (s) += 4; \ + CRYPTO_store_u32_le((s), (c)->h[3]); \ + (s) += 4; \ } while (0) #define HASH_BLOCK_DATA_ORDER md4_block_data_order @@ -136,7 +135,7 @@ void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num); } while (0) void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { - uint32_t A, B, C, D, l; + uint32_t A, B, C, D; uint32_t X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15; A = state[0]; @@ -145,53 +144,53 @@ void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { D = state[3]; for (; num--;) { - HOST_c2l(data, l); - X0 = l; - HOST_c2l(data, l); - X1 = l; + X0 = CRYPTO_load_u32_le(data); + data += 4; + X1 = CRYPTO_load_u32_le(data); + data += 4; // Round 0 R0(A, B, C, D, X0, 3, 0); - HOST_c2l(data, l); - X2 = l; + X2 = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X1, 7, 0); - HOST_c2l(data, l); - X3 = l; + X3 = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X2, 11, 0); - HOST_c2l(data, l); - X4 = l; + X4 = CRYPTO_load_u32_le(data); + data += 4; R0(B, C, D, A, X3, 19, 0); - HOST_c2l(data, l); - X5 = l; + X5 = CRYPTO_load_u32_le(data); + data += 4; R0(A, B, C, D, X4, 3, 0); - HOST_c2l(data, l); - X6 = l; + X6 = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X5, 7, 0); - HOST_c2l(data, l); - X7 = l; + X7 = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X6, 11, 0); - HOST_c2l(data, l); - X8 = l; + X8 = CRYPTO_load_u32_le(data); + data += 4; R0(B, C, D, A, X7, 19, 0); - HOST_c2l(data, l); - X9 = l; + X9 = CRYPTO_load_u32_le(data); + data += 4; R0(A, B, C, D, X8, 3, 0); - HOST_c2l(data, l); - X10 = l; + X10 = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X9, 7, 0); - HOST_c2l(data, l); - X11 = l; + X11 = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X10, 11, 0); - HOST_c2l(data, l); - X12 = l; + X12 = CRYPTO_load_u32_le(data); + data += 4; R0(B, C, D, A, X11, 19, 0); - HOST_c2l(data, l); - X13 = l; + X13 = CRYPTO_load_u32_le(data); + data += 4; R0(A, B, C, D, X12, 3, 0); - HOST_c2l(data, l); - X14 = l; + X14 = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X13, 7, 0); - HOST_c2l(data, l); - X15 = l; + X15 = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X14, 11, 0); R0(B, C, D, A, X15, 19, 0); // Round 1 @@ -252,5 +251,3 @@ void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { #undef R0 #undef R1 #undef R2 -#undef HOST_c2l -#undef HOST_l2c diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/md5/md5.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/md5/md5.c index 7c74f1f3..4a7a9094 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/md5/md5.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/md5/md5.c @@ -98,17 +98,16 @@ static void md5_block_data_order(uint32_t *state, const uint8_t *data, #define HASH_UPDATE MD5_Update #define HASH_TRANSFORM MD5_Transform #define HASH_FINAL MD5_Final -#define HASH_MAKE_STRING(c, s) \ - do { \ - uint32_t ll; \ - ll = (c)->h[0]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[1]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[2]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[3]; \ - HOST_l2c(ll, (s)); \ +#define HASH_MAKE_STRING(c, s) \ + do { \ + CRYPTO_store_u32_le((s), (c)->h[0]); \ + (s) += 4; \ + CRYPTO_store_u32_le((s), (c)->h[1]); \ + (s) += 4; \ + CRYPTO_store_u32_le((s), (c)->h[2]); \ + (s) += 4; \ + CRYPTO_store_u32_le((s), (c)->h[3]); \ + (s) += 4; \ } while (0) #define HASH_BLOCK_DATA_ORDER md5_block_data_order @@ -158,7 +157,7 @@ static void md5_block_data_order(uint32_t *state, const uint8_t *data, #endif static void md5_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { - uint32_t A, B, C, D, l; + uint32_t A, B, C, D; uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; #define X(i) XX##i @@ -169,53 +168,53 @@ static void md5_block_data_order(uint32_t *state, const uint8_t *data, D = state[3]; for (; num--;) { - HOST_c2l(data, l); - X(0) = l; - HOST_c2l(data, l); - X(1) = l; + X(0) = CRYPTO_load_u32_le(data); + data += 4; + X(1) = CRYPTO_load_u32_le(data); + data += 4; // Round 0 R0(A, B, C, D, X(0), 7, 0xd76aa478L); - HOST_c2l(data, l); - X(2) = l; + X(2) = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X(1), 12, 0xe8c7b756L); - HOST_c2l(data, l); - X(3) = l; + X(3) = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X(2), 17, 0x242070dbL); - HOST_c2l(data, l); - X(4) = l; + X(4) = CRYPTO_load_u32_le(data); + data += 4; R0(B, C, D, A, X(3), 22, 0xc1bdceeeL); - HOST_c2l(data, l); - X(5) = l; + X(5) = CRYPTO_load_u32_le(data); + data += 4; R0(A, B, C, D, X(4), 7, 0xf57c0fafL); - HOST_c2l(data, l); - X(6) = l; + X(6) = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X(5), 12, 0x4787c62aL); - HOST_c2l(data, l); - X(7) = l; + X(7) = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X(6), 17, 0xa8304613L); - HOST_c2l(data, l); - X(8) = l; + X(8) = CRYPTO_load_u32_le(data); + data += 4; R0(B, C, D, A, X(7), 22, 0xfd469501L); - HOST_c2l(data, l); - X(9) = l; + X(9) = CRYPTO_load_u32_le(data); + data += 4; R0(A, B, C, D, X(8), 7, 0x698098d8L); - HOST_c2l(data, l); - X(10) = l; + X(10) = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X(9), 12, 0x8b44f7afL); - HOST_c2l(data, l); - X(11) = l; + X(11) = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X(10), 17, 0xffff5bb1L); - HOST_c2l(data, l); - X(12) = l; + X(12) = CRYPTO_load_u32_le(data); + data += 4; R0(B, C, D, A, X(11), 22, 0x895cd7beL); - HOST_c2l(data, l); - X(13) = l; + X(13) = CRYPTO_load_u32_le(data); + data += 4; R0(A, B, C, D, X(12), 7, 0x6b901122L); - HOST_c2l(data, l); - X(14) = l; + X(14) = CRYPTO_load_u32_le(data); + data += 4; R0(D, A, B, C, X(13), 12, 0xfd987193L); - HOST_c2l(data, l); - X(15) = l; + X(15) = CRYPTO_load_u32_le(data); + data += 4; R0(C, D, A, B, X(14), 17, 0xa679438eL); R0(B, C, D, A, X(15), 22, 0x49b40821L); // Round 1 @@ -297,5 +296,3 @@ static void md5_block_data_order(uint32_t *state, const uint8_t *data, #undef R1 #undef R2 #undef R3 -#undef HOST_c2l -#undef HOST_l2c diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cbc.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cbc.c index ee6a2c8e..2afaa262 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cbc.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cbc.c @@ -52,20 +52,25 @@ #include #include "internal.h" +#include "../../internal.h" void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len, const AES_KEY *key, uint8_t ivec[16], block128_f block) { - size_t n; - const uint8_t *iv = ivec; - assert(key != NULL && ivec != NULL); - assert(len == 0 || (in != NULL && out != NULL)); + if (len == 0) { + // Avoid |ivec| == |iv| in the |memcpy| below, which is not legal in C. + return; + } + assert(in != NULL && out != NULL); + size_t n; + const uint8_t *iv = ivec; while (len >= 16) { - for (n = 0; n < 16; n += sizeof(size_t)) { - store_word_le(out + n, load_word_le(in + n) ^ load_word_le(iv + n)); + for (n = 0; n < 16; n += sizeof(crypto_word_t)) { + CRYPTO_store_word_le( + out + n, CRYPTO_load_word_le(in + n) ^ CRYPTO_load_word_le(iv + n)); } (*block)(out, out, key); iv = out; @@ -97,30 +102,36 @@ void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len, void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len, const AES_KEY *key, uint8_t ivec[16], block128_f block) { - size_t n; - union { - size_t t[16 / sizeof(size_t)]; - uint8_t c[16]; - } tmp; - assert(key != NULL && ivec != NULL); - assert(len == 0 || (in != NULL && out != NULL)); + if (len == 0) { + // Avoid |ivec| == |iv| in the |memcpy| below, which is not legal in C. + return; + } + + assert(in != NULL && out != NULL); const uintptr_t inptr = (uintptr_t) in; const uintptr_t outptr = (uintptr_t) out; // If |in| and |out| alias, |in| must be ahead. assert(inptr >= outptr || inptr + len <= outptr); + size_t n; + union { + crypto_word_t t[16 / sizeof(crypto_word_t)]; + uint8_t c[16]; + } tmp; + if ((inptr >= 32 && outptr <= inptr - 32) || inptr < outptr) { // If |out| is at least two blocks behind |in| or completely disjoint, there // is no need to decrypt to a temporary block. - OPENSSL_STATIC_ASSERT(16 % sizeof(size_t) == 0, + OPENSSL_STATIC_ASSERT(16 % sizeof(crypto_word_t) == 0, "block cannot be evenly divided into words"); const uint8_t *iv = ivec; while (len >= 16) { (*block)(in, out, key); - for (n = 0; n < 16; n += sizeof(size_t)) { - store_word_le(out + n, load_word_le(out + n) ^ load_word_le(iv + n)); + for (n = 0; n < 16; n += sizeof(crypto_word_t)) { + CRYPTO_store_word_le(out + n, CRYPTO_load_word_le(out + n) ^ + CRYPTO_load_word_le(iv + n)); } iv = in; len -= 16; @@ -129,16 +140,16 @@ void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len, } OPENSSL_memcpy(ivec, iv, 16); } else { - OPENSSL_STATIC_ASSERT(16 % sizeof(size_t) == 0, + OPENSSL_STATIC_ASSERT(16 % sizeof(crypto_word_t) == 0, "block cannot be evenly divided into words"); while (len >= 16) { (*block)(in, tmp.c, key); - for (n = 0; n < 16; n += sizeof(size_t)) { - size_t c = load_word_le(in + n); - store_word_le(out + n, - tmp.t[n / sizeof(size_t)] ^ load_word_le(ivec + n)); - store_word_le(ivec + n, c); + for (n = 0; n < 16; n += sizeof(crypto_word_t)) { + crypto_word_t c = CRYPTO_load_word_le(in + n); + CRYPTO_store_word_le(out + n, tmp.t[n / sizeof(crypto_word_t)] ^ + CRYPTO_load_word_le(ivec + n)); + CRYPTO_store_word_le(ivec + n, c); } len -= 16; in += 16; diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cfb.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cfb.c index 61b44a6b..9cb9c6ad 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cfb.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/cfb.c @@ -72,10 +72,11 @@ void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, } while (len >= 16) { (*block)(ivec, ivec, key); - for (; n < 16; n += sizeof(size_t)) { - size_t tmp = load_word_le(ivec + n) ^ load_word_le(in + n); - store_word_le(ivec + n, tmp); - store_word_le(out + n, tmp); + for (; n < 16; n += sizeof(crypto_word_t)) { + crypto_word_t tmp = + CRYPTO_load_word_le(ivec + n) ^ CRYPTO_load_word_le(in + n); + CRYPTO_store_word_le(ivec + n, tmp); + CRYPTO_store_word_le(out + n, tmp); } len -= 16; out += 16; @@ -101,10 +102,10 @@ void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, } while (len >= 16) { (*block)(ivec, ivec, key); - for (; n < 16; n += sizeof(size_t)) { - size_t t = load_word_le(in + n); - store_word_le(out + n, load_word_le(ivec + n) ^ t); - store_word_le(ivec + n, t); + for (; n < 16; n += sizeof(crypto_word_t)) { + crypto_word_t t = CRYPTO_load_word_le(in + n); + CRYPTO_store_word_le(out + n, CRYPTO_load_word_le(ivec + n) ^ t); + CRYPTO_store_word_le(ivec + n, t); } len -= 16; out += 16; diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ctr.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ctr.c index 6f1f0593..893a58d0 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ctr.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ctr.c @@ -52,6 +52,7 @@ #include #include "internal.h" +#include "../../internal.h" // NOTE: the IV/counter CTR mode is big-endian. The code itself @@ -69,8 +70,8 @@ static void ctr128_inc(uint8_t *counter) { } while (n); } -OPENSSL_STATIC_ASSERT(16 % sizeof(size_t) == 0, - "block cannot be divided into size_t"); +OPENSSL_STATIC_ASSERT(16 % sizeof(crypto_word_t) == 0, + "block cannot be divided into crypto_word_t"); // The input encrypted as though 128bit counter mode is being used. The extra // state information to record how much of the 128bit block we have used is @@ -102,9 +103,9 @@ void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len, while (len >= 16) { (*block)(ivec, ecount_buf, key); ctr128_inc(ivec); - for (n = 0; n < 16; n += sizeof(size_t)) { - store_word_le(out + n, - load_word_le(in + n) ^ load_word_le(ecount_buf + n)); + for (n = 0; n < 16; n += sizeof(crypto_word_t)) { + CRYPTO_store_word_le(out + n, CRYPTO_load_word_le(in + n) ^ + CRYPTO_load_word_le(ecount_buf + n)); } len -= 16; out += 16; @@ -152,7 +153,7 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len, n = (n + 1) % 16; } - ctr32 = GETU32(ivec + 12); + ctr32 = CRYPTO_load_u32_be(ivec + 12); while (len >= 16) { size_t blocks = len / 16; // 1<<28 is just a not-so-small yet not-so-large number... @@ -172,7 +173,7 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len, } (*func)(in, out, blocks, key, ivec); // (*func) does not update ivec, caller does: - PUTU32(ivec + 12, ctr32); + CRYPTO_store_u32_be(ivec + 12, ctr32); // ... overflow was detected, propogate carry. if (ctr32 == 0) { ctr96_inc(ivec); @@ -186,7 +187,7 @@ void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len, OPENSSL_memset(ecount_buf, 0, 16); (*func)(ecount_buf, ecount_buf, 1, key, ivec); ++ctr32; - PUTU32(ivec + 12, ctr32); + CRYPTO_store_u32_be(ivec + 12, ctr32); if (ctr32 == 0) { ctr96_inc(ivec); } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/gcm.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/gcm.c index 4b0b93dd..65bfde1a 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/gcm.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/gcm.c @@ -73,7 +73,7 @@ static const size_t kSizeTWithoutLower4Bits = (size_t) -16; #if defined(GHASH_ASM_X86_64) || defined(GHASH_ASM_X86) static inline void gcm_reduce_1bit(u128 *V) { - if (sizeof(size_t) == 8) { + if (sizeof(crypto_word_t) == 8) { uint64_t T = UINT64_C(0xe100000000000000) & (0 - (V->hi & 1)); V->hi = (V->lo << 63) | (V->hi >> 1); V->lo = (V->lo >> 1) ^ T; @@ -377,9 +377,10 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const AES_KEY *key, (*block)(ctx->Yi.c, ctx->EKi.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - for (size_t i = 0; i < 16; i += sizeof(size_t)) { - store_word_le(out + i, - load_word_le(in + i) ^ ctx->EKi.t[i / sizeof(size_t)]); + for (size_t i = 0; i < 16; i += sizeof(crypto_word_t)) { + CRYPTO_store_word_le(out + i, + CRYPTO_load_word_le(in + i) ^ + ctx->EKi.t[i / sizeof(crypto_word_t)]); } out += 16; in += 16; @@ -394,9 +395,10 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const AES_KEY *key, (*block)(ctx->Yi.c, ctx->EKi.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - for (size_t i = 0; i < 16; i += sizeof(size_t)) { - store_word_le(out + i, - load_word_le(in + i) ^ ctx->EKi.t[i / sizeof(size_t)]); + for (size_t i = 0; i < 16; i += sizeof(crypto_word_t)) { + CRYPTO_store_word_le(out + i, + CRYPTO_load_word_le(in + i) ^ + ctx->EKi.t[i / sizeof(crypto_word_t)]); } out += 16; in += 16; @@ -468,9 +470,10 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const AES_KEY *key, (*block)(ctx->Yi.c, ctx->EKi.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - for (size_t i = 0; i < 16; i += sizeof(size_t)) { - store_word_le(out + i, - load_word_le(in + i) ^ ctx->EKi.t[i / sizeof(size_t)]); + for (size_t i = 0; i < 16; i += sizeof(crypto_word_t)) { + CRYPTO_store_word_le(out + i, + CRYPTO_load_word_le(in + i) ^ + ctx->EKi.t[i / sizeof(crypto_word_t)]); } out += 16; in += 16; @@ -485,9 +488,10 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const AES_KEY *key, (*block)(ctx->Yi.c, ctx->EKi.c, key); ++ctr; ctx->Yi.d[3] = CRYPTO_bswap4(ctr); - for (size_t i = 0; i < 16; i += sizeof(size_t)) { - store_word_le(out + i, - load_word_le(in + i) ^ ctx->EKi.t[i / sizeof(size_t)]); + for (size_t i = 0; i < 16; i += sizeof(crypto_word_t)) { + CRYPTO_store_word_le(out + i, + CRYPTO_load_word_le(in + i) ^ + ctx->EKi.t[i / sizeof(crypto_word_t)]); } out += 16; in += 16; diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h index 92149db3..5e78e8ce 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h @@ -64,27 +64,6 @@ extern "C" { #endif -static inline uint32_t GETU32(const void *in) { - uint32_t v; - OPENSSL_memcpy(&v, in, sizeof(v)); - return CRYPTO_bswap4(v); -} - -static inline void PUTU32(void *out, uint32_t v) { - v = CRYPTO_bswap4(v); - OPENSSL_memcpy(out, &v, sizeof(v)); -} - -static inline size_t load_word_le(const void *in) { - size_t v; - OPENSSL_memcpy(&v, in, sizeof(v)); - return v; -} - -static inline void store_word_le(void *out, size_t v) { - OPENSSL_memcpy(out, &v, sizeof(v)); -} - // block128_f is the type of an AES block cipher implementation. // // Unlike upstream OpenSSL, it and the other functions in this file hard-code @@ -171,7 +150,7 @@ typedef struct { uint64_t u[2]; uint32_t d[4]; uint8_t c[16]; - size_t t[16 / sizeof(size_t)]; + crypto_word_t t[16 / sizeof(crypto_word_t)]; } Yi, EKi, EK0, len, Xi; // Note that the order of |Xi| and |gcm_key| is fixed by the MOVBE-based, diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ofb.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ofb.c index 1c7270e5..fd4078ff 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ofb.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/ofb.c @@ -60,7 +60,8 @@ OPENSSL_STATIC_ASSERT(16 % sizeof(size_t) == 0, void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len, const AES_KEY *key, uint8_t ivec[16], unsigned *num, block128_f block) { - assert(in && out && key && ivec && num); + assert(key != NULL && ivec != NULL && num != NULL); + assert(len == 0 || (in != NULL && out != NULL)); unsigned n = *num; diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/urandom.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/urandom.c index 0c838e9b..96d53ca7 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/urandom.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/urandom.c @@ -62,6 +62,15 @@ #include #endif +#if defined(OPENSSL_FREEBSD) +#define URANDOM_BLOCKS_FOR_ENTROPY +#if __FreeBSD__ >= 12 +// getrandom is supported in FreeBSD 12 and up. +#define FREEBSD_GETRANDOM +#include +#endif +#endif + #include #include @@ -176,6 +185,11 @@ static void init_once(void) { } #endif +#if defined(FREEBSD_GETRANDOM) + *urandom_fd_bss_get() = kHaveGetrandom; + return; +#endif + // Android FIPS builds must support getrandom. #if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID) perror("getrandom not found"); @@ -256,11 +270,11 @@ static void wait_for_entropy(void) { return; } -#if defined(BORINGSSL_FIPS) - // In FIPS mode we ensure that the kernel has sufficient entropy before - // continuing. This is automatically handled by getrandom, which requires - // that the entropy pool has been initialised, but for urandom we have to - // poll. +#if defined(BORINGSSL_FIPS) && !defined(URANDOM_BLOCKS_FOR_ENTROPY) + // In FIPS mode on platforms where urandom doesn't block at startup, we ensure + // that the kernel has sufficient entropy before continuing. This is + // automatically handled by getrandom, which requires that the entropy pool + // has been initialised, but for urandom we have to poll. for (;;) { int entropy_bits; if (ioctl(fd, RNDGETENTCNT, &entropy_bits)) { @@ -277,7 +291,7 @@ static void wait_for_entropy(void) { usleep(250000); } -#endif // BORINGSSL_FIPS +#endif // BORINGSSL_FIPS && !URANDOM_BLOCKS_FOR_ENTROPY } // fill_with_entropy writes |len| bytes of entropy into |out|. It returns one @@ -291,11 +305,14 @@ static int fill_with_entropy(uint8_t *out, size_t len, int block, int seed) { return 1; } -#if defined(USE_NR_getrandom) +#if defined(USE_NR_getrandom) || defined(FREEBSD_GETRANDOM) int getrandom_flags = 0; if (!block) { getrandom_flags |= GRND_NONBLOCK; } +#endif + +#if defined (USE_NR_getrandom) if (seed) { getrandom_flags |= *extra_getrandom_flags_for_seed_bss_get(); } @@ -315,6 +332,8 @@ static int fill_with_entropy(uint8_t *out, size_t len, int block, int seed) { if (*urandom_fd_bss_get() == kHaveGetrandom) { #if defined(USE_NR_getrandom) r = boringssl_getrandom(out, len, getrandom_flags); +#elif defined(FREEBSD_GETRANDOM) + r = getrandom(out, len, getrandom_flags); #elif defined(OPENSSL_MACOS) if (__builtin_available(macos 10.12, *)) { // |getentropy| can only request 256 bytes at a time. diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/fips.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/fips.c new file mode 100644 index 00000000..8f56e02d --- /dev/null +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/fips.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2017, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include + +#include "../../internal.h" +#include "../delocate.h" + + +int FIPS_mode(void) { +#if defined(BORINGSSL_FIPS) && !defined(OPENSSL_ASAN) + return 1; +#else + return 0; +#endif +} + +int FIPS_mode_set(int on) { return on == FIPS_mode(); } + +#if defined(BORINGSSL_FIPS_COUNTERS) + +size_t FIPS_read_counter(enum fips_counter_t counter) { + if (counter < 0 || counter > fips_counter_max) { + abort(); + } + + const size_t *array = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_FIPS_COUNTERS); + if (!array) { + return 0; + } + + return array[counter]; +} + +void boringssl_fips_inc_counter(enum fips_counter_t counter) { + if (counter < 0 || counter > fips_counter_max) { + abort(); + } + + size_t *array = + CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_FIPS_COUNTERS); + if (!array) { + const size_t num_bytes = sizeof(size_t) * (fips_counter_max + 1); + array = OPENSSL_malloc(num_bytes); + if (!array) { + return; + } + + OPENSSL_memset(array, 0, num_bytes); + if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_FIPS_COUNTERS, array, + OPENSSL_free)) { + // |OPENSSL_free| has already been called by |CRYPTO_set_thread_local|. + return; + } + } + + array[counter]++; +} + +#else + +size_t FIPS_read_counter(enum fips_counter_t counter) { return 0; } + +// boringssl_fips_inc_counter is a no-op, inline function in internal.h in this +// case. That should let the compiler optimise away the callsites. + +#endif diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/self_check.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/self_check.c index 10b87f65..72b79236 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/self_check.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/self_check/self_check.c @@ -40,8 +40,14 @@ // MSVC wants to put a NUL byte at the end of non-char arrays and so cannot -// compile this. -#if !defined(_MSC_VER) +// compile the real logic. +#if defined(_MSC_VER) + +int BORINGSSL_self_test(void) { + return 0; +} + +#else #if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID) // FIPS builds on Android will test for flag files, named after the module hash, diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.c index 71622878..70a39058 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.c @@ -88,19 +88,18 @@ uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t out[SHA_DIGEST_LENGTH]) { #define HASH_CTX SHA_CTX #define HASH_CBLOCK 64 #define HASH_DIGEST_LENGTH 20 -#define HASH_MAKE_STRING(c, s) \ - do { \ - uint32_t ll; \ - ll = (c)->h[0]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[1]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[2]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[3]; \ - HOST_l2c(ll, (s)); \ - ll = (c)->h[4]; \ - HOST_l2c(ll, (s)); \ +#define HASH_MAKE_STRING(c, s) \ + do { \ + CRYPTO_store_u32_be((s), (c)->h[0]); \ + (s) += 4; \ + CRYPTO_store_u32_be((s), (c)->h[1]); \ + (s) += 4; \ + CRYPTO_store_u32_be((s), (c)->h[2]); \ + (s) += 4; \ + CRYPTO_store_u32_be((s), (c)->h[3]); \ + (s) += 4; \ + CRYPTO_store_u32_be((s), (c)->h[4]); \ + (s) += 4; \ } while (0) #define HASH_UPDATE SHA1_Update @@ -193,7 +192,7 @@ static void sha1_block_data_order(uint32_t *state, const uint8_t *data, #if !defined(SHA1_ASM) static void sha1_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { - register uint32_t A, B, C, D, E, T, l; + register uint32_t A, B, C, D, E, T; uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12, XX13, XX14, XX15; @@ -204,52 +203,52 @@ static void sha1_block_data_order(uint32_t *state, const uint8_t *data, E = state[4]; for (;;) { - HOST_c2l(data, l); - X(0) = l; - HOST_c2l(data, l); - X(1) = l; + X(0) = CRYPTO_load_u32_be(data); + data += 4; + X(1) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(0, A, B, C, D, E, T, X(0)); - HOST_c2l(data, l); - X(2) = l; + X(2) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(1, T, A, B, C, D, E, X(1)); - HOST_c2l(data, l); - X(3) = l; + X(3) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(2, E, T, A, B, C, D, X(2)); - HOST_c2l(data, l); - X(4) = l; + X(4) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(3, D, E, T, A, B, C, X(3)); - HOST_c2l(data, l); - X(5) = l; + X(5) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(4, C, D, E, T, A, B, X(4)); - HOST_c2l(data, l); - X(6) = l; + X(6) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(5, B, C, D, E, T, A, X(5)); - HOST_c2l(data, l); - X(7) = l; + X(7) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(6, A, B, C, D, E, T, X(6)); - HOST_c2l(data, l); - X(8) = l; + X(8) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(7, T, A, B, C, D, E, X(7)); - HOST_c2l(data, l); - X(9) = l; + X(9) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(8, E, T, A, B, C, D, X(8)); - HOST_c2l(data, l); - X(10) = l; + X(10) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(9, D, E, T, A, B, C, X(9)); - HOST_c2l(data, l); - X(11) = l; + X(11) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(10, C, D, E, T, A, B, X(10)); - HOST_c2l(data, l); - X(12) = l; + X(12) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(11, B, C, D, E, T, A, X(11)); - HOST_c2l(data, l); - X(13) = l; + X(13) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(12, A, B, C, D, E, T, X(12)); - HOST_c2l(data, l); - X(14) = l; + X(14) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(13, T, A, B, C, D, E, X(13)); - HOST_c2l(data, l); - X(15) = l; + X(15) = CRYPTO_load_u32_be(data); + data += 4; BODY_00_15(14, E, T, A, B, C, D, X(14)); BODY_00_15(15, D, E, T, A, B, C, X(15)); @@ -367,5 +366,3 @@ static void sha1_block_data_order(uint32_t *state, const uint8_t *data, #undef BODY_40_59 #undef BODY_60_79 #undef X -#undef HOST_c2l -#undef HOST_l2c diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.c index d21c4f84..8e99f0c7 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.c @@ -139,19 +139,18 @@ int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], SHA256_CTX *ctx) { // hash 'final' function can fail. This should never happen. #define HASH_MAKE_STRING(c, s) \ do { \ - uint32_t ll; \ unsigned int nn; \ switch ((c)->md_len) { \ case SHA224_DIGEST_LENGTH: \ for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) { \ - ll = (c)->h[nn]; \ - HOST_l2c(ll, (s)); \ + CRYPTO_store_u32_be((s), (c)->h[nn]); \ + (s) += 4; \ } \ break; \ case SHA256_DIGEST_LENGTH: \ for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) { \ - ll = (c)->h[nn]; \ - HOST_l2c(ll, (s)); \ + CRYPTO_store_u32_be((s), (c)->h[nn]); \ + (s) += 4; \ } \ break; \ default: \ @@ -159,8 +158,8 @@ int SHA224_Final(uint8_t out[SHA224_DIGEST_LENGTH], SHA256_CTX *ctx) { return 0; \ } \ for (nn = 0; nn < (c)->md_len / 4; nn++) { \ - ll = (c)->h[nn]; \ - HOST_l2c(ll, (s)); \ + CRYPTO_store_u32_be((s), (c)->h[nn]); \ + (s) += 4; \ } \ break; \ } \ @@ -241,55 +240,53 @@ static void sha256_block_data_order(uint32_t *state, const uint8_t *data, g = state[6]; h = state[7]; - uint32_t l; - - HOST_c2l(data, l); - T1 = X[0] = l; + T1 = X[0] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(0, a, b, c, d, e, f, g, h); - HOST_c2l(data, l); - T1 = X[1] = l; + T1 = X[1] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(1, h, a, b, c, d, e, f, g); - HOST_c2l(data, l); - T1 = X[2] = l; + T1 = X[2] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(2, g, h, a, b, c, d, e, f); - HOST_c2l(data, l); - T1 = X[3] = l; + T1 = X[3] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(3, f, g, h, a, b, c, d, e); - HOST_c2l(data, l); - T1 = X[4] = l; + T1 = X[4] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(4, e, f, g, h, a, b, c, d); - HOST_c2l(data, l); - T1 = X[5] = l; + T1 = X[5] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(5, d, e, f, g, h, a, b, c); - HOST_c2l(data, l); - T1 = X[6] = l; + T1 = X[6] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(6, c, d, e, f, g, h, a, b); - HOST_c2l(data, l); - T1 = X[7] = l; + T1 = X[7] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(7, b, c, d, e, f, g, h, a); - HOST_c2l(data, l); - T1 = X[8] = l; + T1 = X[8] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(8, a, b, c, d, e, f, g, h); - HOST_c2l(data, l); - T1 = X[9] = l; + T1 = X[9] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(9, h, a, b, c, d, e, f, g); - HOST_c2l(data, l); - T1 = X[10] = l; + T1 = X[10] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(10, g, h, a, b, c, d, e, f); - HOST_c2l(data, l); - T1 = X[11] = l; + T1 = X[11] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(11, f, g, h, a, b, c, d, e); - HOST_c2l(data, l); - T1 = X[12] = l; + T1 = X[12] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(12, e, f, g, h, a, b, c, d); - HOST_c2l(data, l); - T1 = X[13] = l; + T1 = X[13] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(13, d, e, f, g, h, a, b, c); - HOST_c2l(data, l); - T1 = X[14] = l; + T1 = X[14] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(14, c, d, e, f, g, h, a, b); - HOST_c2l(data, l); - T1 = X[15] = l; + T1 = X[15] = CRYPTO_load_u32_be(data); + data += 4; ROUND_00_15(15, b, c, d, e, f, g, h, a); for (i = 16; i < 64; i += 8) { @@ -339,5 +336,3 @@ void SHA256_TransformBlocks(uint32_t state[8], const uint8_t *data, #undef Maj #undef ROUND_00_15 #undef ROUND_16_63 -#undef HOST_c2l -#undef HOST_l2c diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.c index ae2d22eb..62fdde77 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.c @@ -70,6 +70,8 @@ // this writing, so there is no need for a common collector/padding // implementation yet. +static int sha512_final_impl(uint8_t *out, SHA512_CTX *sha); + int SHA384_Init(SHA512_CTX *sha) { sha->h[0] = UINT64_C(0xcbbb9d5dc1059ed8); sha->h[1] = UINT64_C(0x629a292a367cd507); @@ -146,8 +148,8 @@ uint8_t *SHA512_256(const uint8_t *data, size_t len, uint8_t out[SHA512_256_DIGEST_LENGTH]) { SHA512_CTX ctx; SHA512_256_Init(&ctx); - SHA512_Update(&ctx, data, len); - SHA512_Final(out, &ctx); + SHA512_256_Update(&ctx, data, len); + SHA512_256_Final(out, &ctx); OPENSSL_cleanse(&ctx, sizeof(ctx)); return out; } @@ -161,7 +163,8 @@ static void sha512_block_data_order(uint64_t *state, const uint8_t *in, int SHA384_Final(uint8_t out[SHA384_DIGEST_LENGTH], SHA512_CTX *sha) { // |SHA384_Init| sets |sha->md_len| to |SHA384_DIGEST_LENGTH|, so this has a // |smaller output. - return SHA512_Final(out, sha); + assert(sha->md_len == SHA384_DIGEST_LENGTH); + return sha512_final_impl(out, sha); } int SHA384_Update(SHA512_CTX *sha, const void *data, size_t len) { @@ -172,11 +175,11 @@ int SHA512_256_Update(SHA512_CTX *sha, const void *data, size_t len) { return SHA512_Update(sha, data, len); } -int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], - SHA512_CTX *sha) { +int SHA512_256_Final(uint8_t out[SHA512_256_DIGEST_LENGTH], SHA512_CTX *sha) { // |SHA512_256_Init| sets |sha->md_len| to |SHA512_256_DIGEST_LENGTH|, so this // has a |smaller output. - return SHA512_Final(out, sha); + assert(sha->md_len == SHA512_256_DIGEST_LENGTH); + return sha512_final_impl(out, sha); } void SHA512_Transform(SHA512_CTX *c, const uint8_t block[SHA512_CBLOCK]) { @@ -232,6 +235,15 @@ int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) { } int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], SHA512_CTX *sha) { + // Ideally we would assert |sha->md_len| is |SHA512_DIGEST_LENGTH| to match + // the size hint, but calling code often pairs |SHA384_Init| with + // |SHA512_Final| and expects |sha->md_len| to carry the over. + // + // TODO(davidben): Add an assert and fix code to match them up. + return sha512_final_impl(out, sha); +} + +static int sha512_final_impl(uint8_t *out, SHA512_CTX *sha) { uint8_t *p = sha->p; size_t n = sha->num; @@ -244,22 +256,8 @@ int SHA512_Final(uint8_t out[SHA512_DIGEST_LENGTH], SHA512_CTX *sha) { } OPENSSL_memset(p + n, 0, sizeof(sha->p) - 16 - n); - p[sizeof(sha->p) - 1] = (uint8_t)(sha->Nl); - p[sizeof(sha->p) - 2] = (uint8_t)(sha->Nl >> 8); - p[sizeof(sha->p) - 3] = (uint8_t)(sha->Nl >> 16); - p[sizeof(sha->p) - 4] = (uint8_t)(sha->Nl >> 24); - p[sizeof(sha->p) - 5] = (uint8_t)(sha->Nl >> 32); - p[sizeof(sha->p) - 6] = (uint8_t)(sha->Nl >> 40); - p[sizeof(sha->p) - 7] = (uint8_t)(sha->Nl >> 48); - p[sizeof(sha->p) - 8] = (uint8_t)(sha->Nl >> 56); - p[sizeof(sha->p) - 9] = (uint8_t)(sha->Nh); - p[sizeof(sha->p) - 10] = (uint8_t)(sha->Nh >> 8); - p[sizeof(sha->p) - 11] = (uint8_t)(sha->Nh >> 16); - p[sizeof(sha->p) - 12] = (uint8_t)(sha->Nh >> 24); - p[sizeof(sha->p) - 13] = (uint8_t)(sha->Nh >> 32); - p[sizeof(sha->p) - 14] = (uint8_t)(sha->Nh >> 40); - p[sizeof(sha->p) - 15] = (uint8_t)(sha->Nh >> 48); - p[sizeof(sha->p) - 16] = (uint8_t)(sha->Nh >> 56); + CRYPTO_store_u64_be(p + sizeof(sha->p) - 16, sha->Nh); + CRYPTO_store_u64_be(p + sizeof(sha->p) - 8, sha->Nl); sha512_block_data_order(sha->h, p, 1); @@ -356,12 +354,6 @@ static const uint64_t K512[80] = { #define ROTR(x, s) (((x) >> s) | (x) << (64 - s)) #endif -static inline uint64_t load_u64_be(const void *ptr) { - uint64_t ret; - OPENSSL_memcpy(&ret, ptr, sizeof(ret)); - return CRYPTO_bswap8(ret); -} - #define Sigma0(x) (ROTR((x), 28) ^ ROTR((x), 34) ^ ROTR((x), 39)) #define Sigma1(x) (ROTR((x), 14) ^ ROTR((x), 18) ^ ROTR((x), 41)) #define sigma0(x) (ROTR((x), 1) ^ ROTR((x), 8) ^ ((x) >> 7)) @@ -392,7 +384,7 @@ static void sha512_block_data_order(uint64_t *state, const uint8_t *in, F[7] = state[7]; for (i = 0; i < 16; i++, F--) { - T = load_u64_be(in + i * 8); + T = CRYPTO_load_u64_be(in + i * 8); F[0] = A; F[4] = E; F[8] = T; @@ -464,37 +456,37 @@ static void sha512_block_data_order(uint64_t *state, const uint8_t *in, g = state[6]; h = state[7]; - T1 = X[0] = load_u64_be(in); + T1 = X[0] = CRYPTO_load_u64_be(in); ROUND_00_15(0, a, b, c, d, e, f, g, h); - T1 = X[1] = load_u64_be(in + 8); + T1 = X[1] = CRYPTO_load_u64_be(in + 8); ROUND_00_15(1, h, a, b, c, d, e, f, g); - T1 = X[2] = load_u64_be(in + 2 * 8); + T1 = X[2] = CRYPTO_load_u64_be(in + 2 * 8); ROUND_00_15(2, g, h, a, b, c, d, e, f); - T1 = X[3] = load_u64_be(in + 3 * 8); + T1 = X[3] = CRYPTO_load_u64_be(in + 3 * 8); ROUND_00_15(3, f, g, h, a, b, c, d, e); - T1 = X[4] = load_u64_be(in + 4 * 8); + T1 = X[4] = CRYPTO_load_u64_be(in + 4 * 8); ROUND_00_15(4, e, f, g, h, a, b, c, d); - T1 = X[5] = load_u64_be(in + 5 * 8); + T1 = X[5] = CRYPTO_load_u64_be(in + 5 * 8); ROUND_00_15(5, d, e, f, g, h, a, b, c); - T1 = X[6] = load_u64_be(in + 6 * 8); + T1 = X[6] = CRYPTO_load_u64_be(in + 6 * 8); ROUND_00_15(6, c, d, e, f, g, h, a, b); - T1 = X[7] = load_u64_be(in + 7 * 8); + T1 = X[7] = CRYPTO_load_u64_be(in + 7 * 8); ROUND_00_15(7, b, c, d, e, f, g, h, a); - T1 = X[8] = load_u64_be(in + 8 * 8); + T1 = X[8] = CRYPTO_load_u64_be(in + 8 * 8); ROUND_00_15(8, a, b, c, d, e, f, g, h); - T1 = X[9] = load_u64_be(in + 9 * 8); + T1 = X[9] = CRYPTO_load_u64_be(in + 9 * 8); ROUND_00_15(9, h, a, b, c, d, e, f, g); - T1 = X[10] = load_u64_be(in + 10 * 8); + T1 = X[10] = CRYPTO_load_u64_be(in + 10 * 8); ROUND_00_15(10, g, h, a, b, c, d, e, f); - T1 = X[11] = load_u64_be(in + 11 * 8); + T1 = X[11] = CRYPTO_load_u64_be(in + 11 * 8); ROUND_00_15(11, f, g, h, a, b, c, d, e); - T1 = X[12] = load_u64_be(in + 12 * 8); + T1 = X[12] = CRYPTO_load_u64_be(in + 12 * 8); ROUND_00_15(12, e, f, g, h, a, b, c, d); - T1 = X[13] = load_u64_be(in + 13 * 8); + T1 = X[13] = CRYPTO_load_u64_be(in + 13 * 8); ROUND_00_15(13, d, e, f, g, h, a, b, c); - T1 = X[14] = load_u64_be(in + 14 * 8); + T1 = X[14] = CRYPTO_load_u64_be(in + 14 * 8); ROUND_00_15(14, c, d, e, f, g, h, a, b); - T1 = X[15] = load_u64_be(in + 15 * 8); + T1 = X[15] = CRYPTO_load_u64_be(in + 15 * 8); ROUND_00_15(15, b, c, d, e, f, g, h, a); for (i = 16; i < 80; i += 16) { diff --git a/Sources/CNIOBoringSSL/crypto/hpke/hpke.c b/Sources/CNIOBoringSSL/crypto/hpke/hpke.c index 7ee357f9..93cd0c2f 100644 --- a/Sources/CNIOBoringSSL/crypto/hpke/hpke.c +++ b/Sources/CNIOBoringSSL/crypto/hpke/hpke.c @@ -17,9 +17,10 @@ #include #include +#include #include #include -#include +#include #include #include @@ -31,9 +32,6 @@ #define KEM_CONTEXT_LEN (2 * X25519_PUBLIC_VALUE_LEN) -// HPKE KEM scheme IDs. -#define HPKE_DHKEM_X25519_HKDF_SHA256 0x0020 - // This is strlen("HPKE") + 3 * sizeof(uint16_t). #define HPKE_SUITE_ID_LEN 10 @@ -50,8 +48,8 @@ static int add_label_string(CBB *cbb, const char *label) { // that the suite_id used outside of the KEM also includes the kdf_id and // aead_id. static const uint8_t kX25519SuiteID[] = { - 'K', 'E', 'M', HPKE_DHKEM_X25519_HKDF_SHA256 >> 8, - HPKE_DHKEM_X25519_HKDF_SHA256 & 0x00ff}; + 'K', 'E', 'M', EVP_HPKE_DHKEM_X25519_HKDF_SHA256 >> 8, + EVP_HPKE_DHKEM_X25519_HKDF_SHA256 & 0x00ff}; // The suite_id for non-KEM pieces of HPKE is defined as concat("HPKE", // I2OSP(kem_id, 2), I2OSP(kdf_id, 2), I2OSP(aead_id, 2)). @@ -60,7 +58,7 @@ static int hpke_build_suite_id(uint8_t out[HPKE_SUITE_ID_LEN], uint16_t kdf_id, CBB cbb; int ret = CBB_init_fixed(&cbb, out, HPKE_SUITE_ID_LEN) && add_label_string(&cbb, "HPKE") && - CBB_add_u16(&cbb, HPKE_DHKEM_X25519_HKDF_SHA256) && + CBB_add_u16(&cbb, EVP_HPKE_DHKEM_X25519_HKDF_SHA256) && CBB_add_u16(&cbb, kdf_id) && CBB_add_u16(&cbb, aead_id); CBB_cleanup(&cbb); @@ -125,11 +123,19 @@ static int hpke_extract_and_expand(const EVP_MD *hkdf_md, uint8_t *out_key, return 1; } +uint16_t EVP_HPKE_CTX_get_aead_id(const EVP_HPKE_CTX *hpke) { + return hpke->aead_id; +} + +uint16_t EVP_HPKE_CTX_get_kdf_id(const EVP_HPKE_CTX *hpke) { + return hpke->kdf_id; +} + const EVP_AEAD *EVP_HPKE_get_aead(uint16_t aead_id) { switch (aead_id) { - case EVP_HPKE_AEAD_AES_GCM_128: + case EVP_HPKE_AEAD_AES_128_GCM: return EVP_aead_aes_128_gcm(); - case EVP_HPKE_AEAD_AES_GCM_256: + case EVP_HPKE_AEAD_AES_256_GCM: return EVP_aead_aes_256_gcm(); case EVP_HPKE_AEAD_CHACHA20POLY1305: return EVP_aead_chacha20_poly1305(); @@ -316,27 +322,44 @@ void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx) { EVP_AEAD_CTX_cleanup(&ctx->aead_ctx); } -int EVP_HPKE_CTX_setup_base_s_x25519( - EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN], - uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], - const uint8_t *info, size_t info_len) { +int EVP_HPKE_CTX_setup_base_s_x25519(EVP_HPKE_CTX *hpke, uint8_t *out_enc, + size_t out_enc_len, uint16_t kdf_id, + uint16_t aead_id, + const uint8_t *peer_public_value, + size_t peer_public_value_len, + const uint8_t *info, size_t info_len) { + if (out_enc_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); + return 0; + } + // The GenerateKeyPair() step technically belongs in the KEM's Encap() // function, but we've moved it up a layer to make it easier for tests to // inject an ephemeral keypair. uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN]; X25519_keypair(out_enc, ephemeral_private); return EVP_HPKE_CTX_setup_base_s_x25519_for_test( - hpke, kdf_id, aead_id, peer_public_value, info, info_len, - ephemeral_private, out_enc); + hpke, kdf_id, aead_id, peer_public_value, peer_public_value_len, info, + info_len, ephemeral_private, sizeof(ephemeral_private), out_enc, + out_enc_len); } int EVP_HPKE_CTX_setup_base_s_x25519_for_test( EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], - const uint8_t *info, size_t info_len, - const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN], - const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]) { + const uint8_t *peer_public_value, size_t peer_public_value_len, + const uint8_t *info, size_t info_len, const uint8_t *ephemeral_private, + size_t ephemeral_private_len, const uint8_t *ephemeral_public, + size_t ephemeral_public_len) { + if (peer_public_value_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY); + return 0; + } + if (ephemeral_private_len != X25519_PRIVATE_KEY_LEN || + ephemeral_public_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + hpke->is_sender = 1; hpke->kdf_id = kdf_id; hpke->aead_id = aead_id; @@ -355,12 +378,23 @@ int EVP_HPKE_CTX_setup_base_s_x25519_for_test( return 1; } -int EVP_HPKE_CTX_setup_base_r_x25519( - EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t enc[X25519_PUBLIC_VALUE_LEN], - const uint8_t public_key[X25519_PUBLIC_VALUE_LEN], - const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info, - size_t info_len) { +int EVP_HPKE_CTX_setup_base_r_x25519(EVP_HPKE_CTX *hpke, uint16_t kdf_id, + uint16_t aead_id, const uint8_t *enc, + size_t enc_len, const uint8_t *public_key, + size_t public_key_len, + const uint8_t *private_key, + size_t private_key_len, + const uint8_t *info, size_t info_len) { + if (enc_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY); + return 0; + } + if (public_key_len != X25519_PUBLIC_VALUE_LEN || + private_key_len != X25519_PRIVATE_KEY_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + hpke->is_sender = 0; hpke->kdf_id = kdf_id; hpke->aead_id = aead_id; @@ -378,29 +412,47 @@ int EVP_HPKE_CTX_setup_base_r_x25519( return 1; } -int EVP_HPKE_CTX_setup_psk_s_x25519( - EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN], - uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], - const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len, - const uint8_t *psk_id, size_t psk_id_len) { +int EVP_HPKE_CTX_setup_psk_s_x25519(EVP_HPKE_CTX *hpke, uint8_t *out_enc, + size_t out_enc_len, uint16_t kdf_id, + uint16_t aead_id, + const uint8_t *peer_public_value, + size_t peer_public_value_len, + const uint8_t *info, size_t info_len, + const uint8_t *psk, size_t psk_len, + const uint8_t *psk_id, size_t psk_id_len) { + if (out_enc_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE); + return 0; + } + // The GenerateKeyPair() step technically belongs in the KEM's Encap() // function, but we've moved it up a layer to make it easier for tests to // inject an ephemeral keypair. uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN]; X25519_keypair(out_enc, ephemeral_private); return EVP_HPKE_CTX_setup_psk_s_x25519_for_test( - hpke, kdf_id, aead_id, peer_public_value, info, info_len, psk, psk_len, - psk_id, psk_id_len, ephemeral_private, out_enc); + hpke, kdf_id, aead_id, peer_public_value, peer_public_value_len, info, + info_len, psk, psk_len, psk_id, psk_id_len, ephemeral_private, + sizeof(ephemeral_private), out_enc, out_enc_len); } int EVP_HPKE_CTX_setup_psk_s_x25519_for_test( EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], + const uint8_t *peer_public_value, size_t peer_public_value_len, const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len, - const uint8_t *psk_id, size_t psk_id_len, - const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN], - const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]) { + const uint8_t *psk_id, size_t psk_id_len, const uint8_t *ephemeral_private, + size_t ephemeral_private_len, const uint8_t *ephemeral_public, + size_t ephemeral_public_len) { + if (peer_public_value_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY); + return 0; + } + if (ephemeral_private_len != X25519_PRIVATE_KEY_LEN || + ephemeral_public_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + hpke->is_sender = 1; hpke->kdf_id = kdf_id; hpke->aead_id = aead_id; @@ -420,12 +472,21 @@ int EVP_HPKE_CTX_setup_psk_s_x25519_for_test( } int EVP_HPKE_CTX_setup_psk_r_x25519( - EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t enc[X25519_PUBLIC_VALUE_LEN], - const uint8_t public_key[X25519_PUBLIC_VALUE_LEN], - const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info, + EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, const uint8_t *enc, + size_t enc_len, const uint8_t *public_key, size_t public_key_len, + const uint8_t *private_key, size_t private_key_len, const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len, const uint8_t *psk_id, size_t psk_id_len) { + if (enc_len != X25519_PUBLIC_VALUE_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY); + return 0; + } + if (public_key_len != X25519_PUBLIC_VALUE_LEN || + private_key_len != X25519_PRIVATE_KEY_LEN) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); + return 0; + } + hpke->is_sender = 0; hpke->kdf_id = kdf_id; hpke->aead_id = aead_id; diff --git a/Sources/CNIOBoringSSL/crypto/hpke/internal.h b/Sources/CNIOBoringSSL/crypto/hpke/internal.h index 657112d3..eb193fc4 100644 --- a/Sources/CNIOBoringSSL/crypto/hpke/internal.h +++ b/Sources/CNIOBoringSSL/crypto/hpke/internal.h @@ -33,9 +33,12 @@ extern "C" { // // See https://tools.ietf.org/html/draft-irtf-cfrg-hpke-07. +// EVP_HPKE_DHKEM_* are KEM identifiers. +#define EVP_HPKE_DHKEM_X25519_HKDF_SHA256 0x0020 + // EVP_HPKE_AEAD_* are AEAD identifiers. -#define EVP_HPKE_AEAD_AES_GCM_128 0x0001 -#define EVP_HPKE_AEAD_AES_GCM_256 0x0002 +#define EVP_HPKE_AEAD_AES_128_GCM 0x0001 +#define EVP_HPKE_AEAD_AES_256_GCM 0x0002 #define EVP_HPKE_AEAD_CHACHA20POLY1305 0x0003 // EVP_HPKE_HKDF_* are HKDF identifiers. @@ -86,32 +89,35 @@ OPENSSL_EXPORT void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx); // recipient's public key). It returns one on success, and zero otherwise. Note // that this function will fail if |peer_public_value| is invalid. // -// This function writes the encapsulated shared secret to |out_enc|. +// This function writes the encapsulated shared secret, a Diffie-Hellman public +// key, to |out_enc|. It will fail if the buffer's size in |out_enc_len| is not +// exactly |X25519_PUBLIC_VALUE_LEN|. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519( - EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN], - uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], - const uint8_t *info, size_t info_len); + EVP_HPKE_CTX *hpke, uint8_t *out_enc, size_t out_enc_len, uint16_t kdf_id, + uint16_t aead_id, const uint8_t *peer_public_value, + size_t peer_public_value_len, const uint8_t *info, size_t info_len); // EVP_HPKE_CTX_setup_base_s_x25519_for_test behaves like // |EVP_HPKE_CTX_setup_base_s_x25519|, but takes a pre-generated ephemeral -// sender key. +// sender key. The caller ensures that |ephemeral_public| and +// |ephemeral_private| are a valid keypair. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_s_x25519_for_test( EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], - const uint8_t *info, size_t info_len, - const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN], - const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]); + const uint8_t *peer_public_value, size_t peer_public_value_len, + const uint8_t *info, size_t info_len, const uint8_t *ephemeral_private, + size_t ephemeral_private_len, const uint8_t *ephemeral_public, + size_t ephemeral_public_len); // EVP_HPKE_CTX_setup_base_r_x25519 sets up |hpke| as a recipient context that -// can decrypt messages. |private_key| is the recipient's private key, and |enc| -// is the encapsulated shared secret from the sender. Note that this function -// will fail if |enc| is invalid. +// can decrypt messages. It returns one on success, and zero otherwise. +// +// The recipient's keypair is composed of |public_key| and |private_key|, and +// |enc| is the encapsulated shared secret from the sender. If |enc| is invalid, +// this function will fail. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_r_x25519( - EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t enc[X25519_PUBLIC_VALUE_LEN], - const uint8_t public_key[X25519_PUBLIC_VALUE_LEN], - const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info, + EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, const uint8_t *enc, + size_t enc_len, const uint8_t *public_key, size_t public_key_len, + const uint8_t *private_key, size_t private_key_len, const uint8_t *info, size_t info_len); // EVP_HPKE_CTX_setup_psk_s_x25519 sets up |hpke| as a sender context that can @@ -124,39 +130,44 @@ OPENSSL_EXPORT int EVP_HPKE_CTX_setup_base_r_x25519( // must be nonempty (|psk_len| and |psk_id_len| must be non-zero), or this // function will fail. // -// This function writes the encapsulated shared secret to |out_enc|. +// This function writes the encapsulated shared secret, a Diffie-Hellman public +// key, to |out_enc|. It will fail if the buffer's size in |out_enc_len| is not +// exactly |X25519_PUBLIC_VALUE_LEN|. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_psk_s_x25519( - EVP_HPKE_CTX *hpke, uint8_t out_enc[X25519_PUBLIC_VALUE_LEN], - uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], - const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len, - const uint8_t *psk_id, size_t psk_id_len); + EVP_HPKE_CTX *hpke, uint8_t *out_enc, size_t out_enc_len, uint16_t kdf_id, + uint16_t aead_id, const uint8_t *peer_public_value, + size_t peer_public_value_len, const uint8_t *info, size_t info_len, + const uint8_t *psk, size_t psk_len, const uint8_t *psk_id, + size_t psk_id_len); // EVP_HPKE_CTX_setup_psk_s_x25519_for_test behaves like // |EVP_HPKE_CTX_setup_psk_s_x25519|, but takes a pre-generated ephemeral sender -// key. +// key. The caller ensures that |ephemeral_public| and |ephemeral_private| are a +// valid keypair. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_psk_s_x25519_for_test( EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t peer_public_value[X25519_PUBLIC_VALUE_LEN], + const uint8_t *peer_public_value, size_t peer_public_value_len, const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len, - const uint8_t *psk_id, size_t psk_id_len, - const uint8_t ephemeral_private[X25519_PRIVATE_KEY_LEN], - const uint8_t ephemeral_public[X25519_PUBLIC_VALUE_LEN]); + const uint8_t *psk_id, size_t psk_id_len, const uint8_t *ephemeral_private, + size_t ephemeral_private_len, const uint8_t *ephemeral_public, + size_t ephemeral_public_len); // EVP_HPKE_CTX_setup_psk_r_x25519 sets up |hpke| as a recipient context that // can decrypt messages. Future open (decrypt) operations will fail if the -// sender does not possess the PSK indicated by |psk| and |psk_id|. -// |private_key| is the recipient's private key, and |enc| is the encapsulated -// shared secret from the sender. If |enc| is invalid, this function will fail. +// sender does not possess the PSK indicated by |psk| and |psk_id|. It returns +// one on success, and zero otherwise. +// +// The recipient's keypair is composed of |public_key| and |private_key|, and +// |enc| is the encapsulated shared secret from the sender. If |enc| is invalid, +// this function will fail. // // The PSK and its ID must be provided in |psk| and |psk_id|, respectively. Both // must be nonempty (|psk_len| and |psk_id_len| must be non-zero), or this // function will fail. OPENSSL_EXPORT int EVP_HPKE_CTX_setup_psk_r_x25519( - EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, - const uint8_t enc[X25519_PUBLIC_VALUE_LEN], - const uint8_t public_key[X25519_PUBLIC_VALUE_LEN], - const uint8_t private_key[X25519_PRIVATE_KEY_LEN], const uint8_t *info, + EVP_HPKE_CTX *hpke, uint16_t kdf_id, uint16_t aead_id, const uint8_t *enc, + size_t enc_len, const uint8_t *public_key, size_t public_key_len, + const uint8_t *private_key, size_t private_key_len, const uint8_t *info, size_t info_len, const uint8_t *psk, size_t psk_len, const uint8_t *psk_id, size_t psk_id_len); @@ -216,6 +227,16 @@ OPENSSL_EXPORT int EVP_HPKE_CTX_export(const EVP_HPKE_CTX *hpke, uint8_t *out, // set up as a sender. OPENSSL_EXPORT size_t EVP_HPKE_CTX_max_overhead(const EVP_HPKE_CTX *hpke); +// EVP_HPKE_CTX_get_aead_id returns |hpke|'s configured AEAD. The returned value +// is one of the |EVP_HPKE_AEAD_*| constants, or zero if the context has not +// been set up. +OPENSSL_EXPORT uint16_t EVP_HPKE_CTX_get_aead_id(const EVP_HPKE_CTX *hpke); + +// EVP_HPKE_CTX_get_aead_id returns |hpke|'s configured KDF. The returned value +// is one of the |EVP_HPKE_HKDF_*| constants, or zero if the context has not +// been set up. +OPENSSL_EXPORT uint16_t EVP_HPKE_CTX_get_kdf_id(const EVP_HPKE_CTX *hpke); + // EVP_HPKE_get_aead returns the AEAD corresponding to |aead_id|, or NULL if // |aead_id| is not a known AEAD identifier. OPENSSL_EXPORT const EVP_AEAD *EVP_HPKE_get_aead(uint16_t aead_id); diff --git a/Sources/CNIOBoringSSL/crypto/internal.h b/Sources/CNIOBoringSSL/crypto/internal.h index 01036d94..66defef8 100644 --- a/Sources/CNIOBoringSSL/crypto/internal.h +++ b/Sources/CNIOBoringSSL/crypto/internal.h @@ -109,6 +109,7 @@ #ifndef OPENSSL_HEADER_CRYPTO_INTERNAL_H #define OPENSSL_HEADER_CRYPTO_INTERNAL_H +#include #include #include #include @@ -470,6 +471,12 @@ OPENSSL_EXPORT void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)); // Reference counting. +// Automatically enable C11 atomics if implemented. +#if !defined(OPENSSL_C11_ATOMIC) && !defined(__STDC_NO_ATOMICS__) && \ + defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define OPENSSL_C11_ATOMIC +#endif + // CRYPTO_REFCOUNT_MAX is the value at which the reference count saturates. #define CRYPTO_REFCOUNT_MAX 0xffffffff @@ -607,6 +614,7 @@ BSSL_NAMESPACE_END typedef enum { OPENSSL_THREAD_LOCAL_ERR = 0, OPENSSL_THREAD_LOCAL_RAND, + OPENSSL_THREAD_LOCAL_FIPS_COUNTERS, OPENSSL_THREAD_LOCAL_TEST, NUM_OPENSSL_THREAD_LOCALS, } thread_local_data_t; @@ -811,6 +819,58 @@ static inline void *OPENSSL_memset(void *dst, int c, size_t n) { return memset(dst, c, n); } + +// Loads and stores. +// +// The following functions load and store sized integers with the specified +// endianness. They use |memcpy|, and so avoid alignment or strict aliasing +// requirements on the input and output pointers. + +static inline uint32_t CRYPTO_load_u32_le(const void *in) { + uint32_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); + return v; +} + +static inline void CRYPTO_store_u32_le(void *out, uint32_t v) { + OPENSSL_memcpy(out, &v, sizeof(v)); +} + +static inline uint32_t CRYPTO_load_u32_be(const void *in) { + uint32_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); + return CRYPTO_bswap4(v); +} + +static inline void CRYPTO_store_u32_be(void *out, uint32_t v) { + v = CRYPTO_bswap4(v); + OPENSSL_memcpy(out, &v, sizeof(v)); +} + +static inline uint64_t CRYPTO_load_u64_be(const void *ptr) { + uint64_t ret; + OPENSSL_memcpy(&ret, ptr, sizeof(ret)); + return CRYPTO_bswap8(ret); +} + +static inline void CRYPTO_store_u64_be(void *out, uint64_t v) { + v = CRYPTO_bswap8(v); + OPENSSL_memcpy(out, &v, sizeof(v)); +} + +static inline crypto_word_t CRYPTO_load_word_le(const void *in) { + crypto_word_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); + return v; +} + +static inline void CRYPTO_store_word_le(void *out, crypto_word_t v) { + OPENSSL_memcpy(out, &v, sizeof(v)); +} + + +// FIPS functions. + #if defined(BORINGSSL_FIPS) // BORINGSSL_FIPS_abort is called when a FIPS power-on or continuous test // fails. It prevents any further cryptographic operations by the current @@ -826,6 +886,11 @@ void BORINGSSL_FIPS_abort(void) __attribute__((noreturn)); int boringssl_fips_self_test(const uint8_t *module_hash, size_t module_hash_len); +#if defined(BORINGSSL_FIPS_COUNTERS) +void boringssl_fips_inc_counter(enum fips_counter_t counter); +#else +OPENSSL_INLINE void boringssl_fips_inc_counter(enum fips_counter_t counter) {} +#endif #if defined(__cplusplus) } // extern C diff --git a/Sources/CNIOBoringSSL/crypto/mem.c b/Sources/CNIOBoringSSL/crypto/mem.c index f35a347c..e5a6af51 100644 --- a/Sources/CNIOBoringSSL/crypto/mem.c +++ b/Sources/CNIOBoringSSL/crypto/mem.c @@ -107,6 +107,20 @@ WEAK_SYMBOL_FUNC(void, sdallocx, (void *ptr, size_t size, int flags)); // allocation and freeing. If defined, it is the responsibility of // |OPENSSL_memory_free| to zero out the memory before returning it to the // system. |OPENSSL_memory_free| will not be passed NULL pointers. +// +// WARNING: These functions are called on every allocation and free in +// BoringSSL across the entire process. They may be called by any code in the +// process which calls BoringSSL, including in process initializers and thread +// destructors. When called, BoringSSL may hold pthreads locks. Any other code +// in the process which, directly or indirectly, calls BoringSSL may be on the +// call stack and may itself be using arbitrary synchronization primitives. +// +// As a result, these functions may not have the usual programming environment +// available to most C or C++ code. In particular, they may not call into +// BoringSSL, or any library which depends on BoringSSL. Any synchronization +// primitives used must tolerate every other synchronization primitive linked +// into the process, including pthreads locks. Failing to meet these constraints +// may result in deadlocks, crashes, or memory corruption. WEAK_SYMBOL_FUNC(void*, OPENSSL_memory_alloc, (size_t size)); WEAK_SYMBOL_FUNC(void, OPENSSL_memory_free, (void *ptr)); WEAK_SYMBOL_FUNC(size_t, OPENSSL_memory_get_size, (void *ptr)); diff --git a/Sources/CNIOBoringSSL/crypto/obj/obj.c b/Sources/CNIOBoringSSL/crypto/obj/obj.c index 121b600d..a515c57f 100644 --- a/Sources/CNIOBoringSSL/crypto/obj/obj.c +++ b/Sources/CNIOBoringSSL/crypto/obj/obj.c @@ -338,12 +338,12 @@ OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) { return 1; } -const ASN1_OBJECT *OBJ_nid2obj(int nid) { +ASN1_OBJECT *OBJ_nid2obj(int nid) { if (nid >= 0 && nid < NUM_NID) { if (nid != NID_undef && kObjects[nid].nid == NID_undef) { goto err; } - return &kObjects[nid]; + return (ASN1_OBJECT *)&kObjects[nid]; } CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); @@ -411,7 +411,7 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) { } if (nid != NID_undef) { - return (ASN1_OBJECT*) OBJ_nid2obj(nid); + return OBJ_nid2obj(nid); } } diff --git a/Sources/CNIOBoringSSL/crypto/pkcs7/pkcs7_x509.c b/Sources/CNIOBoringSSL/crypto/pkcs7/pkcs7_x509.c index 3eb46e15..d3bed555 100644 --- a/Sources/CNIOBoringSSL/crypto/pkcs7/pkcs7_x509.c +++ b/Sources/CNIOBoringSSL/crypto/pkcs7/pkcs7_x509.c @@ -235,7 +235,7 @@ static PKCS7 *pkcs7_new(CBS *cbs) { return NULL; } OPENSSL_memset(ret, 0, sizeof(PKCS7)); - ret->type = (ASN1_OBJECT *)OBJ_nid2obj(NID_pkcs7_signed); + ret->type = OBJ_nid2obj(NID_pkcs7_signed); ret->d.sign = OPENSSL_malloc(sizeof(PKCS7_SIGNED)); if (ret->d.sign == NULL) { goto err; diff --git a/Sources/CNIOBoringSSL/crypto/thread_pthread.c b/Sources/CNIOBoringSSL/crypto/thread_pthread.c index c265f8fb..4743a5f5 100644 --- a/Sources/CNIOBoringSSL/crypto/thread_pthread.c +++ b/Sources/CNIOBoringSSL/crypto/thread_pthread.c @@ -127,34 +127,6 @@ static pthread_once_t g_thread_local_init_once = PTHREAD_ONCE_INIT; static pthread_key_t g_thread_local_key; static int g_thread_local_key_created = 0; -// OPENSSL_DANGEROUS_RELEASE_PTHREAD_KEY can be defined to cause -// |pthread_key_delete| to be called in a destructor function. This can be -// useful for programs that dlclose BoringSSL. -// -// Note that dlclose()ing BoringSSL is not supported and will leak memory: -// thread-local values will be leaked as well as anything initialised via a -// once. The |pthread_key_t| is destroyed because they run out very quickly, -// while the other leaks are slow, and this allows code that happens to use -// dlclose() despite all the problems to continue functioning. -// -// This is marked "dangerous" because it can cause multi-threaded processes to -// crash (even if they don't use dlclose): if the destructor runs while other -// threads are still executing then they may end up using an invalid key to -// access thread-local variables. -// -// This may be removed after February 2020. -#if defined(OPENSSL_DANGEROUS_RELEASE_PTHREAD_KEY) && \ - (defined(__GNUC__) || defined(__clang__)) -// thread_key_destructor is called when the library is unloaded with dlclose. -static void thread_key_destructor(void) __attribute__((destructor, unused)); -static void thread_key_destructor(void) { - if (g_thread_local_key_created) { - g_thread_local_key_created = 0; - pthread_key_delete(g_thread_local_key); - } -} -#endif - static void thread_local_init(void) { g_thread_local_key_created = pthread_key_create(&g_thread_local_key, thread_local_destructor) == 0; diff --git a/Sources/CNIOBoringSSL/crypto/x509/internal.h b/Sources/CNIOBoringSSL/crypto/x509/internal.h index f62c8348..af4cc7e0 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/internal.h +++ b/Sources/CNIOBoringSSL/crypto/x509/internal.h @@ -31,6 +31,17 @@ struct X509_val_st { ASN1_TIME *notAfter; } /* X509_VAL */; +struct X509_pubkey_st { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; +} /* X509_PUBKEY */; + +struct x509_attributes_st { + ASN1_OBJECT *object; + STACK_OF(ASN1_TYPE) *set; +} /* X509_ATTRIBUTE */; + /* RSA-PSS functions. */ diff --git a/Sources/CNIOBoringSSL/crypto/x509/t_req.c b/Sources/CNIOBoringSSL/crypto/x509/t_req.c index 94fa8cbf..eb41a8b8 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/t_req.c +++ b/Sources/CNIOBoringSSL/crypto/x509/t_req.c @@ -63,6 +63,8 @@ #include #include +#include "internal.h" + int X509_REQ_print_fp(FILE *fp, X509_REQ *x) { BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); diff --git a/Sources/CNIOBoringSSL/crypto/x509/x509_att.c b/Sources/CNIOBoringSSL/crypto/x509/x509_att.c index 7a5c3726..3efac383 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x509_att.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x509_att.c @@ -62,6 +62,10 @@ #include #include +#include "../asn1/asn1_locl.h" +#include "internal.h" + + int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) { return sk_X509_ATTRIBUTE_num(x); @@ -214,7 +218,7 @@ void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, - int atrtype, const void *data, + int attrtype, const void *data, int len) { const ASN1_OBJECT *obj; @@ -224,12 +228,12 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID); return (NULL); } - return X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); + return X509_ATTRIBUTE_create_by_OBJ(attr, obj, attrtype, data, len); } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, - int atrtype, const void *data, + int attrtype, const void *data, int len) { X509_ATTRIBUTE *ret; @@ -244,7 +248,7 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, if (!X509_ATTRIBUTE_set1_object(ret, obj)) goto err; - if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) + if (!X509_ATTRIBUTE_set1_data(ret, attrtype, data, len)) goto err; if ((attr != NULL) && (*attr == NULL)) @@ -257,17 +261,17 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, } X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, - const char *atrname, int type, + const char *attrname, int type, const unsigned char *bytes, int len) { ASN1_OBJECT *obj; X509_ATTRIBUTE *nattr; - obj = OBJ_txt2obj(atrname, 0); + obj = OBJ_txt2obj(attrname, 0); if (obj == NULL) { OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME); - ERR_add_error_data(2, "name=", atrname); + ERR_add_error_data(2, "name=", attrname); return (NULL); } nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); @@ -307,9 +311,6 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, goto err; atype = attrtype; } - if (!(attr->value.set = sk_ASN1_TYPE_new_null())) - goto err; - attr->single = 0; /* * This is a bit naughty because the attribute should really have at * least one value but some types use and zero length SET and require @@ -328,7 +329,7 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, ASN1_TYPE_set(ttmp, atype, stmp); stmp = NULL; } - if (!sk_ASN1_TYPE_push(attr->value.set, ttmp)) + if (!sk_ASN1_TYPE_push(attr->set, ttmp)) goto err; return 1; err: @@ -338,13 +339,9 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, return 0; } -int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr) +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) { - if (!attr->single) - return sk_ASN1_TYPE_num(attr->value.set); - if (attr->value.single) - return 1; - return 0; + return sk_ASN1_TYPE_num(attr->set); } ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) @@ -355,27 +352,24 @@ ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) } void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, - int atrtype, void *data) + int attrtype, void *unused) { ASN1_TYPE *ttmp; ttmp = X509_ATTRIBUTE_get0_type(attr, idx); if (!ttmp) return NULL; - if (atrtype != ASN1_TYPE_get(ttmp)) { + if (attrtype != ASN1_TYPE_get(ttmp)) { OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); return NULL; } - return ttmp->value.ptr; + return (void *)asn1_type_value_as_pointer(ttmp); } ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) { if (attr == NULL) - return (NULL); + return NULL; if (idx >= X509_ATTRIBUTE_count(attr)) return NULL; - if (!attr->single) - return sk_ASN1_TYPE_value(attr->value.set, idx); - else - return attr->value.single; + return sk_ASN1_TYPE_value(attr->set, idx); } diff --git a/Sources/CNIOBoringSSL/crypto/x509/x509_cmp.c b/Sources/CNIOBoringSSL/crypto/x509/x509_cmp.c index bc2ef878..1d1c1cfc 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x509_cmp.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x509_cmp.c @@ -68,6 +68,7 @@ #include "../internal.h" #include "../x509v3/internal.h" +#include "internal.h" int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) diff --git a/Sources/CNIOBoringSSL/crypto/x509/x509_req.c b/Sources/CNIOBoringSSL/crypto/x509/x509_req.c index a889d401..e8b74325 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x509_req.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x509_req.c @@ -157,62 +157,31 @@ int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) return (ok); } -/* - * It seems several organisations had the same idea of including a list of - * extensions in a certificate request. There are at least two OIDs that are - * used and there may be more: so the list is configurable. - */ - -static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef }; - -static const int *ext_nids = ext_nid_list; - int X509_REQ_extension_nid(int req_nid) { - int i, nid; - for (i = 0;; i++) { - nid = ext_nids[i]; - if (nid == NID_undef) - return 0; - else if (req_nid == nid) - return 1; - } -} - -const int *X509_REQ_get_extension_nids(void) -{ - return ext_nids; -} - -void X509_REQ_set_extension_nids(const int *nids) -{ - ext_nids = nids; + return req_nid == NID_ext_req || req_nid == NID_ms_ext_req; } STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) { - X509_ATTRIBUTE *attr; - ASN1_TYPE *ext = NULL; - int idx; - const int *pnid; - const unsigned char *p; + if (req == NULL || req->req_info == NULL) { + return NULL; + } - if ((req == NULL) || (req->req_info == NULL) || !ext_nids) - return (NULL); - for (pnid = ext_nids; *pnid != NID_undef; pnid++) { - idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); - if (idx == -1) - continue; - attr = X509_REQ_get_attr(req, idx); - if (attr->single) - ext = attr->value.single; - else if (sk_ASN1_TYPE_num(attr->value.set)) - ext = sk_ASN1_TYPE_value(attr->value.set, 0); - break; + int idx = X509_REQ_get_attr_by_NID(req, NID_ext_req, -1); + if (idx == -1) { + idx = X509_REQ_get_attr_by_NID(req, NID_ms_ext_req, -1); + } + if (idx == -1) { + return NULL; } - if (!ext || (ext->type != V_ASN1_SEQUENCE)) + + X509_ATTRIBUTE *attr = X509_REQ_get_attr(req, idx); + ASN1_TYPE *ext = X509_ATTRIBUTE_get0_type(attr, 0); + if (!ext || ext->type != V_ASN1_SEQUENCE) { return NULL; - p = ext->value.sequence->data; + } + const unsigned char *p = ext->value.sequence->data; return (STACK_OF(X509_EXTENSION) *) ASN1_item_d2i(NULL, &p, ext->value.sequence->length, ASN1_ITEM_rptr(X509_EXTENSIONS)); @@ -223,44 +192,25 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) * in case we want to create a non standard one. */ -int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, - int nid) +int X509_REQ_add_extensions_nid(X509_REQ *req, + const STACK_OF(X509_EXTENSION) *exts, int nid) { - ASN1_TYPE *at = NULL; - X509_ATTRIBUTE *attr = NULL; - if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new())) - goto err; - - at->type = V_ASN1_SEQUENCE; /* Generate encoding of extensions */ - at->value.sequence->length = - ASN1_item_i2d((ASN1_VALUE *)exts, - &at->value.sequence->data, - ASN1_ITEM_rptr(X509_EXTENSIONS)); - if (!(attr = X509_ATTRIBUTE_new())) - goto err; - if (!(attr->value.set = sk_ASN1_TYPE_new_null())) - goto err; - if (!sk_ASN1_TYPE_push(attr->value.set, at)) - goto err; - at = NULL; - attr->single = 0; - attr->object = (ASN1_OBJECT *)OBJ_nid2obj(nid); - if (!req->req_info->attributes) { - if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null())) - goto err; + unsigned char *ext = NULL; + int ext_len = ASN1_item_i2d((ASN1_VALUE *)exts, &ext, + ASN1_ITEM_rptr(X509_EXTENSIONS)); + if (ext_len <= 0) { + return 0; } - if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) - goto err; - return 1; - err: - X509_ATTRIBUTE_free(attr); - ASN1_TYPE_free(at); - return 0; + int ret = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, + ext_len); + OPENSSL_free(ext); + return ret; } /* This is the normal usage: use the "official" OID */ -int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) +int X509_REQ_add_extensions(X509_REQ *req, + const STACK_OF(X509_EXTENSION) *exts) { return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); } @@ -277,7 +227,7 @@ int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); } -int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj, +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, int lastpos) { return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); @@ -301,31 +251,31 @@ int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) } int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, - const ASN1_OBJECT *obj, int type, - const unsigned char *bytes, int len) + const ASN1_OBJECT *obj, int attrtype, + const unsigned char *data, int len) { if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, - type, bytes, len)) + attrtype, data, len)) return 1; return 0; } int X509_REQ_add1_attr_by_NID(X509_REQ *req, - int nid, int type, - const unsigned char *bytes, int len) + int nid, int attrtype, + const unsigned char *data, int len) { if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, - type, bytes, len)) + attrtype, data, len)) return 1; return 0; } int X509_REQ_add1_attr_by_txt(X509_REQ *req, - const char *attrname, int type, - const unsigned char *bytes, int len) + const char *attrname, int attrtype, + const unsigned char *data, int len) { if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, - type, bytes, len)) + attrtype, data, len)) return 1; return 0; } diff --git a/Sources/CNIOBoringSSL/crypto/x509/x_algor.c b/Sources/CNIOBoringSSL/crypto/x509/x_algor.c index 6ba1d10f..6c754f0e 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x_algor.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x_algor.c @@ -61,6 +61,8 @@ #include #include +#include "../asn1/asn1_locl.h" + ASN1_SEQUENCE(X509_ALGOR) = { ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT), @@ -77,8 +79,7 @@ IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR) IMPLEMENT_ASN1_SET_OF(X509_ALGOR) -int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, - void *pval) +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) { if (!alg) return 0; @@ -89,9 +90,8 @@ int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, return 0; } if (alg) { - if (alg->algorithm) - ASN1_OBJECT_free(alg->algorithm); - alg->algorithm = (ASN1_OBJECT *)aobj; + ASN1_OBJECT_free(alg->algorithm); + alg->algorithm = aobj; } if (ptype == 0) return 1; @@ -105,19 +105,23 @@ int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, return 1; } -void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, const void **ppval, - const X509_ALGOR *algor) +void X509_ALGOR_get0(const ASN1_OBJECT **out_obj, int *out_param_type, + const void **out_param_value, const X509_ALGOR *alg) { - if (paobj) - *paobj = algor->algorithm; - if (pptype) { - if (algor->parameter == NULL) { - *pptype = V_ASN1_UNDEF; - return; - } else - *pptype = algor->parameter->type; - if (ppval) - *ppval = algor->parameter->value.ptr; + if (out_obj != NULL) { + *out_obj = alg->algorithm; + } + if (out_param_type != NULL) { + int type = V_ASN1_UNDEF; + const void *value = NULL; + if (alg->parameter != NULL) { + type = alg->parameter->type; + value = asn1_type_value_as_pointer(alg->parameter); + } + *out_param_type = type; + if (out_param_value != NULL) { + *out_param_value = value; + } } } diff --git a/Sources/CNIOBoringSSL/crypto/x509/x_attrib.c b/Sources/CNIOBoringSSL/crypto/x509/x_attrib.c index d1eaecf1..7f871b4b 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x_attrib.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x_attrib.c @@ -59,33 +59,20 @@ #include #include -/* - * X509_ATTRIBUTE: this has the following form: typedef struct - * x509_attributes_st { ASN1_OBJECT *object; int single; union { char *ptr; - * STACK_OF(ASN1_TYPE) *set; ASN1_TYPE *single; } value; } X509_ATTRIBUTE; - * this needs some extra thought because the CHOICE type is merged with the - * main structure and because the value can be anything at all we *must* try - * the SET OF first because the ASN1_ANY type will swallow anything including - * the whole SET OF structure. - */ +#include "internal.h" -ASN1_CHOICE(X509_ATTRIBUTE_SET) = { - ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY), - ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY) -} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single) ASN1_SEQUENCE(X509_ATTRIBUTE) = { ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT), - /* CHOICE type merged with parent */ - ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET) + ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY), } ASN1_SEQUENCE_END(X509_ATTRIBUTE) IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE) IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE) -X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype, void *value) { - const ASN1_OBJECT *obj = OBJ_nid2obj(nid); + ASN1_OBJECT *obj = OBJ_nid2obj(nid); if (obj == NULL) { return NULL; } @@ -96,17 +83,12 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) goto err; } - /* TODO(fork): const correctness. |ASN1_OBJECT| is messy because static - * objects are const but freeable with a no-op |ASN1_OBJECT_free|. */ - ret->object = (ASN1_OBJECT *)obj; - ret->single = 0; - ret->value.set = sk_ASN1_TYPE_new_null(); - if (ret->value.set == NULL || - !sk_ASN1_TYPE_push(ret->value.set, val)) { + ret->object = obj; + if (!sk_ASN1_TYPE_push(ret->set, val)) { goto err; } - ASN1_TYPE_set(val, atrtype, value); + ASN1_TYPE_set(val, attrtype, value); return ret; err: diff --git a/Sources/CNIOBoringSSL/crypto/x509/x_pubkey.c b/Sources/CNIOBoringSSL/crypto/x509/x_pubkey.c index 3ee1945b..7da5866f 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x_pubkey.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x_pubkey.c @@ -68,6 +68,7 @@ #include #include "../internal.h" +#include "internal.h" /* Minor tweak to operation: free up EVP_PKEY */ static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, @@ -180,35 +181,37 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) return NULL; } -int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj, - int ptype, void *pval, - unsigned char *penc, int penclen) +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type, + void *param_value, uint8_t *key, int key_len) { - if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) + if (!X509_ALGOR_set0(pub->algor, obj, param_type, param_value)) { return 0; - if (penc) { - if (pub->public_key->data) - OPENSSL_free(pub->public_key->data); - pub->public_key->data = penc; - pub->public_key->length = penclen; - /* Set number of unused bits to zero */ - pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; } + + ASN1_STRING_set0(pub->public_key, key, key_len); + /* Set the number of unused bits to zero. */ + pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; return 1; } -int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, - const unsigned char **pk, int *ppklen, - X509_ALGOR **pa, X509_PUBKEY *pub) +int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, const uint8_t **out_key, + int *out_key_len, X509_ALGOR **out_alg, + X509_PUBKEY *pub) { - if (ppkalg) - *ppkalg = pub->algor->algorithm; - if (pk) { - *pk = pub->public_key->data; - *ppklen = pub->public_key->length; + if (out_obj != NULL) { + *out_obj = pub->algor->algorithm; + } + if (out_key != NULL) { + *out_key = pub->public_key->data; + *out_key_len = pub->public_key->length; + } + if (out_alg != NULL) { + *out_alg = pub->algor; } - if (pa) - *pa = pub->algor; return 1; } + +const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) { + return pub->public_key; +} diff --git a/Sources/CNIOBoringSSL/crypto/x509v3/v3_cpols.c b/Sources/CNIOBoringSSL/crypto/x509v3/v3_cpols.c index 4bbfcb66..a3dfaa9a 100644 --- a/Sources/CNIOBoringSSL/crypto/x509v3/v3_cpols.c +++ b/Sources/CNIOBoringSSL/crypto/x509v3/v3_cpols.c @@ -239,8 +239,7 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, goto merr; if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) goto merr; - /* TODO(fork): const correctness */ - qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_cps); + qual->pqualid = OBJ_nid2obj(NID_id_qt_cps); if (qual->pqualid == NULL) { OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); goto err; @@ -307,8 +306,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, POLICYQUALINFO *qual; if (!(qual = POLICYQUALINFO_new())) goto merr; - /* TODO(fork): const correctness */ - qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_unotice); + qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); if (qual->pqualid == NULL) { OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR); goto err; diff --git a/Sources/CNIOBoringSSL/crypto/x509v3/v3_skey.c b/Sources/CNIOBoringSSL/crypto/x509v3/v3_skey.c index c7398ed3..24a1723c 100644 --- a/Sources/CNIOBoringSSL/crypto/x509v3/v3_skey.c +++ b/Sources/CNIOBoringSSL/crypto/x509v3/v3_skey.c @@ -63,6 +63,7 @@ #include #include +#include "../x509/internal.h" #include "internal.h" diff --git a/Sources/CNIOBoringSSL/hash.txt b/Sources/CNIOBoringSSL/hash.txt index 1a1532c6..01b95cc6 100644 --- a/Sources/CNIOBoringSSL/hash.txt +++ b/Sources/CNIOBoringSSL/hash.txt @@ -1 +1 @@ -This directory is derived from BoringSSL cloned from https://boringssl.googlesource.com/boringssl at revision 04b3213d43492b6c9e0434d8e2a4530a9938f958 +This directory is derived from BoringSSL cloned from https://boringssl.googlesource.com/boringssl at revision ab7811ee8751ea699b22095caa70246f641ed3a2 diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_aead.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_aead.h index 29614d6b..1df58436 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_aead.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_aead.h @@ -397,12 +397,9 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_AEAD_CTX_aead(const EVP_AEAD_CTX *ctx); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void); -OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void); -OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void); -OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void); OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void); diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_asn1.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_asn1.h index caa14656..41621470 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_asn1.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_asn1.h @@ -103,7 +103,7 @@ extern "C" { #define V_ASN1_PRIMITIVE_TAG 0x1f // V_ASN1_MAX_UNIVERSAL is the highest supported universal tag number. It is -// necessary to avoid ambiguity with |V_ASN1_NEG|. +// necessary to avoid ambiguity with |V_ASN1_NEG| and |MBSTRING_FLAG|. // // TODO(davidben): Make this private. #define V_ASN1_MAX_UNIVERSAL 0xff @@ -197,9 +197,8 @@ extern "C" { // the DER encoding of the value. For example, the UNIX epoch would be // "19700101000000Z" for a GeneralizedTime and "700101000000Z" for a UTCTime. // -// TODO(davidben): |ASN1_TYPE| additionally uses |ASN1_STRING| to represent -// various other odd cases. It also likes to assume unknown universal tags are -// string types. Make a note here when documenting |ASN1_TYPE|. +// |ASN1_STRING|, when stored in an |ASN1_TYPE|, may also represent an element +// with tag not directly supported by this library. See |ASN1_TYPE| for details. // // |ASN1_STRING| additionally has the following typedefs: |ASN1_BIT_STRING|, // |ASN1_BMPSTRING|, |ASN1_ENUMERATED|, |ASN1_GENERALIZEDTIME|, @@ -313,6 +312,111 @@ OPENSSL_EXPORT void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); // types. +// Arbitrary elements. + +// ASN1_VALUE_st (aka |ASN1_VALUE|) is an opaque type used internally in the +// library. +typedef struct ASN1_VALUE_st ASN1_VALUE; + +// An asn1_type_st (aka |ASN1_TYPE|) represents an arbitrary ASN.1 element, +// typically used used for ANY types. It contains a |type| field and a |value| +// union dependent on |type|. +// +// WARNING: This struct has a complex representation. Callers must not construct +// |ASN1_TYPE| values manually. Use |ASN1_TYPE_set| and |ASN1_TYPE_set1| +// instead. Additionally, callers performing non-trivial operations on this type +// are encouraged to use |CBS| and |CBB| from , and +// convert to or from |ASN1_TYPE| with |d2i_ASN1_TYPE| or |i2d_ASN1_TYPE|. +// +// The |type| field corresponds to the tag of the ASN.1 element being +// represented: +// +// If |type| is a |V_ASN1_*| constant for an ASN.1 string-like type, as defined +// by |ASN1_STRING|, the tag matches the constant. |value| contains an +// |ASN1_STRING| pointer (equivalently, one of the more specific typedefs). See +// |ASN1_STRING| for details on the representation. Unlike |ASN1_STRING|, +// |ASN1_TYPE| does not use the |V_ASN1_NEG| flag for negative INTEGER and +// ENUMERATE values. For a negative value, the |ASN1_TYPE|'s |type| will be +// |V_ASN1_INTEGER| or |V_ASN1_ENUMERATED|, but |value| will an |ASN1_STRING| +// whose |type| is |V_ASN1_NEG_INTEGER| or |V_ASN1_NEG_ENUMERATED|. +// +// If |type| is |V_ASN1_OBJECT|, the tag is OBJECT IDENTIFIER and |value| +// contains an |ASN1_OBJECT| pointer. +// +// If |type| is |V_ASN1_NULL|, the tag is NULL. |value| contains a NULL pointer. +// +// If |type| is |V_ASN1_BOOLEAN|, the tag is BOOLEAN. |value| contains an +// |ASN1_BOOLEAN|. +// +// If |type| is |V_ASN1_SEQUENCE|, |V_ASN1_SET|, or |V_ASN1_OTHER|, the tag is +// SEQUENCE, SET, or some non-universal tag, respectively. |value| is an +// |ASN1_STRING| containing the entire element, including the tag and length. +// The |ASN1_STRING|'s |type| field matches the containing |ASN1_TYPE|'s |type|. +// +// Other positive values of |type|, up to |V_ASN1_MAX_UNIVERSAL|, correspond to +// universal primitive tags not directly supported by this library. |value| is +// an |ASN1_STRING| containing the body of the element, excluding the tag +// and length. The |ASN1_STRING|'s |type| field matches the containing +// |ASN1_TYPE|'s |type|. +struct asn1_type_st { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING *asn1_string; + ASN1_OBJECT *object; + ASN1_INTEGER *integer; + ASN1_ENUMERATED *enumerated; + ASN1_BIT_STRING *bit_string; + ASN1_OCTET_STRING *octet_string; + ASN1_PRINTABLESTRING *printablestring; + ASN1_T61STRING *t61string; + ASN1_IA5STRING *ia5string; + ASN1_GENERALSTRING *generalstring; + ASN1_BMPSTRING *bmpstring; + ASN1_UNIVERSALSTRING *universalstring; + ASN1_UTCTIME *utctime; + ASN1_GENERALIZEDTIME *generalizedtime; + ASN1_VISIBLESTRING *visiblestring; + ASN1_UTF8STRING *utf8string; + // set and sequence are left complete and still contain the entire element. + ASN1_STRING *set; + ASN1_STRING *sequence; + ASN1_VALUE *asn1_value; + } value; +}; + +// ASN1_TYPE_get returns the type of |a|, which will be one of the |V_ASN1_*| +// constants, or zero if |a| is not fully initialized. +OPENSSL_EXPORT int ASN1_TYPE_get(const ASN1_TYPE *a); + +// ASN1_TYPE_set sets |a| to an |ASN1_TYPE| of type |type| and value |value|, +// releasing the previous contents of |a|. +// +// If |type| is |V_ASN1_BOOLEAN|, |a| is set to FALSE if |value| is NULL and +// TRUE otherwise. If setting |a| to TRUE, |value| may be an invalid pointer, +// such as (void*)1. +// +// If |type| is |V_ASN1_NULL|, |value| must be NULL. +// +// For other values of |type|, this function takes ownership of |value|, which +// must point to an object of the corresponding type. See |ASN1_TYPE| for +// details. +OPENSSL_EXPORT void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); + +// ASN1_TYPE_set1 behaves like |ASN1_TYPE_set| except it does not take ownership +// of |value|. It returns one on success and zero on error. +OPENSSL_EXPORT int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); + +// ASN1_TYPE_cmp returns zero if |a| and |b| are equal and some non-zero value +// otherwise. Note this function can only be used for equality checks, not an +// ordering. +OPENSSL_EXPORT int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +// TODO(davidben): Most of |ASN1_TYPE|'s APIs are hidden behind macros. Expand +// the macros, document them, and move them to this section. + + // Underdocumented functions. // // The following functions are not yet documented and organized. @@ -356,6 +460,16 @@ OPENSSL_EXPORT void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); #define ASN1_OBJECT_FLAG_DYNAMIC 0x01 // internal use #define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 // internal use #define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 // internal use + +// An asn1_object_st (aka |ASN1_OBJECT|) represents an ASN.1 OBJECT IDENTIFIER. +// +// Note: Although the struct is exposed, mutating an |ASN1_OBJECT| is only +// permitted when initializing it. The library maintains a table of static +// |ASN1_OBJECT|s, which may be referenced by non-const |ASN1_OBJECT| pointers. +// Code which receives an |ASN1_OBJECT| pointer externally must assume it is +// immutable, even if the pointer is not const. +// +// TODO(davidben): Document this more completely in its own section. struct asn1_object_st { const char *sn, *ln; int nid; @@ -414,8 +528,6 @@ typedef struct asn1_string_table_st { // see asn1t.h typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; typedef struct ASN1_TLC_st ASN1_TLC; -// This is just an opaque pointer -typedef struct ASN1_VALUE_st ASN1_VALUE; // Declare ASN1 functions: the implement macro in in asn1t.h @@ -581,35 +693,6 @@ typedef const ASN1_ITEM ASN1_ITEM_EXP; DEFINE_STACK_OF(ASN1_INTEGER) DECLARE_ASN1_SET_OF(ASN1_INTEGER) -struct asn1_type_st { - int type; - union { - char *ptr; - ASN1_BOOLEAN boolean; - ASN1_STRING *asn1_string; - ASN1_OBJECT *object; - ASN1_INTEGER *integer; - ASN1_ENUMERATED *enumerated; - ASN1_BIT_STRING *bit_string; - ASN1_OCTET_STRING *octet_string; - ASN1_PRINTABLESTRING *printablestring; - ASN1_T61STRING *t61string; - ASN1_IA5STRING *ia5string; - ASN1_GENERALSTRING *generalstring; - ASN1_BMPSTRING *bmpstring; - ASN1_UNIVERSALSTRING *universalstring; - ASN1_UTCTIME *utctime; - ASN1_GENERALIZEDTIME *generalizedtime; - ASN1_VISIBLESTRING *visiblestring; - ASN1_UTF8STRING *utf8string; - // set and sequence are left complete and still - // contain the set or sequence bytes - ASN1_STRING *set; - ASN1_STRING *sequence; - ASN1_VALUE *asn1_value; - } value; -}; - DEFINE_STACK_OF(ASN1_TYPE) DECLARE_ASN1_SET_OF(ASN1_TYPE) @@ -696,11 +779,6 @@ typedef struct BIT_STRING_BITNAME_st { DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) -OPENSSL_EXPORT int ASN1_TYPE_get(const ASN1_TYPE *a); -OPENSSL_EXPORT void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); -OPENSSL_EXPORT int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); -OPENSSL_EXPORT int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); - OPENSSL_EXPORT ASN1_OBJECT *ASN1_OBJECT_new(void); OPENSSL_EXPORT void ASN1_OBJECT_free(ASN1_OBJECT *a); OPENSSL_EXPORT int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp); diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h index 690628bd..32edec30 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_base.h @@ -171,6 +171,10 @@ extern "C" { #endif #endif +#if defined(__FreeBSD__) +#define OPENSSL_FREEBSD +#endif + // BoringSSL requires platform's locking APIs to make internal global state // thread-safe, including the PRNG. On some single-threaded embedded platforms, // locking APIs may not exist, so this dependency may be disabled with the @@ -432,6 +436,7 @@ typedef struct spake2_ctx_st SPAKE2_CTX; typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE; typedef struct ssl_cipher_st SSL_CIPHER; typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_ech_server_config_list_st SSL_ECH_SERVER_CONFIG_LIST; typedef struct ssl_method_st SSL_METHOD; typedef struct ssl_private_key_method_st SSL_PRIVATE_KEY_METHOD; typedef struct ssl_quic_method_st SSL_QUIC_METHOD; diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h index 9a5e6ed2..918132d0 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h @@ -966,6 +966,8 @@ #define EVP_EncryptUpdate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptUpdate) #define EVP_HPKE_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_cleanup) #define EVP_HPKE_CTX_export BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_export) +#define EVP_HPKE_CTX_get_aead_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_get_aead_id) +#define EVP_HPKE_CTX_get_kdf_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_get_kdf_id) #define EVP_HPKE_CTX_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_init) #define EVP_HPKE_CTX_max_overhead BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_max_overhead) #define EVP_HPKE_CTX_open BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_open) @@ -1092,7 +1094,6 @@ #define EVP_add_digest BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_add_digest) #define EVP_aead_aes_128_cbc_sha1_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha1_tls) #define EVP_aead_aes_128_cbc_sha1_tls_implicit_iv BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha1_tls_implicit_iv) -#define EVP_aead_aes_128_cbc_sha256_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha256_tls) #define EVP_aead_aes_128_ccm_bluetooth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_ccm_bluetooth) #define EVP_aead_aes_128_ccm_bluetooth_8 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_ccm_bluetooth_8) #define EVP_aead_aes_128_ctr_hmac_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_ctr_hmac_sha256) @@ -1104,8 +1105,6 @@ #define EVP_aead_aes_192_gcm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_192_gcm) #define EVP_aead_aes_256_cbc_sha1_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha1_tls) #define EVP_aead_aes_256_cbc_sha1_tls_implicit_iv BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha1_tls_implicit_iv) -#define EVP_aead_aes_256_cbc_sha256_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha256_tls) -#define EVP_aead_aes_256_cbc_sha384_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha384_tls) #define EVP_aead_aes_256_ctr_hmac_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_ctr_hmac_sha256) #define EVP_aead_aes_256_gcm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_gcm) #define EVP_aead_aes_256_gcm_randnonce BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_gcm_randnonce) @@ -1161,6 +1160,7 @@ #define EVP_rc2_cbc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_rc2_cbc) #define EVP_rc4 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_rc4) #define EVP_sha1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha1) +#define EVP_sha1_final_with_secret_suffix BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha1_final_with_secret_suffix) #define EVP_sha224 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha224) #define EVP_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha256) #define EVP_sha384 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha384) @@ -1175,6 +1175,7 @@ #define EXTENDED_KEY_USAGE_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EXTENDED_KEY_USAGE_new) #define FIPS_mode BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_mode) #define FIPS_mode_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_mode_set) +#define FIPS_read_counter BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_read_counter) #define GENERAL_NAMES_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, GENERAL_NAMES_free) #define GENERAL_NAMES_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, GENERAL_NAMES_it) #define GENERAL_NAMES_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, GENERAL_NAMES_new) @@ -1687,6 +1688,7 @@ #define SSL_CTX_set1_chain BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_chain) #define SSL_CTX_set1_curves BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_curves) #define SSL_CTX_set1_curves_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_curves_list) +#define SSL_CTX_set1_ech_server_config_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_ech_server_config_list) #define SSL_CTX_set1_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_param) #define SSL_CTX_set1_sigalgs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_sigalgs) #define SSL_CTX_set1_sigalgs_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_sigalgs_list) @@ -1774,6 +1776,10 @@ #define SSL_CTX_use_certificate_chain_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_certificate_chain_file) #define SSL_CTX_use_certificate_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_certificate_file) #define SSL_CTX_use_psk_identity_hint BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_psk_identity_hint) +#define SSL_ECH_SERVER_CONFIG_LIST_add BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_add) +#define SSL_ECH_SERVER_CONFIG_LIST_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_free) +#define SSL_ECH_SERVER_CONFIG_LIST_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_new) +#define SSL_ECH_SERVER_CONFIG_LIST_up_ref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_up_ref) #define SSL_SESSION_copy_without_early_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_copy_without_early_data) #define SSL_SESSION_early_data_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_early_data_capable) #define SSL_SESSION_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_free) @@ -1958,9 +1964,12 @@ #define SSL_read BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_read) #define SSL_renegotiate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_renegotiate) #define SSL_renegotiate_pending BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_renegotiate_pending) +#define SSL_request_handshake_hints BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_request_handshake_hints) #define SSL_reset_early_data_reject BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_reset_early_data_reject) #define SSL_select_next_proto BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_select_next_proto) #define SSL_send_fatal_alert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_send_fatal_alert) +#define SSL_serialize_capabilities BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_serialize_capabilities) +#define SSL_serialize_handshake_hints BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_serialize_handshake_hints) #define SSL_session_reused BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_session_reused) #define SSL_set0_chain BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set0_chain) #define SSL_set0_client_CAs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set0_client_CAs) @@ -1991,6 +2000,7 @@ #define SSL_set_enforce_rsa_key_usage BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_enforce_rsa_key_usage) #define SSL_set_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_ex_data) #define SSL_set_fd BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_fd) +#define SSL_set_handshake_hints BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_handshake_hints) #define SSL_set_info_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_info_callback) #define SSL_set_jdk11_workaround BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_jdk11_workaround) #define SSL_set_max_cert_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_max_cert_list) @@ -2158,7 +2168,6 @@ #define X509_ALGOR_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_new) #define X509_ALGOR_set0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_set0) #define X509_ALGOR_set_md BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_set_md) -#define X509_ATTRIBUTE_SET_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_SET_it) #define X509_ATTRIBUTE_count BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_count) #define X509_ATTRIBUTE_create BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_create) #define X509_ATTRIBUTE_create_by_NID BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_create_by_NID) @@ -2310,6 +2319,7 @@ #define X509_PUBKEY_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_free) #define X509_PUBKEY_get BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get) #define X509_PUBKEY_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0_param) +#define X509_PUBKEY_get0_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0_public_key) #define X509_PUBKEY_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_it) #define X509_PUBKEY_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_new) #define X509_PUBKEY_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_set) @@ -2346,7 +2356,6 @@ #define X509_REQ_get_attr_by_NID BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_attr_by_NID) #define X509_REQ_get_attr_by_OBJ BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_attr_by_OBJ) #define X509_REQ_get_attr_count BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_attr_count) -#define X509_REQ_get_extension_nids BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_extension_nids) #define X509_REQ_get_extensions BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_extensions) #define X509_REQ_get_pubkey BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_pubkey) #define X509_REQ_get_signature_nid BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_signature_nid) @@ -2357,7 +2366,6 @@ #define X509_REQ_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_print) #define X509_REQ_print_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_print_ex) #define X509_REQ_print_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_print_fp) -#define X509_REQ_set_extension_nids BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_extension_nids) #define X509_REQ_set_pubkey BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_pubkey) #define X509_REQ_set_subject_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_subject_name) #define X509_REQ_set_version BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_version) @@ -2707,6 +2715,7 @@ #define asn1_refcount_dec_and_test_zero BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_refcount_dec_and_test_zero) #define asn1_refcount_set_one BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_refcount_set_one) #define asn1_set_choice_selector BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_set_choice_selector) +#define asn1_type_value_as_pointer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_type_value_as_pointer) #define asn1_utctime_to_tm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_utctime_to_tm) #define beeu_mod_inverse_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, beeu_mod_inverse_vartime) #define bio_clear_socket_error BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bio_clear_socket_error) @@ -4427,5 +4436,6 @@ #define lh_SSL_SESSION_doall BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, lh_SSL_SESSION_doall) #define lh_SSL_SESSION_doall_arg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, lh_SSL_SESSION_doall_arg) #define ssl_ctx_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_ctx_st) +#define ssl_ech_server_config_list_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_ech_server_config_list_st) #define ssl_session_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_session_st) #define ssl_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_st) diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h index 7b4cd207..94272bb5 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h @@ -971,6 +971,8 @@ #define _EVP_EncryptUpdate BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_EncryptUpdate) #define _EVP_HPKE_CTX_cleanup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_cleanup) #define _EVP_HPKE_CTX_export BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_export) +#define _EVP_HPKE_CTX_get_aead_id BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_get_aead_id) +#define _EVP_HPKE_CTX_get_kdf_id BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_get_kdf_id) #define _EVP_HPKE_CTX_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_init) #define _EVP_HPKE_CTX_max_overhead BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_max_overhead) #define _EVP_HPKE_CTX_open BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_CTX_open) @@ -1097,7 +1099,6 @@ #define _EVP_add_digest BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_add_digest) #define _EVP_aead_aes_128_cbc_sha1_tls BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha1_tls) #define _EVP_aead_aes_128_cbc_sha1_tls_implicit_iv BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha1_tls_implicit_iv) -#define _EVP_aead_aes_128_cbc_sha256_tls BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha256_tls) #define _EVP_aead_aes_128_ccm_bluetooth BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_128_ccm_bluetooth) #define _EVP_aead_aes_128_ccm_bluetooth_8 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_128_ccm_bluetooth_8) #define _EVP_aead_aes_128_ctr_hmac_sha256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_128_ctr_hmac_sha256) @@ -1109,8 +1110,6 @@ #define _EVP_aead_aes_192_gcm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_192_gcm) #define _EVP_aead_aes_256_cbc_sha1_tls BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha1_tls) #define _EVP_aead_aes_256_cbc_sha1_tls_implicit_iv BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha1_tls_implicit_iv) -#define _EVP_aead_aes_256_cbc_sha256_tls BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha256_tls) -#define _EVP_aead_aes_256_cbc_sha384_tls BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha384_tls) #define _EVP_aead_aes_256_ctr_hmac_sha256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_ctr_hmac_sha256) #define _EVP_aead_aes_256_gcm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_gcm) #define _EVP_aead_aes_256_gcm_randnonce BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_aead_aes_256_gcm_randnonce) @@ -1166,6 +1165,7 @@ #define _EVP_rc2_cbc BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_rc2_cbc) #define _EVP_rc4 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_rc4) #define _EVP_sha1 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_sha1) +#define _EVP_sha1_final_with_secret_suffix BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_sha1_final_with_secret_suffix) #define _EVP_sha224 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_sha224) #define _EVP_sha256 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_sha256) #define _EVP_sha384 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_sha384) @@ -1180,6 +1180,7 @@ #define _EXTENDED_KEY_USAGE_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EXTENDED_KEY_USAGE_new) #define _FIPS_mode BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_mode) #define _FIPS_mode_set BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_mode_set) +#define _FIPS_read_counter BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, FIPS_read_counter) #define _GENERAL_NAMES_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, GENERAL_NAMES_free) #define _GENERAL_NAMES_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, GENERAL_NAMES_it) #define _GENERAL_NAMES_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, GENERAL_NAMES_new) @@ -1692,6 +1693,7 @@ #define _SSL_CTX_set1_chain BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_chain) #define _SSL_CTX_set1_curves BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_curves) #define _SSL_CTX_set1_curves_list BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_curves_list) +#define _SSL_CTX_set1_ech_server_config_list BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_ech_server_config_list) #define _SSL_CTX_set1_param BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_param) #define _SSL_CTX_set1_sigalgs BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_sigalgs) #define _SSL_CTX_set1_sigalgs_list BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_set1_sigalgs_list) @@ -1779,6 +1781,10 @@ #define _SSL_CTX_use_certificate_chain_file BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_use_certificate_chain_file) #define _SSL_CTX_use_certificate_file BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_use_certificate_file) #define _SSL_CTX_use_psk_identity_hint BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CTX_use_psk_identity_hint) +#define _SSL_ECH_SERVER_CONFIG_LIST_add BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_add) +#define _SSL_ECH_SERVER_CONFIG_LIST_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_free) +#define _SSL_ECH_SERVER_CONFIG_LIST_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_new) +#define _SSL_ECH_SERVER_CONFIG_LIST_up_ref BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_up_ref) #define _SSL_SESSION_copy_without_early_data BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_SESSION_copy_without_early_data) #define _SSL_SESSION_early_data_capable BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_SESSION_early_data_capable) #define _SSL_SESSION_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_SESSION_free) @@ -1963,9 +1969,12 @@ #define _SSL_read BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_read) #define _SSL_renegotiate BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_renegotiate) #define _SSL_renegotiate_pending BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_renegotiate_pending) +#define _SSL_request_handshake_hints BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_request_handshake_hints) #define _SSL_reset_early_data_reject BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_reset_early_data_reject) #define _SSL_select_next_proto BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_select_next_proto) #define _SSL_send_fatal_alert BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_send_fatal_alert) +#define _SSL_serialize_capabilities BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_serialize_capabilities) +#define _SSL_serialize_handshake_hints BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_serialize_handshake_hints) #define _SSL_session_reused BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_session_reused) #define _SSL_set0_chain BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set0_chain) #define _SSL_set0_client_CAs BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set0_client_CAs) @@ -1996,6 +2005,7 @@ #define _SSL_set_enforce_rsa_key_usage BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_enforce_rsa_key_usage) #define _SSL_set_ex_data BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_ex_data) #define _SSL_set_fd BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_fd) +#define _SSL_set_handshake_hints BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_handshake_hints) #define _SSL_set_info_callback BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_info_callback) #define _SSL_set_jdk11_workaround BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_jdk11_workaround) #define _SSL_set_max_cert_list BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_set_max_cert_list) @@ -2163,7 +2173,6 @@ #define _X509_ALGOR_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_new) #define _X509_ALGOR_set0 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_set0) #define _X509_ALGOR_set_md BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ALGOR_set_md) -#define _X509_ATTRIBUTE_SET_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ATTRIBUTE_SET_it) #define _X509_ATTRIBUTE_count BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ATTRIBUTE_count) #define _X509_ATTRIBUTE_create BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ATTRIBUTE_create) #define _X509_ATTRIBUTE_create_by_NID BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_ATTRIBUTE_create_by_NID) @@ -2315,6 +2324,7 @@ #define _X509_PUBKEY_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_free) #define _X509_PUBKEY_get BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get) #define _X509_PUBKEY_get0_param BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get0_param) +#define _X509_PUBKEY_get0_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_get0_public_key) #define _X509_PUBKEY_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_it) #define _X509_PUBKEY_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_new) #define _X509_PUBKEY_set BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_PUBKEY_set) @@ -2351,7 +2361,6 @@ #define _X509_REQ_get_attr_by_NID BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_attr_by_NID) #define _X509_REQ_get_attr_by_OBJ BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_attr_by_OBJ) #define _X509_REQ_get_attr_count BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_attr_count) -#define _X509_REQ_get_extension_nids BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_extension_nids) #define _X509_REQ_get_extensions BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_extensions) #define _X509_REQ_get_pubkey BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_pubkey) #define _X509_REQ_get_signature_nid BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_get_signature_nid) @@ -2362,7 +2371,6 @@ #define _X509_REQ_print BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_print) #define _X509_REQ_print_ex BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_print_ex) #define _X509_REQ_print_fp BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_print_fp) -#define _X509_REQ_set_extension_nids BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_set_extension_nids) #define _X509_REQ_set_pubkey BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_set_pubkey) #define _X509_REQ_set_subject_name BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_set_subject_name) #define _X509_REQ_set_version BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X509_REQ_set_version) @@ -2712,6 +2720,7 @@ #define _asn1_refcount_dec_and_test_zero BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_refcount_dec_and_test_zero) #define _asn1_refcount_set_one BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_refcount_set_one) #define _asn1_set_choice_selector BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_set_choice_selector) +#define _asn1_type_value_as_pointer BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_type_value_as_pointer) #define _asn1_utctime_to_tm BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, asn1_utctime_to_tm) #define _beeu_mod_inverse_vartime BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, beeu_mod_inverse_vartime) #define _bio_clear_socket_error BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, bio_clear_socket_error) diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_crypto.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_crypto.h index 81464e16..8a1c1c43 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_crypto.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_crypto.h @@ -55,10 +55,6 @@ OPENSSL_EXPORT int CRYPTO_is_confidential_build(void); // in which case it returns zero. OPENSSL_EXPORT int CRYPTO_has_asm(void); -// FIPS_mode returns zero unless BoringSSL is built with BORINGSSL_FIPS, in -// which case it returns one. -OPENSSL_EXPORT int FIPS_mode(void); - // BORINGSSL_self_test triggers the FIPS KAT-based self tests. It returns one on // success and zero on error. OPENSSL_EXPORT int BORINGSSL_self_test(void); @@ -72,6 +68,30 @@ OPENSSL_EXPORT int BORINGSSL_self_test(void); OPENSSL_EXPORT void CRYPTO_pre_sandbox_init(void); +// FIPS monitoring + +// FIPS_mode returns zero unless BoringSSL is built with BORINGSSL_FIPS, in +// which case it returns one. +OPENSSL_EXPORT int FIPS_mode(void); + +// fips_counter_t denotes specific APIs/algorithms. A counter is maintained for +// each in FIPS mode so that tests can be written to assert that the expected, +// FIPS functions are being called by a certain peice of code. +enum fips_counter_t { + fips_counter_evp_aes_128_gcm = 0, + fips_counter_evp_aes_256_gcm = 1, + fips_counter_evp_aes_128_ctr = 2, + fips_counter_evp_aes_256_ctr = 3, + + fips_counter_max = 3, +}; + +// FIPS_read_counter returns a counter of the number of times the specific +// function denoted by |counter| has been used. This always returns zero unless +// BoringSSL was built with BORINGSSL_FIPS_COUNTERS defined. +OPENSSL_EXPORT size_t FIPS_read_counter(enum fips_counter_t counter); + + // Deprecated functions. // OPENSSL_VERSION_TEXT contains a string the identifies the version of diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp.h index a6445efe..31e1e47c 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp.h @@ -59,6 +59,7 @@ #include "CNIOBoringSSL_base.h" +#include "CNIOBoringSSL_evp_errors.h" #include "CNIOBoringSSL_thread.h" // OpenSSL included digest and cipher functions in this header so we include @@ -1091,42 +1092,4 @@ BSSL_NAMESPACE_END #endif -#define EVP_R_BUFFER_TOO_SMALL 100 -#define EVP_R_COMMAND_NOT_SUPPORTED 101 -#define EVP_R_DECODE_ERROR 102 -#define EVP_R_DIFFERENT_KEY_TYPES 103 -#define EVP_R_DIFFERENT_PARAMETERS 104 -#define EVP_R_ENCODE_ERROR 105 -#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106 -#define EVP_R_EXPECTING_AN_RSA_KEY 107 -#define EVP_R_EXPECTING_A_DSA_KEY 108 -#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109 -#define EVP_R_INVALID_DIGEST_LENGTH 110 -#define EVP_R_INVALID_DIGEST_TYPE 111 -#define EVP_R_INVALID_KEYBITS 112 -#define EVP_R_INVALID_MGF1_MD 113 -#define EVP_R_INVALID_OPERATION 114 -#define EVP_R_INVALID_PADDING_MODE 115 -#define EVP_R_INVALID_PSS_SALTLEN 116 -#define EVP_R_KEYS_NOT_SET 117 -#define EVP_R_MISSING_PARAMETERS 118 -#define EVP_R_NO_DEFAULT_DIGEST 119 -#define EVP_R_NO_KEY_SET 120 -#define EVP_R_NO_MDC2_SUPPORT 121 -#define EVP_R_NO_NID_FOR_CURVE 122 -#define EVP_R_NO_OPERATION_SET 123 -#define EVP_R_NO_PARAMETERS_SET 124 -#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 125 -#define EVP_R_OPERATON_NOT_INITIALIZED 126 -#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 127 -#define EVP_R_UNSUPPORTED_ALGORITHM 128 -#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 129 -#define EVP_R_NOT_A_PRIVATE_KEY 130 -#define EVP_R_INVALID_SIGNATURE 131 -#define EVP_R_MEMORY_LIMIT_EXCEEDED 132 -#define EVP_R_INVALID_PARAMETERS 133 -#define EVP_R_INVALID_PEER_KEY 134 -#define EVP_R_NOT_XOF_OR_INVALID_LENGTH 135 -#define EVP_R_EMPTY_PSK 136 - #endif // OPENSSL_HEADER_EVP_H diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp_errors.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp_errors.h new file mode 100644 index 00000000..8583f521 --- /dev/null +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_evp_errors.h @@ -0,0 +1,99 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] */ + +#ifndef OPENSSL_HEADER_EVP_ERRORS_H +#define OPENSSL_HEADER_EVP_ERRORS_H + +#define EVP_R_BUFFER_TOO_SMALL 100 +#define EVP_R_COMMAND_NOT_SUPPORTED 101 +#define EVP_R_DECODE_ERROR 102 +#define EVP_R_DIFFERENT_KEY_TYPES 103 +#define EVP_R_DIFFERENT_PARAMETERS 104 +#define EVP_R_ENCODE_ERROR 105 +#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106 +#define EVP_R_EXPECTING_AN_RSA_KEY 107 +#define EVP_R_EXPECTING_A_DSA_KEY 108 +#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109 +#define EVP_R_INVALID_DIGEST_LENGTH 110 +#define EVP_R_INVALID_DIGEST_TYPE 111 +#define EVP_R_INVALID_KEYBITS 112 +#define EVP_R_INVALID_MGF1_MD 113 +#define EVP_R_INVALID_OPERATION 114 +#define EVP_R_INVALID_PADDING_MODE 115 +#define EVP_R_INVALID_PSS_SALTLEN 116 +#define EVP_R_KEYS_NOT_SET 117 +#define EVP_R_MISSING_PARAMETERS 118 +#define EVP_R_NO_DEFAULT_DIGEST 119 +#define EVP_R_NO_KEY_SET 120 +#define EVP_R_NO_MDC2_SUPPORT 121 +#define EVP_R_NO_NID_FOR_CURVE 122 +#define EVP_R_NO_OPERATION_SET 123 +#define EVP_R_NO_PARAMETERS_SET 124 +#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 125 +#define EVP_R_OPERATON_NOT_INITIALIZED 126 +#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 127 +#define EVP_R_UNSUPPORTED_ALGORITHM 128 +#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 129 +#define EVP_R_NOT_A_PRIVATE_KEY 130 +#define EVP_R_INVALID_SIGNATURE 131 +#define EVP_R_MEMORY_LIMIT_EXCEEDED 132 +#define EVP_R_INVALID_PARAMETERS 133 +#define EVP_R_INVALID_PEER_KEY 134 +#define EVP_R_NOT_XOF_OR_INVALID_LENGTH 135 +#define EVP_R_EMPTY_PSK 136 +#define EVP_R_INVALID_BUFFER_SIZE 137 + +#endif // OPENSSL_HEADER_EVP_ERRORS_H diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_obj.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_obj.h index e0dd5694..9bf419a5 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_obj.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_obj.h @@ -124,9 +124,22 @@ OPENSSL_EXPORT int OBJ_txt2nid(const char *s); // Getting information about nids. -// OBJ_nid2obj returns the ASN1_OBJECT corresponding to |nid|, or NULL if |nid| -// is unknown. -OPENSSL_EXPORT const ASN1_OBJECT *OBJ_nid2obj(int nid); +// OBJ_nid2obj returns the |ASN1_OBJECT| corresponding to |nid|, or NULL if +// |nid| is unknown. +// +// This function returns a static, immutable |ASN1_OBJECT|. Although the output +// is not const, callers may not mutate it. It is also not necessary to release +// the object with |ASN1_OBJECT_free|. +// +// However, functions like |X509_ALGOR_set0| expect to take ownership of a +// possibly dynamically-allocated |ASN1_OBJECT|. |ASN1_OBJECT_free| is a no-op +// for static |ASN1_OBJECT|s, so |OBJ_nid2obj| is compatible with such +// functions. +// +// Callers are encouraged to store the result of this function in a const +// pointer. However, if using functions like |X509_ALGOR_set0|, callers may use +// a non-const pointer and manage ownership. +OPENSSL_EXPORT ASN1_OBJECT *OBJ_nid2obj(int nid); // OBJ_nid2sn returns the short name for |nid|, or NULL if |nid| is unknown. OPENSSL_EXPORT const char *OBJ_nid2sn(int nid); diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h index a27d98b0..92e1f3b4 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h @@ -567,6 +567,11 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code); // See also |ssl_renegotiate_explicit|. #define SSL_ERROR_WANT_RENEGOTIATE 19 +// SSL_ERROR_HANDSHAKE_HINTS_READY indicates the handshake has progressed enough +// for |SSL_serialize_handshake_hints| to be called. See also +// |SSL_request_handshake_hints|. +#define SSL_ERROR_HANDSHAKE_HINTS_READY 20 + // SSL_error_description returns a string representation of |err|, where |err| // is one of the |SSL_ERROR_*| constants returned by |SSL_get_error|, or NULL // if the value is unrecognized. @@ -2723,8 +2728,9 @@ OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx); // SSL_CTX_set_alpn_protos sets the client ALPN protocol list on |ctx| to // |protos|. |protos| must be in wire-format (i.e. a series of non-empty, 8-bit -// length-prefixed strings). It returns zero on success and one on failure. -// Configuring this list enables ALPN on a client. +// length-prefixed strings), or the empty string to disable ALPN. It returns +// zero on success and one on failure. Configuring a non-empty string enables +// ALPN on a client. // // WARNING: this function is dangerous because it breaks the usual return value // convention. @@ -2733,8 +2739,9 @@ OPENSSL_EXPORT int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, // SSL_set_alpn_protos sets the client ALPN protocol list on |ssl| to |protos|. // |protos| must be in wire-format (i.e. a series of non-empty, 8-bit -// length-prefixed strings). It returns zero on success and one on failure. -// Configuring this list enables ALPN on a client. +// length-prefixed strings), or the empty string to disable ALPN. It returns +// zero on success and one on failure. Configuring a non-empty string enables +// ALPN on a client. // // WARNING: this function is dangerous because it breaks the usual return value // convention. @@ -3575,7 +3582,7 @@ OPENSSL_EXPORT const char *SSL_early_data_reason_string( enum ssl_early_data_reason_t reason); -// Encrypted Client Hello. +// Encrypted ClientHello. // // ECH is a mechanism for encrypting the entire ClientHello message in TLS 1.3. // This can prevent observers from seeing cleartext information about the @@ -3589,6 +3596,72 @@ OPENSSL_EXPORT const char *SSL_early_data_reason_string( // as part of this connection. OPENSSL_EXPORT void SSL_set_enable_ech_grease(SSL *ssl, int enable); +// SSL_ECH_SERVER_CONFIG_LIST_new returns a newly-allocated +// |SSL_ECH_SERVER_CONFIG_LIST| or NULL on error. +OPENSSL_EXPORT SSL_ECH_SERVER_CONFIG_LIST *SSL_ECH_SERVER_CONFIG_LIST_new(void); + +// SSL_ECH_SERVER_CONFIG_LIST_up_ref increments the reference count of |list|. +OPENSSL_EXPORT void SSL_ECH_SERVER_CONFIG_LIST_up_ref( + SSL_ECH_SERVER_CONFIG_LIST *list); + +// SSL_ECH_SERVER_CONFIG_LIST_free releases memory associated with |list|. +OPENSSL_EXPORT void SSL_ECH_SERVER_CONFIG_LIST_free( + SSL_ECH_SERVER_CONFIG_LIST *list); + +// SSL_ECH_SERVER_CONFIG_LIST_add appends an ECHConfig in |ech_config| and its +// corresponding private key in |private_key| to |list|. When |is_retry_config| +// is non-zero, this config will be returned to the client on configuration +// mismatch. It returns one on success and zero on error. See also +// |SSL_CTX_set1_ech_server_config_list|. +// +// This function should be called successively to register each ECHConfig in +// decreasing order of preference. This configuration must be completed before +// setting |list| on an |SSL_CTX| with |SSL_CTX_set1_ech_server_config_list|. +// After that point, |list| is immutable; no more ECHConfig values may be added. +OPENSSL_EXPORT int SSL_ECH_SERVER_CONFIG_LIST_add( + SSL_ECH_SERVER_CONFIG_LIST *list, int is_retry_config, + const uint8_t *ech_config, size_t ech_config_len, + const uint8_t *private_key, size_t private_key_len); + +// SSL_CTX_set1_ech_server_config_list atomically sets the refcounted |list| +// onto |ctx|, releasing the old list. |SSL| objects associated with |ctx|, as +// servers, will use |list| to decrypt incoming encrypted ClientHello messages. +// It returns one on success, and zero on failure. +// +// If |list| does not contain any retry configs, this function will fail. Retry +// configs are marked as such when they are added to |list| with +// |SSL_ECH_SERVER_CONFIG_LIST_add|. +// +// Once |list| has been passed to this function, it is immutable. Unlike most +// |SSL_CTX| configuration functions, this function may be called even if |ctx| +// already has associated connections on multiple threads. This may be used to +// rotate keys in a long-lived server process. +// +// The configured ECHConfig values should also be advertised out-of-band via DNS +// (see draft-ietf-dnsop-svcb-https). Before advertising an ECHConfig in DNS, +// deployments should ensure all instances of the service are configured with +// the ECHConfig and corresponding private key. +// +// Only the most recent fully-deployed ECHConfigs should be advertised in DNS. +// |list| may contain a newer set if those ECHConfigs are mid-deployment. It +// should also contain older sets, until the DNS change has rolled out and the +// old records have expired from caches. +// +// If there is a mismatch, |SSL| objects associated with |ctx| will complete the +// handshake using the cleartext ClientHello and send updated ECHConfig values +// to the client. The client will then retry to recover, but with a latency +// penalty. This recovery flow depends on the public name in the ECHConfig. +// Before advertising an ECHConfig in DNS, deployments must ensure all instances +// of the service can present a valid certificate for the public name. +// +// BoringSSL negotiates ECH before certificate selection callbacks are called, +// including |SSL_CTX_set_select_certificate_cb|. If ECH is negotiated, the +// reported |SSL_CLIENT_HELLO| structure and |SSL_get_servername| function will +// transparently reflect the inner ClientHello. Callers should select parameters +// based on these values to correctly handle ECH as well as the recovery flow. +OPENSSL_EXPORT int SSL_CTX_set1_ech_server_config_list( + SSL_CTX *ctx, SSL_ECH_SERVER_CONFIG_LIST *list); + // Alerts. // @@ -3725,6 +3798,101 @@ OPENSSL_EXPORT uint64_t SSL_get_read_sequence(const SSL *ssl); OPENSSL_EXPORT uint64_t SSL_get_write_sequence(const SSL *ssl); +// Handshake hints. +// +// *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** +// +// Some server deployments make asynchronous RPC calls in both ClientHello +// dispatch and private key operations. In TLS handshakes where the private key +// operation occurs in the first round-trip, this results in two consecutive RPC +// round-trips. Handshake hints allow the RPC service to predicte a signature. +// If correctly predicted, this can skip the second RPC call. +// +// First, the server installs a certificate selection callback (see +// |SSL_CTX_set_select_certificate_cb|). When that is called, it performs the +// RPC as before, but includes the ClientHello and a capabilities string from +// |SSL_serialize_capabilities|. +// +// Next, the RPC service creates its own |SSL| object, applies the results of +// certificate selection, calls |SSL_request_handshake_hints|, and runs the +// handshake. If this successfully computes handshake hints (see +// |SSL_serialize_handshake_hints|), the RPC server should send the hints +// alongside any certificate selection results. +// +// Finally, the server calls |SSL_set_handshake_hints| and applies any +// configuration from the RPC server. It then completes the handshake as before. +// If the hints apply, BoringSSL will use the predicted signature and skip the +// private key callbacks. Otherwise, BoringSSL will call private key callbacks +// to generate a signature as before. +// +// Callers should synchronize configuration across the two services. +// Configuration mismatches and some cases of version skew are not fatal, but +// may result in the hints not applying. Additionally, some handshake flows use +// the private key in later round-trips, such as TLS 1.3 HelloRetryRequest. In +// those cases, BoringSSL will not predict a signature as there is no benefit. +// Callers must allow for handshakes to complete without a predicted signature. +// +// For now, only TLS 1.3 is hinted. TLS 1.2 will work, but the hints will be +// empty. + +// SSL_serialize_capabilities writes an opaque byte string to |out| describing +// some of |ssl|'s capabilities. It returns one on success and zero on error. +// +// This string is used by BoringSSL internally to reduce the impact of version +// skew. +OPENSSL_EXPORT int SSL_serialize_capabilities(const SSL *ssl, CBB *out); + +// SSL_request_handshake_hints configures |ssl| to generate a handshake hint for +// |client_hello|. It returns one on success and zero on error. |client_hello| +// should contain a serialized ClientHello structure, from the |client_hello| +// and |client_hello_len| fields of the |SSL_CLIENT_HELLO| structure. +// |capabilities| should contain the output of |SSL_serialize_capabilities|. +// +// When configured, |ssl| will perform no I/O (so there is no need to configure +// |BIO|s). For QUIC, the caller should still configure an |SSL_QUIC_METHOD|, +// but the callbacks themselves will never be called and may be left NULL or +// report failure. |SSL_provide_quic_data| also should not be called. +// +// If hint generation is successful, |SSL_do_handshake| will stop the handshake +// early with |SSL_get_error| returning |SSL_ERROR_HANDSHAKE_HINTS_READY|. At +// this point, the caller should run |SSL_serialize_handshake_hints| to extract +// the resulting hints. +// +// Hint generation may fail if, e.g., |ssl| was unable to process the +// ClientHello. Callers should then complete the certificate selection RPC and +// continue the original handshake with no hint. It will likely fail, but this +// reports the correct alert to the client and is more robust in case of +// mismatch. +OPENSSL_EXPORT int SSL_request_handshake_hints(SSL *ssl, + const uint8_t *client_hello, + size_t client_hello_len, + const uint8_t *capabilities, + size_t capabilities_len); + +// SSL_serialize_handshake_hints writes an opaque byte string to |out| +// containing the handshake hints computed by |out|. It returns one on success +// and zero on error. This function should only be called if +// |SSL_request_handshake_hints| was configured and the handshake terminated +// with |SSL_ERROR_HANDSHAKE_HINTS_READY|. +// +// This string may be passed to |SSL_set_handshake_hints| on another |SSL| to +// avoid an extra signature call. +OPENSSL_EXPORT int SSL_serialize_handshake_hints(const SSL *ssl, CBB *out); + +// SSL_set_handshake_hints configures |ssl| to use |hints| as handshake hints. +// It returns one on success and zero on error. The handshake will then continue +// as before, but apply predicted values from |hints| where applicable. +// +// Hints may contain connection and session secrets, so they must not leak and +// must come from a source trusted to terminate the connection. However, they +// will not change |ssl|'s configuration. The caller is responsible for +// serializing and applying options from the RPC server as needed. This ensures +// |ssl|'s behavior is self-consistent and consistent with the caller's local +// decisions. +OPENSSL_EXPORT int SSL_set_handshake_hints(SSL *ssl, const uint8_t *hints, + size_t hints_len); + + // Obscure functions. // SSL_CTX_set_msg_callback installs |cb| as the message callback for |ctx|. @@ -4960,6 +5128,10 @@ BSSL_NAMESPACE_BEGIN BORINGSSL_MAKE_DELETER(SSL, SSL_free) BORINGSSL_MAKE_DELETER(SSL_CTX, SSL_CTX_free) BORINGSSL_MAKE_UP_REF(SSL_CTX, SSL_CTX_up_ref) +BORINGSSL_MAKE_DELETER(SSL_ECH_SERVER_CONFIG_LIST, + SSL_ECH_SERVER_CONFIG_LIST_free) +BORINGSSL_MAKE_UP_REF(SSL_ECH_SERVER_CONFIG_LIST, + SSL_ECH_SERVER_CONFIG_LIST_up_ref) BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free) BORINGSSL_MAKE_UP_REF(SSL_SESSION, SSL_SESSION_up_ref) @@ -5076,6 +5248,7 @@ OPENSSL_EXPORT bool SSL_get_traffic_secrets( const SSL *ssl, Span *out_read_traffic_secret, Span *out_write_traffic_secret); + BSSL_NAMESPACE_END } // extern C++ @@ -5293,6 +5466,13 @@ BSSL_NAMESPACE_END #define SSL_R_NO_APPLICATION_PROTOCOL 307 #define SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN 308 #define SSL_R_ALPS_MISMATCH_ON_EARLY_DATA 309 +#define SSL_R_ECH_SERVER_CONFIG_AND_PRIVATE_KEY_MISMATCH 310 +#define SSL_R_ECH_SERVER_CONFIG_UNSUPPORTED_EXTENSION 311 +#define SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG 312 +#define SSL_R_ECH_SERVER_WOULD_HAVE_NO_RETRY_CONFIGS 313 +#define SSL_R_INVALID_CLIENT_HELLO_INNER 314 +#define SSL_R_INVALID_ALPN_PROTOCOL_LIST 315 +#define SSL_R_COULD_NOT_PARSE_HINTS 316 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_tls1.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_tls1.h index b2d6b436..4e660760 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_tls1.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_tls1.h @@ -257,6 +257,7 @@ extern "C" { // extension number. #define TLSEXT_TYPE_encrypted_client_hello 0xfe09 #define TLSEXT_TYPE_ech_is_inner 0xda09 +#define TLSEXT_TYPE_ech_outer_extensions 0xfd00 // ExtensionType value from RFC6962 #define TLSEXT_TYPE_certificate_timestamp 18 diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_x509.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_x509.h index 671e0a5a..a5974f3b 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_x509.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_x509.h @@ -115,12 +115,6 @@ DECLARE_ASN1_SET_OF(X509_ALGOR) typedef STACK_OF(X509_ALGOR) X509_ALGORS; -struct X509_pubkey_st { - X509_ALGOR *algor; - ASN1_BIT_STRING *public_key; - EVP_PKEY *pkey; -}; - struct X509_sig_st { X509_ALGOR *algor; ASN1_OCTET_STRING *digest; @@ -159,17 +153,6 @@ typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; DEFINE_STACK_OF(X509_EXTENSION) DECLARE_ASN1_SET_OF(X509_EXTENSION) -// a sequence of these are used -struct x509_attributes_st { - ASN1_OBJECT *object; - int single; // 0 for a set, 1 for a single item (which is wrong) - union { - char *ptr; - /* 0 */ STACK_OF(ASN1_TYPE) *set; - /* 1 */ ASN1_TYPE *single; - } value; -} /* X509_ATTRIBUTE */; - DEFINE_STACK_OF(X509_ATTRIBUTE) DECLARE_ASN1_SET_OF(X509_ATTRIBUTE) @@ -536,9 +519,12 @@ OPENSSL_EXPORT int X509_set_notBefore(X509 *x509, const ASN1_TIME *tm); // instead. OPENSSL_EXPORT int X509_set_notAfter(X509 *x509, const ASN1_TIME *tm); -// X509_get0_uids sets |*out_issuer_uid| and |*out_subject_uid| to non-owning -// pointers to the issuerUID and subjectUID fields, respectively, of |x509|. -// Either output pointer may be NULL to skip the field. +// X509_get0_uids sets |*out_issuer_uid| to a non-owning pointer to the +// issuerUID field of |x509|, or NULL if |x509| has no issuerUID. It similarly +// outputs |x509|'s subjectUID field to |*out_subject_uid|. +// +// Callers may pass NULL to either |out_issuer_uid| or |out_subject_uid| to +// ignore the corresponding field. OPENSSL_EXPORT void X509_get0_uids(const X509 *x509, const ASN1_BIT_STRING **out_issuer_uid, const ASN1_BIT_STRING **out_subject_uid); @@ -615,14 +601,16 @@ OPENSSL_EXPORT ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl); // const-correct for legacy reasons. OPENSSL_EXPORT X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); -// X509_CRL_get_REVOKED returns the list of revoked certificates in |crl|. +// X509_CRL_get_REVOKED returns the list of revoked certificates in |crl|, or +// NULL if |crl| omits it. // // TOOD(davidben): This function was originally a macro, without clear const // semantics. It should take a const input and give const output, but the latter // would break existing callers. For now, we match upstream. OPENSSL_EXPORT STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl); -// X509_CRL_get0_extensions returns |crl|'s extension list. +// X509_CRL_get0_extensions returns |crl|'s extension list, or NULL if |crl| +// omits it. OPENSSL_EXPORT const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions( const X509_CRL *crl); @@ -905,12 +893,54 @@ OPENSSL_EXPORT X509_CRL *X509_CRL_dup(X509_CRL *crl); OPENSSL_EXPORT X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev); OPENSSL_EXPORT X509_REQ *X509_REQ_dup(X509_REQ *req); OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); -OPENSSL_EXPORT int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, - int ptype, void *pval); -OPENSSL_EXPORT void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, - const void **ppval, - const X509_ALGOR *algor); + +// X509_ALGOR_set0 sets |alg| to an AlgorithmIdentifier with algorithm |obj| and +// parameter determined by |param_type| and |param_value|. It returns one on +// success and zero on error. This function takes ownership of |obj| and +// |param_value| on success. +// +// If |param_type| is |V_ASN1_UNDEF|, the parameter is omitted. If |param_type| +// is zero, the parameter is left unchanged. Otherwise, |param_type| and +// |param_value| are interpreted as in |ASN1_TYPE_set|. +// +// Note omitting the parameter (|V_ASN1_UNDEF|) and encoding an explicit NULL +// value (|V_ASN1_NULL|) are different. Some algorithms require one and some the +// other. Consult the relevant specification before calling this function. The +// correct parameter for an RSASSA-PKCS1-v1_5 signature is |V_ASN1_NULL|. The +// correct one for an ECDSA or Ed25519 signature is |V_ASN1_UNDEF|. +OPENSSL_EXPORT int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *obj, + int param_type, void *param_value); + +// X509_ALGOR_get0 sets |*out_obj| to the |alg|'s algorithm. If |alg|'s +// parameter is omitted, it sets |*out_param_type| and |*out_param_value| to +// |V_ASN1_UNDEF| and NULL. Otherwise, it sets |*out_param_type| and +// |*out_param_value| to the parameter, using the same representation as +// |ASN1_TYPE_set0|. See |ASN1_TYPE_set0| and |ASN1_TYPE| for details. +// +// Callers that require the parameter in serialized form should, after checking +// for |V_ASN1_UNDEF|, use |ASN1_TYPE_set1| and |d2i_ASN1_TYPE|, rather than +// inspecting |*out_param_value|. +// +// Each of |out_obj|, |out_param_type|, and |out_param_value| may be NULL to +// ignore the output. If |out_param_type| is NULL, |out_param_value| is ignored. +// +// WARNING: If |*out_param_type| is set to |V_ASN1_UNDEF|, OpenSSL and older +// revisions of BoringSSL leave |*out_param_value| unset rather than setting it +// to NULL. Callers that support both OpenSSL and BoringSSL should not assume +// |*out_param_value| is uniformly initialized. +OPENSSL_EXPORT void X509_ALGOR_get0(const ASN1_OBJECT **out_obj, + int *out_param_type, + const void **out_param_value, + const X509_ALGOR *alg); + +// X509_ALGOR_set_md sets |alg| to the hash function |md|. Note this +// AlgorithmIdentifier represents the hash function itself, not a signature +// algorithm that uses |md|. OPENSSL_EXPORT void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); + +// X509_ALGOR_cmp returns zero if |a| and |b| are equal, and some non-zero value +// otherwise. Note this function can only be used for equality checks, not an +// ordering. OPENSSL_EXPORT int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn); @@ -950,7 +980,12 @@ DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO) DECLARE_ASN1_FUNCTIONS(X509_REQ) DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE) -OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, + +// X509_ATTRIBUTE_create returns a newly-allocated |X509_ATTRIBUTE|, or NULL on +// error. The attribute has type |nid| and contains a single value determined by +// |attrtype| and |value|, which are interpreted as in |ASN1_TYPE_set|. Note +// this function takes ownership of |value|. +OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype, void *value); DECLARE_ASN1_FUNCTIONS(X509_EXTENSION) @@ -1096,16 +1131,47 @@ OPENSSL_EXPORT int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx); -OPENSSL_EXPORT ASN1_INTEGER *X509_get_serialNumber(X509 *x); -OPENSSL_EXPORT int X509_set_issuer_name(X509 *x, X509_NAME *name); -OPENSSL_EXPORT X509_NAME *X509_get_issuer_name(const X509 *a); -OPENSSL_EXPORT int X509_set_subject_name(X509 *x, X509_NAME *name); -OPENSSL_EXPORT X509_NAME *X509_get_subject_name(const X509 *a); -OPENSSL_EXPORT int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); -OPENSSL_EXPORT EVP_PKEY *X509_get_pubkey(X509 *x); -OPENSSL_EXPORT ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); +// X509_get_serialNumber returns a mutable pointer to |x509|'s serial number. +// Prefer |X509_get0_serialNumber|. +OPENSSL_EXPORT ASN1_INTEGER *X509_get_serialNumber(X509 *x509); + +// X509_set_issuer_name sets |x509|'s issuer to a copy of |name|. It returns one +// on success and zero on error. +OPENSSL_EXPORT int X509_set_issuer_name(X509 *x509, X509_NAME *name); + +// X509_get_issuer_name returns |x509|'s issuer. +OPENSSL_EXPORT X509_NAME *X509_get_issuer_name(const X509 *x509); + +// X509_set_subject_name sets |x509|'s subject to a copy of |name|. It returns +// one on success and zero on error. +OPENSSL_EXPORT int X509_set_subject_name(X509 *x509, X509_NAME *name); + +// X509_get_issuer_name returns |x509|'s subject. +OPENSSL_EXPORT X509_NAME *X509_get_subject_name(const X509 *x509); + +// X509_set_pubkey sets |x509|'s public key to |pkey|. It returns one on success +// and zero on error. This function does not take ownership of |pkey| and +// internally copies and updates reference counts as needed. +OPENSSL_EXPORT int X509_set_pubkey(X509 *x509, EVP_PKEY *pkey); + +// X509_get_pubkey returns |x509|'s public key as an |EVP_PKEY|, or NULL if the +// public key was unsupported or could not be decoded. This function returns a +// reference to the |EVP_PKEY|. The caller must release the result with +// |EVP_PKEY_free| when done. +OPENSSL_EXPORT EVP_PKEY *X509_get_pubkey(X509 *x509); + +// X509_get0_pubkey_bitstr returns the BIT STRING portion of |x509|'s public +// key. Note this does not contain the AlgorithmIdentifier portion. +// +// WARNING: This function returns a non-const pointer for OpenSSL compatibility, +// but the caller must not modify the resulting object. Doing so will break +// internal invariants in |x509|. +OPENSSL_EXPORT ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x509); + +// X509_get0_extensions returns |x509|'s extension list, or NULL if |x509| omits +// it. OPENSSL_EXPORT const STACK_OF(X509_EXTENSION) *X509_get0_extensions( - const X509 *x); + const X509 *x509); // X509_get0_tbs_sigalg returns the signature algorithm in |x509|'s // TBSCertificate. For the outer signature algorithm, see |X509_get0_signature|. @@ -1119,6 +1185,9 @@ OPENSSL_EXPORT const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x509); // // Note no versions other than |X509V1_VERSION| are defined for CSRs. OPENSSL_EXPORT int X509_REQ_set_version(X509_REQ *req, long version); + +// X509_REQ_set_subject_name sets |req|'s subject to a copy of |name|. It +// returns one on success and zero on error. OPENSSL_EXPORT int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); // X509_REQ_get0_signature sets |*out_sig| and |*out_alg| to the signature and @@ -1133,36 +1202,116 @@ OPENSSL_EXPORT void X509_REQ_get0_signature(const X509_REQ *req, // a known NID. OPENSSL_EXPORT int X509_REQ_get_signature_nid(const X509_REQ *req); -OPENSSL_EXPORT int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp); -OPENSSL_EXPORT int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +// i2d_re_X509_REQ_tbs serializes the CertificationRequestInfo (see RFC2986) +// portion of |req|. If |outp| is NULL, nothing is written. Otherwise, if +// |*outp| is not NULL, the result is written to |*outp|, which must have enough +// space available, and |*outp| is advanced just past the output. If |outp| is +// non-NULL and |*outp| is NULL, it sets |*outp| to a newly-allocated buffer +// containing the result. The caller is responsible for releasing the buffer +// with |OPENSSL_free|. In all cases, this function returns the number of bytes +// in the result, whether written or not, or a negative value on error. +// +// This function re-encodes the CertificationRequestInfo and may not reflect +// |req|'s original encoding. It may be used to manually generate a signature +// for a new certificate request. +OPENSSL_EXPORT int i2d_re_X509_REQ_tbs(X509_REQ *req, uint8_t **outp); + +// X509_REQ_set_pubkey sets |req|'s public key to |pkey|. It returns one on +// success and zero on error. This function does not take ownership of |pkey| +// and internally copies and updates reference counts as needed. +OPENSSL_EXPORT int X509_REQ_set_pubkey(X509_REQ *req, EVP_PKEY *pkey); + +// X509_REQ_get_pubkey returns |req|'s public key as an |EVP_PKEY|, or NULL if +// the public key was unsupported or could not be decoded. This function returns +// a reference to the |EVP_PKEY|. The caller must release the result with +// |EVP_PKEY_free| when done. OPENSSL_EXPORT EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req); + +// X509_REQ_extension_nid returns one if |nid| is a supported CSR attribute type +// for carrying extensions and zero otherwise. The supported types are +// |NID_ext_req| (pkcs-9-at-extensionRequest from RFC2985) and |NID_ms_ext_req| +// (a Microsoft szOID_CERT_EXTENSIONS variant). OPENSSL_EXPORT int X509_REQ_extension_nid(int nid); -OPENSSL_EXPORT const int *X509_REQ_get_extension_nids(void); -OPENSSL_EXPORT void X509_REQ_set_extension_nids(const int *nids); + +// X509_REQ_get_extensions decodes the list of requested extensions in |req| and +// returns a newly-allocated |STACK_OF(X509_EXTENSION)| containing the result. +// It returns NULL on error, or if |req| did not request extensions. +// +// This function supports both pkcs-9-at-extensionRequest from RFC2985 and the +// Microsoft szOID_CERT_EXTENSIONS variant. OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); -OPENSSL_EXPORT int X509_REQ_add_extensions_nid(X509_REQ *req, - STACK_OF(X509_EXTENSION) *exts, - int nid); -OPENSSL_EXPORT int X509_REQ_add_extensions(X509_REQ *req, - STACK_OF(X509_EXTENSION) *exts); + +// X509_REQ_add_extensions_nid adds an attribute to |req| of type |nid|, to +// request the certificate extensions in |exts|. It returns one on success and +// zero on error. |nid| should be |NID_ext_req| or |NID_ms_ext_req|. +OPENSSL_EXPORT int X509_REQ_add_extensions_nid( + X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts, int nid); + +// X509_REQ_add_extensions behaves like |X509_REQ_add_extensions_nid|, using the +// standard |NID_ext_req| for the attribute type. +OPENSSL_EXPORT int X509_REQ_add_extensions( + X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts); + +// X509_REQ_get_attr_count returns the number of attributes in |req|. OPENSSL_EXPORT int X509_REQ_get_attr_count(const X509_REQ *req); + +// X509_REQ_get_attr_by_NID returns the index of the attribute in |req| of type +// |nid|, or a negative number if not found. If found, callers can use +// |X509_REQ_get_attr| to look up the attribute by index. +// +// If |lastpos| is non-negative, it begins searching at |lastpos| + 1. Callers +// can thus loop over all matching attributes by first passing -1 and then +// passing the previously-returned value until no match is returned. OPENSSL_EXPORT int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos); + +// X509_REQ_get_attr_by_OBJ behaves like |X509_REQ_get_attr_by_NID| but looks +// for attributes of type |obj|. OPENSSL_EXPORT int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, - ASN1_OBJECT *obj, int lastpos); + const ASN1_OBJECT *obj, + int lastpos); + +// X509_REQ_get_attr returns the attribute at index |loc| in |req|, or NULL if +// out of bounds. OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); + +// X509_REQ_delete_attr removes the attribute at index |loc| in |req|. It +// returns the removed attribute to the caller, or NULL if |loc| was out of +// bounds. If non-NULL, the caller must release the result with +// |X509_ATTRIBUTE_free| when done. It is also safe, but not necessary, to call +// |X509_ATTRIBUTE_free| if the result is NULL. OPENSSL_EXPORT X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); + +// X509_REQ_add1_attr appends a copy of |attr| to |req|'s list of attributes. It +// returns one on success and zero on error. +// +// TODO(https://crbug.com/boringssl/407): |attr| should be const. OPENSSL_EXPORT int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); + +// X509_REQ_add1_attr_by_OBJ appends a new attribute to |req| with type |obj|. +// It returns one on success and zero on error. The value is determined by +// |X509_ATTRIBUTE_set1_data|. +// +// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and +// error-prone. See |X509_ATTRIBUTE_set1_data| for details. OPENSSL_EXPORT int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, - const ASN1_OBJECT *obj, int type, - const unsigned char *bytes, + const ASN1_OBJECT *obj, + int attrtype, + const unsigned char *data, int len); -OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int type, - const unsigned char *bytes, + +// X509_REQ_add1_attr_by_NID behaves like |X509_REQ_add1_attr_by_OBJ| except the +// attribute type is determined by |nid|. +OPENSSL_EXPORT int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, + int attrtype, + const unsigned char *data, int len); + +// X509_REQ_add1_attr_by_txt behaves like |X509_REQ_add1_attr_by_OBJ| except the +// attribute type is determined by calling |OBJ_txt2obj| with |attrname|. OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req, - const char *attrname, int type, - const unsigned char *bytes, + const char *attrname, int attrtype, + const unsigned char *data, int len); // X509_CRL_set_version sets |crl|'s version to |version|, which should be one @@ -1172,7 +1321,11 @@ OPENSSL_EXPORT int X509_REQ_add1_attr_by_txt(X509_REQ *req, // If unsure, use |X509V2_VERSION|. Note |X509V3_VERSION| is not defined for // CRLs. OPENSSL_EXPORT int X509_CRL_set_version(X509_CRL *crl, long version); -OPENSSL_EXPORT int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); + +// X509_CRL_set_issuer_name sets |crl|'s issuer to a copy of |name|. It returns +// one on success and zero on error. +OPENSSL_EXPORT int X509_CRL_set_issuer_name(X509_CRL *crl, X509_NAME *name); + OPENSSL_EXPORT int X509_CRL_sort(X509_CRL *crl); // X509_CRL_up_ref adds one to the reference count of |crl| and returns one. @@ -1243,7 +1396,8 @@ OPENSSL_EXPORT const ASN1_TIME *X509_REVOKED_get0_revocationDate( OPENSSL_EXPORT int X509_REVOKED_set_revocationDate(X509_REVOKED *revoked, const ASN1_TIME *tm); -// X509_REVOKED_get0_extensions returns |r|'s extensions. +// X509_REVOKED_get0_extensions returns |r|'s extensions list, or NULL if |r| +// omits it. OPENSSL_EXPORT const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions( const X509_REVOKED *r); @@ -1497,22 +1651,96 @@ OPENSSL_EXPORT STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt( OPENSSL_EXPORT void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, ASN1_OBJECT *obj, int lastpos, int type); + +// X509_ATTRIBUTE_create_by_NID returns a newly-allocated |X509_ATTRIBUTE| of +// type |nid|, or NULL on error. The value is determined as in +// |X509_ATTRIBUTE_set1_data|. +// +// If |attr| is non-NULL, the resulting |X509_ATTRIBUTE| is also written to +// |*attr|. If |*attr| was non-NULL when the function was called, |*attr| is +// reused instead of creating a new object. +// +// WARNING: The interpretation of |attrtype|, |data|, and |len| is complex and +// error-prone. See |X509_ATTRIBUTE_set1_data| for details. +// +// WARNING: The object reuse form is deprecated and may be removed in the +// future. It also currently incorrectly appends to the reused object's value +// set rather than overwriting it. OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID( - X509_ATTRIBUTE **attr, int nid, int atrtype, const void *data, int len); + X509_ATTRIBUTE **attr, int nid, int attrtype, const void *data, int len); + +// X509_ATTRIBUTE_create_by_OBJ behaves like |X509_ATTRIBUTE_create_by_NID| +// except the attribute's type is determined by |obj|. OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ( - X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, int atrtype, + X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, int attrtype, const void *data, int len); + +// X509_ATTRIBUTE_create_by_txt behaves like |X509_ATTRIBUTE_create_by_NID| +// except the attribute's type is determined by calling |OBJ_txt2obj| with +// |attrname|. OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt( - X509_ATTRIBUTE **attr, const char *atrname, int type, + X509_ATTRIBUTE **attr, const char *attrname, int type, const unsigned char *bytes, int len); + +// X509_ATTRIBUTE_set1_object sets |attr|'s type to |obj|. It returns one on +// success and zero on error. OPENSSL_EXPORT int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); + +// X509_ATTRIBUTE_set1_data appends a value to |attr|'s value set and returns +// one on success or zero on error. The value is determined as follows: +// +// If |attrtype| is a |MBSTRING_*| constant, the value is an ASN.1 string. The +// string is determined by decoding |len| bytes from |data| in the encoding +// specified by |attrtype|, and then re-encoding it in a form appropriate for +// |attr|'s type. If |len| is -1, |strlen(data)| is used instead. See +// |ASN1_STRING_set_by_NID| for details. +// +// TODO(davidben): Document |ASN1_STRING_set_by_NID| so the reference is useful. +// +// Otherwise, if |len| is not -1, the value is an ASN.1 string. |attrtype| is an +// |ASN1_STRING| type value and the |len| bytes from |data| are copied as the +// type-specific representation of |ASN1_STRING|. See |ASN1_STRING| for details. +// +// WARNING: If this form is used to construct a negative INTEGER or ENUMERATED, +// |attrtype| includes the |V_ASN1_NEG| flag for |ASN1_STRING|, but the function +// forgets to clear the flag for |ASN1_TYPE|. This matches OpenSSL but is +// probably a bug. For now, do not use this form with negative values. +// +// Otherwise, if |len| is -1, the value is constructed by passing |attrtype| and +// |data| to |ASN1_TYPE_set1|. That is, |attrtype| is an |ASN1_TYPE| type value, +// and |data| is cast to the corresponding pointer type. +// +// WARNING: Despite the name, this function appends to |attr|'s value set, +// rather than overwriting it. To overwrite the value set, create a new +// |X509_ATTRIBUTE| with |X509_ATTRIBUTE_new|. +// +// WARNING: If using the |MBSTRING_*| form, pass a length rather than relying on +// |strlen|. In particular, |strlen| will not behave correctly if the input is +// |MBSTRING_BMP| or |MBSTRING_UNIV|. +// +// WARNING: This function currently misinterprets |V_ASN1_OTHER| as an +// |MBSTRING_*| constant. This matches OpenSSL but means it is impossible to +// construct a value with a non-universal tag. OPENSSL_EXPORT int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len); + +// X509_ATTRIBUTE_get0_data returns the |idx|th value of |attr| in a +// type-specific representation to |attrtype|, or NULL if out of bounds or the +// type does not match. |attrtype| is one of the type values in |ASN1_TYPE|. On +// match, the return value uses the same representation as |ASN1_TYPE_set0|. See +// |ASN1_TYPE| for details. OPENSSL_EXPORT void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, - int atrtype, void *data); -OPENSSL_EXPORT int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr); + int attrtype, void *unused); + +// X509_ATTRIBUTE_count returns the number of values in |attr|. +OPENSSL_EXPORT int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr); + +// X509_ATTRIBUTE_get0_object returns the type of |attr|. OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); + +// X509_ATTRIBUTE_get0_type returns the |idx|th value in |attr|, or NULL if out +// of bounds. Note this function returns one of |attr|'s values, not the type. OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); @@ -1538,13 +1766,36 @@ OPENSSL_EXPORT int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8); -OPENSSL_EXPORT int X509_PUBKEY_set0_param(X509_PUBKEY *pub, - const ASN1_OBJECT *aobj, int ptype, - void *pval, unsigned char *penc, - int penclen); -OPENSSL_EXPORT int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, - const unsigned char **pk, int *ppklen, - X509_ALGOR **pa, X509_PUBKEY *pub); +// X509_PUBKEY_set0_param sets |pub| to a key with AlgorithmIdentifier +// determined by |obj|, |param_type|, and |param_value|, and an encoded +// public key of |key|. On success, it takes ownership of all its parameters and +// returns one. Otherwise, it returns zero. |key| must have been allocated by +// |OPENSSL_malloc|. +// +// |obj|, |param_type|, and |param_value| are interpreted as in +// |X509_ALGOR_set0|. See |X509_ALGOR_set0| for details. +OPENSSL_EXPORT int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, + int param_type, void *param_value, + uint8_t *key, int key_len); + +// X509_PUBKEY_get0_param outputs fields of |pub| and returns one. If |out_obj| +// is not NULL, it sets |*out_obj| to AlgorithmIdentifier's OID. If |out_key| +// is not NULL, it sets |*out_key| and |*out_key_len| to the encoded public key. +// If |out_alg| is not NULL, it sets |*out_alg| to the AlgorithmIdentifier. +// +// Note: X.509 SubjectPublicKeyInfo structures store the encoded public key as a +// BIT STRING. |*out_key| and |*out_key_len| will silently pad the key with zero +// bits if |pub| did not contain a whole number of bytes. Use +// |X509_PUBKEY_get0_public_key| to preserve this information. +OPENSSL_EXPORT int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, + const uint8_t **out_key, + int *out_key_len, + X509_ALGOR **out_alg, + X509_PUBKEY *pub); + +// X509_PUBKEY_get0_public_key returns |pub|'s encoded public key. +OPENSSL_EXPORT const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key( + const X509_PUBKEY *pub); OPENSSL_EXPORT int X509_check_trust(X509 *x, int id, int flags); OPENSSL_EXPORT int X509_TRUST_get_count(void); @@ -1584,6 +1835,7 @@ BORINGSSL_MAKE_DELETER(RSA_PSS_PARAMS, RSA_PSS_PARAMS_free) BORINGSSL_MAKE_DELETER(X509, X509_free) BORINGSSL_MAKE_UP_REF(X509, X509_up_ref) BORINGSSL_MAKE_DELETER(X509_ALGOR, X509_ALGOR_free) +BORINGSSL_MAKE_DELETER(X509_ATTRIBUTE, X509_ATTRIBUTE_free) BORINGSSL_MAKE_DELETER(X509_CRL, X509_CRL_free) BORINGSSL_MAKE_UP_REF(X509_CRL, X509_CRL_up_ref) BORINGSSL_MAKE_DELETER(X509_CRL_METHOD, X509_CRL_METHOD_free) diff --git a/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc b/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc index e981293b..0071f0ab 100644 --- a/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc +++ b/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc @@ -964,6 +964,8 @@ %xdefine _EVP_EncryptUpdate _ %+ BORINGSSL_PREFIX %+ _EVP_EncryptUpdate %xdefine _EVP_HPKE_CTX_cleanup _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_cleanup %xdefine _EVP_HPKE_CTX_export _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_export +%xdefine _EVP_HPKE_CTX_get_aead_id _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_get_aead_id +%xdefine _EVP_HPKE_CTX_get_kdf_id _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_get_kdf_id %xdefine _EVP_HPKE_CTX_init _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_init %xdefine _EVP_HPKE_CTX_max_overhead _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_max_overhead %xdefine _EVP_HPKE_CTX_open _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_open @@ -1090,7 +1092,6 @@ %xdefine _EVP_add_digest _ %+ BORINGSSL_PREFIX %+ _EVP_add_digest %xdefine _EVP_aead_aes_128_cbc_sha1_tls _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_128_cbc_sha1_tls %xdefine _EVP_aead_aes_128_cbc_sha1_tls_implicit_iv _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_128_cbc_sha1_tls_implicit_iv -%xdefine _EVP_aead_aes_128_cbc_sha256_tls _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_128_cbc_sha256_tls %xdefine _EVP_aead_aes_128_ccm_bluetooth _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_128_ccm_bluetooth %xdefine _EVP_aead_aes_128_ccm_bluetooth_8 _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_128_ccm_bluetooth_8 %xdefine _EVP_aead_aes_128_ctr_hmac_sha256 _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_128_ctr_hmac_sha256 @@ -1102,8 +1103,6 @@ %xdefine _EVP_aead_aes_192_gcm _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_192_gcm %xdefine _EVP_aead_aes_256_cbc_sha1_tls _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha1_tls %xdefine _EVP_aead_aes_256_cbc_sha1_tls_implicit_iv _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha1_tls_implicit_iv -%xdefine _EVP_aead_aes_256_cbc_sha256_tls _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha256_tls -%xdefine _EVP_aead_aes_256_cbc_sha384_tls _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha384_tls %xdefine _EVP_aead_aes_256_ctr_hmac_sha256 _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_ctr_hmac_sha256 %xdefine _EVP_aead_aes_256_gcm _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_gcm %xdefine _EVP_aead_aes_256_gcm_randnonce _ %+ BORINGSSL_PREFIX %+ _EVP_aead_aes_256_gcm_randnonce @@ -1159,6 +1158,7 @@ %xdefine _EVP_rc2_cbc _ %+ BORINGSSL_PREFIX %+ _EVP_rc2_cbc %xdefine _EVP_rc4 _ %+ BORINGSSL_PREFIX %+ _EVP_rc4 %xdefine _EVP_sha1 _ %+ BORINGSSL_PREFIX %+ _EVP_sha1 +%xdefine _EVP_sha1_final_with_secret_suffix _ %+ BORINGSSL_PREFIX %+ _EVP_sha1_final_with_secret_suffix %xdefine _EVP_sha224 _ %+ BORINGSSL_PREFIX %+ _EVP_sha224 %xdefine _EVP_sha256 _ %+ BORINGSSL_PREFIX %+ _EVP_sha256 %xdefine _EVP_sha384 _ %+ BORINGSSL_PREFIX %+ _EVP_sha384 @@ -1173,6 +1173,7 @@ %xdefine _EXTENDED_KEY_USAGE_new _ %+ BORINGSSL_PREFIX %+ _EXTENDED_KEY_USAGE_new %xdefine _FIPS_mode _ %+ BORINGSSL_PREFIX %+ _FIPS_mode %xdefine _FIPS_mode_set _ %+ BORINGSSL_PREFIX %+ _FIPS_mode_set +%xdefine _FIPS_read_counter _ %+ BORINGSSL_PREFIX %+ _FIPS_read_counter %xdefine _GENERAL_NAMES_free _ %+ BORINGSSL_PREFIX %+ _GENERAL_NAMES_free %xdefine _GENERAL_NAMES_it _ %+ BORINGSSL_PREFIX %+ _GENERAL_NAMES_it %xdefine _GENERAL_NAMES_new _ %+ BORINGSSL_PREFIX %+ _GENERAL_NAMES_new @@ -1685,6 +1686,7 @@ %xdefine _SSL_CTX_set1_chain _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_chain %xdefine _SSL_CTX_set1_curves _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_curves %xdefine _SSL_CTX_set1_curves_list _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_curves_list +%xdefine _SSL_CTX_set1_ech_server_config_list _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_ech_server_config_list %xdefine _SSL_CTX_set1_param _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_param %xdefine _SSL_CTX_set1_sigalgs _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_sigalgs %xdefine _SSL_CTX_set1_sigalgs_list _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_set1_sigalgs_list @@ -1772,6 +1774,10 @@ %xdefine _SSL_CTX_use_certificate_chain_file _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_use_certificate_chain_file %xdefine _SSL_CTX_use_certificate_file _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_use_certificate_file %xdefine _SSL_CTX_use_psk_identity_hint _ %+ BORINGSSL_PREFIX %+ _SSL_CTX_use_psk_identity_hint +%xdefine _SSL_ECH_SERVER_CONFIG_LIST_add _ %+ BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_add +%xdefine _SSL_ECH_SERVER_CONFIG_LIST_free _ %+ BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_free +%xdefine _SSL_ECH_SERVER_CONFIG_LIST_new _ %+ BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_new +%xdefine _SSL_ECH_SERVER_CONFIG_LIST_up_ref _ %+ BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_up_ref %xdefine _SSL_SESSION_copy_without_early_data _ %+ BORINGSSL_PREFIX %+ _SSL_SESSION_copy_without_early_data %xdefine _SSL_SESSION_early_data_capable _ %+ BORINGSSL_PREFIX %+ _SSL_SESSION_early_data_capable %xdefine _SSL_SESSION_free _ %+ BORINGSSL_PREFIX %+ _SSL_SESSION_free @@ -1956,9 +1962,12 @@ %xdefine _SSL_read _ %+ BORINGSSL_PREFIX %+ _SSL_read %xdefine _SSL_renegotiate _ %+ BORINGSSL_PREFIX %+ _SSL_renegotiate %xdefine _SSL_renegotiate_pending _ %+ BORINGSSL_PREFIX %+ _SSL_renegotiate_pending +%xdefine _SSL_request_handshake_hints _ %+ BORINGSSL_PREFIX %+ _SSL_request_handshake_hints %xdefine _SSL_reset_early_data_reject _ %+ BORINGSSL_PREFIX %+ _SSL_reset_early_data_reject %xdefine _SSL_select_next_proto _ %+ BORINGSSL_PREFIX %+ _SSL_select_next_proto %xdefine _SSL_send_fatal_alert _ %+ BORINGSSL_PREFIX %+ _SSL_send_fatal_alert +%xdefine _SSL_serialize_capabilities _ %+ BORINGSSL_PREFIX %+ _SSL_serialize_capabilities +%xdefine _SSL_serialize_handshake_hints _ %+ BORINGSSL_PREFIX %+ _SSL_serialize_handshake_hints %xdefine _SSL_session_reused _ %+ BORINGSSL_PREFIX %+ _SSL_session_reused %xdefine _SSL_set0_chain _ %+ BORINGSSL_PREFIX %+ _SSL_set0_chain %xdefine _SSL_set0_client_CAs _ %+ BORINGSSL_PREFIX %+ _SSL_set0_client_CAs @@ -1989,6 +1998,7 @@ %xdefine _SSL_set_enforce_rsa_key_usage _ %+ BORINGSSL_PREFIX %+ _SSL_set_enforce_rsa_key_usage %xdefine _SSL_set_ex_data _ %+ BORINGSSL_PREFIX %+ _SSL_set_ex_data %xdefine _SSL_set_fd _ %+ BORINGSSL_PREFIX %+ _SSL_set_fd +%xdefine _SSL_set_handshake_hints _ %+ BORINGSSL_PREFIX %+ _SSL_set_handshake_hints %xdefine _SSL_set_info_callback _ %+ BORINGSSL_PREFIX %+ _SSL_set_info_callback %xdefine _SSL_set_jdk11_workaround _ %+ BORINGSSL_PREFIX %+ _SSL_set_jdk11_workaround %xdefine _SSL_set_max_cert_list _ %+ BORINGSSL_PREFIX %+ _SSL_set_max_cert_list @@ -2156,7 +2166,6 @@ %xdefine _X509_ALGOR_new _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_new %xdefine _X509_ALGOR_set0 _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_set0 %xdefine _X509_ALGOR_set_md _ %+ BORINGSSL_PREFIX %+ _X509_ALGOR_set_md -%xdefine _X509_ATTRIBUTE_SET_it _ %+ BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_SET_it %xdefine _X509_ATTRIBUTE_count _ %+ BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_count %xdefine _X509_ATTRIBUTE_create _ %+ BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_create %xdefine _X509_ATTRIBUTE_create_by_NID _ %+ BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_create_by_NID @@ -2308,6 +2317,7 @@ %xdefine _X509_PUBKEY_free _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_free %xdefine _X509_PUBKEY_get _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get %xdefine _X509_PUBKEY_get0_param _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_param +%xdefine _X509_PUBKEY_get0_public_key _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_public_key %xdefine _X509_PUBKEY_it _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_it %xdefine _X509_PUBKEY_new _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_new %xdefine _X509_PUBKEY_set _ %+ BORINGSSL_PREFIX %+ _X509_PUBKEY_set @@ -2344,7 +2354,6 @@ %xdefine _X509_REQ_get_attr_by_NID _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_attr_by_NID %xdefine _X509_REQ_get_attr_by_OBJ _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_attr_by_OBJ %xdefine _X509_REQ_get_attr_count _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_attr_count -%xdefine _X509_REQ_get_extension_nids _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_extension_nids %xdefine _X509_REQ_get_extensions _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_extensions %xdefine _X509_REQ_get_pubkey _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_pubkey %xdefine _X509_REQ_get_signature_nid _ %+ BORINGSSL_PREFIX %+ _X509_REQ_get_signature_nid @@ -2355,7 +2364,6 @@ %xdefine _X509_REQ_print _ %+ BORINGSSL_PREFIX %+ _X509_REQ_print %xdefine _X509_REQ_print_ex _ %+ BORINGSSL_PREFIX %+ _X509_REQ_print_ex %xdefine _X509_REQ_print_fp _ %+ BORINGSSL_PREFIX %+ _X509_REQ_print_fp -%xdefine _X509_REQ_set_extension_nids _ %+ BORINGSSL_PREFIX %+ _X509_REQ_set_extension_nids %xdefine _X509_REQ_set_pubkey _ %+ BORINGSSL_PREFIX %+ _X509_REQ_set_pubkey %xdefine _X509_REQ_set_subject_name _ %+ BORINGSSL_PREFIX %+ _X509_REQ_set_subject_name %xdefine _X509_REQ_set_version _ %+ BORINGSSL_PREFIX %+ _X509_REQ_set_version @@ -2705,6 +2713,7 @@ %xdefine _asn1_refcount_dec_and_test_zero _ %+ BORINGSSL_PREFIX %+ _asn1_refcount_dec_and_test_zero %xdefine _asn1_refcount_set_one _ %+ BORINGSSL_PREFIX %+ _asn1_refcount_set_one %xdefine _asn1_set_choice_selector _ %+ BORINGSSL_PREFIX %+ _asn1_set_choice_selector +%xdefine _asn1_type_value_as_pointer _ %+ BORINGSSL_PREFIX %+ _asn1_type_value_as_pointer %xdefine _asn1_utctime_to_tm _ %+ BORINGSSL_PREFIX %+ _asn1_utctime_to_tm %xdefine _beeu_mod_inverse_vartime _ %+ BORINGSSL_PREFIX %+ _beeu_mod_inverse_vartime %xdefine _bio_clear_socket_error _ %+ BORINGSSL_PREFIX %+ _bio_clear_socket_error @@ -4330,6 +4339,8 @@ %xdefine EVP_EncryptUpdate BORINGSSL_PREFIX %+ _EVP_EncryptUpdate %xdefine EVP_HPKE_CTX_cleanup BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_cleanup %xdefine EVP_HPKE_CTX_export BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_export +%xdefine EVP_HPKE_CTX_get_aead_id BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_get_aead_id +%xdefine EVP_HPKE_CTX_get_kdf_id BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_get_kdf_id %xdefine EVP_HPKE_CTX_init BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_init %xdefine EVP_HPKE_CTX_max_overhead BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_max_overhead %xdefine EVP_HPKE_CTX_open BORINGSSL_PREFIX %+ _EVP_HPKE_CTX_open @@ -4456,7 +4467,6 @@ %xdefine EVP_add_digest BORINGSSL_PREFIX %+ _EVP_add_digest %xdefine EVP_aead_aes_128_cbc_sha1_tls BORINGSSL_PREFIX %+ _EVP_aead_aes_128_cbc_sha1_tls %xdefine EVP_aead_aes_128_cbc_sha1_tls_implicit_iv BORINGSSL_PREFIX %+ _EVP_aead_aes_128_cbc_sha1_tls_implicit_iv -%xdefine EVP_aead_aes_128_cbc_sha256_tls BORINGSSL_PREFIX %+ _EVP_aead_aes_128_cbc_sha256_tls %xdefine EVP_aead_aes_128_ccm_bluetooth BORINGSSL_PREFIX %+ _EVP_aead_aes_128_ccm_bluetooth %xdefine EVP_aead_aes_128_ccm_bluetooth_8 BORINGSSL_PREFIX %+ _EVP_aead_aes_128_ccm_bluetooth_8 %xdefine EVP_aead_aes_128_ctr_hmac_sha256 BORINGSSL_PREFIX %+ _EVP_aead_aes_128_ctr_hmac_sha256 @@ -4468,8 +4478,6 @@ %xdefine EVP_aead_aes_192_gcm BORINGSSL_PREFIX %+ _EVP_aead_aes_192_gcm %xdefine EVP_aead_aes_256_cbc_sha1_tls BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha1_tls %xdefine EVP_aead_aes_256_cbc_sha1_tls_implicit_iv BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha1_tls_implicit_iv -%xdefine EVP_aead_aes_256_cbc_sha256_tls BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha256_tls -%xdefine EVP_aead_aes_256_cbc_sha384_tls BORINGSSL_PREFIX %+ _EVP_aead_aes_256_cbc_sha384_tls %xdefine EVP_aead_aes_256_ctr_hmac_sha256 BORINGSSL_PREFIX %+ _EVP_aead_aes_256_ctr_hmac_sha256 %xdefine EVP_aead_aes_256_gcm BORINGSSL_PREFIX %+ _EVP_aead_aes_256_gcm %xdefine EVP_aead_aes_256_gcm_randnonce BORINGSSL_PREFIX %+ _EVP_aead_aes_256_gcm_randnonce @@ -4525,6 +4533,7 @@ %xdefine EVP_rc2_cbc BORINGSSL_PREFIX %+ _EVP_rc2_cbc %xdefine EVP_rc4 BORINGSSL_PREFIX %+ _EVP_rc4 %xdefine EVP_sha1 BORINGSSL_PREFIX %+ _EVP_sha1 +%xdefine EVP_sha1_final_with_secret_suffix BORINGSSL_PREFIX %+ _EVP_sha1_final_with_secret_suffix %xdefine EVP_sha224 BORINGSSL_PREFIX %+ _EVP_sha224 %xdefine EVP_sha256 BORINGSSL_PREFIX %+ _EVP_sha256 %xdefine EVP_sha384 BORINGSSL_PREFIX %+ _EVP_sha384 @@ -4539,6 +4548,7 @@ %xdefine EXTENDED_KEY_USAGE_new BORINGSSL_PREFIX %+ _EXTENDED_KEY_USAGE_new %xdefine FIPS_mode BORINGSSL_PREFIX %+ _FIPS_mode %xdefine FIPS_mode_set BORINGSSL_PREFIX %+ _FIPS_mode_set +%xdefine FIPS_read_counter BORINGSSL_PREFIX %+ _FIPS_read_counter %xdefine GENERAL_NAMES_free BORINGSSL_PREFIX %+ _GENERAL_NAMES_free %xdefine GENERAL_NAMES_it BORINGSSL_PREFIX %+ _GENERAL_NAMES_it %xdefine GENERAL_NAMES_new BORINGSSL_PREFIX %+ _GENERAL_NAMES_new @@ -5051,6 +5061,7 @@ %xdefine SSL_CTX_set1_chain BORINGSSL_PREFIX %+ _SSL_CTX_set1_chain %xdefine SSL_CTX_set1_curves BORINGSSL_PREFIX %+ _SSL_CTX_set1_curves %xdefine SSL_CTX_set1_curves_list BORINGSSL_PREFIX %+ _SSL_CTX_set1_curves_list +%xdefine SSL_CTX_set1_ech_server_config_list BORINGSSL_PREFIX %+ _SSL_CTX_set1_ech_server_config_list %xdefine SSL_CTX_set1_param BORINGSSL_PREFIX %+ _SSL_CTX_set1_param %xdefine SSL_CTX_set1_sigalgs BORINGSSL_PREFIX %+ _SSL_CTX_set1_sigalgs %xdefine SSL_CTX_set1_sigalgs_list BORINGSSL_PREFIX %+ _SSL_CTX_set1_sigalgs_list @@ -5138,6 +5149,10 @@ %xdefine SSL_CTX_use_certificate_chain_file BORINGSSL_PREFIX %+ _SSL_CTX_use_certificate_chain_file %xdefine SSL_CTX_use_certificate_file BORINGSSL_PREFIX %+ _SSL_CTX_use_certificate_file %xdefine SSL_CTX_use_psk_identity_hint BORINGSSL_PREFIX %+ _SSL_CTX_use_psk_identity_hint +%xdefine SSL_ECH_SERVER_CONFIG_LIST_add BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_add +%xdefine SSL_ECH_SERVER_CONFIG_LIST_free BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_free +%xdefine SSL_ECH_SERVER_CONFIG_LIST_new BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_new +%xdefine SSL_ECH_SERVER_CONFIG_LIST_up_ref BORINGSSL_PREFIX %+ _SSL_ECH_SERVER_CONFIG_LIST_up_ref %xdefine SSL_SESSION_copy_without_early_data BORINGSSL_PREFIX %+ _SSL_SESSION_copy_without_early_data %xdefine SSL_SESSION_early_data_capable BORINGSSL_PREFIX %+ _SSL_SESSION_early_data_capable %xdefine SSL_SESSION_free BORINGSSL_PREFIX %+ _SSL_SESSION_free @@ -5322,9 +5337,12 @@ %xdefine SSL_read BORINGSSL_PREFIX %+ _SSL_read %xdefine SSL_renegotiate BORINGSSL_PREFIX %+ _SSL_renegotiate %xdefine SSL_renegotiate_pending BORINGSSL_PREFIX %+ _SSL_renegotiate_pending +%xdefine SSL_request_handshake_hints BORINGSSL_PREFIX %+ _SSL_request_handshake_hints %xdefine SSL_reset_early_data_reject BORINGSSL_PREFIX %+ _SSL_reset_early_data_reject %xdefine SSL_select_next_proto BORINGSSL_PREFIX %+ _SSL_select_next_proto %xdefine SSL_send_fatal_alert BORINGSSL_PREFIX %+ _SSL_send_fatal_alert +%xdefine SSL_serialize_capabilities BORINGSSL_PREFIX %+ _SSL_serialize_capabilities +%xdefine SSL_serialize_handshake_hints BORINGSSL_PREFIX %+ _SSL_serialize_handshake_hints %xdefine SSL_session_reused BORINGSSL_PREFIX %+ _SSL_session_reused %xdefine SSL_set0_chain BORINGSSL_PREFIX %+ _SSL_set0_chain %xdefine SSL_set0_client_CAs BORINGSSL_PREFIX %+ _SSL_set0_client_CAs @@ -5355,6 +5373,7 @@ %xdefine SSL_set_enforce_rsa_key_usage BORINGSSL_PREFIX %+ _SSL_set_enforce_rsa_key_usage %xdefine SSL_set_ex_data BORINGSSL_PREFIX %+ _SSL_set_ex_data %xdefine SSL_set_fd BORINGSSL_PREFIX %+ _SSL_set_fd +%xdefine SSL_set_handshake_hints BORINGSSL_PREFIX %+ _SSL_set_handshake_hints %xdefine SSL_set_info_callback BORINGSSL_PREFIX %+ _SSL_set_info_callback %xdefine SSL_set_jdk11_workaround BORINGSSL_PREFIX %+ _SSL_set_jdk11_workaround %xdefine SSL_set_max_cert_list BORINGSSL_PREFIX %+ _SSL_set_max_cert_list @@ -5522,7 +5541,6 @@ %xdefine X509_ALGOR_new BORINGSSL_PREFIX %+ _X509_ALGOR_new %xdefine X509_ALGOR_set0 BORINGSSL_PREFIX %+ _X509_ALGOR_set0 %xdefine X509_ALGOR_set_md BORINGSSL_PREFIX %+ _X509_ALGOR_set_md -%xdefine X509_ATTRIBUTE_SET_it BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_SET_it %xdefine X509_ATTRIBUTE_count BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_count %xdefine X509_ATTRIBUTE_create BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_create %xdefine X509_ATTRIBUTE_create_by_NID BORINGSSL_PREFIX %+ _X509_ATTRIBUTE_create_by_NID @@ -5674,6 +5692,7 @@ %xdefine X509_PUBKEY_free BORINGSSL_PREFIX %+ _X509_PUBKEY_free %xdefine X509_PUBKEY_get BORINGSSL_PREFIX %+ _X509_PUBKEY_get %xdefine X509_PUBKEY_get0_param BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_param +%xdefine X509_PUBKEY_get0_public_key BORINGSSL_PREFIX %+ _X509_PUBKEY_get0_public_key %xdefine X509_PUBKEY_it BORINGSSL_PREFIX %+ _X509_PUBKEY_it %xdefine X509_PUBKEY_new BORINGSSL_PREFIX %+ _X509_PUBKEY_new %xdefine X509_PUBKEY_set BORINGSSL_PREFIX %+ _X509_PUBKEY_set @@ -5710,7 +5729,6 @@ %xdefine X509_REQ_get_attr_by_NID BORINGSSL_PREFIX %+ _X509_REQ_get_attr_by_NID %xdefine X509_REQ_get_attr_by_OBJ BORINGSSL_PREFIX %+ _X509_REQ_get_attr_by_OBJ %xdefine X509_REQ_get_attr_count BORINGSSL_PREFIX %+ _X509_REQ_get_attr_count -%xdefine X509_REQ_get_extension_nids BORINGSSL_PREFIX %+ _X509_REQ_get_extension_nids %xdefine X509_REQ_get_extensions BORINGSSL_PREFIX %+ _X509_REQ_get_extensions %xdefine X509_REQ_get_pubkey BORINGSSL_PREFIX %+ _X509_REQ_get_pubkey %xdefine X509_REQ_get_signature_nid BORINGSSL_PREFIX %+ _X509_REQ_get_signature_nid @@ -5721,7 +5739,6 @@ %xdefine X509_REQ_print BORINGSSL_PREFIX %+ _X509_REQ_print %xdefine X509_REQ_print_ex BORINGSSL_PREFIX %+ _X509_REQ_print_ex %xdefine X509_REQ_print_fp BORINGSSL_PREFIX %+ _X509_REQ_print_fp -%xdefine X509_REQ_set_extension_nids BORINGSSL_PREFIX %+ _X509_REQ_set_extension_nids %xdefine X509_REQ_set_pubkey BORINGSSL_PREFIX %+ _X509_REQ_set_pubkey %xdefine X509_REQ_set_subject_name BORINGSSL_PREFIX %+ _X509_REQ_set_subject_name %xdefine X509_REQ_set_version BORINGSSL_PREFIX %+ _X509_REQ_set_version @@ -6071,6 +6088,7 @@ %xdefine asn1_refcount_dec_and_test_zero BORINGSSL_PREFIX %+ _asn1_refcount_dec_and_test_zero %xdefine asn1_refcount_set_one BORINGSSL_PREFIX %+ _asn1_refcount_set_one %xdefine asn1_set_choice_selector BORINGSSL_PREFIX %+ _asn1_set_choice_selector +%xdefine asn1_type_value_as_pointer BORINGSSL_PREFIX %+ _asn1_type_value_as_pointer %xdefine asn1_utctime_to_tm BORINGSSL_PREFIX %+ _asn1_utctime_to_tm %xdefine beeu_mod_inverse_vartime BORINGSSL_PREFIX %+ _beeu_mod_inverse_vartime %xdefine bio_clear_socket_error BORINGSSL_PREFIX %+ _bio_clear_socket_error diff --git a/Sources/CNIOBoringSSL/ssl/d1_both.cc b/Sources/CNIOBoringSSL/ssl/d1_both.cc index d3cbdc8a..68252e04 100644 --- a/Sources/CNIOBoringSSL/ssl/d1_both.cc +++ b/Sources/CNIOBoringSSL/ssl/d1_both.cc @@ -771,6 +771,11 @@ static int send_flight(SSL *ssl) { return -1; } + if (ssl->wbio == nullptr) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); + return -1; + } + dtls1_update_mtu(ssl); int ret = -1; diff --git a/Sources/CNIOBoringSSL/ssl/encrypted_client_hello.cc b/Sources/CNIOBoringSSL/ssl/encrypted_client_hello.cc new file mode 100644 index 00000000..1acd9e68 --- /dev/null +++ b/Sources/CNIOBoringSSL/ssl/encrypted_client_hello.cc @@ -0,0 +1,444 @@ +/* Copyright (c) 2021, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include +#include +#include + +#include "internal.h" + + +#if defined(OPENSSL_MSAN) +#define NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) +#else +#define NO_SANITIZE_MEMORY +#endif + +BSSL_NAMESPACE_BEGIN + +// ssl_client_hello_write_without_extensions serializes |client_hello| into +// |out|, omitting the length-prefixed extensions. It serializes individual +// fields, starting with |client_hello->version|, and ignores the +// |client_hello->client_hello| field. It returns true on success and false on +// failure. +static bool ssl_client_hello_write_without_extensions( + const SSL_CLIENT_HELLO *client_hello, CBB *out) { + CBB cbb; + if (!CBB_add_u16(out, client_hello->version) || + !CBB_add_bytes(out, client_hello->random, client_hello->random_len) || + !CBB_add_u8_length_prefixed(out, &cbb) || + !CBB_add_bytes(&cbb, client_hello->session_id, + client_hello->session_id_len) || + !CBB_add_u16_length_prefixed(out, &cbb) || + !CBB_add_bytes(&cbb, client_hello->cipher_suites, + client_hello->cipher_suites_len) || + !CBB_add_u8_length_prefixed(out, &cbb) || + !CBB_add_bytes(&cbb, client_hello->compression_methods, + client_hello->compression_methods_len) || + !CBB_flush(out)) { + return false; + } + return true; +} + +bool ssl_decode_client_hello_inner( + SSL *ssl, uint8_t *out_alert, Array *out_client_hello_inner, + Span encoded_client_hello_inner, + const SSL_CLIENT_HELLO *client_hello_outer) { + SSL_CLIENT_HELLO client_hello_inner; + if (!ssl_client_hello_init(ssl, &client_hello_inner, + encoded_client_hello_inner)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + // TLS 1.3 ClientHellos must have extensions, and EncodedClientHelloInners use + // ClientHelloOuter's session_id. + if (client_hello_inner.extensions_len == 0 || + client_hello_inner.session_id_len != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + client_hello_inner.session_id = client_hello_outer->session_id; + client_hello_inner.session_id_len = client_hello_outer->session_id_len; + + // Begin serializing a message containing the ClientHelloInner in |cbb|. + ScopedCBB cbb; + CBB body, extensions; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO) || + !ssl_client_hello_write_without_extensions(&client_hello_inner, &body) || + !CBB_add_u16_length_prefixed(&body, &extensions)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + + // Sort the extensions in ClientHelloOuter, so ech_outer_extensions may be + // processed in O(n*log(n)) time, rather than O(n^2). + struct Extension { + uint16_t extension = 0; + Span body; + bool copied = false; + }; + + // MSan's libc interceptors do not handle |bsearch|. See b/182583130. + auto compare_extension = [](const void *a, const void *b) + NO_SANITIZE_MEMORY -> int { + const Extension *extension_a = reinterpret_cast(a); + const Extension *extension_b = reinterpret_cast(b); + if (extension_a->extension < extension_b->extension) { + return -1; + } else if (extension_a->extension > extension_b->extension) { + return 1; + } + return 0; + }; + GrowableArray sorted_extensions; + CBS unsorted_extensions(MakeConstSpan(client_hello_outer->extensions, + client_hello_outer->extensions_len)); + while (CBS_len(&unsorted_extensions) > 0) { + Extension extension; + CBS extension_body; + if (!CBS_get_u16(&unsorted_extensions, &extension.extension) || + !CBS_get_u16_length_prefixed(&unsorted_extensions, &extension_body)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + extension.body = extension_body; + if (!sorted_extensions.Push(extension)) { + return false; + } + } + qsort(sorted_extensions.data(), sorted_extensions.size(), sizeof(Extension), + compare_extension); + + // Copy extensions from |client_hello_inner|, expanding ech_outer_extensions. + CBS inner_extensions(MakeConstSpan(client_hello_inner.extensions, + client_hello_inner.extensions_len)); + while (CBS_len(&inner_extensions) > 0) { + uint16_t extension_id; + CBS extension_body; + if (!CBS_get_u16(&inner_extensions, &extension_id) || + !CBS_get_u16_length_prefixed(&inner_extensions, &extension_body)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + if (extension_id != TLSEXT_TYPE_ech_outer_extensions) { + if (!CBB_add_u16(&extensions, extension_id) || + !CBB_add_u16(&extensions, CBS_len(&extension_body)) || + !CBB_add_bytes(&extensions, CBS_data(&extension_body), + CBS_len(&extension_body))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + continue; + } + + // Replace ech_outer_extensions with the corresponding outer extensions. + CBS outer_extensions; + if (!CBS_get_u8_length_prefixed(&extension_body, &outer_extensions) || + CBS_len(&extension_body) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + while (CBS_len(&outer_extensions) > 0) { + uint16_t extension_needed; + if (!CBS_get_u16(&outer_extensions, &extension_needed)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + if (extension_needed == TLSEXT_TYPE_encrypted_client_hello) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + // Find the referenced extension. + Extension key; + key.extension = extension_needed; + Extension *result = reinterpret_cast( + bsearch(&key, sorted_extensions.data(), sorted_extensions.size(), + sizeof(Extension), compare_extension)); + if (result == nullptr) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + + // Extensions may be referenced at most once, to bound the result size. + if (result->copied) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION); + return false; + } + result->copied = true; + + if (!CBB_add_u16(&extensions, extension_needed) || + !CBB_add_u16(&extensions, result->body.size()) || + !CBB_add_bytes(&extensions, result->body.data(), + result->body.size())) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return false; + } + } + } + if (!CBB_flush(&body)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + + // See https://github.com/tlswg/draft-ietf-tls-esni/pull/411 + CBS extension; + if (!ssl_client_hello_init(ssl, &client_hello_inner, + MakeConstSpan(CBB_data(&body), CBB_len(&body))) || + !ssl_client_hello_get_extension(&client_hello_inner, &extension, + TLSEXT_TYPE_ech_is_inner) || + CBS_len(&extension) != 0 || + ssl_client_hello_get_extension(&client_hello_inner, &extension, + TLSEXT_TYPE_encrypted_client_hello) || + !ssl_client_hello_get_extension(&client_hello_inner, &extension, + TLSEXT_TYPE_supported_versions)) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CLIENT_HELLO_INNER); + return false; + } + // Parse supported_versions and reject TLS versions prior to TLS 1.3. Older + // versions are incompatible with ECH. + CBS versions; + if (!CBS_get_u8_length_prefixed(&extension, &versions) || + CBS_len(&extension) != 0 || // + CBS_len(&versions) == 0) { + *out_alert = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + while (CBS_len(&versions) != 0) { + uint16_t version; + if (!CBS_get_u16(&versions, &version)) { + *out_alert = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + if (version == SSL3_VERSION || version == TLS1_VERSION || + version == TLS1_1_VERSION || version == TLS1_2_VERSION || + version == DTLS1_VERSION || version == DTLS1_2_VERSION) { + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_CLIENT_HELLO_INNER); + return false; + } + } + + if (!ssl->method->finish_message(ssl, cbb.get(), out_client_hello_inner)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + return true; +} + +bool ssl_client_hello_decrypt( + EVP_HPKE_CTX *hpke_ctx, Array *out_encoded_client_hello_inner, + bool *out_is_decrypt_error, const SSL_CLIENT_HELLO *client_hello_outer, + uint16_t kdf_id, uint16_t aead_id, Span config_id, + Span enc, Span payload) { + *out_is_decrypt_error = false; + + // Compute the ClientHello portion of the ClientHelloOuterAAD value. See + // draft-ietf-tls-esni-09, section 5.2. + ScopedCBB ch_outer_aad_cbb; + CBB config_id_cbb, enc_cbb, outer_hello_cbb, extensions_cbb; + if (!CBB_init(ch_outer_aad_cbb.get(), 0) || + !CBB_add_u16(ch_outer_aad_cbb.get(), kdf_id) || + !CBB_add_u16(ch_outer_aad_cbb.get(), aead_id) || + !CBB_add_u8_length_prefixed(ch_outer_aad_cbb.get(), &config_id_cbb) || + !CBB_add_bytes(&config_id_cbb, config_id.data(), config_id.size()) || + !CBB_add_u16_length_prefixed(ch_outer_aad_cbb.get(), &enc_cbb) || + !CBB_add_bytes(&enc_cbb, enc.data(), enc.size()) || + !CBB_add_u24_length_prefixed(ch_outer_aad_cbb.get(), &outer_hello_cbb) || + !ssl_client_hello_write_without_extensions(client_hello_outer, + &outer_hello_cbb) || + !CBB_add_u16_length_prefixed(&outer_hello_cbb, &extensions_cbb)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return false; + } + + CBS extensions(MakeConstSpan(client_hello_outer->extensions, + client_hello_outer->extensions_len)); + while (CBS_len(&extensions) > 0) { + uint16_t extension_id; + CBS extension_body; + if (!CBS_get_u16(&extensions, &extension_id) || + !CBS_get_u16_length_prefixed(&extensions, &extension_body)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + if (extension_id == TLSEXT_TYPE_encrypted_client_hello) { + continue; + } + if (!CBB_add_u16(&extensions_cbb, extension_id) || + !CBB_add_u16(&extensions_cbb, CBS_len(&extension_body)) || + !CBB_add_bytes(&extensions_cbb, CBS_data(&extension_body), + CBS_len(&extension_body))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return false; + } + } + if (!CBB_flush(ch_outer_aad_cbb.get())) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return false; + } + + // Attempt to decrypt into |out_encoded_client_hello_inner|. + if (!out_encoded_client_hello_inner->Init(payload.size())) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return false; + } + size_t encoded_client_hello_inner_len; + if (!EVP_HPKE_CTX_open(hpke_ctx, out_encoded_client_hello_inner->data(), + &encoded_client_hello_inner_len, + out_encoded_client_hello_inner->size(), payload.data(), + payload.size(), CBB_data(ch_outer_aad_cbb.get()), + CBB_len(ch_outer_aad_cbb.get()))) { + *out_is_decrypt_error = true; + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); + return false; + } + out_encoded_client_hello_inner->Shrink(encoded_client_hello_inner_len); + return true; +} + + +bool ECHServerConfig::Init(Span raw, + Span private_key, + bool is_retry_config) { + assert(!initialized_); + is_retry_config_ = is_retry_config; + + if (!raw_.CopyFrom(raw)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return false; + } + // Read from |raw_| so we can save Spans with the same lifetime as |this|. + CBS reader(raw_); + + uint16_t version; + if (!CBS_get_u16(&reader, &version)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + // Parse the ECHConfig, rejecting all unsupported parameters and extensions. + // Unlike most server options, ECH's server configuration is serialized and + // configured in both the server and DNS. If the caller configures an + // unsupported parameter, this is a deployment error. To catch these errors, + // we fail early. + if (version != TLSEXT_TYPE_encrypted_client_hello) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG); + return false; + } + + CBS ech_config_contents, public_name, public_key, cipher_suites, extensions; + uint16_t kem_id, max_name_len; + if (!CBS_get_u16_length_prefixed(&reader, &ech_config_contents) || + !CBS_get_u16_length_prefixed(&ech_config_contents, &public_name) || + CBS_len(&public_name) == 0 || + !CBS_get_u16_length_prefixed(&ech_config_contents, &public_key) || + CBS_len(&public_key) == 0 || + !CBS_get_u16(&ech_config_contents, &kem_id) || + !CBS_get_u16_length_prefixed(&ech_config_contents, &cipher_suites) || + CBS_len(&cipher_suites) == 0 || + !CBS_get_u16(&ech_config_contents, &max_name_len) || + !CBS_get_u16_length_prefixed(&ech_config_contents, &extensions) || + CBS_len(&ech_config_contents) != 0 || // + CBS_len(&reader) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + // We only support one KEM, and the KEM decides the length of |public_key|. + if (CBS_len(&public_key) != X25519_PUBLIC_VALUE_LEN || + kem_id != EVP_HPKE_DHKEM_X25519_HKDF_SHA256) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG); + return false; + } + public_key_ = public_key; + + // We do not support any ECHConfig extensions, so |extensions| must be empty. + if (CBS_len(&extensions) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ECH_SERVER_CONFIG_UNSUPPORTED_EXTENSION); + return false; + } + + cipher_suites_ = cipher_suites; + while (CBS_len(&cipher_suites) > 0) { + uint16_t kdf_id, aead_id; + if (!CBS_get_u16(&cipher_suites, &kdf_id) || + !CBS_get_u16(&cipher_suites, &aead_id)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + // This parser fails when it encounters any bytes it does not understand. If + // the config lists any unsupported cipher suites, that is a parse error. + if (kdf_id != EVP_HPKE_HKDF_SHA256 || + (aead_id != EVP_HPKE_AEAD_AES_128_GCM && + aead_id != EVP_HPKE_AEAD_AES_256_GCM && + aead_id != EVP_HPKE_AEAD_CHACHA20POLY1305)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ECH_SERVER_CONFIG); + return false; + } + } + + // Precompute the config_id. + uint8_t key[EVP_MAX_KEY_LENGTH]; + size_t key_len; + static const uint8_t kInfo[] = "tls ech config id"; + if (!HKDF_extract(key, &key_len, EVP_sha256(), raw_.data(), raw_.size(), + nullptr, 0) || + !HKDF_expand(config_id_sha256_, sizeof(config_id_sha256_), EVP_sha256(), + key, key_len, kInfo, OPENSSL_ARRAY_SIZE(kInfo) - 1)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + + if (private_key.size() != X25519_PRIVATE_KEY_LEN) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return false; + } + uint8_t expected_public_key[X25519_PUBLIC_VALUE_LEN]; + X25519_public_from_private(expected_public_key, private_key.data()); + if (public_key_ != expected_public_key) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ECH_SERVER_CONFIG_AND_PRIVATE_KEY_MISMATCH); + return false; + } + assert(sizeof(private_key_) == private_key.size()); + OPENSSL_memcpy(private_key_, private_key.data(), private_key.size()); + + initialized_ = true; + return true; +} + +bool ECHServerConfig::SupportsCipherSuite(uint16_t kdf_id, + uint16_t aead_id) const { + assert(initialized_); + CBS cbs(cipher_suites_); + while (CBS_len(&cbs) != 0) { + uint16_t supported_kdf_id, supported_aead_id; + if (!CBS_get_u16(&cbs, &supported_kdf_id) || + !CBS_get_u16(&cbs, &supported_aead_id)) { + return false; + } + if (kdf_id == supported_kdf_id && aead_id == supported_aead_id) { + return true; + } + } + return false; +} + +BSSL_NAMESPACE_END diff --git a/Sources/CNIOBoringSSL/ssl/handoff.cc b/Sources/CNIOBoringSSL/ssl/handoff.cc index 40f8f959..dfe4c486 100644 --- a/Sources/CNIOBoringSSL/ssl/handoff.cc +++ b/Sources/CNIOBoringSSL/ssl/handoff.cc @@ -15,6 +15,7 @@ #include #include +#include #include "internal.h" @@ -93,7 +94,7 @@ bool SSL_serialize_handoff(const SSL *ssl, CBB *out, !serialize_features(&seq) || !CBB_flush(out) || !ssl->method->get_message(ssl, &msg) || - !ssl_client_hello_init(ssl, out_hello, msg)) { + !ssl_client_hello_init(ssl, out_hello, msg.body)) { return false; } @@ -708,3 +709,245 @@ bool SSL_apply_handback(SSL *ssl, Span handback) { } BSSL_NAMESPACE_END + +using namespace bssl; + +int SSL_serialize_capabilities(const SSL *ssl, CBB *out) { + CBB seq; + if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || + !serialize_features(&seq) || // + !CBB_flush(out)) { + return 0; + } + + return 1; +} + +int SSL_request_handshake_hints(SSL *ssl, const uint8_t *client_hello, + size_t client_hello_len, + const uint8_t *capabilities, + size_t capabilities_len) { + if (SSL_is_dtls(ssl)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + CBS cbs, seq; + CBS_init(&cbs, capabilities, capabilities_len); + UniquePtr hints = MakeUnique(); + if (hints == nullptr || + !CBS_get_asn1(&cbs, &seq, CBS_ASN1_SEQUENCE) || + !apply_remote_features(ssl, &seq)) { + return 0; + } + + SSL3_STATE *const s3 = ssl->s3; + s3->v2_hello_done = true; + s3->has_message = true; + + Array client_hello_msg; + ScopedCBB client_hello_cbb; + CBB client_hello_body; + if (!ssl->method->init_message(ssl, client_hello_cbb.get(), + &client_hello_body, SSL3_MT_CLIENT_HELLO) || + !CBB_add_bytes(&client_hello_body, client_hello, client_hello_len) || + !ssl->method->finish_message(ssl, client_hello_cbb.get(), + &client_hello_msg)) { + return 0; + } + + s3->hs_buf.reset(BUF_MEM_new()); + if (!s3->hs_buf || !BUF_MEM_append(s3->hs_buf.get(), client_hello_msg.data(), + client_hello_msg.size())) { + return 0; + } + + s3->hs->hints_requested = true; + s3->hs->hints = std::move(hints); + return 1; +} + +// |SSL_HANDSHAKE_HINTS| is serialized as the following ASN.1 structure. We use +// implicit tagging to make it a little more compact. +// +// HandshakeHints ::= SEQUENCE { +// serverRandom [0] IMPLICIT OCTET STRING OPTIONAL, +// keyShareHint [1] IMPLICIT KeyShareHint OPTIONAL, +// signatureHint [2] IMPLICIT SignatureHint OPTIONAL, +// -- At most one of decryptedPSKHint or ignorePSKHint may be present. It +// -- corresponds to the first entry in pre_shared_keys. TLS 1.2 session +// -- tickets will use a separate hint, to ensure the caller does not mix +// -- them up. +// decryptedPSKHint [3] IMPLICIT OCTET STRING OPTIONAL, +// ignorePSKHint [4] IMPLICIT NULL OPTIONAL, +// } +// +// KeyShareHint ::= SEQUENCE { +// groupId INTEGER, +// publicKey OCTET STRING, +// secret OCTET STRING, +// } +// +// SignatureHint ::= SEQUENCE { +// algorithm INTEGER, +// input OCTET STRING, +// subjectPublicKeyInfo OCTET STRING, +// signature OCTET STRING, +// } + +// HandshakeHints tags. +static const unsigned kServerRandomTag = CBS_ASN1_CONTEXT_SPECIFIC | 0; +static const unsigned kKeyShareHintTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1; +static const unsigned kSignatureHintTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2; +static const unsigned kDecryptedPSKTag = CBS_ASN1_CONTEXT_SPECIFIC | 3; +static const unsigned kIgnorePSKTag = CBS_ASN1_CONTEXT_SPECIFIC | 4; + +int SSL_serialize_handshake_hints(const SSL *ssl, CBB *out) { + const SSL_HANDSHAKE *hs = ssl->s3->hs.get(); + if (!ssl->server || !hs->hints_requested) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + const SSL_HANDSHAKE_HINTS *hints = hs->hints.get(); + CBB seq, server_random, key_share_hint, signature_hint, decrypted_psk, + ignore_psk; + if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE)) { + return 0; + } + + if (!hints->server_random.empty()) { + if (!CBB_add_asn1(&seq, &server_random, kServerRandomTag) || + !CBB_add_bytes(&server_random, hints->server_random.data(), + hints->server_random.size())) { + return 0; + } + } + + if (hints->key_share_group_id != 0 && !hints->key_share_public_key.empty() && + !hints->key_share_secret.empty()) { + if (!CBB_add_asn1(&seq, &key_share_hint, kKeyShareHintTag) || + !CBB_add_asn1_uint64(&key_share_hint, hints->key_share_group_id) || + !CBB_add_asn1_octet_string(&key_share_hint, + hints->key_share_public_key.data(), + hints->key_share_public_key.size()) || + !CBB_add_asn1_octet_string(&key_share_hint, + hints->key_share_secret.data(), + hints->key_share_secret.size())) { + return 0; + } + } + + if (hints->signature_algorithm != 0 && !hints->signature_input.empty() && + !hints->signature.empty()) { + if (!CBB_add_asn1(&seq, &signature_hint, kSignatureHintTag) || + !CBB_add_asn1_uint64(&signature_hint, hints->signature_algorithm) || + !CBB_add_asn1_octet_string(&signature_hint, + hints->signature_input.data(), + hints->signature_input.size()) || + !CBB_add_asn1_octet_string(&signature_hint, + hints->signature_spki.data(), + hints->signature_spki.size()) || + !CBB_add_asn1_octet_string(&signature_hint, hints->signature.data(), + hints->signature.size())) { + return 0; + } + } + + if (!hints->decrypted_psk.empty()) { + if (!CBB_add_asn1(&seq, &decrypted_psk, kDecryptedPSKTag) || + !CBB_add_bytes(&decrypted_psk, hints->decrypted_psk.data(), + hints->decrypted_psk.size())) { + return 0; + } + } + + if (hints->ignore_psk && // + !CBB_add_asn1(&seq, &ignore_psk, kIgnorePSKTag)) { + return 0; + } + + return CBB_flush(out); +} + +int SSL_set_handshake_hints(SSL *ssl, const uint8_t *hints, size_t hints_len) { + if (SSL_is_dtls(ssl)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + UniquePtr hints_obj = MakeUnique(); + if (hints_obj == nullptr) { + return 0; + } + + CBS cbs, seq, server_random, key_share, signature_hint, ticket, ignore_psk; + int has_server_random, has_key_share, has_signature_hint, has_ticket, + has_ignore_psk; + CBS_init(&cbs, hints, hints_len); + if (!CBS_get_asn1(&cbs, &seq, CBS_ASN1_SEQUENCE) || + !CBS_get_optional_asn1(&seq, &server_random, &has_server_random, + kServerRandomTag) || + !CBS_get_optional_asn1(&seq, &key_share, &has_key_share, + kKeyShareHintTag) || + !CBS_get_optional_asn1(&seq, &signature_hint, &has_signature_hint, + kSignatureHintTag) || + !CBS_get_optional_asn1(&seq, &ticket, &has_ticket, kDecryptedPSKTag) || + !CBS_get_optional_asn1(&seq, &ignore_psk, &has_ignore_psk, + kIgnorePSKTag)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); + return 0; + } + + if (has_server_random && !hints_obj->server_random.CopyFrom(server_random)) { + return 0; + } + + if (has_key_share) { + uint64_t group_id; + CBS public_key, secret; + if (!CBS_get_asn1_uint64(&key_share, &group_id) || // + group_id == 0 || group_id > 0xffff || + !CBS_get_asn1(&key_share, &public_key, CBS_ASN1_OCTETSTRING) || + !hints_obj->key_share_public_key.CopyFrom(public_key) || + !CBS_get_asn1(&key_share, &secret, CBS_ASN1_OCTETSTRING) || + !hints_obj->key_share_secret.CopyFrom(secret)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); + return 0; + } + hints_obj->key_share_group_id = static_cast(group_id); + } + + if (has_signature_hint) { + uint64_t sig_alg; + CBS input, spki, signature; + if (!CBS_get_asn1_uint64(&signature_hint, &sig_alg) || // + sig_alg == 0 || sig_alg > 0xffff || + !CBS_get_asn1(&signature_hint, &input, CBS_ASN1_OCTETSTRING) || + !hints_obj->signature_input.CopyFrom(input) || + !CBS_get_asn1(&signature_hint, &spki, CBS_ASN1_OCTETSTRING) || + !hints_obj->signature_spki.CopyFrom(spki) || + !CBS_get_asn1(&signature_hint, &signature, CBS_ASN1_OCTETSTRING) || + !hints_obj->signature.CopyFrom(signature)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_COULD_NOT_PARSE_HINTS); + return 0; + } + hints_obj->signature_algorithm = static_cast(sig_alg); + } + + if (has_ticket && !hints_obj->decrypted_psk.CopyFrom(ticket)) { + return 0; + } + + if (has_ignore_psk) { + if (CBS_len(&ignore_psk) != 0) { + return 0; + } + hints_obj->ignore_psk = true; + } + + ssl->s3->hs->hints = std::move(hints_obj); + return 1; +} diff --git a/Sources/CNIOBoringSSL/ssl/handshake.cc b/Sources/CNIOBoringSSL/ssl/handshake.cc index 80bc1d40..04102715 100644 --- a/Sources/CNIOBoringSSL/ssl/handshake.cc +++ b/Sources/CNIOBoringSSL/ssl/handshake.cc @@ -126,6 +126,7 @@ BSSL_NAMESPACE_BEGIN SSL_HANDSHAKE::SSL_HANDSHAKE(SSL *ssl_arg) : ssl(ssl_arg), + ech_accept(false), ech_present(false), ech_is_inner_present(false), scts_requested(false), @@ -148,6 +149,7 @@ SSL_HANDSHAKE::SSL_HANDSHAKE(SSL *ssl_arg) pending_private_key_op(false), grease_seeded(false), handback(false), + hints_requested(false), cert_compression_negotiated(false), apply_jdk11_workaround(false) { assert(ssl); @@ -164,6 +166,28 @@ void SSL_HANDSHAKE::ResizeSecrets(size_t hash_len) { hash_len_ = hash_len; } +bool SSL_HANDSHAKE::GetClientHello(SSLMessage *out_msg, + SSL_CLIENT_HELLO *out_client_hello) { + if (!ech_client_hello_buf.empty()) { + // If the backing buffer is non-empty, the ClientHelloInner has been set. + out_msg->is_v2_hello = false; + out_msg->type = SSL3_MT_CLIENT_HELLO; + out_msg->raw = CBS(ech_client_hello_buf); + out_msg->body = MakeConstSpan(ech_client_hello_buf).subspan(4); + } else if (!ssl->method->get_message(ssl, out_msg)) { + // The message has already been read, so this cannot fail. + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return false; + } + + if (!ssl_client_hello_init(ssl, out_client_hello, out_msg->body)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return false; + } + return true; +} + UniquePtr ssl_handshake_new(SSL *ssl) { UniquePtr hs = MakeUnique(ssl); if (!hs || !hs->transcript.Init()) { @@ -552,7 +576,11 @@ const SSL_SESSION *ssl_handshake_session(const SSL_HANDSHAKE *hs) { int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { SSL *const ssl = hs->ssl; for (;;) { - // Resolve the operation the handshake was waiting on. + // Resolve the operation the handshake was waiting on. Each condition may + // halt the handshake by returning, or continue executing if the handshake + // may immediately proceed. Cases which halt the handshake can clear + // |hs->wait| to re-enter the state machine on the next iteration, or leave + // it set to keep the condition sticky. switch (hs->wait) { case ssl_hs_error: ERR_restore_state(hs->error.get()); @@ -570,13 +598,13 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { case ssl_hs_read_message: case ssl_hs_read_change_cipher_spec: { if (ssl->quic_method) { + // QUIC has no ChangeCipherSpec messages. + assert(hs->wait != ssl_hs_read_change_cipher_spec); + // The caller should call |SSL_provide_quic_data|. Clear |hs->wait| so + // the handshake can check if there is sufficient data next iteration. + ssl->s3->rwstate = SSL_ERROR_WANT_READ; hs->wait = ssl_hs_ok; - // The change cipher spec is omitted in QUIC. - if (hs->wait != ssl_hs_read_change_cipher_spec) { - ssl->s3->rwstate = SSL_ERROR_WANT_READ; - return -1; - } - break; + return -1; } uint8_t alert = SSL_AD_DECODE_ERROR; @@ -646,31 +674,30 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { return -1; } + // The following cases are associated with callback APIs which expect to + // be called each time the state machine runs. Thus they set |hs->wait| + // to |ssl_hs_ok| so that, next time, we re-enter the state machine and + // call the callback again. case ssl_hs_x509_lookup: ssl->s3->rwstate = SSL_ERROR_WANT_X509_LOOKUP; hs->wait = ssl_hs_ok; return -1; - case ssl_hs_channel_id_lookup: ssl->s3->rwstate = SSL_ERROR_WANT_CHANNEL_ID_LOOKUP; hs->wait = ssl_hs_ok; return -1; - case ssl_hs_private_key_operation: ssl->s3->rwstate = SSL_ERROR_WANT_PRIVATE_KEY_OPERATION; hs->wait = ssl_hs_ok; return -1; - case ssl_hs_pending_session: ssl->s3->rwstate = SSL_ERROR_PENDING_SESSION; hs->wait = ssl_hs_ok; return -1; - case ssl_hs_pending_ticket: ssl->s3->rwstate = SSL_ERROR_PENDING_TICKET; hs->wait = ssl_hs_ok; return -1; - case ssl_hs_certificate_verify: ssl->s3->rwstate = SSL_ERROR_WANT_CERTIFICATE_VERIFY; hs->wait = ssl_hs_ok; @@ -687,6 +714,10 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { hs->wait = ssl_hs_ok; return 1; + case ssl_hs_hints_ready: + ssl->s3->rwstate = SSL_ERROR_HANDSHAKE_HINTS_READY; + return -1; + case ssl_hs_ok: break; } diff --git a/Sources/CNIOBoringSSL/ssl/handshake_server.cc b/Sources/CNIOBoringSSL/ssl/handshake_server.cc index 75391192..3db565e9 100644 --- a/Sources/CNIOBoringSSL/ssl/handshake_server.cc +++ b/Sources/CNIOBoringSSL/ssl/handshake_server.cc @@ -154,6 +154,8 @@ #include #include #include +#include +#include #include #include #include @@ -167,6 +169,7 @@ #include "internal.h" #include "../crypto/internal.h" +#include "../crypto/hpke/internal.h" BSSL_NAMESPACE_BEGIN @@ -563,7 +566,7 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) { } SSL_CLIENT_HELLO client_hello; - if (!ssl_client_hello_init(ssl, &client_hello, msg)) { + if (!ssl_client_hello_init(ssl, &client_hello, msg.body)) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; @@ -581,12 +584,137 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) { return ssl_hs_handoff; } + // If the ClientHello contains an encrypted_client_hello extension (and no + // ech_is_inner extension), act as a client-facing server and attempt to + // decrypt the ClientHelloInner. + CBS ech_body; + if (ssl_client_hello_get_extension(&client_hello, &ech_body, + TLSEXT_TYPE_encrypted_client_hello)) { + CBS unused; + if (ssl_client_hello_get_extension(&client_hello, &unused, + TLSEXT_TYPE_ech_is_inner)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return ssl_hs_error; + } + + // Parse a ClientECH out of the extension body. + uint16_t kdf_id, aead_id; + CBS config_id, enc, payload; + if (!CBS_get_u16(&ech_body, &kdf_id) || // + !CBS_get_u16(&ech_body, &aead_id) || + !CBS_get_u8_length_prefixed(&ech_body, &config_id) || + !CBS_get_u16_length_prefixed(&ech_body, &enc) || + !CBS_get_u16_length_prefixed(&ech_body, &payload) || + CBS_len(&ech_body) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return ssl_hs_error; + } + + { + MutexReadLock lock(&ssl->ctx->lock); + hs->ech_server_config_list = UpRef(ssl->ctx->ech_server_config_list); + } + + if (hs->ech_server_config_list) { + for (const ECHServerConfig &ech_config : + hs->ech_server_config_list->configs) { + // Skip this config if the client-provided config_id does not match or + // if the client indicated an unsupported HPKE ciphersuite. + if (config_id != ech_config.config_id_sha256() || + !ech_config.SupportsCipherSuite(kdf_id, aead_id)) { + continue; + } + + static const uint8_t kInfoLabel[] = "tls ech"; + ScopedCBB info_cbb; + if (!CBB_init(info_cbb.get(), + sizeof(kInfoLabel) + ech_config.raw().size()) || + !CBB_add_bytes(info_cbb.get(), kInfoLabel, + sizeof(kInfoLabel) /* includes trailing NUL */) || + !CBB_add_bytes(info_cbb.get(), ech_config.raw().data(), + ech_config.raw().size())) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return ssl_hs_error; + } + + // Set up a fresh HPKE context for each decryption attempt. + hs->ech_hpke_ctx.Reset(); + + if (CBS_len(&enc) != X25519_PUBLIC_VALUE_LEN || + !EVP_HPKE_CTX_setup_base_r_x25519( + hs->ech_hpke_ctx.get(), kdf_id, aead_id, CBS_data(&enc), + CBS_len(&enc), ech_config.public_key().data(), + ech_config.public_key().size(), ech_config.private_key().data(), + ech_config.private_key().size(), CBB_data(info_cbb.get()), + CBB_len(info_cbb.get()))) { + // Ignore the error and try another ECHConfig. + ERR_clear_error(); + continue; + } + Array encoded_client_hello_inner; + bool is_decrypt_error; + if (!ssl_client_hello_decrypt(hs->ech_hpke_ctx.get(), + &encoded_client_hello_inner, + &is_decrypt_error, &client_hello, kdf_id, + aead_id, config_id, enc, payload)) { + if (is_decrypt_error) { + // Ignore the error and try another ECHConfig. + ERR_clear_error(); + continue; + } + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); + return ssl_hs_error; + } + + // Recover the ClientHelloInner from the EncodedClientHelloInner. + uint8_t alert = SSL_AD_DECODE_ERROR; + bssl::Array client_hello_inner; + if (!ssl_decode_client_hello_inner(ssl, &alert, &client_hello_inner, + encoded_client_hello_inner, + &client_hello)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return ssl_hs_error; + } + hs->ech_client_hello_buf = std::move(client_hello_inner); + + // Load the ClientHelloInner into |client_hello|. + if (!hs->GetClientHello(&msg, &client_hello)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return ssl_hs_error; + } + + hs->ech_accept = true; + break; + } + } + + // If we did not set |hs->ech_accept| to true, we will send the current + // ECHConfigs as retry_configs in the ServerHello's encrypted extensions. + // Proceed with the ClientHelloOuter. + } + uint8_t alert = SSL_AD_DECODE_ERROR; if (!extract_sni(hs, &alert, &client_hello)) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; } + hs->state = state12_read_client_hello_after_ech; + return ssl_hs_ok; +} + +static enum ssl_hs_wait_t do_read_client_hello_after_ech(SSL_HANDSHAKE *hs) { + SSL *const ssl = hs->ssl; + + SSLMessage msg_unused; + SSL_CLIENT_HELLO client_hello; + if (!hs->GetClientHello(&msg_unused, &client_hello)) { + return ssl_hs_error; + } + // Run the early callback. if (ssl->ctx->select_certificate_cb != NULL) { switch (ssl->ctx->select_certificate_cb(&client_hello)) { @@ -614,6 +742,7 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) { hs->apply_jdk11_workaround = true; } + uint8_t alert = SSL_AD_DECODE_ERROR; if (!negotiate_version(hs, &alert, &client_hello)) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; @@ -657,11 +786,6 @@ static enum ssl_hs_wait_t do_read_client_hello(SSL_HANDSHAKE *hs) { static enum ssl_hs_wait_t do_select_certificate(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - SSLMessage msg; - if (!ssl->method->get_message(ssl, &msg)) { - return ssl_hs_read_message; - } - // Call |cert_cb| to update server certificates if required. if (hs->config->cert->cert_cb != NULL) { int rv = hs->config->cert->cert_cb(ssl, hs->config->cert->cert_cb_arg); @@ -701,10 +825,22 @@ static enum ssl_hs_wait_t do_select_certificate(SSL_HANDSHAKE *hs) { return ssl_hs_ok; } + // It should not be possible to negotiate TLS 1.2 with ECH. The + // ClientHelloInner decoding function rejects ClientHellos which offer TLS 1.2 + // or below. + assert(!hs->ech_accept); + + // TODO(davidben): Also compute hints for TLS 1.2. When doing so, update the + // check in bssl_shim.cc to test this. + if (hs->hints_requested) { + return ssl_hs_hints_ready; + } + ssl->s3->early_data_reason = ssl_early_data_protocol_version; + SSLMessage msg_unused; SSL_CLIENT_HELLO client_hello; - if (!ssl_client_hello_init(ssl, &client_hello, msg)) { + if (!hs->GetClientHello(&msg_unused, &client_hello)) { return ssl_hs_error; } @@ -743,7 +879,7 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { } SSL_CLIENT_HELLO client_hello; - if (!ssl_client_hello_init(ssl, &client_hello, msg)) { + if (!ssl_client_hello_init(ssl, &client_hello, msg.body)) { return ssl_hs_error; } @@ -1693,6 +1829,9 @@ enum ssl_hs_wait_t ssl_server_handshake(SSL_HANDSHAKE *hs) { case state12_read_client_hello: ret = do_read_client_hello(hs); break; + case state12_read_client_hello_after_ech: + ret = do_read_client_hello_after_ech(hs); + break; case state12_select_certificate: ret = do_select_certificate(hs); break; @@ -1773,6 +1912,8 @@ const char *ssl_server_handshake_state(SSL_HANDSHAKE *hs) { return "TLS server start_accept"; case state12_read_client_hello: return "TLS server read_client_hello"; + case state12_read_client_hello_after_ech: + return "TLS server read_client_hello_after_ech"; case state12_select_certificate: return "TLS server select_certificate"; case state12_tls13: diff --git a/Sources/CNIOBoringSSL/ssl/internal.h b/Sources/CNIOBoringSSL/ssl/internal.h index 6b095d14..e84bf4d9 100644 --- a/Sources/CNIOBoringSSL/ssl/internal.h +++ b/Sources/CNIOBoringSSL/ssl/internal.h @@ -152,6 +152,7 @@ #include #include +#include #include #include #include @@ -161,6 +162,7 @@ #include "../crypto/err/internal.h" #include "../crypto/internal.h" +#include "../crypto/hpke/internal.h" #if defined(OPENSSL_WINDOWS) @@ -378,6 +380,8 @@ class GrowableArray { return *this; } + const T *data() const { return array_.data(); } + T *data() { return array_.data(); } size_t size() const { return size_; } bool empty() const { return size_ == 0; } @@ -1066,6 +1070,10 @@ class SSLKeyShare { // |Serialize|. static UniquePtr Create(CBS *in); + // Serializes writes the group ID and private key, in a format that can be + // read by |Create|. + bool Serialize(CBB *out); + // GroupID returns the group ID. virtual uint16_t GroupID() const PURE_VIRTUAL; @@ -1090,13 +1098,13 @@ class SSLKeyShare { virtual bool Finish(Array *out_secret, uint8_t *out_alert, Span peer_key) PURE_VIRTUAL; - // Serialize writes the state of the key exchange to |out|, returning true if - // successful and false otherwise. - virtual bool Serialize(CBB *out) { return false; } + // SerializePrivateKey writes the private key to |out|, returning true if + // successful and false otherwise. It should be called after |Offer|. + virtual bool SerializePrivateKey(CBB *out) { return false; } - // Deserialize initializes the state of the key exchange from |in|, returning - // true if successful and false otherwise. It is called by |Create|. - virtual bool Deserialize(CBS *in) { return false; } + // DeserializePrivateKey initializes the state of the key exchange from |in|, + // returning true if successful and false otherwise. + virtual bool DeserializePrivateKey(CBS *in) { return false; } }; struct NamedGroup { @@ -1419,7 +1427,88 @@ bool tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session, const SSLMessage &msg, CBS *binders); -// Encrypted Client Hello. +// Encrypted ClientHello. + +class ECHServerConfig { + public: + ECHServerConfig() : is_retry_config_(false), initialized_(false) {} + ECHServerConfig(ECHServerConfig &&other) = default; + ~ECHServerConfig() = default; + ECHServerConfig &operator=(ECHServerConfig &&) = default; + + // Init parses |ech_config| as an ECHConfig and saves a copy of |private_key|. + // It returns true on success and false on error. It will also error if + // |private_key| is not a valid X25519 private key or it does not correspond + // to the parsed public key. + bool Init(Span ech_config, Span private_key, + bool is_retry_config); + + // SupportsCipherSuite returns true when this ECHConfig supports the HPKE + // ciphersuite composed of |kdf_id| and |aead_id|. This function must only be + // called on an initialized object. + bool SupportsCipherSuite(uint16_t kdf_id, uint16_t aead_id) const; + + Span raw() const { + assert(initialized_); + return raw_; + } + Span public_key() const { + assert(initialized_); + return public_key_; + } + Span private_key() const { + assert(initialized_); + return MakeConstSpan(private_key_, sizeof(private_key_)); + } + Span config_id_sha256() const { + assert(initialized_); + return MakeConstSpan(config_id_sha256_, sizeof(config_id_sha256_)); + } + bool is_retry_config() const { + assert(initialized_); + return is_retry_config_; + } + + private: + Array raw_; + Span public_key_; + Span cipher_suites_; + + // private_key_ is the key corresponding to |public_key|. For clients, it must + // be empty (|private_key_present_ == false|). For servers, it must be a valid + // X25519 private key. + uint8_t private_key_[X25519_PRIVATE_KEY_LEN]; + + // config_id_ stores the precomputed result of |ConfigID| for + // |EVP_HPKE_HKDF_SHA256|. + uint8_t config_id_sha256_[8]; + + bool is_retry_config_ : 1; + bool initialized_ : 1; +}; + +// ssl_decode_client_hello_inner recovers the full ClientHelloInner from the +// EncodedClientHelloInner |encoded_client_hello_inner| by replacing its +// outer_extensions extension with the referenced extensions from the +// ClientHelloOuter |client_hello_outer|. If successful, it writes the recovered +// ClientHelloInner to |out_client_hello_inner|. It returns true on success and +// false on failure. +OPENSSL_EXPORT bool ssl_decode_client_hello_inner( + SSL *ssl, uint8_t *out_alert, Array *out_client_hello_inner, + Span encoded_client_hello_inner, + const SSL_CLIENT_HELLO *client_hello_outer); + +// ssl_client_hello_decrypt attempts to decrypt the given |payload| into +// |out_encoded_client_hello_inner|. The decrypted value should be an +// EncodedClientHelloInner. It returns false if any fatal errors occur and true +// otherwise, regardless of whether the decrypt was successful. It sets +// |out_encoded_client_hello_inner| to true if the decryption fails, and false +// otherwise. +bool ssl_client_hello_decrypt( + EVP_HPKE_CTX *hpke_ctx, Array *out_encoded_client_hello_inner, + bool *out_is_decrypt_error, const SSL_CLIENT_HELLO *client_hello_outer, + uint16_t kdf_id, uint16_t aead_id, Span config_id, + Span enc, Span payload); // tls13_ech_accept_confirmation computes the server's ECH acceptance signal, // writing it to |out|. It returns true on success, and false on failure. @@ -1428,6 +1517,45 @@ bool tls13_ech_accept_confirmation( bssl::Span server_hello_ech_conf); +// Delegated credentials. + +// This structure stores a delegated credential (DC) as defined by +// draft-ietf-tls-subcerts-03. +struct DC { + static constexpr bool kAllowUniquePtr = true; + ~DC(); + + // Dup returns a copy of this DC and takes references to |raw| and |pkey|. + UniquePtr Dup(); + + // Parse parses the delegated credential stored in |in|. If successful it + // returns the parsed structure, otherwise it returns |nullptr| and sets + // |*out_alert|. + static UniquePtr Parse(CRYPTO_BUFFER *in, uint8_t *out_alert); + + // raw is the delegated credential encoded as specified in draft-ietf-tls- + // subcerts-03. + UniquePtr raw; + + // expected_cert_verify_algorithm is the signature scheme of the DC public + // key. + uint16_t expected_cert_verify_algorithm = 0; + + // pkey is the public key parsed from |public_key|. + UniquePtr pkey; + + private: + friend DC* New(); + DC(); +}; + +// ssl_signing_with_dc returns true if the peer has indicated support for +// delegated credentials and this host has sent a delegated credential in +// response. If this is true then we've committed to using the DC in the +// handshake. +bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs); + + // Handshake functions. enum ssl_hs_wait_t { @@ -1449,6 +1577,7 @@ enum ssl_hs_wait_t { ssl_hs_read_end_of_early_data, ssl_hs_read_change_cipher_spec, ssl_hs_certificate_verify, + ssl_hs_hints_ready, }; enum ssl_grease_index_t { @@ -1464,6 +1593,7 @@ enum ssl_grease_index_t { enum tls12_server_hs_state_t { state12_start_accept = 0, state12_read_client_hello, + state12_read_client_hello_after_ech, state12_select_certificate, state12_tls13, state12_select_parameters, @@ -1515,46 +1645,26 @@ enum handback_t { handback_max_value = handback_tls13, }; - -// Delegated credentials. - -// This structure stores a delegated credential (DC) as defined by -// draft-ietf-tls-subcerts-03. -struct DC { +// SSL_HANDSHAKE_HINTS contains handshake hints for a connection. See +// |SSL_request_handshake_hints| and related functions. +struct SSL_HANDSHAKE_HINTS { static constexpr bool kAllowUniquePtr = true; - ~DC(); - // Dup returns a copy of this DC and takes references to |raw| and |pkey|. - UniquePtr Dup(); + Array server_random; - // Parse parses the delegated credential stored in |in|. If successful it - // returns the parsed structure, otherwise it returns |nullptr| and sets - // |*out_alert|. - static UniquePtr Parse(CRYPTO_BUFFER *in, uint8_t *out_alert); + uint16_t key_share_group_id = 0; + Array key_share_public_key; + Array key_share_secret; - // raw is the delegated credential encoded as specified in draft-ietf-tls- - // subcerts-03. - UniquePtr raw; + uint16_t signature_algorithm = 0; + Array signature_input; + Array signature_spki; + Array signature; - // expected_cert_verify_algorithm is the signature scheme of the DC public - // key. - uint16_t expected_cert_verify_algorithm = 0; - - // pkey is the public key parsed from |public_key|. - UniquePtr pkey; - - private: - friend DC* New(); - DC(); + Array decrypted_psk; + bool ignore_psk = false; }; -// ssl_signing_with_dc returns true if the peer has indicated support for -// delegated credentials and this host has sent a delegated credential in -// response. If this is true then we've committed to using the DC in the -// handshake. -bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs); - - struct SSL_HANDSHAKE { explicit SSL_HANDSHAKE(SSL *ssl); ~SSL_HANDSHAKE(); @@ -1599,6 +1709,17 @@ struct SSL_HANDSHAKE { public: void ResizeSecrets(size_t hash_len); + // GetClientHello, on the server, returns either the normal ClientHello + // message or the ClientHelloInner if it has been serialized to + // |ech_client_hello_buf|. This function should only be called when the + // current message is a ClientHello. It returns true on success and false on + // error. + // + // Note that fields of the returned |out_msg| and |out_client_hello| point + // into a handshake-owned buffer, so their lifetimes should not exceed this + // SSL_HANDSHAKE. + bool GetClientHello(SSLMessage *out_msg, SSL_CLIENT_HELLO *out_client_hello); + Span secret() { return MakeSpan(secret_, hash_len_); } Span early_traffic_secret() { return MakeSpan(early_traffic_secret_, hash_len_); @@ -1651,6 +1772,10 @@ struct SSL_HANDSHAKE { // the first ClientHello. Array ech_grease; + // ech_client_hello_buf, on the server, contains the bytes of the + // reconstructed ClientHelloInner message. + Array ech_client_hello_buf; + // key_share_bytes is the value of the previously sent KeyShare extension by // the client in TLS 1.3. Array key_share_bytes; @@ -1687,6 +1812,10 @@ struct SSL_HANDSHAKE { // |cert_compression_negotiated| is true. uint16_t cert_compression_alg_id; + // ech_hpke_ctx, on the server, is the HPKE context used to decrypt the + // client's ECH payloads. + ScopedEVP_HPKE_CTX ech_hpke_ctx; + // server_params, in a TLS 1.2 server, stores the ServerKeyExchange // parameters. It has client and server randoms prepended for signing // convenience. @@ -1723,12 +1852,28 @@ struct SSL_HANDSHAKE { // the client if |in_early_data| is true. UniquePtr early_session; + // ech_server_config_list, for servers, is the list of ECHConfig values that + // were valid when the server received the first ClientHello. Its value will + // not change when the config list on |SSL_CTX| is updated. + UniquePtr ech_server_config_list; + // new_cipher is the cipher being negotiated in this handshake. const SSL_CIPHER *new_cipher = nullptr; // key_block is the record-layer key block for TLS 1.2 and earlier. Array key_block; + // hints contains the handshake hints for this connection. If + // |hints_requested| is true, this field is non-null and contains the pending + // hints to filled as the predicted handshake progresses. Otherwise, this + // field, if non-null, contains hints configured by the caller and will + // influence the handshake on match. + UniquePtr hints; + + // ech_accept, on the server, indicates whether the server should overwrite + // part of ServerHello.random with the ECH accept_confirmation value. + bool ech_accept : 1; + // ech_present, on the server, indicates whether the ClientHello contained an // encrypted_client_hello extension. bool ech_present : 1; @@ -1814,6 +1959,11 @@ struct SSL_HANDSHAKE { // |SSL_apply_handoff|. bool handback : 1; + // hints_requested indicates the caller has requested handshake hints. Only + // the first round-trip of the handshake will complete, after which the + // |hints| structure can be serialized. + bool hints_requested : 1; + // cert_compression_negotiated is true iff |cert_compression_alg_id| is valid. bool cert_compression_negotiated : 1; @@ -1901,10 +2051,10 @@ bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, Array *out_secret, uint8_t *out_alert, CBS *contents); bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found, - Array *out_secret, - uint8_t *out_alert, CBS *contents); -bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out, - bool dry_run); + Span *out_peer_key, + uint8_t *out_alert, + const SSL_CLIENT_HELLO *client_hello); +bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out); bool ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, @@ -1935,6 +2085,9 @@ bool tls13_get_cert_verify_signature_input( SSL_HANDSHAKE *hs, Array *out, enum ssl_cert_verify_context_t cert_verify_context); +// ssl_is_valid_alpn_list returns whether |in| is a valid ALPN protocol list. +bool ssl_is_valid_alpn_list(Span in); + // ssl_is_alpn_protocol_allowed returns whether |protocol| is a valid server // selection for |hs->ssl|'s client preferences. bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs, @@ -1993,8 +2146,11 @@ bool ssl_log_secret(const SSL *ssl, const char *label, // ClientHello functions. -bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out, - const SSLMessage &msg); +// ssl_client_hello_init parses |body| as a ClientHello message, excluding the +// message header, and writes the result to |*out|. It returns true on success +// and false on error. This function is exported for testing. +OPENSSL_EXPORT bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out, + Span body); bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello, CBS *out, uint16_t extension_type); @@ -3318,6 +3474,11 @@ struct ssl_ctx_st { // The client's Channel ID private key. bssl::UniquePtr channel_id_private; + // ech_server_config_list contains the server's list of ECHConfig values and + // associated private keys. This list may be swapped out at any time, so all + // access must be synchronized through |lock|. + bssl::UniquePtr ech_server_config_list; + // keylog_callback, if not NULL, is the key logging callback. See // |SSL_CTX_set_keylog_callback|. void (*keylog_callback)(const SSL *ssl, const char *line) = nullptr; @@ -3631,5 +3792,18 @@ struct ssl_session_st { friend void SSL_SESSION_free(SSL_SESSION *); }; +struct ssl_ech_server_config_list_st { + ssl_ech_server_config_list_st() = default; + ssl_ech_server_config_list_st(const ssl_ech_server_config_list_st &) = delete; + ssl_ech_server_config_list_st &operator=( + const ssl_ech_server_config_list_st &) = delete; + + bssl::GrowableArray configs; + CRYPTO_refcount_t references = 1; + + private: + ~ssl_ech_server_config_list_st() = default; + friend void SSL_ECH_SERVER_CONFIG_LIST_free(SSL_ECH_SERVER_CONFIG_LIST *); +}; #endif // OPENSSL_HEADER_SSL_INTERNAL_H diff --git a/Sources/CNIOBoringSSL/ssl/s3_both.cc b/Sources/CNIOBoringSSL/ssl/s3_both.cc index bf7a7fc1..673da666 100644 --- a/Sources/CNIOBoringSSL/ssl/s3_both.cc +++ b/Sources/CNIOBoringSSL/ssl/s3_both.cc @@ -251,7 +251,8 @@ bool tls_flush_pending_hs_data(SSL *ssl) { MakeConstSpan(reinterpret_cast(pending_hs_data->data), pending_hs_data->length); if (ssl->quic_method) { - if (!ssl->quic_method->add_handshake_data(ssl, ssl->s3->write_level, + if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && + !ssl->quic_method->add_handshake_data(ssl, ssl->s3->write_level, data.data(), data.size())) { OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR); return false; @@ -322,6 +323,11 @@ int tls_flush_flight(SSL *ssl) { } } + if (ssl->wbio == nullptr) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET); + return -1; + } + // Write the pending flight. while (ssl->s3->pending_flight_offset < ssl->s3->pending_flight->length) { int ret = BIO_write( diff --git a/Sources/CNIOBoringSSL/ssl/ssl_cert.cc b/Sources/CNIOBoringSSL/ssl/ssl_cert.cc index 926f44a3..db5477dc 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_cert.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_cert.cc @@ -548,13 +548,11 @@ bool ssl_cert_check_key_usage(const CBS *in, enum ssl_key_usage_t bit) { // subjectPublicKeyInfo !CBS_get_asn1(&tbs_cert, NULL, CBS_ASN1_SEQUENCE) || // issuerUniqueID - !CBS_get_optional_asn1( - &tbs_cert, NULL, NULL, - CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) || + !CBS_get_optional_asn1(&tbs_cert, NULL, NULL, + CBS_ASN1_CONTEXT_SPECIFIC | 1) || // subjectUniqueID - !CBS_get_optional_asn1( - &tbs_cert, NULL, NULL, - CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) || + !CBS_get_optional_asn1(&tbs_cert, NULL, NULL, + CBS_ASN1_CONTEXT_SPECIFIC | 2) || !CBS_get_optional_asn1( &tbs_cert, &outer_extensions, &has_extensions, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) { diff --git a/Sources/CNIOBoringSSL/ssl/ssl_key_share.cc b/Sources/CNIOBoringSSL/ssl/ssl_key_share.cc index 71b12ff9..b3677538 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_key_share.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_key_share.cc @@ -124,29 +124,17 @@ class ECKeyShare : public SSLKeyShare { return true; } - bool Serialize(CBB *out) override { + bool SerializePrivateKey(CBB *out) override { assert(private_key_); - CBB cbb; UniquePtr group(EC_GROUP_new_by_curve_name(nid_)); // Padding is added to avoid leaking the length. size_t len = BN_num_bytes(EC_GROUP_get0_order(group.get())); - if (!CBB_add_asn1_uint64(out, group_id_) || - !CBB_add_asn1(out, &cbb, CBS_ASN1_OCTETSTRING) || - !BN_bn2cbb_padded(&cbb, len, private_key_.get()) || - !CBB_flush(out)) { - return false; - } - return true; + return BN_bn2cbb_padded(out, len, private_key_.get()); } - bool Deserialize(CBS *in) override { + bool DeserializePrivateKey(CBS *in) override { assert(!private_key_); - CBS private_key; - if (!CBS_get_asn1(in, &private_key, CBS_ASN1_OCTETSTRING)) { - return false; - } - private_key_.reset(BN_bin2bn(CBS_data(&private_key), - CBS_len(&private_key), nullptr)); + private_key_.reset(BN_bin2bn(CBS_data(in), CBS_len(in), nullptr)); return private_key_ != nullptr; } @@ -189,16 +177,13 @@ class X25519KeyShare : public SSLKeyShare { return true; } - bool Serialize(CBB *out) override { - return (CBB_add_asn1_uint64(out, GroupID()) && - CBB_add_asn1_octet_string(out, private_key_, sizeof(private_key_))); + bool SerializePrivateKey(CBB *out) override { + return CBB_add_bytes(out, private_key_, sizeof(private_key_)); } - bool Deserialize(CBS *in) override { - CBS key; - if (!CBS_get_asn1(in, &key, CBS_ASN1_OCTETSTRING) || - CBS_len(&key) != sizeof(private_key_) || - !CBS_copy_bytes(&key, private_key_, sizeof(private_key_))) { + bool DeserializePrivateKey(CBS *in) override { + if (CBS_len(in) != sizeof(private_key_) || + !CBS_copy_bytes(in, private_key_, sizeof(private_key_))) { return false; } return true; @@ -339,16 +324,28 @@ UniquePtr SSLKeyShare::Create(uint16_t group_id) { UniquePtr SSLKeyShare::Create(CBS *in) { uint64_t group; - if (!CBS_get_asn1_uint64(in, &group) || group > 0xffff) { + CBS private_key; + if (!CBS_get_asn1_uint64(in, &group) || group > 0xffff || + !CBS_get_asn1(in, &private_key, CBS_ASN1_OCTETSTRING)) { return nullptr; } UniquePtr key_share = Create(static_cast(group)); - if (!key_share || !key_share->Deserialize(in)) { + if (!key_share || !key_share->DeserializePrivateKey(&private_key)) { return nullptr; } return key_share; } +bool SSLKeyShare::Serialize(CBB *out) { + CBB private_key; + if (!CBB_add_asn1_uint64(out, GroupID()) || + !CBB_add_asn1(out, &private_key, CBS_ASN1_OCTETSTRING) || + !SerializePrivateKey(&private_key) || // + !CBB_flush(out)) { + return false; + } + return true; +} bool SSLKeyShare::Accept(CBB *out_public_key, Array *out_secret, uint8_t *out_alert, Span peer_key) { diff --git a/Sources/CNIOBoringSSL/ssl/ssl_lib.cc b/Sources/CNIOBoringSSL/ssl/ssl_lib.cc index f24a92f6..b2b6e971 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_lib.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_lib.cc @@ -1378,6 +1378,7 @@ int SSL_get_error(const SSL *ssl, int ret_code) { case SSL_ERROR_EARLY_DATA_REJECTED: case SSL_ERROR_WANT_CERTIFICATE_VERIFY: case SSL_ERROR_WANT_RENEGOTIATE: + case SSL_ERROR_HANDSHAKE_HINTS_READY: return ssl->s3->rwstate; case SSL_ERROR_WANT_READ: { @@ -1463,6 +1464,8 @@ const char *SSL_error_description(int err) { return "HANDOFF"; case SSL_ERROR_HANDBACK: return "HANDBACK"; + case SSL_ERROR_HANDSHAKE_HINTS_READY: + return "HANDSHAKE_HINTS_READY"; default: return nullptr; } @@ -2186,6 +2189,63 @@ int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) { return 1; } +SSL_ECH_SERVER_CONFIG_LIST *SSL_ECH_SERVER_CONFIG_LIST_new() { + return New(); +} + +void SSL_ECH_SERVER_CONFIG_LIST_up_ref(SSL_ECH_SERVER_CONFIG_LIST *configs) { + CRYPTO_refcount_inc(&configs->references); +} + +void SSL_ECH_SERVER_CONFIG_LIST_free(SSL_ECH_SERVER_CONFIG_LIST *configs) { + if (configs == nullptr || + !CRYPTO_refcount_dec_and_test_zero(&configs->references)) { + return; + } + + configs->~ssl_ech_server_config_list_st(); + OPENSSL_free(configs); +} + +int SSL_ECH_SERVER_CONFIG_LIST_add(SSL_ECH_SERVER_CONFIG_LIST *configs, + int is_retry_config, + const uint8_t *ech_config, + size_t ech_config_len, + const uint8_t *private_key, + size_t private_key_len) { + ECHServerConfig parsed_config; + if (!parsed_config.Init(MakeConstSpan(ech_config, ech_config_len), + MakeConstSpan(private_key, private_key_len), + !!is_retry_config)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + return 0; + } + if (!configs->configs.Push(std::move(parsed_config))) { + OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} + +int SSL_CTX_set1_ech_server_config_list(SSL_CTX *ctx, + SSL_ECH_SERVER_CONFIG_LIST *list) { + bool has_retry_config = false; + for (const bssl::ECHServerConfig &config : list->configs) { + if (config.is_retry_config()) { + has_retry_config = true; + break; + } + } + if (!has_retry_config) { + OPENSSL_PUT_ERROR(SSL, SSL_R_ECH_SERVER_WOULD_HAVE_NO_RETRY_CONFIGS); + return 0; + } + UniquePtr owned_list = UpRef(list); + MutexWriteLock lock(&ctx->lock); + ctx->ech_server_config_list.swap(owned_list); + return 1; +} + int SSL_select_next_proto(uint8_t **out, uint8_t *out_len, const uint8_t *peer, unsigned peer_len, const uint8_t *supported, unsigned supported_len) { @@ -2243,21 +2303,26 @@ void SSL_CTX_set_next_proto_select_cb( int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, unsigned protos_len) { - // Note this function's calling convention is backwards. - return ctx->alpn_client_proto_list.CopyFrom(MakeConstSpan(protos, protos_len)) - ? 0 - : 1; + // Note this function's return value is backwards. + auto span = MakeConstSpan(protos, protos_len); + if (!span.empty() && !ssl_is_valid_alpn_list(span)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL_LIST); + return 1; + } + return ctx->alpn_client_proto_list.CopyFrom(span) ? 0 : 1; } int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) { - // Note this function's calling convention is backwards. + // Note this function's return value is backwards. if (!ssl->config) { return 1; } - return ssl->config->alpn_client_proto_list.CopyFrom( - MakeConstSpan(protos, protos_len)) - ? 0 - : 1; + auto span = MakeConstSpan(protos, protos_len); + if (!span.empty() && !ssl_is_valid_alpn_list(span)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL_LIST); + return 1; + } + return ssl->config->alpn_client_proto_list.CopyFrom(span) ? 0 : 1; } void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, diff --git a/Sources/CNIOBoringSSL/ssl/t1_lib.cc b/Sources/CNIOBoringSSL/ssl/t1_lib.cc index 2a90af4b..0da820fc 100644 --- a/Sources/CNIOBoringSSL/ssl/t1_lib.cc +++ b/Sources/CNIOBoringSSL/ssl/t1_lib.cc @@ -209,11 +209,11 @@ static bool is_post_quantum_group(uint16_t id) { } bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out, - const SSLMessage &msg) { + Span body) { OPENSSL_memset(out, 0, sizeof(*out)); out->ssl = const_cast(ssl); - out->client_hello = CBS_data(&msg.body); - out->client_hello_len = CBS_len(&msg.body); + out->client_hello = body.data(); + out->client_hello_len = body.size(); CBS client_hello, random, session_id; CBS_init(&client_hello, out->client_hello, out->client_hello_len); @@ -591,7 +591,7 @@ static bool ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { } -// Encrypted Client Hello (ECH) +// Encrypted ClientHello (ECH) // // https://tools.ietf.org/html/draft-ietf-tls-esni-09 @@ -620,7 +620,7 @@ static bool ext_ech_add_clienthello_grease(SSL_HANDSHAKE *hs, CBB *out) { constexpr uint16_t kdf_id = EVP_HPKE_HKDF_SHA256; const uint16_t aead_id = EVP_has_aes_hardware() - ? EVP_HPKE_AEAD_AES_GCM_128 + ? EVP_HPKE_AEAD_AES_128_GCM : EVP_HPKE_AEAD_CHACHA20POLY1305; const EVP_AEAD *aead = EVP_HPKE_get_aead(aead_id); assert(aead != nullptr); @@ -748,6 +748,35 @@ static bool ext_ech_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, return true; } +static bool ext_ech_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { + SSL *const ssl = hs->ssl; + if (ssl_protocol_version(ssl) < TLS1_3_VERSION || // + hs->ech_accept || // + hs->ech_server_config_list == nullptr) { + return true; + } + + // Write the list of retry configs to |out|. Note + // |SSL_CTX_set1_ech_server_config_list| ensures |ech_server_config_list| + // contains at least one retry config. + CBB body, retry_configs; + if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) || + !CBB_add_u16_length_prefixed(out, &body) || + !CBB_add_u16_length_prefixed(&body, &retry_configs)) { + return false; + } + for (const ECHServerConfig &config : hs->ech_server_config_list->configs) { + if (!config.is_retry_config()) { + continue; + } + if (!CBB_add_bytes(&retry_configs, config.raw().data(), + config.raw().size())) { + return false; + } + } + return CBB_flush(out); +} + static bool ext_ech_is_inner_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { return true; } @@ -1499,6 +1528,22 @@ static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, return true; } +bool ssl_is_valid_alpn_list(Span in) { + CBS protocol_name_list = in; + if (CBS_len(&protocol_name_list) == 0) { + return false; + } + while (CBS_len(&protocol_name_list) > 0) { + CBS protocol_name; + if (!CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || + // Empty protocol names are forbidden. + CBS_len(&protocol_name) == 0) { + return false; + } + } + return true; +} + bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs, Span protocol) { if (hs->config->alpn_client_proto_list.empty()) { @@ -1551,25 +1596,12 @@ bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS protocol_name_list; if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) || CBS_len(&contents) != 0 || - CBS_len(&protocol_name_list) < 2) { + !ssl_is_valid_alpn_list(protocol_name_list)) { OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); *out_alert = SSL_AD_DECODE_ERROR; return false; } - // Validate the protocol list. - CBS protocol_name_list_copy = protocol_name_list; - while (CBS_len(&protocol_name_list_copy) > 0) { - CBS protocol_name; - if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name) || - // Empty protocol names are forbidden. - CBS_len(&protocol_name) == 0) { - OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); - *out_alert = SSL_AD_DECODE_ERROR; - return false; - } - } - const uint8_t *selected; uint8_t selected_len; int ret = ssl->ctx->alpn_select_cb( @@ -2415,25 +2447,29 @@ bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, } bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found, - Array *out_secret, - uint8_t *out_alert, CBS *contents) { - uint16_t group_id; - CBS key_shares; - if (!tls1_get_shared_group(hs, &group_id)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_GROUP); - *out_alert = SSL_AD_HANDSHAKE_FAILURE; + Span *out_peer_key, + uint8_t *out_alert, + const SSL_CLIENT_HELLO *client_hello) { + // We only support connections that include an ECDHE key exchange. + CBS contents; + if (!ssl_client_hello_get_extension(client_hello, &contents, + TLSEXT_TYPE_key_share)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE); + *out_alert = SSL_AD_MISSING_EXTENSION; return false; } - if (!CBS_get_u16_length_prefixed(contents, &key_shares) || - CBS_len(contents) != 0) { + CBS key_shares; + if (!CBS_get_u16_length_prefixed(&contents, &key_shares) || + CBS_len(&contents) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return false; } // Find the corresponding key share. + const uint16_t group_id = hs->new_session->group_id; CBS peer_key; - CBS_init(&peer_key, NULL, 0); + CBS_init(&peer_key, nullptr, 0); while (CBS_len(&key_shares) > 0) { uint16_t id; CBS peer_key_tmp; @@ -2456,47 +2492,24 @@ bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found, } } - if (CBS_len(&peer_key) == 0) { - *out_found = false; - out_secret->Reset(); - return true; + if (out_peer_key != nullptr) { + *out_peer_key = peer_key; } - - // Compute the DH secret. - Array secret; - ScopedCBB public_key; - UniquePtr key_share = SSLKeyShare::Create(group_id); - if (!key_share || - !CBB_init(public_key.get(), 32) || - !key_share->Accept(public_key.get(), &secret, out_alert, peer_key) || - !CBBFinishArray(public_key.get(), &hs->ecdh_public_key)) { - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return false; - } - - *out_secret = std::move(secret); - *out_found = true; + *out_found = CBS_len(&peer_key) != 0; return true; } -bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out, - bool dry_run) { - uint16_t group_id; +bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { CBB kse_bytes, public_key; - if (!tls1_get_shared_group(hs, &group_id) || - !CBB_add_u16(out, TLSEXT_TYPE_key_share) || + if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) || !CBB_add_u16_length_prefixed(out, &kse_bytes) || - !CBB_add_u16(&kse_bytes, group_id) || + !CBB_add_u16(&kse_bytes, hs->new_session->group_id) || !CBB_add_u16_length_prefixed(&kse_bytes, &public_key) || !CBB_add_bytes(&public_key, hs->ecdh_public_key.data(), hs->ecdh_public_key.size()) || !CBB_flush(out)) { return false; } - if (!dry_run) { - hs->ecdh_public_key.Reset(); - hs->new_session->group_id = group_id; - } return true; } @@ -3264,7 +3277,7 @@ static const struct tls_extension kExtensions[] = { ext_ech_add_clienthello, ext_ech_parse_serverhello, ext_ech_parse_clienthello, - dont_add_serverhello, + ext_ech_add_serverhello, }, { TLSEXT_TYPE_ech_is_inner, @@ -4046,6 +4059,7 @@ enum ssl_ticket_aead_result_t ssl_process_ticket( SSL_HANDSHAKE *hs, UniquePtr *out_session, bool *out_renew_ticket, Span ticket, Span session_id) { + SSL *const ssl = hs->ssl; *out_renew_ticket = false; out_session->reset(); @@ -4054,9 +4068,21 @@ enum ssl_ticket_aead_result_t ssl_process_ticket( return ssl_ticket_aead_ignore_ticket; } + // Tickets in TLS 1.3 are tied into pre-shared keys (PSKs), unlike in TLS 1.2 + // where that concept doesn't exist. The |decrypted_psk| and |ignore_psk| + // hints only apply to PSKs. We check the version to determine which this is. + const bool is_psk = ssl_protocol_version(ssl) >= TLS1_3_VERSION; + Array plaintext; enum ssl_ticket_aead_result_t result; - if (hs->ssl->session_ctx->ticket_aead_method != NULL) { + SSL_HANDSHAKE_HINTS *const hints = hs->hints.get(); + if (is_psk && hints && !hs->hints_requested && + !hints->decrypted_psk.empty()) { + result = plaintext.CopyFrom(hints->decrypted_psk) ? ssl_ticket_aead_success + : ssl_ticket_aead_error; + } else if (is_psk && hints && !hs->hints_requested && hints->ignore_psk) { + result = ssl_ticket_aead_ignore_ticket; + } else if (ssl->session_ctx->ticket_aead_method != NULL) { result = ssl_decrypt_ticket_with_method(hs, &plaintext, out_renew_ticket, ticket); } else { @@ -4065,9 +4091,8 @@ enum ssl_ticket_aead_result_t ssl_process_ticket( // length should be well under the minimum size for the session material and // HMAC. if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) { - return ssl_ticket_aead_ignore_ticket; - } - if (hs->ssl->session_ctx->ticket_key_cb != NULL) { + result = ssl_ticket_aead_ignore_ticket; + } else if (ssl->session_ctx->ticket_key_cb != NULL) { result = ssl_decrypt_ticket_with_cb(hs, &plaintext, out_renew_ticket, ticket); } else { @@ -4075,13 +4100,22 @@ enum ssl_ticket_aead_result_t ssl_process_ticket( } } + if (is_psk && hints && hs->hints_requested) { + if (result == ssl_ticket_aead_ignore_ticket) { + hints->ignore_psk = true; + } else if (result == ssl_ticket_aead_success && + !hints->decrypted_psk.CopyFrom(plaintext)) { + return ssl_ticket_aead_error; + } + } + if (result != ssl_ticket_aead_success) { return result; } // Decode the session. UniquePtr session(SSL_SESSION_from_bytes( - plaintext.data(), plaintext.size(), hs->ssl->ctx.get())); + plaintext.data(), plaintext.size(), ssl->ctx.get())); if (!session) { ERR_clear_error(); // Don't leave an error on the queue. return ssl_ticket_aead_ignore_ticket; diff --git a/Sources/CNIOBoringSSL/ssl/tls13_both.cc b/Sources/CNIOBoringSSL/ssl/tls13_both.cc index b262319e..d1092466 100644 --- a/Sources/CNIOBoringSSL/ssl/tls13_both.cc +++ b/Sources/CNIOBoringSSL/ssl/tls13_both.cc @@ -580,10 +580,40 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) { return ssl_private_key_failure; } - enum ssl_private_key_result_t sign_result = ssl_private_key_sign( - hs, sig, &sig_len, max_sig_len, signature_algorithm, msg); - if (sign_result != ssl_private_key_success) { - return sign_result; + SSL_HANDSHAKE_HINTS *const hints = hs->hints.get(); + Array spki; + if (hints) { + ScopedCBB spki_cbb; + if (!CBB_init(spki_cbb.get(), 64) || + !EVP_marshal_public_key(spki_cbb.get(), hs->local_pubkey.get()) || + !CBBFinishArray(spki_cbb.get(), &spki)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return ssl_private_key_failure; + } + } + + if (hints && !hs->hints_requested && + signature_algorithm == hints->signature_algorithm && + MakeConstSpan(msg) == hints->signature_input && + MakeConstSpan(spki) == hints->signature_spki && + !hints->signature.empty() && hints->signature.size() <= max_sig_len) { + // Signature algorithm and input both match. Reuse the signature from hints. + sig_len = hints->signature.size(); + OPENSSL_memcpy(sig, hints->signature.data(), sig_len); + } else { + enum ssl_private_key_result_t sign_result = ssl_private_key_sign( + hs, sig, &sig_len, max_sig_len, signature_algorithm, msg); + if (sign_result != ssl_private_key_success) { + return sign_result; + } + if (hints && hs->hints_requested) { + hints->signature_algorithm = signature_algorithm; + hints->signature_input = std::move(msg); + hints->signature_spki = std::move(spki); + if (!hints->signature.CopyFrom(MakeSpan(sig, sig_len))) { + return ssl_private_key_failure; + } + } } if (!CBB_did_write(&child, sig_len) || diff --git a/Sources/CNIOBoringSSL/ssl/tls13_server.cc b/Sources/CNIOBoringSSL/ssl/tls13_server.cc index 39d24482..ab3ff8f6 100644 --- a/Sources/CNIOBoringSSL/ssl/tls13_server.cc +++ b/Sources/CNIOBoringSSL/ssl/tls13_server.cc @@ -28,6 +28,7 @@ #include #include "../crypto/internal.h" +#include "../crypto/hpke/internal.h" #include "internal.h" @@ -41,35 +42,57 @@ static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0}; // See RFC 8446, section 8.3. static const int32_t kMaxTicketAgeSkewSeconds = 60; -static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, bool *out_need_retry, - SSL_CLIENT_HELLO *client_hello) { +static bool resolve_ecdhe_secret(SSL_HANDSHAKE *hs, + const SSL_CLIENT_HELLO *client_hello) { SSL *const ssl = hs->ssl; - *out_need_retry = false; - - // We only support connections that include an ECDHE key exchange. - CBS key_share; - if (!ssl_client_hello_get_extension(client_hello, &key_share, - TLSEXT_TYPE_key_share)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION); - return 0; - } + const uint16_t group_id = hs->new_session->group_id; bool found_key_share; - Array dhe_secret; + Span peer_key; uint8_t alert = SSL_AD_DECODE_ERROR; - if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret, - &alert, &key_share)) { + if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &peer_key, + &alert, client_hello)) { ssl_send_alert(ssl, SSL3_AL_FATAL, alert); - return 0; + return false; } if (!found_key_share) { - *out_need_retry = true; - return 0; + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE); + return false; + } + + Array secret; + SSL_HANDSHAKE_HINTS *const hints = hs->hints.get(); + if (hints && !hs->hints_requested && hints->key_share_group_id == group_id && + !hints->key_share_secret.empty()) { + // Copy DH secret from hints. + if (!hs->ecdh_public_key.CopyFrom(hints->key_share_public_key) || + !secret.CopyFrom(hints->key_share_secret)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return false; + } + } else { + ScopedCBB public_key; + UniquePtr key_share = SSLKeyShare::Create(group_id); + if (!key_share || // + !CBB_init(public_key.get(), 32) || + !key_share->Accept(public_key.get(), &secret, &alert, peer_key) || + !CBBFinishArray(public_key.get(), &hs->ecdh_public_key)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); + return false; + } + if (hints && hs->hints_requested) { + hints->key_share_group_id = group_id; + if (!hints->key_share_public_key.CopyFrom(hs->ecdh_public_key) || + !hints->key_share_secret.CopyFrom(secret)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + return false; + } + } } - return tls13_advance_key_schedule(hs, dhe_secret); + return tls13_advance_key_schedule(hs, secret); } static int ssl_ext_supported_versions_add_serverhello(SSL_HANDSHAKE *hs, @@ -186,13 +209,8 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { // the common handshake logic. Resolve the remaining non-PSK parameters. SSL *const ssl = hs->ssl; SSLMessage msg; - if (!ssl->method->get_message(ssl, &msg)) { - return ssl_hs_read_message; - } SSL_CLIENT_HELLO client_hello; - if (!ssl_client_hello_init(ssl, &client_hello, msg)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + if (!hs->GetClientHello(&msg, &client_hello)) { return ssl_hs_error; } @@ -252,6 +270,16 @@ static enum ssl_ticket_aead_result_t select_session( return ssl_ticket_aead_ignore_ticket; } + // Per RFC8446, section 4.2.9, servers MUST abort the handshake if the client + // sends pre_shared_key without psk_key_exchange_modes. + CBS unused; + if (!ssl_client_hello_get_extension(client_hello, &unused, + TLSEXT_TYPE_psk_key_exchange_modes)) { + *out_alert = SSL_AD_MISSING_EXTENSION; + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION); + return ssl_ticket_aead_error; + } + CBS ticket, binders; uint32_t client_ticket_age; if (!ssl_ext_pre_shared_key_parse_clienthello( @@ -337,13 +365,8 @@ static bool quic_ticket_compatible(const SSL_SESSION *session, static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; SSLMessage msg; - if (!ssl->method->get_message(ssl, &msg)) { - return ssl_hs_read_message; - } SSL_CLIENT_HELLO client_hello; - if (!ssl_client_hello_init(ssl, &client_hello, msg)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + if (!hs->GetClientHello(&msg, &client_hello)) { return ssl_hs_error; } @@ -393,6 +416,23 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { return ssl_hs_error; } + // Record connection properties in the new session. + hs->new_session->cipher = hs->new_cipher; + if (!tls1_get_shared_group(hs, &hs->new_session->group_id)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_GROUP); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + return ssl_hs_error; + } + + // Determine if we need HelloRetryRequest. + bool found_key_share; + if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, + /*out_key_share=*/nullptr, &alert, + &client_hello)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); + return ssl_hs_error; + } + // Determine if we're negotiating 0-RTT. if (!ssl->enable_early_data) { ssl->s3->early_data_reason = ssl_early_data_disabled; @@ -423,6 +463,8 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { ssl->s3->early_data_reason = ssl_early_data_ticket_age_skew; } else if (!quic_ticket_compatible(session.get(), hs->config)) { ssl->s3->early_data_reason = ssl_early_data_quic_parameter_mismatch; + } else if (!found_key_share) { + ssl->s3->early_data_reason = ssl_early_data_hello_retry_request; } else { // |ssl_session_is_resumable| forbids cross-cipher resumptions even if the // PRF hashes match. @@ -432,9 +474,6 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { ssl->s3->early_data_accepted = true; } - // Record connection properties in the new session. - hs->new_session->cipher = hs->new_cipher; - // Store the ALPN and ALPS values in the session for 0-RTT. Note the peer // applications settings are not generally known until client // EncryptedExtensions. @@ -497,33 +536,30 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { ssl->s3->skip_early_data = true; } - // Resolve ECDHE and incorporate it into the secret. - bool need_retry; - if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) { - if (need_retry) { - if (ssl->s3->early_data_accepted) { - ssl->s3->early_data_reason = ssl_early_data_hello_retry_request; - ssl->s3->early_data_accepted = false; - } - ssl->s3->skip_early_data = true; - ssl->method->next_message(ssl); - if (!hs->transcript.UpdateForHelloRetryRequest()) { - return ssl_hs_error; - } - hs->tls13_state = state13_send_hello_retry_request; - return ssl_hs_ok; + if (!found_key_share) { + ssl->method->next_message(ssl); + if (!hs->transcript.UpdateForHelloRetryRequest()) { + return ssl_hs_error; } + hs->tls13_state = state13_send_hello_retry_request; + return ssl_hs_ok; + } + + if (!resolve_ecdhe_secret(hs, &client_hello)) { return ssl_hs_error; } ssl->method->next_message(ssl); + hs->ech_client_hello_buf.Reset(); hs->tls13_state = state13_send_server_hello; return ssl_hs_ok; } static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - + if (hs->hints_requested) { + return ssl_hs_hints_ready; + } ScopedCBB cbb; CBB body, session_id, extensions; @@ -566,12 +602,78 @@ static enum ssl_hs_wait_t do_read_second_client_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } SSL_CLIENT_HELLO client_hello; - if (!ssl_client_hello_init(ssl, &client_hello, msg)) { + if (!ssl_client_hello_init(ssl, &client_hello, msg.body)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } + if (hs->ech_accept) { + // If we previously accepted the ClientHelloInner, check that the second + // ClientHello contains an encrypted_client_hello extension. + CBS ech_body; + if (!ssl_client_hello_get_extension(&client_hello, &ech_body, + TLSEXT_TYPE_encrypted_client_hello)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION); + return ssl_hs_error; + } + + // Parse a ClientECH out of the extension body. + uint16_t kdf_id, aead_id; + CBS config_id, enc, payload; + if (!CBS_get_u16(&ech_body, &kdf_id) || // + !CBS_get_u16(&ech_body, &aead_id) || + !CBS_get_u8_length_prefixed(&ech_body, &config_id) || + !CBS_get_u16_length_prefixed(&ech_body, &enc) || + !CBS_get_u16_length_prefixed(&ech_body, &payload) || + CBS_len(&ech_body) != 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return ssl_hs_error; + } + + // Check that ClientECH.cipher_suite is unchanged and that + // ClientECH.config_id and ClientECH.enc are empty. + if (kdf_id != EVP_HPKE_CTX_get_kdf_id(hs->ech_hpke_ctx.get()) || + aead_id != EVP_HPKE_CTX_get_aead_id(hs->ech_hpke_ctx.get()) || + CBS_len(&config_id) > 0 || CBS_len(&enc) > 0) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return ssl_hs_error; + } + + // Decrypt the payload with the HPKE context from the first ClientHello. + Array encoded_client_hello_inner; + bool unused; + if (!ssl_client_hello_decrypt( + hs->ech_hpke_ctx.get(), &encoded_client_hello_inner, &unused, + &client_hello, kdf_id, aead_id, config_id, enc, payload)) { + // Decryption failure is fatal in the second ClientHello. + OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR); + return ssl_hs_error; + } + + // Recover the ClientHelloInner from the EncodedClientHelloInner. + uint8_t alert = SSL_AD_DECODE_ERROR; + bssl::Array client_hello_inner; + if (!ssl_decode_client_hello_inner(ssl, &alert, &client_hello_inner, + encoded_client_hello_inner, + &client_hello)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); + ssl_send_alert(ssl, SSL3_AL_FATAL, alert); + return ssl_hs_error; + } + hs->ech_client_hello_buf = std::move(client_hello_inner); + + // Reparse |client_hello| from the buffer owned by |hs|. + if (!hs->GetClientHello(&msg, &client_hello)) { + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); + return ssl_hs_error; + } + } + // We perform all our negotiation based on the first ClientHello (for // consistency with what |select_certificate_cb| observed), which is in the // transcript, so we can ignore most of this second one. @@ -607,13 +709,7 @@ static enum ssl_hs_wait_t do_read_second_client_hello(SSL_HANDSHAKE *hs) { } } - bool need_retry; - if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) { - if (need_retry) { - // Only send one HelloRetryRequest. - ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); - OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE); - } + if (!resolve_ecdhe_secret(hs, &client_hello)) { return ssl_hs_error; } @@ -629,70 +725,73 @@ static enum ssl_hs_wait_t do_read_second_client_hello(SSL_HANDSHAKE *hs) { } ssl->method->next_message(ssl); + hs->ech_client_hello_buf.Reset(); hs->tls13_state = state13_send_server_hello; return ssl_hs_ok; } +static bool make_server_hello(SSL_HANDSHAKE *hs, Array *out) { + SSL *const ssl = hs->ssl; + ScopedCBB cbb; + CBB body, extensions, session_id; + if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) || + !CBB_add_u16(&body, TLS1_2_VERSION) || + !CBB_add_bytes(&body, ssl->s3->server_random, + sizeof(ssl->s3->server_random)) || + !CBB_add_u8_length_prefixed(&body, &session_id) || + !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || + !CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) || + !CBB_add_u8(&body, 0) || + !CBB_add_u16_length_prefixed(&body, &extensions) || + !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || + !ssl_ext_key_share_add_serverhello(hs, &extensions) || + !ssl_ext_supported_versions_add_serverhello(hs, &extensions) || + !ssl->method->finish_message(ssl, cbb.get(), out)) { + return false; + } + return true; +} + static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; Span random(ssl->s3->server_random); - RAND_bytes(random.data(), random.size()); - // If the ClientHello has an ech_is_inner extension, we must be the ECH - // backend server. In response to ech_is_inner, we will overwrite part of the - // ServerHello.random with the ECH acceptance confirmation. + SSL_HANDSHAKE_HINTS *const hints = hs->hints.get(); + if (hints && !hs->hints_requested && + hints->server_random.size() == random.size()) { + OPENSSL_memcpy(random.data(), hints->server_random.data(), random.size()); + } else { + RAND_bytes(random.data(), random.size()); + if (hints && hs->hints_requested && + !hints->server_random.CopyFrom(random)) { + return ssl_hs_error; + } + } + + assert(!hs->ech_accept || hs->ech_is_inner_present); + if (hs->ech_is_inner_present) { // Construct the ServerHelloECHConf message, which is the same as // ServerHello, except the last 8 bytes of its random field are zeroed out. Span random_suffix = random.subspan(24); OPENSSL_memset(random_suffix.data(), 0, random_suffix.size()); - ScopedCBB cbb; - CBB body, extensions, session_id; - if (!ssl->method->init_message(ssl, cbb.get(), &body, - SSL3_MT_SERVER_HELLO) || - !CBB_add_u16(&body, TLS1_2_VERSION) || - !CBB_add_bytes(&body, random.data(), random.size()) || - !CBB_add_u8_length_prefixed(&body, &session_id) || - !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || - !CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) || - !CBB_add_u8(&body, 0) || - !CBB_add_u16_length_prefixed(&body, &extensions) || - !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || - !ssl_ext_key_share_add_serverhello(hs, &extensions, /*dry_run=*/true) || - !ssl_ext_supported_versions_add_serverhello(hs, &extensions) || - !CBB_flush(cbb.get())) { - return ssl_hs_error; - } - - // Note that |cbb| includes the message type and length fields, but not the - // record layer header. - if (!tls13_ech_accept_confirmation( - hs, random_suffix, - bssl::MakeConstSpan(CBB_data(cbb.get()), CBB_len(cbb.get())))) { + Array server_hello_ech_conf; + if (!make_server_hello(hs, &server_hello_ech_conf) || + !tls13_ech_accept_confirmation(hs, random_suffix, + server_hello_ech_conf)) { return ssl_hs_error; } } - // Send a ServerHello. - ScopedCBB cbb; - CBB body, extensions, session_id; - if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) || - !CBB_add_u16(&body, TLS1_2_VERSION) || - !CBB_add_bytes(&body, random.data(), random.size()) || - !CBB_add_u8_length_prefixed(&body, &session_id) || - !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) || - !CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) || - !CBB_add_u8(&body, 0) || - !CBB_add_u16_length_prefixed(&body, &extensions) || - !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || - !ssl_ext_key_share_add_serverhello(hs, &extensions, /*dry_run=*/false) || - !ssl_ext_supported_versions_add_serverhello(hs, &extensions) || - !ssl_add_message_cbb(ssl, cbb.get())) { + Array server_hello; + if (!make_server_hello(hs, &server_hello) || + !ssl->method->add_message(ssl, std::move(server_hello))) { return ssl_hs_error; } + hs->ecdh_public_key.Reset(); // No longer needed. if (!ssl->s3->used_hello_retry_request && !ssl->method->add_change_cipher_spec(ssl)) { return ssl_hs_error; @@ -707,6 +806,8 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { } // Send EncryptedExtensions. + ScopedCBB cbb; + CBB body; if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_ENCRYPTED_EXTENSIONS) || !ssl_add_serverhello_tlsext(hs, &body) || @@ -796,6 +897,10 @@ static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs) { static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; + if (hs->hints_requested) { + return ssl_hs_hints_ready; + } + if (!tls13_add_finished(hs) || // Update the secret to the master secret and derive traffic keys. !tls13_advance_key_schedule( diff --git a/Sources/CNIOBoringSSL/ssl/tls_method.cc b/Sources/CNIOBoringSSL/ssl/tls_method.cc index 9c97a7e4..1fc1b304 100644 --- a/Sources/CNIOBoringSSL/ssl/tls_method.cc +++ b/Sources/CNIOBoringSSL/ssl/tls_method.cc @@ -93,7 +93,8 @@ static bool tls_set_read_state(SSL *ssl, ssl_encryption_level_t level, } if (ssl->quic_method != nullptr) { - if (!ssl->quic_method->set_read_secret(ssl, level, aead_ctx->cipher(), + if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && + !ssl->quic_method->set_read_secret(ssl, level, aead_ctx->cipher(), secret_for_quic.data(), secret_for_quic.size())) { return false; @@ -121,7 +122,8 @@ static bool tls_set_write_state(SSL *ssl, ssl_encryption_level_t level, } if (ssl->quic_method != nullptr) { - if (!ssl->quic_method->set_write_secret(ssl, level, aead_ctx->cipher(), + if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && + !ssl->quic_method->set_write_secret(ssl, level, aead_ctx->cipher(), secret_for_quic.data(), secret_for_quic.size())) { return false;