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}
|
||||
curve25519/asm/x25519-asm-arm.S
|
||||
poly1305/poly1305_arm_asm.S
|
||||
hrss/asm/poly_mul_vec_armv7_neon.S
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -131,6 +132,7 @@ if(${ARCH} STREQUAL "x86_64")
|
||||
chacha/chacha-x86_64.${ASM_EXT}
|
||||
cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT}
|
||||
cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT}
|
||||
hrss/asm/poly_rq_mul.S
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -275,6 +277,7 @@ add_library(
|
||||
evp/sign.c
|
||||
ex_data.c
|
||||
hkdf/hkdf.c
|
||||
hrss/hrss.c
|
||||
lhash/lhash.c
|
||||
mem.c
|
||||
obj/obj.c
|
||||
@ -455,6 +458,7 @@ add_executable(
|
||||
fipsmodule/rand/ctrdrbg_test.cc
|
||||
hkdf/hkdf_test.cc
|
||||
hmac_extra/hmac_test.cc
|
||||
hrss/hrss_test.cc
|
||||
lhash/lhash_test.cc
|
||||
obj/obj_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. */
|
||||
|
||||
|
||||
#define NUM_NID 959
|
||||
#define NUM_NID 960
|
||||
|
||||
static const uint8_t kObjectData[] = {
|
||||
/* NID_rsadsi */
|
||||
@ -8755,6 +8755,7 @@ static const ASN1_OBJECT kObjects[NUM_NID] = {
|
||||
{"AuthPSK", "auth-psk", NID_auth_psk, 0, NULL, 0},
|
||||
{"KxANY", "kx-any", NID_kx_any, 0, NULL, 0},
|
||||
{"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0},
|
||||
{"CECPQ2", "CECPQ2", NID_CECPQ2, 0, NULL, 0},
|
||||
};
|
||||
|
||||
static const unsigned kNIDsInShortNameOrder[] = {
|
||||
@ -8816,6 +8817,7 @@ static const unsigned kNIDsInShortNameOrder[] = {
|
||||
110 /* CAST5-CFB */,
|
||||
109 /* CAST5-ECB */,
|
||||
111 /* CAST5-OFB */,
|
||||
959 /* CECPQ2 */,
|
||||
894 /* CMAC */,
|
||||
13 /* CN */,
|
||||
141 /* CRLReason */,
|
||||
@ -9720,6 +9722,7 @@ static const unsigned kNIDsInLongNameOrder[] = {
|
||||
285 /* Biometric Info */,
|
||||
179 /* CA Issuers */,
|
||||
785 /* CA Repository */,
|
||||
959 /* CECPQ2 */,
|
||||
131 /* Code Signing */,
|
||||
783 /* Diffie-Hellman based MAC */,
|
||||
382 /* Directory */,
|
||||
|
@ -947,3 +947,4 @@ auth_ecdsa 955
|
||||
auth_psk 956
|
||||
kx_any 957
|
||||
auth_any 958
|
||||
CECPQ2 959
|
||||
|
@ -559,7 +559,7 @@ id-cmc 19 : id-cmc-responseInfo
|
||||
id-cmc 21 : id-cmc-queryPending
|
||||
id-cmc 22 : id-cmc-popLinkRandom
|
||||
id-cmc 23 : id-cmc-popLinkWitness
|
||||
id-cmc 24 : id-cmc-confirmCertAcceptance
|
||||
id-cmc 24 : id-cmc-confirmCertAcceptance
|
||||
|
||||
# other names
|
||||
id-on 1 : id-on-personalData
|
||||
@ -1239,7 +1239,7 @@ cryptocom 1 8 1 : id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Se
|
||||
# Definitions for Camellia cipher - ECB, CFB, OFB MODE
|
||||
|
||||
!Alias ntt-ds 0 3 4401 5
|
||||
!Alias camellia ntt-ds 3 1 9
|
||||
!Alias camellia ntt-ds 3 1 9
|
||||
|
||||
camellia 1 : CAMELLIA-128-ECB : camellia-128-ecb
|
||||
!Cname camellia-128-ofb128
|
||||
@ -1310,7 +1310,7 @@ ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH
|
||||
1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1
|
||||
1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1
|
||||
1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1
|
||||
1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1
|
||||
1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1
|
||||
|
||||
# ECDH schemes from RFC5753
|
||||
!Alias x9-63-scheme 1 3 133 16 840 63 0
|
||||
@ -1334,6 +1334,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
|
||||
# NID for X25519 (no corresponding OID).
|
||||
: X25519
|
||||
|
||||
# NID for CECPQ2 (no corresponding OID).
|
||||
: CECPQ2
|
||||
|
||||
# See RFC 8410.
|
||||
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 NID_auth_any 958
|
||||
|
||||
#define SN_CECPQ2 "CECPQ2"
|
||||
#define NID_CECPQ2 959
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* 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_SECP521R1 25
|
||||
#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
|
||||
// completed handshake or 0 if not applicable.
|
||||
|
@ -307,7 +307,7 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) {
|
||||
return false;
|
||||
}
|
||||
if (type == handback_after_ecdhe &&
|
||||
!s3->hs->key_share->Serialize(&key_share)) {
|
||||
!s3->hs->key_shares[0]->Serialize(&key_share)) {
|
||||
return false;
|
||||
}
|
||||
return CBB_flush(out);
|
||||
@ -471,7 +471,7 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
hs->key_share.reset();
|
||||
hs->key_shares[0].reset();
|
||||
hs->key_shares[1].reset();
|
||||
hs->key_share_bytes.Reset();
|
||||
|
||||
// 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.
|
||||
hs->key_share = SSLKeyShare::Create(group_id);
|
||||
if (!hs->key_share ||
|
||||
hs->key_shares[0] = SSLKeyShare::Create(group_id);
|
||||
if (!hs->key_shares[0] ||
|
||||
!hs->peer_key.CopyFrom(point)) {
|
||||
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.
|
||||
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);
|
||||
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.
|
||||
hs->key_share.reset();
|
||||
hs->key_shares[0].reset();
|
||||
hs->key_shares[1].reset();
|
||||
hs->peer_key.Reset();
|
||||
} else if (alg_k & SSL_kPSK) {
|
||||
// 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;
|
||||
|
||||
// Set up ECDH, generate a key, and emit the public half.
|
||||
hs->key_share = SSLKeyShare::Create(group_id);
|
||||
if (!hs->key_share ||
|
||||
hs->key_shares[0] = SSLKeyShare::Create(group_id);
|
||||
if (!hs->key_shares[0] ||
|
||||
!CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) ||
|
||||
!CBB_add_u16(cbb.get(), group_id) ||
|
||||
!CBB_add_u8_length_prefixed(cbb.get(), &child) ||
|
||||
!hs->key_share->Offer(&child)) {
|
||||
!hs->key_shares[0]->Offer(&child)) {
|
||||
return ssl_hs_error;
|
||||
}
|
||||
} else {
|
||||
@ -1275,13 +1275,14 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
|
||||
|
||||
// Compute the premaster.
|
||||
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);
|
||||
return ssl_hs_error;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
|
||||
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.
|
||||
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|,
|
||||
// and sets |*out_secret| the shared secret. On failure, it returns false and
|
||||
// sets |*out_alert| to an alert to send to the peer.
|
||||
// and sets |*out_secret| to the shared secret. On failure, it returns false
|
||||
// and sets |*out_alert| to an alert to send to the peer.
|
||||
//
|
||||
// The default implementation calls |Offer| and then |Finish|, assuming a key
|
||||
// exchange protocol where the peers are symmetric.
|
||||
@ -986,7 +986,7 @@ class SSLKeyShare {
|
||||
|
||||
// Finish performs a key exchange against the |peer_key| generated by
|
||||
// |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.
|
||||
virtual bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
|
||||
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.
|
||||
UniquePtr<ERR_SAVE_STATE> error;
|
||||
|
||||
// key_share is the current key exchange instance.
|
||||
UniquePtr<SSLKeyShare> key_share;
|
||||
// key_shares are the current key exchange instances. The second is only used
|
||||
// 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.
|
||||
SSLTranscript transcript;
|
||||
|
@ -24,8 +24,10 @@
|
||||
#include <openssl/curve25519.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hrss.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../crypto/internal.h"
|
||||
@ -207,12 +209,104 @@ class X25519KeyShare : public SSLKeyShare {
|
||||
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[] = {
|
||||
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
|
||||
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
|
||||
{NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
|
||||
{NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
|
||||
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
|
||||
{NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -237,6 +331,8 @@ UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
|
||||
New<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1));
|
||||
case SSL_CURVE_X25519:
|
||||
return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
|
||||
case SSL_CURVE_CECPQ2:
|
||||
return UniquePtr<SSLKeyShare>(New<CECPQ2KeyShare>());
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -394,6 +394,11 @@ static const CurveTest kCurveTests[] = {
|
||||
"P-256",
|
||||
{ SSL_CURVE_SECP256R1 },
|
||||
},
|
||||
{
|
||||
"P-256:CECPQ2",
|
||||
{ SSL_CURVE_SECP256R1, SSL_CURVE_CECPQ2 },
|
||||
},
|
||||
|
||||
{
|
||||
"P-256:P-384:P-521:X25519",
|
||||
{
|
||||
|
@ -292,10 +292,23 @@ static const uint16_t kDefaultGroups[] = {
|
||||
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) {
|
||||
if (!hs->config->supported_group_list.empty()) {
|
||||
return hs->config->supported_group_list;
|
||||
}
|
||||
if (hs->ssl->server) {
|
||||
return Span<const uint16_t>(kDefaultGroupsServer);
|
||||
}
|
||||
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 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;
|
||||
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) {
|
||||
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)) {
|
||||
if (supported == group_id) {
|
||||
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 second_group_id = 0;
|
||||
if (hs->received_hello_retry_request) {
|
||||
// We received a HelloRetryRequest without a new curve, so there is no new
|
||||
// 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];
|
||||
|
||||
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;
|
||||
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_length_prefixed(&kse_bytes, &key_exchange) ||
|
||||
!hs->key_share->Offer(&key_exchange) ||
|
||||
!hs->key_shares[0]->Offer(&key_exchange) ||
|
||||
!CBB_flush(&kse_bytes)) {
|
||||
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 &&
|
||||
!hs->key_share_bytes.CopyFrom(
|
||||
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;
|
||||
}
|
||||
|
||||
if (hs->key_share->GroupID() != group_id) {
|
||||
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
||||
return false;
|
||||
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;
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
hs->new_session->group_id = group_id;
|
||||
hs->key_share.reset();
|
||||
hs->key_shares[0].reset();
|
||||
hs->key_shares[1].reset();
|
||||
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)) {
|
||||
if (group == SSL_CURVE_CECPQ2 &&
|
||||
hs->max_version < TLS1_3_VERSION) {
|
||||
continue;
|
||||
}
|
||||
if (!CBB_add_u16(&groups_bytes, group)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -649,7 +649,6 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
|
||||
SSL_set_connect_state(ssl.get());
|
||||
}
|
||||
|
||||
|
||||
int sock = Connect(config->port);
|
||||
if (sock == -1) {
|
||||
return false;
|
||||
|
@ -26,7 +26,7 @@ type keyAgreement interface {
|
||||
// In the case that the key agreement protocol doesn't use a
|
||||
// ServerKeyExchange message, generateServerKeyExchange can return nil,
|
||||
// nil.
|
||||
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error)
|
||||
generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg, uint16) (*serverKeyExchangeMsg, error)
|
||||
processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error)
|
||||
|
||||
// On the client side, the next two methods are called in order.
|
||||
|
@ -163,6 +163,7 @@ const (
|
||||
CurveP384 CurveID = 24
|
||||
CurveP521 CurveID = 25
|
||||
CurveX25519 CurveID = 29
|
||||
CurveCECPQ2 CurveID = 16696
|
||||
)
|
||||
|
||||
// TLS Elliptic Curve Point Formats
|
||||
@ -1645,6 +1646,18 @@ type ProtocolBugs struct {
|
||||
// ExpectJDK11DowngradeRandom is whether the client should expect the
|
||||
// server to send the JDK 11 downgrade signal.
|
||||
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() {
|
||||
@ -1724,7 +1737,7 @@ func (c *Config) maxVersion(isDTLS bool) uint16 {
|
||||
return ret
|
||||
}
|
||||
|
||||
var defaultCurvePreferences = []CurveID{CurveX25519, CurveP256, CurveP384, CurveP521}
|
||||
var defaultCurvePreferences = []CurveID{CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
|
||||
|
||||
func (c *Config) curvePreferences() []CurveID {
|
||||
if c == nil || len(c.CurvePreferences) == 0 {
|
||||
|
@ -549,6 +549,9 @@ NextCipherSuite:
|
||||
helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
|
||||
var secondHelloBytes []byte
|
||||
if haveHelloRetryRequest {
|
||||
if c.config.Bugs.FailIfHelloRetryRequested {
|
||||
return errors.New("tls: unexpected HelloRetryRequest")
|
||||
}
|
||||
// Explicitly read the ChangeCipherSpec now; it should
|
||||
// be attached to the first flight, not the second flight.
|
||||
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
|
||||
|
||||
// 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()
|
||||
Curves:
|
||||
for _, curve := range hs.clientHello.supportedCurves {
|
||||
if curve == CurveCECPQ2 && c.vers < VersionTLS13 {
|
||||
// CECPQ2 is TLS 1.3-only.
|
||||
continue
|
||||
}
|
||||
|
||||
for _, supported := range preferredCurves {
|
||||
if supported == curve {
|
||||
supportedCurve = true
|
||||
@ -1621,7 +1646,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
||||
}
|
||||
|
||||
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 {
|
||||
c.sendAlert(alertHandshakeFailure)
|
||||
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/ed25519"
|
||||
"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
|
||||
)
|
||||
|
||||
type keyType int
|
||||
@ -37,7 +38,7 @@ type rsaKeyAgreement struct {
|
||||
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.
|
||||
ka.clientVersion = clientHello.vers
|
||||
|
||||
@ -347,6 +348,90 @@ func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err er
|
||||
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) {
|
||||
switch id {
|
||||
case CurveP224:
|
||||
@ -359,6 +444,8 @@ func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
|
||||
return &ellipticECDHCurve{curve: elliptic.P521(), sendCompressed: config.Bugs.SendCompressedCoordinates}, true
|
||||
case CurveX25519:
|
||||
return &x25519ECDHCurve{setHighBit: config.Bugs.SetX25519HighBit}, true
|
||||
case CurveCECPQ2:
|
||||
return &cecpq2Curve{}, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
@ -501,12 +588,17 @@ type ecdheKeyAgreement struct {
|
||||
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
|
||||
preferredCurves := config.curvePreferences()
|
||||
|
||||
NextCandidate:
|
||||
for _, candidate := range preferredCurves {
|
||||
if candidate == CurveCECPQ2 && version < VersionTLS13 {
|
||||
// CECPQ2 is TLS 1.3-only.
|
||||
continue
|
||||
}
|
||||
|
||||
for _, c := range clientHello.supportedCurves {
|
||||
if candidate == c {
|
||||
curveid = c
|
||||
@ -614,7 +706,7 @@ func (ka *ecdheKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
|
||||
// exchange.
|
||||
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
|
||||
}
|
||||
|
||||
@ -666,7 +758,7 @@ type pskKeyAgreement struct {
|
||||
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.
|
||||
bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
|
||||
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
|
||||
// ServerKeyExchange.
|
||||
baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello)
|
||||
baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -9619,7 +9619,7 @@ func addSignatureAlgorithmTests() {
|
||||
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
|
||||
Certificates: []Certificate{ecdsaP256Certificate},
|
||||
},
|
||||
flags: []string{"-p384-only"},
|
||||
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||
shouldFail: true,
|
||||
expectedError: ":BAD_ECC_CERT:",
|
||||
})
|
||||
@ -9631,7 +9631,7 @@ func addSignatureAlgorithmTests() {
|
||||
MaxVersion: VersionTLS13,
|
||||
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.
|
||||
@ -10711,6 +10711,7 @@ var testCurves = []struct {
|
||||
{"P-384", CurveP384},
|
||||
{"P-521", CurveP521},
|
||||
{"X25519", CurveX25519},
|
||||
{"CECPQ2", CurveCECPQ2},
|
||||
}
|
||||
|
||||
const bogusCurve = 0x1234
|
||||
@ -10718,6 +10719,10 @@ const bogusCurve = 0x1234
|
||||
func addCurveTests() {
|
||||
for _, curve := range testCurves {
|
||||
for _, ver := range tlsVersions {
|
||||
if curve.id == CurveCECPQ2 && ver.version < VersionTLS13 {
|
||||
continue
|
||||
}
|
||||
|
||||
suffix := curve.name + "-" + ver.name
|
||||
|
||||
testCases = append(testCases, testCase{
|
||||
@ -10758,7 +10763,7 @@ func addCurveTests() {
|
||||
expectedCurveID: curve.id,
|
||||
})
|
||||
|
||||
if curve.id != CurveX25519 {
|
||||
if curve.id != CurveX25519 && curve.id != CurveCECPQ2 {
|
||||
testCases = append(testCases, testCase{
|
||||
name: "CurveTest-Client-Compressed-" + suffix,
|
||||
config: Config{
|
||||
@ -10902,7 +10907,7 @@ func addCurveTests() {
|
||||
IgnorePeerCurvePreferences: true,
|
||||
},
|
||||
},
|
||||
flags: []string{"-p384-only"},
|
||||
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||
shouldFail: true,
|
||||
expectedError: ":WRONG_CURVE:",
|
||||
})
|
||||
@ -10918,7 +10923,7 @@ func addCurveTests() {
|
||||
SendCurve: CurveP256,
|
||||
},
|
||||
},
|
||||
flags: []string{"-p384-only"},
|
||||
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||
shouldFail: true,
|
||||
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() {
|
||||
@ -12706,7 +12817,7 @@ func addTLS13HandshakeTests() {
|
||||
},
|
||||
},
|
||||
tls13Variant: variant,
|
||||
flags: []string{"-p384-only"},
|
||||
flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
|
||||
shouldFail: true,
|
||||
expectedError: ":WRONG_CURVE:",
|
||||
})
|
||||
|
@ -104,7 +104,6 @@ const Flag<bool> kBoolFlags[] = {
|
||||
{ "-renegotiate-ignore", &TestConfig::renegotiate_ignore },
|
||||
{ "-forbid-renegotiation-after-handshake",
|
||||
&TestConfig::forbid_renegotiation_after_handshake },
|
||||
{ "-p384-only", &TestConfig::p384_only },
|
||||
{ "-enable-all-curves", &TestConfig::enable_all_curves },
|
||||
{ "-use-old-client-cert-callback",
|
||||
&TestConfig::use_old_client_cert_callback },
|
||||
@ -147,6 +146,7 @@ const Flag<bool> kBoolFlags[] = {
|
||||
{ "-handshaker-resume", &TestConfig::handshaker_resume },
|
||||
{ "-reverify-on-resume", &TestConfig::reverify_on_resume },
|
||||
{ "-jdk11-workaround", &TestConfig::jdk11_workaround },
|
||||
{ "-server-preference", &TestConfig::server_preference },
|
||||
};
|
||||
|
||||
const Flag<std::string> kStringFlags[] = {
|
||||
@ -220,10 +220,10 @@ const Flag<int> kIntFlags[] = {
|
||||
};
|
||||
|
||||
const Flag<std::vector<int>> kIntVectorFlags[] = {
|
||||
{ "-signing-prefs", &TestConfig::signing_prefs },
|
||||
{ "-verify-prefs", &TestConfig::verify_prefs },
|
||||
{ "-expect-peer-verify-pref",
|
||||
&TestConfig::expected_peer_verify_prefs },
|
||||
{"-signing-prefs", &TestConfig::signing_prefs},
|
||||
{"-verify-prefs", &TestConfig::verify_prefs},
|
||||
{"-expect-peer-verify-pref", &TestConfig::expected_peer_verify_prefs},
|
||||
{"-curves", &TestConfig::curves},
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
if (install_cert_compression_algs &&
|
||||
(!SSL_CTX_add_cert_compression_alg(
|
||||
ssl_ctx.get(), 0xff02,
|
||||
@ -1341,6 +1340,10 @@ bssl::UniquePtr<SSL_CTX> TestConfig::SetupCtx(SSL_CTX *old_ctx) const {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (server_preference) {
|
||||
SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
}
|
||||
|
||||
return ssl_ctx;
|
||||
}
|
||||
|
||||
@ -1589,16 +1592,43 @@ bssl::UniquePtr<SSL> TestConfig::NewSSL(
|
||||
if (!check_close_notify) {
|
||||
SSL_set_quiet_shutdown(ssl.get(), 1);
|
||||
}
|
||||
if (p384_only) {
|
||||
int nid = NID_secp384r1;
|
||||
if (!SSL_set1_curves(ssl.get(), &nid, 1)) {
|
||||
return nullptr;
|
||||
if (!curves.empty()) {
|
||||
std::vector<int> nids;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enable_all_curves) {
|
||||
static const int kAllCurves[] = {
|
||||
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,
|
||||
OPENSSL_ARRAY_SIZE(kAllCurves))) {
|
||||
|
@ -33,6 +33,7 @@ struct TestConfig {
|
||||
std::vector<int> signing_prefs;
|
||||
std::vector<int> verify_prefs;
|
||||
std::vector<int> expected_peer_verify_prefs;
|
||||
std::vector<int> curves;
|
||||
std::string key_file;
|
||||
std::string cert_file;
|
||||
std::string expected_server_name;
|
||||
@ -122,7 +123,6 @@ struct TestConfig {
|
||||
bool renegotiate_ignore = false;
|
||||
bool forbid_renegotiation_after_handshake = false;
|
||||
int expect_peer_signature_algorithm = 0;
|
||||
bool p384_only = false;
|
||||
bool enable_all_curves = false;
|
||||
int expect_curve_id = 0;
|
||||
bool use_old_client_cert_callback = false;
|
||||
@ -170,6 +170,7 @@ struct TestConfig {
|
||||
bool handshaker_resume = false;
|
||||
std::string handshaker_path;
|
||||
bool jdk11_workaround = false;
|
||||
bool server_preference = false;
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
|
@ -165,15 +165,17 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
|
||||
return ssl_hs_error;
|
||||
}
|
||||
|
||||
// Check that the HelloRetryRequest does not request the key share that
|
||||
// was provided in the initial ClientHello.
|
||||
if (hs->key_share->GroupID() == group_id) {
|
||||
// Check that the HelloRetryRequest does not request a key share that was
|
||||
// provided in the initial ClientHello.
|
||||
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);
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
|
||||
return ssl_hs_error;
|
||||
}
|
||||
|
||||
hs->key_share.reset();
|
||||
hs->key_shares[0].reset();
|
||||
hs->key_shares[1].reset();
|
||||
hs->retry_group = group_id;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/ec_key.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hrss.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rsa.h>
|
||||
@ -744,6 +745,61 @@ static bool SpeedScrypt(const std::string &selected) {
|
||||
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[] = {
|
||||
{
|
||||
"-filter", kOptionalArgument,
|
||||
@ -817,7 +873,8 @@ bool Speed(const std::vector<std::string> &args) {
|
||||
!Speed25519(selected) ||
|
||||
!SpeedSPAKE2(selected) ||
|
||||
!SpeedScrypt(selected) ||
|
||||
!SpeedRSAKeyGen(selected)) {
|
||||
!SpeedRSAKeyGen(selected) ||
|
||||
!SpeedHRSS(selected)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,10 @@ NON_PERL_FILES = {
|
||||
('linux', 'arm'): [
|
||||
'src/crypto/curve25519/asm/x25519-asm-arm.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