From 4fb7ead803e38949eb1d6fabb849206a72c580f3 Mon Sep 17 00:00:00 2001 From: George Barnett Date: Thu, 20 Oct 2022 13:19:57 +0100 Subject: [PATCH] Update BoringSSL to b819f7e9392d25db6705a6bd3c92be3bb91775e2 (#406) --- Package.swift | 2 +- Package@swift-5.5.swift | 2 +- Sources/CNIOBoringSSL/crypto/asn1/a_strex.c | 17 +- Sources/CNIOBoringSSL/crypto/asn1/a_utf8.c | 142 -------- Sources/CNIOBoringSSL/crypto/asn1/internal.h | 2 - .../crypto/bytestring/asn1_compat.c | 3 +- Sources/CNIOBoringSSL/crypto/bytestring/cbb.c | 309 ++++++++---------- .../crypto/cpu_aarch64_freebsd.c | 62 ++++ .../CNIOBoringSSL/crypto/cpu_arm_freebsd.c | 55 ++++ .../CNIOBoringSSL/crypto/dh_extra/dh_asn1.c | 1 + .../CNIOBoringSSL/crypto/dh_extra/params.c | 16 +- Sources/CNIOBoringSSL/crypto/dsa/dsa.c | 1 + .../crypto/ecdsa_extra/ecdsa_asn1.c | 6 +- .../crypto/fipsmodule/dh/check.c | 5 +- .../CNIOBoringSSL/crypto/fipsmodule/dh/dh.c | 3 - .../crypto/fipsmodule/dh/internal.h | 20 ++ .../crypto/fipsmodule/rsa/internal.h | 2 +- .../CNIOBoringSSL/crypto/fipsmodule/rsa/rsa.c | 63 +++- Sources/CNIOBoringSSL/crypto/hpke/hpke.c | 24 +- .../crypto/trust_token/trust_token.c | 44 +-- Sources/CNIOBoringSSL/crypto/x509/x_all.c | 2 + Sources/CNIOBoringSSL/hash.txt | 2 +- .../CNIOBoringSSL_boringssl_prefix_symbols.h | 5 +- ...IOBoringSSL_boringssl_prefix_symbols_asm.h | 5 +- .../include/CNIOBoringSSL_bytestring.h | 51 ++- .../CNIOBoringSSL/include/CNIOBoringSSL_dh.h | 26 -- .../include/CNIOBoringSSL_hpke.h | 32 +- .../CNIOBoringSSL/include/CNIOBoringSSL_rsa.h | 6 +- .../CNIOBoringSSL/include/CNIOBoringSSL_ssl.h | 65 +--- .../include/boringssl_prefix_symbols_nasm.inc | 10 +- Sources/CNIOBoringSSL/ssl/dtls_method.cc | 7 +- Sources/CNIOBoringSSL/ssl/dtls_record.cc | 58 ++-- Sources/CNIOBoringSSL/ssl/handoff.cc | 21 +- Sources/CNIOBoringSSL/ssl/internal.h | 25 +- Sources/CNIOBoringSSL/ssl/ssl_aead_ctx.cc | 17 +- Sources/CNIOBoringSSL/ssl/ssl_lib.cc | 9 +- Sources/CNIOBoringSSL/ssl/t1_enc.cc | 4 +- Sources/CNIOBoringSSL/ssl/tls_method.cc | 4 +- Sources/CNIOBoringSSL/ssl/tls_record.cc | 114 +------ 39 files changed, 544 insertions(+), 698 deletions(-) delete mode 100644 Sources/CNIOBoringSSL/crypto/asn1/a_utf8.c create mode 100644 Sources/CNIOBoringSSL/crypto/cpu_aarch64_freebsd.c create mode 100644 Sources/CNIOBoringSSL/crypto/cpu_arm_freebsd.c diff --git a/Package.swift b/Package.swift index 234b132e..fe72932d 100644 --- a/Package.swift +++ b/Package.swift @@ -26,7 +26,7 @@ import class Foundation.ProcessInfo // Sources/CNIOBoringSSL directory. The source repository is at // https://boringssl.googlesource.com/boringssl. // -// BoringSSL Commit: cab31f65f1ad6e6daca62e95b25dd6cd805fce0b +// BoringSSL Commit: b819f7e9392d25db6705a6bd3c92be3bb91775e2 /// This function generates the dependencies we want to express. /// diff --git a/Package@swift-5.5.swift b/Package@swift-5.5.swift index 35a02312..686b08d2 100644 --- a/Package@swift-5.5.swift +++ b/Package@swift-5.5.swift @@ -26,7 +26,7 @@ import class Foundation.ProcessInfo // Sources/CNIOBoringSSL directory. The source repository is at // https://boringssl.googlesource.com/boringssl. // -// BoringSSL Commit: cab31f65f1ad6e6daca62e95b25dd6cd805fce0b +// BoringSSL Commit: b819f7e9392d25db6705a6bd3c92be3bb91775e2 /// This function generates the dependencies we want to express. /// diff --git a/Sources/CNIOBoringSSL/crypto/asn1/a_strex.c b/Sources/CNIOBoringSSL/crypto/asn1/a_strex.c index 627d216c..c726b564 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/a_strex.c +++ b/Sources/CNIOBoringSSL/crypto/asn1/a_strex.c @@ -167,12 +167,17 @@ static int do_buf(const unsigned char *buf, int buflen, int encoding, } const int is_last = CBS_len(&cbs) == 0; if (flags & ASN1_STRFLGS_UTF8_CONVERT) { - unsigned char utfbuf[6]; - int utflen; - utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c); - for (int i = 0; i < utflen; i++) { - int len = do_esc_char(utfbuf[i], flags, quotes, out, is_first && i == 0, - is_last && i == utflen - 1); + uint8_t utf8_buf[6]; + CBB utf8_cbb; + CBB_init_fixed(&utf8_cbb, utf8_buf, sizeof(utf8_buf)); + if (!cbb_add_utf8(&utf8_cbb, c)) { + OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR); + return 1; + } + size_t utf8_len = CBB_len(&utf8_cbb); + for (size_t i = 0; i < utf8_len; i++) { + int len = do_esc_char(utf8_buf[i], flags, quotes, out, + is_first && i == 0, is_last && i == utf8_len - 1); if (len < 0) { return -1; } diff --git a/Sources/CNIOBoringSSL/crypto/asn1/a_utf8.c b/Sources/CNIOBoringSSL/crypto/asn1/a_utf8.c deleted file mode 100644 index 46868809..00000000 --- a/Sources/CNIOBoringSSL/crypto/asn1/a_utf8.c +++ /dev/null @@ -1,142 +0,0 @@ -/* 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.] */ - -#include - -#include -#include - -#include "internal.h" - -// UTF8 utilities - -// This takes a character 'value' and writes the UTF8 encoded value in 'str' -// where 'str' is a buffer containing 'len' characters. Returns the number of -// characters written or -1 if 'len' is too small. 'str' can be set to NULL -// in which case it just returns the number of characters. It will need at -// most 6 characters. - -int UTF8_putc(unsigned char *str, int len, uint32_t value) { - if (!str) { - len = 6; // Maximum we will need - } else if (len <= 0) { - return -1; - } - if (value < 0x80) { - if (str) { - *str = (unsigned char)value; - } - return 1; - } - if (value < 0x800) { - if (len < 2) { - return -1; - } - if (str) { - *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 2; - } - if (value < 0x10000) { - if (len < 3) { - return -1; - } - if (str) { - *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 3; - } - if (value < 0x200000) { - if (len < 4) { - return -1; - } - if (str) { - *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 4; - } - if (value < 0x4000000) { - if (len < 5) { - return -1; - } - if (str) { - *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); - *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 5; - } - if (len < 6) { - return -1; - } - if (str) { - *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); - *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); - *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); - *str = (unsigned char)((value & 0x3f) | 0x80); - } - return 6; -} diff --git a/Sources/CNIOBoringSSL/crypto/asn1/internal.h b/Sources/CNIOBoringSSL/crypto/asn1/internal.h index 486f95a3..307340f3 100644 --- a/Sources/CNIOBoringSSL/crypto/asn1/internal.h +++ b/Sources/CNIOBoringSSL/crypto/asn1/internal.h @@ -156,8 +156,6 @@ OPENSSL_EXPORT int asn1_generalizedtime_to_tm(struct tm *tm, void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine); -int UTF8_putc(unsigned char *str, int len, uint32_t value); - int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); diff --git a/Sources/CNIOBoringSSL/crypto/bytestring/asn1_compat.c b/Sources/CNIOBoringSSL/crypto/bytestring/asn1_compat.c index 1073ac38..351e8448 100644 --- a/Sources/CNIOBoringSSL/crypto/bytestring/asn1_compat.c +++ b/Sources/CNIOBoringSSL/crypto/bytestring/asn1_compat.c @@ -26,7 +26,8 @@ int CBB_finish_i2d(CBB *cbb, uint8_t **outp) { - assert(cbb->base->can_resize); + assert(!cbb->is_child); + assert(cbb->u.base.can_resize); uint8_t *der; size_t der_len; diff --git a/Sources/CNIOBoringSSL/crypto/bytestring/cbb.c b/Sources/CNIOBoringSSL/crypto/bytestring/cbb.c index 772e4cae..2da37edd 100644 --- a/Sources/CNIOBoringSSL/crypto/bytestring/cbb.c +++ b/Sources/CNIOBoringSSL/crypto/bytestring/cbb.c @@ -27,24 +27,14 @@ void CBB_zero(CBB *cbb) { OPENSSL_memset(cbb, 0, sizeof(CBB)); } -static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) { - // This assumes that |cbb| has already been zeroed. - struct cbb_buffer_st *base; - - base = OPENSSL_malloc(sizeof(struct cbb_buffer_st)); - if (base == NULL) { - return 0; - } - - base->buf = buf; - base->len = 0; - base->cap = cap; - base->can_resize = 1; - base->error = 0; - - cbb->base = base; +static void cbb_init(CBB *cbb, uint8_t *buf, size_t cap, int can_resize) { cbb->is_child = 0; - return 1; + cbb->child = NULL; + cbb->u.base.buf = buf; + cbb->u.base.len = 0; + cbb->u.base.cap = cap; + cbb->u.base.can_resize = can_resize; + cbb->u.base.error = 0; } int CBB_init(CBB *cbb, size_t initial_capacity) { @@ -55,22 +45,13 @@ int CBB_init(CBB *cbb, size_t initial_capacity) { return 0; } - if (!cbb_init(cbb, buf, initial_capacity)) { - OPENSSL_free(buf); - return 0; - } - + cbb_init(cbb, buf, initial_capacity, /*can_resize=*/1); return 1; } int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) { CBB_zero(cbb); - - if (!cbb_init(cbb, buf, len)) { - return 0; - } - - cbb->base->can_resize = 0; + cbb_init(cbb, buf, len, /*can_resize=*/0); return 1; } @@ -82,41 +63,33 @@ void CBB_cleanup(CBB *cbb) { return; } - if (cbb->base) { - if (cbb->base->can_resize) { - OPENSSL_free(cbb->base->buf); - } - OPENSSL_free(cbb->base); + if (cbb->u.base.can_resize) { + OPENSSL_free(cbb->u.base.buf); } - cbb->base = NULL; } static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out, size_t len) { - size_t newlen; - if (base == NULL) { return 0; } - newlen = base->len + len; + size_t newlen = base->len + len; if (newlen < base->len) { // Overflow goto err; } if (newlen > base->cap) { - size_t newcap = base->cap * 2; - uint8_t *newbuf; - if (!base->can_resize) { goto err; } + size_t newcap = base->cap * 2; if (newcap < base->cap || newcap < newlen) { newcap = newlen; } - newbuf = OPENSSL_realloc(base->buf, newcap); + uint8_t *newbuf = OPENSSL_realloc(base->buf, newcap); if (newbuf == NULL) { goto err; } @@ -146,30 +119,6 @@ static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, return 1; } -static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint64_t v, - size_t len_len) { - if (len_len == 0) { - return 1; - } - - uint8_t *buf; - if (!cbb_buffer_add(base, &buf, len_len)) { - return 0; - } - - for (size_t i = len_len - 1; i < len_len; i--) { - buf[i] = v; - v >>= 8; - } - - if (v != 0) { - base->error = 1; - return 0; - } - - return 1; -} - int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { if (cbb->is_child) { return 0; @@ -179,57 +128,67 @@ int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) { return 0; } - if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) { + if (cbb->u.base.can_resize && (out_data == NULL || out_len == NULL)) { // |out_data| and |out_len| can only be NULL if the CBB is fixed. return 0; } if (out_data != NULL) { - *out_data = cbb->base->buf; + *out_data = cbb->u.base.buf; } if (out_len != NULL) { - *out_len = cbb->base->len; + *out_len = cbb->u.base.len; } - cbb->base->buf = NULL; + cbb->u.base.buf = NULL; CBB_cleanup(cbb); return 1; } +static struct cbb_buffer_st *cbb_get_base(CBB *cbb) { + if (cbb->is_child) { + return cbb->u.child.base; + } + return &cbb->u.base; +} + // CBB_flush recurses and then writes out any pending length prefix. The // current length of the underlying base is taken to be the length of the // length-prefixed data. int CBB_flush(CBB *cbb) { - size_t child_start, i, len; - - // If |cbb->base| has hit an error, the buffer is in an undefined state, so + // If |base| has hit an error, the buffer is in an undefined state, so // fail all following calls. In particular, |cbb->child| may point to invalid // memory. - if (cbb->base == NULL || cbb->base->error) { + struct cbb_buffer_st *base = cbb_get_base(cbb); + if (base == NULL || base->error) { return 0; } - if (cbb->child == NULL || cbb->child->pending_len_len == 0) { + if (cbb->child == NULL) { + // Nothing to flush. return 1; } - child_start = cbb->child->offset + cbb->child->pending_len_len; + assert(cbb->child->is_child); + struct cbb_child_st *child = &cbb->child->u.child; + assert(child->base == base); + size_t child_start = child->offset + child->pending_len_len; if (!CBB_flush(cbb->child) || - child_start < cbb->child->offset || - cbb->base->len < child_start) { + child_start < child->offset || + base->len < child_start) { goto err; } - len = cbb->base->len - child_start; + size_t len = base->len - child_start; - if (cbb->child->pending_is_asn1) { + if (child->pending_is_asn1) { // For ASN.1 we assume that we'll only need a single byte for the length. // If that turned out to be incorrect, we have to move the contents along // in order to make space. uint8_t len_len; uint8_t initial_length_byte; - assert (cbb->child->pending_len_len == 1); + assert (child->pending_len_len == 1); if (len > 0xfffffffe) { // Too large. @@ -255,70 +214,85 @@ int CBB_flush(CBB *cbb) { if (len_len != 1) { // We need to move the contents along in order to make space. size_t extra_bytes = len_len - 1; - if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) { + if (!cbb_buffer_add(base, NULL, extra_bytes)) { goto err; } - OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes, - cbb->base->buf + child_start, len); + OPENSSL_memmove(base->buf + child_start + extra_bytes, + base->buf + child_start, len); } - cbb->base->buf[cbb->child->offset++] = initial_length_byte; - cbb->child->pending_len_len = len_len - 1; + base->buf[child->offset++] = initial_length_byte; + child->pending_len_len = len_len - 1; } - for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len; - i--) { - cbb->base->buf[cbb->child->offset + i] = (uint8_t)len; + for (size_t i = child->pending_len_len - 1; i < child->pending_len_len; i--) { + base->buf[child->offset + i] = (uint8_t)len; len >>= 8; } if (len != 0) { goto err; } - cbb->child->base = NULL; + child->base = NULL; cbb->child = NULL; return 1; err: - cbb->base->error = 1; + base->error = 1; return 0; } const uint8_t *CBB_data(const CBB *cbb) { assert(cbb->child == NULL); - return cbb->base->buf + cbb->offset + cbb->pending_len_len; + if (cbb->is_child) { + return cbb->u.child.base->buf + cbb->u.child.offset + + cbb->u.child.pending_len_len; + } + return cbb->u.base.buf; } size_t CBB_len(const CBB *cbb) { assert(cbb->child == NULL); - assert(cbb->offset + cbb->pending_len_len <= cbb->base->len); - - return cbb->base->len - cbb->offset - cbb->pending_len_len; + if (cbb->is_child) { + assert(cbb->u.child.offset + cbb->u.child.pending_len_len <= + cbb->u.child.base->len); + return cbb->u.child.base->len - cbb->u.child.offset - + cbb->u.child.pending_len_len; + } + return cbb->u.base.len; } -static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, - uint8_t len_len) { - uint8_t *prefix_bytes; +static int cbb_add_child(CBB *cbb, CBB *out_child, uint8_t len_len, + int is_asn1) { + assert(cbb->child == NULL); + assert(!is_asn1 || len_len == 1); + struct cbb_buffer_st *base = cbb_get_base(cbb); + size_t offset = base->len; - if (!CBB_flush(cbb)) { + // Reserve space for the length prefix. + uint8_t *prefix_bytes; + if (!cbb_buffer_add(base, &prefix_bytes, len_len)) { return 0; } + OPENSSL_memset(prefix_bytes, 0, len_len); + + CBB_zero(out_child); + out_child->is_child = 1; + out_child->u.child.base = base; + out_child->u.child.offset = offset; + out_child->u.child.pending_len_len = len_len; + out_child->u.child.pending_is_asn1 = is_asn1; + cbb->child = out_child; + return 1; +} - size_t offset = cbb->base->len; - if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) { +static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, + uint8_t len_len) { + if (!CBB_flush(cbb)) { return 0; } - OPENSSL_memset(prefix_bytes, 0, len_len); - OPENSSL_memset(out_contents, 0, sizeof(CBB)); - out_contents->base = cbb->base; - out_contents->is_child = 1; - cbb->child = out_contents; - cbb->child->offset = offset; - cbb->child->pending_len_len = len_len; - cbb->child->pending_is_asn1 = 0; - - return 1; + return cbb_add_child(cbb, out_contents, len_len, /*is_asn1=*/0); } int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) { @@ -377,30 +351,16 @@ int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) { return 0; } - size_t offset = cbb->base->len; - if (!CBB_add_u8(cbb, 0)) { - return 0; - } - - OPENSSL_memset(out_contents, 0, sizeof(CBB)); - out_contents->base = cbb->base; - out_contents->is_child = 1; - cbb->child = out_contents; - cbb->child->offset = offset; - cbb->child->pending_len_len = 1; - cbb->child->pending_is_asn1 = 1; - - return 1; + // Reserve one byte of length prefix. |CBB_flush| will finish it later. + return cbb_add_child(cbb, out_contents, /*len_len=*/1, /*is_asn1=*/1); } int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) { - uint8_t *dest; - - if (!CBB_flush(cbb) || - !cbb_buffer_add(cbb->base, &dest, len)) { + uint8_t *out; + if (!CBB_add_space(cbb, &out, len)) { return 0; } - OPENSSL_memcpy(dest, data, len); + OPENSSL_memcpy(out, data, len); return 1; } @@ -415,7 +375,7 @@ int CBB_add_zeros(CBB *cbb, size_t len) { int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) { if (!CBB_flush(cbb) || - !cbb_buffer_add(cbb->base, out_data, len)) { + !cbb_buffer_add(cbb_get_base(cbb), out_data, len)) { return 0; } return 1; @@ -423,37 +383,50 @@ int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) { int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) { if (!CBB_flush(cbb) || - !cbb_buffer_reserve(cbb->base, out_data, len)) { + !cbb_buffer_reserve(cbb_get_base(cbb), out_data, len)) { return 0; } return 1; } int CBB_did_write(CBB *cbb, size_t len) { - size_t newlen = cbb->base->len + len; + struct cbb_buffer_st *base = cbb_get_base(cbb); + size_t newlen = base->len + len; if (cbb->child != NULL || - newlen < cbb->base->len || - newlen > cbb->base->cap) { + newlen < base->len || + newlen > base->cap) { return 0; } - cbb->base->len = newlen; + base->len = newlen; return 1; } -int CBB_add_u8(CBB *cbb, uint8_t value) { - if (!CBB_flush(cbb)) { +static int cbb_add_u(CBB *cbb, uint64_t v, size_t len_len) { + uint8_t *buf; + if (!CBB_add_space(cbb, &buf, len_len)) { return 0; } - return cbb_buffer_add_u(cbb->base, value, 1); -} + for (size_t i = len_len - 1; i < len_len; i--) { + buf[i] = v; + v >>= 8; + } -int CBB_add_u16(CBB *cbb, uint16_t value) { - if (!CBB_flush(cbb)) { + // |v| must fit in |len_len| bytes. + if (v != 0) { + cbb_get_base(cbb)->error = 1; return 0; } - return cbb_buffer_add_u(cbb->base, value, 2); + return 1; +} + +int CBB_add_u8(CBB *cbb, uint8_t value) { + return cbb_add_u(cbb, value, 1); +} + +int CBB_add_u16(CBB *cbb, uint16_t value) { + return cbb_add_u(cbb, value, 2); } int CBB_add_u16le(CBB *cbb, uint16_t value) { @@ -461,19 +434,11 @@ int CBB_add_u16le(CBB *cbb, uint16_t value) { } int CBB_add_u24(CBB *cbb, uint32_t value) { - if (!CBB_flush(cbb)) { - return 0; - } - - return cbb_buffer_add_u(cbb->base, value, 3); + return cbb_add_u(cbb, value, 3); } int CBB_add_u32(CBB *cbb, uint32_t value) { - if (!CBB_flush(cbb)) { - return 0; - } - - return cbb_buffer_add_u(cbb->base, value, 4); + return cbb_add_u(cbb, value, 4); } int CBB_add_u32le(CBB *cbb, uint32_t value) { @@ -481,10 +446,7 @@ int CBB_add_u32le(CBB *cbb, uint32_t value) { } int CBB_add_u64(CBB *cbb, uint64_t value) { - if (!CBB_flush(cbb)) { - return 0; - } - return cbb_buffer_add_u(cbb->base, value, 8); + return cbb_add_u(cbb, value, 8); } int CBB_add_u64le(CBB *cbb, uint64_t value) { @@ -496,20 +458,25 @@ void CBB_discard_child(CBB *cbb) { return; } - cbb->base->len = cbb->child->offset; + struct cbb_buffer_st *base = cbb_get_base(cbb); + assert(cbb->child->is_child); + base->len = cbb->child->u.child.offset; - cbb->child->base = NULL; + cbb->child->u.child.base = NULL; cbb->child = NULL; } int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { - CBB child; - int started = 0; + return CBB_add_asn1_uint64_with_tag(cbb, value, CBS_ASN1_INTEGER); +} - if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { +int CBB_add_asn1_uint64_with_tag(CBB *cbb, uint64_t value, unsigned tag) { + CBB child; + if (!CBB_add_asn1(cbb, &child, tag)) { return 0; } + int started = 0; for (size_t i = 0; i < 8; i++) { uint8_t byte = (value >> 8*(7-i)) & 0xff; if (!started) { @@ -538,8 +505,12 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) { } int CBB_add_asn1_int64(CBB *cbb, int64_t value) { + return CBB_add_asn1_int64_with_tag(cbb, value, CBS_ASN1_INTEGER); +} + +int CBB_add_asn1_int64_with_tag(CBB *cbb, int64_t value, unsigned tag) { if (value >= 0) { - return CBB_add_asn1_uint64(cbb, value); + return CBB_add_asn1_uint64_with_tag(cbb, (uint64_t)value, tag); } uint8_t bytes[sizeof(int64_t)]; @@ -551,7 +522,7 @@ int CBB_add_asn1_int64(CBB *cbb, int64_t value) { } CBB child; - if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) { + if (!CBB_add_asn1(cbb, &child, tag)) { return 0; } for (int i = start; i >= 0; i--) { @@ -707,14 +678,14 @@ int CBB_flush_asn1_set_of(CBB *cbb) { } qsort(children, num_children, sizeof(CBS), compare_set_of_element); - // Rewind |cbb| and write the contents back in the new order. - cbb->base->len = cbb->offset + cbb->pending_len_len; + // Write the contents back in the new order. + uint8_t *out = (uint8_t *)CBB_data(cbb); + size_t offset = 0; for (size_t i = 0; i < num_children; i++) { - if (!CBB_add_bytes(cbb, CBS_data(&children[i]), CBS_len(&children[i]))) { - goto err; - } + OPENSSL_memcpy(out + offset, CBS_data(&children[i]), CBS_len(&children[i])); + offset += CBS_len(&children[i]); } - assert(CBB_len(cbb) == buf_len); + assert(offset == buf_len); ret = 1; diff --git a/Sources/CNIOBoringSSL/crypto/cpu_aarch64_freebsd.c b/Sources/CNIOBoringSSL/crypto/cpu_aarch64_freebsd.c new file mode 100644 index 00000000..0c413b94 --- /dev/null +++ b/Sources/CNIOBoringSSL/crypto/cpu_aarch64_freebsd.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2022, 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 "internal.h" + +#if defined(OPENSSL_AARCH64) && defined(OPENSSL_FREEBSD) && \ + !defined(OPENSSL_STATIC_ARMCAP) + +#include +#include + +#include + +extern uint32_t OPENSSL_armcap_P; + +// ID_AA64ISAR0_*_VAL are defined starting FreeBSD 13.0. When FreeBSD +// 12.x is out of support, these compatibility macros can be removed. + +#ifndef ID_AA64ISAR0_AES_VAL +#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES +#endif +#ifndef ID_AA64ISAR0_SHA1_VAL +#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1 +#endif +#ifndef ID_AA64ISAR0_SHA2_VAL +#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2 +#endif + +void OPENSSL_cpuid_setup(void) { + uint64_t id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1); + + OPENSSL_armcap_P |= ARMV7_NEON; + + if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) >= ID_AA64ISAR0_AES_BASE) { + OPENSSL_armcap_P |= ARMV8_AES; + } + if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) >= ID_AA64ISAR0_AES_PMULL) { + OPENSSL_armcap_P |= ARMV8_PMULL; + } + if (ID_AA64ISAR0_SHA1_VAL(id_aa64isar0) >= ID_AA64ISAR0_SHA1_BASE) { + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) >= ID_AA64ISAR0_SHA2_BASE) { + OPENSSL_armcap_P |= ARMV8_SHA256; + } + if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) >= ID_AA64ISAR0_SHA2_512) { + OPENSSL_armcap_P |= ARMV8_SHA512; + } +} + +#endif // OPENSSL_AARCH64 && OPENSSL_FREEBSD && !OPENSSL_STATIC_ARMCAP diff --git a/Sources/CNIOBoringSSL/crypto/cpu_arm_freebsd.c b/Sources/CNIOBoringSSL/crypto/cpu_arm_freebsd.c new file mode 100644 index 00000000..48c53511 --- /dev/null +++ b/Sources/CNIOBoringSSL/crypto/cpu_arm_freebsd.c @@ -0,0 +1,55 @@ +/* Copyright (c) 2022, 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 "internal.h" + +#if defined(OPENSSL_ARM) && defined(OPENSSL_FREEBSD) && \ + !defined(OPENSSL_STATIC_ARMCAP) +#include +#include + +#include +#include + +extern uint32_t OPENSSL_armcap_P; + +void OPENSSL_cpuid_setup(void) { + unsigned long hwcap = 0, hwcap2 = 0; + + // |elf_aux_info| may fail, in which case |hwcap| and |hwcap2| will be + // left at zero. The rest of this function will then gracefully report + // the features are absent. + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); + elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2)); + + // Matching OpenSSL, only report other features if NEON is present. + if (hwcap & HWCAP_NEON) { + OPENSSL_armcap_P |= ARMV7_NEON; + + if (hwcap2 & HWCAP2_AES) { + OPENSSL_armcap_P |= ARMV8_AES; + } + if (hwcap2 & HWCAP2_PMULL) { + OPENSSL_armcap_P |= ARMV8_PMULL; + } + if (hwcap2 & HWCAP2_SHA1) { + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (hwcap2 & HWCAP2_SHA2) { + OPENSSL_armcap_P |= ARMV8_SHA256; + } + } +} + +#endif // OPENSSL_ARM && OPENSSL_OPENBSD && !OPENSSL_STATIC_ARMCAP diff --git a/Sources/CNIOBoringSSL/crypto/dh_extra/dh_asn1.c b/Sources/CNIOBoringSSL/crypto/dh_extra/dh_asn1.c index 987fb1da..f137fe64 100644 --- a/Sources/CNIOBoringSSL/crypto/dh_extra/dh_asn1.c +++ b/Sources/CNIOBoringSSL/crypto/dh_extra/dh_asn1.c @@ -63,6 +63,7 @@ #include #include "../bytestring/internal.h" +#include "../fipsmodule/dh/internal.h" static int parse_integer(CBS *cbs, BIGNUM **out) { diff --git a/Sources/CNIOBoringSSL/crypto/dh_extra/params.c b/Sources/CNIOBoringSSL/crypto/dh_extra/params.c index 735bc18f..33fafa0a 100644 --- a/Sources/CNIOBoringSSL/crypto/dh_extra/params.c +++ b/Sources/CNIOBoringSSL/crypto/dh_extra/params.c @@ -57,6 +57,7 @@ #include #include "../fipsmodule/bn/internal.h" +#include "../fipsmodule/dh/internal.h" static BIGNUM *get_params(BIGNUM *ret, const BN_ULONG *words, size_t num_words) { @@ -452,23 +453,10 @@ static int int_dh_param_copy(DH *to, const DH *from, int is_x942) { return 1; } - if (!int_dh_bn_cpy(&to->q, from->q) || - !int_dh_bn_cpy(&to->j, from->j)) { + if (!int_dh_bn_cpy(&to->q, from->q)) { return 0; } - OPENSSL_free(to->seed); - to->seed = NULL; - to->seedlen = 0; - - if (from->seed) { - to->seed = OPENSSL_memdup(from->seed, from->seedlen); - if (!to->seed) { - return 0; - } - to->seedlen = from->seedlen; - } - return 1; } diff --git a/Sources/CNIOBoringSSL/crypto/dsa/dsa.c b/Sources/CNIOBoringSSL/crypto/dsa/dsa.c index 2503aaba..caab4ecb 100644 --- a/Sources/CNIOBoringSSL/crypto/dsa/dsa.c +++ b/Sources/CNIOBoringSSL/crypto/dsa/dsa.c @@ -74,6 +74,7 @@ #include "internal.h" #include "../fipsmodule/bn/internal.h" +#include "../fipsmodule/dh/internal.h" #include "../internal.h" diff --git a/Sources/CNIOBoringSSL/crypto/ecdsa_extra/ecdsa_asn1.c b/Sources/CNIOBoringSSL/crypto/ecdsa_extra/ecdsa_asn1.c index bd71fa1b..ce38274f 100644 --- a/Sources/CNIOBoringSSL/crypto/ecdsa_extra/ecdsa_asn1.c +++ b/Sources/CNIOBoringSSL/crypto/ecdsa_extra/ecdsa_asn1.c @@ -81,13 +81,11 @@ int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig, } CBB cbb; - CBB_zero(&cbb); + CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)); size_t len; - if (!CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)) || - !ECDSA_SIG_marshal(&cbb, s) || + if (!ECDSA_SIG_marshal(&cbb, s) || !CBB_finish(&cbb, NULL, &len)) { OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR); - CBB_cleanup(&cbb); *sig_len = 0; goto err; } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/check.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/check.c index 9adaa79f..e0c49992 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/check.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/check.c @@ -58,6 +58,8 @@ #include +#include "internal.h" + int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *out_flags) { *out_flags = 0; @@ -165,9 +167,6 @@ int DH_check(const DH *dh, int *out_flags) { if (!BN_is_one(t2)) { *out_flags |= DH_CHECK_INVALID_Q_VALUE; } - if (dh->j && BN_cmp(dh->j, t1)) { - *out_flags |= DH_CHECK_INVALID_J_VALUE; - } } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { l = BN_mod_word(dh->p, 24); if (l == (BN_ULONG)-1) { diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/dh.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/dh.c index b6a184bb..e08fa2c3 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/dh.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/dh.c @@ -101,9 +101,6 @@ void DH_free(DH *dh) { BN_clear_free(dh->p); BN_clear_free(dh->g); BN_clear_free(dh->q); - BN_clear_free(dh->j); - OPENSSL_free(dh->seed); - BN_clear_free(dh->counter); BN_clear_free(dh->pub_key); BN_clear_free(dh->priv_key); CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock); diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/internal.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/internal.h index 68867956..c913c7a2 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/internal.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/dh/internal.h @@ -17,11 +17,31 @@ #include +#include + #if defined(__cplusplus) extern "C" { #endif +struct dh_st { + BIGNUM *p; + BIGNUM *g; + BIGNUM *q; + BIGNUM *pub_key; // g^x mod p + BIGNUM *priv_key; // x + + // priv_length contains the length, in bits, of the private value. If zero, + // the private value will be the same length as |p|. + unsigned priv_length; + + CRYPTO_MUTEX method_mont_p_lock; + BN_MONT_CTX *method_mont_p; + + int flags; + CRYPTO_refcount_t references; +}; + // dh_compute_key_padded_no_self_test does the same as |DH_compute_key_padded|, // but doesn't try to run the self-test first. This is for use in the self tests // themselves, to prevent an infinite loop. diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/internal.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/internal.h index e7d4ff77..8b58bc9a 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/internal.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/internal.h @@ -142,7 +142,7 @@ int rsa_verify_raw_no_self_test(RSA *rsa, size_t *out_len, uint8_t *out, size_t in_len, int padding); int rsa_sign_no_self_test(int hash_nid, const uint8_t *digest, - unsigned digest_len, uint8_t *out, unsigned *out_len, + size_t digest_len, uint8_t *out, unsigned *out_len, RSA *rsa); diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/rsa.c b/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/rsa.c index 49ec35e4..197ed7b8 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/rsa.c +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/rsa/rsa.c @@ -56,6 +56,7 @@ #include +#include #include #include @@ -470,18 +471,43 @@ static const struct pkcs1_sig_prefix kPKCS1SigPrefixes[] = { }, }; -int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, - int *is_alloced, int hash_nid, const uint8_t *digest, - size_t digest_len) { +static int rsa_check_digest_size(int hash_nid, size_t digest_len) { if (hash_nid == NID_md5_sha1) { - // Special case: SSL signature, just check the length. if (digest_len != SSL_SIG_LENGTH) { OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } + return 1; + } + + for (size_t i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) { + const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i]; + if (sig_prefix->nid == hash_nid) { + if (digest_len != sig_prefix->hash_len) { + OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); + return 0; + } + return 1; + } + } + OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return 0; + +} + +int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, + int *is_alloced, int hash_nid, const uint8_t *digest, + size_t digest_len) { + if (!rsa_check_digest_size(hash_nid, digest_len)) { + return 0; + } + + if (hash_nid == NID_md5_sha1) { + // The length should already have been checked. + assert(digest_len == SSL_SIG_LENGTH); *out_msg = (uint8_t *)digest; - *out_msg_len = SSL_SIG_LENGTH; + *out_msg_len = digest_len; *is_alloced = 0; return 1; } @@ -492,11 +518,8 @@ int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, continue; } - if (digest_len != sig_prefix->hash_len) { - OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); - return 0; - } - + // The length should already have been checked. + assert(digest_len == sig_prefix->hash_len); const uint8_t* prefix = sig_prefix->bytes; size_t prefix_len = sig_prefix->len; size_t signed_msg_len = prefix_len + digest_len; @@ -526,19 +549,25 @@ int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, } int rsa_sign_no_self_test(int hash_nid, const uint8_t *digest, - unsigned digest_len, uint8_t *out, unsigned *out_len, + size_t digest_len, uint8_t *out, unsigned *out_len, RSA *rsa) { + if (rsa->meth->sign) { + if (!rsa_check_digest_size(hash_nid, digest_len)) { + return 0; + } + // All supported digest lengths fit in |unsigned|. + assert(digest_len <= EVP_MAX_MD_SIZE); + static_assert(EVP_MAX_MD_SIZE <= UINT_MAX, "digest too long"); + return rsa->meth->sign(hash_nid, digest, (unsigned)digest_len, out, out_len, + rsa); + } + const unsigned rsa_size = RSA_size(rsa); int ret = 0; uint8_t *signed_msg = NULL; size_t signed_msg_len = 0; int signed_msg_is_alloced = 0; size_t size_t_out_len; - - if (rsa->meth->sign) { - return rsa->meth->sign(hash_nid, digest, digest_len, out, out_len, rsa); - } - if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len, &signed_msg_is_alloced, hash_nid, digest, digest_len) || @@ -563,7 +592,7 @@ int rsa_sign_no_self_test(int hash_nid, const uint8_t *digest, return ret; } -int RSA_sign(int hash_nid, const uint8_t *digest, unsigned digest_len, +int RSA_sign(int hash_nid, const uint8_t *digest, size_t digest_len, uint8_t *out, unsigned *out_len, RSA *rsa) { boringssl_ensure_rsa_self_test(); diff --git a/Sources/CNIOBoringSSL/crypto/hpke/hpke.c b/Sources/CNIOBoringSSL/crypto/hpke/hpke.c index ef7e2ac2..35de7ffc 100644 --- a/Sources/CNIOBoringSSL/crypto/hpke/hpke.c +++ b/Sources/CNIOBoringSSL/crypto/hpke/hpke.c @@ -228,6 +228,14 @@ const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256(void) { uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem) { return kem->id; } +size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem) { + return kem->public_key_len; +} + +size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem) { + return kem->private_key_len; +} + size_t EVP_HPKE_KEM_enc_len(const EVP_HPKE_KEM *kem) { return kem->enc_len; } void EVP_HPKE_KEY_zero(EVP_HPKE_KEY *key) { @@ -358,13 +366,11 @@ const EVP_AEAD *EVP_HPKE_AEAD_aead(const EVP_HPKE_AEAD *aead) { static int hpke_build_suite_id(const EVP_HPKE_CTX *ctx, uint8_t out[HPKE_SUITE_ID_LEN]) { CBB cbb; - int ret = CBB_init_fixed(&cbb, out, HPKE_SUITE_ID_LEN) && - add_label_string(&cbb, "HPKE") && // - CBB_add_u16(&cbb, ctx->kem->id) && // - CBB_add_u16(&cbb, ctx->kdf->id) && // - CBB_add_u16(&cbb, ctx->aead->id); - CBB_cleanup(&cbb); - return ret; + CBB_init_fixed(&cbb, out, HPKE_SUITE_ID_LEN); + return add_label_string(&cbb, "HPKE") && // + CBB_add_u16(&cbb, ctx->kem->id) && // + CBB_add_u16(&cbb, ctx->kdf->id) && // + CBB_add_u16(&cbb, ctx->aead->id); } #define HPKE_MODE_BASE 0 @@ -401,8 +407,8 @@ static int hpke_key_schedule(EVP_HPKE_CTX *ctx, const uint8_t *shared_secret, uint8_t context[sizeof(uint8_t) + 2 * EVP_MAX_MD_SIZE]; size_t context_len; CBB context_cbb; - if (!CBB_init_fixed(&context_cbb, context, sizeof(context)) || - !CBB_add_u8(&context_cbb, HPKE_MODE_BASE) || + CBB_init_fixed(&context_cbb, context, sizeof(context)); + if (!CBB_add_u8(&context_cbb, HPKE_MODE_BASE) || !CBB_add_bytes(&context_cbb, psk_id_hash, psk_id_hash_len) || !CBB_add_bytes(&context_cbb, info_hash, info_hash_len) || !CBB_finish(&context_cbb, NULL, &context_len)) { diff --git a/Sources/CNIOBoringSSL/crypto/trust_token/trust_token.c b/Sources/CNIOBoringSSL/crypto/trust_token/trust_token.c index b5deeaa2..2b4024b7 100644 --- a/Sources/CNIOBoringSSL/crypto/trust_token/trust_token.c +++ b/Sources/CNIOBoringSSL/crypto/trust_token/trust_token.c @@ -113,34 +113,26 @@ int TRUST_TOKEN_generate_key(const TRUST_TOKEN_METHOD *method, size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id) { // Prepend the key ID in front of the PMBTokens format. - int ret = 0; CBB priv_cbb, pub_cbb; - CBB_zero(&priv_cbb); - CBB_zero(&pub_cbb); - if (!CBB_init_fixed(&priv_cbb, out_priv_key, max_priv_key_len) || - !CBB_init_fixed(&pub_cbb, out_pub_key, max_pub_key_len) || - !CBB_add_u32(&priv_cbb, id) || + CBB_init_fixed(&priv_cbb, out_priv_key, max_priv_key_len); + CBB_init_fixed(&pub_cbb, out_pub_key, max_pub_key_len); + if (!CBB_add_u32(&priv_cbb, id) || // !CBB_add_u32(&pub_cbb, id)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); - goto err; + return 0; } if (!method->generate_key(&priv_cbb, &pub_cbb)) { - goto err; + return 0; } if (!CBB_finish(&priv_cbb, NULL, out_priv_key_len) || !CBB_finish(&pub_cbb, NULL, out_pub_key_len)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); - goto err; + return 0; } - ret = 1; - -err: - CBB_cleanup(&priv_cbb); - CBB_cleanup(&pub_cbb); - return ret; + return 1; } int TRUST_TOKEN_derive_key_from_secret( @@ -149,35 +141,27 @@ int TRUST_TOKEN_derive_key_from_secret( size_t *out_pub_key_len, size_t max_pub_key_len, uint32_t id, const uint8_t *secret, size_t secret_len) { // Prepend the key ID in front of the PMBTokens format. - int ret = 0; CBB priv_cbb, pub_cbb; - CBB_zero(&priv_cbb); - CBB_zero(&pub_cbb); - if (!CBB_init_fixed(&priv_cbb, out_priv_key, max_priv_key_len) || - !CBB_init_fixed(&pub_cbb, out_pub_key, max_pub_key_len) || - !CBB_add_u32(&priv_cbb, id) || + CBB_init_fixed(&priv_cbb, out_priv_key, max_priv_key_len); + CBB_init_fixed(&pub_cbb, out_pub_key, max_pub_key_len); + if (!CBB_add_u32(&priv_cbb, id) || // !CBB_add_u32(&pub_cbb, id)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); - goto err; + return 0; } if (!method->derive_key_from_secret(&priv_cbb, &pub_cbb, secret, secret_len)) { - goto err; + return 0; } if (!CBB_finish(&priv_cbb, NULL, out_priv_key_len) || !CBB_finish(&pub_cbb, NULL, out_pub_key_len)) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_BUFFER_TOO_SMALL); - goto err; + return 0; } - ret = 1; - -err: - CBB_cleanup(&priv_cbb); - CBB_cleanup(&pub_cbb); - return ret; + return 1; } TRUST_TOKEN_CLIENT *TRUST_TOKEN_CLIENT_new(const TRUST_TOKEN_METHOD *method, diff --git a/Sources/CNIOBoringSSL/crypto/x509/x_all.c b/Sources/CNIOBoringSSL/crypto/x509/x_all.c index b9238726..cf6b1509 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/x_all.c +++ b/Sources/CNIOBoringSSL/crypto/x509/x_all.c @@ -96,11 +96,13 @@ int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) { } int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { + x->req_info->enc.modified = 1; return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, x->signature, x->req_info, pkey, md)); } int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) { + x->req_info->enc.modified = 1; return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL, x->signature, x->req_info, ctx); } diff --git a/Sources/CNIOBoringSSL/hash.txt b/Sources/CNIOBoringSSL/hash.txt index 4b06eeff..ef533e98 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 cab31f65f1ad6e6daca62e95b25dd6cd805fce0b +This directory is derived from BoringSSL cloned from https://boringssl.googlesource.com/boringssl at revision b819f7e9392d25db6705a6bd3c92be3bb91775e2 diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h index f2392007..19874334 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h @@ -469,9 +469,11 @@ #define CBB_add_asn1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1) #define CBB_add_asn1_bool BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_bool) #define CBB_add_asn1_int64 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_int64) +#define CBB_add_asn1_int64_with_tag BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_int64_with_tag) #define CBB_add_asn1_octet_string BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_octet_string) #define CBB_add_asn1_oid_from_text BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_oid_from_text) #define CBB_add_asn1_uint64 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_uint64) +#define CBB_add_asn1_uint64_with_tag BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_asn1_uint64_with_tag) #define CBB_add_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_bytes) #define CBB_add_space BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_space) #define CBB_add_u16 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CBB_add_u16) @@ -1027,6 +1029,8 @@ #define EVP_HPKE_KDF_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KDF_id) #define EVP_HPKE_KEM_enc_len BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEM_enc_len) #define EVP_HPKE_KEM_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEM_id) +#define EVP_HPKE_KEM_private_key_len BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEM_private_key_len) +#define EVP_HPKE_KEM_public_key_len BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEM_public_key_len) #define EVP_HPKE_KEY_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEY_cleanup) #define EVP_HPKE_KEY_copy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEY_copy) #define EVP_HPKE_KEY_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_KEY_free) @@ -2230,7 +2234,6 @@ #define USERNOTICE_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, USERNOTICE_free) #define USERNOTICE_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, USERNOTICE_it) #define USERNOTICE_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, USERNOTICE_new) -#define UTF8_putc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, UTF8_putc) #define X25519 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X25519) #define X25519_keypair BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X25519_keypair) #define X25519_public_from_private BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X25519_public_from_private) diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h index d61a8a94..41647ac4 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h @@ -474,9 +474,11 @@ #define _CBB_add_asn1 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1) #define _CBB_add_asn1_bool BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_bool) #define _CBB_add_asn1_int64 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_int64) +#define _CBB_add_asn1_int64_with_tag BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_int64_with_tag) #define _CBB_add_asn1_octet_string BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_octet_string) #define _CBB_add_asn1_oid_from_text BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_oid_from_text) #define _CBB_add_asn1_uint64 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_uint64) +#define _CBB_add_asn1_uint64_with_tag BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_asn1_uint64_with_tag) #define _CBB_add_bytes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_bytes) #define _CBB_add_space BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_space) #define _CBB_add_u16 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, CBB_add_u16) @@ -1032,6 +1034,8 @@ #define _EVP_HPKE_KDF_id BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KDF_id) #define _EVP_HPKE_KEM_enc_len BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEM_enc_len) #define _EVP_HPKE_KEM_id BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEM_id) +#define _EVP_HPKE_KEM_private_key_len BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEM_private_key_len) +#define _EVP_HPKE_KEM_public_key_len BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEM_public_key_len) #define _EVP_HPKE_KEY_cleanup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEY_cleanup) #define _EVP_HPKE_KEY_copy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEY_copy) #define _EVP_HPKE_KEY_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_HPKE_KEY_free) @@ -2235,7 +2239,6 @@ #define _USERNOTICE_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, USERNOTICE_free) #define _USERNOTICE_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, USERNOTICE_it) #define _USERNOTICE_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, USERNOTICE_new) -#define _UTF8_putc BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, UTF8_putc) #define _X25519 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X25519) #define _X25519_keypair BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X25519_keypair) #define _X25519_public_from_private BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, X25519_public_from_private) diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_bytestring.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_bytestring.h index d6a7a3a7..c2a91b55 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_bytestring.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_bytestring.h @@ -391,28 +391,40 @@ OPENSSL_EXPORT int CBS_parse_utc_time(const CBS *cbs, struct tm *out_tm, struct cbb_buffer_st { uint8_t *buf; - size_t len; // The number of valid bytes. - size_t cap; // The size of buf. - char can_resize; /* One iff |buf| is owned by this object. If not then |buf| - cannot be resized. */ - char error; /* One iff there was an error writing to this CBB. All future - operations will fail. */ + // len is the number of valid bytes in |buf|. + size_t len; + // cap is the size of |buf|. + size_t cap; + // can_resize is one iff |buf| is owned by this object. If not then |buf| + // cannot be resized. + unsigned can_resize : 1; + // error is one if there was an error writing to this CBB. All future + // operations will fail. + unsigned error : 1; }; -struct cbb_st { +struct cbb_child_st { + // base is a pointer to the buffer this |CBB| writes to. struct cbb_buffer_st *base; - // child points to a child CBB if a length-prefix is pending. - CBB *child; // offset is the number of bytes from the start of |base->buf| to this |CBB|'s // pending length prefix. size_t offset; // pending_len_len contains the number of bytes in this |CBB|'s pending // length-prefix, or zero if no length-prefix is pending. uint8_t pending_len_len; - char pending_is_asn1; - // is_child is true iff this is a child |CBB| (as opposed to a top-level - // |CBB|). Top-level objects are valid arguments for |CBB_finish|. + unsigned pending_is_asn1 : 1; +}; + +struct cbb_st { + // child points to a child CBB if a length-prefix is pending. + CBB *child; + // is_child is one if this is a child |CBB| and zero if it is a top-level + // |CBB|. This determines which arm of the union is valid. char is_child; + union { + struct cbb_buffer_st base; + struct cbb_child_st child; + } u; }; // CBB_zero sets an uninitialised |cbb| to the zero state. It must be @@ -428,7 +440,8 @@ OPENSSL_EXPORT int CBB_init(CBB *cbb, size_t initial_capacity); // CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since // |buf| cannot grow, trying to write more than |len| bytes will cause CBB -// functions to fail. It returns one on success or zero on error. +// functions to fail. This function is infallible and always returns one. It is +// safe, but not necessary, to call |CBB_cleanup| on |cbb|. OPENSSL_EXPORT int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); // CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects @@ -557,11 +570,23 @@ OPENSSL_EXPORT void CBB_discard_child(CBB *cbb); // error. OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); +// CBB_add_asn1_uint64_with_tag behaves like |CBB_add_asn1_uint64| but uses +// |tag| as the tag instead of INTEGER. This is useful if the INTEGER type uses +// implicit tagging. +OPENSSL_EXPORT int CBB_add_asn1_uint64_with_tag(CBB *cbb, uint64_t value, + unsigned tag); + // CBB_add_asn1_int64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| // and writes |value| in its contents. It returns one on success and zero on // error. OPENSSL_EXPORT int CBB_add_asn1_int64(CBB *cbb, int64_t value); +// CBB_add_asn1_int64_with_tag behaves like |CBB_add_asn1_int64| but uses |tag| +// as the tag instead of INTEGER. This is useful if the INTEGER type uses +// implicit tagging. +OPENSSL_EXPORT int CBB_add_asn1_int64_with_tag(CBB *cbb, int64_t value, + unsigned tag); + // CBB_add_asn1_octet_string writes an ASN.1 OCTET STRING into |cbb| with the // given contents. It returns one on success and zero on error. OPENSSL_EXPORT int CBB_add_asn1_octet_string(CBB *cbb, const uint8_t *data, diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_dh.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_dh.h index bef7749d..92debe37 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_dh.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_dh.h @@ -244,7 +244,6 @@ OPENSSL_EXPORT unsigned DH_num_bits(const DH *dh); #define DH_CHECK_NOT_SUITABLE_GENERATOR 0x08 #define DH_CHECK_Q_NOT_PRIME 0x10 #define DH_CHECK_INVALID_Q_VALUE 0x20 -#define DH_CHECK_INVALID_J_VALUE 0x40 // These are compatibility defines. #define DH_NOT_SUITABLE_GENERATOR DH_CHECK_NOT_SUITABLE_GENERATOR @@ -330,31 +329,6 @@ OPENSSL_EXPORT int DH_compute_key(uint8_t *out, const BIGNUM *peers_key, DH *dh); -struct dh_st { - BIGNUM *p; - BIGNUM *g; - BIGNUM *pub_key; // g^x mod p - BIGNUM *priv_key; // x - - // priv_length contains the length, in bits, of the private value. If zero, - // the private value will be the same length as |p|. - unsigned priv_length; - - CRYPTO_MUTEX method_mont_p_lock; - BN_MONT_CTX *method_mont_p; - - // Place holders if we want to do X9.42 DH - BIGNUM *q; - BIGNUM *j; - unsigned char *seed; - int seedlen; - BIGNUM *counter; - - int flags; - CRYPTO_refcount_t references; -}; - - #if defined(__cplusplus) } // extern C diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_hpke.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_hpke.h index 7bcfeab5..4e454a7a 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_hpke.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_hpke.h @@ -51,8 +51,24 @@ OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256(void); // will be one of the |EVP_HPKE_KEM_*| constants. OPENSSL_EXPORT uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem); +// EVP_HPKE_MAX_PUBLIC_KEY_LENGTH is the maximum length of an encoded public key +// for all KEMs currently supported by this library. +#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 32 + +// EVP_HPKE_KEM_public_key_len returns the length of a public key for |kem|. +// This value will be at most |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH|. +OPENSSL_EXPORT size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem); + +// EVP_HPKE_MAX_PRIVATE_KEY_LENGTH is the maximum length of an encoded private +// key for all KEMs currently supported by this library. +#define EVP_HPKE_MAX_PRIVATE_KEY_LENGTH 32 + +// EVP_HPKE_KEM_private_key_len returns the length of a private key for |kem|. +// This value will be at most |EVP_HPKE_MAX_PRIVATE_KEY_LENGTH|. +OPENSSL_EXPORT size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem); + // EVP_HPKE_MAX_ENC_LENGTH is the maximum length of "enc", the encapsulated -// shared secret, for all supported KEMs in this library. +// shared secret, for all KEMs currently supported by this library. #define EVP_HPKE_MAX_ENC_LENGTH 32 // EVP_HPKE_KEM_enc_len returns the length of the "enc", the encapsulated shared @@ -140,28 +156,22 @@ OPENSSL_EXPORT int EVP_HPKE_KEY_generate(EVP_HPKE_KEY *key, // EVP_HPKE_KEY_kem returns the HPKE KEM used by |key|. OPENSSL_EXPORT const EVP_HPKE_KEM *EVP_HPKE_KEY_kem(const EVP_HPKE_KEY *key); -// EVP_HPKE_MAX_PUBLIC_KEY_LENGTH is the maximum length of a public key for all -// KEMs supported by this library. -#define EVP_HPKE_MAX_PUBLIC_KEY_LENGTH 32 - // EVP_HPKE_KEY_public_key writes |key|'s public key to |out| and sets // |*out_len| to the number of bytes written. On success, it returns one and // writes at most |max_out| bytes. If |max_out| is too small, it returns zero. // Setting |max_out| to |EVP_HPKE_MAX_PUBLIC_KEY_LENGTH| will ensure the public -// key fits. +// key fits. An exact size can also be determined by +// |EVP_HPKE_KEM_public_key_len|. OPENSSL_EXPORT int EVP_HPKE_KEY_public_key(const EVP_HPKE_KEY *key, uint8_t *out, size_t *out_len, size_t max_out); -// EVP_HPKE_MAX_PRIVATE_KEY_LENGTH is the maximum length of a private key for -// all KEMs supported by this library. -#define EVP_HPKE_MAX_PRIVATE_KEY_LENGTH 32 - // EVP_HPKE_KEY_private_key writes |key|'s private key to |out| and sets // |*out_len| to the number of bytes written. On success, it returns one and // writes at most |max_out| bytes. If |max_out| is too small, it returns zero. // Setting |max_out| to |EVP_HPKE_MAX_PRIVATE_KEY_LENGTH| will ensure the -// private key fits. +// private key fits. An exact size can also be determined by +// |EVP_HPKE_KEM_private_key_len|. OPENSSL_EXPORT int EVP_HPKE_KEY_private_key(const EVP_HPKE_KEY *key, uint8_t *out, size_t *out_len, size_t max_out); diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_rsa.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_rsa.h index e6966cbf..2fa076ac 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_rsa.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_rsa.h @@ -298,8 +298,8 @@ OPENSSL_EXPORT int RSA_private_decrypt(size_t flen, const uint8_t *from, // |hash_nid|. Passing unhashed inputs will not result in a secure signature // scheme. OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *digest, - unsigned digest_len, uint8_t *out, - unsigned *out_len, RSA *rsa); + size_t digest_len, uint8_t *out, unsigned *out_len, + RSA *rsa); // RSA_sign_pss_mgf1 signs |digest_len| bytes from |digest| with the public key // from |rsa| using RSASSA-PSS with MGF1 as the mask generation function. It @@ -625,7 +625,7 @@ OPENSSL_EXPORT int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); // should use instead. It returns NULL on error, or a newly-allocated |RSA| on // success. This function is provided for compatibility only. The |callback| // and |cb_arg| parameters must be NULL. -OPENSSL_EXPORT RSA *RSA_generate_key(int bits, unsigned long e, void *callback, +OPENSSL_EXPORT RSA *RSA_generate_key(int bits, uint64_t e, void *callback, void *cb_arg); // d2i_RSAPublicKey parses a DER-encoded RSAPublicKey structure (RFC 8017) from diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h index 275cc84c..52359030 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h @@ -3931,13 +3931,14 @@ OPENSSL_EXPORT int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv, const uint8_t **out_write_iv, size_t *out_iv_len); -// SSL_get_key_block_len returns the length of |ssl|'s key block. It is an error -// to call this function during a handshake. +// SSL_get_key_block_len returns the length of |ssl|'s key block, for TLS 1.2 +// and below. It is an error to call this function during a handshake, or if +// |ssl| negotiated TLS 1.3. OPENSSL_EXPORT size_t SSL_get_key_block_len(const SSL *ssl); // SSL_generate_key_block generates |out_len| bytes of key material for |ssl|'s -// current connection state. It is an error to call this function during a -// handshake. +// current connection state, for TLS 1.2 and below. It is an error to call this +// function during a handshake, or if |ssl| negotiated TLS 1.3. OPENSSL_EXPORT int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len); @@ -5353,62 +5354,6 @@ BORINGSSL_MAKE_UP_REF(SSL_ECH_KEYS, SSL_ECH_KEYS_up_ref) BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free) BORINGSSL_MAKE_UP_REF(SSL_SESSION, SSL_SESSION_up_ref) -enum class OpenRecordResult { - kOK, - kDiscard, - kIncompleteRecord, - kAlertCloseNotify, - kError, -}; - -// *** EXPERIMENTAL -- DO NOT USE *** -// -// OpenRecord decrypts the first complete SSL record from |in| in-place, sets -// |out| to the decrypted application data, and |out_record_len| to the length -// of the encrypted record. Returns: -// - kOK if an application-data record was successfully decrypted and verified. -// - kDiscard if a record was sucessfully processed, but should be discarded. -// - kIncompleteRecord if |in| did not contain a complete record. -// - kAlertCloseNotify if a record was successfully processed but is a -// close_notify alert. -// - kError if an error occurred or the record is invalid. |*out_alert| will be -// set to an alert to emit, or zero if no alert should be emitted. -OPENSSL_EXPORT OpenRecordResult OpenRecord(SSL *ssl, Span *out, - size_t *out_record_len, - uint8_t *out_alert, - Span in); - -OPENSSL_EXPORT size_t SealRecordPrefixLen(const SSL *ssl, size_t plaintext_len); - -// SealRecordSuffixLen returns the length of the suffix written by |SealRecord|. -// -// |plaintext_len| must be equal to the size of the plaintext passed to -// |SealRecord|. -// -// |plaintext_len| must not exceed |SSL3_RT_MAX_PLAINTEXT_LENGTH|. The returned -// suffix length will not exceed |SSL3_RT_MAX_ENCRYPTED_OVERHEAD|. -OPENSSL_EXPORT size_t SealRecordSuffixLen(const SSL *ssl, size_t plaintext_len); - -// *** EXPERIMENTAL -- DO NOT USE *** -// -// SealRecord encrypts the cleartext of |in| and scatters the resulting TLS -// application data record between |out_prefix|, |out|, and |out_suffix|. It -// returns true on success or false if an error occurred. -// -// The length of |out_prefix| must equal |SealRecordPrefixLen|. The length of -// |out| must equal the length of |in|, which must not exceed -// |SSL3_RT_MAX_PLAINTEXT_LENGTH|. The length of |out_suffix| must equal -// |SealRecordSuffixLen|. -// -// If enabled, |SealRecord| may perform TLS 1.0 CBC 1/n-1 record splitting. -// |SealRecordPrefixLen| accounts for the required overhead if that is the case. -// -// |out| may equal |in| to encrypt in-place but may not otherwise alias. -// |out_prefix| and |out_suffix| may not alias anything. -OPENSSL_EXPORT bool SealRecord(SSL *ssl, Span out_prefix, - Span out, Span out_suffix, - Span in); - // *** EXPERIMENTAL — DO NOT USE WITHOUT CHECKING *** // diff --git a/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc b/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc index 82a386e3..66ea9016 100644 --- a/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc +++ b/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc @@ -466,9 +466,11 @@ %xdefine _CBB_add_asn1 _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1 %xdefine _CBB_add_asn1_bool _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_bool %xdefine _CBB_add_asn1_int64 _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_int64 +%xdefine _CBB_add_asn1_int64_with_tag _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_int64_with_tag %xdefine _CBB_add_asn1_octet_string _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_octet_string %xdefine _CBB_add_asn1_oid_from_text _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_oid_from_text %xdefine _CBB_add_asn1_uint64 _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_uint64 +%xdefine _CBB_add_asn1_uint64_with_tag _ %+ BORINGSSL_PREFIX %+ _CBB_add_asn1_uint64_with_tag %xdefine _CBB_add_bytes _ %+ BORINGSSL_PREFIX %+ _CBB_add_bytes %xdefine _CBB_add_space _ %+ BORINGSSL_PREFIX %+ _CBB_add_space %xdefine _CBB_add_u16 _ %+ BORINGSSL_PREFIX %+ _CBB_add_u16 @@ -1025,6 +1027,8 @@ %xdefine _EVP_HPKE_KDF_id _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KDF_id %xdefine _EVP_HPKE_KEM_enc_len _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_enc_len %xdefine _EVP_HPKE_KEM_id _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_id +%xdefine _EVP_HPKE_KEM_private_key_len _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_private_key_len +%xdefine _EVP_HPKE_KEM_public_key_len _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_public_key_len %xdefine _EVP_HPKE_KEY_cleanup _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_cleanup %xdefine _EVP_HPKE_KEY_copy _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_copy %xdefine _EVP_HPKE_KEY_free _ %+ BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_free @@ -2228,7 +2232,6 @@ %xdefine _USERNOTICE_free _ %+ BORINGSSL_PREFIX %+ _USERNOTICE_free %xdefine _USERNOTICE_it _ %+ BORINGSSL_PREFIX %+ _USERNOTICE_it %xdefine _USERNOTICE_new _ %+ BORINGSSL_PREFIX %+ _USERNOTICE_new -%xdefine _UTF8_putc _ %+ BORINGSSL_PREFIX %+ _UTF8_putc %xdefine _X25519 _ %+ BORINGSSL_PREFIX %+ _X25519 %xdefine _X25519_keypair _ %+ BORINGSSL_PREFIX %+ _X25519_keypair %xdefine _X25519_public_from_private _ %+ BORINGSSL_PREFIX %+ _X25519_public_from_private @@ -3935,9 +3938,11 @@ %xdefine CBB_add_asn1 BORINGSSL_PREFIX %+ _CBB_add_asn1 %xdefine CBB_add_asn1_bool BORINGSSL_PREFIX %+ _CBB_add_asn1_bool %xdefine CBB_add_asn1_int64 BORINGSSL_PREFIX %+ _CBB_add_asn1_int64 +%xdefine CBB_add_asn1_int64_with_tag BORINGSSL_PREFIX %+ _CBB_add_asn1_int64_with_tag %xdefine CBB_add_asn1_octet_string BORINGSSL_PREFIX %+ _CBB_add_asn1_octet_string %xdefine CBB_add_asn1_oid_from_text BORINGSSL_PREFIX %+ _CBB_add_asn1_oid_from_text %xdefine CBB_add_asn1_uint64 BORINGSSL_PREFIX %+ _CBB_add_asn1_uint64 +%xdefine CBB_add_asn1_uint64_with_tag BORINGSSL_PREFIX %+ _CBB_add_asn1_uint64_with_tag %xdefine CBB_add_bytes BORINGSSL_PREFIX %+ _CBB_add_bytes %xdefine CBB_add_space BORINGSSL_PREFIX %+ _CBB_add_space %xdefine CBB_add_u16 BORINGSSL_PREFIX %+ _CBB_add_u16 @@ -4494,6 +4499,8 @@ %xdefine EVP_HPKE_KDF_id BORINGSSL_PREFIX %+ _EVP_HPKE_KDF_id %xdefine EVP_HPKE_KEM_enc_len BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_enc_len %xdefine EVP_HPKE_KEM_id BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_id +%xdefine EVP_HPKE_KEM_private_key_len BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_private_key_len +%xdefine EVP_HPKE_KEM_public_key_len BORINGSSL_PREFIX %+ _EVP_HPKE_KEM_public_key_len %xdefine EVP_HPKE_KEY_cleanup BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_cleanup %xdefine EVP_HPKE_KEY_copy BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_copy %xdefine EVP_HPKE_KEY_free BORINGSSL_PREFIX %+ _EVP_HPKE_KEY_free @@ -5697,7 +5704,6 @@ %xdefine USERNOTICE_free BORINGSSL_PREFIX %+ _USERNOTICE_free %xdefine USERNOTICE_it BORINGSSL_PREFIX %+ _USERNOTICE_it %xdefine USERNOTICE_new BORINGSSL_PREFIX %+ _USERNOTICE_new -%xdefine UTF8_putc BORINGSSL_PREFIX %+ _UTF8_putc %xdefine X25519 BORINGSSL_PREFIX %+ _X25519 %xdefine X25519_keypair BORINGSSL_PREFIX %+ _X25519_keypair %xdefine X25519_public_from_private BORINGSSL_PREFIX %+ _X25519_public_from_private diff --git a/Sources/CNIOBoringSSL/ssl/dtls_method.cc b/Sources/CNIOBoringSSL/ssl/dtls_method.cc index 4fbb2cea..f8d16fad 100644 --- a/Sources/CNIOBoringSSL/ssl/dtls_method.cc +++ b/Sources/CNIOBoringSSL/ssl/dtls_method.cc @@ -90,7 +90,7 @@ static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level, ssl->d1->r_epoch++; OPENSSL_memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap)); - OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence)); + ssl->s3->read_sequence = 0; ssl->s3->aead_read_ctx = std::move(aead_ctx); ssl->s3->read_level = level; @@ -103,9 +103,8 @@ static bool dtls1_set_write_state(SSL *ssl, ssl_encryption_level_t level, Span secret_for_quic) { assert(secret_for_quic.empty()); // QUIC does not use DTLS. ssl->d1->w_epoch++; - OPENSSL_memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence, - sizeof(ssl->s3->write_sequence)); - OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence)); + ssl->d1->last_write_sequence = ssl->s3->write_sequence; + ssl->s3->write_sequence = 0; ssl->d1->last_aead_write_ctx = std::move(ssl->s3->aead_write_ctx); ssl->s3->aead_write_ctx = std::move(aead_ctx); diff --git a/Sources/CNIOBoringSSL/ssl/dtls_record.cc b/Sources/CNIOBoringSSL/ssl/dtls_record.cc index 4b4fef3e..15116688 100644 --- a/Sources/CNIOBoringSSL/ssl/dtls_record.cc +++ b/Sources/CNIOBoringSSL/ssl/dtls_record.cc @@ -123,52 +123,37 @@ BSSL_NAMESPACE_BEGIN -// to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as -// a |uint64_t|. -static uint64_t to_u64_be(const uint8_t in[8]) { - uint64_t ret = 0; - unsigned i; - for (i = 0; i < 8; i++) { - ret <<= 8; - ret |= in[i]; - } - return ret; -} - // dtls1_bitmap_should_discard returns one if |seq_num| has been seen in // |bitmap| or is stale. Otherwise it returns zero. static bool dtls1_bitmap_should_discard(DTLS1_BITMAP *bitmap, - const uint8_t seq_num[8]) { + uint64_t seq_num) { const unsigned kWindowSize = sizeof(bitmap->map) * 8; - uint64_t seq_num_u = to_u64_be(seq_num); - if (seq_num_u > bitmap->max_seq_num) { + if (seq_num > bitmap->max_seq_num) { return false; } - uint64_t idx = bitmap->max_seq_num - seq_num_u; + uint64_t idx = bitmap->max_seq_num - seq_num; return idx >= kWindowSize || (bitmap->map & (((uint64_t)1) << idx)); } // dtls1_bitmap_record updates |bitmap| to record receipt of sequence number // |seq_num|. It slides the window forward if needed. It is an error to call // this function on a stale sequence number. -static void dtls1_bitmap_record(DTLS1_BITMAP *bitmap, - const uint8_t seq_num[8]) { +static void dtls1_bitmap_record(DTLS1_BITMAP *bitmap, uint64_t seq_num) { const unsigned kWindowSize = sizeof(bitmap->map) * 8; - uint64_t seq_num_u = to_u64_be(seq_num); // Shift the window if necessary. - if (seq_num_u > bitmap->max_seq_num) { - uint64_t shift = seq_num_u - bitmap->max_seq_num; + if (seq_num > bitmap->max_seq_num) { + uint64_t shift = seq_num - bitmap->max_seq_num; if (shift >= kWindowSize) { bitmap->map = 0; } else { bitmap->map <<= shift; } - bitmap->max_seq_num = seq_num_u; + bitmap->max_seq_num = seq_num; } - uint64_t idx = bitmap->max_seq_num - seq_num_u; + uint64_t idx = bitmap->max_seq_num - seq_num; if (idx < kWindowSize) { bitmap->map |= ((uint64_t)1) << idx; } @@ -192,11 +177,11 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, // Decode the record. uint8_t type; uint16_t version; - uint8_t sequence[8]; + uint8_t sequence_bytes[8]; CBS body; if (!CBS_get_u8(&cbs, &type) || !CBS_get_u16(&cbs, &version) || - !CBS_copy_bytes(&cbs, sequence, 8) || + !CBS_copy_bytes(&cbs, sequence_bytes, sizeof(sequence_bytes)) || !CBS_get_u16_length_prefixed(&cbs, &body) || CBS_len(&body) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { // The record header was incomplete or malformed. Drop the entire packet. @@ -222,7 +207,8 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, Span header = in.subspan(0, DTLS1_RT_HEADER_LENGTH); ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, header); - uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1]; + uint64_t sequence = CRYPTO_load_u64_be(sequence_bytes); + uint16_t epoch = static_cast(sequence >> 48); if (epoch != ssl->d1->r_epoch || dtls1_bitmap_should_discard(&ssl->d1->bitmap, sequence)) { // Drop this record. It's from the wrong epoch or is a replay. Note that if @@ -304,12 +290,12 @@ bool dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, // Determine the parameters for the current epoch. uint16_t epoch = ssl->d1->w_epoch; SSLAEADContext *aead = ssl->s3->aead_write_ctx.get(); - uint8_t *seq = ssl->s3->write_sequence; + uint64_t *seq = &ssl->s3->write_sequence; if (use_epoch == dtls1_use_previous_epoch) { assert(ssl->d1->w_epoch >= 1); epoch = ssl->d1->w_epoch - 1; aead = ssl->d1->last_aead_write_ctx.get(); - seq = ssl->d1->last_write_sequence; + seq = &ssl->d1->last_write_sequence; } if (max_out < DTLS1_RT_HEADER_LENGTH) { @@ -323,9 +309,15 @@ bool dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, out[1] = record_version >> 8; out[2] = record_version & 0xff; - out[3] = epoch >> 8; - out[4] = epoch & 0xff; - OPENSSL_memcpy(&out[5], &seq[2], 6); + // Ensure the sequence number update does not overflow. + const uint64_t kMaxSequenceNumber = (uint64_t{1} << 48) - 1; + if (*seq + 1 > kMaxSequenceNumber) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return false; + } + + uint64_t seq_with_epoch = (uint64_t{epoch} << 48) | *seq; + CRYPTO_store_u64_be(&out[3], seq_with_epoch); size_t ciphertext_len; if (!aead->CiphertextLen(&ciphertext_len, in_len, 0)) { @@ -339,12 +331,12 @@ bool dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, size_t len_copy; if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &len_copy, max_out - DTLS1_RT_HEADER_LENGTH, type, record_version, - &out[3] /* seq */, header, in, in_len) || - !ssl_record_sequence_update(&seq[2], 6)) { + seq_with_epoch, header, in, in_len)) { return false; } assert(ciphertext_len == len_copy); + (*seq)++; *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len; ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header); return true; diff --git a/Sources/CNIOBoringSSL/ssl/handoff.cc b/Sources/CNIOBoringSSL/ssl/handoff.cc index 9b9650c4..6656b77c 100644 --- a/Sources/CNIOBoringSSL/ssl/handoff.cc +++ b/Sources/CNIOBoringSSL/ssl/handoff.cc @@ -17,6 +17,7 @@ #include #include +#include "../crypto/internal.h" #include "internal.h" @@ -338,14 +339,16 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) { } else { session = s3->session_reused ? ssl->session.get() : hs->new_session.get(); } + uint8_t read_sequence[8], write_sequence[8]; + CRYPTO_store_u64_be(read_sequence, s3->read_sequence); + CRYPTO_store_u64_be(write_sequence, s3->write_sequence); static const uint8_t kUnusedChannelID[64] = {0}; if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&seq, kHandbackVersion) || !CBB_add_asn1_uint64(&seq, type) || - !CBB_add_asn1_octet_string(&seq, s3->read_sequence, - sizeof(s3->read_sequence)) || - !CBB_add_asn1_octet_string(&seq, s3->write_sequence, - sizeof(s3->write_sequence)) || + !CBB_add_asn1_octet_string(&seq, read_sequence, sizeof(read_sequence)) || + !CBB_add_asn1_octet_string(&seq, write_sequence, + sizeof(write_sequence)) || !CBB_add_asn1_octet_string(&seq, s3->server_random, sizeof(s3->server_random)) || !CBB_add_asn1_octet_string(&seq, s3->client_random, @@ -366,7 +369,7 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) { sizeof(kUnusedChannelID)) || // These two fields were historically |token_binding_negotiated| and // |negotiated_token_binding_param|. - !CBB_add_asn1_bool(&seq, 0) || + !CBB_add_asn1_bool(&seq, 0) || // !CBB_add_asn1_uint64(&seq, 0) || !CBB_add_asn1_bool(&seq, s3->hs->next_proto_neg_seen) || !CBB_add_asn1_bool(&seq, s3->hs->cert_request) || @@ -694,11 +697,13 @@ bool SSL_apply_handback(SSL *ssl, Span handback) { } break; } - if (!CopyExact({s3->read_sequence, sizeof(s3->read_sequence)}, &read_seq) || - !CopyExact({s3->write_sequence, sizeof(s3->write_sequence)}, - &write_seq)) { + uint8_t read_sequence[8], write_sequence[8]; + if (!CopyExact(read_sequence, &read_seq) || + !CopyExact(write_sequence, &write_seq)) { return false; } + s3->read_sequence = CRYPTO_load_u64_be(read_sequence); + s3->write_sequence = CRYPTO_load_u64_be(write_sequence); if (type == handback_after_ecdhe && (hs->key_shares[0] = SSLKeyShare::Create(&key_share)) == nullptr) { return false; diff --git a/Sources/CNIOBoringSSL/ssl/internal.h b/Sources/CNIOBoringSSL/ssl/internal.h index 71edbf32..54c9e0f8 100644 --- a/Sources/CNIOBoringSSL/ssl/internal.h +++ b/Sources/CNIOBoringSSL/ssl/internal.h @@ -829,15 +829,14 @@ class SSLAEADContext { // to the plaintext in |in| and returns true. Otherwise, it returns // false. The output will always be |ExplicitNonceLen| bytes ahead of |in|. bool Open(Span *out, uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], Span header, - Span in); + uint64_t seqnum, Span header, Span in); // Seal encrypts and authenticates |in_len| bytes from |in| and writes the // result to |out|. It returns true on success and false on error. // // If |in| and |out| alias then |out| + |ExplicitNonceLen| must be == |in|. bool Seal(uint8_t *out, size_t *out_len, size_t max_out, uint8_t type, - uint16_t record_version, const uint8_t seqnum[8], + uint16_t record_version, uint64_t seqnum, Span header, const uint8_t *in, size_t in_len); // SealScatter encrypts and authenticates |in_len| bytes from |in| and splits @@ -856,10 +855,9 @@ class SSLAEADContext { // If |in| and |out| alias then |out| must be == |in|. Other arguments may not // alias anything. bool SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix, - uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], Span header, - const uint8_t *in, size_t in_len, const uint8_t *extra_in, - size_t extra_in_len); + uint8_t type, uint16_t record_version, uint64_t seqnum, + Span header, const uint8_t *in, size_t in_len, + const uint8_t *extra_in, size_t extra_in_len); bool GetIV(const uint8_t **out_iv, size_t *out_iv_len) const; @@ -868,8 +866,7 @@ class SSLAEADContext { // necessary. Span GetAdditionalData(uint8_t storage[13], uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], - size_t plaintext_len, + uint64_t seqnum, size_t plaintext_len, Span header); const SSL_CIPHER *cipher_; @@ -916,10 +913,6 @@ struct DTLS1_BITMAP { // Record layer. -// ssl_record_sequence_update increments the sequence number in |seq|. It -// returns true on success and false on wraparound. -bool ssl_record_sequence_update(uint8_t *seq, size_t seq_len); - // ssl_record_prefix_len returns the length of the prefix before the ciphertext // of a record for |ssl|. // @@ -2644,8 +2637,8 @@ struct SSL3_STATE { SSL3_STATE(); ~SSL3_STATE(); - uint8_t read_sequence[8] = {0}; - uint8_t write_sequence[8] = {0}; + uint64_t read_sequence = 0; + uint64_t write_sequence = 0; uint8_t server_random[SSL3_RANDOM_SIZE] = {0}; uint8_t client_random[SSL3_RANDOM_SIZE] = {0}; @@ -2935,7 +2928,7 @@ struct DTLS1_STATE { uint16_t handshake_read_seq = 0; // save last sequence number for retransmissions - uint8_t last_write_sequence[8] = {0}; + uint64_t last_write_sequence = 0; UniquePtr last_aead_write_ctx; // incoming_messages is a ring buffer of incoming handshake messages that have diff --git a/Sources/CNIOBoringSSL/ssl/ssl_aead_ctx.cc b/Sources/CNIOBoringSSL/ssl/ssl_aead_ctx.cc index bef5d328..bc4f89e8 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_aead_ctx.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_aead_ctx.cc @@ -220,13 +220,13 @@ size_t SSLAEADContext::MaxOverhead() const { } Span SSLAEADContext::GetAdditionalData( - uint8_t storage[13], uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], size_t plaintext_len, Span header) { + uint8_t storage[13], uint8_t type, uint16_t record_version, uint64_t seqnum, + size_t plaintext_len, Span header) { if (ad_is_header_) { return header; } - OPENSSL_memcpy(storage, seqnum, 8); + CRYPTO_store_u64_be(storage, seqnum); size_t len = 8; storage[len++] = type; storage[len++] = static_cast((record_version >> 8)); @@ -239,7 +239,7 @@ Span SSLAEADContext::GetAdditionalData( } bool SSLAEADContext::Open(Span *out, uint8_t type, - uint16_t record_version, const uint8_t seqnum[8], + uint16_t record_version, uint64_t seqnum, Span header, Span in) { if (is_null_cipher() || FUZZER_MODE) { // Handle the initial NULL cipher. @@ -288,7 +288,7 @@ bool SSLAEADContext::Open(Span *out, uint8_t type, in = in.subspan(variable_nonce_len_); } else { assert(variable_nonce_len_ == 8); - OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_); + CRYPTO_store_u64_be(nonce + nonce_len, seqnum); } nonce_len += variable_nonce_len_; @@ -313,8 +313,7 @@ bool SSLAEADContext::Open(Span *out, uint8_t type, bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix, uint8_t type, - uint16_t record_version, - const uint8_t seqnum[8], + uint16_t record_version, uint64_t seqnum, Span header, const uint8_t *in, size_t in_len, const uint8_t *extra_in, size_t extra_in_len) { @@ -365,7 +364,7 @@ bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out, // When sending we use the sequence number as the variable part of the // nonce. assert(variable_nonce_len_ == 8); - OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_); + CRYPTO_store_u64_be(nonce + nonce_len, seqnum); } nonce_len += variable_nonce_len_; @@ -398,7 +397,7 @@ bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out, bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len, uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], Span header, + uint64_t seqnum, Span header, const uint8_t *in, size_t in_len) { const size_t prefix_len = ExplicitNonceLen(); size_t suffix_len; diff --git a/Sources/CNIOBoringSSL/ssl/ssl_lib.cc b/Sources/CNIOBoringSSL/ssl/ssl_lib.cc index 9864dc5b..83a2b2ce 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_lib.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_lib.cc @@ -687,7 +687,7 @@ SSL_CONFIG::SSL_CONFIG(SSL *ssl_arg) signed_cert_timestamps_enabled(false), ocsp_stapling_enabled(false), channel_id_enabled(false), - enforce_rsa_key_usage(false), + enforce_rsa_key_usage(true), retain_only_sha256_of_client_certs(false), handoff(false), shed_handshake_config(false), @@ -2823,20 +2823,19 @@ int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv, } uint64_t SSL_get_read_sequence(const SSL *ssl) { - // TODO(davidben): Internally represent sequence numbers as uint64_t. if (SSL_is_dtls(ssl)) { // max_seq_num already includes the epoch. assert(ssl->d1->r_epoch == (ssl->d1->bitmap.max_seq_num >> 48)); return ssl->d1->bitmap.max_seq_num; } - return CRYPTO_load_u64_be(ssl->s3->read_sequence); + return ssl->s3->read_sequence; } uint64_t SSL_get_write_sequence(const SSL *ssl) { - uint64_t ret = CRYPTO_load_u64_be(ssl->s3->write_sequence); + uint64_t ret = ssl->s3->write_sequence; if (SSL_is_dtls(ssl)) { assert((ret >> 48) == 0); - ret |= ((uint64_t)ssl->d1->w_epoch) << 48; + ret |= uint64_t{ssl->d1->w_epoch} << 48; } return ret; } diff --git a/Sources/CNIOBoringSSL/ssl/t1_enc.cc b/Sources/CNIOBoringSSL/ssl/t1_enc.cc index d748b1ee..5c1b8c64 100644 --- a/Sources/CNIOBoringSSL/ssl/t1_enc.cc +++ b/Sources/CNIOBoringSSL/ssl/t1_enc.cc @@ -302,7 +302,7 @@ using namespace bssl; size_t SSL_get_key_block_len(const SSL *ssl) { // See |SSL_generate_key_block|. - if (SSL_in_init(ssl)) { + if (SSL_in_init(ssl) || ssl_protocol_version(ssl) > TLS1_2_VERSION) { return 0; } @@ -321,7 +321,7 @@ int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) { // there are points where read and write states are from different epochs. // During a handshake, before ChangeCipherSpec, the encryption states may not // match |ssl->s3->client_random| and |ssl->s3->server_random|. - if (SSL_in_init(ssl)) { + if (SSL_in_init(ssl) || ssl_protocol_version(ssl) > TLS1_2_VERSION) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } diff --git a/Sources/CNIOBoringSSL/ssl/tls_method.cc b/Sources/CNIOBoringSSL/ssl/tls_method.cc index 1fc1b304..f03b9110 100644 --- a/Sources/CNIOBoringSSL/ssl/tls_method.cc +++ b/Sources/CNIOBoringSSL/ssl/tls_method.cc @@ -108,7 +108,7 @@ static bool tls_set_read_state(SSL *ssl, ssl_encryption_level_t level, } } - OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence)); + ssl->s3->read_sequence = 0; ssl->s3->aead_read_ctx = std::move(aead_ctx); ssl->s3->read_level = level; return true; @@ -137,7 +137,7 @@ static bool tls_set_write_state(SSL *ssl, ssl_encryption_level_t level, } } - OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence)); + ssl->s3->write_sequence = 0; ssl->s3->aead_write_ctx = std::move(aead_ctx); ssl->s3->write_level = level; return true; diff --git a/Sources/CNIOBoringSSL/ssl/tls_record.cc b/Sources/CNIOBoringSSL/ssl/tls_record.cc index 5f52dd56..3b7d7e5c 100644 --- a/Sources/CNIOBoringSSL/ssl/tls_record.cc +++ b/Sources/CNIOBoringSSL/ssl/tls_record.cc @@ -151,17 +151,6 @@ static bool ssl_needs_record_splitting(const SSL *ssl) { #endif } -bool ssl_record_sequence_update(uint8_t *seq, size_t seq_len) { - for (size_t i = seq_len - 1; i < seq_len; i--) { - ++seq[i]; - if (seq[i] != 0) { - return true; - } - } - OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); - return false; -} - size_t ssl_record_prefix_len(const SSL *ssl) { size_t header_len; if (SSL_is_dtls(ssl)) { @@ -286,6 +275,13 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, return skip_early_data(ssl, out_alert, *out_consumed); } + // Ensure the sequence number update does not overflow. + if (ssl->s3->read_sequence + 1 == 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + *out_alert = SSL_AD_INTERNAL_ERROR; + return ssl_open_record_error; + } + // Decrypt the body in-place. if (!ssl->s3->aead_read_ctx->Open( out, type, version, ssl->s3->read_sequence, header, @@ -301,11 +297,7 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, } ssl->s3->skip_early_data = false; - - if (!ssl_record_sequence_update(ssl->s3->read_sequence, 8)) { - *out_alert = SSL_AD_INTERNAL_ERROR; - return ssl_open_record_error; - } + ssl->s3->read_sequence++; // TLS 1.3 hides the record type inside the encrypted data. bool has_padding = @@ -411,13 +403,19 @@ static bool do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, out_prefix[4] = ciphertext_len & 0xff; Span header = MakeSpan(out_prefix, SSL3_RT_HEADER_LENGTH); + // Ensure the sequence number update does not overflow. + if (ssl->s3->write_sequence + 1 == 0) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return false; + } + if (!aead->SealScatter(out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, out_prefix[0], record_version, ssl->s3->write_sequence, - header, in, in_len, extra_in, extra_in_len) || - !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) { + header, in, in_len, extra_in, extra_in_len)) { return false; } + ssl->s3->write_sequence++; ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header); return true; } @@ -602,86 +600,6 @@ enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert, return ssl_open_record_error; } -OpenRecordResult OpenRecord(SSL *ssl, Span *out, - size_t *out_record_len, uint8_t *out_alert, - const Span in) { - // This API is a work in progress and currently only works for TLS 1.2 servers - // and below. - if (SSL_in_init(ssl) || - SSL_is_dtls(ssl) || - ssl_protocol_version(ssl) > TLS1_2_VERSION) { - assert(false); - *out_alert = SSL_AD_INTERNAL_ERROR; - return OpenRecordResult::kError; - } - - Span plaintext; - uint8_t type = 0; - const ssl_open_record_t result = tls_open_record( - ssl, &type, &plaintext, out_record_len, out_alert, in); - - switch (result) { - case ssl_open_record_success: - if (type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_ALERT) { - *out_alert = SSL_AD_UNEXPECTED_MESSAGE; - return OpenRecordResult::kError; - } - *out = plaintext; - return OpenRecordResult::kOK; - case ssl_open_record_discard: - return OpenRecordResult::kDiscard; - case ssl_open_record_partial: - return OpenRecordResult::kIncompleteRecord; - case ssl_open_record_close_notify: - return OpenRecordResult::kAlertCloseNotify; - case ssl_open_record_error: - return OpenRecordResult::kError; - } - assert(false); - return OpenRecordResult::kError; -} - -size_t SealRecordPrefixLen(const SSL *ssl, const size_t record_len) { - return tls_seal_scatter_prefix_len(ssl, SSL3_RT_APPLICATION_DATA, record_len); -} - -size_t SealRecordSuffixLen(const SSL *ssl, const size_t plaintext_len) { - assert(plaintext_len <= SSL3_RT_MAX_PLAIN_LENGTH); - size_t suffix_len; - if (!tls_seal_scatter_suffix_len(ssl, &suffix_len, SSL3_RT_APPLICATION_DATA, - plaintext_len)) { - assert(false); - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return 0; - } - assert(suffix_len <= SSL3_RT_MAX_ENCRYPTED_OVERHEAD); - return suffix_len; -} - -bool SealRecord(SSL *ssl, const Span out_prefix, - const Span out, Span out_suffix, - const Span in) { - // This API is a work in progress and currently only works for TLS 1.2 servers - // and below. - if (SSL_in_init(ssl) || - SSL_is_dtls(ssl) || - ssl_protocol_version(ssl) > TLS1_2_VERSION) { - assert(false); - OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); - return false; - } - - if (out_prefix.size() != SealRecordPrefixLen(ssl, in.size()) || - out.size() != in.size() || - out_suffix.size() != SealRecordSuffixLen(ssl, in.size())) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); - return false; - } - return tls_seal_scatter_record(ssl, out_prefix.data(), out.data(), - out_suffix.data(), SSL3_RT_APPLICATION_DATA, - in.data(), in.size()); -} - BSSL_NAMESPACE_END using namespace bssl;