diff --git a/Package.swift b/Package.swift index 434f3b4e..4cb22ac5 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: 059585c8dadc7c8170c788f8c89843ee1c5b8f11 +// BoringSSL Commit: 9559c4566a6d12194c42db5f3dbbcb5de35cfec2 /// This function generates the dependencies we want to express. /// diff --git a/Sources/CNIOBoringSSL/crypto/dilithium/dilithium.cc b/Sources/CNIOBoringSSL/crypto/dilithium/dilithium.cc deleted file mode 100644 index 54bd8046..00000000 --- a/Sources/CNIOBoringSSL/crypto/dilithium/dilithium.cc +++ /dev/null @@ -1,1538 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#define OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM -#include - -#include -#include - -#include -#include - -#include "../internal.h" -#include "../keccak/internal.h" -#include "./internal.h" - -#define DEGREE 256 -#define K 6 -#define L 5 -#define ETA 4 -#define TAU 49 -#define BETA 196 -#define OMEGA 55 - -#define RHO_BYTES 32 -#define SIGMA_BYTES 64 -#define K_BYTES 32 -#define TR_BYTES 64 -#define MU_BYTES 64 -#define RHO_PRIME_BYTES 64 -#define LAMBDA_BITS 192 -#define LAMBDA_BYTES (LAMBDA_BITS / 8) - -// 2^23 - 2^13 + 1 -static const uint32_t kPrime = 8380417; -// Inverse of -kPrime modulo 2^32 -static const uint32_t kPrimeNegInverse = 4236238847; -static const int kDroppedBits = 13; -static const uint32_t kHalfPrime = (8380417 - 1) / 2; -static const uint32_t kGamma1 = 1 << 19; -static const uint32_t kGamma2 = (8380417 - 1) / 32; -// 256^-1 mod kPrime, in Montgomery form. -static const uint32_t kInverseDegreeMontgomery = 41978; - -typedef struct scalar { - uint32_t c[DEGREE]; -} scalar; - -typedef struct vectork { - scalar v[K]; -} vectork; - -typedef struct vectorl { - scalar v[L]; -} vectorl; - -typedef struct matrix { - scalar v[K][L]; -} matrix; - -/* Arithmetic */ - -// This bit of Python will be referenced in some of the following comments: -// -// q = 8380417 -// # Inverse of -q modulo 2^32 -// q_neg_inverse = 4236238847 -// # 2^64 modulo q -// montgomery_square = 2365951 -// -// def bitreverse(i): -// ret = 0 -// for n in range(8): -// bit = i & 1 -// ret <<= 1 -// ret |= bit -// i >>= 1 -// return ret -// -// def montgomery_reduce(x): -// a = (x * q_neg_inverse) % 2**32 -// b = x + a * q -// assert b & 0xFFFF_FFFF == 0 -// c = b >> 32 -// assert c < q -// return c -// -// def montgomery_transform(x): -// return montgomery_reduce(x * montgomery_square) - -// kNTTRootsMontgomery = [ -// montgomery_transform(pow(1753, bitreverse(i), q)) for i in range(256) -// ] -static const uint32_t kNTTRootsMontgomery[256] = { - 4193792, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, - 1826347, 2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103, - 2725464, 1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868, - 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005, - 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, - 4519302, 5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, - 6681150, 6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596, - 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638, - 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, - 7122806, 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, - 3412210, 7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370, - 7709315, 7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987, - 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618, - 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561, - 189548, 4827145, 3159746, 6529015, 5971092, 8202977, 1315589, 1341330, - 1285669, 6795489, 7567685, 6940675, 5361315, 4499357, 4751448, 3839961, - 2091667, 3407706, 2316500, 3817976, 5037939, 2244091, 5933984, 4817955, - 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039, - 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917, - 7725090, 5257975, 2031748, 3207046, 4823422, 7855319, 7611795, 4784579, - 342297, 286988, 5942594, 4108315, 3437287, 5038140, 1735879, 203044, - 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353, 1595974, - 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447, - 7047359, 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775, - 7100756, 1917081, 5834105, 7005614, 1500165, 777191, 2235880, 3406031, - 7838005, 5548557, 6709241, 6533464, 5796124, 4656147, 594136, 4603424, - 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531, 7173032, - 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310, - 5341501, 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078, - 7953734, 1723600, 6577327, 1910376, 6712985, 7276084, 8119771, 4546524, - 5441381, 6144432, 7959518, 6094090, 183443, 7403526, 1612842, 4834730, - 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263, 1976782}; - -// Reduces x mod kPrime in constant time, where 0 <= x < 2*kPrime. -static uint32_t reduce_once(uint32_t x) { - declassify_assert(x < 2 * kPrime); - // return x < kPrime ? x : x - kPrime; - return constant_time_select_int(constant_time_lt_w(x, kPrime), x, x - kPrime); -} - -// Returns the absolute value in constant time. -static uint32_t abs_signed(uint32_t x) { - // return is_positive(x) ? x : -x; - // Note: MSVC doesn't like applying the unary minus operator to unsigned types - // (warning C4146), so we write the negation as a bitwise not plus one - // (assuming two's complement representation). - return constant_time_select_int(constant_time_lt_w(x, 0x80000000), x, ~x + 1); -} - -// Returns the absolute value modulo kPrime. -static uint32_t abs_mod_prime(uint32_t x) { - declassify_assert(x < kPrime); - // return x > kHalfPrime ? kPrime - x : x; - return constant_time_select_int(constant_time_lt_w(kHalfPrime, x), kPrime - x, - x); -} - -// Returns the maximum of two values in constant time. -static uint32_t maximum(uint32_t x, uint32_t y) { - // return x < y ? y : x; - return constant_time_select_int(constant_time_lt_w(x, y), y, x); -} - -static void scalar_add(scalar *out, const scalar *lhs, const scalar *rhs) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = reduce_once(lhs->c[i] + rhs->c[i]); - } -} - -static void scalar_sub(scalar *out, const scalar *lhs, const scalar *rhs) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = reduce_once(kPrime + lhs->c[i] - rhs->c[i]); - } -} - -static uint32_t reduce_montgomery(uint64_t x) { - uint64_t a = (uint32_t)x * kPrimeNegInverse; - uint64_t b = x + a * kPrime; - declassify_assert((b & 0xffffffff) == 0); - uint32_t c = b >> 32; - return reduce_once(c); -} - -// Multiply two scalars in the number theoretically transformed state. -static void scalar_mult(scalar *out, const scalar *lhs, const scalar *rhs) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = reduce_montgomery((uint64_t)lhs->c[i] * (uint64_t)rhs->c[i]); - } -} - -// In place number theoretic transform of a given scalar. -// -// FIPS 204, Algorithm 35 (`NTT`). -static void scalar_ntt(scalar *s) { - // Step: 1, 2, 4, 8, ..., 128 - // Offset: 128, 64, 32, 16, ..., 1 - int offset = DEGREE; - for (int step = 1; step < DEGREE; step <<= 1) { - offset >>= 1; - int k = 0; - for (int i = 0; i < step; i++) { - assert(k == 2 * offset * i); - const uint32_t step_root = kNTTRootsMontgomery[step + i]; - for (int j = k; j < k + offset; j++) { - uint32_t even = s->c[j]; - uint32_t odd = - reduce_montgomery((uint64_t)step_root * (uint64_t)s->c[j + offset]); - s->c[j] = reduce_once(odd + even); - s->c[j + offset] = reduce_once(kPrime + even - odd); - } - k += 2 * offset; - } - } -} - -// In place inverse number theoretic transform of a given scalar. -// -// FIPS 204, Algorithm 36 (`NTT^-1`). -static void scalar_inverse_ntt(scalar *s) { - // Step: 128, 64, 32, 16, ..., 1 - // Offset: 1, 2, 4, 8, ..., 128 - int step = DEGREE; - for (int offset = 1; offset < DEGREE; offset <<= 1) { - step >>= 1; - int k = 0; - for (int i = 0; i < step; i++) { - assert(k == 2 * offset * i); - const uint32_t step_root = - kPrime - kNTTRootsMontgomery[step + (step - 1 - i)]; - for (int j = k; j < k + offset; j++) { - uint32_t even = s->c[j]; - uint32_t odd = s->c[j + offset]; - s->c[j] = reduce_once(odd + even); - s->c[j + offset] = reduce_montgomery((uint64_t)step_root * - (uint64_t)(kPrime + even - odd)); - } - k += 2 * offset; - } - } - for (int i = 0; i < DEGREE; i++) { - s->c[i] = reduce_montgomery((uint64_t)s->c[i] * - (uint64_t)kInverseDegreeMontgomery); - } -} - -static void vectork_zero(vectork *out) { OPENSSL_memset(out, 0, sizeof(*out)); } - -static void vectork_add(vectork *out, const vectork *lhs, const vectork *rhs) { - for (int i = 0; i < K; i++) { - scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]); - } -} - -static void vectork_sub(vectork *out, const vectork *lhs, const vectork *rhs) { - for (int i = 0; i < K; i++) { - scalar_sub(&out->v[i], &lhs->v[i], &rhs->v[i]); - } -} - -static void vectork_mult_scalar(vectork *out, const vectork *lhs, - const scalar *rhs) { - for (int i = 0; i < K; i++) { - scalar_mult(&out->v[i], &lhs->v[i], rhs); - } -} - -static void vectork_ntt(vectork *a) { - for (int i = 0; i < K; i++) { - scalar_ntt(&a->v[i]); - } -} - -static void vectork_inverse_ntt(vectork *a) { - for (int i = 0; i < K; i++) { - scalar_inverse_ntt(&a->v[i]); - } -} - -static void vectorl_add(vectorl *out, const vectorl *lhs, const vectorl *rhs) { - for (int i = 0; i < L; i++) { - scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]); - } -} - -static void vectorl_mult_scalar(vectorl *out, const vectorl *lhs, - const scalar *rhs) { - for (int i = 0; i < L; i++) { - scalar_mult(&out->v[i], &lhs->v[i], rhs); - } -} - -static void vectorl_ntt(vectorl *a) { - for (int i = 0; i < L; i++) { - scalar_ntt(&a->v[i]); - } -} - -static void vectorl_inverse_ntt(vectorl *a) { - for (int i = 0; i < L; i++) { - scalar_inverse_ntt(&a->v[i]); - } -} - -static void matrix_mult(vectork *out, const matrix *m, const vectorl *a) { - vectork_zero(out); - for (int i = 0; i < K; i++) { - for (int j = 0; j < L; j++) { - scalar product; - scalar_mult(&product, &m->v[i][j], &a->v[j]); - scalar_add(&out->v[i], &out->v[i], &product); - } - } -} - -/* Rounding & hints */ - -// FIPS 204, Algorithm 29 (`Power2Round`). -static void power2_round(uint32_t *r1, uint32_t *r0, uint32_t r) { - *r1 = r >> kDroppedBits; - *r0 = r - (*r1 << kDroppedBits); - - uint32_t r0_adjusted = reduce_once(kPrime + *r0 - (1 << kDroppedBits)); - uint32_t r1_adjusted = *r1 + 1; - - // Mask is set iff r0 > 2^(dropped_bits - 1). - crypto_word_t mask = - constant_time_lt_w((uint32_t)(1 << (kDroppedBits - 1)), *r0); - // r0 = mask ? r0_adjusted : r0 - *r0 = constant_time_select_int(mask, r0_adjusted, *r0); - // r1 = mask ? r1_adjusted : r1 - *r1 = constant_time_select_int(mask, r1_adjusted, *r1); -} - -// Scale back previously rounded value. -static void scale_power2_round(uint32_t *out, uint32_t r1) { - // Pre-condition: 0 <= r1 <= 2^10 - 1 - *out = r1 << kDroppedBits; - // Post-condition: 0 <= out <= 2^23 - 2^13 = kPrime - 1 - assert(*out < kPrime); -} - -// FIPS 204, Algorithm 31 (`HighBits`). -static uint32_t high_bits(uint32_t x) { - // Reference description (given 0 <= x < q): - // - // ``` - // int32_t r0 = x mod+- (2 * kGamma2); - // if (x - r0 == q - 1) { - // return 0; - // } else { - // return (x - r0) / (2 * kGamma2); - // } - // ``` - // - // Below is the formula taken from the reference implementation. - // - // Here, kGamma2 == 2^18 - 2^8 - // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4 - uint32_t r1 = (x + 127) >> 7; - r1 = (r1 * 1025 + (1 << 21)) >> 22; - r1 &= 15; - return r1; -} - -// FIPS 204, Algorithm 30 (`Decompose`). -static void decompose(uint32_t *r1, int32_t *r0, uint32_t r) { - *r1 = high_bits(r); - - *r0 = r; - *r0 -= *r1 * 2 * (int32_t)kGamma2; - *r0 -= (((int32_t)kHalfPrime - *r0) >> 31) & (int32_t)kPrime; -} - -// FIPS 204, Algorithm 32 (`LowBits`). -static int32_t low_bits(uint32_t x) { - uint32_t r1; - int32_t r0; - decompose(&r1, &r0, x); - return r0; -} - -// FIPS 204, Algorithm 33 (`MakeHint`). -static int32_t make_hint(uint32_t ct0, uint32_t cs2, uint32_t w) { - uint32_t r_plus_z = reduce_once(kPrime + w - cs2); - uint32_t r = reduce_once(r_plus_z + ct0); - return high_bits(r) != high_bits(r_plus_z); -} - -// FIPS 204, Algorithm 34 (`UseHint`). -static uint32_t use_hint_vartime(uint32_t h, uint32_t r) { - uint32_t r1; - int32_t r0; - decompose(&r1, &r0, r); - - if (h) { - if (r0 > 0) { - return (r1 + 1) & 15; - } else { - return (r1 - 1) & 15; - } - } else { - return r1; - } -} - -static void scalar_power2_round(scalar *s1, scalar *s0, const scalar *s) { - for (int i = 0; i < DEGREE; i++) { - power2_round(&s1->c[i], &s0->c[i], s->c[i]); - } -} - -static void scalar_scale_power2_round(scalar *out, const scalar *in) { - for (int i = 0; i < DEGREE; i++) { - scale_power2_round(&out->c[i], in->c[i]); - } -} - -static void scalar_high_bits(scalar *out, const scalar *in) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = high_bits(in->c[i]); - } -} - -static void scalar_low_bits(scalar *out, const scalar *in) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = low_bits(in->c[i]); - } -} - -static void scalar_max(uint32_t *max, const scalar *s) { - for (int i = 0; i < DEGREE; i++) { - uint32_t abs = abs_mod_prime(s->c[i]); - *max = maximum(*max, abs); - } -} - -static void scalar_max_signed(uint32_t *max, const scalar *s) { - for (int i = 0; i < DEGREE; i++) { - uint32_t abs = abs_signed(s->c[i]); - *max = maximum(*max, abs); - } -} - -static void scalar_make_hint(scalar *out, const scalar *ct0, const scalar *cs2, - const scalar *w) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]); - } -} - -static void scalar_use_hint_vartime(scalar *out, const scalar *h, - const scalar *r) { - for (int i = 0; i < DEGREE; i++) { - out->c[i] = use_hint_vartime(h->c[i], r->c[i]); - } -} - -static void vectork_power2_round(vectork *t1, vectork *t0, const vectork *t) { - for (int i = 0; i < K; i++) { - scalar_power2_round(&t1->v[i], &t0->v[i], &t->v[i]); - } -} - -static void vectork_scale_power2_round(vectork *out, const vectork *in) { - for (int i = 0; i < K; i++) { - scalar_scale_power2_round(&out->v[i], &in->v[i]); - } -} - -static void vectork_high_bits(vectork *out, const vectork *in) { - for (int i = 0; i < K; i++) { - scalar_high_bits(&out->v[i], &in->v[i]); - } -} - -static void vectork_low_bits(vectork *out, const vectork *in) { - for (int i = 0; i < K; i++) { - scalar_low_bits(&out->v[i], &in->v[i]); - } -} - -static uint32_t vectork_max(const vectork *a) { - uint32_t max = 0; - for (int i = 0; i < K; i++) { - scalar_max(&max, &a->v[i]); - } - return max; -} - -static uint32_t vectork_max_signed(const vectork *a) { - uint32_t max = 0; - for (int i = 0; i < K; i++) { - scalar_max_signed(&max, &a->v[i]); - } - return max; -} - -// The input vector contains only zeroes and ones. -static size_t vectork_count_ones(const vectork *a) { - size_t count = 0; - for (int i = 0; i < K; i++) { - for (int j = 0; j < DEGREE; j++) { - count += a->v[i].c[j]; - } - } - return count; -} - -static void vectork_make_hint(vectork *out, const vectork *ct0, - const vectork *cs2, const vectork *w) { - for (int i = 0; i < K; i++) { - scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]); - } -} - -static void vectork_use_hint_vartime(vectork *out, const vectork *h, - const vectork *r) { - for (int i = 0; i < K; i++) { - scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]); - } -} - -static uint32_t vectorl_max(const vectorl *a) { - uint32_t max = 0; - for (int i = 0; i < L; i++) { - scalar_max(&max, &a->v[i]); - } - return max; -} - -/* Bit packing */ - -static const uint8_t kMasks[8] = {0x01, 0x03, 0x07, 0x0f, - 0x1f, 0x3f, 0x7f, 0xff}; - -// FIPS 204, Algorithm 10 (`SimpleBitPack`). -static void scalar_encode(uint8_t *out, const scalar *s, int bits) { - assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1); - - uint8_t out_byte = 0; - int out_byte_bits = 0; - - for (int i = 0; i < DEGREE; i++) { - uint32_t element = s->c[i]; - int element_bits_done = 0; - - while (element_bits_done < bits) { - int chunk_bits = bits - element_bits_done; - int out_bits_remaining = 8 - out_byte_bits; - if (chunk_bits >= out_bits_remaining) { - chunk_bits = out_bits_remaining; - out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; - *out = out_byte; - out++; - out_byte_bits = 0; - out_byte = 0; - } else { - out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; - out_byte_bits += chunk_bits; - } - - element_bits_done += chunk_bits; - element >>= chunk_bits; - } - } - - if (out_byte_bits > 0) { - *out = out_byte; - } -} - -// FIPS 204, Algorithm 11 (`BitPack`). -static void scalar_encode_signed(uint8_t *out, const scalar *s, int bits, - uint32_t max) { - assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1); - - uint8_t out_byte = 0; - int out_byte_bits = 0; - - for (int i = 0; i < DEGREE; i++) { - uint32_t element = reduce_once(kPrime + max - s->c[i]); - declassify_assert(element <= 2 * max); - int element_bits_done = 0; - - while (element_bits_done < bits) { - int chunk_bits = bits - element_bits_done; - int out_bits_remaining = 8 - out_byte_bits; - if (chunk_bits >= out_bits_remaining) { - chunk_bits = out_bits_remaining; - out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; - *out = out_byte; - out++; - out_byte_bits = 0; - out_byte = 0; - } else { - out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits; - out_byte_bits += chunk_bits; - } - - element_bits_done += chunk_bits; - element >>= chunk_bits; - } - } - - if (out_byte_bits > 0) { - *out = out_byte; - } -} - -// FIPS 204, Algorithm 12 (`SimpleBitUnpack`). -static void scalar_decode(scalar *out, const uint8_t *in, int bits) { - assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1); - - uint8_t in_byte = 0; - int in_byte_bits_left = 0; - - for (int i = 0; i < DEGREE; i++) { - uint32_t element = 0; - int element_bits_done = 0; - - while (element_bits_done < bits) { - if (in_byte_bits_left == 0) { - in_byte = *in; - in++; - in_byte_bits_left = 8; - } - - int chunk_bits = bits - element_bits_done; - if (chunk_bits > in_byte_bits_left) { - chunk_bits = in_byte_bits_left; - } - - element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done; - in_byte_bits_left -= chunk_bits; - in_byte >>= chunk_bits; - - element_bits_done += chunk_bits; - } - - out->c[i] = element; - } -} - -// FIPS 204, Algorithm 13 (`BitUnpack`). -static int scalar_decode_signed(scalar *out, const uint8_t *in, int bits, - uint32_t max) { - assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1); - - uint8_t in_byte = 0; - int in_byte_bits_left = 0; - - for (int i = 0; i < DEGREE; i++) { - uint32_t element = 0; - int element_bits_done = 0; - - while (element_bits_done < bits) { - if (in_byte_bits_left == 0) { - in_byte = *in; - in++; - in_byte_bits_left = 8; - } - - int chunk_bits = bits - element_bits_done; - if (chunk_bits > in_byte_bits_left) { - chunk_bits = in_byte_bits_left; - } - - element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done; - in_byte_bits_left -= chunk_bits; - in_byte >>= chunk_bits; - - element_bits_done += chunk_bits; - } - - // This may be only out of range in cases of invalid input, in which case it - // is okay to leak the value. This function is also called with secret - // input during signing, in |scalar_sample_mask|. However, in that case - // (and in any case when |max| is a power of two), this case is impossible. - if (constant_time_declassify_int(element > 2 * max)) { - return 0; - } - out->c[i] = reduce_once(kPrime + max - element); - } - - return 1; -} - -/* Expansion functions */ - -// FIPS 204, Algorithm 24 (`RejNTTPoly`). -// -// Rejection samples a Keccak stream to get uniformly distributed elements. This -// is used for matrix expansion and only operates on public inputs. -static void scalar_from_keccak_vartime( - scalar *out, const uint8_t derived_seed[RHO_BYTES + 2]) { - struct BORINGSSL_keccak_st keccak_ctx; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake128); - BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, RHO_BYTES + 2); - assert(keccak_ctx.squeeze_offset == 0); - assert(keccak_ctx.rate_bytes == 168); - static_assert(168 % 3 == 0, "block and coefficient boundaries do not align"); - - int done = 0; - while (done < DEGREE) { - uint8_t block[168]; - BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); - for (size_t i = 0; i < sizeof(block) && done < DEGREE; i += 3) { - // FIPS 204, Algorithm 8 (`CoeffFromThreeBytes`). - uint32_t value = (uint32_t)block[i] | ((uint32_t)block[i + 1] << 8) | - (((uint32_t)block[i + 2] & 0x7f) << 16); - if (value < kPrime) { - out->c[done++] = value; - } - } - } -} - -// FIPS 204, Algorithm 25 (`RejBoundedPoly`). -static void scalar_uniform_eta_4(scalar *out, - const uint8_t derived_seed[SIGMA_BYTES + 2]) { - static_assert(ETA == 4, "This implementation is specialized for ETA == 4"); - - struct BORINGSSL_keccak_st keccak_ctx; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, SIGMA_BYTES + 2); - assert(keccak_ctx.squeeze_offset == 0); - assert(keccak_ctx.rate_bytes == 136); - - int done = 0; - while (done < DEGREE) { - uint8_t block[136]; - BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); - for (size_t i = 0; i < sizeof(block) && done < DEGREE; ++i) { - uint32_t t0 = block[i] & 0x0F; - uint32_t t1 = block[i] >> 4; - // FIPS 204, Algorithm 9 (`CoefFromHalfByte`). Although both the input and - // output here are secret, it is OK to leak when we rejected a byte. - // Individual bytes of the SHAKE-256 stream are (indistiguishable from) - // independent of each other and the original seed, so leaking information - // about the rejected bytes does not reveal the input or output. - if (constant_time_declassify_int(t0 < 9)) { - out->c[done++] = reduce_once(kPrime + ETA - t0); - } - if (done < DEGREE && constant_time_declassify_int(t1 < 9)) { - out->c[done++] = reduce_once(kPrime + ETA - t1); - } - } - } -} - -// FIPS 204, Algorithm 28 (`ExpandMask`). -static void scalar_sample_mask( - scalar *out, const uint8_t derived_seed[RHO_PRIME_BYTES + 2]) { - uint8_t buf[640]; - BORINGSSL_keccak(buf, sizeof(buf), derived_seed, RHO_PRIME_BYTES + 2, - boringssl_shake256); - - // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail. - scalar_decode_signed(out, buf, 20, 1 << 19); -} - -// FIPS 204, Algorithm 23 (`SampleInBall`). -static void scalar_sample_in_ball_vartime(scalar *out, const uint8_t *seed, - int len) { - assert(len == 32); - - struct BORINGSSL_keccak_st keccak_ctx; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, seed, len); - assert(keccak_ctx.squeeze_offset == 0); - assert(keccak_ctx.rate_bytes == 136); - - uint8_t block[136]; - BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); - - uint64_t signs = CRYPTO_load_u64_le(block); - int offset = 8; - // SampleInBall implements a Fisher–Yates shuffle, which unavoidably leaks - // where the zeros are by memory access pattern. Although this leak happens - // before bad signatures are rejected, this is safe. See - // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/8d8f01ac_70af3f21/ - CONSTTIME_DECLASSIFY(block + offset, sizeof(block) - offset); - - OPENSSL_memset(out, 0, sizeof(*out)); - for (size_t i = DEGREE - TAU; i < DEGREE; i++) { - size_t byte; - for (;;) { - if (offset == 136) { - BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block)); - // See above. - CONSTTIME_DECLASSIFY(block, sizeof(block)); - offset = 0; - } - - byte = block[offset++]; - if (byte <= i) { - break; - } - } - - out->c[i] = out->c[byte]; - out->c[byte] = reduce_once(kPrime + 1 - 2 * (signs & 1)); - signs >>= 1; - } -} - -// FIPS 204, Algorithm 26 (`ExpandA`). -static void matrix_expand(matrix *out, const uint8_t rho[RHO_BYTES]) { - static_assert(K <= 0x100, "K must fit in 8 bits"); - static_assert(L <= 0x100, "L must fit in 8 bits"); - - uint8_t derived_seed[RHO_BYTES + 2]; - OPENSSL_memcpy(derived_seed, rho, RHO_BYTES); - for (int i = 0; i < K; i++) { - for (int j = 0; j < L; j++) { - derived_seed[RHO_BYTES + 1] = i; - derived_seed[RHO_BYTES] = j; - scalar_from_keccak_vartime(&out->v[i][j], derived_seed); - } - } -} - -// FIPS 204, Algorithm 27 (`ExpandS`). -static void vector_expand_short(vectorl *s1, vectork *s2, - const uint8_t sigma[SIGMA_BYTES]) { - static_assert(K <= 0x100, "K must fit in 8 bits"); - static_assert(L <= 0x100, "L must fit in 8 bits"); - static_assert(K + L <= 0x100, "K+L must fit in 8 bits"); - - uint8_t derived_seed[SIGMA_BYTES + 2]; - OPENSSL_memcpy(derived_seed, sigma, SIGMA_BYTES); - derived_seed[SIGMA_BYTES] = 0; - derived_seed[SIGMA_BYTES + 1] = 0; - for (int i = 0; i < L; i++) { - scalar_uniform_eta_4(&s1->v[i], derived_seed); - ++derived_seed[SIGMA_BYTES]; - } - for (int i = 0; i < K; i++) { - scalar_uniform_eta_4(&s2->v[i], derived_seed); - ++derived_seed[SIGMA_BYTES]; - } -} - -// FIPS 204, Algorithm 28 (`ExpandMask`). -static void vectorl_expand_mask(vectorl *out, - const uint8_t seed[RHO_PRIME_BYTES], - size_t kappa) { - assert(kappa + L <= 0x10000); - - uint8_t derived_seed[RHO_PRIME_BYTES + 2]; - OPENSSL_memcpy(derived_seed, seed, RHO_PRIME_BYTES); - for (int i = 0; i < L; i++) { - size_t index = kappa + i; - derived_seed[RHO_PRIME_BYTES] = index & 0xFF; - derived_seed[RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF; - scalar_sample_mask(&out->v[i], derived_seed); - } -} - -/* Encoding */ - -// FIPS 204, Algorithm 10 (`SimpleBitPack`). -// -// Encodes an entire vector into 32*K*|bits| bytes. Note that since 256 (DEGREE) -// is divisible by 8, the individual vector entries will always fill a whole -// number of bytes, so we do not need to worry about bit packing here. -static void vectork_encode(uint8_t *out, const vectork *a, int bits) { - for (int i = 0; i < K; i++) { - scalar_encode(out + i * bits * DEGREE / 8, &a->v[i], bits); - } -} - -// FIPS 204, Algorithm 12 (`SimpleBitUnpack`). -static void vectork_decode(vectork *out, const uint8_t *in, int bits) { - for (int i = 0; i < K; i++) { - scalar_decode(&out->v[i], in + i * bits * DEGREE / 8, bits); - } -} - -static void vectork_encode_signed(uint8_t *out, const vectork *a, int bits, - uint32_t max) { - for (int i = 0; i < K; i++) { - scalar_encode_signed(out + i * bits * DEGREE / 8, &a->v[i], bits, max); - } -} - -static int vectork_decode_signed(vectork *out, const uint8_t *in, int bits, - uint32_t max) { - for (int i = 0; i < K; i++) { - if (!scalar_decode_signed(&out->v[i], in + i * bits * DEGREE / 8, bits, - max)) { - return 0; - } - } - return 1; -} - -// FIPS 204, Algorithm 11 (`BitPack`). -// -// Encodes an entire vector into 32*L*|bits| bytes. Note that since 256 (DEGREE) -// is divisible by 8, the individual vector entries will always fill a whole -// number of bytes, so we do not need to worry about bit packing here. -static void vectorl_encode_signed(uint8_t *out, const vectorl *a, int bits, - uint32_t max) { - for (int i = 0; i < L; i++) { - scalar_encode_signed(out + i * bits * DEGREE / 8, &a->v[i], bits, max); - } -} - -static int vectorl_decode_signed(vectorl *out, const uint8_t *in, int bits, - uint32_t max) { - for (int i = 0; i < L; i++) { - if (!scalar_decode_signed(&out->v[i], in + i * bits * DEGREE / 8, bits, - max)) { - return 0; - } - } - return 1; -} - -// FIPS 204, Algorithm 22 (`w1Encode`). -// -// The output must point to an array of 128*K bytes. -static void w1_encode(uint8_t *out, const vectork *w1) { - vectork_encode(out, w1, 4); -} - -// FIPS 204, Algorithm 14 (`HintBitPack`). -static void hint_bit_pack(uint8_t *out, const vectork *h) { - OPENSSL_memset(out, 0, OMEGA + K); - int index = 0; - for (int i = 0; i < K; i++) { - for (int j = 0; j < DEGREE; j++) { - if (h->v[i].c[j]) { - out[index++] = j; - } - } - out[OMEGA + i] = index; - } -} - -// FIPS 204, Algorithm 15 (`HintBitUnpack`). -static int hint_bit_unpack(vectork *h, const uint8_t *in) { - vectork_zero(h); - int index = 0; - for (int i = 0; i < K; i++) { - int limit = in[OMEGA + i]; - if (limit < index || limit > OMEGA) { - return 0; - } - - int last = -1; - while (index < limit) { - int byte = in[index++]; - if (last >= 0 && byte <= last) { - return 0; - } - last = byte; - h->v[i].c[byte] = 1; - } - } - for (; index < OMEGA; index++) { - if (in[index] != 0) { - return 0; - } - } - return 1; -} - -struct public_key { - uint8_t rho[RHO_BYTES]; - vectork t1; - // Pre-cached value(s). - uint8_t public_key_hash[TR_BYTES]; -}; - -struct private_key { - uint8_t rho[RHO_BYTES]; - uint8_t k[K_BYTES]; - uint8_t public_key_hash[TR_BYTES]; - vectorl s1; - vectork s2; - vectork t0; -}; - -struct signature { - uint8_t c_tilde[2 * LAMBDA_BYTES]; - vectorl z; - vectork h; -}; - -// FIPS 204, Algorithm 16 (`pkEncode`). -static int dilithium_marshal_public_key(CBB *out, - const struct public_key *pub) { - if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) { - return 0; - } - - uint8_t *vectork_output; - if (!CBB_add_space(out, &vectork_output, 320 * K)) { - return 0; - } - vectork_encode(vectork_output, &pub->t1, 10); - - return 1; -} - -// FIPS 204, Algorithm 17 (`pkDecode`). -static int dilithium_parse_public_key(struct public_key *pub, CBS *in) { - if (!CBS_copy_bytes(in, pub->rho, sizeof(pub->rho))) { - return 0; - } - - CBS t1_bytes; - if (!CBS_get_bytes(in, &t1_bytes, 320 * K)) { - return 0; - } - vectork_decode(&pub->t1, CBS_data(&t1_bytes), 10); - - return 1; -} - -// FIPS 204, Algorithm 18 (`skEncode`). -static int dilithium_marshal_private_key(CBB *out, - const struct private_key *priv) { - if (!CBB_add_bytes(out, priv->rho, sizeof(priv->rho)) || - !CBB_add_bytes(out, priv->k, sizeof(priv->k)) || - !CBB_add_bytes(out, priv->public_key_hash, - sizeof(priv->public_key_hash))) { - return 0; - } - - uint8_t *vectorl_output; - if (!CBB_add_space(out, &vectorl_output, 128 * L)) { - return 0; - } - vectorl_encode_signed(vectorl_output, &priv->s1, 4, ETA); - - uint8_t *vectork_output; - if (!CBB_add_space(out, &vectork_output, 128 * K)) { - return 0; - } - vectork_encode_signed(vectork_output, &priv->s2, 4, ETA); - - if (!CBB_add_space(out, &vectork_output, 416 * K)) { - return 0; - } - vectork_encode_signed(vectork_output, &priv->t0, 13, 1 << 12); - - return 1; -} - -// FIPS 204, Algorithm 19 (`skDecode`). -static int dilithium_parse_private_key(struct private_key *priv, CBS *in) { - CBS s1_bytes; - CBS s2_bytes; - CBS t0_bytes; - if (!CBS_copy_bytes(in, priv->rho, sizeof(priv->rho)) || - !CBS_copy_bytes(in, priv->k, sizeof(priv->k)) || - !CBS_copy_bytes(in, priv->public_key_hash, - sizeof(priv->public_key_hash)) || - !CBS_get_bytes(in, &s1_bytes, 128 * L) || - !vectorl_decode_signed(&priv->s1, CBS_data(&s1_bytes), 4, ETA) || - !CBS_get_bytes(in, &s2_bytes, 128 * K) || - !vectork_decode_signed(&priv->s2, CBS_data(&s2_bytes), 4, ETA) || - !CBS_get_bytes(in, &t0_bytes, 416 * K) || - // Note: Decoding 13 bits into (-2^12, 2^12] cannot fail. - !vectork_decode_signed(&priv->t0, CBS_data(&t0_bytes), 13, 1 << 12)) { - return 0; - } - - return 1; -} - -// FIPS 204, Algorithm 20 (`sigEncode`). -static int dilithium_marshal_signature(CBB *out, const struct signature *sign) { - if (!CBB_add_bytes(out, sign->c_tilde, sizeof(sign->c_tilde))) { - return 0; - } - - uint8_t *vectorl_output; - if (!CBB_add_space(out, &vectorl_output, 640 * L)) { - return 0; - } - vectorl_encode_signed(vectorl_output, &sign->z, 20, 1 << 19); - - uint8_t *hint_output; - if (!CBB_add_space(out, &hint_output, OMEGA + K)) { - return 0; - } - hint_bit_pack(hint_output, &sign->h); - - return 1; -} - -// FIPS 204, Algorithm 21 (`sigDecode`). -static int dilithium_parse_signature(struct signature *sign, CBS *in) { - CBS z_bytes; - CBS hint_bytes; - if (!CBS_copy_bytes(in, sign->c_tilde, sizeof(sign->c_tilde)) || - !CBS_get_bytes(in, &z_bytes, 640 * L) || - // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail. - !vectorl_decode_signed(&sign->z, CBS_data(&z_bytes), 20, 1 << 19) || - !CBS_get_bytes(in, &hint_bytes, OMEGA + K) || - !hint_bit_unpack(&sign->h, CBS_data(&hint_bytes))) { - return 0; - }; - - return 1; -} - -static struct private_key *private_key_from_external( - const struct DILITHIUM_private_key *external) { - static_assert( - sizeof(struct DILITHIUM_private_key) == sizeof(struct private_key), - "Kyber private key size incorrect"); - static_assert( - alignof(struct DILITHIUM_private_key) == alignof(struct private_key), - "Kyber private key align incorrect"); - return (struct private_key *)external; -} - -static struct public_key *public_key_from_external( - const struct DILITHIUM_public_key *external) { - static_assert( - sizeof(struct DILITHIUM_public_key) == sizeof(struct public_key), - "Dilithium public key size incorrect"); - static_assert( - alignof(struct DILITHIUM_public_key) == alignof(struct public_key), - "Dilithium public key align incorrect"); - return (struct public_key *)external; -} - -/* API */ - -// Calls |DILITHIUM_generate_key_external_entropy| with random bytes from -// |RAND_bytes|. Returns 1 on success and 0 on failure. -int DILITHIUM_generate_key( - uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], - struct DILITHIUM_private_key *out_private_key) { - uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]; - RAND_bytes(entropy, sizeof(entropy)); - return DILITHIUM_generate_key_external_entropy(out_encoded_public_key, - out_private_key, entropy); -} - -// FIPS 204, Algorithm 1 (`ML-DSA.KeyGen`). Returns 1 on success and 0 on -// failure. -int DILITHIUM_generate_key_external_entropy( - uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], - struct DILITHIUM_private_key *out_private_key, - const uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]) { - int ret = 0; - - // Intermediate values, allocated on the heap to allow use when there is a - // limited amount of stack. - struct values_st { - struct public_key pub; - matrix a_ntt; - vectorl s1_ntt; - vectork t; - }; - struct values_st *values = - reinterpret_cast(OPENSSL_malloc(sizeof(*values))); - if (values == NULL) { - return 0; - } - - struct private_key *priv = private_key_from_external(out_private_key); - - uint8_t expanded_seed[RHO_BYTES + SIGMA_BYTES + K_BYTES]; - BORINGSSL_keccak(expanded_seed, sizeof(expanded_seed), entropy, - DILITHIUM_GENERATE_KEY_ENTROPY, boringssl_shake256); - const uint8_t *const rho = expanded_seed; - const uint8_t *const sigma = expanded_seed + RHO_BYTES; - const uint8_t *const k = expanded_seed + RHO_BYTES + SIGMA_BYTES; - // rho is public. - CONSTTIME_DECLASSIFY(rho, RHO_BYTES); - OPENSSL_memcpy(values->pub.rho, rho, sizeof(values->pub.rho)); - OPENSSL_memcpy(priv->rho, rho, sizeof(priv->rho)); - OPENSSL_memcpy(priv->k, k, sizeof(priv->k)); - - matrix_expand(&values->a_ntt, rho); - vector_expand_short(&priv->s1, &priv->s2, sigma); - - OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt)); - vectorl_ntt(&values->s1_ntt); - - matrix_mult(&values->t, &values->a_ntt, &values->s1_ntt); - vectork_inverse_ntt(&values->t); - vectork_add(&values->t, &values->t, &priv->s2); - - vectork_power2_round(&values->pub.t1, &priv->t0, &values->t); - // t1 is public. - CONSTTIME_DECLASSIFY(&values->pub.t1, sizeof(values->pub.t1)); - - CBB cbb; - CBB_init_fixed(&cbb, out_encoded_public_key, DILITHIUM_PUBLIC_KEY_BYTES); - if (!dilithium_marshal_public_key(&cbb, &values->pub)) { - goto err; - } - - BORINGSSL_keccak(priv->public_key_hash, sizeof(priv->public_key_hash), - out_encoded_public_key, DILITHIUM_PUBLIC_KEY_BYTES, - boringssl_shake256); - - ret = 1; -err: - OPENSSL_free(values); - return ret; -} - -int DILITHIUM_public_from_private( - struct DILITHIUM_public_key *out_public_key, - const struct DILITHIUM_private_key *private_key) { - // Intermediate values, allocated on the heap to allow use when there is a - // limited amount of stack. - struct values_st { - matrix a_ntt; - vectorl s1_ntt; - vectork t; - vectork t0; - }; - struct values_st *values = - reinterpret_cast(OPENSSL_malloc(sizeof(*values))); - if (values == NULL) { - return 0; - } - - const struct private_key *priv = private_key_from_external(private_key); - struct public_key *pub = public_key_from_external(out_public_key); - - OPENSSL_memcpy(pub->rho, priv->rho, sizeof(pub->rho)); - OPENSSL_memcpy(pub->public_key_hash, priv->public_key_hash, - sizeof(pub->public_key_hash)); - - matrix_expand(&values->a_ntt, priv->rho); - - OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt)); - vectorl_ntt(&values->s1_ntt); - - matrix_mult(&values->t, &values->a_ntt, &values->s1_ntt); - vectork_inverse_ntt(&values->t); - vectork_add(&values->t, &values->t, &priv->s2); - - vectork_power2_round(&pub->t1, &values->t0, &values->t); - - OPENSSL_free(values); - return 1; -} - -// FIPS 204, Algorithm 2 (`ML-DSA.Sign`). Returns 1 on success and 0 on failure. -static int dilithium_sign_with_randomizer( - uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const struct DILITHIUM_private_key *private_key, const uint8_t *msg, - size_t msg_len, - const uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]) { - int ret = 0; - - const struct private_key *priv = private_key_from_external(private_key); - - uint8_t mu[MU_BYTES]; - struct BORINGSSL_keccak_st keccak_ctx; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, priv->public_key_hash, - sizeof(priv->public_key_hash)); - BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len); - BORINGSSL_keccak_squeeze(&keccak_ctx, mu, MU_BYTES); - - uint8_t rho_prime[RHO_PRIME_BYTES]; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, priv->k, sizeof(priv->k)); - BORINGSSL_keccak_absorb(&keccak_ctx, randomizer, - DILITHIUM_SIGNATURE_RANDOMIZER_BYTES); - BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES); - BORINGSSL_keccak_squeeze(&keccak_ctx, rho_prime, RHO_PRIME_BYTES); - - // Intermediate values, allocated on the heap to allow use when there is a - // limited amount of stack. - struct values_st { - struct signature sign; - vectorl s1_ntt; - vectork s2_ntt; - vectork t0_ntt; - matrix a_ntt; - vectorl y; - vectorl y_ntt; - vectork w; - vectork w1; - vectorl cs1; - vectork cs2; - vectork r0; - vectork ct0; - }; - struct values_st *values = - reinterpret_cast(OPENSSL_malloc(sizeof(*values))); - if (values == NULL) { - goto err; - } - OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt)); - vectorl_ntt(&values->s1_ntt); - - OPENSSL_memcpy(&values->s2_ntt, &priv->s2, sizeof(values->s2_ntt)); - vectork_ntt(&values->s2_ntt); - - OPENSSL_memcpy(&values->t0_ntt, &priv->t0, sizeof(values->t0_ntt)); - vectork_ntt(&values->t0_ntt); - - matrix_expand(&values->a_ntt, priv->rho); - - for (size_t kappa = 0;; kappa += L) { - // TODO(bbe): y only lives long enough to compute y_ntt. - // consider using another vectorl to save memory. - vectorl_expand_mask(&values->y, rho_prime, kappa); - - OPENSSL_memcpy(&values->y_ntt, &values->y, sizeof(values->y_ntt)); - vectorl_ntt(&values->y_ntt); - - // TODO(bbe): w only lives long enough to compute y_ntt. - // consider using another vectork to save memory. - matrix_mult(&values->w, &values->a_ntt, &values->y_ntt); - vectork_inverse_ntt(&values->w); - - vectork_high_bits(&values->w1, &values->w); - uint8_t w1_encoded[128 * K]; - w1_encode(w1_encoded, &values->w1); - - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES); - BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); - BORINGSSL_keccak_squeeze(&keccak_ctx, values->sign.c_tilde, - 2 * LAMBDA_BYTES); - - scalar c_ntt; - scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde, 32); - scalar_ntt(&c_ntt); - - vectorl_mult_scalar(&values->cs1, &values->s1_ntt, &c_ntt); - vectorl_inverse_ntt(&values->cs1); - vectork_mult_scalar(&values->cs2, &values->s2_ntt, &c_ntt); - vectork_inverse_ntt(&values->cs2); - - vectorl_add(&values->sign.z, &values->y, &values->cs1); - - vectork_sub(&values->r0, &values->w, &values->cs2); - vectork_low_bits(&values->r0, &values->r0); - - // Leaking the fact that a signature was rejected is fine as the next - // attempt at a signature will be (indistinguishable from) independent of - // this one. Note, however, that we additionally leak which of the two - // branches rejected the signature. Section 5.5 of - // https://pq-crystals.org/dilithium/data/dilithium-specification-round3.pdf - // describes this leak as OK. Note we leak less than what is described by - // the paper; we do not reveal which coefficient violated the bound, and we - // hide which of the |z_max| or |r0_max| bound failed. See also - // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/2bbab0fa_d241d35a/ - uint32_t z_max = vectorl_max(&values->sign.z); - uint32_t r0_max = vectork_max_signed(&values->r0); - if (constant_time_declassify_w( - constant_time_ge_w(z_max, kGamma1 - BETA) | - constant_time_ge_w(r0_max, kGamma2 - BETA))) { - continue; - } - - vectork_mult_scalar(&values->ct0, &values->t0_ntt, &c_ntt); - vectork_inverse_ntt(&values->ct0); - vectork_make_hint(&values->sign.h, &values->ct0, &values->cs2, &values->w); - - // See above. - uint32_t ct0_max = vectork_max(&values->ct0); - size_t h_ones = vectork_count_ones(&values->sign.h); - if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) | - constant_time_lt_w(OMEGA, h_ones))) { - continue; - } - - // Although computed with the private key, the signature is public. - CONSTTIME_DECLASSIFY(values->sign.c_tilde, sizeof(values->sign.c_tilde)); - CONSTTIME_DECLASSIFY(&values->sign.z, sizeof(values->sign.z)); - CONSTTIME_DECLASSIFY(&values->sign.h, sizeof(values->sign.h)); - - CBB cbb; - CBB_init_fixed(&cbb, out_encoded_signature, DILITHIUM_SIGNATURE_BYTES); - if (!dilithium_marshal_signature(&cbb, &values->sign)) { - goto err; - } - - BSSL_CHECK(CBB_len(&cbb) == DILITHIUM_SIGNATURE_BYTES); - ret = 1; - break; - } - -err: - OPENSSL_free(values); - return ret; -} - -// Dilithium signature in deterministic mode. Returns 1 on success and 0 on -// failure. -int DILITHIUM_sign_deterministic( - uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const struct DILITHIUM_private_key *private_key, const uint8_t *msg, - size_t msg_len) { - uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]; - OPENSSL_memset(randomizer, 0, sizeof(randomizer)); - return dilithium_sign_with_randomizer(out_encoded_signature, private_key, msg, - msg_len, randomizer); -} - -// Dilithium signature in randomized mode, filling the random bytes with -// |RAND_bytes|. Returns 1 on success and 0 on failure. -int DILITHIUM_sign(uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const struct DILITHIUM_private_key *private_key, - const uint8_t *msg, size_t msg_len) { - uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]; - RAND_bytes(randomizer, sizeof(randomizer)); - return dilithium_sign_with_randomizer(out_encoded_signature, private_key, msg, - msg_len, randomizer); -} - -// FIPS 204, Algorithm 3 (`ML-DSA.Verify`). -int DILITHIUM_verify(const struct DILITHIUM_public_key *public_key, - const uint8_t encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const uint8_t *msg, size_t msg_len) { - // Intermediate values, allocated on the heap to allow use when there is a - // limited amount of stack. - struct values_st { - struct signature sign; - matrix a_ntt; - vectorl z_ntt; - vectork az_ntt; - vectork t1_ntt; - vectork ct1_ntt; - vectork w_approx; - vectork w1; - }; - struct values_st *values = - reinterpret_cast(OPENSSL_malloc(sizeof(*values))); - if (values == NULL) { - return 0; - } - - const struct public_key *pub = public_key_from_external(public_key); - - CBS cbs; - CBS_init(&cbs, encoded_signature, DILITHIUM_SIGNATURE_BYTES); - if (!dilithium_parse_signature(&values->sign, &cbs)) { - OPENSSL_free(values); - return 0; - } - - matrix_expand(&values->a_ntt, pub->rho); - - uint8_t mu[MU_BYTES]; - struct BORINGSSL_keccak_st keccak_ctx; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, pub->public_key_hash, - sizeof(pub->public_key_hash)); - BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len); - BORINGSSL_keccak_squeeze(&keccak_ctx, mu, MU_BYTES); - - scalar c_ntt; - scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde, 32); - scalar_ntt(&c_ntt); - - OPENSSL_memcpy(&values->z_ntt, &values->sign.z, sizeof(values->z_ntt)); - vectorl_ntt(&values->z_ntt); - - matrix_mult(&values->az_ntt, &values->a_ntt, &values->z_ntt); - - vectork_scale_power2_round(&values->t1_ntt, &pub->t1); - vectork_ntt(&values->t1_ntt); - - vectork_mult_scalar(&values->ct1_ntt, &values->t1_ntt, &c_ntt); - - vectork_sub(&values->w_approx, &values->az_ntt, &values->ct1_ntt); - vectork_inverse_ntt(&values->w_approx); - - vectork_use_hint_vartime(&values->w1, &values->sign.h, &values->w_approx); - uint8_t w1_encoded[128 * K]; - w1_encode(w1_encoded, &values->w1); - - uint8_t c_tilde[2 * LAMBDA_BYTES]; - BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256); - BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES); - BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K); - BORINGSSL_keccak_squeeze(&keccak_ctx, c_tilde, 2 * LAMBDA_BYTES); - - uint32_t z_max = vectorl_max(&values->sign.z); - size_t h_ones = vectork_count_ones(&values->sign.h); - int ret = 0; - if (z_max < kGamma1 - BETA && h_ones <= OMEGA && - OPENSSL_memcmp(c_tilde, values->sign.c_tilde, 2 * LAMBDA_BYTES) == 0) { - ret = 1; - } - - OPENSSL_free(values); - return ret; -} - -/* Serialization of keys. */ - -int DILITHIUM_marshal_public_key( - CBB *out, const struct DILITHIUM_public_key *public_key) { - return dilithium_marshal_public_key(out, - public_key_from_external(public_key)); -} - -int DILITHIUM_parse_public_key(struct DILITHIUM_public_key *public_key, - CBS *in) { - struct public_key *pub = public_key_from_external(public_key); - CBS orig_in = *in; - if (!dilithium_parse_public_key(pub, in) || CBS_len(in) != 0) { - return 0; - } - - // Compute pre-cached values. - BORINGSSL_keccak(pub->public_key_hash, sizeof(pub->public_key_hash), - CBS_data(&orig_in), CBS_len(&orig_in), boringssl_shake256); - return 1; -} - -int DILITHIUM_marshal_private_key( - CBB *out, const struct DILITHIUM_private_key *private_key) { - return dilithium_marshal_private_key(out, - private_key_from_external(private_key)); -} - -int DILITHIUM_parse_private_key(struct DILITHIUM_private_key *private_key, - CBS *in) { - struct private_key *priv = private_key_from_external(private_key); - return dilithium_parse_private_key(priv, in) && CBS_len(in) == 0; -} diff --git a/Sources/CNIOBoringSSL/crypto/dilithium/internal.h b/Sources/CNIOBoringSSL/crypto/dilithium/internal.h deleted file mode 100644 index 02930691..00000000 --- a/Sources/CNIOBoringSSL/crypto/dilithium/internal.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_DILITHIUM_INTERNAL_H -#define OPENSSL_HEADER_CRYPTO_DILITHIUM_INTERNAL_H - -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - - -// DILITHIUM_GENERATE_KEY_ENTROPY is the number of bytes of uniformly random -// entropy necessary to generate a key pair. -#define DILITHIUM_GENERATE_KEY_ENTROPY 32 - -// DILITHIUM_SIGNATURE_RANDOMIZER_BYTES is the number of bytes of uniformly -// random entropy necessary to generate a signature in randomized mode. -#define DILITHIUM_SIGNATURE_RANDOMIZER_BYTES 32 - -// DILITHIUM_generate_key_external_entropy generates a public/private key pair -// using the given seed, writes the encoded public key to -// |out_encoded_public_key| and sets |out_private_key| to the private key, -// returning 1 on success and 0 on failure. Returns 1 on success and 0 on -// failure. -OPENSSL_EXPORT int DILITHIUM_generate_key_external_entropy( - uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], - struct DILITHIUM_private_key *out_private_key, - const uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]); - -// DILITHIUM_sign_deterministic generates a signature for the message |msg| of -// length |msg_len| using |private_key| following the deterministic algorithm, -// and writes the encoded signature to |out_encoded_signature|. Returns 1 on -// success and 0 on failure. -OPENSSL_EXPORT int DILITHIUM_sign_deterministic( - uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const struct DILITHIUM_private_key *private_key, const uint8_t *msg, - size_t msg_len); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_DILITHIUM_INTERNAL_H diff --git a/Sources/CNIOBoringSSL/crypto/evp/scrypt.cc b/Sources/CNIOBoringSSL/crypto/evp/scrypt.cc index 7f3765b4..a7ff5eef 100644 --- a/Sources/CNIOBoringSSL/crypto/evp/scrypt.cc +++ b/Sources/CNIOBoringSSL/crypto/evp/scrypt.cc @@ -140,7 +140,7 @@ static void scryptROMix(block_t *B, uint64_t r, uint64_t N, block_t *T, // SCRYPT_MAX_MEM is the default maximum memory that may be allocated by // |EVP_PBE_scrypt|. -#define SCRYPT_MAX_MEM (1024 * 1024 * 32) +#define SCRYPT_MAX_MEM (1024 * 1024 * 65) int EVP_PBE_scrypt(const char *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint64_t N, uint64_t r, diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/bcm_interface.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/bcm_interface.h index 9acb093c..811bd75e 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/bcm_interface.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/bcm_interface.h @@ -34,23 +34,21 @@ extern "C" { // FIPS service indicator. For the moment, the official service indicator // remains the counter, not these values. Once we fully transition to // these return values from bcm we will change that. -enum bcm_infallible_t { - bcm_infallible_approved, - bcm_infallible_not_approved, +enum class bcm_infallible_t { + approved, + not_approved, }; -enum bcm_status_t { - bcm_status_approved, - bcm_status_not_approved, - - // Failure codes, which must all be negative. - bcm_status_failure, +enum class bcm_status_t { + approved, + not_approved, + failure, }; typedef enum bcm_status_t bcm_status; typedef enum bcm_infallible_t bcm_infallible; OPENSSL_INLINE int bcm_success(bcm_status status) { - return status == bcm_status_approved || status == bcm_status_not_approved; + return status == bcm_status::approved || status == bcm_status::not_approved; } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digest.cc.inc b/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digest.cc.inc index a9b833e6..080f49a7 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digest.cc.inc +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/digest/digest.cc.inc @@ -266,24 +266,27 @@ int EVP_Digest(const void *data, size_t count, uint8_t *out_md, return ret; } - -const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) { +const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx) { if (ctx == NULL) { return NULL; } return ctx->digest; } +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) { + return EVP_MD_CTX_get0_md(ctx); +} + size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx) { - return EVP_MD_size(EVP_MD_CTX_md(ctx)); + return EVP_MD_size(EVP_MD_CTX_get0_md(ctx)); } size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) { - return EVP_MD_block_size(EVP_MD_CTX_md(ctx)); + return EVP_MD_block_size(EVP_MD_CTX_get0_md(ctx)); } int EVP_MD_CTX_type(const EVP_MD_CTX *ctx) { - return EVP_MD_type(EVP_MD_CTX_md(ctx)); + return EVP_MD_type(EVP_MD_CTX_get0_md(ctx)); } int EVP_add_digest(const EVP_MD *digest) { return 1; } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h index b1bbec44..0fbc8c3a 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/modes/internal.h @@ -190,64 +190,56 @@ void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash, // CRYPTO_gcm128_init_key initialises |gcm_key| to use |block| (typically AES) // with the given key. |block_is_hwaes| is one if |block| is |aes_hw_encrypt|. -OPENSSL_EXPORT void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, - const AES_KEY *key, block128_f block, - int block_is_hwaes); +void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, const AES_KEY *key, + block128_f block, int block_is_hwaes); // CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. The |key| must be the // same key that was passed to |CRYPTO_gcm128_init|. -OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const AES_KEY *key, - const uint8_t *iv, size_t iv_len); +void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const AES_KEY *key, + const uint8_t *iv, size_t iv_len); // CRYPTO_gcm128_aad sets the authenticated data for an instance of GCM. // This must be called before and data is encrypted. It returns one on success // and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, - size_t len); +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len); // CRYPTO_gcm128_encrypt encrypts |len| bytes from |in| to |out|. The |key| // must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one // on success and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, - const AES_KEY *key, const uint8_t *in, - uint8_t *out, size_t len); +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const AES_KEY *key, + const uint8_t *in, uint8_t *out, size_t len); // CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. The |key| // must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one // on success and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, - const AES_KEY *key, const uint8_t *in, - uint8_t *out, size_t len); +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const AES_KEY *key, + const uint8_t *in, uint8_t *out, size_t len); // CRYPTO_gcm128_encrypt_ctr32 encrypts |len| bytes from |in| to |out| using // a CTR function that only handles the bottom 32 bits of the nonce, like // |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was // passed to |CRYPTO_gcm128_init|. It returns one on success and zero // otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, - const AES_KEY *key, - const uint8_t *in, uint8_t *out, - size_t len, ctr128_f stream); +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const AES_KEY *key, + const uint8_t *in, uint8_t *out, size_t len, + ctr128_f stream); // CRYPTO_gcm128_decrypt_ctr32 decrypts |len| bytes from |in| to |out| using // a CTR function that only handles the bottom 32 bits of the nonce, like // |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was // passed to |CRYPTO_gcm128_init|. It returns one on success and zero // otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, - const AES_KEY *key, - const uint8_t *in, uint8_t *out, - size_t len, ctr128_f stream); +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const AES_KEY *key, + const uint8_t *in, uint8_t *out, size_t len, + ctr128_f stream); // CRYPTO_gcm128_finish calculates the authenticator and compares it against // |len| bytes of |tag|. It returns one on success and zero otherwise. -OPENSSL_EXPORT int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, - size_t len); +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len); // CRYPTO_gcm128_tag calculates the authenticator and copies it into |tag|. // The minimum of |len| and 16 bytes are copied into |tag|. -OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag, - size_t len); +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag, size_t len); // GCM assembly. diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/rand.cc.inc b/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/rand.cc.inc index d019341d..d351acdf 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/rand.cc.inc +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/rand/rand.cc.inc @@ -169,12 +169,12 @@ static int rdrand(uint8_t *buf, size_t len) { return 0; } bcm_status BCM_rand_bytes_hwrng(uint8_t *buf, const size_t len) { if (!have_rdrand()) { - return bcm_status_failure; + return bcm_status::failure; } if (rdrand(buf, len)) { - return bcm_status_not_approved; + return bcm_status::not_approved; } - return bcm_status_failure; + return bcm_status::failure; } #if defined(BORINGSSL_FIPS) @@ -213,7 +213,7 @@ bcm_infallible BCM_rand_load_entropy(const uint8_t *entropy, size_t entropy_len, buffer->bytes_valid += entropy_len; buffer->want_additional_input |= want_additional_input && (entropy_len != 0); CRYPTO_MUTEX_unlock_write(entropy_buffer_lock_bss_get()); - return bcm_infallible_not_approved; + return bcm_infallible::not_approved; } // get_seed_entropy fills |out_entropy_len| bytes of |out_entropy| from the @@ -330,7 +330,7 @@ static void rand_get_seed(struct rand_thread_state *state, bcm_infallible BCM_rand_bytes_with_additional_data( uint8_t *out, size_t out_len, const uint8_t user_additional_data[32]) { if (out_len == 0) { - return bcm_infallible_approved; + return bcm_infallible::approved; } const uint64_t fork_generation = CRYPTO_get_fork_generation(); @@ -471,11 +471,11 @@ bcm_infallible BCM_rand_bytes_with_additional_data( #if defined(BORINGSSL_FIPS) CRYPTO_MUTEX_unlock_read(&state->clear_drbg_lock); #endif - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_rand_bytes(uint8_t *out, size_t out_len) { static const uint8_t kZeroAdditionalData[32] = {0}; BCM_rand_bytes_with_additional_data(out, out_len, kZeroAdditionalData); - return bcm_infallible_approved; + return bcm_infallible::approved; } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc b/Sources/CNIOBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc index 7ea3c176..f2ef1c6d 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/service_indicator/service_indicator.cc.inc @@ -186,7 +186,7 @@ static int is_md_fips_approved_for_verifying(int md_type) { static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx, int (*md_ok)(int md_type)) { - if (EVP_MD_CTX_md(ctx) == NULL) { + if (EVP_MD_CTX_get0_md(ctx) == NULL) { // Signature schemes without a prehash are currently never FIPS approved. return; } diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.cc.inc b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.cc.inc index 608e7443..34806b5a 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.cc.inc +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha1.cc.inc @@ -72,7 +72,7 @@ bcm_infallible BCM_sha1_init(SHA_CTX *sha) { sha->h[2] = 0x98badcfeUL; sha->h[3] = 0x10325476UL; sha->h[4] = 0xc3d2e1f0UL; - return bcm_infallible_approved; + return bcm_infallible::approved; } #if !defined(SHA1_ASM) @@ -82,14 +82,14 @@ static void sha1_block_data_order(uint32_t state[5], const uint8_t *data, bcm_infallible BCM_sha1_transform(SHA_CTX *c, const uint8_t data[SHA_CBLOCK]) { sha1_block_data_order(c->h, data, 1); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha1_update(SHA_CTX *c, const void *data, size_t len) { crypto_md32_update(&sha1_block_data_order, c->h, c->data, SHA_CBLOCK, &c->num, &c->Nh, &c->Nl, reinterpret_cast(data), len); - return bcm_infallible_approved; + return bcm_infallible::approved; } static void sha1_output_state(uint8_t out[SHA_DIGEST_LENGTH], @@ -107,7 +107,7 @@ bcm_infallible BCM_sha1_final(uint8_t out[SHA_DIGEST_LENGTH], SHA_CTX *c) { sha1_output_state(out, c); FIPS_service_indicator_update_state(); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_fips_186_2_prf(uint8_t *out, size_t out_len, @@ -144,7 +144,7 @@ bcm_infallible BCM_fips_186_2_prf(uint8_t *out, size_t out_len, out += SHA_DIGEST_LENGTH; out_len -= SHA_DIGEST_LENGTH; } - return bcm_infallible_not_approved; + return bcm_infallible::not_approved; } #define Xupdate(a, ix, ia, ib, ic, id) \ diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.cc.inc b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.cc.inc index 836a86d5..0a7a8637 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.cc.inc +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha256.cc.inc @@ -76,7 +76,7 @@ bcm_infallible BCM_sha224_init(SHA256_CTX *sha) { sha->h[6] = 0x64f98fa7UL; sha->h[7] = 0xbefa4fa4UL; sha->md_len = BCM_SHA224_DIGEST_LENGTH; - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha256_init(SHA256_CTX *sha) { @@ -90,7 +90,7 @@ bcm_infallible BCM_sha256_init(SHA256_CTX *sha) { sha->h[6] = 0x1f83d9abUL; sha->h[7] = 0x5be0cd19UL; sha->md_len = BCM_SHA256_DIGEST_LENGTH; - return bcm_infallible_approved; + return bcm_infallible::approved; } #if !defined(SHA256_ASM) @@ -101,14 +101,14 @@ static void sha256_block_data_order(uint32_t state[8], const uint8_t *in, bcm_infallible BCM_sha256_transform(SHA256_CTX *c, const uint8_t data[BCM_SHA256_CBLOCK]) { sha256_block_data_order(c->h, data, 1); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha256_update(SHA256_CTX *c, const void *data, size_t len) { crypto_md32_update(&sha256_block_data_order, c->h, c->data, BCM_SHA256_CBLOCK, &c->num, &c->Nh, &c->Nl, reinterpret_cast(data), len); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha224_update(SHA256_CTX *ctx, const void *data, @@ -140,7 +140,7 @@ bcm_infallible BCM_sha256_final(uint8_t out[BCM_SHA256_DIGEST_LENGTH], // // TODO(davidben): Add an assert and fix code to match them up. sha256_final_impl(out, c->md_len, c); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha224_final(uint8_t out[BCM_SHA224_DIGEST_LENGTH], @@ -149,7 +149,7 @@ bcm_infallible BCM_sha224_final(uint8_t out[BCM_SHA224_DIGEST_LENGTH], // to |BCM_SHA224_DIGEST_LENGTH|. assert(ctx->md_len == BCM_SHA224_DIGEST_LENGTH); sha256_final_impl(out, BCM_SHA224_DIGEST_LENGTH, ctx); - return bcm_infallible_approved; + return bcm_infallible::approved; } #if !defined(SHA256_ASM) @@ -328,7 +328,7 @@ bcm_infallible BCM_sha256_transform_blocks(uint32_t state[8], const uint8_t *data, size_t num_blocks) { sha256_block_data_order(state, data, num_blocks); - return bcm_infallible_approved; + return bcm_infallible::approved; } #undef Sigma0 diff --git a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc index 6179ce79..c75522b4 100644 --- a/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc +++ b/Sources/CNIOBoringSSL/crypto/fipsmodule/sha/sha512.cc.inc @@ -86,7 +86,7 @@ bcm_infallible BCM_sha384_init(SHA512_CTX *sha) { sha->Nh = 0; sha->num = 0; sha->md_len = BCM_SHA384_DIGEST_LENGTH; - return bcm_infallible_approved; + return bcm_infallible::approved; } @@ -104,7 +104,7 @@ bcm_infallible BCM_sha512_init(SHA512_CTX *sha) { sha->Nh = 0; sha->num = 0; sha->md_len = BCM_SHA512_DIGEST_LENGTH; - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha512_256_init(SHA512_CTX *sha) { @@ -121,7 +121,7 @@ bcm_infallible BCM_sha512_256_init(SHA512_CTX *sha) { sha->Nh = 0; sha->num = 0; sha->md_len = BCM_SHA512_256_DIGEST_LENGTH; - return bcm_infallible_approved; + return bcm_infallible::approved; } #if !defined(SHA512_ASM) @@ -136,7 +136,7 @@ bcm_infallible BCM_sha384_final(uint8_t out[BCM_SHA384_DIGEST_LENGTH], // |sha->md_len| to |BCM_SHA384_DIGEST_LENGTH|. assert(sha->md_len == BCM_SHA384_DIGEST_LENGTH); sha512_final_impl(out, BCM_SHA384_DIGEST_LENGTH, sha); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha384_update(SHA512_CTX *sha, const void *data, @@ -155,13 +155,13 @@ bcm_infallible BCM_sha512_256_final(uint8_t out[BCM_SHA512_256_DIGEST_LENGTH], // |sha->md_len| to |BCM_SHA512_256_DIGEST_LENGTH|. assert(sha->md_len == BCM_SHA512_256_DIGEST_LENGTH); sha512_final_impl(out, BCM_SHA512_256_DIGEST_LENGTH, sha); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha512_transform(SHA512_CTX *c, const uint8_t block[SHA512_CBLOCK]) { sha512_block_data_order(c->h, block, 1); - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, @@ -171,7 +171,7 @@ bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, const uint8_t *data = reinterpret_cast(in_data); if (len == 0) { - return bcm_infallible_approved; + return bcm_infallible::approved; } l = (c->Nl + (((uint64_t)len) << 3)) & UINT64_C(0xffffffffffffffff); @@ -189,7 +189,7 @@ bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, if (len < n) { OPENSSL_memcpy(p + c->num, data, len); c->num += (unsigned int)len; - return bcm_infallible_approved; + return bcm_infallible::approved; } else { OPENSSL_memcpy(p + c->num, data, n), c->num = 0; len -= n; @@ -210,7 +210,7 @@ bcm_infallible BCM_sha512_update(SHA512_CTX *c, const void *in_data, c->num = (int)len; } - return bcm_infallible_approved; + return bcm_infallible::approved; } bcm_infallible BCM_sha512_final(uint8_t out[BCM_SHA512_DIGEST_LENGTH], @@ -221,7 +221,7 @@ bcm_infallible BCM_sha512_final(uint8_t out[BCM_SHA512_DIGEST_LENGTH], // // TODO(davidben): Add an assert and fix code to match them up. sha512_final_impl(out, sha->md_len, sha); - return bcm_infallible_approved; + return bcm_infallible::approved; } static void sha512_final_impl(uint8_t *out, size_t md_len, SHA512_CTX *sha) { diff --git a/Sources/CNIOBoringSSL/crypto/internal.h b/Sources/CNIOBoringSSL/crypto/internal.h index 2fa7fa63..0eaef7b8 100644 --- a/Sources/CNIOBoringSSL/crypto/internal.h +++ b/Sources/CNIOBoringSSL/crypto/internal.h @@ -1558,49 +1558,33 @@ OPENSSL_EXPORT int OPENSSL_vasprintf_internal(char **str, const char *format, // bit. |carry| must be zero or one. #if OPENSSL_HAS_BUILTIN(__builtin_addc) -template -struct CRYPTO_addc_impl { - static_assert(sizeof(T) == 0, "Unsupported type for addc operation"); -}; - -template <> -struct CRYPTO_addc_impl { - static unsigned int add(unsigned int x, unsigned int y, unsigned int carry, - unsigned int *out_carry) { - return __builtin_addc(x, y, carry, out_carry); - } -}; - -template <> -struct CRYPTO_addc_impl { - static unsigned long add(unsigned long x, unsigned long y, - unsigned long carry, unsigned long *out_carry) { - return __builtin_addcl(x, y, carry, out_carry); - } -}; +inline unsigned int CRYPTO_addc_impl(unsigned int x, unsigned int y, + unsigned int carry, + unsigned int *out_carry) { + return __builtin_addc(x, y, carry, out_carry); +} -template <> -struct CRYPTO_addc_impl { - static unsigned long long add(unsigned long long x, unsigned long long y, - unsigned long long carry, - unsigned long long *out_carry) { - return __builtin_addcll(x, y, carry, out_carry); - } -}; +inline unsigned long CRYPTO_addc_impl(unsigned long x, unsigned long y, + unsigned long carry, + unsigned long *out_carry) { + return __builtin_addcl(x, y, carry, out_carry); +} -template -inline T CRYPTO_addc(T x, T y, T carry, T *out_carry) { - return CRYPTO_addc_impl::add(x, y, carry, out_carry); +inline unsigned long long CRYPTO_addc_impl(unsigned long long x, + unsigned long long y, + unsigned long long carry, + unsigned long long *out_carry) { + return __builtin_addcll(x, y, carry, out_carry); } inline uint32_t CRYPTO_addc_u32(uint32_t x, uint32_t y, uint32_t carry, uint32_t *out_carry) { - return CRYPTO_addc(x, y, carry, out_carry); + return CRYPTO_addc_impl(x, y, carry, out_carry); } inline uint64_t CRYPTO_addc_u64(uint64_t x, uint64_t y, uint64_t carry, uint64_t *out_carry) { - return CRYPTO_addc(x, y, carry, out_carry); + return CRYPTO_addc_impl(x, y, carry, out_carry); } #else @@ -1638,49 +1622,33 @@ static inline uint64_t CRYPTO_addc_u64(uint64_t x, uint64_t y, uint64_t carry, // bit. |borrow| must be zero or one. #if OPENSSL_HAS_BUILTIN(__builtin_subc) -template -struct CRYPTO_subc_impl { - static_assert(sizeof(T) == 0, "Unsupported type for subc operation"); -}; - -template <> -struct CRYPTO_subc_impl { - static unsigned int sub(unsigned int x, unsigned int y, unsigned int borrow, - unsigned int *out_borrow) { - return __builtin_subc(x, y, borrow, out_borrow); - } -}; - -template <> -struct CRYPTO_subc_impl { - static unsigned long sub(unsigned long x, unsigned long y, - unsigned long borrow, unsigned long *out_borrow) { - return __builtin_subcl(x, y, borrow, out_borrow); - } -}; +inline unsigned int CRYPTO_subc_impl(unsigned int x, unsigned int y, + unsigned int borrow, + unsigned int *out_borrow) { + return __builtin_subc(x, y, borrow, out_borrow); +} -template <> -struct CRYPTO_subc_impl { - static unsigned long long sub(unsigned long long x, unsigned long long y, - unsigned long long borrow, - unsigned long long *out_borrow) { - return __builtin_subcll(x, y, borrow, out_borrow); - } -}; +inline unsigned long CRYPTO_subc_impl(unsigned long x, unsigned long y, + unsigned long borrow, + unsigned long *out_borrow) { + return __builtin_subcl(x, y, borrow, out_borrow); +} -template -inline T CRYPTO_subc(T x, T y, T borrow, T *out_borrow) { - return CRYPTO_subc_impl::sub(x, y, borrow, out_borrow); +inline unsigned long long CRYPTO_subc_impl(unsigned long long x, + unsigned long long y, + unsigned long long borrow, + unsigned long long *out_borrow) { + return __builtin_subcll(x, y, borrow, out_borrow); } inline uint32_t CRYPTO_subc_u32(uint32_t x, uint32_t y, uint32_t borrow, uint32_t *out_borrow) { - return CRYPTO_subc(x, y, borrow, out_borrow); + return CRYPTO_subc_impl(x, y, borrow, out_borrow); } inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow, uint64_t *out_borrow) { - return CRYPTO_subc(x, y, borrow, out_borrow); + return CRYPTO_subc_impl(x, y, borrow, out_borrow); } #else diff --git a/Sources/CNIOBoringSSL/crypto/md4/md4.cc b/Sources/CNIOBoringSSL/crypto/md4/md4.cc index fa86dea2..efb53ee3 100644 --- a/Sources/CNIOBoringSSL/crypto/md4/md4.cc +++ b/Sources/CNIOBoringSSL/crypto/md4/md4.cc @@ -83,7 +83,8 @@ int MD4_Init(MD4_CTX *md4) { return 1; } -void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num); +static void md4_block_data_order(uint32_t *state, const uint8_t *data, + size_t num); void MD4_Transform(MD4_CTX *c, const uint8_t data[MD4_CBLOCK]) { md4_block_data_order(c->h, data, 1); @@ -132,7 +133,8 @@ int MD4_Final(uint8_t out[MD4_DIGEST_LENGTH], MD4_CTX *c) { (a) = CRYPTO_rotl_u32(a, s); \ } while (0) -void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) { +static void md4_block_data_order(uint32_t *state, const uint8_t *data, + size_t num) { uint32_t A, B, C, D; uint32_t X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15; diff --git a/Sources/CNIOBoringSSL/crypto/mlkem/mlkem.cc b/Sources/CNIOBoringSSL/crypto/mlkem/mlkem.cc index 07ad62e4..bffca331 100644 --- a/Sources/CNIOBoringSSL/crypto/mlkem/mlkem.cc +++ b/Sources/CNIOBoringSSL/crypto/mlkem/mlkem.cc @@ -75,11 +75,11 @@ static const int kDV768 = 4; static const int kDU1024 = 11; static const int kDV1024 = 5; -constexpr size_t encoded_vector_size(int rank) { +static constexpr size_t encoded_vector_size(int rank) { return (kLog2Prime * DEGREE / 8) * static_cast(rank); } -constexpr size_t encoded_public_key_size(int rank) { +static constexpr size_t encoded_public_key_size(int rank) { return encoded_vector_size(rank) + /*sizeof(rho)=*/32; } @@ -88,13 +88,13 @@ static_assert(encoded_public_key_size(RANK768) == MLKEM768_PUBLIC_KEY_BYTES, static_assert(encoded_public_key_size(RANK1024) == MLKEM1024_PUBLIC_KEY_BYTES, ""); -constexpr size_t compressed_vector_size(int rank) { +static constexpr size_t compressed_vector_size(int rank) { // `if constexpr` isn't available in C++17. return (rank == RANK768 ? kDU768 : kDU1024) * static_cast(rank) * DEGREE / 8; } -constexpr size_t ciphertext_size(int rank) { +static constexpr size_t ciphertext_size(int rank) { return compressed_vector_size(rank) + (rank == RANK768 ? kDV768 : kDV1024) * DEGREE / 8; } @@ -743,9 +743,9 @@ static int mlkem_marshal_public_key(CBB *out, } template -void mlkem_generate_key_external_seed(uint8_t *out_encoded_public_key, - private_key *priv, - const uint8_t seed[MLKEM_SEED_BYTES]) { +static void mlkem_generate_key_external_seed( + uint8_t *out_encoded_public_key, private_key *priv, + const uint8_t seed[MLKEM_SEED_BYTES]) { uint8_t augmented_seed[33]; OPENSSL_memcpy(augmented_seed, seed, 32); augmented_seed[32] = RANK; diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx.cc b/Sources/CNIOBoringSSL/crypto/spx/spx.cc deleted file mode 100644 index cd1bedcf..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 - -#define OPENSSL_UNSTABLE_EXPERIMENTAL_SPX -#include -#include - -#include "./spx_address.h" -#include "./spx_fors.h" -#include "./spx_merkle.h" -#include "./spx_params.h" -#include "./spx_util.h" -#include "./spx_thash.h" - -void SPX_generate_key(uint8_t out_public_key[SPX_PUBLIC_KEY_BYTES], - uint8_t out_secret_key[SPX_SECRET_KEY_BYTES]) { - uint8_t seed[3 * SPX_N]; - RAND_bytes(seed, 3 * SPX_N); - SPX_generate_key_from_seed(out_public_key, out_secret_key, seed); -} - -void SPX_generate_key_from_seed(uint8_t out_public_key[SPX_PUBLIC_KEY_BYTES], - uint8_t out_secret_key[SPX_SECRET_KEY_BYTES], - const uint8_t seed[3 * SPX_N]) { - // Initialize SK.seed || SK.prf || PK.seed from seed. - memcpy(out_secret_key, seed, 3 * SPX_N); - - // Initialize PK.seed from seed. - memcpy(out_public_key, seed + 2 * SPX_N, SPX_N); - - uint8_t addr[32] = {0}; - spx_set_layer_addr(addr, SPX_D - 1); - - // Set PK.root - spx_treehash(out_public_key + SPX_N, out_secret_key, 0, SPX_TREE_HEIGHT, - out_public_key, addr); - memcpy(out_secret_key + 3 * SPX_N, out_public_key + SPX_N, SPX_N); -} - -void SPX_sign(uint8_t out_signature[SPX_SIGNATURE_BYTES], - const uint8_t secret_key[SPX_SECRET_KEY_BYTES], - const uint8_t *msg, size_t msg_len, int randomized) { - uint8_t addr[32] = {0}; - const uint8_t *sk_seed = secret_key; - const uint8_t *sk_prf = secret_key + SPX_N; - const uint8_t *pk_seed = secret_key + 2 * SPX_N; - const uint8_t *pk_root = secret_key + 3 * SPX_N; - - uint8_t opt_rand[SPX_N] = {0}; - - if (randomized) { - RAND_bytes(opt_rand, SPX_N); - } else { - memcpy(opt_rand, pk_seed, SPX_N); - } - - // Derive randomizer r and copy it to signature. - uint8_t r[SPX_N]; - spx_thash_prfmsg(r, sk_prf, opt_rand, msg, msg_len); - memcpy(out_signature, r, SPX_N); - - uint8_t digest[SPX_DIGEST_SIZE]; - spx_thash_hmsg(digest, r, pk_seed, pk_root, msg, msg_len); - - uint8_t fors_digest[SPX_FORS_MSG_BYTES]; - memcpy(fors_digest, digest, SPX_FORS_MSG_BYTES); - - uint8_t *tmp_idx_tree = digest + SPX_FORS_MSG_BYTES; - uint8_t *tmp_idx_leaf = tmp_idx_tree + SPX_TREE_BYTES; - - uint64_t idx_tree = spx_to_uint64(tmp_idx_tree, SPX_TREE_BYTES); - idx_tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - - uint32_t idx_leaf = (uint32_t)spx_to_uint64(tmp_idx_leaf, SPX_LEAF_BYTES); - idx_leaf &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); - - spx_set_tree_addr(addr, idx_tree); - spx_set_type(addr, SPX_ADDR_TYPE_FORSTREE); - spx_set_keypair_addr(addr, idx_leaf); - - spx_fors_sign(out_signature + SPX_N, fors_digest, sk_seed, pk_seed, addr); - - uint8_t pk_fors[SPX_N]; - spx_fors_pk_from_sig(pk_fors, out_signature + SPX_N, fors_digest, pk_seed, - addr); - - spx_ht_sign(out_signature + SPX_N + SPX_FORS_BYTES, pk_fors, idx_tree, - idx_leaf, sk_seed, pk_seed); -} - -int SPX_verify(const uint8_t signature[SPX_SIGNATURE_BYTES], - const uint8_t public_key[SPX_SECRET_KEY_BYTES], - const uint8_t *msg, size_t msg_len) { - uint8_t addr[32] = {0}; - const uint8_t *pk_seed = public_key; - const uint8_t *pk_root = public_key + SPX_N; - - const uint8_t *r = signature; - const uint8_t *sig_fors = signature + SPX_N; - const uint8_t *sig_ht = sig_fors + SPX_FORS_BYTES; - - uint8_t digest[SPX_DIGEST_SIZE]; - spx_thash_hmsg(digest, r, pk_seed, pk_root, msg, msg_len); - - uint8_t fors_digest[SPX_FORS_MSG_BYTES]; - memcpy(fors_digest, digest, SPX_FORS_MSG_BYTES); - - uint8_t *tmp_idx_tree = digest + SPX_FORS_MSG_BYTES; - uint8_t *tmp_idx_leaf = tmp_idx_tree + SPX_TREE_BYTES; - - uint64_t idx_tree = spx_to_uint64(tmp_idx_tree, SPX_TREE_BYTES); - idx_tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS); - - uint32_t idx_leaf = (uint32_t)spx_to_uint64(tmp_idx_leaf, SPX_LEAF_BYTES); - idx_leaf &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS); - - spx_set_tree_addr(addr, idx_tree); - spx_set_type(addr, SPX_ADDR_TYPE_FORSTREE); - spx_set_keypair_addr(addr, idx_leaf); - - uint8_t pk_fors[SPX_N]; - spx_fors_pk_from_sig(pk_fors, sig_fors, fors_digest, pk_seed, addr); - - return spx_ht_verify(sig_ht, pk_fors, idx_tree, idx_leaf, pk_root, pk_seed); -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_address.cc b/Sources/CNIOBoringSSL/crypto/spx/spx_address.cc deleted file mode 100644 index 2a1e6ff5..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_address.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 "../internal.h" -#include "./spx_address.h" -#include "./spx_util.h" - - -// Offsets of various fields in the address structure for SPHINCS+-SHA2-128s. - -// The byte used to specify the Merkle tree layer. -#define SPX_OFFSET_LAYER 0 - -// The start of the 8 byte field used to specify the tree. -#define SPX_OFFSET_TREE 1 - -// The byte used to specify the hash type (reason). -#define SPX_OFFSET_TYPE 9 - -// The high byte used to specify the key pair (which one-time signature). -#define SPX_OFFSET_KP_ADDR2 12 - -// The low byte used to specific the key pair. -#define SPX_OFFSET_KP_ADDR1 13 - -// The byte used to specify the chain address (which Winternitz chain). -#define SPX_OFFSET_CHAIN_ADDR 17 - -// The byte used to specify the hash address (where in the Winternitz chain). -#define SPX_OFFSET_HASH_ADDR 21 - -// The byte used to specify the height of this node in the FORS or Merkle tree. -#define SPX_OFFSET_TREE_HGT 17 - -// The start of the 4 byte field used to specify the node in the FORS or Merkle -// tree. -#define SPX_OFFSET_TREE_INDEX 18 - - -void spx_set_chain_addr(uint8_t addr[32], uint32_t chain) { - addr[SPX_OFFSET_CHAIN_ADDR] = (uint8_t)chain; -} - -void spx_set_hash_addr(uint8_t addr[32], uint32_t hash) { - addr[SPX_OFFSET_HASH_ADDR] = (uint8_t)hash; -} - -void spx_set_keypair_addr(uint8_t addr[32], uint32_t keypair) { - addr[SPX_OFFSET_KP_ADDR2] = (uint8_t)(keypair >> 8); - addr[SPX_OFFSET_KP_ADDR1] = (uint8_t)keypair; -} - -void spx_copy_keypair_addr(uint8_t out[32], const uint8_t in[32]) { - memcpy(out, in, SPX_OFFSET_TREE + 8); - out[SPX_OFFSET_KP_ADDR2] = in[SPX_OFFSET_KP_ADDR2]; - out[SPX_OFFSET_KP_ADDR1] = in[SPX_OFFSET_KP_ADDR1]; -} - -void spx_set_layer_addr(uint8_t addr[32], uint32_t layer) { - addr[SPX_OFFSET_LAYER] = (uint8_t)layer; -} - -void spx_set_tree_addr(uint8_t addr[32], uint64_t tree) { - spx_uint64_to_len_bytes(&addr[SPX_OFFSET_TREE], 8, tree); -} - -void spx_set_type(uint8_t addr[32], uint32_t type) { - // NIST draft relies on this setting parts of the address to 0, so we do it - // here to avoid confusion. - // - // The behavior here is only correct for the SHA2 instantiations. - memset(addr + 10, 0, 12); - addr[SPX_OFFSET_TYPE] = (uint8_t)type; -} - -void spx_set_tree_height(uint8_t addr[32], uint32_t tree_height) { - addr[SPX_OFFSET_TREE_HGT] = (uint8_t)tree_height; -} - -void spx_set_tree_index(uint8_t addr[32], uint32_t tree_index) { - CRYPTO_store_u32_be(&addr[SPX_OFFSET_TREE_INDEX], tree_index); -} - -uint32_t spx_get_tree_index(uint8_t addr[32]) { - return CRYPTO_load_u32_be(addr + SPX_OFFSET_TREE_INDEX); -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_address.h b/Sources/CNIOBoringSSL/crypto/spx/spx_address.h deleted file mode 100644 index 7e2499fb..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_address.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_ADDRESS_H -#define OPENSSL_HEADER_CRYPTO_SPX_ADDRESS_H - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - - -#define SPX_ADDR_TYPE_WOTS 0 -#define SPX_ADDR_TYPE_WOTSPK 1 -#define SPX_ADDR_TYPE_HASHTREE 2 -#define SPX_ADDR_TYPE_FORSTREE 3 -#define SPX_ADDR_TYPE_FORSPK 4 -#define SPX_ADDR_TYPE_WOTSPRF 5 -#define SPX_ADDR_TYPE_FORSPRF 6 - -void spx_set_chain_addr(uint8_t addr[32], uint32_t chain); -void spx_set_hash_addr(uint8_t addr[32], uint32_t hash); -void spx_set_keypair_addr(uint8_t addr[32], uint32_t keypair); -void spx_set_layer_addr(uint8_t addr[32], uint32_t layer); -void spx_set_tree_addr(uint8_t addr[32], uint64_t tree); -void spx_set_type(uint8_t addr[32], uint32_t type); -void spx_set_tree_height(uint8_t addr[32], uint32_t tree_height); -void spx_set_tree_index(uint8_t addr[32], uint32_t tree_index); -void spx_copy_keypair_addr(uint8_t out[32], const uint8_t in[32]); - -uint32_t spx_get_tree_index(uint8_t addr[32]); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_ADDRESS_H diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_fors.cc b/Sources/CNIOBoringSSL/crypto/spx/spx_fors.cc deleted file mode 100644 index 937a205f..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_fors.cc +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 "./spx_address.h" -#include "./spx_fors.h" -#include "./spx_params.h" -#include "./spx_util.h" -#include "./spx_thash.h" - -void spx_fors_sk_gen(uint8_t *fors_sk, uint32_t idx, - const uint8_t sk_seed[SPX_N], const uint8_t pk_seed[SPX_N], - uint8_t addr[32]) { - uint8_t sk_addr[32]; - memcpy(sk_addr, addr, sizeof(sk_addr)); - - spx_set_type(sk_addr, SPX_ADDR_TYPE_FORSPRF); - spx_copy_keypair_addr(sk_addr, addr); - spx_set_tree_index(sk_addr, idx); - spx_thash_prf(fors_sk, pk_seed, sk_seed, sk_addr); -} - -void spx_fors_treehash(uint8_t root_node[SPX_N], const uint8_t sk_seed[SPX_N], - uint32_t i /*target node index*/, - uint32_t z /*target node height*/, - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - - BSSL_CHECK(z <= SPX_FORS_HEIGHT); - BSSL_CHECK(i < (uint32_t)(SPX_FORS_TREES * (1 << (SPX_FORS_HEIGHT - z)))); - - if (z == 0) { - uint8_t sk[SPX_N]; - spx_set_tree_height(addr, 0); - spx_set_tree_index(addr, i); - spx_fors_sk_gen(sk, i, sk_seed, pk_seed, addr); - spx_thash_f(root_node, sk, pk_seed, addr); - } else { - // Stores left node and right node. - uint8_t nodes[2 * SPX_N]; - spx_fors_treehash(nodes, sk_seed, 2 * i, z - 1, pk_seed, addr); - spx_fors_treehash(nodes + SPX_N, sk_seed, 2 * i + 1, z - 1, pk_seed, addr); - spx_set_tree_height(addr, z); - spx_set_tree_index(addr, i); - spx_thash_h(root_node, nodes, pk_seed, addr); - } -} - -void spx_fors_sign(uint8_t *fors_sig, const uint8_t message[SPX_FORS_MSG_BYTES], - const uint8_t sk_seed[SPX_N], const uint8_t pk_seed[SPX_N], - uint8_t addr[32]) { - uint32_t indices[SPX_FORS_TREES]; - - // Derive FORS indices compatible with the NIST changes. - spx_base_b(indices, SPX_FORS_TREES, message, /*log2_b=*/SPX_FORS_HEIGHT); - - for (size_t i = 0; i < SPX_FORS_TREES; ++i) { - spx_set_tree_height(addr, 0); - // Write the FORS secret key element to the correct position. - spx_fors_sk_gen(fors_sig + i * SPX_N * (SPX_FORS_HEIGHT + 1), - i * (1 << SPX_FORS_HEIGHT) + indices[i], sk_seed, pk_seed, - addr); - for (size_t j = 0; j < SPX_FORS_HEIGHT; ++j) { - size_t s = (indices[i] / (1 << j)) ^ 1; - // Write the FORS auth path element to the correct position. - spx_fors_treehash(fors_sig + SPX_N * (i * (SPX_FORS_HEIGHT + 1) + j + 1), - sk_seed, i * (1ULL << (SPX_FORS_HEIGHT - j)) + s, j, - pk_seed, addr); - } - } -} - -void spx_fors_pk_from_sig(uint8_t *fors_pk, - const uint8_t fors_sig[SPX_FORS_BYTES], - const uint8_t message[SPX_FORS_MSG_BYTES], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - uint32_t indices[SPX_FORS_TREES]; - uint8_t tmp[2 * SPX_N]; - uint8_t roots[SPX_FORS_TREES * SPX_N]; - - // Derive FORS indices compatible with the NIST changes. - spx_base_b(indices, SPX_FORS_TREES, message, /*log2_b=*/SPX_FORS_HEIGHT); - - for (size_t i = 0; i < SPX_FORS_TREES; ++i) { - // Pointer to current sk and authentication path - const uint8_t *sk = fors_sig + i * SPX_N * (SPX_FORS_HEIGHT + 1); - const uint8_t *auth = fors_sig + i * SPX_N * (SPX_FORS_HEIGHT + 1) + SPX_N; - uint8_t nodes[2 * SPX_N]; - - spx_set_tree_height(addr, 0); - spx_set_tree_index(addr, (i * (1 << SPX_FORS_HEIGHT)) + indices[i]); - - spx_thash_f(nodes, sk, pk_seed, addr); - - for (size_t j = 0; j < SPX_FORS_HEIGHT; ++j) { - spx_set_tree_height(addr, j + 1); - - // Even node - if (((indices[i] / (1 << j)) % 2) == 0) { - spx_set_tree_index(addr, spx_get_tree_index(addr) / 2); - memcpy(tmp, nodes, SPX_N); - memcpy(tmp + SPX_N, auth + j * SPX_N, SPX_N); - spx_thash_h(nodes + SPX_N, tmp, pk_seed, addr); - } else { - spx_set_tree_index(addr, (spx_get_tree_index(addr) - 1) / 2); - memcpy(tmp, auth + j * SPX_N, SPX_N); - memcpy(tmp + SPX_N, nodes, SPX_N); - spx_thash_h(nodes + SPX_N, tmp, pk_seed, addr); - } - memcpy(nodes, nodes + SPX_N, SPX_N); - } - memcpy(roots + i * SPX_N, nodes, SPX_N); - } - - uint8_t forspk_addr[32]; - memcpy(forspk_addr, addr, sizeof(forspk_addr)); - spx_set_type(forspk_addr, SPX_ADDR_TYPE_FORSPK); - spx_copy_keypair_addr(forspk_addr, addr); - spx_thash_tk(fors_pk, roots, pk_seed, forspk_addr); -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_fors.h b/Sources/CNIOBoringSSL/crypto/spx/spx_fors.h deleted file mode 100644 index b5e4ee64..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_fors.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_FORS_H -#define OPENSSL_HEADER_CRYPTO_SPX_FORS_H - -#include - -#include "./spx_params.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -// Algorithm 13: Generate a FORS private key value. -void spx_fors_sk_gen(uint8_t *fors_sk, uint32_t idx, - const uint8_t sk_seed[SPX_N], const uint8_t pk_seed[SPX_N], - uint8_t addr[32]); - -// Algorithm 14: Compute the root of a Merkle subtree of FORS public values. -void spx_fors_treehash(uint8_t root_node[SPX_N], const uint8_t sk_seed[SPX_N], - uint32_t i /*target node index*/, - uint32_t z /*target node height*/, - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - -// Algorithm 15: Generate a FORS signature. -void spx_fors_sign(uint8_t *fors_sig, const uint8_t message[SPX_FORS_MSG_BYTES], - const uint8_t sk_seed[SPX_N], const uint8_t pk_seed[SPX_N], - uint8_t addr[32]); - -// Algorithm 16: Compute a FORS public key from a FORS signature. -void spx_fors_pk_from_sig(uint8_t *fors_pk, - const uint8_t fors_sig[SPX_FORS_BYTES], - const uint8_t message[SPX_FORS_MSG_BYTES], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_FORS_H diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_merkle.cc b/Sources/CNIOBoringSSL/crypto/spx/spx_merkle.cc deleted file mode 100644 index e49ee025..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_merkle.cc +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 "./spx_address.h" -#include "./spx_merkle.h" -#include "./spx_params.h" -#include "./spx_thash.h" -#include "./spx_wots.h" - -void spx_treehash(uint8_t out_pk[SPX_N], const uint8_t sk_seed[SPX_N], - uint32_t i /*target node index*/, - uint32_t z /*target node height*/, - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - BSSL_CHECK(z <= SPX_TREE_HEIGHT); - BSSL_CHECK(i < (uint32_t)(1 << (SPX_TREE_HEIGHT - z))); - - if (z == 0) { - spx_set_type(addr, SPX_ADDR_TYPE_WOTS); - spx_set_keypair_addr(addr, i); - spx_wots_pk_gen(out_pk, sk_seed, pk_seed, addr); - } else { - // Stores left node and right node. - uint8_t nodes[2 * SPX_N]; - spx_treehash(nodes, sk_seed, 2 * i, z - 1, pk_seed, addr); - spx_treehash(nodes + SPX_N, sk_seed, 2 * i + 1, z - 1, pk_seed, addr); - spx_set_type(addr, SPX_ADDR_TYPE_HASHTREE); - spx_set_tree_height(addr, z); - spx_set_tree_index(addr, i); - spx_thash_h(out_pk, nodes, pk_seed, addr); - } -} - -void spx_xmss_sign(uint8_t *sig, const uint8_t msg[SPX_N], unsigned int idx, - const uint8_t sk_seed[SPX_N], const uint8_t pk_seed[SPX_N], - uint8_t addr[32]) { - // Build authentication path - for (size_t j = 0; j < SPX_TREE_HEIGHT; ++j) { - unsigned int k = (idx >> j) ^ 1; - spx_treehash(sig + SPX_WOTS_BYTES + j * SPX_N, sk_seed, k, j, pk_seed, - addr); - } - - // Compute WOTS+ signature - spx_set_type(addr, SPX_ADDR_TYPE_WOTS); - spx_set_keypair_addr(addr, idx); - spx_wots_sign(sig, msg, sk_seed, pk_seed, addr); -} - -void spx_xmss_pk_from_sig(uint8_t *root, const uint8_t *xmss_sig, - unsigned int idx, const uint8_t msg[SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - // Stores node[0] and node[1] from Algorithm 10 - uint8_t node[2 * SPX_N]; - uint8_t tmp[2 * SPX_N]; - spx_set_type(addr, SPX_ADDR_TYPE_WOTS); - spx_set_keypair_addr(addr, idx); - spx_wots_pk_from_sig(node, xmss_sig, msg, pk_seed, addr); - - const uint8_t *auth = xmss_sig + SPX_WOTS_BYTES; - - spx_set_type(addr, SPX_ADDR_TYPE_HASHTREE); - spx_set_tree_index(addr, idx); - for (size_t k = 0; k < SPX_TREE_HEIGHT; ++k) { - spx_set_tree_height(addr, k + 1); - // Is even - if (((idx >> k) & 1) == 0) { - spx_set_tree_index(addr, spx_get_tree_index(addr) >> 1); - memcpy(tmp, node, SPX_N); - memcpy(tmp + SPX_N, auth + k * SPX_N, SPX_N); - spx_thash_h(node + SPX_N, tmp, pk_seed, addr); - } else { - spx_set_tree_index(addr, (spx_get_tree_index(addr) - 1) >> 1); - memcpy(tmp, auth + k * SPX_N, SPX_N); - memcpy(tmp + SPX_N, node, SPX_N); - spx_thash_h(node + SPX_N, tmp, pk_seed, addr); - } - memcpy(node, node + SPX_N, SPX_N); - } - memcpy(root, node, SPX_N); -} - -void spx_ht_sign(uint8_t *sig, const uint8_t message[SPX_N], uint64_t idx_tree, - uint32_t idx_leaf, const uint8_t sk_seed[SPX_N], - const uint8_t pk_seed[SPX_N]) { - uint8_t addr[32] = {0}; - spx_set_tree_addr(addr, idx_tree); - - // Layer 0 - uint8_t sig_tmp[SPX_XMSS_BYTES]; - spx_xmss_sign(sig_tmp, message, idx_leaf, sk_seed, pk_seed, addr); - memcpy(sig, sig_tmp, sizeof(sig_tmp)); - - uint8_t root[SPX_N]; - spx_xmss_pk_from_sig(root, sig_tmp, idx_leaf, message, pk_seed, addr); - - // All other layers - for (size_t j = 1; j < SPX_D; ++j) { - idx_leaf = idx_tree % (1 << SPX_TREE_HEIGHT); - idx_tree = idx_tree >> SPX_TREE_HEIGHT; - spx_set_layer_addr(addr, j); - spx_set_tree_addr(addr, idx_tree); - spx_xmss_sign(sig_tmp, root, idx_leaf, sk_seed, pk_seed, addr); - memcpy(sig + j * SPX_XMSS_BYTES, sig_tmp, sizeof(sig_tmp)); - - if (j < (SPX_D - 1)) { - spx_xmss_pk_from_sig(root, sig_tmp, idx_leaf, root, pk_seed, addr); - } - } -} - -int spx_ht_verify(const uint8_t sig[SPX_D * SPX_XMSS_BYTES], - const uint8_t message[SPX_N], uint64_t idx_tree, - uint32_t idx_leaf, const uint8_t pk_root[SPX_N], - const uint8_t pk_seed[SPX_N]) { - uint8_t addr[32] = {0}; - spx_set_tree_addr(addr, idx_tree); - - uint8_t sig_tmp[SPX_XMSS_BYTES]; - memcpy(sig_tmp, sig, sizeof(sig_tmp)); - - uint8_t node[SPX_N]; - spx_xmss_pk_from_sig(node, sig_tmp, idx_leaf, message, pk_seed, addr); - - for (size_t j = 1; j < SPX_D; ++j) { - idx_leaf = idx_tree % (1 << SPX_TREE_HEIGHT); - idx_tree = idx_tree >> SPX_TREE_HEIGHT; - spx_set_layer_addr(addr, j); - spx_set_tree_addr(addr, idx_tree); - // Get jth XMSS signature - memcpy(sig_tmp, sig + j * SPX_XMSS_BYTES, sizeof(sig_tmp)); - - spx_xmss_pk_from_sig(node, sig_tmp, idx_leaf, node, pk_seed, addr); - } - return memcmp(node, pk_root, SPX_N) == 0; -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_merkle.h b/Sources/CNIOBoringSSL/crypto/spx/spx_merkle.h deleted file mode 100644 index 98d60166..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_merkle.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_MERKLE_H -#define OPENSSL_HEADER_CRYPTO_SPX_MERKLE_H - -#include - -#include - -#include "./spx_params.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -// Algorithm 8: Compute the root of a Merkle subtree of WOTS+ public keys. -void spx_treehash(uint8_t out_pk[SPX_N], const uint8_t sk_seed[SPX_N], - uint32_t i /*target node index*/, - uint32_t z /*target node height*/, - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - -// Algorithm 9: Generate an XMSS signature. -void spx_xmss_sign(uint8_t *sig, const uint8_t msg[SPX_N], unsigned int idx, - const uint8_t sk_seed[SPX_N], const uint8_t pk_seed[SPX_N], - uint8_t addr[32]); - -// Algorithm 10: Compute an XMSS public key from an XMSS signature. -void spx_xmss_pk_from_sig(uint8_t *root, const uint8_t *xmss_sig, - unsigned int idx, const uint8_t msg[SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - -// Algorithm 11: Generate a hypertree signature. -void spx_ht_sign(uint8_t *sig, const uint8_t message[SPX_N], uint64_t idx_tree, - uint32_t idx_leaf, const uint8_t sk_seed[SPX_N], - const uint8_t pk_seed[SPX_N]); - -// Algorithm 12: Verify a hypertree signature. -int spx_ht_verify(const uint8_t sig[SPX_D * SPX_XMSS_BYTES], - const uint8_t message[SPX_N], uint64_t idx_tree, - uint32_t idx_leaf, const uint8_t pk_root[SPX_N], - const uint8_t pk_seed[SPX_N]); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_MERKLE_H diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_params.h b/Sources/CNIOBoringSSL/crypto/spx/spx_params.h deleted file mode 100644 index cc7fd102..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_params.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_PARAMS_H -#define OPENSSL_HEADER_CRYPTO_SPX_PARAMS_H - -#if defined(__cplusplus) -extern "C" { -#endif - - -// Output length of the hash function. -#define SPX_N 16 -// Total height of the tree structure. -#define SPX_FULL_HEIGHT 63 -// Number of subtree layers. -#define SPX_D 7 -// Height of the trees on each layer -#define SPX_TREE_HEIGHT 9 -// Height of each individual FORS tree. -#define SPX_FORS_HEIGHT 12 -// Total number of FORS tree used. -#define SPX_FORS_TREES 14 -// Size of a FORS signature -#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N) - -// Winternitz parameter and derived values -#define SPX_WOTS_W 16 -#define SPX_WOTS_LOG_W 4 -#define SPX_WOTS_LEN1 32 -#define SPX_WOTS_LEN2 3 -#define SPX_WOTS_LEN 35 -#define SPX_WOTS_BYTES (SPX_N * SPX_WOTS_LEN) - -// XMSS sizes -#define SPX_XMSS_BYTES (SPX_WOTS_BYTES + (SPX_N * SPX_TREE_HEIGHT)) - -// Size of the message digest (NOTE: This is only correct for the SHA256 params -// here) -#define SPX_DIGEST_SIZE \ - (((SPX_FORS_TREES * SPX_FORS_HEIGHT) / 8) + \ - (((SPX_FULL_HEIGHT - SPX_TREE_HEIGHT) / 8) + 1) + (SPX_TREE_HEIGHT / 8) + \ - 1) - -// Compressed address size when using SHA256 -#define SPX_SHA256_ADDR_BYTES 22 - -// Size of the FORS message hash -#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8) -#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1)) -#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8) -#define SPX_LEAF_BITS SPX_TREE_HEIGHT -#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8) - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_PARAMS_H diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_thash.cc b/Sources/CNIOBoringSSL/crypto/spx/spx_thash.cc deleted file mode 100644 index 2a12524a..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_thash.cc +++ /dev/null @@ -1,136 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 "./spx_params.h" -#include "./spx_util.h" -#include "./spx_thash.h" - -static void spx_thash(uint8_t *output, const uint8_t *input, - size_t input_blocks, const uint8_t pk_seed[SPX_N], - uint8_t addr[32]) { - uint8_t hash[32]; - SHA256_CTX sha256; - SHA256_Init(&sha256); - - // Process pubseed with padding to full block. - // TODO: This could be precomputed instead as it will be the same across all - // hash calls. - uint8_t padded_pk_seed[64] = {0}; - memcpy(padded_pk_seed, pk_seed, SPX_N); - - SHA256_Update(&sha256, padded_pk_seed, sizeof(padded_pk_seed)); - SHA256_Update(&sha256, addr, SPX_SHA256_ADDR_BYTES); - SHA256_Update(&sha256, input, input_blocks * SPX_N); - - SHA256_Final(hash, &sha256); - memcpy(output, hash, SPX_N); -} - -void spx_thash_f(uint8_t *output, const uint8_t input[SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - spx_thash(output, input, 1, pk_seed, addr); -} - -void spx_thash_h(uint8_t *output, const uint8_t input[2 * SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - spx_thash(output, input, 2, pk_seed, addr); -} - -void spx_thash_hmsg(uint8_t *output, const uint8_t r[SPX_N], - const uint8_t pk_seed[SPX_N], const uint8_t pk_root[SPX_N], - const uint8_t *msg, size_t msg_len) { - // MGF1-SHA-256(R || PK.seed || SHA-256(R || PK.seed || PK.root || M), m) - // input_buffer stores R || PK_SEED || SHA256(..) || 4-byte index - uint8_t input_buffer[2 * SPX_N + 32 + 4] = {0}; - memcpy(input_buffer, r, SPX_N); - memcpy(input_buffer + SPX_N, pk_seed, SPX_N); - - // Inner hash - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, r, SPX_N); - SHA256_Update(&ctx, pk_seed, SPX_N); - SHA256_Update(&ctx, pk_root, SPX_N); - SHA256_Update(&ctx, msg, msg_len); - // Write directly into the input buffer - SHA256_Final(input_buffer + 2 * SPX_N, &ctx); - - // MGF1-SHA-256 - uint8_t output_buffer[3 * 32]; - // Need to call SHA256 3 times for message digest. - static_assert(SPX_DIGEST_SIZE <= sizeof(output_buffer), - "not enough room for hashes"); - SHA256(input_buffer, sizeof(input_buffer), output_buffer); - input_buffer[2 * SPX_N + 32 + 3] = 1; - SHA256(input_buffer, sizeof(input_buffer), output_buffer + 32); - input_buffer[2 * SPX_N + 32 + 3] = 2; - SHA256(input_buffer, sizeof(input_buffer), output_buffer + 64); - - memcpy(output, output_buffer, SPX_DIGEST_SIZE); -} - -void spx_thash_prf(uint8_t *output, const uint8_t pk_seed[SPX_N], - const uint8_t sk_seed[SPX_N], uint8_t addr[32]) { - spx_thash(output, sk_seed, 1, pk_seed, addr); -} - -void spx_thash_prfmsg(uint8_t *output, const uint8_t sk_prf[SPX_N], - const uint8_t opt_rand[SPX_N], const uint8_t *msg, - size_t msg_len) { - // Compute HMAC-SHA256(sk_prf, opt_rand || msg). We inline HMAC to avoid an - // allocation. - uint8_t hmac_key[SHA256_CBLOCK] = {0}; - static_assert(SPX_N <= SHA256_CBLOCK, "HMAC key is larger than block size"); - memcpy(hmac_key, sk_prf, SPX_N); - for (size_t i = 0; i < sizeof(hmac_key); i++) { - hmac_key[i] ^= 0x36; - } - - uint8_t hash[SHA256_DIGEST_LENGTH]; - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, hmac_key, sizeof(hmac_key)); - SHA256_Update(&ctx, opt_rand, SPX_N); - SHA256_Update(&ctx, msg, msg_len); - SHA256_Final(hash, &ctx); - - for (size_t i = 0; i < sizeof(hmac_key); i++) { - hmac_key[i] ^= 0x36 ^ 0x5c; - } - SHA256_Init(&ctx); - SHA256_Update(&ctx, hmac_key, sizeof(hmac_key)); - SHA256_Update(&ctx, hash, sizeof(hash)); - SHA256_Final(hash, &ctx); - - // Truncate to SPX_N bytes - memcpy(output, hash, SPX_N); -} - -void spx_thash_tl(uint8_t *output, const uint8_t input[SPX_WOTS_BYTES], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - spx_thash(output, input, SPX_WOTS_LEN, pk_seed, addr); -} - -void spx_thash_tk(uint8_t *output, const uint8_t input[SPX_FORS_TREES * SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]) { - spx_thash(output, input, SPX_FORS_TREES, pk_seed, addr); -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_thash.h b/Sources/CNIOBoringSSL/crypto/spx/spx_thash.h deleted file mode 100644 index 17aa7946..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_thash.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_THASH_H -#define OPENSSL_HEADER_CRYPTO_SPX_THASH_H - -#include - -#include "./spx_params.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -// Implements F: a hash function takes an n-byte message as input and produces -// an n-byte output. -void spx_thash_f(uint8_t *output, const uint8_t input[SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - -// Implements H: a hash function takes a 2*n-byte message as input and produces -// an n-byte output. -void spx_thash_h(uint8_t *output, const uint8_t input[2 * SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - -// Implements Hmsg: a hash function used to generate the digest of the message -// to be signed. -void spx_thash_hmsg(uint8_t *output, const uint8_t r[SPX_N], - const uint8_t pk_seed[SPX_N], const uint8_t pk_root[SPX_N], - const uint8_t *msg, size_t msg_len); - -// Implements PRF: a pseudo-random function that is used to generate the secret -// values in WOTS+ and FORS private keys. -void spx_thash_prf(uint8_t *output, const uint8_t pk_seed[SPX_N], - const uint8_t sk_seed[SPX_N], uint8_t addr[32]); - -// Implements PRF: a pseudo-random function that is used to generate the -// randomizer r for the randomized hashing of the message to be signed. values -// in WOTS+ and FORS private keys. -void spx_thash_prfmsg(uint8_t *output, const uint8_t sk_prf[SPX_N], - const uint8_t opt_rand[SPX_N], const uint8_t *msg, - size_t msg_len); - -// Implements Tl: a hash function that maps an l*n-byte message to an n-byte -// message. -void spx_thash_tl(uint8_t *output, const uint8_t input[SPX_WOTS_BYTES], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - -// Implements Tk: a hash function that maps a k*n-byte message to an n-byte -// message. -void spx_thash_tk(uint8_t *output, const uint8_t input[SPX_FORS_TREES * SPX_N], - const uint8_t pk_seed[SPX_N], uint8_t addr[32]); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_THASH_H diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_util.cc b/Sources/CNIOBoringSSL/crypto/spx/spx_util.cc deleted file mode 100644 index d9ddba8b..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_util.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 "./spx_util.h" - -void spx_uint64_to_len_bytes(uint8_t *output, size_t out_len, uint64_t input) { - for (size_t i = out_len; i > 0; --i) { - output[i - 1] = input & 0xff; - input = input >> 8; - } -} - -uint64_t spx_to_uint64(const uint8_t *input, size_t input_len) { - uint64_t tmp = 0; - for (size_t i = 0; i < input_len; ++i) { - tmp = 256 * tmp + input[i]; - } - return tmp; -} - -void spx_base_b(uint32_t *output, size_t out_len, const uint8_t *input, - unsigned int log2_b) { - int in = 0; - uint32_t out = 0; - uint32_t bits = 0; - uint32_t total = 0; - uint32_t base = UINT32_C(1) << log2_b; - - for (out = 0; out < out_len; ++out) { - while (bits < log2_b) { - total = (total << 8) + input[in]; - in++; - bits = bits + 8; - } - bits -= log2_b; - output[out] = (total >> bits) % base; - } -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_util.h b/Sources/CNIOBoringSSL/crypto/spx/spx_util.h deleted file mode 100644 index 4278c174..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_util.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_UTIL_H -#define OPENSSL_HEADER_CRYPTO_SPX_UTIL_H - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - - -// Encodes the integer value of input to out_len bytes in big-endian order. -// Note that input < 2^(8*out_len), as otherwise this function will truncate -// the least significant bytes of the integer representation. -void spx_uint64_to_len_bytes(uint8_t *output, size_t out_len, uint64_t input); - -uint64_t spx_to_uint64(const uint8_t *input, size_t input_len); - -// Compute the base 2^log2_b representation of X. -// -// As some of the parameter sets in https://eprint.iacr.org/2022/1725.pdf use -// a FORS height > 16 we use a uint32_t to store the output. -void spx_base_b(uint32_t *output, size_t out_len, const uint8_t *input, - unsigned int log2_b); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_UTIL_H diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_wots.cc b/Sources/CNIOBoringSSL/crypto/spx/spx_wots.cc deleted file mode 100644 index ee704be2..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_wots.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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 "./spx_address.h" -#include "./spx_params.h" -#include "./spx_util.h" -#include "./spx_thash.h" -#include "./spx_wots.h" - -// Chaining function used in WOTS+. -static void chain(uint8_t *output, const uint8_t *input, uint32_t start, - uint32_t steps, const uint8_t *pub_seed, uint8_t addr[32]) { - memcpy(output, input, SPX_N); - - for (size_t i = start; i < (start + steps) && i < SPX_WOTS_W; ++i) { - spx_set_hash_addr(addr, i); - spx_thash_f(output, output, pub_seed, addr); - } -} - -void spx_wots_pk_from_sig(uint8_t *pk, const uint8_t *sig, const uint8_t *msg, - const uint8_t pub_seed[SPX_N], uint8_t addr[32]) { - uint8_t tmp[SPX_WOTS_BYTES]; - uint8_t wots_pk_addr[32]; - memcpy(wots_pk_addr, addr, sizeof(wots_pk_addr)); - - // Convert message to base w - uint32_t base_w_msg[SPX_WOTS_LEN]; - spx_base_b(base_w_msg, SPX_WOTS_LEN1, msg, /*log2_b=*/SPX_WOTS_LOG_W); - - // Compute checksum - uint64_t csum = 0; - for (size_t i = 0; i < SPX_WOTS_LEN1; ++i) { - csum += SPX_WOTS_W - 1 - base_w_msg[i]; - } - - // Convert csum to base w as in Algorithm 7, Line 9 - uint8_t csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOG_W + 7) / 8]; - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOG_W)) % 8) % 8); - spx_uint64_to_len_bytes(csum_bytes, sizeof(csum_bytes), csum); - - // Write the base w representation of csum to the end of the message. - spx_base_b(base_w_msg + SPX_WOTS_LEN1, SPX_WOTS_LEN2, csum_bytes, - /*log2_b=*/SPX_WOTS_LOG_W); - - // Compute chains - for (size_t i = 0; i < SPX_WOTS_LEN; ++i) { - spx_set_chain_addr(addr, i); - chain(tmp + i * SPX_N, sig + i * SPX_N, base_w_msg[i], - SPX_WOTS_W - 1 - base_w_msg[i], pub_seed, addr); - } - - // Compress pk - spx_set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - spx_copy_keypair_addr(wots_pk_addr, addr); - spx_thash_tl(pk, tmp, pub_seed, wots_pk_addr); -} - -void spx_wots_pk_gen(uint8_t *pk, const uint8_t sk_seed[SPX_N], - const uint8_t pub_seed[SPX_N], uint8_t addr[32]) { - uint8_t tmp[SPX_WOTS_BYTES]; - uint8_t tmp_sk[SPX_N]; - uint8_t wots_pk_addr[32], sk_addr[32]; - memcpy(wots_pk_addr, addr, sizeof(wots_pk_addr)); - memcpy(sk_addr, addr, sizeof(sk_addr)); - - spx_set_type(sk_addr, SPX_ADDR_TYPE_WOTSPRF); - spx_copy_keypair_addr(sk_addr, addr); - - for (size_t i = 0; i < SPX_WOTS_LEN; ++i) { - spx_set_chain_addr(sk_addr, i); - spx_thash_prf(tmp_sk, pub_seed, sk_seed, sk_addr); - spx_set_chain_addr(addr, i); - chain(tmp + i * SPX_N, tmp_sk, 0, SPX_WOTS_W - 1, pub_seed, addr); - } - - // Compress pk - spx_set_type(wots_pk_addr, SPX_ADDR_TYPE_WOTSPK); - spx_copy_keypair_addr(wots_pk_addr, addr); - spx_thash_tl(pk, tmp, pub_seed, wots_pk_addr); -} - -void spx_wots_sign(uint8_t *sig, const uint8_t msg[SPX_N], - const uint8_t sk_seed[SPX_N], const uint8_t pub_seed[SPX_N], - uint8_t addr[32]) { - // Convert message to base w - uint32_t base_w_msg[SPX_WOTS_LEN]; - spx_base_b(base_w_msg, SPX_WOTS_LEN1, msg, /*log2_b=*/SPX_WOTS_LOG_W); - - // Compute checksum - uint64_t csum = 0; - for (size_t i = 0; i < SPX_WOTS_LEN1; ++i) { - csum += SPX_WOTS_W - 1 - base_w_msg[i]; - } - - // Convert csum to base w as in Algorithm 6, Line 9 - uint8_t csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOG_W + 7) / 8]; - csum = csum << ((8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOG_W)) % 8) % 8); - spx_uint64_to_len_bytes(csum_bytes, sizeof(csum_bytes), csum); - - // Write the base w representation of csum to the end of the message. - spx_base_b(base_w_msg + SPX_WOTS_LEN1, SPX_WOTS_LEN2, csum_bytes, - /*log2_b=*/SPX_WOTS_LOG_W); - - // Compute chains - uint8_t tmp_sk[SPX_N]; - uint8_t sk_addr[32]; - memcpy(sk_addr, addr, sizeof(sk_addr)); - spx_set_type(sk_addr, SPX_ADDR_TYPE_WOTSPRF); - spx_copy_keypair_addr(sk_addr, addr); - - for (size_t i = 0; i < SPX_WOTS_LEN; ++i) { - spx_set_chain_addr(sk_addr, i); - spx_thash_prf(tmp_sk, pub_seed, sk_seed, sk_addr); - spx_set_chain_addr(addr, i); - chain(sig + i * SPX_N, tmp_sk, 0, base_w_msg[i], pub_seed, addr); - } -} diff --git a/Sources/CNIOBoringSSL/crypto/spx/spx_wots.h b/Sources/CNIOBoringSSL/crypto/spx/spx_wots.h deleted file mode 100644 index 229a8645..00000000 --- a/Sources/CNIOBoringSSL/crypto/spx/spx_wots.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_CRYPTO_SPX_WOTS_H -#define OPENSSL_HEADER_CRYPTO_SPX_WOTS_H - -#include - -#include "./spx_params.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -// Algorithm 5: Generate a WOTS+ public key. -void spx_wots_pk_gen(uint8_t *pk, const uint8_t sk_seed[SPX_N], - const uint8_t pub_seed[SPX_N], uint8_t addr[32]); - -// Algorithm 6: Generate a WOTS+ signature on an n-byte message. -void spx_wots_sign(uint8_t *sig, const uint8_t msg[SPX_N], - const uint8_t sk_seed[SPX_N], const uint8_t pub_seed[SPX_N], - uint8_t addr[32]); - -// Algorithm 7: Compute a WOTS+ public key from a message and its signature. -void spx_wots_pk_from_sig(uint8_t *pk, const uint8_t *sig, const uint8_t *msg, - const uint8_t pub_seed[SPX_N], uint8_t addr[32]); - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_CRYPTO_SPX_WOTS_H diff --git a/Sources/CNIOBoringSSL/crypto/x509/algorithm.cc b/Sources/CNIOBoringSSL/crypto/x509/algorithm.cc index 681dd552..5f395331 100644 --- a/Sources/CNIOBoringSSL/crypto/x509/algorithm.cc +++ b/Sources/CNIOBoringSSL/crypto/x509/algorithm.cc @@ -98,7 +98,7 @@ int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) { // Default behavior: look up the OID for the algorithm/hash pair and encode // that. - const EVP_MD *digest = EVP_MD_CTX_md(ctx); + const EVP_MD *digest = EVP_MD_CTX_get0_md(ctx); if (digest == NULL) { OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED); return 0; diff --git a/Sources/CNIOBoringSSL/hash.txt b/Sources/CNIOBoringSSL/hash.txt index c87bb7bc..c13c8db3 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 059585c8dadc7c8170c788f8c89843ee1c5b8f11 +This directory is derived from BoringSSL cloned from https://boringssl.googlesource.com/boringssl at revision 9559c4566a6d12194c42db5f3dbbcb5de35cfec2 diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL.h index c5a545ea..68f1dc40 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL.h @@ -73,8 +73,6 @@ #include "CNIOBoringSSL_type_check.h" #include "CNIOBoringSSL_x509_vfy.h" #include "CNIOBoringSSL_x509v3.h" -#include "experimental/CNIOBoringSSL_dilithium.h" #include "experimental/CNIOBoringSSL_kyber.h" -#include "experimental/CNIOBoringSSL_spx.h" #endif // C_NIO_BORINGSSL_H diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h index 904dfd28..e2e29450 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols.h @@ -783,16 +783,6 @@ #define DH_size BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_size) #define DH_up_ref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DH_up_ref) #define DHparams_dup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DHparams_dup) -#define DILITHIUM_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_generate_key) -#define DILITHIUM_generate_key_external_entropy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_generate_key_external_entropy) -#define DILITHIUM_marshal_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_marshal_private_key) -#define DILITHIUM_marshal_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_marshal_public_key) -#define DILITHIUM_parse_private_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_parse_private_key) -#define DILITHIUM_parse_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_parse_public_key) -#define DILITHIUM_public_from_private BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_public_from_private) -#define DILITHIUM_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_sign) -#define DILITHIUM_sign_deterministic BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_sign_deterministic) -#define DILITHIUM_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DILITHIUM_verify) #define DIRECTORYSTRING_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DIRECTORYSTRING_free) #define DIRECTORYSTRING_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DIRECTORYSTRING_it) #define DIRECTORYSTRING_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, DIRECTORYSTRING_new) @@ -1153,6 +1143,7 @@ #define EVP_MD_CTX_create BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_create) #define EVP_MD_CTX_destroy BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_destroy) #define EVP_MD_CTX_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_free) +#define EVP_MD_CTX_get0_md BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_get0_md) #define EVP_MD_CTX_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_init) #define EVP_MD_CTX_md BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_md) #define EVP_MD_CTX_move BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_MD_CTX_move) @@ -1876,10 +1867,6 @@ #define SPAKE2_CTX_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPAKE2_CTX_new) #define SPAKE2_generate_msg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPAKE2_generate_msg) #define SPAKE2_process_msg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPAKE2_process_msg) -#define SPX_generate_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPX_generate_key) -#define SPX_generate_key_from_seed BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPX_generate_key_from_seed) -#define SPX_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPX_sign) -#define SPX_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SPX_verify) #define SSL_CIPHER_description BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CIPHER_description) #define SSL_CIPHER_get_auth_nid BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CIPHER_get_auth_nid) #define SSL_CIPHER_get_bits BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CIPHER_get_bits) @@ -2276,6 +2263,7 @@ #define SSL_in_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_in_init) #define SSL_is_dtls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_dtls) #define SSL_is_init_finished BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_init_finished) +#define SSL_is_quic BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_quic) #define SSL_is_server BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_server) #define SSL_is_signature_algorithm_rsa_pss BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_signature_algorithm_rsa_pss) #define SSL_key_update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_key_update) @@ -3871,38 +3859,6 @@ #define slhdsa_wots_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, slhdsa_wots_sign) #define slhdsa_xmss_pk_from_sig BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, slhdsa_xmss_pk_from_sig) #define slhdsa_xmss_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, slhdsa_xmss_sign) -#define spx_base_b BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_base_b) -#define spx_copy_keypair_addr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_copy_keypair_addr) -#define spx_fors_pk_from_sig BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_fors_pk_from_sig) -#define spx_fors_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_fors_sign) -#define spx_fors_sk_gen BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_fors_sk_gen) -#define spx_fors_treehash BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_fors_treehash) -#define spx_get_tree_index BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_get_tree_index) -#define spx_ht_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_ht_sign) -#define spx_ht_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_ht_verify) -#define spx_set_chain_addr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_chain_addr) -#define spx_set_hash_addr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_hash_addr) -#define spx_set_keypair_addr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_keypair_addr) -#define spx_set_layer_addr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_layer_addr) -#define spx_set_tree_addr BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_tree_addr) -#define spx_set_tree_height BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_tree_height) -#define spx_set_tree_index BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_tree_index) -#define spx_set_type BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_set_type) -#define spx_thash_f BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_f) -#define spx_thash_h BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_h) -#define spx_thash_hmsg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_hmsg) -#define spx_thash_prf BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_prf) -#define spx_thash_prfmsg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_prfmsg) -#define spx_thash_tk BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_tk) -#define spx_thash_tl BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_thash_tl) -#define spx_to_uint64 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_to_uint64) -#define spx_treehash BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_treehash) -#define spx_uint64_to_len_bytes BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_uint64_to_len_bytes) -#define spx_wots_pk_from_sig BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_wots_pk_from_sig) -#define spx_wots_pk_gen BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_wots_pk_gen) -#define spx_wots_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_wots_sign) -#define spx_xmss_pk_from_sig BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_xmss_pk_from_sig) -#define spx_xmss_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, spx_xmss_sign) #define v2i_GENERAL_NAME BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, v2i_GENERAL_NAME) #define v2i_GENERAL_NAMES BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, v2i_GENERAL_NAMES) #define v2i_GENERAL_NAME_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, v2i_GENERAL_NAME_ex) @@ -4941,8 +4897,6 @@ #define lh_SSL_SESSION_call_doall_arg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, lh_SSL_SESSION_call_doall_arg) #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 CRYPTO_addc_impl BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_addc_impl) -#define CRYPTO_subc_impl BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, CRYPTO_subc_impl) #define ssl_credential_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_credential_st) #define ssl_ctx_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_ctx_st) #define ssl_ech_keys_st BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ssl_ech_keys_st) diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h index 414f9540..a193993b 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_boringssl_prefix_symbols_asm.h @@ -788,16 +788,6 @@ #define _DH_size BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DH_size) #define _DH_up_ref BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DH_up_ref) #define _DHparams_dup BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DHparams_dup) -#define _DILITHIUM_generate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_generate_key) -#define _DILITHIUM_generate_key_external_entropy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_generate_key_external_entropy) -#define _DILITHIUM_marshal_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_marshal_private_key) -#define _DILITHIUM_marshal_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_marshal_public_key) -#define _DILITHIUM_parse_private_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_parse_private_key) -#define _DILITHIUM_parse_public_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_parse_public_key) -#define _DILITHIUM_public_from_private BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_public_from_private) -#define _DILITHIUM_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_sign) -#define _DILITHIUM_sign_deterministic BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_sign_deterministic) -#define _DILITHIUM_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DILITHIUM_verify) #define _DIRECTORYSTRING_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DIRECTORYSTRING_free) #define _DIRECTORYSTRING_it BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DIRECTORYSTRING_it) #define _DIRECTORYSTRING_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, DIRECTORYSTRING_new) @@ -1158,6 +1148,7 @@ #define _EVP_MD_CTX_create BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_create) #define _EVP_MD_CTX_destroy BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_destroy) #define _EVP_MD_CTX_free BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_free) +#define _EVP_MD_CTX_get0_md BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_get0_md) #define _EVP_MD_CTX_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_init) #define _EVP_MD_CTX_md BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_md) #define _EVP_MD_CTX_move BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, EVP_MD_CTX_move) @@ -1881,10 +1872,6 @@ #define _SPAKE2_CTX_new BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPAKE2_CTX_new) #define _SPAKE2_generate_msg BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPAKE2_generate_msg) #define _SPAKE2_process_msg BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPAKE2_process_msg) -#define _SPX_generate_key BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPX_generate_key) -#define _SPX_generate_key_from_seed BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPX_generate_key_from_seed) -#define _SPX_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPX_sign) -#define _SPX_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SPX_verify) #define _SSL_CIPHER_description BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CIPHER_description) #define _SSL_CIPHER_get_auth_nid BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CIPHER_get_auth_nid) #define _SSL_CIPHER_get_bits BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_CIPHER_get_bits) @@ -2281,6 +2268,7 @@ #define _SSL_in_init BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_in_init) #define _SSL_is_dtls BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_is_dtls) #define _SSL_is_init_finished BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_is_init_finished) +#define _SSL_is_quic BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_is_quic) #define _SSL_is_server BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_is_server) #define _SSL_is_signature_algorithm_rsa_pss BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_is_signature_algorithm_rsa_pss) #define _SSL_key_update BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, SSL_key_update) @@ -3876,38 +3864,6 @@ #define _slhdsa_wots_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, slhdsa_wots_sign) #define _slhdsa_xmss_pk_from_sig BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, slhdsa_xmss_pk_from_sig) #define _slhdsa_xmss_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, slhdsa_xmss_sign) -#define _spx_base_b BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_base_b) -#define _spx_copy_keypair_addr BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_copy_keypair_addr) -#define _spx_fors_pk_from_sig BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_fors_pk_from_sig) -#define _spx_fors_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_fors_sign) -#define _spx_fors_sk_gen BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_fors_sk_gen) -#define _spx_fors_treehash BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_fors_treehash) -#define _spx_get_tree_index BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_get_tree_index) -#define _spx_ht_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_ht_sign) -#define _spx_ht_verify BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_ht_verify) -#define _spx_set_chain_addr BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_chain_addr) -#define _spx_set_hash_addr BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_hash_addr) -#define _spx_set_keypair_addr BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_keypair_addr) -#define _spx_set_layer_addr BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_layer_addr) -#define _spx_set_tree_addr BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_tree_addr) -#define _spx_set_tree_height BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_tree_height) -#define _spx_set_tree_index BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_tree_index) -#define _spx_set_type BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_set_type) -#define _spx_thash_f BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_f) -#define _spx_thash_h BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_h) -#define _spx_thash_hmsg BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_hmsg) -#define _spx_thash_prf BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_prf) -#define _spx_thash_prfmsg BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_prfmsg) -#define _spx_thash_tk BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_tk) -#define _spx_thash_tl BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_thash_tl) -#define _spx_to_uint64 BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_to_uint64) -#define _spx_treehash BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_treehash) -#define _spx_uint64_to_len_bytes BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_uint64_to_len_bytes) -#define _spx_wots_pk_from_sig BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_wots_pk_from_sig) -#define _spx_wots_pk_gen BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_wots_pk_gen) -#define _spx_wots_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_wots_sign) -#define _spx_xmss_pk_from_sig BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_xmss_pk_from_sig) -#define _spx_xmss_sign BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, spx_xmss_sign) #define _v2i_GENERAL_NAME BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, v2i_GENERAL_NAME) #define _v2i_GENERAL_NAMES BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, v2i_GENERAL_NAMES) #define _v2i_GENERAL_NAME_ex BORINGSSL_ADD_PREFIX_MAC_ASM(BORINGSSL_PREFIX, v2i_GENERAL_NAME_ex) diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_digest.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_digest.h index 8d6422dd..0a317df5 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_digest.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_digest.h @@ -226,8 +226,13 @@ OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md); // Digest operation accessors. +// EVP_MD_CTX_get0_md returns the underlying digest function, or NULL if one has +// not been set. +OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx); + // EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not -// been set. +// been set. (This is the same as |EVP_MD_CTX_get0_md| but OpenSSL has +// deprecated this spelling.) OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); // EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It diff --git a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h index 474ee522..66c72604 100644 --- a/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h +++ b/Sources/CNIOBoringSSL/include/CNIOBoringSSL_ssl.h @@ -242,6 +242,9 @@ OPENSSL_EXPORT int SSL_is_server(const SSL *ssl); // SSL_is_dtls returns one if |ssl| is a DTLS connection and zero otherwise. OPENSSL_EXPORT int SSL_is_dtls(const SSL *ssl); +// SSL_is_quic returns one if |ssl| is a QUIC connection and zero otherwise. +OPENSSL_EXPORT int SSL_is_quic(const SSL *ssl); + // SSL_set_bio configures |ssl| to read from |rbio| and write to |wbio|. |ssl| // takes ownership of the two |BIO|s. If |rbio| and |wbio| are the same, |ssl| // only takes ownership of one reference. See |SSL_set0_rbio| and @@ -620,7 +623,8 @@ OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl, // DTLSv1_get_timeout queries the running DTLS timers. If there are any in // progress, it sets |*out| to the time remaining until the first timer expires -// and returns one. Otherwise, it returns zero. +// and returns one. Otherwise, it returns zero. Timers may be scheduled both +// during and after the handshake. // // When the timeout expires, call |DTLSv1_handle_timeout| to handle the // retransmit behavior. @@ -630,9 +634,11 @@ OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl, OPENSSL_EXPORT int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out); // DTLSv1_handle_timeout is called when a DTLS timeout expires. If no timeout -// had expired, it returns 0. Otherwise, it retransmits the previous flight of -// handshake messages, or post-handshake messages, and returns 1. If too many -// timeouts had expired without progress or an error occurs, it returns -1. +// had expired, it returns 0. Otherwise, it handles the timeout and returns 1 on +// success or -1 on error. +// +// This function may write to the transport (e.g. to retransmit messages) or +// update |ssl|'s internal state and schedule an updated timer. // // The caller's external timer should be compatible with the one |ssl| queries // within some fudge factor. Otherwise, the call will be a no-op, but @@ -640,12 +646,16 @@ OPENSSL_EXPORT int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out); // // If the function returns -1, checking if |SSL_get_error| returns // |SSL_ERROR_WANT_WRITE| may be used to determine if the retransmit failed due -// to a non-fatal error at the write |BIO|. However, the operation may not be -// retried until the next timeout fires. +// to a non-fatal error at the write |BIO|. In this case, when the |BIO| is +// writable, the operation may be retried by calling the original function, +// |SSL_do_handshake| or |SSL_read|. // // WARNING: This function breaks the usual return value convention. // -// TODO(davidben): This |SSL_ERROR_WANT_WRITE| behavior is kind of bizarre. +// TODO(davidben): We can make this function entirely optional by just checking +// the timers in |SSL_do_handshake| or |SSL_read|. Then timers behave like any +// other retry condition: rerun the operation and the library will make what +// progress it can. OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl); @@ -662,17 +672,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl); #define DTLS1_VERSION 0xfeff #define DTLS1_2_VERSION 0xfefd -// DTLS1_3_EXPERIMENTAL_VERSION gates experimental, in-progress code for DTLS -// 1.3. -// -// WARNING: Do not use this value. BoringSSL's DTLS 1.3 implementation is still -// under development. The code enabled by this value is neither stable nor -// secure. It does not correspond to any real protocol. It is also incompatible -// with other DTLS implementations, and it is not compatible with future or past -// versions of BoringSSL. -// -// When the DTLS 1.3 implementation is complete, this symbol will be replaced. -#define DTLS1_3_EXPERIMENTAL_VERSION 0xfc25 +#define DTLS1_3_VERSION 0xfefc // SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to // |version|. If |version| is zero, the default minimum version is used. It @@ -1151,9 +1151,8 @@ SSL_get0_peer_verify_algorithms(const SSL *ssl, const uint16_t **out_sigalgs); // The behavior of this function is undefined except during the callbacks set by // by |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb| or when the // handshake is paused because of them. -OPENSSL_EXPORT size_t -SSL_get0_peer_delegation_algorithms(const SSL *ssl, - const uint16_t **out_sigalgs); +OPENSSL_EXPORT size_t SSL_get0_peer_delegation_algorithms( + const SSL *ssl, const uint16_t **out_sigalgs); // SSL_CTX_get0_certificate returns |ctx|'s leaf certificate. OPENSSL_EXPORT X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); @@ -1211,8 +1210,7 @@ OPENSSL_EXPORT int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, // SSL_set_ocsp_response sets the OCSP response that is sent to clients which // request it. It returns one on success and zero on error. The caller retains // ownership of |response|. -OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl, - const uint8_t *response, +OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response, size_t response_len); // SSL_SIGN_* are signature algorithm values as defined in TLS 1.3. @@ -1372,8 +1370,7 @@ OPENSSL_EXPORT int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, #define SSL_FILETYPE_ASN1 2 OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, - const char *file, - int type); + const char *file, int type); OPENSSL_EXPORT int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); @@ -1532,8 +1529,7 @@ OPENSSL_EXPORT void SSL_CREDENTIAL_clear_must_match_issuer( // that this credential should be considered only when it matches a peer request // for a particular issuer via a negotiation mechanism (such as the // certificate_authorities extension). -OPENSSL_EXPORT int SSL_CREDENTIAL_must_match_issuer( - const SSL_CREDENTIAL *cred); +OPENSSL_EXPORT int SSL_CREDENTIAL_must_match_issuer(const SSL_CREDENTIAL *cred); // SSL_can_release_private_key returns one if |ssl| will no longer call into the // private key and zero otherwise. If the function returns one, the caller can @@ -1854,8 +1850,8 @@ OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl); // verification. The caller does not take ownership of the result. // // This is the |CRYPTO_BUFFER| variant of |SSL_get_peer_full_cert_chain|. -OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) * - SSL_get0_peer_certificates(const SSL *ssl); +OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates( + const SSL *ssl); // SSL_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to point to // |*out_len| bytes of SCT information from the server. This is only valid if @@ -1969,8 +1965,9 @@ OPENSSL_EXPORT int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, // SSL_SESSION_from_bytes parses |in_len| bytes from |in| as an SSL_SESSION. It // returns a newly-allocated |SSL_SESSION| on success or NULL on error. -OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes( - const uint8_t *in, size_t in_len, const SSL_CTX *ctx); +OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, + size_t in_len, + const SSL_CTX *ctx); // SSL_SESSION_get_version returns a string describing the TLS or DTLS version // |session| was established at. For example, "TLSv1.2" or "DTLSv1". @@ -2032,7 +2029,7 @@ OPENSSL_EXPORT X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session); // unverified list of certificates as sent by the peer, not the final chain // built during verification. The caller does not take ownership of the result. OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) * - SSL_SESSION_get0_peer_certificates(const SSL_SESSION *session); +SSL_SESSION_get0_peer_certificates(const SSL_SESSION *session); // SSL_SESSION_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to // point to |*out_len| bytes of SCT information stored in |session|. This is @@ -2220,7 +2217,7 @@ OPENSSL_EXPORT void SSL_SESSION_get0_peer_sha256(const SSL_SESSION *session, // SSL_SESS_CACHE_NO_INTERNAL, on a server, disables the internal session // cache. #define SSL_SESS_CACHE_NO_INTERNAL \ - (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE) + (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | SSL_SESS_CACHE_NO_INTERNAL_STORE) // SSL_CTX_set_session_cache_mode sets the session cache mode bits for |ctx| to // |mode|. It returns the previous value. @@ -2478,9 +2475,9 @@ OPENSSL_EXPORT int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, // WARNING: |callback| wildly breaks the usual return value convention and is // called in two different modes. OPENSSL_EXPORT int SSL_CTX_set_tlsext_ticket_key_cb( - SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv, - EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx, - int encrypt)); + SSL_CTX *ctx, + int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv, + EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx, int encrypt)); // ssl_ticket_aead_result_t enumerates the possible results from decrypting a // ticket with an |SSL_TICKET_AEAD_METHOD|. @@ -2844,8 +2841,7 @@ OPENSSL_EXPORT int SSL_CTX_set1_param(SSL_CTX *ctx, // SSL_set1_param sets verification parameters from |param|. It returns one on // success and zero on failure. The caller retains ownership of |param|. -OPENSSL_EXPORT int SSL_set1_param(SSL *ssl, - const X509_VERIFY_PARAM *param); +OPENSSL_EXPORT int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param); // SSL_CTX_get0_param returns |ctx|'s |X509_VERIFY_PARAM| for certificate // verification. The caller must not release the returned pointer but may call @@ -3014,10 +3010,10 @@ OPENSSL_EXPORT void SSL_set0_client_CAs(SSL *ssl, STACK_OF(CRYPTO_BUFFER) *name_list); // SSL_set0_CA_names sets |ssl|'s CA name list for the certificate authorities -// extension to |name_list|, which should contain DER-encoded distinguished names -// (RFC 5280). It takes ownership of |name_list|. +// extension to |name_list|, which should contain DER-encoded distinguished +// names (RFC 5280). It takes ownership of |name_list|. OPENSSL_EXPORT void SSL_set0_CA_names(SSL *ssl, - STACK_OF(CRYPTO_BUFFER) *name_list); + STACK_OF(CRYPTO_BUFFER) *name_list); // SSL_CTX_set0_client_CAs sets |ctx|'s client certificate CA list to // |name_list|, which should contain DER-encoded distinguished names (RFC 5280). @@ -3042,12 +3038,12 @@ OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl); // // The returned stack is owned by |ssl|, as are its contents. It should not be // used past the point where the handshake is restarted after the callback. -OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) * - SSL_get0_server_requested_CAs(const SSL *ssl); +OPENSSL_EXPORT const STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs( + const SSL *ssl); // SSL_CTX_get_client_CA_list returns |ctx|'s client certificate CA list. -OPENSSL_EXPORT STACK_OF(X509_NAME) * - SSL_CTX_get_client_CA_list(const SSL_CTX *ctx); +OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list( + const SSL_CTX *ctx); // SSL_add_client_CA appends |x509|'s subject to the client certificate CA list. // It returns one on success or zero on error. The caller retains ownership of @@ -3202,8 +3198,9 @@ OPENSSL_EXPORT int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, // |SSL_get_pending_cipher| to query the cipher suite. This may be used to // implement HTTP/2's cipher suite constraints. OPENSSL_EXPORT void SSL_CTX_set_alpn_select_cb( - SSL_CTX *ctx, int (*cb)(SSL *ssl, const uint8_t **out, uint8_t *out_len, - const uint8_t *in, unsigned in_len, void *arg), + SSL_CTX *ctx, + int (*cb)(SSL *ssl, const uint8_t **out, uint8_t *out_len, + const uint8_t *in, unsigned in_len, void *arg), void *arg); // SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. @@ -3368,8 +3365,9 @@ OPENSSL_EXPORT void SSL_CTX_set_next_protos_advertised_cb( // the client to offer NPN in the ClientHello. Callers thus should not configure // this callback in TLS client contexts that are not intended to use NPN. OPENSSL_EXPORT void SSL_CTX_set_next_proto_select_cb( - SSL_CTX *ctx, int (*cb)(SSL *ssl, uint8_t **out, uint8_t *out_len, - const uint8_t *in, unsigned in_len, void *arg), + SSL_CTX *ctx, + int (*cb)(SSL *ssl, uint8_t **out, uint8_t *out_len, const uint8_t *in, + unsigned in_len, void *arg), void *arg); // SSL_get0_next_proto_negotiated sets |*out_data| and |*out_len| to point to @@ -3485,10 +3483,10 @@ DEFINE_CONST_STACK_OF(SRTP_PROTECTION_PROFILE) #define SRTP_AES128_CM_SHA1_32 0x0002 #define SRTP_AES128_F8_SHA1_80 0x0003 #define SRTP_AES128_F8_SHA1_32 0x0004 -#define SRTP_NULL_SHA1_80 0x0005 -#define SRTP_NULL_SHA1_32 0x0006 -#define SRTP_AEAD_AES_128_GCM 0x0007 -#define SRTP_AEAD_AES_256_GCM 0x0008 +#define SRTP_NULL_SHA1_80 0x0005 +#define SRTP_NULL_SHA1_32 0x0006 +#define SRTP_AEAD_AES_128_GCM 0x0007 +#define SRTP_AEAD_AES_256_GCM 0x0008 // SSL_CTX_set_srtp_profiles enables SRTP for all SSL objects created from // |ctx|. |profile| contains a colon-separated list of profile names. It returns @@ -4801,8 +4799,9 @@ OPENSSL_EXPORT int SSL_was_key_usage_invalid(const SSL *ssl); // a server (respectively, client) handshake completes, fails, or is paused. // The |value| argument is one if the handshake succeeded and <= 0 // otherwise. -OPENSSL_EXPORT void SSL_CTX_set_info_callback( - SSL_CTX *ctx, void (*cb)(const SSL *ssl, int type, int value)); +OPENSSL_EXPORT void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb)(const SSL *ssl, + int type, int value)); // SSL_CTX_get_info_callback returns the callback set by // |SSL_CTX_set_info_callback|. @@ -4812,8 +4811,9 @@ OPENSSL_EXPORT void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, // SSL_set_info_callback configures a callback to be run at various events // during a connection's lifetime. See |SSL_CTX_set_info_callback|. -OPENSSL_EXPORT void SSL_set_info_callback( - SSL *ssl, void (*cb)(const SSL *ssl, int type, int value)); +OPENSSL_EXPORT void SSL_set_info_callback(SSL *ssl, + void (*cb)(const SSL *ssl, int type, + int value)); // SSL_get_info_callback returns the callback set by |SSL_set_info_callback|. OPENSSL_EXPORT void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl, @@ -5218,16 +5218,16 @@ OPENSSL_EXPORT int SSL_set1_sigalgs_list(SSL *ssl, const char *str); #define SSL_get_cipher(ssl) SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)) #define SSL_get_cipher_bits(ssl, out_alg_bits) \ - SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits) + SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits) #define SSL_get_cipher_version(ssl) \ - SSL_CIPHER_get_version(SSL_get_current_cipher(ssl)) + SSL_CIPHER_get_version(SSL_get_current_cipher(ssl)) #define SSL_get_cipher_name(ssl) \ - SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)) + SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)) #define SSL_get_time(session) SSL_SESSION_get_time(session) #define SSL_set_time(session, time) SSL_SESSION_set_time((session), (time)) #define SSL_get_timeout(session) SSL_SESSION_get_timeout(session) #define SSL_set_timeout(session, timeout) \ - SSL_SESSION_set_timeout((session), (timeout)) + SSL_SESSION_set_timeout((session), (timeout)) struct ssl_comp_st { int id; @@ -5328,19 +5328,19 @@ OPENSSL_EXPORT int SSL_want(const SSL *ssl); #define SSL_want_read(ssl) (SSL_want(ssl) == SSL_READING) #define SSL_want_write(ssl) (SSL_want(ssl) == SSL_WRITING) - // SSL_get_finished writes up to |count| bytes of the Finished message sent by - // |ssl| to |buf|. It returns the total untruncated length or zero if none has - // been sent yet. At TLS 1.3 and later, it returns zero. - // - // Use |SSL_get_tls_unique| instead. +// SSL_get_finished writes up to |count| bytes of the Finished message sent by +// |ssl| to |buf|. It returns the total untruncated length or zero if none has +// been sent yet. At TLS 1.3 and later, it returns zero. +// +// Use |SSL_get_tls_unique| instead. OPENSSL_EXPORT size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count); - // SSL_get_peer_finished writes up to |count| bytes of the Finished message - // received from |ssl|'s peer to |buf|. It returns the total untruncated length - // or zero if none has been received yet. At TLS 1.3 and later, it returns - // zero. - // - // Use |SSL_get_tls_unique| instead. +// SSL_get_peer_finished writes up to |count| bytes of the Finished message +// received from |ssl|'s peer to |buf|. It returns the total untruncated length +// or zero if none has been received yet. At TLS 1.3 and later, it returns +// zero. +// +// Use |SSL_get_tls_unique| instead. OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *ssl, void *buf, size_t count); @@ -5816,7 +5816,7 @@ OPENSSL_EXPORT int SSL_set_compliance_policy( #define SSL_CTX_set_session_cache_mode SSL_CTX_set_session_cache_mode #define SSL_CTX_set_tlsext_servername_arg SSL_CTX_set_tlsext_servername_arg #define SSL_CTX_set_tlsext_servername_callback \ - SSL_CTX_set_tlsext_servername_callback + SSL_CTX_set_tlsext_servername_callback #define SSL_CTX_set_tlsext_ticket_key_cb SSL_CTX_set_tlsext_ticket_key_cb #define SSL_CTX_set_tlsext_ticket_keys SSL_CTX_set_tlsext_ticket_keys #define SSL_CTX_set_tmp_dh SSL_CTX_set_tmp_dh @@ -5834,7 +5834,7 @@ OPENSSL_EXPORT int SSL_set_compliance_policy( #define SSL_get_negotiated_group SSL_get_negotiated_group #define SSL_get_options SSL_get_options #define SSL_get_secure_renegotiation_support \ - SSL_get_secure_renegotiation_support + SSL_get_secure_renegotiation_support #define SSL_need_tmp_RSA SSL_need_tmp_RSA #define SSL_num_renegotiations SSL_num_renegotiations #define SSL_session_reused SSL_session_reused @@ -5854,7 +5854,7 @@ OPENSSL_EXPORT int SSL_set_compliance_policy( #define SSL_set_tmp_rsa SSL_set_tmp_rsa #define SSL_total_renegotiations SSL_total_renegotiations -#endif // !defined(BORINGSSL_PREFIX) +#endif // !defined(BORINGSSL_PREFIX) #if defined(__cplusplus) diff --git a/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc b/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc index 5aec53fa..6c6cde3b 100644 --- a/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc +++ b/Sources/CNIOBoringSSL/include/boringssl_prefix_symbols_nasm.inc @@ -780,16 +780,6 @@ %xdefine _DH_size _ %+ BORINGSSL_PREFIX %+ _DH_size %xdefine _DH_up_ref _ %+ BORINGSSL_PREFIX %+ _DH_up_ref %xdefine _DHparams_dup _ %+ BORINGSSL_PREFIX %+ _DHparams_dup -%xdefine _DILITHIUM_generate_key _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_generate_key -%xdefine _DILITHIUM_generate_key_external_entropy _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_generate_key_external_entropy -%xdefine _DILITHIUM_marshal_private_key _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_marshal_private_key -%xdefine _DILITHIUM_marshal_public_key _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_marshal_public_key -%xdefine _DILITHIUM_parse_private_key _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_parse_private_key -%xdefine _DILITHIUM_parse_public_key _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_parse_public_key -%xdefine _DILITHIUM_public_from_private _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_public_from_private -%xdefine _DILITHIUM_sign _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_sign -%xdefine _DILITHIUM_sign_deterministic _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_sign_deterministic -%xdefine _DILITHIUM_verify _ %+ BORINGSSL_PREFIX %+ _DILITHIUM_verify %xdefine _DIRECTORYSTRING_free _ %+ BORINGSSL_PREFIX %+ _DIRECTORYSTRING_free %xdefine _DIRECTORYSTRING_it _ %+ BORINGSSL_PREFIX %+ _DIRECTORYSTRING_it %xdefine _DIRECTORYSTRING_new _ %+ BORINGSSL_PREFIX %+ _DIRECTORYSTRING_new @@ -1150,6 +1140,7 @@ %xdefine _EVP_MD_CTX_create _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_create %xdefine _EVP_MD_CTX_destroy _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_destroy %xdefine _EVP_MD_CTX_free _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_free +%xdefine _EVP_MD_CTX_get0_md _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_get0_md %xdefine _EVP_MD_CTX_init _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_init %xdefine _EVP_MD_CTX_md _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_md %xdefine _EVP_MD_CTX_move _ %+ BORINGSSL_PREFIX %+ _EVP_MD_CTX_move @@ -1873,10 +1864,6 @@ %xdefine _SPAKE2_CTX_new _ %+ BORINGSSL_PREFIX %+ _SPAKE2_CTX_new %xdefine _SPAKE2_generate_msg _ %+ BORINGSSL_PREFIX %+ _SPAKE2_generate_msg %xdefine _SPAKE2_process_msg _ %+ BORINGSSL_PREFIX %+ _SPAKE2_process_msg -%xdefine _SPX_generate_key _ %+ BORINGSSL_PREFIX %+ _SPX_generate_key -%xdefine _SPX_generate_key_from_seed _ %+ BORINGSSL_PREFIX %+ _SPX_generate_key_from_seed -%xdefine _SPX_sign _ %+ BORINGSSL_PREFIX %+ _SPX_sign -%xdefine _SPX_verify _ %+ BORINGSSL_PREFIX %+ _SPX_verify %xdefine _SSL_CIPHER_description _ %+ BORINGSSL_PREFIX %+ _SSL_CIPHER_description %xdefine _SSL_CIPHER_get_auth_nid _ %+ BORINGSSL_PREFIX %+ _SSL_CIPHER_get_auth_nid %xdefine _SSL_CIPHER_get_bits _ %+ BORINGSSL_PREFIX %+ _SSL_CIPHER_get_bits @@ -2273,6 +2260,7 @@ %xdefine _SSL_in_init _ %+ BORINGSSL_PREFIX %+ _SSL_in_init %xdefine _SSL_is_dtls _ %+ BORINGSSL_PREFIX %+ _SSL_is_dtls %xdefine _SSL_is_init_finished _ %+ BORINGSSL_PREFIX %+ _SSL_is_init_finished +%xdefine _SSL_is_quic _ %+ BORINGSSL_PREFIX %+ _SSL_is_quic %xdefine _SSL_is_server _ %+ BORINGSSL_PREFIX %+ _SSL_is_server %xdefine _SSL_is_signature_algorithm_rsa_pss _ %+ BORINGSSL_PREFIX %+ _SSL_is_signature_algorithm_rsa_pss %xdefine _SSL_key_update _ %+ BORINGSSL_PREFIX %+ _SSL_key_update @@ -3868,38 +3856,6 @@ %xdefine _slhdsa_wots_sign _ %+ BORINGSSL_PREFIX %+ _slhdsa_wots_sign %xdefine _slhdsa_xmss_pk_from_sig _ %+ BORINGSSL_PREFIX %+ _slhdsa_xmss_pk_from_sig %xdefine _slhdsa_xmss_sign _ %+ BORINGSSL_PREFIX %+ _slhdsa_xmss_sign -%xdefine _spx_base_b _ %+ BORINGSSL_PREFIX %+ _spx_base_b -%xdefine _spx_copy_keypair_addr _ %+ BORINGSSL_PREFIX %+ _spx_copy_keypair_addr -%xdefine _spx_fors_pk_from_sig _ %+ BORINGSSL_PREFIX %+ _spx_fors_pk_from_sig -%xdefine _spx_fors_sign _ %+ BORINGSSL_PREFIX %+ _spx_fors_sign -%xdefine _spx_fors_sk_gen _ %+ BORINGSSL_PREFIX %+ _spx_fors_sk_gen -%xdefine _spx_fors_treehash _ %+ BORINGSSL_PREFIX %+ _spx_fors_treehash -%xdefine _spx_get_tree_index _ %+ BORINGSSL_PREFIX %+ _spx_get_tree_index -%xdefine _spx_ht_sign _ %+ BORINGSSL_PREFIX %+ _spx_ht_sign -%xdefine _spx_ht_verify _ %+ BORINGSSL_PREFIX %+ _spx_ht_verify -%xdefine _spx_set_chain_addr _ %+ BORINGSSL_PREFIX %+ _spx_set_chain_addr -%xdefine _spx_set_hash_addr _ %+ BORINGSSL_PREFIX %+ _spx_set_hash_addr -%xdefine _spx_set_keypair_addr _ %+ BORINGSSL_PREFIX %+ _spx_set_keypair_addr -%xdefine _spx_set_layer_addr _ %+ BORINGSSL_PREFIX %+ _spx_set_layer_addr -%xdefine _spx_set_tree_addr _ %+ BORINGSSL_PREFIX %+ _spx_set_tree_addr -%xdefine _spx_set_tree_height _ %+ BORINGSSL_PREFIX %+ _spx_set_tree_height -%xdefine _spx_set_tree_index _ %+ BORINGSSL_PREFIX %+ _spx_set_tree_index -%xdefine _spx_set_type _ %+ BORINGSSL_PREFIX %+ _spx_set_type -%xdefine _spx_thash_f _ %+ BORINGSSL_PREFIX %+ _spx_thash_f -%xdefine _spx_thash_h _ %+ BORINGSSL_PREFIX %+ _spx_thash_h -%xdefine _spx_thash_hmsg _ %+ BORINGSSL_PREFIX %+ _spx_thash_hmsg -%xdefine _spx_thash_prf _ %+ BORINGSSL_PREFIX %+ _spx_thash_prf -%xdefine _spx_thash_prfmsg _ %+ BORINGSSL_PREFIX %+ _spx_thash_prfmsg -%xdefine _spx_thash_tk _ %+ BORINGSSL_PREFIX %+ _spx_thash_tk -%xdefine _spx_thash_tl _ %+ BORINGSSL_PREFIX %+ _spx_thash_tl -%xdefine _spx_to_uint64 _ %+ BORINGSSL_PREFIX %+ _spx_to_uint64 -%xdefine _spx_treehash _ %+ BORINGSSL_PREFIX %+ _spx_treehash -%xdefine _spx_uint64_to_len_bytes _ %+ BORINGSSL_PREFIX %+ _spx_uint64_to_len_bytes -%xdefine _spx_wots_pk_from_sig _ %+ BORINGSSL_PREFIX %+ _spx_wots_pk_from_sig -%xdefine _spx_wots_pk_gen _ %+ BORINGSSL_PREFIX %+ _spx_wots_pk_gen -%xdefine _spx_wots_sign _ %+ BORINGSSL_PREFIX %+ _spx_wots_sign -%xdefine _spx_xmss_pk_from_sig _ %+ BORINGSSL_PREFIX %+ _spx_xmss_pk_from_sig -%xdefine _spx_xmss_sign _ %+ BORINGSSL_PREFIX %+ _spx_xmss_sign %xdefine _v2i_GENERAL_NAME _ %+ BORINGSSL_PREFIX %+ _v2i_GENERAL_NAME %xdefine _v2i_GENERAL_NAMES _ %+ BORINGSSL_PREFIX %+ _v2i_GENERAL_NAMES %xdefine _v2i_GENERAL_NAME_ex _ %+ BORINGSSL_PREFIX %+ _v2i_GENERAL_NAME_ex @@ -4747,16 +4703,6 @@ %xdefine DH_size BORINGSSL_PREFIX %+ _DH_size %xdefine DH_up_ref BORINGSSL_PREFIX %+ _DH_up_ref %xdefine DHparams_dup BORINGSSL_PREFIX %+ _DHparams_dup -%xdefine DILITHIUM_generate_key BORINGSSL_PREFIX %+ _DILITHIUM_generate_key -%xdefine DILITHIUM_generate_key_external_entropy BORINGSSL_PREFIX %+ _DILITHIUM_generate_key_external_entropy -%xdefine DILITHIUM_marshal_private_key BORINGSSL_PREFIX %+ _DILITHIUM_marshal_private_key -%xdefine DILITHIUM_marshal_public_key BORINGSSL_PREFIX %+ _DILITHIUM_marshal_public_key -%xdefine DILITHIUM_parse_private_key BORINGSSL_PREFIX %+ _DILITHIUM_parse_private_key -%xdefine DILITHIUM_parse_public_key BORINGSSL_PREFIX %+ _DILITHIUM_parse_public_key -%xdefine DILITHIUM_public_from_private BORINGSSL_PREFIX %+ _DILITHIUM_public_from_private -%xdefine DILITHIUM_sign BORINGSSL_PREFIX %+ _DILITHIUM_sign -%xdefine DILITHIUM_sign_deterministic BORINGSSL_PREFIX %+ _DILITHIUM_sign_deterministic -%xdefine DILITHIUM_verify BORINGSSL_PREFIX %+ _DILITHIUM_verify %xdefine DIRECTORYSTRING_free BORINGSSL_PREFIX %+ _DIRECTORYSTRING_free %xdefine DIRECTORYSTRING_it BORINGSSL_PREFIX %+ _DIRECTORYSTRING_it %xdefine DIRECTORYSTRING_new BORINGSSL_PREFIX %+ _DIRECTORYSTRING_new @@ -5117,6 +5063,7 @@ %xdefine EVP_MD_CTX_create BORINGSSL_PREFIX %+ _EVP_MD_CTX_create %xdefine EVP_MD_CTX_destroy BORINGSSL_PREFIX %+ _EVP_MD_CTX_destroy %xdefine EVP_MD_CTX_free BORINGSSL_PREFIX %+ _EVP_MD_CTX_free +%xdefine EVP_MD_CTX_get0_md BORINGSSL_PREFIX %+ _EVP_MD_CTX_get0_md %xdefine EVP_MD_CTX_init BORINGSSL_PREFIX %+ _EVP_MD_CTX_init %xdefine EVP_MD_CTX_md BORINGSSL_PREFIX %+ _EVP_MD_CTX_md %xdefine EVP_MD_CTX_move BORINGSSL_PREFIX %+ _EVP_MD_CTX_move @@ -5840,10 +5787,6 @@ %xdefine SPAKE2_CTX_new BORINGSSL_PREFIX %+ _SPAKE2_CTX_new %xdefine SPAKE2_generate_msg BORINGSSL_PREFIX %+ _SPAKE2_generate_msg %xdefine SPAKE2_process_msg BORINGSSL_PREFIX %+ _SPAKE2_process_msg -%xdefine SPX_generate_key BORINGSSL_PREFIX %+ _SPX_generate_key -%xdefine SPX_generate_key_from_seed BORINGSSL_PREFIX %+ _SPX_generate_key_from_seed -%xdefine SPX_sign BORINGSSL_PREFIX %+ _SPX_sign -%xdefine SPX_verify BORINGSSL_PREFIX %+ _SPX_verify %xdefine SSL_CIPHER_description BORINGSSL_PREFIX %+ _SSL_CIPHER_description %xdefine SSL_CIPHER_get_auth_nid BORINGSSL_PREFIX %+ _SSL_CIPHER_get_auth_nid %xdefine SSL_CIPHER_get_bits BORINGSSL_PREFIX %+ _SSL_CIPHER_get_bits @@ -6240,6 +6183,7 @@ %xdefine SSL_in_init BORINGSSL_PREFIX %+ _SSL_in_init %xdefine SSL_is_dtls BORINGSSL_PREFIX %+ _SSL_is_dtls %xdefine SSL_is_init_finished BORINGSSL_PREFIX %+ _SSL_is_init_finished +%xdefine SSL_is_quic BORINGSSL_PREFIX %+ _SSL_is_quic %xdefine SSL_is_server BORINGSSL_PREFIX %+ _SSL_is_server %xdefine SSL_is_signature_algorithm_rsa_pss BORINGSSL_PREFIX %+ _SSL_is_signature_algorithm_rsa_pss %xdefine SSL_key_update BORINGSSL_PREFIX %+ _SSL_key_update @@ -7835,38 +7779,6 @@ %xdefine slhdsa_wots_sign BORINGSSL_PREFIX %+ _slhdsa_wots_sign %xdefine slhdsa_xmss_pk_from_sig BORINGSSL_PREFIX %+ _slhdsa_xmss_pk_from_sig %xdefine slhdsa_xmss_sign BORINGSSL_PREFIX %+ _slhdsa_xmss_sign -%xdefine spx_base_b BORINGSSL_PREFIX %+ _spx_base_b -%xdefine spx_copy_keypair_addr BORINGSSL_PREFIX %+ _spx_copy_keypair_addr -%xdefine spx_fors_pk_from_sig BORINGSSL_PREFIX %+ _spx_fors_pk_from_sig -%xdefine spx_fors_sign BORINGSSL_PREFIX %+ _spx_fors_sign -%xdefine spx_fors_sk_gen BORINGSSL_PREFIX %+ _spx_fors_sk_gen -%xdefine spx_fors_treehash BORINGSSL_PREFIX %+ _spx_fors_treehash -%xdefine spx_get_tree_index BORINGSSL_PREFIX %+ _spx_get_tree_index -%xdefine spx_ht_sign BORINGSSL_PREFIX %+ _spx_ht_sign -%xdefine spx_ht_verify BORINGSSL_PREFIX %+ _spx_ht_verify -%xdefine spx_set_chain_addr BORINGSSL_PREFIX %+ _spx_set_chain_addr -%xdefine spx_set_hash_addr BORINGSSL_PREFIX %+ _spx_set_hash_addr -%xdefine spx_set_keypair_addr BORINGSSL_PREFIX %+ _spx_set_keypair_addr -%xdefine spx_set_layer_addr BORINGSSL_PREFIX %+ _spx_set_layer_addr -%xdefine spx_set_tree_addr BORINGSSL_PREFIX %+ _spx_set_tree_addr -%xdefine spx_set_tree_height BORINGSSL_PREFIX %+ _spx_set_tree_height -%xdefine spx_set_tree_index BORINGSSL_PREFIX %+ _spx_set_tree_index -%xdefine spx_set_type BORINGSSL_PREFIX %+ _spx_set_type -%xdefine spx_thash_f BORINGSSL_PREFIX %+ _spx_thash_f -%xdefine spx_thash_h BORINGSSL_PREFIX %+ _spx_thash_h -%xdefine spx_thash_hmsg BORINGSSL_PREFIX %+ _spx_thash_hmsg -%xdefine spx_thash_prf BORINGSSL_PREFIX %+ _spx_thash_prf -%xdefine spx_thash_prfmsg BORINGSSL_PREFIX %+ _spx_thash_prfmsg -%xdefine spx_thash_tk BORINGSSL_PREFIX %+ _spx_thash_tk -%xdefine spx_thash_tl BORINGSSL_PREFIX %+ _spx_thash_tl -%xdefine spx_to_uint64 BORINGSSL_PREFIX %+ _spx_to_uint64 -%xdefine spx_treehash BORINGSSL_PREFIX %+ _spx_treehash -%xdefine spx_uint64_to_len_bytes BORINGSSL_PREFIX %+ _spx_uint64_to_len_bytes -%xdefine spx_wots_pk_from_sig BORINGSSL_PREFIX %+ _spx_wots_pk_from_sig -%xdefine spx_wots_pk_gen BORINGSSL_PREFIX %+ _spx_wots_pk_gen -%xdefine spx_wots_sign BORINGSSL_PREFIX %+ _spx_wots_sign -%xdefine spx_xmss_pk_from_sig BORINGSSL_PREFIX %+ _spx_xmss_pk_from_sig -%xdefine spx_xmss_sign BORINGSSL_PREFIX %+ _spx_xmss_sign %xdefine v2i_GENERAL_NAME BORINGSSL_PREFIX %+ _v2i_GENERAL_NAME %xdefine v2i_GENERAL_NAMES BORINGSSL_PREFIX %+ _v2i_GENERAL_NAMES %xdefine v2i_GENERAL_NAME_ex BORINGSSL_PREFIX %+ _v2i_GENERAL_NAME_ex diff --git a/Sources/CNIOBoringSSL/include/experimental/CNIOBoringSSL_dilithium.h b/Sources/CNIOBoringSSL/include/experimental/CNIOBoringSSL_dilithium.h deleted file mode 100644 index 5162aa22..00000000 --- a/Sources/CNIOBoringSSL/include/experimental/CNIOBoringSSL_dilithium.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_DILITHIUM_H -#define OPENSSL_HEADER_DILITHIUM_H - -#include "CNIOBoringSSL_base.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -#if defined(OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM) -// The ML-DSA spec has now been standardized and ML-DSA is available in -// BoringSSL. This code should no longer be used. It was intended for -// short-lived experiments and must not have been deployed anywhere durable. If -// you were using this you need to use the instead. This -// header and code will be removed from BoringSSL soon. - -// Dilithium3. - -// DILITHIUM_private_key contains a Dilithium3 private key. The contents of this -// object should never leave the address space since the format is unstable. -struct DILITHIUM_private_key { - union { - uint8_t bytes[32 + 32 + 64 + 256 * 4 * (5 + 6 + 6)]; - uint32_t alignment; - } opaque; -}; - -// DILITHIUM_public_key contains a Dilithium3 public key. The contents of this -// object should never leave the address space since the format is unstable. -struct DILITHIUM_public_key { - union { - uint8_t bytes[32 + 64 + 256 * 4 * 6]; - uint32_t alignment; - } opaque; -}; - -// DILITHIUM_PRIVATE_KEY_BYTES is the number of bytes in an encoded Dilithium3 -// private key. -#define DILITHIUM_PRIVATE_KEY_BYTES 4032 - -// DILITHIUM_PUBLIC_KEY_BYTES is the number of bytes in an encoded Dilithium3 -// public key. -#define DILITHIUM_PUBLIC_KEY_BYTES 1952 - -// DILITHIUM_SIGNATURE_BYTES is the number of bytes in an encoded Dilithium3 -// signature. -#define DILITHIUM_SIGNATURE_BYTES 3309 - -// DILITHIUM_generate_key generates a random public/private key pair, writes the -// encoded public key to |out_encoded_public_key| and sets |out_private_key| to -// the private key. Returns 1 on success and 0 on failure. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_generate_key( - uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES], - struct DILITHIUM_private_key *out_private_key); - -// DILITHIUM_public_from_private sets |*out_public_key| to the public key that -// corresponds to |private_key|. Returns 1 on success and 0 on failure. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_public_from_private( - struct DILITHIUM_public_key *out_public_key, - const struct DILITHIUM_private_key *private_key); - -// DILITHIUM_sign generates a signature for the message |msg| of length -// |msg_len| using |private_key| following the randomized algorithm, and writes -// the encoded signature to |out_encoded_signature|. Returns 1 on success and 0 -// on failure. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_sign( - uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const struct DILITHIUM_private_key *private_key, const uint8_t *msg, - size_t msg_len); - -// DILITHIUM_verify verifies that |encoded_signature| constitutes a valid -// signature for the message |msg| of length |msg_len| using |public_key|. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_verify( - const struct DILITHIUM_public_key *public_key, - const uint8_t encoded_signature[DILITHIUM_SIGNATURE_BYTES], - const uint8_t *msg, size_t msg_len); - - -// Serialisation of keys. - -// DILITHIUM_marshal_public_key serializes |public_key| to |out| in the standard -// format for Dilithium public keys. It returns one on success or zero on -// allocation error. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_marshal_public_key( - CBB *out, const struct DILITHIUM_public_key *public_key); - -// DILITHIUM_parse_public_key parses a public key, in the format generated by -// |DILITHIUM_marshal_public_key|, from |in| and writes the result to -// |out_public_key|. It returns one on success or zero on parse error or if -// there are trailing bytes in |in|. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_parse_public_key( - struct DILITHIUM_public_key *public_key, CBS *in); - -// DILITHIUM_marshal_private_key serializes |private_key| to |out| in the -// standard format for Dilithium private keys. It returns one on success or zero -// on allocation error. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_marshal_private_key( - CBB *out, const struct DILITHIUM_private_key *private_key); - -// DILITHIUM_parse_private_key parses a private key, in the format generated by -// |DILITHIUM_marshal_private_key|, from |in| and writes the result to -// |out_private_key|. It returns one on success or zero on parse error or if -// there are trailing bytes in |in|. -OPENSSL_EXPORT OPENSSL_DEPRECATED int DILITHIUM_parse_private_key( - struct DILITHIUM_private_key *private_key, CBS *in); - -#endif // OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_DILITHIUM_H diff --git a/Sources/CNIOBoringSSL/include/experimental/CNIOBoringSSL_spx.h b/Sources/CNIOBoringSSL/include/experimental/CNIOBoringSSL_spx.h deleted file mode 100644 index c5b45e4d..00000000 --- a/Sources/CNIOBoringSSL/include/experimental/CNIOBoringSSL_spx.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2023, Google LLC - * - * 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. */ - -#ifndef OPENSSL_HEADER_SPX_H -#define OPENSSL_HEADER_SPX_H - -#include "CNIOBoringSSL_base.h" - -#if defined(__cplusplus) -extern "C" { -#endif - - -#if defined(OPENSSL_UNSTABLE_EXPERIMENTAL_SPX) -// This header implements experimental, draft versions of not-yet-standardized -// primitives. When the standard is complete, these functions will be removed -// and replaced with the final, incompatible standard version. They are -// available now for short-lived experiments, but must not be deployed anywhere -// durable, such as a long-lived key store. To use these functions define -// OPENSSL_UNSTABLE_EXPERIMENTAL_SPX - -// SPX_N is the number of bytes in the hash output -#define SPX_N 16 - -// SPX_PUBLIC_KEY_BYTES is the nNumber of bytes in the public key of -// SPHINCS+-SHA2-128s -#define SPX_PUBLIC_KEY_BYTES 32 - -// SPX_SECRET_KEY_BYTES is the number of bytes in the private key of -// SPHINCS+-SHA2-128s -#define SPX_SECRET_KEY_BYTES 64 - -// SPX_SIGNATURE_BYTES is the number of bytes in a signature of -// SPHINCS+-SHA2-128s -#define SPX_SIGNATURE_BYTES 7856 - -// SPX_generate_key generates a SPHINCS+-SHA2-128s key pair and writes the -// result to |out_public_key| and |out_secret_key|. -// Private key: SK.seed || SK.prf || PK.seed || PK.root -// Public key: PK.seed || PK.root -OPENSSL_EXPORT void SPX_generate_key( - uint8_t out_public_key[SPX_PUBLIC_KEY_BYTES], - uint8_t out_secret_key[SPX_SECRET_KEY_BYTES]); - -// SPX_generate_key_from_seed generates a SPHINCS+-SHA2-128s key pair from a -// 48-byte seed and writes the result to |out_public_key| and |out_secret_key|. -// Secret key: SK.seed || SK.prf || PK.seed || PK.root -// Public key: PK.seed || PK.root -OPENSSL_EXPORT void SPX_generate_key_from_seed( - uint8_t out_public_key[SPX_PUBLIC_KEY_BYTES], - uint8_t out_secret_key[SPX_SECRET_KEY_BYTES], - const uint8_t seed[3 * SPX_N]); - -// SPX_sign generates a SPHINCS+-SHA2-128s signature over |msg| or length -// |msg_len| using |secret_key| and writes the output to |out_signature|. -// -// if |randomized| is 0, deterministic signing is performed, otherwise, -// non-deterministic signing is performed. -OPENSSL_EXPORT void SPX_sign( - uint8_t out_snignature[SPX_SIGNATURE_BYTES], - const uint8_t secret_key[SPX_SECRET_KEY_BYTES], const uint8_t *msg, - size_t msg_len, int randomized); - -// SPX_verify verifies a SPHINCS+-SHA2-128s signature in |signature| over |msg| -// or length |msg_len| using |public_key|. 1 is returned if the signature -// matches, 0 otherwise. -OPENSSL_EXPORT int SPX_verify( - const uint8_t signature[SPX_SIGNATURE_BYTES], - const uint8_t public_key[SPX_SECRET_KEY_BYTES], const uint8_t *msg, - size_t msg_len); - -#endif //OPENSSL_UNSTABLE_EXPERIMENTAL_SPX - - -#if defined(__cplusplus) -} // extern C -#endif - -#endif // OPENSSL_HEADER_SPX_H diff --git a/Sources/CNIOBoringSSL/ssl/d1_both.cc b/Sources/CNIOBoringSSL/ssl/d1_both.cc index af800dac..705db03e 100644 --- a/Sources/CNIOBoringSSL/ssl/d1_both.cc +++ b/Sources/CNIOBoringSSL/ssl/d1_both.cc @@ -368,14 +368,14 @@ bool dtls1_process_handshake_fragments(SSL *ssl, uint8_t *out_alert, const size_t frag_off = msg_hdr.frag_off; const size_t frag_len = msg_hdr.frag_len; const size_t msg_len = msg_hdr.msg_len; - if (frag_off > msg_len || frag_len > msg_len - frag_off || - msg_len > ssl_max_handshake_message_len(ssl)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); + if (frag_off > msg_len || frag_len > msg_len - frag_off) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD); *out_alert = SSL_AD_ILLEGAL_PARAMETER; return false; } - if (msg_hdr.seq < ssl->d1->handshake_read_seq) { + if (msg_hdr.seq < ssl->d1->handshake_read_seq || + ssl->d1->handshake_read_overflow) { // Ignore fragments from the past. This is a retransmit of data we already // received. // @@ -383,19 +383,24 @@ bool dtls1_process_handshake_fragments(SSL *ssl, uint8_t *out_alert, continue; } - assert(record_number.epoch() == ssl->d1->read_epoch.epoch); - if (ssl->d1->next_read_epoch != nullptr) { - // Any any time, we only expect new messages in one epoch. If - // |next_read_epoch| is set, we've started a new epoch but haven't - // received records in it yet. (Once a record is received in the new - // epoch, |next_read_epoch| becomes the current read epoch.) This new - // fragment is in the old epoch, but we expect handshake messages to be in - // the next epoch, so this is an error. + if (record_number.epoch() != ssl->d1->read_epoch.epoch || + ssl->d1->next_read_epoch != nullptr) { + // New messages can only arrive in the latest epoch. This can fail if the + // record came from |prev_read_epoch|, or if it came from |read_epoch| but + // |next_read_epoch| exists. (It cannot come from |next_read_epoch| + // because |next_read_epoch| becomes |read_epoch| once it receives a + // record.) OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESS_HANDSHAKE_DATA); *out_alert = SSL_AD_UNEXPECTED_MESSAGE; return false; } + if (msg_len > ssl_max_handshake_message_len(ssl)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return false; + } + if (SSL_in_init(ssl) && ssl_has_final_version(ssl) && ssl_protocol_version(ssl) >= TLS1_3_VERSION) { // During the handshake, if we receive any portion of the next flight, the @@ -407,9 +412,6 @@ bool dtls1_process_handshake_fragments(SSL *ssl, uint8_t *out_alert, // apply immediately after the handshake. As a client, receiving a // KeyUpdate or NewSessionTicket does not imply the server has received // our Finished. The server may have sent those messages in half-RTT. - // - // TODO(crbug.com/42290594): Once post-handshake messages are working, - // write a test for the half-RTT KeyUpdate case. implicit_ack = true; } @@ -448,7 +450,7 @@ bool dtls1_process_handshake_fragments(SSL *ssl, uint8_t *out_alert, if (ssl_has_final_version(ssl) && ssl_protocol_version(ssl) >= TLS1_3_VERSION && - !ssl->d1->ack_timer.IsSet()) { + !ssl->d1->ack_timer.IsSet() && !ssl->d1->sending_ack) { // Schedule sending an ACK. The delay serves several purposes: // - If there are more records to come, we send only one ACK. // - If there are more records to come and the flight is now complete, we @@ -484,18 +486,23 @@ ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed, return ssl_open_record_discard; case SSL3_RT_CHANGE_CIPHER_SPEC: + if (record.size() != 1u || record[0] != SSL3_MT_CCS) { + OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return ssl_open_record_error; + } + // We do not support renegotiation, so encrypted ChangeCipherSpec records // are illegal. - if (ssl->d1->read_epoch.epoch != 0) { + if (record_number.epoch() != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); *out_alert = SSL_AD_UNEXPECTED_MESSAGE; return ssl_open_record_error; } - if (record.size() != 1u || record[0] != SSL3_MT_CCS) { - OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return ssl_open_record_error; + // Ignore ChangeCipherSpec from a previous epoch. + if (record_number.epoch() != ssl->d1->read_epoch.epoch) { + return ssl_open_record_discard; } // Flag the ChangeCipherSpec for later. @@ -509,20 +516,17 @@ ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed, return dtls1_process_ack(ssl, out_alert, record_number, record); case SSL3_RT_HANDSHAKE: - // Break out to main processing. - break; + if (!dtls1_process_handshake_fragments(ssl, out_alert, record_number, + record)) { + return ssl_open_record_error; + } + return ssl_open_record_success; default: OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD); *out_alert = SSL_AD_UNEXPECTED_MESSAGE; return ssl_open_record_error; } - - if (!dtls1_process_handshake_fragments(ssl, out_alert, record_number, - record)) { - return ssl_open_record_error; - } - return ssl_open_record_success; } bool dtls1_get_message(const SSL *ssl, SSLMessage *out) { @@ -549,6 +553,9 @@ void dtls1_next_message(SSL *ssl) { size_t index = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT; ssl->d1->incoming_messages[index].reset(); ssl->d1->handshake_read_seq++; + if (ssl->d1->handshake_read_seq == 0) { + ssl->d1->handshake_read_overflow = true; + } ssl->s3->has_message = false; // If we previously sent a flight, mark it as having a reply, so // |on_handshake_complete| can manage post-handshake retransmission. @@ -615,6 +622,7 @@ void dtls_clear_outgoing_messages(SSL *ssl) { ssl->d1->outgoing_offset = 0; ssl->d1->outgoing_messages_complete = false; ssl->d1->flight_has_reply = false; + ssl->d1->sending_flight = false; dtls_clear_unused_write_epochs(ssl); } @@ -674,6 +682,10 @@ static bool add_outgoing(SSL *ssl, bool is_ccs, Array data) { } if (!is_ccs) { + if (ssl->d1->handshake_write_overflow) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return false; + } // TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript // on hs. if (ssl->s3->hs != NULL && !ssl->s3->hs->transcript.Update(data)) { @@ -681,6 +693,9 @@ static bool add_outgoing(SSL *ssl, bool is_ccs, Array data) { return false; } ssl->d1->handshake_write_seq++; + if (ssl->d1->handshake_write_seq == 0) { + ssl->d1->handshake_write_overflow = true; + } } DTLSOutgoingMessage msg; @@ -963,6 +978,11 @@ static int send_flight(SSL *ssl) { return -1; } + if (ssl->d1->num_timeouts > DTLS1_MAX_TIMEOUTS) { + OPENSSL_PUT_ERROR(SSL, SSL_R_READ_TIMEOUT_EXPIRED); + return -1; + } + dtls1_update_mtu(ssl); Array packet; @@ -1007,27 +1027,38 @@ static int send_flight(SSL *ssl) { return 1; } -int dtls1_flush_flight(SSL *ssl, bool post_handshake) { - ssl->d1->outgoing_messages_complete = true; - if (!post_handshake) { - // Our new flight implicitly ACKs the previous flight, so there is no need - // to ACK previous records. This clears the ACK buffer slightly earlier than - // the specification suggests. See the discussion in +void dtls1_finish_flight(SSL *ssl) { + if (ssl->d1->outgoing_messages.empty() || + ssl->d1->outgoing_messages_complete) { + return; // Nothing to do. + } + + if (ssl->d1->outgoing_messages[0].epoch <= 2) { + // DTLS 1.3 handshake messages (epoch 2 and below) implicitly ACK the + // previous flight, so there is no need to ACK previous records. This + // clears the ACK buffer slightly earlier than the specification suggests. + // See the discussion in // https://mailarchive.ietf.org/arch/msg/tls/kjJnquJOVaWxu5hUCmNzB35eqY0/ ssl->d1->records_to_ack.Clear(); ssl->d1->ack_timer.Stop(); + ssl->d1->sending_ack = false; } - // Start the retransmission timer for the next flight (if any). - dtls1_start_timer(ssl); - return send_flight(ssl); + + ssl->d1->outgoing_messages_complete = true; + ssl->d1->sending_flight = true; + // Stop retransmitting the previous flight. In DTLS 1.3, we'll have stopped + // the timer already, but DTLS 1.2 keeps it running until the next flight is + // ready. + dtls1_stop_timer(ssl); } -int dtls1_send_ack(SSL *ssl) { - assert(ssl_protocol_version(ssl) >= TLS1_3_VERSION); +void dtls1_schedule_ack(SSL *ssl) { ssl->d1->ack_timer.Stop(); - if (ssl->d1->records_to_ack.empty()) { - return 1; - } + ssl->d1->sending_ack = !ssl->d1->records_to_ack.empty(); +} + +static int send_ack(SSL *ssl) { + assert(ssl_protocol_version(ssl) >= TLS1_3_VERSION); // Ensure we don't send so many ACKs that we overflow the MTU. There is a // 2-byte length prefix and each ACK is 16 bytes. @@ -1083,18 +1114,54 @@ int dtls1_send_ack(SSL *ssl) { return bio_ret; } + if (BIO_flush(ssl->wbio.get()) <= 0) { + ssl->s3->rwstate = SSL_ERROR_WANT_WRITE; + return -1; + } + return 1; } -int dtls1_retransmit_outgoing_messages(SSL *ssl) { - // Rewind to the start of the flight and write it again. - // - // TODO(davidben): This does not allow retransmits to be resumed on - // non-blocking write. - ssl->d1->outgoing_written = 0; - ssl->d1->outgoing_offset = 0; +int dtls1_flush(SSL *ssl) { + // Send the pending ACK, if any. + if (ssl->d1->sending_ack) { + int ret = send_ack(ssl); + if (ret <= 0) { + return ret; + } + ssl->d1->sending_ack = false; + } - return send_flight(ssl); + // Send the pending flight, if any. + if (ssl->d1->sending_flight) { + int ret = send_flight(ssl); + if (ret <= 0) { + return ret; + } + + // Reset state for the next send. + ssl->d1->outgoing_written = 0; + ssl->d1->outgoing_offset = 0; + ssl->d1->sending_flight = false; + + // Schedule the next retransmit timer. In DTLS 1.3, we retransmit all + // flights until ACKed. In DTLS 1.2, the final Finished flight is never + // ACKed, so we do not keep the timer running after the handshake. + if (SSL_in_init(ssl) || ssl_protocol_version(ssl) >= TLS1_3_VERSION) { + if (ssl->d1->num_timeouts == 0) { + ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms; + } else { + ssl->d1->timeout_duration_ms = + std::min(ssl->d1->timeout_duration_ms * 2, uint32_t{60000}); + } + + OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get()); + ssl->d1->retransmit_timer.StartMicroseconds( + now, uint64_t{ssl->d1->timeout_duration_ms} * 1000); + } + } + + return 1; } unsigned int dtls1_min_mtu(void) { return kMinMTU; } diff --git a/Sources/CNIOBoringSSL/ssl/d1_lib.cc b/Sources/CNIOBoringSSL/ssl/d1_lib.cc index 14cb2857..49aea429 100644 --- a/Sources/CNIOBoringSSL/ssl/d1_lib.cc +++ b/Sources/CNIOBoringSSL/ssl/d1_lib.cc @@ -70,18 +70,15 @@ BSSL_NAMESPACE_BEGIN -// DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire -// before starting to decrease the MTU. -#define DTLS1_MTU_TIMEOUTS 2 - -// DTLS1_MAX_TIMEOUTS is the maximum number of timeouts to expire -// before failing the DTLS handshake. -#define DTLS1_MAX_TIMEOUTS 12 - DTLS1_STATE::DTLS1_STATE() : has_change_cipher_spec(false), outgoing_messages_complete(false), - flight_has_reply(false) {} + flight_has_reply(false), + handshake_write_overflow(false), + handshake_read_overflow(false), + sending_flight(false), + sending_ack(false), + queued_key_update(QueuedKeyUpdate::kNone) {} DTLS1_STATE::~DTLS1_STATE() {} @@ -185,52 +182,12 @@ uint64_t DTLSTimer::MicrosecondsRemaining(OPENSSL_timeval now) const { return sec + usec; } -void dtls1_start_timer(SSL *ssl) { - // If timer is not set, initialize duration. - if (!ssl->d1->retransmit_timer.IsSet()) { - ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms; - } - - OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get()); - ssl->d1->retransmit_timer.StartMicroseconds( - now, uint64_t{ssl->d1->timeout_duration_ms} * 1000); -} - -static void dtls1_double_timeout(SSL *ssl) { - ssl->d1->timeout_duration_ms *= 2; - if (ssl->d1->timeout_duration_ms > 60000) { - ssl->d1->timeout_duration_ms = 60000; - } -} - void dtls1_stop_timer(SSL *ssl) { ssl->d1->num_timeouts = 0; ssl->d1->retransmit_timer.Stop(); ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms; } -bool dtls1_check_timeout_num(SSL *ssl) { - ssl->d1->num_timeouts++; - - // Reduce MTU after 2 unsuccessful retransmissions - if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS && - !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { - long mtu = - BIO_ctrl(ssl->wbio.get(), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, nullptr); - if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) { - ssl->d1->mtu = (unsigned)mtu; - } - } - - if (ssl->d1->num_timeouts > DTLS1_MAX_TIMEOUTS) { - // fail the connection, enough alerts have been sent - OPENSSL_PUT_ERROR(SSL, SSL_R_READ_TIMEOUT_EXPIRED); - return false; - } - - return true; -} - BSSL_NAMESPACE_END using namespace bssl; @@ -285,25 +242,30 @@ int DTLSv1_handle_timeout(SSL *ssl) { bool any_timer_expired = false; if (ssl->d1->ack_timer.IsExpired(now)) { any_timer_expired = true; - int ret = dtls1_send_ack(ssl); - if (ret <= 0) { - return ret; - } + ssl->d1->sending_ack = true; + ssl->d1->ack_timer.Stop(); } if (ssl->d1->retransmit_timer.IsExpired(now)) { any_timer_expired = true; - if (!dtls1_check_timeout_num(ssl)) { - return -1; + ssl->d1->sending_flight = true; + ssl->d1->retransmit_timer.Stop(); + + ssl->d1->num_timeouts++; + // Reduce MTU after 2 unsuccessful retransmissions. + if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS && + !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) { + long mtu = BIO_ctrl(ssl->wbio.get(), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, + nullptr); + if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) { + ssl->d1->mtu = (unsigned)mtu; + } } + } - dtls1_double_timeout(ssl); - dtls1_start_timer(ssl); - int ret = dtls1_retransmit_outgoing_messages(ssl); - if (ret <= 0) { - return ret; - } + if (!any_timer_expired) { + return 0; } - return any_timer_expired ? 1 : 0; + return dtls1_flush(ssl); } diff --git a/Sources/CNIOBoringSSL/ssl/d1_pkt.cc b/Sources/CNIOBoringSSL/ssl/d1_pkt.cc index bc959f29..5a11f303 100644 --- a/Sources/CNIOBoringSSL/ssl/d1_pkt.cc +++ b/Sources/CNIOBoringSSL/ssl/d1_pkt.cc @@ -222,6 +222,26 @@ ssl_open_record_t dtls1_process_ack(SSL *ssl, uint8_t *out_alert, [](const auto &msg) { return msg.IsFullyAcked(); })) { dtls1_stop_timer(ssl); dtls_clear_outgoing_messages(ssl); + + // DTLS 1.3 defers the key update to when the message is ACKed. + if (ssl->s3->key_update_pending) { + if (!tls13_rotate_traffic_key(ssl, evp_aead_seal)) { + return ssl_open_record_error; + } + ssl->s3->key_update_pending = false; + } + + // Check for deferred messages. + if (ssl->d1->queued_key_update != QueuedKeyUpdate::kNone) { + int request_type = + ssl->d1->queued_key_update == QueuedKeyUpdate::kUpdateRequested + ? SSL_KEY_UPDATE_REQUESTED + : SSL_KEY_UPDATE_NOT_REQUESTED; + ssl->d1->queued_key_update = QueuedKeyUpdate::kNone; + if (!tls13_add_key_update(ssl, request_type)) { + return ssl_open_record_error; + } + } } else { // We may still be able to drop unused write epochs. dtls_clear_unused_write_epochs(ssl); @@ -261,6 +281,10 @@ ssl_open_record_t dtls1_open_app_data(SSL *ssl, Span *out, // Parse the first fragment header to determine if this is a pre-CCS or // post-CCS handshake record. DTLS resets handshake message numbers on each // handshake, so renegotiations and retransmissions are ambiguous. + // + // TODO(crbug.com/42290594): Move this logic into + // |dtls1_process_handshake_fragments| and integrate it into DTLS 1.3 + // retransmit conditions. CBS cbs, body; struct hm_header_st msg_hdr; CBS_init(&cbs, record.data(), record.size()); @@ -272,16 +296,15 @@ ssl_open_record_t dtls1_open_app_data(SSL *ssl, Span *out, if (msg_hdr.type == SSL3_MT_FINISHED && msg_hdr.seq == ssl->d1->handshake_read_seq - 1) { - if (msg_hdr.frag_off == 0) { + if (!ssl->d1->sending_flight && msg_hdr.frag_off == 0) { // Retransmit our last flight of messages. If the peer sends the second // Finished, they may not have received ours. Only do this for the // first fragment, in case the Finished was fragmented. - if (!dtls1_check_timeout_num(ssl)) { - *out_alert = 0; // TODO(davidben): Send an alert? - return ssl_open_record_error; - } - - dtls1_retransmit_outgoing_messages(ssl); + // + // This is not really a timeout, but increment the timeout count so we + // eventually give up. + ssl->d1->num_timeouts++; + ssl->d1->sending_flight = true; } return ssl_open_record_discard; } @@ -329,7 +352,7 @@ int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, return 1; } - // TODO(crbug.com/42290594): Use the 0-RTT epoch if writing 0-RTT. + // TODO(crbug.com/381113363): Use the 0-RTT epoch if writing 0-RTT. int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in, ssl->d1->write_epoch.epoch()); if (ret <= 0) { diff --git a/Sources/CNIOBoringSSL/ssl/dtls_method.cc b/Sources/CNIOBoringSSL/ssl/dtls_method.cc index e798b52a..c79cbccf 100644 --- a/Sources/CNIOBoringSSL/ssl/dtls_method.cc +++ b/Sources/CNIOBoringSSL/ssl/dtls_method.cc @@ -82,6 +82,34 @@ static void dtls1_on_handshake_complete(SSL *ssl) { } } +static bool next_epoch(const SSL *ssl, uint16_t *out, + ssl_encryption_level_t level, uint16_t prev) { + switch (level) { + case ssl_encryption_initial: + case ssl_encryption_early_data: + case ssl_encryption_handshake: + *out = static_cast(level); + return true; + + case ssl_encryption_application: + if (prev < ssl_encryption_application && + ssl_protocol_version(ssl) >= TLS1_3_VERSION) { + *out = static_cast(level); + return true; + } + + if (prev == 0xffff) { + OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES); + return false; + } + *out = prev + 1; + return true; + } + + assert(0); + return false; +} + static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level, UniquePtr aead_ctx, Span traffic_secret) { @@ -94,10 +122,12 @@ static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level, DTLSReadEpoch new_epoch; new_epoch.aead = std::move(aead_ctx); + if (!next_epoch(ssl, &new_epoch.epoch, level, ssl->d1->read_epoch.epoch)) { + ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return false; + } + if (ssl_protocol_version(ssl) > TLS1_2_VERSION) { - // TODO(crbug.com/42290594): Handle the additional epochs used for key - // update. - new_epoch.epoch = level; new_epoch.rn_encrypter = RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret); if (new_epoch.rn_encrypter == nullptr) { @@ -113,7 +143,6 @@ static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level, return false; } } else { - new_epoch.epoch = ssl->d1->read_epoch.epoch + 1; ssl->d1->read_epoch = std::move(new_epoch); ssl->d1->has_change_cipher_spec = false; } @@ -123,20 +152,21 @@ static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level, static bool dtls1_set_write_state(SSL *ssl, ssl_encryption_level_t level, UniquePtr aead_ctx, Span traffic_secret) { + uint16_t epoch; + if (!next_epoch(ssl, &epoch, level, ssl->d1->write_epoch.epoch())) { + return false; + } + DTLSWriteEpoch new_epoch; + new_epoch.aead = std::move(aead_ctx); + new_epoch.next_record = DTLSRecordNumber(epoch, 0); if (ssl_protocol_version(ssl) > TLS1_2_VERSION) { - // TODO(crbug.com/42290594): See above. - new_epoch.next_record = DTLSRecordNumber(level, 0); new_epoch.rn_encrypter = - RecordNumberEncrypter::Create(aead_ctx->cipher(), traffic_secret); + RecordNumberEncrypter::Create(new_epoch.aead->cipher(), traffic_secret); if (new_epoch.rn_encrypter == nullptr) { return false; } - } else { - new_epoch.next_record = - DTLSRecordNumber(ssl->d1->write_epoch.epoch() + 1, 0); } - new_epoch.aead = std::move(aead_ctx); auto current = MakeUnique(std::move(ssl->d1->write_epoch)); if (current == nullptr) { @@ -165,8 +195,9 @@ static const SSL_PROTOCOL_METHOD kDTLSProtocolMethod = { dtls1_finish_message, dtls1_add_message, dtls1_add_change_cipher_spec, - dtls1_flush_flight, - dtls1_send_ack, + dtls1_finish_flight, + dtls1_schedule_ack, + dtls1_flush, dtls1_on_handshake_complete, dtls1_set_read_state, dtls1_set_write_state, diff --git a/Sources/CNIOBoringSSL/ssl/dtls_record.cc b/Sources/CNIOBoringSSL/ssl/dtls_record.cc index 62d8f98c..44ec941e 100644 --- a/Sources/CNIOBoringSSL/ssl/dtls_record.cc +++ b/Sources/CNIOBoringSSL/ssl/dtls_record.cc @@ -243,9 +243,11 @@ static bool parse_dtls13_record(SSL *ssl, CBS *in, ParsedDTLSRecord *out) { return false; } - // TODO(crbug.com/42290594): Add a runner test that performs many - // key updates to verify epoch reconstruction works for epochs larger than 3. - uint16_t epoch = reconstruct_epoch(out->type, ssl->d1->read_epoch.epoch); + uint16_t max_epoch = ssl->d1->read_epoch.epoch; + if (ssl->d1->next_read_epoch != nullptr) { + max_epoch = std::max(max_epoch, ssl->d1->next_read_epoch->epoch); + } + uint16_t epoch = reconstruct_epoch(out->type, max_epoch); size_t seq_len = (out->type & 0x08) ? 2 : 1; CBS seq_bytes; if (!CBS_get_bytes(in, &seq_bytes, seq_len)) { @@ -263,6 +265,13 @@ static bool parse_dtls13_record(SSL *ssl, CBS *in, ParsedDTLSRecord *out) { BSSL_CHECK(CBS_get_bytes(in, &out->body, CBS_len(in))); } + // Drop the previous read epoch if expired. + if (ssl->d1->prev_read_epoch != nullptr && + ssl_ctx_get_current_time(ssl->ctx.get()).tv_sec > + ssl->d1->prev_read_epoch->expire) { + ssl->d1->prev_read_epoch = nullptr; + } + // Look up the corresponding epoch. This header form only matches encrypted // DTLS 1.3 epochs. DTLSReadEpoch *read_epoch = nullptr; @@ -271,6 +280,9 @@ static bool parse_dtls13_record(SSL *ssl, CBS *in, ParsedDTLSRecord *out) { } else if (ssl->d1->next_read_epoch != nullptr && epoch == ssl->d1->next_read_epoch->epoch) { read_epoch = ssl->d1->next_read_epoch.get(); + } else if (ssl->d1->prev_read_epoch != nullptr && + epoch == ssl->d1->prev_read_epoch->epoch.epoch) { + read_epoch = &ssl->d1->prev_read_epoch->epoch; } if (read_epoch != nullptr && use_dtls13_record_header(ssl, epoch)) { out->read_epoch = read_epoch; @@ -432,22 +444,32 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, record.read_epoch->bitmap.Record(record.number.sequence()); - // Once we receive a record from the next epoch, it becomes the current epoch. + // Once we receive a record from the next epoch in DTLS 1.3, it becomes the + // current epoch. Also save the previous epoch. This allows us to handle + // packet reordering on KeyUpdate, as well as ACK retransmissions of the + // Finished flight. if (record.read_epoch == ssl->d1->next_read_epoch.get()) { + assert(ssl_protocol_version(ssl) >= TLS1_3_VERSION); + auto prev = MakeUnique(); + if (prev == nullptr) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return ssl_open_record_error; + } + + // Release the epoch after a timeout. + prev->expire = ssl_ctx_get_current_time(ssl->ctx.get()).tv_sec; + if (prev->expire >= UINT64_MAX - DTLS_PREV_READ_EPOCH_EXPIRE_SECONDS) { + prev->expire = UINT64_MAX; // Saturate on overflow. + } else { + prev->expire += DTLS_PREV_READ_EPOCH_EXPIRE_SECONDS; + } + + prev->epoch = std::move(ssl->d1->read_epoch); + ssl->d1->prev_read_epoch = std::move(prev); ssl->d1->read_epoch = std::move(*ssl->d1->next_read_epoch); ssl->d1->next_read_epoch = nullptr; } - // We do not retain previous epochs, so it is guaranteed records come in at - // the "current" epoch. (But the current epoch may be one behind the - // handshake.) - // - // TODO(crbug.com/374890768): In DTLS 1.3, where rekeys may occur - // mid-connection, retaining previous epochs would make us more robust to - // packet reordering. If we do this, we'll need to take care to not - // accidentally accept data at the wrong epoch. - assert(record.number.epoch() == ssl->d1->read_epoch.epoch); - // TODO(davidben): Limit the number of empty records as in TLS? This is only // useful if we also limit discarded packets. diff --git a/Sources/CNIOBoringSSL/ssl/extensions.cc b/Sources/CNIOBoringSSL/ssl/extensions.cc index c4b71bf6..3cd83fa1 100644 --- a/Sources/CNIOBoringSSL/ssl/extensions.cc +++ b/Sources/CNIOBoringSSL/ssl/extensions.cc @@ -1361,7 +1361,7 @@ static bool ext_alpn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible, ssl_client_hello_type_t type) { const SSL *const ssl = hs->ssl; - if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) { + if (hs->config->alpn_client_proto_list.empty() && SSL_is_quic(ssl)) { // ALPN MUST be used with QUIC. OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); return false; @@ -1390,7 +1390,7 @@ static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) { SSL *const ssl = hs->ssl; if (contents == NULL) { - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { // ALPN is required when QUIC is used. OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL; @@ -1490,7 +1490,7 @@ bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert, !ssl_client_hello_get_extension( client_hello, &contents, TLSEXT_TYPE_application_layer_protocol_negotiation)) { - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { // ALPN is required when QUIC is used. OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL; @@ -1521,7 +1521,7 @@ bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert, static_cast(CBS_len(&protocol_name_list)), ssl->ctx->alpn_select_cb_arg); // ALPN is required when QUIC is used. - if (ssl->quic_method && + if (SSL_is_quic(ssl) && (ret == SSL_TLSEXT_ERR_NOACK || ret == SSL_TLSEXT_ERR_ALERT_WARNING)) { ret = SSL_TLSEXT_ERR_ALERT_FATAL; } @@ -2595,10 +2595,10 @@ static bool ext_certificate_authorities_parse_clienthello(SSL_HANDSHAKE *hs, static bool ext_quic_transport_params_add_clienthello_impl( const SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) { - if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) { + if (hs->config->quic_transport_params.empty() && !SSL_is_quic(hs->ssl)) { return true; } - if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) { + if (hs->config->quic_transport_params.empty() || !SSL_is_quic(hs->ssl)) { // QUIC Transport Parameters must be sent over QUIC, and they must not be // sent over non-QUIC transports. If transport params are set, then // SSL(_CTX)_set_quic_method must also be called. @@ -2650,7 +2650,7 @@ static bool ext_quic_transport_params_parse_serverhello_impl( // Silently ignore because we expect the other QUIC codepoint. return true; } - if (!ssl->quic_method) { + if (!SSL_is_quic(ssl)) { return true; } *out_alert = SSL_AD_MISSING_EXTENSION; @@ -2658,7 +2658,7 @@ static bool ext_quic_transport_params_parse_serverhello_impl( } // The extensions parser will check for unsolicited extensions before // calling the callback. - assert(ssl->quic_method != nullptr); + assert(SSL_is_quic(ssl)); assert(ssl_protocol_version(ssl) == TLS1_3_VERSION); assert(used_legacy_codepoint == hs->config->quic_use_legacy_codepoint); return ssl->s3->peer_quic_transport_params.CopyFrom(*contents); @@ -2682,7 +2682,7 @@ static bool ext_quic_transport_params_parse_clienthello_impl( bool used_legacy_codepoint) { SSL *const ssl = hs->ssl; if (!contents) { - if (!ssl->quic_method) { + if (!SSL_is_quic(ssl)) { if (hs->config->quic_transport_params.empty()) { return true; } @@ -2699,7 +2699,7 @@ static bool ext_quic_transport_params_parse_clienthello_impl( *out_alert = SSL_AD_MISSING_EXTENSION; return false; } - if (!ssl->quic_method) { + if (!SSL_is_quic(ssl)) { if (used_legacy_codepoint) { // Ignore the legacy private-use codepoint because that could be sent // to mean something else than QUIC transport parameters. @@ -2733,12 +2733,12 @@ static bool ext_quic_transport_params_parse_clienthello_legacy( static bool ext_quic_transport_params_add_serverhello_impl( SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) { - if (hs->ssl->quic_method == nullptr && use_legacy_codepoint) { + if (!SSL_is_quic(hs->ssl) && use_legacy_codepoint) { // Ignore the legacy private-use codepoint because that could be sent // to mean something else than QUIC transport parameters. return true; } - assert(hs->ssl->quic_method != nullptr); + assert(SSL_is_quic(hs->ssl)); if (hs->config->quic_transport_params.empty()) { // Transport parameters must be set when using QUIC. OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED); @@ -3552,7 +3552,7 @@ bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded, // bugs. We also apply this padding to ClientHelloOuter, to keep the wire // images aligned. size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs, type); - if (!SSL_is_dtls(ssl) && !ssl->quic_method && + if (!SSL_is_dtls(ssl) && !SSL_is_quic(ssl) && !ssl->s3->used_hello_retry_request) { header_len += SSL3_HM_HEADER_LENGTH + 2 + CBB_len(&extensions) + psk_extension_len; diff --git a/Sources/CNIOBoringSSL/ssl/handshake.cc b/Sources/CNIOBoringSSL/ssl/handshake.cc index 13fe9d89..624cf363 100644 --- a/Sources/CNIOBoringSSL/ssl/handshake.cc +++ b/Sources/CNIOBoringSSL/ssl/handshake.cc @@ -589,6 +589,16 @@ 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 (;;) { + // If a timeout during the handshake triggered a DTLS ACK or retransmit, we + // resolve that first. E.g., if |ssl_hs_private_key_operation| is slow, the + // ACK timer may fire. + if (hs->wait != ssl_hs_error && SSL_is_dtls(ssl)) { + int ret = ssl->method->flush(ssl); + if (ret <= 0) { + return ret; + } + } + // 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 @@ -599,10 +609,8 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { ERR_restore_state(hs->error.get()); return -1; - case ssl_hs_flush_post_handshake: case ssl_hs_flush: { - bool post_handshake = hs->wait == ssl_hs_flush_post_handshake; - int ret = ssl->method->flush_flight(ssl, post_handshake); + int ret = ssl->method->flush(ssl); if (ret <= 0) { return ret; } @@ -612,7 +620,7 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { case ssl_hs_read_server_hello: case ssl_hs_read_message: case ssl_hs_read_change_cipher_spec: { - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { // 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 @@ -680,7 +688,7 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { return -1; case ssl_hs_handback: { - int ret = ssl->method->flush_flight(ssl, /*post_handshake=*/false); + int ret = ssl->method->flush(ssl); if (ret <= 0) { return ret; } @@ -733,15 +741,6 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { ssl->s3->rwstate = SSL_ERROR_HANDSHAKE_HINTS_READY; return -1; - case ssl_hs_ack: - if (ssl->method->send_ack != nullptr) { - int ret = ssl->method->send_ack(ssl); - if (ret <= 0) { - return ret; - } - } - break; - case ssl_hs_ok: break; } @@ -761,9 +760,14 @@ int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) { *out_early_return = false; return 1; } + // If the handshake returns |ssl_hs_flush|, implicitly finish the flight. + // This is a convenience so we do not need to manually insert this + // throughout the handshake. + if (hs->wait == ssl_hs_flush) { + ssl->method->finish_flight(ssl); + } - // Otherwise, loop to the beginning and resolve what was blocking the - // handshake. + // Loop to the beginning and resolve what was blocking the handshake. } } diff --git a/Sources/CNIOBoringSSL/ssl/handshake_client.cc b/Sources/CNIOBoringSSL/ssl/handshake_client.cc index ddb85456..9db7b490 100644 --- a/Sources/CNIOBoringSSL/ssl/handshake_client.cc +++ b/Sources/CNIOBoringSSL/ssl/handshake_client.cc @@ -430,7 +430,7 @@ static ssl_early_data_reason_t should_offer_early_data( // We discard inapplicable sessions, so this is redundant with the session // checks below, but reporting that TLS 1.3 was disabled is more useful. // - // TODO(crbug.com/42290594): Support early data in DTLS 1.3. + // TODO(crbug.com/381113363): Support early data in DTLS 1.3. return ssl_early_data_protocol_version; } @@ -518,7 +518,7 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) { (session_type == SSLSessionType::kTicket && (SSL_get_options(ssl) & SSL_OP_NO_TICKET)) || !ssl_session_is_time_valid(ssl, ssl->session.get()) || - (ssl->quic_method != nullptr) != ssl->session->is_quic || + SSL_is_quic(ssl) != int{ssl->session->is_quic} || ssl->s3->initial_handshake_complete) { ssl_set_session(ssl, nullptr); session_type = SSLSessionType::kNotResumable; @@ -536,8 +536,7 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) { // Compatibility mode sends a random session ID. Compatibility mode is // enabled for TLS 1.3, but not when it's run over QUIC or DTLS. const bool enable_compatibility_mode = hs->max_version >= TLS1_3_VERSION && - ssl->quic_method == nullptr && - !SSL_is_dtls(hs->ssl); + !SSL_is_quic(ssl) && !SSL_is_dtls(ssl); if (session_type == SSLSessionType::kID) { hs->session_id = ssl->session->session_id; } else if (session_type == SSLSessionType::kTicket || @@ -760,7 +759,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { // TODO(davidben): Should all handshake errors do this? What about record // decryption failures? // - // TODO(crbug.com/42290594): Although missing from the spec, a DTLS 1.2 + // TODO(crbug.com/381113363): Although missing from the spec, a DTLS 1.2 // server will already naturally skip 0-RTT data. If we implement DTLS 1.3 // 0-RTT, we may want a clean reject. assert(!SSL_is_dtls(ssl)); @@ -797,7 +796,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { // Enforce the TLS 1.3 anti-downgrade feature. if (!ssl->s3->initial_handshake_complete && - ssl_supports_version(hs, TLS1_3_VERSION)) { + hs->max_version >= TLS1_3_VERSION) { static_assert( sizeof(kTLS12DowngradeRandom) == sizeof(kTLS13DowngradeRandom), "downgrade signals have different size"); diff --git a/Sources/CNIOBoringSSL/ssl/handshake_server.cc b/Sources/CNIOBoringSSL/ssl/handshake_server.cc index 136283ee..1aa3a9c7 100644 --- a/Sources/CNIOBoringSSL/ssl/handshake_server.cc +++ b/Sources/CNIOBoringSSL/ssl/handshake_server.cc @@ -1057,7 +1057,7 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { } // Implement the TLS 1.3 anti-downgrade feature. - if (ssl_supports_version(hs, TLS1_3_VERSION)) { + if (hs->max_version >= TLS1_3_VERSION) { if (ssl_protocol_version(ssl) == TLS1_2_VERSION) { if (hs->apply_jdk11_workaround) { // JDK 11 implements the TLS 1.3 downgrade signal, so we cannot send it diff --git a/Sources/CNIOBoringSSL/ssl/internal.h b/Sources/CNIOBoringSSL/ssl/internal.h index 26d07e25..13848780 100644 --- a/Sources/CNIOBoringSSL/ssl/internal.h +++ b/Sources/CNIOBoringSSL/ssl/internal.h @@ -2128,7 +2128,6 @@ enum ssl_hs_wait_t { ssl_hs_read_server_hello, ssl_hs_read_message, ssl_hs_flush, - ssl_hs_flush_post_handshake, ssl_hs_certificate_selection_pending, ssl_hs_handoff, ssl_hs_handback, @@ -2142,7 +2141,6 @@ enum ssl_hs_wait_t { ssl_hs_read_change_cipher_spec, ssl_hs_certificate_verify, ssl_hs_hints_ready, - ssl_hs_ack, }; enum ssl_grease_index_t { @@ -2606,10 +2604,9 @@ const char *ssl_server_handshake_state(SSL_HANDSHAKE *hs); const char *tls13_client_handshake_state(SSL_HANDSHAKE *hs); const char *tls13_server_handshake_state(SSL_HANDSHAKE *hs); -// tls13_add_key_update queues a KeyUpdate message on |ssl|. The -// |update_requested| argument must be one of |SSL_KEY_UPDATE_REQUESTED| or -// |SSL_KEY_UPDATE_NOT_REQUESTED|. -bool tls13_add_key_update(SSL *ssl, int update_requested); +// tls13_add_key_update queues a KeyUpdate message on |ssl|. |request_type| must +// be one of |SSL_KEY_UPDATE_REQUESTED| or |SSL_KEY_UPDATE_NOT_REQUESTED|. +bool tls13_add_key_update(SSL *ssl, int request_type); // tls13_post_handshake processes a post-handshake message. It returns true on // success and false on failure. @@ -2965,13 +2962,15 @@ struct SSL_PROTOCOL_METHOD { // add_change_cipher_spec adds a ChangeCipherSpec record to the pending // flight. It returns true on success and false on error. bool (*add_change_cipher_spec)(SSL *ssl); - // flush_flight flushes the pending flight to the transport. It returns one on - // success and <= 0 on error. If |post_handshake| is true, the flight is a - // post-handshake flight. - int (*flush_flight)(SSL *ssl, bool post_handshake); - // send_ack, if not NULL, sends a DTLS ACK record to the peer. It returns one - // on success and <= 0 on error. - int (*send_ack)(SSL *ssl); + // finish_flight marks the pending flight as finished and ready to send. + // |flush| must be called to write it. + void (*finish_flight)(SSL *ssl); + // schedule_ack schedules a DTLS 1.3 ACK to be sent, without an ACK delay. + // |flush| must be called to write it. + void (*schedule_ack)(SSL *ssl); + // flush writes any scheduled data to the transport. It returns one on success + // and <= 0 on error. + int (*flush)(SSL *ssl); // on_handshake_complete is called when the handshake is complete. void (*on_handshake_complete)(SSL *ssl); // set_read_state sets |ssl|'s read cipher state and level to |aead_ctx| and @@ -3238,8 +3237,10 @@ struct SSL3_STATE { // Channel ID and the |channel_id| field is filled in. bool channel_id_valid : 1; - // key_update_pending is true if we have a KeyUpdate acknowledgment - // outstanding. + // key_update_pending is true if we are in the process of sending a KeyUpdate + // message. As a DoS mitigation (and a requirement in DTLS), we never send + // more than one KeyUpdate at once. In DTLS, this tracks whether there is an + // unACKed KeyUpdate. bool key_update_pending : 1; // early_data_accepted is true if early data was accepted by the server. @@ -3533,6 +3534,33 @@ struct DTLSSentRecord { uint32_t last_msg_end = 0; }; +enum class QueuedKeyUpdate { + kNone, + kUpdateNotRequested, + kUpdateRequested, +}; + +// DTLS_PREV_READ_EPOCH_EXPIRE_SECONDS is how long to retain the previous read +// epoch in DTLS 1.3. This value is set based on the following: +// +// - Section 4.2.1 of RFC 9147 recommends retaining past read epochs for the +// default TCP MSL. This accommodates packet reordering with KeyUpdate. +// +// - Section 5.8.1 of RFC 9147 requires being capable of ACKing the client's +// final flight for at least twice the default MSL. That requires retaining +// epoch 2 after the handshake. +// +// - Section 4 of RFC 9293 defines the MSL to be two minutes. +#define DTLS_PREV_READ_EPOCH_EXPIRE_SECONDS (4 * 60) + +struct DTLSPrevReadEpoch { + static constexpr bool kAllowUniquePtr = true; + DTLSReadEpoch epoch; + // expire is the expiration time of the read epoch, expressed as a POSIX + // timestamp in seconds. + uint64_t expire; +}; + struct DTLS1_STATE { static constexpr bool kAllowUniquePtr = true; @@ -3555,19 +3583,36 @@ struct DTLS1_STATE { // peer sent the final flight. bool flight_has_reply : 1; + // handshake_write_overflow and handshake_read_overflow are true if + // handshake_write_seq and handshake_read_seq, respectively have overflowed. + bool handshake_write_overflow : 1; + bool handshake_read_overflow : 1; + + // sending_flight and sending_ack are true if we are in the process of sending + // a handshake flight and ACK, respectively. + bool sending_flight : 1; + bool sending_ack : 1; + + // queued_key_update, if not kNone, indicates we've queued a KeyUpdate message + // to send after the current flight is ACKed. + QueuedKeyUpdate queued_key_update : 2; + uint16_t handshake_write_seq = 0; uint16_t handshake_read_seq = 0; - // read_epoch is the current DTLS read epoch. + // read_epoch is the current read epoch. DTLSReadEpoch read_epoch; - // next_read_epoch is the next DTLS read epoch in DTLS 1.3. It will become + // next_read_epoch is the next read epoch in DTLS 1.3. It will become // current once a record is received from it. UniquePtr next_read_epoch; + // prev_read_epoch is the previous read epoch in DTLS 1.3. + UniquePtr prev_read_epoch; + // write_epoch is the current DTLS write epoch. Non-retransmit records will // generally use this epoch. - // TODO(crbug.com/42290594): 0-RTT will be the exception, when implemented. + // TODO(crbug.com/381113363): 0-RTT will be the exception, when implemented. DTLSWriteEpoch write_epoch; // extra_write_epochs is the collection available write epochs. @@ -3940,14 +3985,15 @@ bool tls_init_message(const SSL *ssl, CBB *cbb, CBB *body, uint8_t type); bool tls_finish_message(const SSL *ssl, CBB *cbb, Array *out_msg); bool tls_add_message(SSL *ssl, Array msg); bool tls_add_change_cipher_spec(SSL *ssl); -int tls_flush_flight(SSL *ssl, bool post_handshake); +int tls_flush(SSL *ssl); bool dtls1_init_message(const SSL *ssl, CBB *cbb, CBB *body, uint8_t type); bool dtls1_finish_message(const SSL *ssl, CBB *cbb, Array *out_msg); bool dtls1_add_message(SSL *ssl, Array msg); bool dtls1_add_change_cipher_spec(SSL *ssl); -int dtls1_flush_flight(SSL *ssl, bool post_handshake); -int dtls1_send_ack(SSL *ssl); +void dtls1_finish_flight(SSL *ssl); +void dtls1_schedule_ack(SSL *ssl); +int dtls1_flush(SSL *ssl); // ssl_add_message_cbb finishes the handshake message in |cbb| and adds it to // the pending flight. It returns true on success and false on error. @@ -3975,13 +4021,19 @@ int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, int dtls1_write_record(SSL *ssl, int type, Span in, uint16_t epoch); -int dtls1_retransmit_outgoing_messages(SSL *ssl); bool dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr, CBS *out_body); -bool dtls1_check_timeout_num(SSL *ssl); -void dtls1_start_timer(SSL *ssl); +// DTLS1_MTU_TIMEOUTS is the maximum number of retransmit timeouts to expire +// before starting to decrease the MTU. +#define DTLS1_MTU_TIMEOUTS 2 + +// DTLS1_MAX_TIMEOUTS is the maximum number of retransmit timeouts to expire +// before failing the DTLS handshake. +#define DTLS1_MAX_TIMEOUTS 12 + void dtls1_stop_timer(SSL *ssl); + unsigned int dtls1_min_mtu(void); bool dtls1_new(SSL *ssl); diff --git a/Sources/CNIOBoringSSL/ssl/s3_both.cc b/Sources/CNIOBoringSSL/ssl/s3_both.cc index 5680fb29..c0052e05 100644 --- a/Sources/CNIOBoringSSL/ssl/s3_both.cc +++ b/Sources/CNIOBoringSSL/ssl/s3_both.cc @@ -194,8 +194,7 @@ bool tls_add_message(SSL *ssl, Array msg) { // // TODO(crbug.com/374991962): See if we can do this uniformly. Span rest = msg; - if (ssl->quic_method == nullptr && - ssl->s3->aead_write_ctx->is_null_cipher()) { + if (!SSL_is_quic(ssl) && ssl->s3->aead_write_ctx->is_null_cipher()) { while (!rest.empty()) { Span chunk = rest.subspan(0, ssl->max_send_fragment); rest = rest.subspan(chunk.size()); @@ -250,7 +249,7 @@ bool tls_flush_pending_hs_data(SSL *ssl) { auto data = MakeConstSpan(reinterpret_cast(pending_hs_data->data), pending_hs_data->length); - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && !ssl->quic_method->add_handshake_data(ssl, ssl->s3->quic_write_level, data.data(), data.size())) { @@ -264,13 +263,12 @@ bool tls_flush_pending_hs_data(SSL *ssl) { } bool tls_add_change_cipher_spec(SSL *ssl) { - static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS}; - - if (!tls_flush_pending_hs_data(ssl)) { - return false; + if (SSL_is_quic(ssl)) { + return true; } - if (!ssl->quic_method && + static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS}; + if (!tls_flush_pending_hs_data(ssl) || !add_record_to_flight(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec)) { return false; @@ -281,12 +279,12 @@ bool tls_add_change_cipher_spec(SSL *ssl) { return true; } -int tls_flush_flight(SSL *ssl, bool post_handshake) { +int tls_flush(SSL *ssl) { if (!tls_flush_pending_hs_data(ssl)) { return -1; } - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { if (ssl->s3->write_shutdown != ssl_shutdown_none) { OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); return -1; @@ -302,15 +300,6 @@ int tls_flush_flight(SSL *ssl, bool post_handshake) { return 1; } - if (post_handshake) { - // Don't flush post-handshake messages like NewSessionTicket until the - // server performs a write, to prevent a non-reading client from causing the - // server to hang in the case of a small server write buffer. Consumers - // which don't write data to the client will need to do a zero-byte write if - // they wish to flush the tickets. - return 1; - } - if (ssl->s3->write_shutdown != ssl_shutdown_none) { OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); return -1; diff --git a/Sources/CNIOBoringSSL/ssl/s3_pkt.cc b/Sources/CNIOBoringSSL/ssl/s3_pkt.cc index 5225786a..0a1c6728 100644 --- a/Sources/CNIOBoringSSL/ssl/s3_pkt.cc +++ b/Sources/CNIOBoringSSL/ssl/s3_pkt.cc @@ -455,7 +455,7 @@ int ssl_send_alert_impl(SSL *ssl, int level, int desc) { } int tls_dispatch_alert(SSL *ssl) { - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { if (!ssl->quic_method->send_alert(ssl, ssl->s3->quic_write_level, ssl->s3->send_alert[1])) { OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR); diff --git a/Sources/CNIOBoringSSL/ssl/ssl_lib.cc b/Sources/CNIOBoringSSL/ssl/ssl_lib.cc index e24d06e0..6b35a1f8 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_lib.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_lib.cc @@ -460,7 +460,7 @@ bool SSL_get_traffic_secrets(const SSL *ssl, Span *out_write_traffic_secret) { // This API is not well-defined for DTLS 1.3 (see https://crbug.com/42290608) // or QUIC, where multiple epochs may be alive at once. - if (SSL_is_dtls(ssl) || ssl->quic_method != nullptr) { + if (SSL_is_dtls(ssl) || SSL_is_quic(ssl)) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return false; } @@ -800,18 +800,18 @@ size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, } enum ssl_encryption_level_t SSL_quic_read_level(const SSL *ssl) { - assert(ssl->quic_method != nullptr); + assert(SSL_is_quic(ssl)); return ssl->s3->quic_read_level; } enum ssl_encryption_level_t SSL_quic_write_level(const SSL *ssl) { - assert(ssl->quic_method != nullptr); + assert(SSL_is_quic(ssl)); return ssl->s3->quic_write_level; } int SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level, const uint8_t *data, size_t len) { - if (ssl->quic_method == nullptr) { + if (!SSL_is_quic(ssl)) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -920,7 +920,7 @@ static int ssl_do_post_handshake(SSL *ssl, const SSLMessage &msg) { int SSL_process_quic_post_handshake(SSL *ssl) { ssl_reset_error_state(ssl); - if (ssl->quic_method == nullptr || SSL_in_init(ssl)) { + if (!SSL_is_quic(ssl) || SSL_in_init(ssl)) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -963,6 +963,15 @@ static int ssl_read_impl(SSL *ssl) { return -1; } + // If a read triggered a DTLS ACK or retransmit, resolve that before reading + // more. + if (SSL_is_dtls(ssl)) { + int ret = ssl->method->flush(ssl); + if (ret <= 0) { + return ret; + } + } + // Complete the current handshake, if any. False Start will cause // |SSL_do_handshake| to return mid-handshake, so this may require multiple // iterations. @@ -1030,7 +1039,7 @@ int SSL_read(SSL *ssl, void *buf, int num) { } int SSL_peek(SSL *ssl, void *buf, int num) { - if (ssl->quic_method != nullptr) { + if (SSL_is_quic(ssl)) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } @@ -1051,7 +1060,7 @@ int SSL_peek(SSL *ssl, void *buf, int num) { int SSL_write(SSL *ssl, const void *buf, int num) { ssl_reset_error_state(ssl); - if (ssl->quic_method != nullptr) { + if (SSL_is_quic(ssl)) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return -1; } @@ -1097,7 +1106,7 @@ int SSL_key_update(SSL *ssl, int request_type) { return 0; } - if (ssl->ctx->quic_method != nullptr) { + if (SSL_is_quic(ssl)) { OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } @@ -1112,12 +1121,7 @@ int SSL_key_update(SSL *ssl, int request_type) { return 0; } - if (!ssl->s3->key_update_pending && - !tls13_add_key_update(ssl, request_type)) { - return 0; - } - - return 1; + return tls13_add_key_update(ssl, request_type); } int SSL_shutdown(SSL *ssl) { @@ -1343,7 +1347,7 @@ int SSL_get_error(const SSL *ssl, int ret_code) { return ssl->s3->rwstate; case SSL_ERROR_WANT_READ: { - if (ssl->quic_method) { + if (SSL_is_quic(ssl)) { return SSL_ERROR_WANT_READ; } BIO *bio = SSL_get_rbio(ssl); @@ -2870,6 +2874,8 @@ int SSL_is_server(const SSL *ssl) { return ssl->server; } int SSL_is_dtls(const SSL *ssl) { return ssl->method->is_dtls; } +int SSL_is_quic(const SSL *ssl) { return ssl->quic_method != nullptr; } + void SSL_CTX_set_select_certificate_cb( SSL_CTX *ctx, enum ssl_select_cert_result_t (*cb)(const SSL_CLIENT_HELLO *)) { diff --git a/Sources/CNIOBoringSSL/ssl/ssl_session.cc b/Sources/CNIOBoringSSL/ssl/ssl_session.cc index 67f9871b..59dbe2f9 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_session.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_session.cc @@ -350,7 +350,7 @@ bool ssl_get_new_session(SSL_HANDSHAKE *hs) { session->is_server = ssl->server; session->ssl_version = ssl->s3->version; - session->is_quic = ssl->quic_method != nullptr; + session->is_quic = SSL_is_quic(ssl); // Fill in the time from the |SSL_CTX|'s clock. OPENSSL_timeval now = ssl_ctx_get_current_time(ssl->ctx.get()); @@ -627,7 +627,7 @@ bool ssl_session_is_resumable(const SSL_HANDSHAKE *hs, hs->config->retain_only_sha256_of_client_certs) && // Only resume if the underlying transport protocol hasn't changed. // This is to prevent cross-protocol resumption between QUIC and TCP. - (hs->ssl->quic_method != nullptr) == session->is_quic; + SSL_is_quic(ssl) == int{session->is_quic}; } // ssl_lookup_session looks up |session_id| in the session cache and sets diff --git a/Sources/CNIOBoringSSL/ssl/ssl_transcript.cc b/Sources/CNIOBoringSSL/ssl/ssl_transcript.cc index 9b2ca552..f7d8afca 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_transcript.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_transcript.cc @@ -233,7 +233,7 @@ void SSLTranscript::FreeBuffer() { buffer_.reset(); } size_t SSLTranscript::DigestLen() const { return EVP_MD_size(Digest()); } const EVP_MD *SSLTranscript::Digest() const { - return EVP_MD_CTX_md(hash_.get()); + return EVP_MD_CTX_get0_md(hash_.get()); } bool SSLTranscript::UpdateForHelloRetryRequest() { diff --git a/Sources/CNIOBoringSSL/ssl/ssl_versions.cc b/Sources/CNIOBoringSSL/ssl/ssl_versions.cc index feb899f2..d6b9c9af 100644 --- a/Sources/CNIOBoringSSL/ssl/ssl_versions.cc +++ b/Sources/CNIOBoringSSL/ssl/ssl_versions.cc @@ -46,7 +46,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) { *out = TLS1_2_VERSION; return true; - case DTLS1_3_EXPERIMENTAL_VERSION: + case DTLS1_3_VERSION: *out = TLS1_3_VERSION; return true; @@ -66,7 +66,7 @@ static const uint16_t kTLSVersions[] = { }; static const uint16_t kDTLSVersions[] = { - DTLS1_3_EXPERIMENTAL_VERSION, + DTLS1_3_VERSION, DTLS1_2_VERSION, DTLS1_VERSION, }; @@ -104,7 +104,7 @@ static const VersionInfo kVersionNames[] = { {TLS1_VERSION, "TLSv1"}, {DTLS1_VERSION, "DTLSv1"}, {DTLS1_2_VERSION, "DTLSv1.2"}, - {DTLS1_3_EXPERIMENTAL_VERSION, "DTLSv1.3"}, + {DTLS1_3_VERSION, "DTLSv1.3"}, }; static const char *ssl_version_to_string(uint16_t version) { @@ -156,6 +156,8 @@ static bool set_min_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out, static bool set_max_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out, uint16_t version) { // Zero is interpreted as the default maximum version. + // TODO(crbug.com/42290594): Enable DTLS 1.3 by default, after it's + // successfully shipped in WebRTC. if (version == 0) { *out = method->is_dtls ? DTLS1_2_VERSION : TLS1_3_VERSION; return true; @@ -196,7 +198,7 @@ bool ssl_get_version_range(const SSL_HANDSHAKE *hs, uint16_t *out_min_version, } // QUIC requires TLS 1.3. - if (hs->ssl->quic_method && min_version < TLS1_3_VERSION) { + if (SSL_is_quic(hs->ssl) && min_version < TLS1_3_VERSION) { min_version = TLS1_3_VERSION; } diff --git a/Sources/CNIOBoringSSL/ssl/tls13_both.cc b/Sources/CNIOBoringSSL/ssl/tls13_both.cc index b63140b9..dd5fb1ce 100644 --- a/Sources/CNIOBoringSSL/ssl/tls13_both.cc +++ b/Sources/CNIOBoringSSL/ssl/tls13_both.cc @@ -618,13 +618,31 @@ bool tls13_add_finished(SSL_HANDSHAKE *hs) { return true; } -bool tls13_add_key_update(SSL *ssl, int update_requested) { +bool tls13_add_key_update(SSL *ssl, int request_type) { + if (ssl->s3->key_update_pending) { + return true; + } + + // We do not support multiple parallel outgoing flights. If there is an + // outgoing flight pending, queue the KeyUpdate for later. + if (SSL_is_dtls(ssl) && !ssl->d1->outgoing_messages.empty()) { + ssl->d1->queued_key_update = request_type == SSL_KEY_UPDATE_REQUESTED + ? QueuedKeyUpdate::kUpdateRequested + : QueuedKeyUpdate::kUpdateNotRequested; + return true; + } + ScopedCBB cbb; CBB body_cbb; if (!ssl->method->init_message(ssl, cbb.get(), &body_cbb, SSL3_MT_KEY_UPDATE) || - !CBB_add_u8(&body_cbb, update_requested) || - !ssl_add_message_cbb(ssl, cbb.get()) || + !CBB_add_u8(&body_cbb, request_type) || + !ssl_add_message_cbb(ssl, cbb.get())) { + return false; + } + + // In DTLS, the actual key update is deferred until KeyUpdate is ACKed. + if (!SSL_is_dtls(ssl) && !tls13_rotate_traffic_key(ssl, evp_aead_seal)) { return false; } @@ -633,7 +651,7 @@ bool tls13_add_key_update(SSL *ssl, int update_requested) { // wire. This prevents us from accumulating write obligations when read and // write progress at different rates. See RFC 8446, section 4.6.3. ssl->s3->key_update_pending = true; - + ssl->method->finish_flight(ssl); return true; } @@ -655,7 +673,6 @@ static bool tls13_receive_key_update(SSL *ssl, const SSLMessage &msg) { // Acknowledge the KeyUpdate if (key_update_request == SSL_KEY_UPDATE_REQUESTED && - !ssl->s3->key_update_pending && !tls13_add_key_update(ssl, SSL_KEY_UPDATE_NOT_REQUESTED)) { return false; } @@ -669,13 +686,8 @@ bool tls13_post_handshake(SSL *ssl, const SSLMessage &msg) { } if (msg.type == SSL3_MT_KEY_UPDATE) { - if (SSL_is_dtls(ssl)) { - // TODO(crbug.com/42290594): Process post-handshake messages in DTLS 1.3. - return true; - } ssl->s3->key_update_count++; - if (ssl->quic_method != nullptr || - ssl->s3->key_update_count > kMaxKeyUpdates) { + if (SSL_is_quic(ssl) || ssl->s3->key_update_count > kMaxKeyUpdates) { OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); return false; diff --git a/Sources/CNIOBoringSSL/ssl/tls13_client.cc b/Sources/CNIOBoringSSL/ssl/tls13_client.cc index 5734ebe6..e2ac00d8 100644 --- a/Sources/CNIOBoringSSL/ssl/tls13_client.cc +++ b/Sources/CNIOBoringSSL/ssl/tls13_client.cc @@ -73,13 +73,13 @@ static bool close_early_data(SSL_HANDSHAKE *hs, ssl_encryption_level_t level) { // write state. The two ClientHello sequence numbers must align, and handshake // write keys must be installed early to ACK the EncryptedExtensions. // - // TODO(crbug.com/42290594): We do not support 0-RTT in DTLS 1.3 and, in + // TODO(crbug.com/381113363): We do not support 0-RTT in DTLS 1.3 and, in // QUIC, the caller handles 0-RTT data, so we can skip installing 0-RTT keys // and act as if there is one write level. Now that we're implementing // DTLS 1.3, switch the abstraction to the DTLS/QUIC model where handshake // keys write keys are installed immediately, but the TLS record layer // internally waits to activate that epoch until the 0-RTT channel is closed. - if (ssl->quic_method == nullptr) { + if (!SSL_is_quic(ssl)) { if (level == ssl_encryption_initial) { bssl::UniquePtr null_ctx = SSLAEADContext::CreateNullCipher(); @@ -527,7 +527,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { // traffic keys to when the early data stream is closed. See // |close_early_data|. Note if the server has already rejected 0-RTT via // HelloRetryRequest, |in_early_data| is already false. - if (!hs->in_early_data || ssl->quic_method != nullptr) { + if (!hs->in_early_data || SSL_is_quic(ssl)) { if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_seal, hs->new_session.get(), hs->client_handshake_secret)) { @@ -795,7 +795,7 @@ static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) { if (ssl->s3->early_data_accepted) { // DTLS and QUIC omit the EndOfEarlyData message. See RFC 9001, section 8.3, // and RFC 9147, section 5.6. - if (ssl->quic_method == nullptr && !SSL_is_dtls(ssl)) { + if (!SSL_is_quic(ssl) && !SSL_is_dtls(ssl)) { ScopedCBB cbb; CBB body; if (!ssl->method->init_message(ssl, cbb.get(), &body, @@ -1158,8 +1158,7 @@ UniquePtr tls13_create_session_with_ticket(SSL *ssl, CBS *body) { // QUIC does not use the max_early_data_size parameter and always sets it to // a fixed value. See RFC 9001, section 4.6.1. - if (ssl->quic_method != nullptr && - session->ticket_max_early_data != 0xffffffff) { + if (SSL_is_quic(ssl) && session->ticket_max_early_data != 0xffffffff) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return nullptr; diff --git a/Sources/CNIOBoringSSL/ssl/tls13_enc.cc b/Sources/CNIOBoringSSL/ssl/tls13_enc.cc index 84bac511..de455924 100644 --- a/Sources/CNIOBoringSSL/ssl/tls13_enc.cc +++ b/Sources/CNIOBoringSSL/ssl/tls13_enc.cc @@ -188,7 +188,7 @@ bool tls13_set_traffic_key(SSL *ssl, enum ssl_encryption_level_t level, const EVP_MD *digest = ssl_session_get_digest(session); bool is_dtls = SSL_is_dtls(ssl); UniquePtr traffic_aead; - if (ssl->quic_method != nullptr) { + if (SSL_is_quic(ssl)) { // Install a placeholder SSLAEADContext so that SSL accessors work. The // encryption itself will be handled by the SSL_QUIC_METHOD. traffic_aead = SSLAEADContext::CreatePlaceholderForQUIC(session->cipher); diff --git a/Sources/CNIOBoringSSL/ssl/tls13_server.cc b/Sources/CNIOBoringSSL/ssl/tls13_server.cc index aa606520..bce7e292 100644 --- a/Sources/CNIOBoringSSL/ssl/tls13_server.cc +++ b/Sources/CNIOBoringSSL/ssl/tls13_server.cc @@ -153,17 +153,17 @@ static bool add_new_session_tickets(SSL_HANDSHAKE *hs, bool *out_sent_tickets) { return false; } session->ticket_age_add_valid = true; - // TODO(crbug.com/42290594): Remove the SSL_is_dtls check once we support + // TODO(crbug.com/381113363): Remove the SSL_is_dtls check once we support // 0-RTT for DTLS 1.3. bool enable_early_data = ssl->enable_early_data && - (!ssl->quic_method || !ssl->config->quic_early_data_context.empty()) && + (!SSL_is_quic(ssl) || !ssl->config->quic_early_data_context.empty()) && !SSL_is_dtls(ssl); if (enable_early_data) { // QUIC does not use the max_early_data_size parameter and always sets it // to a fixed value. See RFC 9001, section 4.6.1. session->ticket_max_early_data = - ssl->quic_method != nullptr ? 0xffffffff : kMaxEarlyDataAccepted; + SSL_is_quic(ssl) ? 0xffffffff : kMaxEarlyDataAccepted; } static_assert(kMaxTickets < 256, "Too many tickets"); @@ -257,7 +257,7 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (ssl->quic_method != nullptr && client_hello.session_id_len > 0) { + if (SSL_is_quic(ssl) && client_hello.session_id_len > 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_COMPATIBILITY_MODE); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); return ssl_hs_error; @@ -557,7 +557,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { } // Copy the QUIC early data context to the session. - if (ssl->enable_early_data && ssl->quic_method) { + if (ssl->enable_early_data && SSL_is_quic(ssl)) { if (!hs->new_session->quic_early_data_context.CopyFrom( hs->config->quic_early_data_context)) { ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); @@ -988,8 +988,7 @@ static enum ssl_hs_wait_t do_send_half_rtt_ticket(SSL_HANDSHAKE *hs) { // Finished early. See RFC 8446, section 4.6.1. static const uint8_t kEndOfEarlyData[4] = {SSL3_MT_END_OF_EARLY_DATA, 0, 0, 0}; - if (ssl->quic_method == nullptr && - !hs->transcript.Update(kEndOfEarlyData)) { + if (!SSL_is_quic(ssl) && !hs->transcript.Update(kEndOfEarlyData)) { OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); return ssl_hs_error; } @@ -1009,8 +1008,8 @@ static enum ssl_hs_wait_t do_send_half_rtt_ticket(SSL_HANDSHAKE *hs) { // Feed the predicted Finished into the transcript. This allows us to derive // the resumption secret early and send half-RTT tickets. // - // TODO(crbug.com/42290594): Queuing up half-RTT tickets with DTLS will also - // make implicit ACKing more subtle. + // TODO(crbug.com/381113363): Don't use half-RTT tickets with DTLS 1.3. + // TODO(crbug.com/376939532): Perhaps don't use half-RTT tickets at all. assert(!SSL_is_dtls(hs->ssl)); assert(hs->expected_client_finished.size() <= 0xff); uint8_t header[4] = { @@ -1032,7 +1031,7 @@ static enum ssl_hs_wait_t do_send_half_rtt_ticket(SSL_HANDSHAKE *hs) { static bool uses_end_of_early_data(const SSL *ssl) { // DTLS and QUIC omit the EndOfEarlyData message. See RFC 9001, section 8.3, // and RFC 9147, section 5.6. - return ssl->quic_method == nullptr && !SSL_is_dtls(ssl); + return !SSL_is_quic(ssl) && !SSL_is_dtls(ssl); } static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) { @@ -1275,17 +1274,29 @@ static enum ssl_hs_wait_t do_read_client_finished(SSL_HANDSHAKE *hs) { } ssl->method->next_message(ssl); - return ssl_hs_ack; + if (SSL_is_dtls(ssl)) { + ssl->method->schedule_ack(ssl); + return ssl_hs_flush; + } + return ssl_hs_ok; } static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) { + SSL *const ssl = hs->ssl; bool sent_tickets; if (!add_new_session_tickets(hs, &sent_tickets)) { return ssl_hs_error; } hs->tls13_state = state13_done; - return sent_tickets ? ssl_hs_flush_post_handshake : ssl_hs_ok; + // In QUIC and DTLS, we can flush the ticket to the transport immediately. In + // TLS over TCP-like transports, we defer until the server performs a write. + // This prevents a non-reading client from causing the server to hang in the + // case of a small server write buffer. Consumers which don't write data to + // the client will need to do a zero-byte write if they wish to flush the + // tickets. + bool should_flush = sent_tickets && (SSL_is_dtls(ssl) || SSL_is_quic(ssl)); + return should_flush ? ssl_hs_flush : ssl_hs_ok; } enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) { diff --git a/Sources/CNIOBoringSSL/ssl/tls_method.cc b/Sources/CNIOBoringSSL/ssl/tls_method.cc index 4ba41a33..2ab6e058 100644 --- a/Sources/CNIOBoringSSL/ssl/tls_method.cc +++ b/Sources/CNIOBoringSSL/ssl/tls_method.cc @@ -92,7 +92,7 @@ static bool tls_set_read_state(SSL *ssl, ssl_encryption_level_t level, return false; } - if (ssl->quic_method != nullptr) { + if (SSL_is_quic(ssl)) { if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && !ssl->quic_method->set_read_secret(ssl, level, aead_ctx->cipher(), traffic_secret.data(), @@ -121,7 +121,7 @@ static bool tls_set_write_state(SSL *ssl, ssl_encryption_level_t level, return false; } - if (ssl->quic_method != nullptr) { + if (SSL_is_quic(ssl)) { if ((ssl->s3->hs == nullptr || !ssl->s3->hs->hints_requested) && !ssl->quic_method->set_write_secret(ssl, level, aead_ctx->cipher(), traffic_secret.data(), @@ -143,6 +143,15 @@ static bool tls_set_write_state(SSL *ssl, ssl_encryption_level_t level, return true; } +static void tls_finish_flight(SSL *ssl) { + // We don't track whether a flight is complete in TLS and instead always flush + // every queued message in |tls_flush|, whether the flight is complete or not. +} + +static void tls_schedule_ack(SSL *ssl) { + // TLS does not use ACKs. +} + static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = { false /* is_dtls */, tls_new, @@ -159,8 +168,9 @@ static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = { tls_finish_message, tls_add_message, tls_add_change_cipher_spec, - tls_flush_flight, - /*send_ack=*/nullptr, + tls_finish_flight, + tls_schedule_ack, + tls_flush, tls_on_handshake_complete, tls_set_read_state, tls_set_write_state, diff --git a/Sources/CNIOBoringSSL/ssl/tls_record.cc b/Sources/CNIOBoringSSL/ssl/tls_record.cc index 9ecd8485..b1a51938 100644 --- a/Sources/CNIOBoringSSL/ssl/tls_record.cc +++ b/Sources/CNIOBoringSSL/ssl/tls_record.cc @@ -596,7 +596,7 @@ using namespace bssl; size_t SSL_max_seal_overhead(const SSL *ssl) { if (SSL_is_dtls(ssl)) { - // TODO(crbug.com/42290594): Use the 0-RTT epoch if writing 0-RTT. + // TODO(crbug.com/381113363): Use the 0-RTT epoch if writing 0-RTT. return dtls_max_seal_overhead(ssl, ssl->d1->write_epoch.epoch()); } diff --git a/scripts/vendor-boringssl.sh b/scripts/vendor-boringssl.sh index 09a7465a..908726a0 100755 --- a/scripts/vendor-boringssl.sh +++ b/scripts/vendor-boringssl.sh @@ -398,9 +398,7 @@ cat << EOF > "$DSTROOT/include/CNIOBoringSSL.h" #include "CNIOBoringSSL_type_check.h" #include "CNIOBoringSSL_x509_vfy.h" #include "CNIOBoringSSL_x509v3.h" -#include "experimental/CNIOBoringSSL_dilithium.h" #include "experimental/CNIOBoringSSL_kyber.h" -#include "experimental/CNIOBoringSSL_spx.h" #endif // C_NIO_BORINGSSL_H EOF