Add initial HRSS support.
This change includes support for a variant of [HRSS], a post-quantum KEM based on NTRU. It includes changes suggested in [SXY]. This is not yet ready for any deployment: some breaking changes, like removing the confirmation hash, are still planned. (CLA for HRSS's assembly code noted in b/119426559.) [HRSS] https://eprint.iacr.org/2017/667.pdf [SXY] https://eprint.iacr.org/2017/1005.pdf Change-Id: I85d813733b066d5c578484bdd248de3f764194db Reviewed-on: https://boringssl-review.googlesource.com/c/33105 Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
602f4669ab
commit
7b935937b1
@ -105,6 +105,7 @@ if(${ARCH} STREQUAL "arm")
|
|||||||
chacha/chacha-armv4.${ASM_EXT}
|
chacha/chacha-armv4.${ASM_EXT}
|
||||||
curve25519/asm/x25519-asm-arm.S
|
curve25519/asm/x25519-asm-arm.S
|
||||||
poly1305/poly1305_arm_asm.S
|
poly1305/poly1305_arm_asm.S
|
||||||
|
hrss/asm/poly_mul_vec_armv7_neon.S
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -131,6 +132,7 @@ if(${ARCH} STREQUAL "x86_64")
|
|||||||
chacha/chacha-x86_64.${ASM_EXT}
|
chacha/chacha-x86_64.${ASM_EXT}
|
||||||
cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT}
|
cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT}
|
||||||
cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT}
|
cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT}
|
||||||
|
hrss/asm/poly_rq_mul.S
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -275,6 +277,7 @@ add_library(
|
|||||||
evp/sign.c
|
evp/sign.c
|
||||||
ex_data.c
|
ex_data.c
|
||||||
hkdf/hkdf.c
|
hkdf/hkdf.c
|
||||||
|
hrss/hrss.c
|
||||||
lhash/lhash.c
|
lhash/lhash.c
|
||||||
mem.c
|
mem.c
|
||||||
obj/obj.c
|
obj/obj.c
|
||||||
@ -455,6 +458,7 @@ add_executable(
|
|||||||
fipsmodule/rand/ctrdrbg_test.cc
|
fipsmodule/rand/ctrdrbg_test.cc
|
||||||
hkdf/hkdf_test.cc
|
hkdf/hkdf_test.cc
|
||||||
hmac_extra/hmac_test.cc
|
hmac_extra/hmac_test.cc
|
||||||
|
hrss/hrss_test.cc
|
||||||
lhash/lhash_test.cc
|
lhash/lhash_test.cc
|
||||||
obj/obj_test.cc
|
obj/obj_test.cc
|
||||||
pem/pem_test.cc
|
pem/pem_test.cc
|
||||||
|
4260
crypto/hrss/asm/poly_mul_vec_armv7_neon.S
Normal file
4260
crypto/hrss/asm/poly_mul_vec_armv7_neon.S
Normal file
File diff suppressed because it is too large
Load Diff
8457
crypto/hrss/asm/poly_rq_mul.S
Normal file
8457
crypto/hrss/asm/poly_rq_mul.S
Normal file
File diff suppressed because it is too large
Load Diff
2265
crypto/hrss/hrss.c
Normal file
2265
crypto/hrss/hrss.c
Normal file
File diff suppressed because it is too large
Load Diff
475
crypto/hrss/hrss_test.cc
Normal file
475
crypto/hrss/hrss_test.cc
Normal file
@ -0,0 +1,475 @@
|
|||||||
|
/* Copyright (c) 2018, Google Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <openssl/hrss.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
|
#include "../test/test_util.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
// poly2_from_bits takes the least-significant bit from each byte of |in| and
|
||||||
|
// sets the bits of |*out| to match.
|
||||||
|
static void poly2_from_bits(struct poly2 *out, const uint8_t in[N]) {
|
||||||
|
crypto_word_t *words = out->v;
|
||||||
|
unsigned shift = 0;
|
||||||
|
crypto_word_t word = 0;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
word >>= 1;
|
||||||
|
word |= (crypto_word_t)(in[i] & 1) << (BITS_PER_WORD - 1);
|
||||||
|
shift++;
|
||||||
|
|
||||||
|
if (shift == BITS_PER_WORD) {
|
||||||
|
*words = word;
|
||||||
|
words++;
|
||||||
|
word = 0;
|
||||||
|
shift = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
word >>= BITS_PER_WORD - shift;
|
||||||
|
*words = word;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HRSS, Poly2RotateRight) {
|
||||||
|
uint8_t bits[N];
|
||||||
|
RAND_bytes(bits, sizeof(bits));
|
||||||
|
for (size_t i = 0; i < N; i++) {
|
||||||
|
bits[i] &= 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct poly2 p, orig, shifted;
|
||||||
|
poly2_from_bits(&p, bits);
|
||||||
|
OPENSSL_memcpy(&orig, &p, sizeof(orig));
|
||||||
|
|
||||||
|
// Test |HRSS_poly2_rotr_consttime| by manually rotating |bits| step-by-step
|
||||||
|
// and testing every possible shift to ensure that it produces the correct
|
||||||
|
// answer.
|
||||||
|
for (size_t shift = 0; shift <= N; shift++) {
|
||||||
|
SCOPED_TRACE(shift);
|
||||||
|
|
||||||
|
OPENSSL_memcpy(&p, &orig, sizeof(orig));
|
||||||
|
HRSS_poly2_rotr_consttime(&p, shift);
|
||||||
|
poly2_from_bits(&shifted, bits);
|
||||||
|
ASSERT_EQ(
|
||||||
|
Bytes(reinterpret_cast<const uint8_t *>(&shifted), sizeof(shifted)),
|
||||||
|
Bytes(reinterpret_cast<const uint8_t *>(&p), sizeof(p)));
|
||||||
|
|
||||||
|
const uint8_t least_significant_bit = bits[0];
|
||||||
|
OPENSSL_memmove(bits, &bits[1], N-1);
|
||||||
|
bits[N-1] = least_significant_bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// poly3_rand sets |r| to a random value (albeit with bias).
|
||||||
|
static void poly3_rand(poly3 *p) {
|
||||||
|
RAND_bytes(reinterpret_cast<uint8_t *>(p), sizeof(p));
|
||||||
|
p->s.v[WORDS_PER_POLY - 1] &= (UINT64_C(1) << BITS_IN_LAST_WORD) - 1;
|
||||||
|
p->a.v[WORDS_PER_POLY - 1] &= (UINT64_C(1) << BITS_IN_LAST_WORD) - 1;
|
||||||
|
// (s, a) = (1, 1) is invalid. Map those to one.
|
||||||
|
for (size_t j = 0; j < WORDS_PER_POLY; j++) {
|
||||||
|
p->s.v[j] ^= p->s.v[j] & p->a.v[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// poly3_word_add sets (|s1|, |a1|) += (|s2|, |a2|).
|
||||||
|
static void poly3_word_add(crypto_word_t *s1, crypto_word_t *a1,
|
||||||
|
const crypto_word_t s2, const crypto_word_t a2) {
|
||||||
|
const crypto_word_t x = *a1 ^ a2;
|
||||||
|
const crypto_word_t y = (*s1 ^ s2) ^ (*a1 & a2);
|
||||||
|
const crypto_word_t z = *s1 & s2;
|
||||||
|
*s1 = y & ~x;
|
||||||
|
*a1 = z | (x & ~y);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HRSS, Poly3Invert) {
|
||||||
|
poly3 p, inverse, result;
|
||||||
|
memset(&p, 0, sizeof(p));
|
||||||
|
memset(&inverse, 0, sizeof(inverse));
|
||||||
|
memset(&result, 0, sizeof(result));
|
||||||
|
|
||||||
|
// The inverse of -1 is -1.
|
||||||
|
p.s.v[0] = 1;
|
||||||
|
HRSS_poly3_invert(&inverse, &p);
|
||||||
|
EXPECT_EQ(Bytes(reinterpret_cast<const uint8_t*>(&p), sizeof(p)),
|
||||||
|
Bytes(reinterpret_cast<const uint8_t*>(&inverse), sizeof(inverse)));
|
||||||
|
|
||||||
|
// The inverse of 1 is 1.
|
||||||
|
p.s.v[0] = 0;
|
||||||
|
p.a.v[0] = 1;
|
||||||
|
HRSS_poly3_invert(&inverse, &p);
|
||||||
|
EXPECT_EQ(Bytes(reinterpret_cast<const uint8_t*>(&p), sizeof(p)),
|
||||||
|
Bytes(reinterpret_cast<const uint8_t*>(&inverse), sizeof(inverse)));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 500; i++) {
|
||||||
|
poly3 r;
|
||||||
|
poly3_rand(&r);
|
||||||
|
HRSS_poly3_invert(&inverse, &r);
|
||||||
|
HRSS_poly3_mul(&result, &inverse, &r);
|
||||||
|
// r×r⁻¹ = 1, and |p| contains 1.
|
||||||
|
EXPECT_EQ(
|
||||||
|
Bytes(reinterpret_cast<const uint8_t *>(&p), sizeof(p)),
|
||||||
|
Bytes(reinterpret_cast<const uint8_t *>(&result), sizeof(result)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HRSS, Poly3UnreducedInput) {
|
||||||
|
// Check that |poly3_mul| works correctly with inputs that aren't reduced mod
|
||||||
|
// Φ(N).
|
||||||
|
poly3 r, inverse, result, one;
|
||||||
|
poly3_rand(&r);
|
||||||
|
HRSS_poly3_invert(&inverse, &r);
|
||||||
|
HRSS_poly3_mul(&result, &inverse, &r);
|
||||||
|
|
||||||
|
memset(&one, 0, sizeof(one));
|
||||||
|
one.a.v[0] = 1;
|
||||||
|
EXPECT_EQ(Bytes(reinterpret_cast<const uint8_t *>(&one), sizeof(one)),
|
||||||
|
Bytes(reinterpret_cast<const uint8_t *>(&result), sizeof(result)));
|
||||||
|
|
||||||
|
// |r| is probably already not reduced mod Φ(N), but add x^701 - 1 and
|
||||||
|
// recompute to ensure that we get the same answer. (Since (x^701 - 1) ≡ 0 mod
|
||||||
|
// Φ(N).)
|
||||||
|
poly3_word_add(&r.s.v[0], &r.a.v[0], 1, 0);
|
||||||
|
poly3_word_add(&r.s.v[WORDS_PER_POLY - 1], &r.a.v[WORDS_PER_POLY - 1], 0,
|
||||||
|
UINT64_C(1) << BITS_IN_LAST_WORD);
|
||||||
|
|
||||||
|
HRSS_poly3_mul(&result, &inverse, &r);
|
||||||
|
EXPECT_EQ(Bytes(reinterpret_cast<const uint8_t *>(&one), sizeof(one)),
|
||||||
|
Bytes(reinterpret_cast<const uint8_t *>(&result), sizeof(result)));
|
||||||
|
|
||||||
|
// Check that x^700 × 1 gives -x^699 - x^698 … -1.
|
||||||
|
poly3 x700;
|
||||||
|
memset(&x700, 0, sizeof(x700));
|
||||||
|
x700.a.v[WORDS_PER_POLY-1] = UINT64_C(1) << (BITS_IN_LAST_WORD - 1);
|
||||||
|
HRSS_poly3_mul(&result, &one, &x700);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < WORDS_PER_POLY-1; i++) {
|
||||||
|
EXPECT_EQ(CONSTTIME_TRUE_W, result.s.v[i]);
|
||||||
|
EXPECT_EQ(0u, result.a.v[i]);
|
||||||
|
}
|
||||||
|
EXPECT_EQ((UINT64_C(1) << (BITS_IN_LAST_WORD - 1)) - 1,
|
||||||
|
result.s.v[WORDS_PER_POLY - 1]);
|
||||||
|
EXPECT_EQ(0u, result.a.v[WORDS_PER_POLY - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HRSS, Basic) {
|
||||||
|
uint8_t generate_key_entropy[HRSS_GENERATE_KEY_BYTES];
|
||||||
|
for (unsigned i = 0; i < sizeof(generate_key_entropy); i++) {
|
||||||
|
generate_key_entropy[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRSS_public_key pub;
|
||||||
|
HRSS_private_key priv;
|
||||||
|
HRSS_generate_key(&pub, &priv, generate_key_entropy);
|
||||||
|
|
||||||
|
uint8_t encap_entropy[HRSS_ENCAP_BYTES];
|
||||||
|
for (unsigned i = 0; i < sizeof(encap_entropy); i++) {
|
||||||
|
encap_entropy[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
|
||||||
|
uint8_t shared_key[HRSS_KEY_BYTES];
|
||||||
|
HRSS_encap(ciphertext, shared_key, &pub, encap_entropy);
|
||||||
|
|
||||||
|
HRSS_public_key pub2;
|
||||||
|
uint8_t pub_bytes[HRSS_PUBLIC_KEY_BYTES];
|
||||||
|
HRSS_marshal_public_key(pub_bytes, &pub);
|
||||||
|
ASSERT_TRUE(HRSS_parse_public_key(&pub2, pub_bytes));
|
||||||
|
|
||||||
|
uint8_t shared_key2[HRSS_KEY_BYTES];
|
||||||
|
HRSS_decap(shared_key2, &pub2, &priv, ciphertext, sizeof(ciphertext));
|
||||||
|
|
||||||
|
EXPECT_EQ(Bytes(shared_key), Bytes(shared_key2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HRSS, Random) {
|
||||||
|
for (unsigned i = 0; i < 10; i++) {
|
||||||
|
uint8_t generate_key_entropy[HRSS_GENERATE_KEY_BYTES];
|
||||||
|
RAND_bytes(generate_key_entropy, sizeof(generate_key_entropy));
|
||||||
|
SCOPED_TRACE(Bytes(generate_key_entropy));
|
||||||
|
|
||||||
|
HRSS_public_key pub;
|
||||||
|
HRSS_private_key priv;
|
||||||
|
HRSS_generate_key(&pub, &priv, generate_key_entropy);
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < 10; j++) {
|
||||||
|
uint8_t encap_entropy[HRSS_ENCAP_BYTES];
|
||||||
|
RAND_bytes(encap_entropy, sizeof(encap_entropy));
|
||||||
|
SCOPED_TRACE(Bytes(generate_key_entropy));
|
||||||
|
|
||||||
|
uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
|
||||||
|
uint8_t shared_key[HRSS_KEY_BYTES];
|
||||||
|
HRSS_encap(ciphertext, shared_key, &pub, encap_entropy);
|
||||||
|
|
||||||
|
uint8_t shared_key2[HRSS_KEY_BYTES];
|
||||||
|
HRSS_decap(shared_key2, &pub, &priv, ciphertext, sizeof(ciphertext));
|
||||||
|
|
||||||
|
EXPECT_EQ(Bytes(shared_key), Bytes(shared_key2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HRSS, Golden) {
|
||||||
|
uint8_t generate_key_entropy[HRSS_GENERATE_KEY_BYTES];
|
||||||
|
for (unsigned i = 0; i < HRSS_SAMPLE_BYTES; i++) {
|
||||||
|
generate_key_entropy[i] = i;
|
||||||
|
}
|
||||||
|
for (unsigned i = HRSS_SAMPLE_BYTES; i < 2 * HRSS_SAMPLE_BYTES; i++) {
|
||||||
|
generate_key_entropy[i] = 2 + i;
|
||||||
|
}
|
||||||
|
for (unsigned i = 2 * HRSS_SAMPLE_BYTES; i < sizeof(generate_key_entropy);
|
||||||
|
i++) {
|
||||||
|
generate_key_entropy[i] = 4 + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRSS_public_key pub;
|
||||||
|
HRSS_private_key priv;
|
||||||
|
OPENSSL_memset(&pub, 0, sizeof(pub));
|
||||||
|
OPENSSL_memset(&priv, 0, sizeof(priv));
|
||||||
|
HRSS_generate_key(&pub, &priv, generate_key_entropy);
|
||||||
|
|
||||||
|
static const uint8_t kExpectedPub[HRSS_PUBLIC_KEY_BYTES] = {
|
||||||
|
0xf8, 0x9f, 0xa0, 0xfc, 0xf1, 0xd4, 0xfa, 0x4d, 0x8f, 0x35, 0x28, 0x73,
|
||||||
|
0x0e, 0x37, 0x18, 0x1d, 0x09, 0xf3, 0x9e, 0x16, 0x0d, 0x7f, 0x9c, 0x82,
|
||||||
|
0x17, 0xa1, 0xa1, 0x88, 0x6b, 0x29, 0x5b, 0x3a, 0x30, 0xcd, 0x6f, 0x8e,
|
||||||
|
0x0c, 0xd3, 0x38, 0x0c, 0x05, 0x68, 0x6e, 0x4c, 0xcc, 0x20, 0xd4, 0x06,
|
||||||
|
0x77, 0x0c, 0xac, 0x1c, 0x49, 0x14, 0x00, 0xd6, 0x9b, 0x1c, 0xde, 0x43,
|
||||||
|
0x0a, 0x59, 0x37, 0xd6, 0x46, 0x68, 0x1f, 0x04, 0xcb, 0x73, 0x92, 0x37,
|
||||||
|
0x2d, 0x7f, 0x57, 0x70, 0x16, 0xe8, 0x06, 0x48, 0x3b, 0x66, 0xb3, 0x63,
|
||||||
|
0x02, 0x5a, 0x71, 0x46, 0xdd, 0xa4, 0xee, 0xb8, 0x78, 0x44, 0xfd, 0x9e,
|
||||||
|
0xd0, 0x71, 0x16, 0x00, 0xbd, 0x01, 0x1e, 0x27, 0x2e, 0xa0, 0xc6, 0x8d,
|
||||||
|
0x55, 0x89, 0x7c, 0x2a, 0x01, 0x2b, 0x1b, 0x75, 0xa2, 0xc2, 0xd1, 0x5a,
|
||||||
|
0x67, 0xfa, 0xdd, 0x3b, 0x70, 0x9d, 0xdb, 0xcd, 0x73, 0x32, 0x5e, 0x24,
|
||||||
|
0xb1, 0xcf, 0x23, 0xbe, 0x3c, 0x56, 0xcc, 0xbe, 0x61, 0xdb, 0xe7, 0x3c,
|
||||||
|
0xc7, 0xf5, 0x09, 0xe6, 0x87, 0xa0, 0x09, 0x52, 0x9d, 0x61, 0x5b, 0xc6,
|
||||||
|
0xd4, 0xc5, 0x2e, 0xc2, 0x6c, 0x87, 0x30, 0x36, 0x49, 0x6f, 0x04, 0xaa,
|
||||||
|
0xb3, 0x26, 0xd5, 0x63, 0xcf, 0xd4, 0x74, 0x1e, 0xc7, 0x79, 0xb3, 0xfc,
|
||||||
|
0x8c, 0x41, 0x36, 0x79, 0xaa, 0xd5, 0xba, 0x64, 0x49, 0x48, 0xdb, 0xeb,
|
||||||
|
0xe8, 0x33, 0x7d, 0xbe, 0x3b, 0x67, 0xd7, 0xfd, 0x93, 0x1e, 0x80, 0x8d,
|
||||||
|
0x17, 0xab, 0x6f, 0xfd, 0x1c, 0x4b, 0x2d, 0x5b, 0x90, 0xf0, 0xf0, 0x5d,
|
||||||
|
0xbe, 0x8f, 0x81, 0x18, 0x29, 0x08, 0x9a, 0x47, 0x1b, 0xc2, 0x2d, 0xa2,
|
||||||
|
0x22, 0x5a, 0x4f, 0xe9, 0x81, 0x64, 0xdd, 0x53, 0x2e, 0x67, 0xe5, 0x07,
|
||||||
|
0x1a, 0xf0, 0x0c, 0x54, 0x9b, 0xe2, 0xf8, 0xe6, 0xb3, 0xb6, 0xe0, 0x5a,
|
||||||
|
0x74, 0xfa, 0x8d, 0x9c, 0xa5, 0x7c, 0x6e, 0x73, 0xba, 0xee, 0x6e, 0x6e,
|
||||||
|
0x31, 0xcb, 0x59, 0xd7, 0xfd, 0x94, 0x1c, 0x4d, 0x62, 0xc6, 0x87, 0x0b,
|
||||||
|
0x38, 0x54, 0xc6, 0x35, 0xac, 0xc8, 0x8c, 0xc0, 0xd9, 0x99, 0xee, 0xfc,
|
||||||
|
0xa9, 0xde, 0xc4, 0x50, 0x88, 0x8e, 0x24, 0xf6, 0xd6, 0x04, 0x54, 0x3e,
|
||||||
|
0x81, 0xc4, 0x96, 0x9a, 0x40, 0xe5, 0xef, 0x8b, 0xec, 0x41, 0x50, 0x1d,
|
||||||
|
0x14, 0xae, 0xa4, 0x5a, 0xac, 0xd4, 0x73, 0x31, 0xc3, 0x1d, 0xc1, 0x96,
|
||||||
|
0x89, 0xd8, 0x62, 0x97, 0x60, 0x3f, 0x58, 0x2a, 0x5f, 0xcf, 0xcb, 0x26,
|
||||||
|
0x99, 0x69, 0x81, 0x13, 0x9c, 0xaf, 0x17, 0x91, 0xa8, 0xeb, 0x9a, 0xf9,
|
||||||
|
0xd3, 0x83, 0x47, 0x66, 0xc7, 0xf8, 0xd8, 0xe3, 0xd2, 0x7e, 0x58, 0xa9,
|
||||||
|
0xf5, 0xb2, 0x03, 0xbe, 0x7e, 0xa5, 0x29, 0x9d, 0xff, 0xd1, 0xd8, 0x55,
|
||||||
|
0x39, 0xc7, 0x2c, 0xce, 0x03, 0x64, 0xdc, 0x18, 0xe7, 0xb0, 0x60, 0x46,
|
||||||
|
0x26, 0xeb, 0xb7, 0x61, 0x4b, 0x91, 0x2c, 0xd8, 0xa2, 0xee, 0x63, 0x2e,
|
||||||
|
0x15, 0x0a, 0x58, 0x88, 0x04, 0xb1, 0xed, 0x6d, 0xf1, 0x5c, 0xc7, 0xee,
|
||||||
|
0x60, 0x38, 0x26, 0xc9, 0x31, 0x7e, 0x69, 0xe4, 0xac, 0x3c, 0x72, 0x09,
|
||||||
|
0x3e, 0xe6, 0x24, 0x30, 0x44, 0x6e, 0x66, 0x83, 0xb9, 0x2a, 0x22, 0xaf,
|
||||||
|
0x26, 0x1e, 0xaa, 0xa3, 0xf4, 0xb1, 0xa1, 0x5c, 0xfa, 0x5f, 0x0d, 0x71,
|
||||||
|
0xac, 0xe3, 0xe0, 0xc3, 0xdd, 0x4f, 0x96, 0x57, 0x8b, 0x58, 0xac, 0xe3,
|
||||||
|
0x42, 0x8e, 0x47, 0x72, 0xb1, 0xe4, 0x19, 0x68, 0x3e, 0xbb, 0x19, 0x14,
|
||||||
|
0xdf, 0x16, 0xb5, 0xde, 0x7f, 0x37, 0xaf, 0xd8, 0xd3, 0x3d, 0x6a, 0x16,
|
||||||
|
0x1b, 0x26, 0xd3, 0xcc, 0x53, 0x82, 0x57, 0x90, 0x89, 0xc5, 0x7e, 0x6d,
|
||||||
|
0x7e, 0x99, 0x5b, 0xcd, 0xd3, 0x18, 0xbb, 0x89, 0xef, 0x76, 0xbd, 0xd2,
|
||||||
|
0x62, 0xf0, 0xe8, 0x25, 0x2a, 0x8d, 0xe2, 0x21, 0xea, 0xde, 0x6e, 0xa5,
|
||||||
|
0xa4, 0x3d, 0x58, 0xee, 0xdf, 0x90, 0xc1, 0xa1, 0x38, 0x5d, 0x11, 0x50,
|
||||||
|
0xb5, 0xac, 0x9d, 0xb4, 0xfd, 0xef, 0x53, 0xe8, 0xc0, 0x17, 0x6c, 0x4f,
|
||||||
|
0x31, 0xe0, 0xcc, 0x8f, 0x80, 0x7a, 0x84, 0x14, 0xde, 0xee, 0xec, 0xdd,
|
||||||
|
0x6a, 0xad, 0x29, 0x65, 0xa5, 0x72, 0xc3, 0x73, 0x5f, 0xe3, 0x6f, 0x60,
|
||||||
|
0xb1, 0xfb, 0x0f, 0xaa, 0xc6, 0xda, 0x53, 0x4a, 0xb1, 0x92, 0x2a, 0xb7,
|
||||||
|
0x02, 0xbe, 0xf9, 0xdf, 0x37, 0x16, 0xe7, 0x5c, 0x38, 0x0b, 0x3c, 0xe2,
|
||||||
|
0xdd, 0x90, 0xb8, 0x7b, 0x48, 0x69, 0x79, 0x81, 0xc5, 0xae, 0x9a, 0x0d,
|
||||||
|
0x78, 0x95, 0x52, 0x63, 0x80, 0xda, 0x46, 0x69, 0x20, 0x57, 0x9b, 0x27,
|
||||||
|
0xe2, 0xe8, 0xbd, 0x2f, 0x45, 0xe6, 0x46, 0x40, 0xae, 0x50, 0xd5, 0xa2,
|
||||||
|
0x53, 0x93, 0xe1, 0x99, 0xfd, 0x13, 0x7c, 0xf6, 0x22, 0xc4, 0x6c, 0xab,
|
||||||
|
0xe3, 0xc9, 0x55, 0x0a, 0x16, 0x67, 0x68, 0x26, 0x6b, 0xd6, 0x7d, 0xde,
|
||||||
|
0xd3, 0xae, 0x71, 0x32, 0x02, 0xf1, 0x27, 0x67, 0x47, 0x74, 0xd9, 0x40,
|
||||||
|
0x35, 0x1d, 0x25, 0x72, 0x32, 0xdf, 0x75, 0xd5, 0x60, 0x26, 0xab, 0x90,
|
||||||
|
0xfa, 0xeb, 0x26, 0x11, 0x4b, 0xb4, 0xc5, 0xc2, 0x3e, 0xa9, 0x23, 0x3a,
|
||||||
|
0x4e, 0x6a, 0xb1, 0xbb, 0xb3, 0xea, 0xf9, 0x1e, 0xe4, 0x10, 0xf5, 0xdc,
|
||||||
|
0x35, 0xde, 0xb5, 0xee, 0xf0, 0xde, 0xa1, 0x18, 0x80, 0xc7, 0x13, 0x68,
|
||||||
|
0x46, 0x94, 0x0e, 0x2a, 0x8e, 0xf8, 0xe9, 0x26, 0x84, 0x42, 0x0f, 0x56,
|
||||||
|
0xed, 0x67, 0x7f, 0xeb, 0x7d, 0x35, 0x07, 0x01, 0x11, 0x81, 0x8b, 0x56,
|
||||||
|
0x88, 0xc6, 0x58, 0x61, 0x65, 0x3c, 0x5d, 0x9c, 0x58, 0x25, 0xd6, 0xdf,
|
||||||
|
0x4e, 0x3b, 0x93, 0xbf, 0x82, 0xe1, 0x19, 0xb8, 0xda, 0xde, 0x26, 0x38,
|
||||||
|
0xf2, 0xd9, 0x95, 0x24, 0x98, 0xde, 0x58, 0xf7, 0x0c, 0xe9, 0x32, 0xbb,
|
||||||
|
0xcc, 0xf7, 0x92, 0x69, 0xa2, 0xf0, 0xc3, 0xfa, 0xd2, 0x31, 0x8b, 0x43,
|
||||||
|
0x4e, 0x03, 0xe2, 0x13, 0x79, 0x6e, 0x73, 0x63, 0x3b, 0x45, 0xde, 0x80,
|
||||||
|
0xf4, 0x26, 0xb1, 0x38, 0xed, 0x62, 0x55, 0xc6, 0x6a, 0x67, 0x00, 0x2d,
|
||||||
|
0xba, 0xb2, 0xc5, 0xb6, 0x97, 0x62, 0x28, 0x64, 0x30, 0xb9, 0xfb, 0x3f,
|
||||||
|
0x94, 0x03, 0x48, 0x36, 0x2c, 0x5d, 0xfd, 0x08, 0x96, 0x40, 0xd1, 0x6c,
|
||||||
|
0xe5, 0xd0, 0xf8, 0x99, 0x40, 0x82, 0x87, 0xd7, 0xdc, 0x2f, 0x8b, 0xaa,
|
||||||
|
0x31, 0x96, 0x0a, 0x34, 0x33, 0xa6, 0xf1, 0x84, 0x6e, 0x33, 0x73, 0xc5,
|
||||||
|
0xe3, 0x26, 0xad, 0xd0, 0xcb, 0x62, 0x71, 0x82, 0xab, 0xd1, 0x82, 0x33,
|
||||||
|
0xe6, 0xca, 0xd0, 0x3e, 0xf5, 0x4d, 0x12, 0x6e, 0xf1, 0x83, 0xbd, 0xdc,
|
||||||
|
0x4d, 0xdf, 0x49, 0xbc, 0x63, 0xae, 0x7e, 0x59, 0xe8, 0x3c, 0x0d, 0xd6,
|
||||||
|
0x1d, 0x41, 0x89, 0x72, 0x52, 0xc0, 0xae, 0xd1, 0x2f, 0x0a, 0x8a, 0xce,
|
||||||
|
0x26, 0xd0, 0x3e, 0x0c, 0x71, 0x32, 0x52, 0xb2, 0xe4, 0xee, 0xa2, 0xe5,
|
||||||
|
0x28, 0xb6, 0x33, 0x69, 0x97, 0x5a, 0x53, 0xdb, 0x56, 0x63, 0xe9, 0xb3,
|
||||||
|
0x6d, 0x60, 0xf4, 0x7a, 0xce, 0xec, 0x36, 0x65, 0xd5, 0xca, 0x63, 0x2a,
|
||||||
|
0x19, 0x90, 0x14, 0x7b, 0x02, 0x33, 0xfa, 0x11, 0x58, 0x5a, 0xd9, 0xc5,
|
||||||
|
0x54, 0xf3, 0x28, 0xd5, 0x6e, 0xea, 0x85, 0xf5, 0x09, 0xbb, 0x81, 0x44,
|
||||||
|
0x1c, 0x63, 0x66, 0x81, 0xc5, 0x96, 0x2d, 0x7c, 0x0e, 0x75, 0x7b, 0xb4,
|
||||||
|
0x7e, 0x4e, 0x0c, 0xfd, 0x3c, 0xc5, 0x5a, 0x22, 0x85, 0x5c, 0xc8, 0xf3,
|
||||||
|
0x97, 0x98, 0x2c, 0xe9, 0x46, 0xb4, 0x02, 0xcf, 0x7d, 0xa4, 0xf2, 0x44,
|
||||||
|
0x7a, 0x89, 0x71, 0xa0, 0xfa, 0xb6, 0xa3, 0xaf, 0x13, 0x25, 0x46, 0xe2,
|
||||||
|
0x64, 0xe3, 0x69, 0xba, 0xf9, 0x68, 0x5c, 0xc0, 0xb7, 0xa8, 0xa6, 0x4b,
|
||||||
|
0xe1, 0x42, 0xe9, 0xb5, 0xc7, 0x84, 0xbb, 0xa6, 0x4b, 0x10, 0x4e, 0xd4,
|
||||||
|
0x68, 0x70, 0x0a, 0x75, 0x2a, 0xbb, 0x9d, 0xa0, 0xcb, 0xf0, 0x36, 0x4c,
|
||||||
|
0x70, 0x6c, 0x60, 0x4d, 0xfe, 0xe8, 0xc8, 0x66, 0x80, 0x1b, 0xf7, 0xcc,
|
||||||
|
0x1a, 0xdd, 0x6b, 0xa7, 0xa7, 0x25, 0x61, 0x0c, 0x31, 0xf0, 0x34, 0x63,
|
||||||
|
0x00, 0x0e, 0x48, 0x6a, 0x5a, 0x8d, 0x47, 0x94, 0x3f, 0x14, 0x16, 0xa8,
|
||||||
|
0x8a, 0x49, 0xbb, 0x0c, 0x43, 0x21, 0xda, 0xf2, 0xc5, 0xd0, 0xff, 0x19,
|
||||||
|
0x3e, 0x36, 0x64, 0x20, 0xb3, 0x70, 0xae, 0x54, 0xca, 0x73, 0x05, 0x56,
|
||||||
|
0x7a, 0x49, 0x45, 0xe9, 0x46, 0xbc, 0xc2, 0x61, 0x70, 0x40, 0x7c, 0xb0,
|
||||||
|
0xf7, 0xea, 0xc0, 0xd1, 0xb0, 0x77, 0x2c, 0xc7, 0xdd, 0x88, 0xcb, 0x9d,
|
||||||
|
0xea, 0x55, 0x6c, 0x5c, 0x28, 0xb8, 0x84, 0x1c, 0x2c, 0x06,
|
||||||
|
};
|
||||||
|
uint8_t pub_bytes[HRSS_PUBLIC_KEY_BYTES];
|
||||||
|
HRSS_marshal_public_key(pub_bytes, &pub);
|
||||||
|
EXPECT_EQ(Bytes(pub_bytes), Bytes(kExpectedPub));
|
||||||
|
|
||||||
|
uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
|
||||||
|
uint8_t shared_key[HRSS_KEY_BYTES];
|
||||||
|
OPENSSL_STATIC_ASSERT(
|
||||||
|
sizeof(kExpectedPub) >= HRSS_ENCAP_BYTES,
|
||||||
|
"Private key too small to use as input to HRSS encapsulation");
|
||||||
|
HRSS_encap(ciphertext, shared_key, &pub, kExpectedPub);
|
||||||
|
|
||||||
|
static const uint8_t kExpectedCiphertext[HRSS_CIPHERTEXT_BYTES] = {
|
||||||
|
0x8e, 0x6b, 0x46, 0x9d, 0x4a, 0xef, 0xa6, 0x8c, 0x28, 0x7b, 0xec, 0x6f,
|
||||||
|
0x13, 0x2d, 0x7f, 0x6c, 0xca, 0x7d, 0x9e, 0x6b, 0x54, 0x62, 0xa3, 0x13,
|
||||||
|
0xe1, 0x1e, 0x8f, 0x5f, 0x71, 0x67, 0xc4, 0x85, 0xdf, 0xd5, 0x6b, 0xbd,
|
||||||
|
0x86, 0x0f, 0x98, 0xec, 0xa5, 0x04, 0xf7, 0x7b, 0x2a, 0xbe, 0xcb, 0xac,
|
||||||
|
0x29, 0xbe, 0xe1, 0x0f, 0xbc, 0x62, 0x87, 0x85, 0x7f, 0x05, 0xae, 0xe4,
|
||||||
|
0x3f, 0x87, 0xfc, 0x1f, 0xf7, 0x45, 0x1e, 0xa3, 0xdb, 0xb1, 0xa0, 0x25,
|
||||||
|
0xba, 0x82, 0xec, 0xca, 0x8d, 0xab, 0x7a, 0x20, 0x03, 0xeb, 0xe5, 0x5c,
|
||||||
|
0x9f, 0xd0, 0x46, 0x78, 0xf1, 0x5a, 0xc7, 0x9e, 0xb4, 0x10, 0x6d, 0x37,
|
||||||
|
0xc0, 0x75, 0x08, 0xfb, 0xeb, 0xcb, 0xd8, 0x35, 0x21, 0x9b, 0x89, 0xa0,
|
||||||
|
0xaa, 0x87, 0x00, 0x66, 0x38, 0x37, 0x68, 0xa4, 0xa3, 0x93, 0x8e, 0x2b,
|
||||||
|
0xca, 0xf7, 0x7a, 0x43, 0xb2, 0x15, 0x79, 0x81, 0xce, 0xa9, 0x09, 0xcb,
|
||||||
|
0x29, 0xd4, 0xcc, 0xef, 0xf1, 0x9b, 0xbd, 0xe6, 0x63, 0xd5, 0x26, 0x0f,
|
||||||
|
0xe8, 0x8b, 0xdf, 0xf1, 0xc3, 0xb4, 0x18, 0x0e, 0xf2, 0x1d, 0x5d, 0x82,
|
||||||
|
0x9b, 0x1f, 0xf3, 0xca, 0x36, 0x2a, 0x26, 0x0a, 0x7f, 0xc4, 0x0d, 0xbd,
|
||||||
|
0x5b, 0x15, 0x1c, 0x18, 0x6c, 0x11, 0x4e, 0xec, 0x36, 0x01, 0xc1, 0x15,
|
||||||
|
0xab, 0xf7, 0x0b, 0x1a, 0xd3, 0xa1, 0xbd, 0x68, 0xc8, 0x59, 0xe7, 0x49,
|
||||||
|
0x5c, 0xd5, 0x4b, 0x8c, 0x31, 0xdb, 0xb3, 0xea, 0x88, 0x09, 0x2f, 0xb9,
|
||||||
|
0x8b, 0xfd, 0x96, 0x35, 0x88, 0x53, 0x72, 0x40, 0xcd, 0x89, 0x75, 0xb4,
|
||||||
|
0x20, 0xf6, 0xf6, 0xe5, 0x74, 0x19, 0x48, 0xaf, 0x4b, 0xaa, 0x42, 0xa4,
|
||||||
|
0xc8, 0x90, 0xee, 0xf3, 0x12, 0x04, 0x63, 0x90, 0x92, 0x8a, 0x89, 0xc3,
|
||||||
|
0xa0, 0x7e, 0xfe, 0x19, 0xb3, 0x54, 0x53, 0x83, 0xe9, 0xc1, 0x6c, 0xe3,
|
||||||
|
0x97, 0xa6, 0x27, 0xc3, 0x20, 0x9a, 0x79, 0x35, 0xc9, 0xb5, 0xc0, 0x90,
|
||||||
|
0xe1, 0x56, 0x84, 0x69, 0xc2, 0x54, 0x77, 0x52, 0x48, 0x55, 0x71, 0x3e,
|
||||||
|
0xcd, 0xa7, 0xd6, 0x25, 0x5d, 0x49, 0x13, 0xd2, 0x59, 0xd7, 0xe1, 0xd1,
|
||||||
|
0x70, 0x46, 0xa0, 0xd4, 0xee, 0x59, 0x13, 0x1f, 0x1a, 0xd3, 0x39, 0x7d,
|
||||||
|
0xb0, 0x79, 0xf7, 0xc0, 0x73, 0x5e, 0xbb, 0x08, 0xf7, 0x5c, 0xb0, 0x31,
|
||||||
|
0x41, 0x3d, 0x7b, 0x1e, 0xf0, 0xe6, 0x47, 0x5c, 0x37, 0xd5, 0x54, 0xf1,
|
||||||
|
0xbb, 0x64, 0xd7, 0x41, 0x8b, 0x34, 0x55, 0xaa, 0xc3, 0x5a, 0x9c, 0xa0,
|
||||||
|
0xcc, 0x29, 0x8e, 0x5a, 0x1a, 0x93, 0x5a, 0x49, 0xd3, 0xd0, 0xa0, 0x56,
|
||||||
|
0xda, 0x32, 0xa2, 0xa9, 0xa7, 0x13, 0x42, 0x93, 0x9b, 0x20, 0x32, 0x37,
|
||||||
|
0x5c, 0x3e, 0x03, 0xa5, 0x28, 0x10, 0x93, 0xdd, 0xa0, 0x04, 0x7b, 0x2a,
|
||||||
|
0xbd, 0x31, 0xc3, 0x6a, 0x89, 0x58, 0x6e, 0x55, 0x0e, 0xc9, 0x5c, 0x70,
|
||||||
|
0x07, 0x10, 0xf1, 0x9a, 0xbd, 0xfb, 0xd2, 0xb7, 0x94, 0x5b, 0x4f, 0x8d,
|
||||||
|
0x90, 0xfa, 0xee, 0xae, 0x37, 0x48, 0xc5, 0xf8, 0x16, 0xa1, 0x3b, 0x70,
|
||||||
|
0x03, 0x1f, 0x0e, 0xb8, 0xbd, 0x8d, 0x30, 0x4f, 0x95, 0x31, 0x0b, 0x9f,
|
||||||
|
0xfc, 0x80, 0xf8, 0xef, 0xa3, 0x3c, 0xbc, 0xe2, 0x23, 0x23, 0x3e, 0x2a,
|
||||||
|
0x55, 0x11, 0xe8, 0x2c, 0x17, 0xea, 0x1c, 0xbd, 0x1d, 0x2d, 0x1b, 0xd5,
|
||||||
|
0x16, 0x9e, 0x05, 0xfc, 0x89, 0x64, 0x50, 0x4d, 0x9a, 0x22, 0x50, 0xc6,
|
||||||
|
0x5a, 0xd9, 0x58, 0x99, 0x8f, 0xbd, 0xf2, 0x4f, 0x2c, 0xdb, 0x51, 0x6a,
|
||||||
|
0x86, 0xe2, 0xc6, 0x64, 0x8f, 0x54, 0x1a, 0xf2, 0xcb, 0x34, 0x88, 0x08,
|
||||||
|
0xbd, 0x2a, 0x8f, 0xec, 0x29, 0xf5, 0x22, 0x36, 0x83, 0x99, 0xb9, 0x71,
|
||||||
|
0x8c, 0x99, 0x5c, 0xec, 0x91, 0x78, 0xc1, 0xe2, 0x2d, 0xe9, 0xd1, 0x4d,
|
||||||
|
0xf5, 0x15, 0x93, 0x4d, 0x93, 0x92, 0x9f, 0x0f, 0x33, 0x5e, 0xcd, 0x58,
|
||||||
|
0x5f, 0x3d, 0x52, 0xb9, 0x38, 0x6a, 0x85, 0x63, 0x8b, 0x63, 0x29, 0xcb,
|
||||||
|
0x67, 0x12, 0x25, 0xc2, 0x44, 0xd7, 0xab, 0x1a, 0x24, 0xca, 0x3d, 0xca,
|
||||||
|
0x77, 0xce, 0x28, 0x68, 0x1a, 0x91, 0xed, 0x7b, 0xc9, 0x70, 0x84, 0xab,
|
||||||
|
0xe2, 0xd4, 0xf4, 0xac, 0x58, 0xf6, 0x70, 0x99, 0xfc, 0x99, 0x4d, 0xbd,
|
||||||
|
0xb4, 0x1b, 0x4f, 0x15, 0x86, 0x95, 0x08, 0xd1, 0x4e, 0x73, 0xa9, 0xbc,
|
||||||
|
0x6a, 0x8c, 0xbc, 0xb5, 0x4b, 0xe0, 0xee, 0x35, 0x24, 0xf9, 0x12, 0xf5,
|
||||||
|
0x88, 0x70, 0x50, 0x6c, 0xfe, 0x0d, 0x35, 0xbd, 0xf7, 0xc4, 0x2e, 0x39,
|
||||||
|
0x16, 0x30, 0x6c, 0xf3, 0xb2, 0x19, 0x44, 0xaa, 0xcb, 0x4a, 0xf6, 0x75,
|
||||||
|
0xb7, 0x09, 0xb9, 0xe1, 0x47, 0x71, 0x70, 0x5c, 0x05, 0x5f, 0x50, 0x50,
|
||||||
|
0x9c, 0xd0, 0xe3, 0xc7, 0x91, 0xee, 0x6b, 0xc7, 0x0f, 0x71, 0x1b, 0xc3,
|
||||||
|
0x48, 0x8b, 0xed, 0x15, 0x26, 0x8c, 0xc3, 0xd5, 0x54, 0x08, 0xcc, 0x33,
|
||||||
|
0x79, 0xc0, 0x9f, 0x49, 0xc8, 0x75, 0xef, 0xb6, 0xf3, 0x29, 0x89, 0xfd,
|
||||||
|
0x75, 0xd1, 0xda, 0x92, 0xc3, 0x13, 0xc6, 0x76, 0x51, 0x11, 0x40, 0x7b,
|
||||||
|
0x82, 0xf7, 0x30, 0x79, 0x49, 0x04, 0xe3, 0xbb, 0x61, 0x34, 0xa6, 0x58,
|
||||||
|
0x0b, 0x7d, 0xef, 0x3e, 0xf9, 0xb3, 0x8d, 0x2a, 0xba, 0xe9, 0xbc, 0xc0,
|
||||||
|
0xa7, 0xe6, 0x6c, 0xda, 0xf8, 0x8c, 0xdf, 0x8d, 0x96, 0x83, 0x2d, 0x80,
|
||||||
|
0x4f, 0x21, 0x81, 0xde, 0x57, 0x9d, 0x0a, 0x3c, 0xcc, 0xec, 0x3b, 0xb2,
|
||||||
|
0x25, 0x96, 0x3c, 0xea, 0xfd, 0x46, 0x26, 0xbe, 0x1c, 0x79, 0x82, 0x1d,
|
||||||
|
0xe0, 0x14, 0x22, 0x7c, 0x80, 0x3d, 0xbd, 0x05, 0x90, 0xfa, 0xaf, 0x7d,
|
||||||
|
0x70, 0x13, 0x43, 0x0f, 0x3d, 0xa0, 0x7f, 0x92, 0x3a, 0x53, 0x69, 0xe4,
|
||||||
|
0xb0, 0x10, 0x0d, 0xa7, 0x73, 0xa8, 0x8c, 0x74, 0xab, 0xd7, 0x78, 0x15,
|
||||||
|
0x45, 0xec, 0x6e, 0xc8, 0x8b, 0xa0, 0xba, 0x21, 0x6f, 0xf3, 0x08, 0xb8,
|
||||||
|
0xc7, 0x4f, 0x14, 0xf5, 0xcc, 0xfd, 0x39, 0xbc, 0x11, 0xf5, 0xb9, 0x11,
|
||||||
|
0xba, 0xf3, 0x11, 0x24, 0x74, 0x3e, 0x0c, 0x07, 0x4f, 0xac, 0x2a, 0xb2,
|
||||||
|
0xb1, 0x3c, 0x00, 0xfa, 0xbb, 0x8c, 0xd8, 0x7d, 0x17, 0x5b, 0x8d, 0x39,
|
||||||
|
0xc6, 0x23, 0x31, 0x32, 0x7d, 0x6e, 0x20, 0x38, 0xd0, 0xc3, 0x58, 0xe2,
|
||||||
|
0xb1, 0xfe, 0x53, 0x6b, 0xc7, 0x10, 0x13, 0x7e, 0xc6, 0x7c, 0x67, 0x59,
|
||||||
|
0x43, 0x70, 0x4a, 0x2d, 0x7f, 0x76, 0xde, 0xbd, 0x45, 0x43, 0x56, 0x60,
|
||||||
|
0xcd, 0xe9, 0x24, 0x7b, 0xb7, 0x41, 0xce, 0x56, 0xed, 0xd3, 0x74, 0x75,
|
||||||
|
0xcc, 0x9d, 0x48, 0x61, 0xc8, 0x19, 0x66, 0x08, 0xfb, 0x28, 0x60, 0x1f,
|
||||||
|
0x83, 0x11, 0xc0, 0x9b, 0xbd, 0x71, 0x53, 0x36, 0x01, 0x76, 0xa8, 0xc0,
|
||||||
|
0xdc, 0x1d, 0x18, 0x85, 0x19, 0x65, 0xce, 0xcf, 0x14, 0x2e, 0x6c, 0x32,
|
||||||
|
0x15, 0xbc, 0x2c, 0x5e, 0x8f, 0xfc, 0x3c, 0xf0, 0x2d, 0xf5, 0x5c, 0x04,
|
||||||
|
0xc9, 0x22, 0xf4, 0xc3, 0xb8, 0x57, 0x79, 0x52, 0x41, 0xfd, 0xff, 0xcd,
|
||||||
|
0x26, 0xa8, 0xc0, 0xd2, 0xe1, 0x71, 0xd6, 0xf1, 0xf4, 0x0c, 0xa8, 0xeb,
|
||||||
|
0x0c, 0x33, 0x40, 0x25, 0x73, 0xbb, 0x31, 0xda, 0x0c, 0xa6, 0xee, 0x0c,
|
||||||
|
0x41, 0x51, 0x94, 0x3c, 0x24, 0x27, 0x65, 0xe9, 0xb5, 0xc4, 0xe2, 0x88,
|
||||||
|
0xc0, 0x82, 0xd0, 0x72, 0xd9, 0x10, 0x4d, 0x7f, 0xc0, 0x88, 0x94, 0x41,
|
||||||
|
0x2d, 0x05, 0x09, 0xfb, 0x97, 0x31, 0x6e, 0xc1, 0xe9, 0xf4, 0x50, 0x70,
|
||||||
|
0xdc, 0x3f, 0x0a, 0x90, 0x46, 0x37, 0x60, 0x8c, 0xfb, 0x06, 0x6e, 0xde,
|
||||||
|
0x6f, 0xa7, 0x6b, 0xa3, 0x88, 0x18, 0x96, 0x93, 0x19, 0x87, 0xe7, 0x0a,
|
||||||
|
0x98, 0xf0, 0x13, 0x01, 0xab, 0x7c, 0xeb, 0x25, 0xa5, 0xe2, 0x98, 0x44,
|
||||||
|
0x7d, 0x09, 0xe2, 0x42, 0x33, 0xd4, 0xeb, 0xcc, 0x9b, 0x70, 0xf6, 0x0f,
|
||||||
|
0xf0, 0xb2, 0x99, 0xcc, 0x4f, 0x64, 0xc4, 0x69, 0x12, 0xea, 0x56, 0xfe,
|
||||||
|
0x50, 0x0e, 0x02, 0x1f, 0x6d, 0x7a, 0x79, 0x62, 0xaa, 0x2e, 0x52, 0xaf,
|
||||||
|
0xa3, 0xed, 0xcd, 0xa7, 0x45, 0xe6, 0x86, 0xed, 0xa1, 0x73, 0x5b, 0x1e,
|
||||||
|
0x49, 0x4f, 0x92, 0x50, 0x83, 0x99, 0x3c, 0xf4, 0xf6, 0xa8, 0x49, 0xd7,
|
||||||
|
0x08, 0xf7, 0xdc, 0x28, 0x2c, 0xe6, 0x22, 0x6f, 0xf8, 0xfa, 0xba, 0x9e,
|
||||||
|
0x0a, 0xcf, 0x72, 0x74, 0x76, 0x75, 0x99, 0x4d, 0x3d, 0x9a, 0x4c, 0x54,
|
||||||
|
0xcd, 0xf8, 0x54, 0xf0, 0xbd, 0x73, 0xe9, 0x4f, 0x29, 0xd0, 0xe1, 0x24,
|
||||||
|
0x94, 0x52, 0xd6, 0x60, 0x80, 0x71, 0x24, 0x95, 0x92, 0x01, 0x0e, 0xa9,
|
||||||
|
0x7e, 0x64, 0x2e, 0xed, 0x51, 0xcc, 0xd2, 0xff, 0xfd, 0x0b, 0xf4, 0x1d,
|
||||||
|
0x25, 0x5d, 0x10, 0x87, 0x09, 0x55, 0x06, 0x95, 0xae, 0xb3, 0xef, 0xe9,
|
||||||
|
0xaa, 0x36, 0x15, 0x97, 0xe6, 0xf2, 0x24, 0xcf, 0x7d, 0xcd, 0x55, 0x11,
|
||||||
|
0xba, 0x20, 0xd0, 0xd7, 0xdc, 0xa6,
|
||||||
|
};
|
||||||
|
EXPECT_EQ(Bytes(ciphertext), Bytes(kExpectedCiphertext));
|
||||||
|
|
||||||
|
static const uint8_t kExpectedSharedKey[HRSS_KEY_BYTES] = {
|
||||||
|
0x04, 0x5a, 0x1a, 0xbc, 0x4c, 0x76, 0x47, 0x1f, 0xbf, 0xc9, 0x23,
|
||||||
|
0xec, 0xcb, 0x6e, 0x4d, 0x59, 0x8d, 0x3f, 0x90, 0x3e, 0x53, 0x73,
|
||||||
|
0x3c, 0x2c, 0x71, 0xcc, 0xac, 0xc5, 0xe0, 0xf2, 0xbc, 0xe8,
|
||||||
|
};
|
||||||
|
EXPECT_EQ(Bytes(shared_key), Bytes(kExpectedSharedKey));
|
||||||
|
|
||||||
|
HRSS_decap(shared_key, &pub, &priv, ciphertext, sizeof(ciphertext));
|
||||||
|
EXPECT_EQ(Bytes(shared_key, sizeof(shared_key)),
|
||||||
|
Bytes(kExpectedSharedKey, sizeof(kExpectedSharedKey)));
|
||||||
|
|
||||||
|
// Corrupt the ciphertext and ensure that the failure key is constant.
|
||||||
|
ciphertext[50] ^= 4;
|
||||||
|
HRSS_decap(shared_key, &pub, &priv, ciphertext, sizeof(ciphertext));
|
||||||
|
|
||||||
|
static const uint8_t kExpectedFailureKey[HRSS_KEY_BYTES] = {
|
||||||
|
0x3a, 0xec, 0xc0, 0x38, 0x4f, 0xa7, 0x17, 0xb2, 0x77, 0x61, 0xb1,
|
||||||
|
0xf8, 0x12, 0x7f, 0xd9, 0x61, 0x67, 0x70, 0x63, 0xbe, 0xa2, 0x72,
|
||||||
|
0xfe, 0x1a, 0x82, 0x8d, 0x1d, 0x90, 0xe0, 0x36, 0x69, 0x2d,
|
||||||
|
};
|
||||||
|
EXPECT_EQ(Bytes(shared_key), Bytes(kExpectedFailureKey));
|
||||||
|
}
|
50
crypto/hrss/internal.h
Normal file
50
crypto/hrss/internal.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/* Copyright (c) 2018, Google Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_HRSS_INTERNAL_H
|
||||||
|
#define OPENSSL_HEADER_HRSS_INTERNAL_H
|
||||||
|
|
||||||
|
#include <openssl/base.h>
|
||||||
|
#include "../internal.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define N 701
|
||||||
|
#define BITS_PER_WORD (sizeof(crypto_word_t) * 8)
|
||||||
|
#define WORDS_PER_POLY ((N + BITS_PER_WORD - 1) / BITS_PER_WORD)
|
||||||
|
#define BITS_IN_LAST_WORD (N % BITS_PER_WORD)
|
||||||
|
|
||||||
|
struct poly2 {
|
||||||
|
crypto_word_t v[WORDS_PER_POLY];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct poly3 {
|
||||||
|
struct poly2 s, a;
|
||||||
|
};
|
||||||
|
|
||||||
|
OPENSSL_EXPORT void HRSS_poly2_rotr_consttime(struct poly2 *p, size_t bits);
|
||||||
|
OPENSSL_EXPORT void HRSS_poly3_mul(struct poly3 *out, const struct poly3 *x,
|
||||||
|
const struct poly3 *y);
|
||||||
|
OPENSSL_EXPORT void HRSS_poly3_invert(struct poly3 *out,
|
||||||
|
const struct poly3 *in);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !OPENSSL_HEADER_HRSS_INTERNAL_H
|
@ -57,7 +57,7 @@
|
|||||||
/* This file is generated by crypto/obj/objects.go. */
|
/* This file is generated by crypto/obj/objects.go. */
|
||||||
|
|
||||||
|
|
||||||
#define NUM_NID 959
|
#define NUM_NID 960
|
||||||
|
|
||||||
static const uint8_t kObjectData[] = {
|
static const uint8_t kObjectData[] = {
|
||||||
/* NID_rsadsi */
|
/* NID_rsadsi */
|
||||||
@ -8755,6 +8755,7 @@ static const ASN1_OBJECT kObjects[NUM_NID] = {
|
|||||||
{"AuthPSK", "auth-psk", NID_auth_psk, 0, NULL, 0},
|
{"AuthPSK", "auth-psk", NID_auth_psk, 0, NULL, 0},
|
||||||
{"KxANY", "kx-any", NID_kx_any, 0, NULL, 0},
|
{"KxANY", "kx-any", NID_kx_any, 0, NULL, 0},
|
||||||
{"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0},
|
{"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0},
|
||||||
|
{"CECPQ2", "CECPQ2", NID_CECPQ2, 0, NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned kNIDsInShortNameOrder[] = {
|
static const unsigned kNIDsInShortNameOrder[] = {
|
||||||
@ -8816,6 +8817,7 @@ static const unsigned kNIDsInShortNameOrder[] = {
|
|||||||
110 /* CAST5-CFB */,
|
110 /* CAST5-CFB */,
|
||||||
109 /* CAST5-ECB */,
|
109 /* CAST5-ECB */,
|
||||||
111 /* CAST5-OFB */,
|
111 /* CAST5-OFB */,
|
||||||
|
959 /* CECPQ2 */,
|
||||||
894 /* CMAC */,
|
894 /* CMAC */,
|
||||||
13 /* CN */,
|
13 /* CN */,
|
||||||
141 /* CRLReason */,
|
141 /* CRLReason */,
|
||||||
@ -9720,6 +9722,7 @@ static const unsigned kNIDsInLongNameOrder[] = {
|
|||||||
285 /* Biometric Info */,
|
285 /* Biometric Info */,
|
||||||
179 /* CA Issuers */,
|
179 /* CA Issuers */,
|
||||||
785 /* CA Repository */,
|
785 /* CA Repository */,
|
||||||
|
959 /* CECPQ2 */,
|
||||||
131 /* Code Signing */,
|
131 /* Code Signing */,
|
||||||
783 /* Diffie-Hellman based MAC */,
|
783 /* Diffie-Hellman based MAC */,
|
||||||
382 /* Directory */,
|
382 /* Directory */,
|
||||||
|
@ -947,3 +947,4 @@ auth_ecdsa 955
|
|||||||
auth_psk 956
|
auth_psk 956
|
||||||
kx_any 957
|
kx_any 957
|
||||||
auth_any 958
|
auth_any 958
|
||||||
|
CECPQ2 959
|
||||||
|
@ -1334,6 +1334,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
|
|||||||
# NID for X25519 (no corresponding OID).
|
# NID for X25519 (no corresponding OID).
|
||||||
: X25519
|
: X25519
|
||||||
|
|
||||||
|
# NID for CECPQ2 (no corresponding OID).
|
||||||
|
: CECPQ2
|
||||||
|
|
||||||
# See RFC 8410.
|
# See RFC 8410.
|
||||||
1 3 101 112 : ED25519
|
1 3 101 112 : ED25519
|
||||||
|
|
||||||
|
102
include/openssl/hrss.h
Normal file
102
include/openssl/hrss.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/* Copyright (c) 2018, Google Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||||
|
|
||||||
|
#ifndef OPENSSL_HEADER_HRSS_H
|
||||||
|
#define OPENSSL_HEADER_HRSS_H
|
||||||
|
|
||||||
|
#include <openssl/base.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// HRSS
|
||||||
|
//
|
||||||
|
// HRSS is a structured-lattice-based post-quantum key encapsulation mechanism.
|
||||||
|
// The best exposition is https://eprint.iacr.org/2017/667.pdf although this
|
||||||
|
// implementation uses a different KEM construction based on
|
||||||
|
// https://eprint.iacr.org/2017/1005.pdf.
|
||||||
|
|
||||||
|
struct HRSS_private_key {
|
||||||
|
uint8_t opaque[1808];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HRSS_public_key {
|
||||||
|
uint8_t opaque[1424];
|
||||||
|
};
|
||||||
|
|
||||||
|
// HRSS_SAMPLE_BYTES is the number of bytes of entropy needed to generate a
|
||||||
|
// short vector. There are 701 coefficients, but the final one is always set to
|
||||||
|
// zero when sampling. Otherwise, one byte of input is enough to generate two
|
||||||
|
// coefficients.
|
||||||
|
#define HRSS_SAMPLE_BYTES ((701 - 1) / 2)
|
||||||
|
// HRSS_GENERATE_KEY_BYTES is the number of bytes of entropy needed to generate
|
||||||
|
// an HRSS key pair.
|
||||||
|
#define HRSS_GENERATE_KEY_BYTES (HRSS_SAMPLE_BYTES + HRSS_SAMPLE_BYTES + 32)
|
||||||
|
// HRSS_ENCAP_BYTES is the number of bytes of entropy needed to encapsulate a
|
||||||
|
// session key.
|
||||||
|
#define HRSS_ENCAP_BYTES (HRSS_SAMPLE_BYTES + HRSS_SAMPLE_BYTES)
|
||||||
|
// HRSS_PUBLIC_KEY_BYTES is the number of bytes in a public key.
|
||||||
|
#define HRSS_PUBLIC_KEY_BYTES 1138
|
||||||
|
// HRSS_CIPHERTEXT_BYTES is the number of bytes in a ciphertext.
|
||||||
|
#define HRSS_CIPHERTEXT_BYTES (1138 + 32)
|
||||||
|
// HRSS_KEY_BYTES is the number of bytes in a shared key.
|
||||||
|
#define HRSS_KEY_BYTES 32
|
||||||
|
// HRSS_POLY3_BYTES is the number of bytes needed to serialise a mod 3
|
||||||
|
// polynomial.
|
||||||
|
#define HRSS_POLY3_BYTES 140
|
||||||
|
#define HRSS_PRIVATE_KEY_BYTES \
|
||||||
|
(HRSS_POLY3_BYTES * 2 + HRSS_PUBLIC_KEY_BYTES + 2 + 32)
|
||||||
|
|
||||||
|
// HRSS_generate_key is a deterministic function that outputs a public and
|
||||||
|
// private key based on the given entropy.
|
||||||
|
OPENSSL_EXPORT void HRSS_generate_key(
|
||||||
|
struct HRSS_public_key *out_pub, struct HRSS_private_key *out_priv,
|
||||||
|
const uint8_t input[HRSS_GENERATE_KEY_BYTES]);
|
||||||
|
|
||||||
|
// HRSS_encap is a deterministic function the generates and encrypts a random
|
||||||
|
// session key from the given entropy, writing those values to |out_shared_key|
|
||||||
|
// and |out_ciphertext|, respectively.
|
||||||
|
OPENSSL_EXPORT void HRSS_encap(uint8_t out_ciphertext[HRSS_CIPHERTEXT_BYTES],
|
||||||
|
uint8_t out_shared_key[HRSS_KEY_BYTES],
|
||||||
|
const struct HRSS_public_key *in_pub,
|
||||||
|
const uint8_t in[HRSS_ENCAP_BYTES]);
|
||||||
|
|
||||||
|
// HRSS_decap decrypts a session key from |ciphertext_len| bytes of
|
||||||
|
// |ciphertext|. If the ciphertext is valid, the decrypted key is written to
|
||||||
|
// |out_shared_key|. Otherwise the HMAC of |ciphertext| under a secret key (kept
|
||||||
|
// in |in_priv|) is written. If the ciphertext is the wrong length then it will
|
||||||
|
// leak which was done via side-channels. Otherwise it should perform either
|
||||||
|
// action in constant-time.
|
||||||
|
OPENSSL_EXPORT void HRSS_decap(uint8_t out_shared_key[HRSS_KEY_BYTES],
|
||||||
|
const struct HRSS_public_key *in_pub,
|
||||||
|
const struct HRSS_private_key *in_priv,
|
||||||
|
const uint8_t *ciphertext,
|
||||||
|
size_t ciphertext_len);
|
||||||
|
|
||||||
|
// HRSS_marshal_public_key serialises |in_pub| to |out|.
|
||||||
|
OPENSSL_EXPORT void HRSS_marshal_public_key(
|
||||||
|
uint8_t out[HRSS_PUBLIC_KEY_BYTES], const struct HRSS_public_key *in_pub);
|
||||||
|
|
||||||
|
// HRSS_parse_public_key sets |*out| to the public-key encoded in |in|. It
|
||||||
|
// returns true on success and zero on error.
|
||||||
|
OPENSSL_EXPORT int HRSS_parse_public_key(
|
||||||
|
struct HRSS_public_key *out, const uint8_t in[HRSS_PUBLIC_KEY_BYTES]);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
} // extern C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // OPENSSL_HEADER_HRSS_H
|
@ -4234,6 +4234,9 @@ extern "C" {
|
|||||||
#define LN_auth_any "auth-any"
|
#define LN_auth_any "auth-any"
|
||||||
#define NID_auth_any 958
|
#define NID_auth_any 958
|
||||||
|
|
||||||
|
#define SN_CECPQ2 "CECPQ2"
|
||||||
|
#define NID_CECPQ2 959
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
} /* extern C */
|
} /* extern C */
|
||||||
|
@ -2177,6 +2177,7 @@ OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
|
|||||||
#define SSL_CURVE_SECP384R1 24
|
#define SSL_CURVE_SECP384R1 24
|
||||||
#define SSL_CURVE_SECP521R1 25
|
#define SSL_CURVE_SECP521R1 25
|
||||||
#define SSL_CURVE_X25519 29
|
#define SSL_CURVE_X25519 29
|
||||||
|
#define SSL_CURVE_CECPQ2 16696
|
||||||
|
|
||||||
// SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently
|
// SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently
|
||||||
// completed handshake or 0 if not applicable.
|
// completed handshake or 0 if not applicable.
|
||||||
|
@ -307,7 +307,7 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == handback_after_ecdhe &&
|
if (type == handback_after_ecdhe &&
|
||||||
!s3->hs->key_share->Serialize(&key_share)) {
|
!s3->hs->key_shares[0]->Serialize(&key_share)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return CBB_flush(out);
|
return CBB_flush(out);
|
||||||
@ -471,7 +471,7 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (type == handback_after_ecdhe &&
|
if (type == handback_after_ecdhe &&
|
||||||
(s3->hs->key_share = SSLKeyShare::Create(&key_share)) == nullptr) {
|
(s3->hs->key_shares[0] = SSLKeyShare::Create(&key_share)) == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +590,8 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear some TLS 1.3 state that no longer needs to be retained.
|
// Clear some TLS 1.3 state that no longer needs to be retained.
|
||||||
hs->key_share.reset();
|
hs->key_shares[0].reset();
|
||||||
|
hs->key_shares[1].reset();
|
||||||
hs->key_share_bytes.Reset();
|
hs->key_share_bytes.Reset();
|
||||||
|
|
||||||
// A TLS 1.2 server would not know to skip the early data we offered. Report
|
// A TLS 1.2 server would not know to skip the early data we offered. Report
|
||||||
@ -1006,8 +1007,8 @@ static enum ssl_hs_wait_t do_read_server_key_exchange(SSL_HANDSHAKE *hs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize ECDH and save the peer public key for later.
|
// Initialize ECDH and save the peer public key for later.
|
||||||
hs->key_share = SSLKeyShare::Create(group_id);
|
hs->key_shares[0] = SSLKeyShare::Create(group_id);
|
||||||
if (!hs->key_share ||
|
if (!hs->key_shares[0] ||
|
||||||
!hs->peer_key.CopyFrom(point)) {
|
!hs->peer_key.CopyFrom(point)) {
|
||||||
return ssl_hs_error;
|
return ssl_hs_error;
|
||||||
}
|
}
|
||||||
@ -1324,7 +1325,7 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
|
|||||||
|
|
||||||
// Compute the premaster.
|
// Compute the premaster.
|
||||||
uint8_t alert = SSL_AD_DECODE_ERROR;
|
uint8_t alert = SSL_AD_DECODE_ERROR;
|
||||||
if (!hs->key_share->Accept(&child, &pms, &alert, hs->peer_key)) {
|
if (!hs->key_shares[0]->Accept(&child, &pms, &alert, hs->peer_key)) {
|
||||||
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
|
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
|
||||||
return ssl_hs_error;
|
return ssl_hs_error;
|
||||||
}
|
}
|
||||||
@ -1333,7 +1334,8 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The key exchange state may now be discarded.
|
// The key exchange state may now be discarded.
|
||||||
hs->key_share.reset();
|
hs->key_shares[0].reset();
|
||||||
|
hs->key_shares[1].reset();
|
||||||
hs->peer_key.Reset();
|
hs->peer_key.Reset();
|
||||||
} else if (alg_k & SSL_kPSK) {
|
} else if (alg_k & SSL_kPSK) {
|
||||||
// For plain PSK, other_secret is a block of 0s with the same length as
|
// For plain PSK, other_secret is a block of 0s with the same length as
|
||||||
|
@ -932,12 +932,12 @@ static enum ssl_hs_wait_t do_send_server_certificate(SSL_HANDSHAKE *hs) {
|
|||||||
hs->new_session->group_id = group_id;
|
hs->new_session->group_id = group_id;
|
||||||
|
|
||||||
// Set up ECDH, generate a key, and emit the public half.
|
// Set up ECDH, generate a key, and emit the public half.
|
||||||
hs->key_share = SSLKeyShare::Create(group_id);
|
hs->key_shares[0] = SSLKeyShare::Create(group_id);
|
||||||
if (!hs->key_share ||
|
if (!hs->key_shares[0] ||
|
||||||
!CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) ||
|
!CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) ||
|
||||||
!CBB_add_u16(cbb.get(), group_id) ||
|
!CBB_add_u16(cbb.get(), group_id) ||
|
||||||
!CBB_add_u8_length_prefixed(cbb.get(), &child) ||
|
!CBB_add_u8_length_prefixed(cbb.get(), &child) ||
|
||||||
!hs->key_share->Offer(&child)) {
|
!hs->key_shares[0]->Offer(&child)) {
|
||||||
return ssl_hs_error;
|
return ssl_hs_error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1275,13 +1275,14 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
|
|||||||
|
|
||||||
// Compute the premaster.
|
// Compute the premaster.
|
||||||
uint8_t alert = SSL_AD_DECODE_ERROR;
|
uint8_t alert = SSL_AD_DECODE_ERROR;
|
||||||
if (!hs->key_share->Finish(&premaster_secret, &alert, peer_key)) {
|
if (!hs->key_shares[0]->Finish(&premaster_secret, &alert, peer_key)) {
|
||||||
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
|
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
|
||||||
return ssl_hs_error;
|
return ssl_hs_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The key exchange state may now be discarded.
|
// The key exchange state may now be discarded.
|
||||||
hs->key_share.reset();
|
hs->key_shares[0].reset();
|
||||||
|
hs->key_shares[1].reset();
|
||||||
} else if (!(alg_k & SSL_kPSK)) {
|
} else if (!(alg_k & SSL_kPSK)) {
|
||||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
|
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
|
||||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||||
|
@ -974,10 +974,10 @@ class SSLKeyShare {
|
|||||||
// |out_public_key|. It returns true on success and false on error.
|
// |out_public_key|. It returns true on success and false on error.
|
||||||
virtual bool Offer(CBB *out_public_key) PURE_VIRTUAL;
|
virtual bool Offer(CBB *out_public_key) PURE_VIRTUAL;
|
||||||
|
|
||||||
// Accept performs a key exchange against the |peer_key| generated by |offer|.
|
// Accept performs a key exchange against the |peer_key| generated by |Offer|.
|
||||||
// On success, it returns true, writes the public value to |out_public_key|,
|
// On success, it returns true, writes the public value to |out_public_key|,
|
||||||
// and sets |*out_secret| the shared secret. On failure, it returns false and
|
// and sets |*out_secret| to the shared secret. On failure, it returns false
|
||||||
// sets |*out_alert| to an alert to send to the peer.
|
// and sets |*out_alert| to an alert to send to the peer.
|
||||||
//
|
//
|
||||||
// The default implementation calls |Offer| and then |Finish|, assuming a key
|
// The default implementation calls |Offer| and then |Finish|, assuming a key
|
||||||
// exchange protocol where the peers are symmetric.
|
// exchange protocol where the peers are symmetric.
|
||||||
@ -986,7 +986,7 @@ class SSLKeyShare {
|
|||||||
|
|
||||||
// Finish performs a key exchange against the |peer_key| generated by
|
// Finish performs a key exchange against the |peer_key| generated by
|
||||||
// |Accept|. On success, it returns true and sets |*out_secret| to the shared
|
// |Accept|. On success, it returns true and sets |*out_secret| to the shared
|
||||||
// secret. On failure, it returns zero and sets |*out_alert| to an alert to
|
// secret. On failure, it returns false and sets |*out_alert| to an alert to
|
||||||
// send to the peer.
|
// send to the peer.
|
||||||
virtual bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
virtual bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
||||||
Span<const uint8_t> peer_key) PURE_VIRTUAL;
|
Span<const uint8_t> peer_key) PURE_VIRTUAL;
|
||||||
@ -1436,8 +1436,10 @@ struct SSL_HANDSHAKE {
|
|||||||
// error, if |wait| is |ssl_hs_error|, is the error the handshake failed on.
|
// error, if |wait| is |ssl_hs_error|, is the error the handshake failed on.
|
||||||
UniquePtr<ERR_SAVE_STATE> error;
|
UniquePtr<ERR_SAVE_STATE> error;
|
||||||
|
|
||||||
// key_share is the current key exchange instance.
|
// key_shares are the current key exchange instances. The second is only used
|
||||||
UniquePtr<SSLKeyShare> key_share;
|
// as a client if we believe that we should offer two key shares in a
|
||||||
|
// ClientHello.
|
||||||
|
UniquePtr<SSLKeyShare> key_shares[2];
|
||||||
|
|
||||||
// transcript is the current handshake transcript.
|
// transcript is the current handshake transcript.
|
||||||
SSLTranscript transcript;
|
SSLTranscript transcript;
|
||||||
|
@ -24,8 +24,10 @@
|
|||||||
#include <openssl/curve25519.h>
|
#include <openssl/curve25519.h>
|
||||||
#include <openssl/ec.h>
|
#include <openssl/ec.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/hrss.h>
|
||||||
#include <openssl/mem.h>
|
#include <openssl/mem.h>
|
||||||
#include <openssl/nid.h>
|
#include <openssl/nid.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "../crypto/internal.h"
|
#include "../crypto/internal.h"
|
||||||
@ -207,12 +209,104 @@ class X25519KeyShare : public SSLKeyShare {
|
|||||||
uint8_t private_key_[32];
|
uint8_t private_key_[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CECPQ2KeyShare : public SSLKeyShare {
|
||||||
|
public:
|
||||||
|
CECPQ2KeyShare() {}
|
||||||
|
|
||||||
|
uint16_t GroupID() const override { return SSL_CURVE_CECPQ2; }
|
||||||
|
|
||||||
|
bool Offer(CBB *out) override {
|
||||||
|
uint8_t x25519_public_key[32];
|
||||||
|
X25519_keypair(x25519_public_key, x25519_private_key_);
|
||||||
|
|
||||||
|
uint8_t hrss_entropy[HRSS_GENERATE_KEY_BYTES];
|
||||||
|
RAND_bytes(hrss_entropy, sizeof(hrss_entropy));
|
||||||
|
HRSS_generate_key(&hrss_public_key_, &hrss_private_key_, hrss_entropy);
|
||||||
|
|
||||||
|
uint8_t hrss_public_key_bytes[HRSS_PUBLIC_KEY_BYTES];
|
||||||
|
HRSS_marshal_public_key(hrss_public_key_bytes, &hrss_public_key_);
|
||||||
|
|
||||||
|
if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
|
||||||
|
!CBB_add_bytes(out, hrss_public_key_bytes,
|
||||||
|
sizeof(hrss_public_key_bytes))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
|
||||||
|
uint8_t *out_alert, Span<const uint8_t> peer_key) override {
|
||||||
|
Array<uint8_t> secret;
|
||||||
|
if (!secret.Init(32 + HRSS_KEY_BYTES)) {
|
||||||
|
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t x25519_public_key[32];
|
||||||
|
X25519_keypair(x25519_public_key, x25519_private_key_);
|
||||||
|
|
||||||
|
HRSS_public_key peer_public_key;
|
||||||
|
if (peer_key.size() != 32 + HRSS_PUBLIC_KEY_BYTES ||
|
||||||
|
!HRSS_parse_public_key(&peer_public_key, peer_key.data() + 32) ||
|
||||||
|
!X25519(secret.data(), x25519_private_key_, peer_key.data())) {
|
||||||
|
*out_alert = SSL_AD_DECODE_ERROR;
|
||||||
|
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
|
||||||
|
uint8_t entropy[HRSS_ENCAP_BYTES];
|
||||||
|
RAND_bytes(entropy, sizeof(entropy));
|
||||||
|
HRSS_encap(ciphertext, secret.data() + 32, &peer_public_key, entropy);
|
||||||
|
|
||||||
|
if (!CBB_add_bytes(out_public_key, x25519_public_key,
|
||||||
|
sizeof(x25519_public_key)) ||
|
||||||
|
!CBB_add_bytes(out_public_key, ciphertext, sizeof(ciphertext))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_secret = std::move(secret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
||||||
|
Span<const uint8_t> peer_key) override {
|
||||||
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
Array<uint8_t> secret;
|
||||||
|
if (!secret.Init(32 + HRSS_KEY_BYTES)) {
|
||||||
|
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peer_key.size() != 32 + HRSS_CIPHERTEXT_BYTES ||
|
||||||
|
!X25519(secret.data(), x25519_private_key_, peer_key.data())) {
|
||||||
|
*out_alert = SSL_AD_DECODE_ERROR;
|
||||||
|
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRSS_decap(secret.data() + 32, &hrss_public_key_, &hrss_private_key_,
|
||||||
|
peer_key.data() + 32, peer_key.size() - 32);
|
||||||
|
|
||||||
|
*out_secret = std::move(secret);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t x25519_private_key_[32];
|
||||||
|
HRSS_public_key hrss_public_key_;
|
||||||
|
HRSS_private_key hrss_private_key_;
|
||||||
|
};
|
||||||
|
|
||||||
CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
|
CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
|
||||||
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
|
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
|
||||||
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
|
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
|
||||||
{NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
|
{NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
|
||||||
{NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
|
{NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
|
||||||
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
|
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
|
||||||
|
{NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -237,6 +331,8 @@ UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
|
|||||||
New<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1));
|
New<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1));
|
||||||
case SSL_CURVE_X25519:
|
case SSL_CURVE_X25519:
|
||||||
return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
|
return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
|
||||||
|
case SSL_CURVE_CECPQ2:
|
||||||
|
return UniquePtr<SSLKeyShare>(New<CECPQ2KeyShare>());
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -394,6 +394,11 @@ static const CurveTest kCurveTests[] = {
|
|||||||
"P-256",
|
"P-256",
|
||||||
{ SSL_CURVE_SECP256R1 },
|
{ SSL_CURVE_SECP256R1 },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"P-256:CECPQ2",
|
||||||
|
{ SSL_CURVE_SECP256R1, SSL_CURVE_CECPQ2 },
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"P-256:P-384:P-521:X25519",
|
"P-256:P-384:P-521:X25519",
|
||||||
{
|
{
|
||||||
|
@ -292,10 +292,23 @@ static const uint16_t kDefaultGroups[] = {
|
|||||||
SSL_CURVE_SECP384R1,
|
SSL_CURVE_SECP384R1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TLS 1.3 servers will pick CECPQ2 if offered by a client, but it's not enabled
|
||||||
|
// by default for clients.
|
||||||
|
static const uint16_t kDefaultGroupsServer[] = {
|
||||||
|
// CECPQ2 is not yet enabled by default.
|
||||||
|
// SSL_CURVE_CECPQ2,
|
||||||
|
SSL_CURVE_X25519,
|
||||||
|
SSL_CURVE_SECP256R1,
|
||||||
|
SSL_CURVE_SECP384R1,
|
||||||
|
};;
|
||||||
|
|
||||||
Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
|
Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) {
|
||||||
if (!hs->config->supported_group_list.empty()) {
|
if (!hs->config->supported_group_list.empty()) {
|
||||||
return hs->config->supported_group_list;
|
return hs->config->supported_group_list;
|
||||||
}
|
}
|
||||||
|
if (hs->ssl->server) {
|
||||||
|
return Span<const uint16_t>(kDefaultGroupsServer);
|
||||||
|
}
|
||||||
return Span<const uint16_t>(kDefaultGroups);
|
return Span<const uint16_t>(kDefaultGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,7 +337,11 @@ bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
|
|||||||
|
|
||||||
for (uint16_t pref_group : pref) {
|
for (uint16_t pref_group : pref) {
|
||||||
for (uint16_t supp_group : supp) {
|
for (uint16_t supp_group : supp) {
|
||||||
if (pref_group == supp_group) {
|
if (pref_group == supp_group &&
|
||||||
|
// CECPQ2 doesn't fit in the u8-length-prefixed ECPoint field in TLS
|
||||||
|
// 1.2 and below.
|
||||||
|
(ssl_protocol_version(ssl) >= TLS1_3_VERSION ||
|
||||||
|
pref_group != SSL_CURVE_CECPQ2)) {
|
||||||
*out_group_id = pref_group;
|
*out_group_id = pref_group;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -386,6 +403,12 @@ bool tls1_set_curves_list(Array<uint16_t> *out_group_ids, const char *curves) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
|
bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) {
|
||||||
|
if (group_id == SSL_CURVE_CECPQ2 &&
|
||||||
|
ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
|
||||||
|
// CECPQ2 requires TLS 1.3.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint16_t supported : tls1_get_grouplist(hs)) {
|
for (uint16_t supported : tls1_get_grouplist(hs)) {
|
||||||
if (supported == group_id) {
|
if (supported == group_id) {
|
||||||
return true;
|
return true;
|
||||||
@ -2144,6 +2167,7 @@ static bool ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t group_id = hs->retry_group;
|
uint16_t group_id = hs->retry_group;
|
||||||
|
uint16_t second_group_id = 0;
|
||||||
if (hs->received_hello_retry_request) {
|
if (hs->received_hello_retry_request) {
|
||||||
// We received a HelloRetryRequest without a new curve, so there is no new
|
// We received a HelloRetryRequest without a new curve, so there is no new
|
||||||
// share to append. Leave |hs->key_share| as-is.
|
// share to append. Leave |hs->key_share| as-is.
|
||||||
@ -2174,19 +2198,38 @@ static bool ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group_id = groups[0];
|
group_id = groups[0];
|
||||||
|
|
||||||
|
if (group_id == SSL_CURVE_CECPQ2 && groups.size() >= 2) {
|
||||||
|
// CECPQ2 is not sent as the only initial key share. We'll include the
|
||||||
|
// 2nd preference group too to avoid round-trips.
|
||||||
|
second_group_id = groups[1];
|
||||||
|
assert(second_group_id != group_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hs->key_share = SSLKeyShare::Create(group_id);
|
|
||||||
CBB key_exchange;
|
CBB key_exchange;
|
||||||
if (!hs->key_share ||
|
hs->key_shares[0] = SSLKeyShare::Create(group_id);
|
||||||
|
if (!hs->key_shares[0] ||
|
||||||
!CBB_add_u16(&kse_bytes, group_id) ||
|
!CBB_add_u16(&kse_bytes, group_id) ||
|
||||||
!CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
|
!CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
|
||||||
!hs->key_share->Offer(&key_exchange) ||
|
!hs->key_shares[0]->Offer(&key_exchange) ||
|
||||||
!CBB_flush(&kse_bytes)) {
|
!CBB_flush(&kse_bytes)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the contents of the extension to repeat it in the second ClientHello.
|
if (second_group_id != 0) {
|
||||||
|
hs->key_shares[1] = SSLKeyShare::Create(second_group_id);
|
||||||
|
if (!hs->key_shares[1] ||
|
||||||
|
!CBB_add_u16(&kse_bytes, second_group_id) ||
|
||||||
|
!CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
|
||||||
|
!hs->key_shares[1]->Offer(&key_exchange) ||
|
||||||
|
!CBB_flush(&kse_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the contents of the extension to repeat it in the second
|
||||||
|
// ClientHello.
|
||||||
if (!hs->received_hello_retry_request &&
|
if (!hs->received_hello_retry_request &&
|
||||||
!hs->key_share_bytes.CopyFrom(
|
!hs->key_share_bytes.CopyFrom(
|
||||||
MakeConstSpan(CBB_data(&kse_bytes), CBB_len(&kse_bytes)))) {
|
MakeConstSpan(CBB_data(&kse_bytes), CBB_len(&kse_bytes)))) {
|
||||||
@ -2209,19 +2252,24 @@ bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hs->key_share->GroupID() != group_id) {
|
SSLKeyShare *key_share = hs->key_shares[0].get();
|
||||||
|
if (key_share->GroupID() != group_id) {
|
||||||
|
if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) {
|
||||||
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
|
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
key_share = hs->key_shares[1].get();
|
||||||
|
}
|
||||||
|
|
||||||
if (!hs->key_share->Finish(out_secret, out_alert, peer_key)) {
|
if (!key_share->Finish(out_secret, out_alert, peer_key)) {
|
||||||
*out_alert = SSL_AD_INTERNAL_ERROR;
|
*out_alert = SSL_AD_INTERNAL_ERROR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hs->new_session->group_id = group_id;
|
hs->new_session->group_id = group_id;
|
||||||
hs->key_share.reset();
|
hs->key_shares[0].reset();
|
||||||
|
hs->key_shares[1].reset();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2389,6 +2437,10 @@ static bool ext_supported_groups_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t group : tls1_get_grouplist(hs)) {
|
for (uint16_t group : tls1_get_grouplist(hs)) {
|
||||||
|
if (group == SSL_CURVE_CECPQ2 &&
|
||||||
|
hs->max_version < TLS1_3_VERSION) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!CBB_add_u16(&groups_bytes, group)) {
|
if (!CBB_add_u16(&groups_bytes, group)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -649,7 +649,6 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
|
|||||||
SSL_set_connect_state(ssl.get());
|
SSL_set_connect_state(ssl.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sock = Connect(config->port);
|
int sock = Connect(config->port);
|
||||||
if (sock == -1) {
|
if (sock == -1) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -26,7 +26,7 @@ type keyAgreement interface {
|
|||||||
// In the case that the key agreement protocol doesn't use a
|
// In the case that the key agreement protocol doesn't use a
|
||||||
// ServerKeyExchange message, generateServerKeyExchange can return nil,
|
// ServerKeyExchange message, generateServerKeyExchange can return nil,
|
||||||
// nil.
|
// nil.
|
||||||
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
|
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg, uint16) (*serverKeyExchangeMsg, error)
|
||||||
processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
|
processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
|
||||||
|
|
||||||
// On the client side, the next two methods are called in order.
|
// On the client side, the next two methods are called in order.
|
||||||
|
@ -163,6 +163,7 @@ const (
|
|||||||
CurveP384 CurveID = 24
|
CurveP384 CurveID = 24
|
||||||
CurveP521 CurveID = 25
|
CurveP521 CurveID = 25
|
||||||
CurveX25519 CurveID = 29
|
CurveX25519 CurveID = 29
|
||||||
|
CurveCECPQ2 CurveID = 16696
|
||||||
)
|
)
|
||||||
|
|
||||||
// TLS Elliptic Curve Point Formats
|
// TLS Elliptic Curve Point Formats
|
||||||
@ -1645,6 +1646,18 @@ type ProtocolBugs struct {
|
|||||||
// ExpectJDK11DowngradeRandom is whether the client should expect the
|
// ExpectJDK11DowngradeRandom is whether the client should expect the
|
||||||
// server to send the JDK 11 downgrade signal.
|
// server to send the JDK 11 downgrade signal.
|
||||||
ExpectJDK11DowngradeRandom bool
|
ExpectJDK11DowngradeRandom bool
|
||||||
|
|
||||||
|
// FailIfHelloRetryRequested causes a handshake failure if a server requests a
|
||||||
|
// hello retry.
|
||||||
|
FailIfHelloRetryRequested bool
|
||||||
|
|
||||||
|
// FailedIfCECPQ2Offered will cause a server to reject a ClientHello if CECPQ2
|
||||||
|
// is supported.
|
||||||
|
FailIfCECPQ2Offered bool
|
||||||
|
|
||||||
|
// ExpectKeyShares, if not nil, lists (in order) the curves that a ClientHello
|
||||||
|
// should have key shares for.
|
||||||
|
ExpectedKeyShares []CurveID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) serverInit() {
|
func (c *Config) serverInit() {
|
||||||
@ -1724,7 +1737,7 @@ func (c *Config) maxVersion(isDTLS bool) uint16 {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultCurvePreferences = []CurveID{CurveX25519, CurveP256, CurveP384, CurveP521}
|
var defaultCurvePreferences = []CurveID{CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
|
||||||
|
|
||||||
func (c *Config) curvePreferences() []CurveID {
|
func (c *Config) curvePreferences() []CurveID {
|
||||||
if c == nil || len(c.CurvePreferences) == 0 {
|
if c == nil || len(c.CurvePreferences) == 0 {
|
||||||
|
@ -549,6 +549,9 @@ NextCipherSuite:
|
|||||||
helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
|
helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
|
||||||
var secondHelloBytes []byte
|
var secondHelloBytes []byte
|
||||||
if haveHelloRetryRequest {
|
if haveHelloRetryRequest {
|
||||||
|
if c.config.Bugs.FailIfHelloRetryRequested {
|
||||||
|
return errors.New("tls: unexpected HelloRetryRequest")
|
||||||
|
}
|
||||||
// Explicitly read the ChangeCipherSpec now; it should
|
// Explicitly read the ChangeCipherSpec now; it should
|
||||||
// be attached to the first flight, not the second flight.
|
// be attached to the first flight, not the second flight.
|
||||||
if err := c.readTLS13ChangeCipherSpec(); err != nil {
|
if err := c.readTLS13ChangeCipherSpec(); err != nil {
|
||||||
|
@ -208,6 +208,26 @@ func (hs *serverHandshakeState) readClientHello() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Bugs.FailIfCECPQ2Offered {
|
||||||
|
for _, offeredCurve := range hs.clientHello.supportedCurves {
|
||||||
|
if offeredCurve == CurveCECPQ2 {
|
||||||
|
return errors.New("tls: CECPQ2 was offered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected := config.Bugs.ExpectedKeyShares; expected != nil {
|
||||||
|
if len(expected) != len(hs.clientHello.keyShares) {
|
||||||
|
return fmt.Errorf("tls: expected %d key shares, but found %d", len(expected), len(hs.clientHello.keyShares))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, group := range expected {
|
||||||
|
if found := hs.clientHello.keyShares[i].group; found != group {
|
||||||
|
return fmt.Errorf("tls: key share #%d is for group %d, not %d", i, found, group)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.clientVersion = hs.clientHello.vers
|
c.clientVersion = hs.clientHello.vers
|
||||||
|
|
||||||
// Use the versions extension if supplied, otherwise use the legacy ClientHello version.
|
// Use the versions extension if supplied, otherwise use the legacy ClientHello version.
|
||||||
@ -1212,6 +1232,11 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error)
|
|||||||
preferredCurves := config.curvePreferences()
|
preferredCurves := config.curvePreferences()
|
||||||
Curves:
|
Curves:
|
||||||
for _, curve := range hs.clientHello.supportedCurves {
|
for _, curve := range hs.clientHello.supportedCurves {
|
||||||
|
if curve == CurveCECPQ2 && c.vers < VersionTLS13 {
|
||||||
|
// CECPQ2 is TLS 1.3-only.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, supported := range preferredCurves {
|
for _, supported := range preferredCurves {
|
||||||
if supported == curve {
|
if supported == curve {
|
||||||
supportedCurve = true
|
supportedCurve = true
|
||||||
@ -1621,7 +1646,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keyAgreement := hs.suite.ka(c.vers)
|
keyAgreement := hs.suite.ka(c.vers)
|
||||||
skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
|
skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello, c.vers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.sendAlert(alertHandshakeFailure)
|
c.sendAlert(alertHandshakeFailure)
|
||||||
return err
|
return err
|
||||||
|
1230
ssl/test/runner/hrss/hrss.go
Normal file
1230
ssl/test/runner/hrss/hrss.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@ import (
|
|||||||
|
|
||||||
"boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519"
|
"boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519"
|
||||||
"boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519"
|
"boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519"
|
||||||
|
"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
|
||||||
)
|
)
|
||||||
|
|
||||||
type keyType int
|
type keyType int
|
||||||
@ -37,7 +38,7 @@ type rsaKeyAgreement struct {
|
|||||||
exportKey *rsa.PrivateKey
|
exportKey *rsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, version uint16) (*serverKeyExchangeMsg, error) {
|
||||||
// Save the client version for comparison later.
|
// Save the client version for comparison later.
|
||||||
ka.clientVersion = clientHello.vers
|
ka.clientVersion = clientHello.vers
|
||||||
|
|
||||||
@ -347,6 +348,90 @@ func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err er
|
|||||||
return out[:], nil
|
return out[:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cecpq2Curve implements CECPQ2, which is HRSS+SXY combined with X25519.
|
||||||
|
type cecpq2Curve struct {
|
||||||
|
x25519PrivateKey [32]byte
|
||||||
|
hrssPrivateKey hrss.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *cecpq2Curve) offer(rand io.Reader) (publicKey []byte, err error) {
|
||||||
|
if _, err := io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var x25519Public [32]byte
|
||||||
|
curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
|
||||||
|
|
||||||
|
e.hrssPrivateKey = hrss.GenerateKey(rand)
|
||||||
|
hrssPublic := e.hrssPrivateKey.PublicKey.Marshal()
|
||||||
|
|
||||||
|
var ret []byte
|
||||||
|
ret = append(ret, x25519Public[:]...)
|
||||||
|
ret = append(ret, hrssPublic...)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *cecpq2Curve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
|
||||||
|
if len(peerKey) != 32+hrss.PublicKeySize {
|
||||||
|
return nil, nil, errors.New("tls: bad length CECPQ2 offer")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var x25519Shared, x25519PeerKey, x25519Public [32]byte
|
||||||
|
copy(x25519PeerKey[:], peerKey)
|
||||||
|
curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
|
||||||
|
curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
|
||||||
|
|
||||||
|
// Per RFC 7748, reject the all-zero value in constant time.
|
||||||
|
var zeros [32]byte
|
||||||
|
if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
|
||||||
|
return nil, nil, errors.New("tls: X25519 value with wrong order")
|
||||||
|
}
|
||||||
|
|
||||||
|
hrssPublicKey, ok := hrss.ParsePublicKey(peerKey[32:])
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, errors.New("tls: bad CECPQ2 offer")
|
||||||
|
}
|
||||||
|
|
||||||
|
hrssCiphertext, hrssShared := hrssPublicKey.Encap(rand)
|
||||||
|
|
||||||
|
publicKey = append(publicKey, x25519Public[:]...)
|
||||||
|
publicKey = append(publicKey, hrssCiphertext...)
|
||||||
|
preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
|
||||||
|
preMasterSecret = append(preMasterSecret, hrssShared...)
|
||||||
|
|
||||||
|
return publicKey, preMasterSecret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *cecpq2Curve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
|
||||||
|
if len(peerKey) != 32+hrss.CiphertextSize {
|
||||||
|
return nil, errors.New("tls: bad length CECPQ2 reply")
|
||||||
|
}
|
||||||
|
|
||||||
|
var x25519Shared, x25519PeerKey [32]byte
|
||||||
|
copy(x25519PeerKey[:], peerKey)
|
||||||
|
curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
|
||||||
|
|
||||||
|
// Per RFC 7748, reject the all-zero value in constant time.
|
||||||
|
var zeros [32]byte
|
||||||
|
if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
|
||||||
|
return nil, errors.New("tls: X25519 value with wrong order")
|
||||||
|
}
|
||||||
|
|
||||||
|
hrssShared, ok := e.hrssPrivateKey.Decap(peerKey[32:])
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("tls: invalid HRSS ciphertext")
|
||||||
|
}
|
||||||
|
|
||||||
|
preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
|
||||||
|
preMasterSecret = append(preMasterSecret, hrssShared...)
|
||||||
|
|
||||||
|
return preMasterSecret, nil
|
||||||
|
}
|
||||||
|
|
||||||
func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
|
func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
|
||||||
switch id {
|
switch id {
|
||||||
case CurveP224:
|
case CurveP224:
|
||||||
@ -359,6 +444,8 @@ func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
|
|||||||
return &ellipticECDHCurve{curve: elliptic.P521(), sendCompressed: config.Bugs.SendCompressedCoordinates}, true
|
return &ellipticECDHCurve{curve: elliptic.P521(), sendCompressed: config.Bugs.SendCompressedCoordinates}, true
|
||||||
case CurveX25519:
|
case CurveX25519:
|
||||||
return &x25519ECDHCurve{setHighBit: config.Bugs.SetX25519HighBit}, true
|
return &x25519ECDHCurve{setHighBit: config.Bugs.SetX25519HighBit}, true
|
||||||
|
case CurveCECPQ2:
|
||||||
|
return &cecpq2Curve{}, true
|
||||||
default:
|
default:
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
@ -501,12 +588,17 @@ type ecdheKeyAgreement struct {
|
|||||||
peerKey []byte
|
peerKey []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, version uint16) (*serverKeyExchangeMsg, error) {
|
||||||
var curveid CurveID
|
var curveid CurveID
|
||||||
preferredCurves := config.curvePreferences()
|
preferredCurves := config.curvePreferences()
|
||||||
|
|
||||||
NextCandidate:
|
NextCandidate:
|
||||||
for _, candidate := range preferredCurves {
|
for _, candidate := range preferredCurves {
|
||||||
|
if candidate == CurveCECPQ2 && version < VersionTLS13 {
|
||||||
|
// CECPQ2 is TLS 1.3-only.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, c := range clientHello.supportedCurves {
|
for _, c := range clientHello.supportedCurves {
|
||||||
if candidate == c {
|
if candidate == c {
|
||||||
curveid = c
|
curveid = c
|
||||||
@ -614,7 +706,7 @@ func (ka *ecdheKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
|||||||
// exchange.
|
// exchange.
|
||||||
type nilKeyAgreement struct{}
|
type nilKeyAgreement struct{}
|
||||||
|
|
||||||
func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, version uint16) (*serverKeyExchangeMsg, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +758,7 @@ type pskKeyAgreement struct {
|
|||||||
identityHint string
|
identityHint string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, version uint16) (*serverKeyExchangeMsg, error) {
|
||||||
// Assemble the identity hint.
|
// Assemble the identity hint.
|
||||||
bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
|
bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
|
||||||
bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
|
bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
|
||||||
@ -675,7 +767,7 @@ func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certi
|
|||||||
|
|
||||||
// If there is one, append the base key agreement's
|
// If there is one, append the base key agreement's
|
||||||
// ServerKeyExchange.
|
// ServerKeyExchange.
|
||||||
baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello)
|
baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -9619,7 +9619,7 @@ func addSignatureAlgorithmTests() {
|
|||||||
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||||
Certificates: []Certificate{ecdsaP256Certificate},
|
Certificates: []Certificate{ecdsaP256Certificate},
|
||||||
},
|
},
|
||||||
flags: []string{"-p384-only"},
|
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
expectedError: ":BAD_ECC_CERT:",
|
expectedError: ":BAD_ECC_CERT:",
|
||||||
})
|
})
|
||||||
@ -9631,7 +9631,7 @@ func addSignatureAlgorithmTests() {
|
|||||||
MaxVersion: VersionTLS13,
|
MaxVersion: VersionTLS13,
|
||||||
Certificates: []Certificate{ecdsaP256Certificate},
|
Certificates: []Certificate{ecdsaP256Certificate},
|
||||||
},
|
},
|
||||||
flags: []string{"-p384-only"},
|
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||||
})
|
})
|
||||||
|
|
||||||
// In TLS 1.2, the ECDSA curve is not in the signature algorithm.
|
// In TLS 1.2, the ECDSA curve is not in the signature algorithm.
|
||||||
@ -10711,6 +10711,7 @@ var testCurves = []struct {
|
|||||||
{"P-384", CurveP384},
|
{"P-384", CurveP384},
|
||||||
{"P-521", CurveP521},
|
{"P-521", CurveP521},
|
||||||
{"X25519", CurveX25519},
|
{"X25519", CurveX25519},
|
||||||
|
{"CECPQ2", CurveCECPQ2},
|
||||||
}
|
}
|
||||||
|
|
||||||
const bogusCurve = 0x1234
|
const bogusCurve = 0x1234
|
||||||
@ -10718,6 +10719,10 @@ const bogusCurve = 0x1234
|
|||||||
func addCurveTests() {
|
func addCurveTests() {
|
||||||
for _, curve := range testCurves {
|
for _, curve := range testCurves {
|
||||||
for _, ver := range tlsVersions {
|
for _, ver := range tlsVersions {
|
||||||
|
if curve.id == CurveCECPQ2 && ver.version < VersionTLS13 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
suffix := curve.name + "-" + ver.name
|
suffix := curve.name + "-" + ver.name
|
||||||
|
|
||||||
testCases = append(testCases, testCase{
|
testCases = append(testCases, testCase{
|
||||||
@ -10758,7 +10763,7 @@ func addCurveTests() {
|
|||||||
expectedCurveID: curve.id,
|
expectedCurveID: curve.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
if curve.id != CurveX25519 {
|
if curve.id != CurveX25519 && curve.id != CurveCECPQ2 {
|
||||||
testCases = append(testCases, testCase{
|
testCases = append(testCases, testCase{
|
||||||
name: "CurveTest-Client-Compressed-" + suffix,
|
name: "CurveTest-Client-Compressed-" + suffix,
|
||||||
config: Config{
|
config: Config{
|
||||||
@ -10902,7 +10907,7 @@ func addCurveTests() {
|
|||||||
IgnorePeerCurvePreferences: true,
|
IgnorePeerCurvePreferences: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
flags: []string{"-p384-only"},
|
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
expectedError: ":WRONG_CURVE:",
|
expectedError: ":WRONG_CURVE:",
|
||||||
})
|
})
|
||||||
@ -10918,7 +10923,7 @@ func addCurveTests() {
|
|||||||
SendCurve: CurveP256,
|
SendCurve: CurveP256,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
flags: []string{"-p384-only"},
|
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
expectedError: ":WRONG_CURVE:",
|
expectedError: ":WRONG_CURVE:",
|
||||||
})
|
})
|
||||||
@ -11169,6 +11174,112 @@ func addCurveTests() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// CECPQ2 should not be offered by a TLS < 1.3 client.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
name: "CECPQ2NotInTLS12",
|
||||||
|
config: Config{
|
||||||
|
Bugs: ProtocolBugs{
|
||||||
|
FailIfCECPQ2Offered: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: []string{
|
||||||
|
"-max-version", strconv.Itoa(VersionTLS12),
|
||||||
|
"-curves", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
"-curves", strconv.Itoa(int(CurveX25519)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// CECPQ2 should not crash a TLS < 1.3 client if the server mistakenly
|
||||||
|
// selects it.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
name: "CECPQ2NotAcceptedByTLS12Client",
|
||||||
|
config: Config{
|
||||||
|
Bugs: ProtocolBugs{
|
||||||
|
SendCurve: CurveCECPQ2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: []string{
|
||||||
|
"-max-version", strconv.Itoa(VersionTLS12),
|
||||||
|
"-curves", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
"-curves", strconv.Itoa(int(CurveX25519)),
|
||||||
|
},
|
||||||
|
shouldFail: true,
|
||||||
|
expectedError: ":WRONG_CURVE:",
|
||||||
|
})
|
||||||
|
|
||||||
|
// CECPQ2 should not be offered by default as a client.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
name: "CECPQ2NotEnabledByDefaultInClients",
|
||||||
|
config: Config{
|
||||||
|
MinVersion: VersionTLS13,
|
||||||
|
Bugs: ProtocolBugs{
|
||||||
|
FailIfCECPQ2Offered: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// If CECPQ2 is offered, both X25519 and CECPQ2 should have a key-share.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
name: "NotJustCECPQ2KeyShare",
|
||||||
|
config: Config{
|
||||||
|
MinVersion: VersionTLS13,
|
||||||
|
Bugs: ProtocolBugs{
|
||||||
|
ExpectedKeyShares: []CurveID{CurveCECPQ2, CurveX25519},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: []string{
|
||||||
|
"-curves", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
"-curves", strconv.Itoa(int(CurveX25519)),
|
||||||
|
"-expect-curve-id", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// ... but only if CECPQ2 is listed first.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
name: "CECPQ2KeyShareNotIncludedSecond",
|
||||||
|
config: Config{
|
||||||
|
MinVersion: VersionTLS13,
|
||||||
|
Bugs: ProtocolBugs{
|
||||||
|
ExpectedKeyShares: []CurveID{CurveX25519},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: []string{
|
||||||
|
"-curves", strconv.Itoa(int(CurveX25519)),
|
||||||
|
"-curves", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// If CECPQ2 is the only configured curve, the key share is sent.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
name: "JustConfiguringCECPQ2Works",
|
||||||
|
config: Config{
|
||||||
|
MinVersion: VersionTLS13,
|
||||||
|
Bugs: ProtocolBugs{
|
||||||
|
ExpectedKeyShares: []CurveID{CurveCECPQ2},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: []string{
|
||||||
|
"-curves", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
"-expect-curve-id", strconv.Itoa(int(CurveCECPQ2)),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// As a server, CECPQ2 is not yet supported by default.
|
||||||
|
testCases = append(testCases, testCase{
|
||||||
|
testType: serverTest,
|
||||||
|
name: "CECPQ2NotEnabledByDefaultForAServer",
|
||||||
|
config: Config{
|
||||||
|
MinVersion: VersionTLS13,
|
||||||
|
CurvePreferences: []CurveID{CurveCECPQ2, CurveX25519},
|
||||||
|
DefaultCurves: []CurveID{CurveCECPQ2},
|
||||||
|
},
|
||||||
|
flags: []string{
|
||||||
|
"-server-preference",
|
||||||
|
"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func addTLS13RecordTests() {
|
func addTLS13RecordTests() {
|
||||||
@ -12706,7 +12817,7 @@ func addTLS13HandshakeTests() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
tls13Variant: variant,
|
tls13Variant: variant,
|
||||||
flags: []string{"-p384-only"},
|
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||||
shouldFail: true,
|
shouldFail: true,
|
||||||
expectedError: ":WRONG_CURVE:",
|
expectedError: ":WRONG_CURVE:",
|
||||||
})
|
})
|
||||||
|
@ -104,7 +104,6 @@ const Flag<bool> kBoolFlags[] = {
|
|||||||
{ "-renegotiate-ignore", &TestConfig::renegotiate_ignore },
|
{ "-renegotiate-ignore", &TestConfig::renegotiate_ignore },
|
||||||
{ "-forbid-renegotiation-after-handshake",
|
{ "-forbid-renegotiation-after-handshake",
|
||||||
&TestConfig::forbid_renegotiation_after_handshake },
|
&TestConfig::forbid_renegotiation_after_handshake },
|
||||||
{ "-p384-only", &TestConfig::p384_only },
|
|
||||||
{ "-enable-all-curves", &TestConfig::enable_all_curves },
|
{ "-enable-all-curves", &TestConfig::enable_all_curves },
|
||||||
{ "-use-old-client-cert-callback",
|
{ "-use-old-client-cert-callback",
|
||||||
&TestConfig::use_old_client_cert_callback },
|
&TestConfig::use_old_client_cert_callback },
|
||||||
@ -147,6 +146,7 @@ const Flag<bool> kBoolFlags[] = {
|
|||||||
{ "-handshaker-resume", &TestConfig::handshaker_resume },
|
{ "-handshaker-resume", &TestConfig::handshaker_resume },
|
||||||
{ "-reverify-on-resume", &TestConfig::reverify_on_resume },
|
{ "-reverify-on-resume", &TestConfig::reverify_on_resume },
|
||||||
{ "-jdk11-workaround", &TestConfig::jdk11_workaround },
|
{ "-jdk11-workaround", &TestConfig::jdk11_workaround },
|
||||||
|
{ "-server-preference", &TestConfig::server_preference },
|
||||||
};
|
};
|
||||||
|
|
||||||
const Flag<std::string> kStringFlags[] = {
|
const Flag<std::string> kStringFlags[] = {
|
||||||
@ -220,10 +220,10 @@ const Flag<int> kIntFlags[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Flag<std::vector<int>> kIntVectorFlags[] = {
|
const Flag<std::vector<int>> kIntVectorFlags[] = {
|
||||||
{ "-signing-prefs", &TestConfig::signing_prefs },
|
{"-signing-prefs", &TestConfig::signing_prefs},
|
||||||
{ "-verify-prefs", &TestConfig::verify_prefs },
|
{"-verify-prefs", &TestConfig::verify_prefs},
|
||||||
{ "-expect-peer-verify-pref",
|
{"-expect-peer-verify-pref", &TestConfig::expected_peer_verify_prefs},
|
||||||
&TestConfig::expected_peer_verify_prefs },
|
{"-curves", &TestConfig::curves},
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ParseFlag(char *flag, int argc, char **argv, int *i,
|
bool ParseFlag(char *flag, int argc, char **argv, int *i,
|
||||||
@ -1294,7 +1294,6 @@ bssl::UniquePtr<SSL_CTX> TestConfig::SetupCtx(SSL_CTX *old_ctx) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (install_cert_compression_algs &&
|
if (install_cert_compression_algs &&
|
||||||
(!SSL_CTX_add_cert_compression_alg(
|
(!SSL_CTX_add_cert_compression_alg(
|
||||||
ssl_ctx.get(), 0xff02,
|
ssl_ctx.get(), 0xff02,
|
||||||
@ -1341,6 +1340,10 @@ bssl::UniquePtr<SSL_CTX> TestConfig::SetupCtx(SSL_CTX *old_ctx) const {
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (server_preference) {
|
||||||
|
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||||
|
}
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1589,16 +1592,43 @@ bssl::UniquePtr<SSL> TestConfig::NewSSL(
|
|||||||
if (!check_close_notify) {
|
if (!check_close_notify) {
|
||||||
SSL_set_quiet_shutdown(ssl.get(), 1);
|
SSL_set_quiet_shutdown(ssl.get(), 1);
|
||||||
}
|
}
|
||||||
if (p384_only) {
|
if (!curves.empty()) {
|
||||||
int nid = NID_secp384r1;
|
std::vector<int> nids;
|
||||||
if (!SSL_set1_curves(ssl.get(), &nid, 1)) {
|
for (auto curve : curves) {
|
||||||
|
switch (curve) {
|
||||||
|
case SSL_CURVE_SECP224R1:
|
||||||
|
nids.push_back(NID_secp224r1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CURVE_SECP256R1:
|
||||||
|
nids.push_back(NID_X9_62_prime256v1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CURVE_SECP384R1:
|
||||||
|
nids.push_back(NID_secp384r1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CURVE_SECP521R1:
|
||||||
|
nids.push_back(NID_secp521r1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CURVE_X25519:
|
||||||
|
nids.push_back(NID_X25519);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSL_CURVE_CECPQ2:
|
||||||
|
nids.push_back(NID_CECPQ2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!SSL_set1_curves(ssl.get(), &nids[0], nids.size())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (enable_all_curves) {
|
if (enable_all_curves) {
|
||||||
static const int kAllCurves[] = {
|
static const int kAllCurves[] = {
|
||||||
NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1,
|
NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1,
|
||||||
NID_secp521r1, NID_X25519,
|
NID_secp521r1, NID_X25519, NID_CECPQ2,
|
||||||
};
|
};
|
||||||
if (!SSL_set1_curves(ssl.get(), kAllCurves,
|
if (!SSL_set1_curves(ssl.get(), kAllCurves,
|
||||||
OPENSSL_ARRAY_SIZE(kAllCurves))) {
|
OPENSSL_ARRAY_SIZE(kAllCurves))) {
|
||||||
|
@ -33,6 +33,7 @@ struct TestConfig {
|
|||||||
std::vector<int> signing_prefs;
|
std::vector<int> signing_prefs;
|
||||||
std::vector<int> verify_prefs;
|
std::vector<int> verify_prefs;
|
||||||
std::vector<int> expected_peer_verify_prefs;
|
std::vector<int> expected_peer_verify_prefs;
|
||||||
|
std::vector<int> curves;
|
||||||
std::string key_file;
|
std::string key_file;
|
||||||
std::string cert_file;
|
std::string cert_file;
|
||||||
std::string expected_server_name;
|
std::string expected_server_name;
|
||||||
@ -122,7 +123,6 @@ struct TestConfig {
|
|||||||
bool renegotiate_ignore = false;
|
bool renegotiate_ignore = false;
|
||||||
bool forbid_renegotiation_after_handshake = false;
|
bool forbid_renegotiation_after_handshake = false;
|
||||||
int expect_peer_signature_algorithm = 0;
|
int expect_peer_signature_algorithm = 0;
|
||||||
bool p384_only = false;
|
|
||||||
bool enable_all_curves = false;
|
bool enable_all_curves = false;
|
||||||
int expect_curve_id = 0;
|
int expect_curve_id = 0;
|
||||||
bool use_old_client_cert_callback = false;
|
bool use_old_client_cert_callback = false;
|
||||||
@ -170,6 +170,7 @@ struct TestConfig {
|
|||||||
bool handshaker_resume = false;
|
bool handshaker_resume = false;
|
||||||
std::string handshaker_path;
|
std::string handshaker_path;
|
||||||
bool jdk11_workaround = false;
|
bool jdk11_workaround = false;
|
||||||
|
bool server_preference = false;
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
|
@ -165,15 +165,17 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
|
|||||||
return ssl_hs_error;
|
return ssl_hs_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the HelloRetryRequest does not request the key share that
|
// Check that the HelloRetryRequest does not request a key share that was
|
||||||
// was provided in the initial ClientHello.
|
// provided in the initial ClientHello.
|
||||||
if (hs->key_share->GroupID() == group_id) {
|
if (hs->key_shares[0]->GroupID() == group_id ||
|
||||||
|
(hs->key_shares[1] && hs->key_shares[1]->GroupID() == group_id)) {
|
||||||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
|
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
|
||||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
||||||
return ssl_hs_error;
|
return ssl_hs_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hs->key_share.reset();
|
hs->key_shares[0].reset();
|
||||||
|
hs->key_shares[1].reset();
|
||||||
hs->retry_group = group_id;
|
hs->retry_group = group_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <openssl/ecdsa.h>
|
#include <openssl/ecdsa.h>
|
||||||
#include <openssl/ec_key.h>
|
#include <openssl/ec_key.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/hrss.h>
|
||||||
#include <openssl/nid.h>
|
#include <openssl/nid.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
@ -744,6 +745,61 @@ static bool SpeedScrypt(const std::string &selected) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool SpeedHRSS(const std::string &selected) {
|
||||||
|
if (!selected.empty() && selected != "HRSS") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeResults results;
|
||||||
|
|
||||||
|
if (!TimeFunction(&results, []() -> bool {
|
||||||
|
struct HRSS_public_key pub;
|
||||||
|
struct HRSS_private_key priv;
|
||||||
|
uint8_t entropy[HRSS_GENERATE_KEY_BYTES];
|
||||||
|
RAND_bytes(entropy, sizeof(entropy));
|
||||||
|
HRSS_generate_key(&pub, &priv, entropy);
|
||||||
|
return true;
|
||||||
|
})) {
|
||||||
|
fprintf(stderr, "Failed to time HRSS_generate_key.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Print("HRSS generate");
|
||||||
|
|
||||||
|
struct HRSS_public_key pub;
|
||||||
|
struct HRSS_private_key priv;
|
||||||
|
uint8_t key_entropy[HRSS_GENERATE_KEY_BYTES];
|
||||||
|
RAND_bytes(key_entropy, sizeof(key_entropy));
|
||||||
|
HRSS_generate_key(&pub, &priv, key_entropy);
|
||||||
|
|
||||||
|
uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
|
||||||
|
if (!TimeFunction(&results, [&pub, &ciphertext]() -> bool {
|
||||||
|
uint8_t entropy[HRSS_ENCAP_BYTES];
|
||||||
|
uint8_t shared_key[HRSS_KEY_BYTES];
|
||||||
|
RAND_bytes(entropy, sizeof(entropy));
|
||||||
|
HRSS_encap(ciphertext, shared_key, &pub, entropy);
|
||||||
|
return true;
|
||||||
|
})) {
|
||||||
|
fprintf(stderr, "Failed to time HRSS_encap.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Print("HRSS encap");
|
||||||
|
|
||||||
|
if (!TimeFunction(&results, [&pub, &priv, &ciphertext]() -> bool {
|
||||||
|
uint8_t shared_key[HRSS_KEY_BYTES];
|
||||||
|
HRSS_decap(shared_key, &pub, &priv, ciphertext, sizeof(ciphertext));
|
||||||
|
return true;
|
||||||
|
})) {
|
||||||
|
fprintf(stderr, "Failed to time HRSS_encap.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Print("HRSS decap");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct argument kArguments[] = {
|
static const struct argument kArguments[] = {
|
||||||
{
|
{
|
||||||
"-filter", kOptionalArgument,
|
"-filter", kOptionalArgument,
|
||||||
@ -817,7 +873,8 @@ bool Speed(const std::vector<std::string> &args) {
|
|||||||
!Speed25519(selected) ||
|
!Speed25519(selected) ||
|
||||||
!SpeedSPAKE2(selected) ||
|
!SpeedSPAKE2(selected) ||
|
||||||
!SpeedScrypt(selected) ||
|
!SpeedScrypt(selected) ||
|
||||||
!SpeedRSAKeyGen(selected)) {
|
!SpeedRSAKeyGen(selected) ||
|
||||||
|
!SpeedHRSS(selected)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ NON_PERL_FILES = {
|
|||||||
('linux', 'arm'): [
|
('linux', 'arm'): [
|
||||||
'src/crypto/curve25519/asm/x25519-asm-arm.S',
|
'src/crypto/curve25519/asm/x25519-asm-arm.S',
|
||||||
'src/crypto/poly1305/poly1305_arm_asm.S',
|
'src/crypto/poly1305/poly1305_arm_asm.S',
|
||||||
|
'src/crypto/hrss/asm/poly_mul_vec_armv7_neon.S',
|
||||||
|
],
|
||||||
|
('linux', 'x86_64'): [
|
||||||
|
'src/crypto/hrss/asm/poly_rq_mul.S',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user