Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upstream merge 2023-10-02 #1221

Merged
merged 9 commits into from
Oct 11, 2023
20 changes: 19 additions & 1 deletion crypto/chacha/chacha.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,25 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
}
#endif

ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
while (in_len > 0) {
// The assembly functions do not have defined overflow behavior. While
// overflow is almost always a bug in the caller, we prefer our functions to
// behave the same across platforms, so divide into multiple calls to avoid
// this case.
uint64_t todo = 64 * ((UINT64_C(1) << 32) - counter_nonce[0]);
if (todo > in_len) {
todo = in_len;
}

ChaCha20_ctr32(out, in, (size_t)todo, key_ptr, counter_nonce);
in += todo;
out += todo;
in_len -= todo;

// We're either done and will next break out of the loop, or we stopped at
// the wraparound point and the counter should continue at zero.
counter_nonce[0] = 0;
}
}

#else
Expand Down
110 changes: 110 additions & 0 deletions crypto/chacha/chacha_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,102 @@ static const uint8_t kOutput[] = {
0x8f, 0x40, 0xcf, 0x4a,
};

static uint32_t kOverflowCounter = 0xffffffff;

static const uint8_t kOverflowOutput[] = {
0x37, 0x64, 0x38, 0xcb, 0x25, 0x69, 0x2c, 0xf5, 0x88, 0x8a, 0xfe, 0x6d,
0x3b, 0x10, 0x07, 0x3c, 0x77, 0xac, 0xcd, 0x1c, 0x0c, 0xa7, 0x17, 0x31,
0x1d, 0xc3, 0x81, 0xd1, 0xa5, 0x20, 0x55, 0xea, 0xd3, 0x00, 0xc9, 0x84,
0xde, 0xe2, 0xe5, 0x5e, 0x7b, 0x28, 0x28, 0x59, 0x73, 0x3a, 0x8e, 0x57,
0x62, 0x18, 0x50, 0x55, 0x97, 0xca, 0x50, 0x3e, 0x8a, 0x84, 0x61, 0x28,
0x4c, 0x22, 0x93, 0x50, 0x48, 0x7e, 0x65, 0x78, 0x06, 0x5a, 0xcd, 0x2b,
0x11, 0xf7, 0x10, 0xfd, 0x6f, 0x41, 0x92, 0x82, 0x7c, 0x3a, 0x71, 0x07,
0x67, 0xd0, 0x7e, 0xb7, 0xdf, 0xdc, 0xfc, 0xee, 0xe6, 0x55, 0xdd, 0x6f,
0x79, 0x23, 0xf3, 0xae, 0xb1, 0x21, 0x96, 0xbe, 0xea, 0x0e, 0x1b, 0x58,
0x0b, 0x3f, 0x63, 0x51, 0xd4, 0xce, 0x98, 0xfe, 0x1a, 0xc7, 0xa7, 0x43,
0x7f, 0x0c, 0xe8, 0x62, 0xcf, 0x78, 0x3f, 0x4e, 0x31, 0xbf, 0x2b, 0x76,
0x91, 0xcd, 0x19, 0x80, 0x0d, 0x7f, 0x11, 0x8b, 0x76, 0xef, 0x43, 0x3c,
0x4f, 0x61, 0x86, 0xc5, 0x64, 0xa8, 0xc2, 0x73, 0xc2, 0x64, 0x39, 0xa0,
0x8b, 0xe6, 0x7f, 0xf6, 0x26, 0xd4, 0x47, 0x4f, 0xe4, 0x46, 0xe2, 0xf5,
0x9e, 0xe6, 0xc7, 0x76, 0x6c, 0xa9, 0x0f, 0x1d, 0x1b, 0x22, 0xa5, 0x62,
0x0a, 0x88, 0x3e, 0x8c, 0xf0, 0xbc, 0x4c, 0x11, 0x3f, 0x0d, 0xf7, 0x85,
0x67, 0x0b, 0x4c, 0xa3, 0x3f, 0xa8, 0xf1, 0x2a, 0x65, 0x2e, 0x00, 0x03,
0xc9, 0x49, 0x91, 0x48, 0xb7, 0xc8, 0x29, 0x28, 0x2f, 0x46, 0x8e, 0x8b,
0xd6, 0x73, 0x19, 0x06, 0x3e, 0x6f, 0x92, 0xc8, 0x3d, 0x3f, 0x4d, 0x68,
0xbc, 0x02, 0xc0, 0x8f, 0x71, 0x46, 0x0d, 0x28, 0x63, 0xfe, 0xad, 0x14,
0x81, 0x04, 0xb7, 0x23, 0xfd, 0x21, 0x0a, 0xf0, 0x6f, 0xcd, 0x47, 0x0b,
0x0e, 0x93, 0xa3, 0xa8, 0x44, 0x15, 0xd6, 0xae, 0x06, 0x44, 0x6b, 0xbc,
0xff, 0x8a, 0x56, 0x60, 0x3c, 0x38, 0xd6, 0xed, 0x03, 0x2d, 0x79, 0x2a,
0xe9, 0x15, 0xef, 0xfc, 0x92, 0x1f, 0x83, 0xa4, 0x60, 0x8f, 0xc9, 0x29,
0xb2, 0xb4, 0x9e, 0x3f, 0xa9, 0xe8, 0xfb, 0xa2, 0x62, 0x20, 0x2e, 0xc9,
0x43, 0xb2, 0xd1, 0x36, 0x85, 0x1e, 0xa4, 0xb3, 0x4f, 0x8c, 0x9e, 0x81,
0x75, 0x68, 0xbc, 0xf1, 0x52, 0xd5, 0x03, 0x22, 0xcf, 0xdf, 0x64, 0xb0,
0x28, 0xd2, 0x45, 0x18, 0x38, 0x8c, 0xd0, 0xf6, 0x30, 0x3c, 0x04, 0xd9,
0x8d, 0xb6, 0xb2, 0x57, 0x2a, 0xee, 0x28, 0xeb, 0x5f, 0x1a, 0x10, 0x6e,
0x88, 0x79, 0x08, 0x23, 0x19, 0x84, 0xf8, 0x80, 0x1a, 0x7d, 0x6f, 0x8b,
0xc1, 0x8e, 0x5f, 0x5f, 0x54, 0x14, 0x2a, 0xdc, 0x41, 0x5d, 0xeb, 0x00,
0xf2, 0x50, 0xae, 0xd3, 0x55, 0x32, 0xf6, 0xd9, 0x34, 0xf4, 0xb2, 0xf2,
0xf5, 0x90, 0x05, 0x8a, 0x9c, 0xc7, 0x94, 0x5d, 0x2d, 0x5a, 0x0f, 0xdd,
0x03, 0xde, 0xbe, 0x18, 0xb3, 0xe3, 0x07, 0x6b, 0x57, 0xfa, 0x1b, 0x7b,
0x75, 0xcb, 0xc2, 0x4d, 0xf7, 0x88, 0xfe, 0xf9, 0xc0, 0x6c, 0xdb, 0x5f,
0xf6, 0x48, 0x00, 0x4a, 0x5d, 0x75, 0xfa, 0x6b, 0x45, 0x43, 0xc4, 0x7f,
0x97, 0x31, 0x22, 0xb4, 0x9c, 0xa3, 0xee, 0x2f, 0x27, 0xa9, 0x9f, 0x0e,
0xdc, 0x40, 0x67, 0x17, 0x2e, 0xcb, 0xfd, 0x9e, 0xe7, 0xb2, 0x85, 0xcd,
0x49, 0x24, 0xc8, 0x8a, 0x59, 0x6b, 0x1f, 0xec, 0x72, 0x89, 0xf8, 0x30,
0xdf, 0x82, 0x61, 0x3b, 0x8b, 0xc9, 0x80, 0xe4, 0x27, 0x0d, 0xfe, 0x42,
0x27, 0x6c, 0xaf, 0x62, 0x3e, 0x2f, 0x1d, 0x38, 0xb6, 0x88, 0x8f, 0x71,
0x5a, 0x54, 0x6c, 0x68, 0x57, 0x40, 0x49, 0x7a, 0xb2, 0xe8, 0xb6, 0x97,
0xab, 0xd6, 0x3c, 0x35, 0xf3, 0x95, 0x12, 0xde, 0xa2, 0x39, 0x54, 0x52,
0x8c, 0x38, 0x2a, 0x2b, 0xe7, 0x21, 0x38, 0x63, 0xb0, 0xd6, 0xad, 0x94,
0x44, 0xaf, 0x49, 0x5d, 0xfc, 0x49, 0x6b, 0x30, 0xdf, 0xe9, 0x19, 0x1e,
0xed, 0x98, 0x0d, 0x4a, 0x3d, 0x56, 0x5e, 0x74, 0xad, 0x13, 0x8b, 0x68,
0x45, 0x08, 0xbe, 0x0e, 0x6c, 0xb4, 0x62, 0x93, 0x27, 0x8b, 0x4f, 0xab,
0x3e, 0xba, 0xe1, 0xe5, 0xff, 0xa8, 0x5d, 0x33, 0x32, 0xff, 0x34, 0xf9,
0x8d, 0x67, 0x24, 0x4a, 0xbb, 0x2c, 0x60, 0xb5, 0x88, 0x96, 0x1b, 0xcc,
0x53, 0xfb, 0x2e, 0x05, 0x1d, 0x8b, 0xc2, 0xa0, 0xde, 0x21, 0x41, 0x5e,
0x11, 0x1b, 0x96, 0xd9, 0xa6, 0xae, 0xbd, 0xf0, 0x91, 0xad, 0x69, 0x2b,
0xd2, 0x3f, 0xe4, 0x3d, 0x16, 0x69, 0xa6, 0xb2, 0x9c, 0xbe, 0x59, 0x7b,
0x87, 0x79, 0xf5, 0xc2, 0x5a, 0xcc, 0xdf, 0xfe, 0x7f, 0xf9, 0xa6, 0x52,
0xde, 0x5f, 0x46, 0x91, 0x21, 0x2c, 0x2c, 0x49, 0x25, 0x00, 0xd5, 0xe4,
0x81, 0x6b, 0x85, 0xad, 0x98, 0xaf, 0x06, 0x4a, 0x83, 0xb2, 0xe3, 0x42,
0x39, 0x31, 0x50, 0xe1, 0x2d, 0x22, 0xe6, 0x07, 0x24, 0x65, 0x29, 0x3f,
0x4c, 0xbd, 0x14, 0x8d, 0xfa, 0x31, 0xfa, 0xa4, 0xb5, 0x99, 0x04, 0xa2,
0xa5, 0xcc, 0x3b, 0x12, 0xb1, 0xaa, 0x6a, 0x17, 0x78, 0x8b, 0xb3, 0xe4,
0x3c, 0x4c, 0xc5, 0xaa, 0x79, 0x12, 0x17, 0xe0, 0x22, 0x4d, 0xf4, 0xa9,
0xd5, 0xd0, 0xed, 0xf8, 0xfe, 0x0a, 0x45, 0x80, 0x9f, 0x3b, 0x74, 0xa0,
0xb1, 0xda, 0x18, 0xfa, 0xc2, 0x7d, 0xf6, 0x18, 0x2e, 0xa9, 0x2b, 0x7e,
0x69, 0x06, 0x43, 0x2d, 0x62, 0x09, 0x42, 0x10, 0x9f, 0x83, 0xad, 0xd9,
0xdd, 0xcd, 0xcb, 0x1b, 0x33, 0x32, 0x3e, 0x1f, 0xf6, 0xac, 0x3b, 0xa3,
0x29, 0xd7, 0xc0, 0x88, 0xf9, 0xb7, 0x4c, 0xcd, 0x0a, 0x1f, 0xb8, 0x0f,
0xe6, 0xf7, 0xd7, 0x4d, 0x5f, 0x06, 0x12, 0x8a, 0x12, 0xa6, 0x2d, 0xbe,
0x5c, 0x57, 0xf8, 0x7f, 0x54, 0x3f, 0x90, 0x83, 0x2c, 0x0a, 0xc5, 0x3d,
0x03, 0x78, 0x8a, 0x68, 0xf0, 0xbd, 0xa5, 0x3e, 0xe7, 0x07, 0xab, 0xc8,
0x58, 0x2f, 0x5c, 0xfd, 0xb5, 0x39, 0xe3, 0xc6, 0x1c, 0x27, 0xf9, 0x0b,
0xc7, 0x4c, 0xcc, 0x67, 0x62, 0xe6, 0x79, 0xe8, 0xc1, 0x0a, 0x86, 0x8a,
0xb2, 0x32, 0x7b, 0x90, 0x36, 0x50, 0x92, 0x1f, 0x3e, 0x68, 0x39, 0x1c,
0x4d, 0x5d, 0xf8, 0x2b, 0xe8, 0x7d, 0xe2, 0x34, 0x61, 0x9e, 0xc3, 0x77,
0xb9, 0x4c, 0x34, 0x08, 0xda, 0x31, 0xc9, 0x1d, 0xbd, 0x3b, 0x7b, 0xf1,
0x14, 0xba, 0x3a, 0x34, 0x13, 0xaa, 0x5e, 0xa8, 0x36, 0xf6, 0xfe, 0xed,
0x5b, 0xef, 0xaf, 0x24, 0x42, 0xba, 0xfc, 0xc9, 0x30, 0x84, 0xec, 0x49,
0x14, 0xab, 0x58, 0x71, 0xfe, 0x4b, 0x6d, 0x7b, 0x9f, 0xbb, 0x3c, 0x83,
0xdf, 0x3a, 0xfb, 0x54, 0xff, 0x36, 0xaa, 0x6c, 0x47, 0x94, 0xc0, 0xde,
0x89, 0x2e, 0xac, 0x68, 0xee, 0xe8, 0xf4, 0xae, 0xa3, 0xe0, 0x91, 0x55,
0x0b, 0x0c, 0xd7, 0xf4, 0x33, 0xb5, 0xf9, 0xf2, 0x9e, 0xda, 0x78, 0xe5,
0x75, 0xec, 0xdb, 0xf6, 0xed, 0x27, 0x9f, 0x44, 0x19, 0x9f, 0xb7, 0xf0,
0xac, 0x1b, 0x3a, 0xf5, 0x77, 0xc7, 0x76, 0x1e, 0x3f, 0x78, 0x12, 0x48,
0x1d, 0xb8, 0xe0, 0x30, 0x29, 0x9a, 0x8c, 0x8f, 0x21, 0x44, 0x9c, 0x89,
0xec, 0x8e, 0xd0, 0x81, 0xf5, 0x6a, 0xd0, 0xac, 0x5e, 0xf0, 0x0f, 0x88,
0x86, 0x31, 0x2e, 0x15, 0x1e, 0x0d, 0x2d, 0xeb, 0x56, 0x30, 0x27, 0x02,
0x93, 0xf4, 0x07, 0x07, 0xba, 0xf7, 0xbd, 0xe8, 0x27, 0x4f, 0xc6, 0xd9,
0x57, 0x10, 0x3b, 0xf0, 0xff, 0x2f, 0x2d, 0x6b, 0xd0, 0x17, 0xb3, 0x49,
0xeb, 0xc2, 0x49, 0xdb,
};


static_assert(sizeof(kInput) == sizeof(kOutput),
"Input and output lengths don't match.");
static_assert(sizeof(kInput) == sizeof(kOverflowOutput),
"Input and output lengths don't match.");

TEST(ChaChaTest, TestVector) {
// Run the test with the test vector at all lengths.
Expand All @@ -237,6 +331,22 @@ TEST(ChaChaTest, TestVector) {
}
}

TEST(ChaChaTest, CounterOverflow) {
// Run the test with the test vector at all lengths.
for (size_t len = 0; len <= sizeof(kInput); len++) {
SCOPED_TRACE(len);

std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kOverflowCounter);
EXPECT_EQ(Bytes(kOverflowOutput, len), Bytes(buf.get(), len));

// Test the in-place version.
OPENSSL_memcpy(buf.get(), kInput, len);
CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kOverflowCounter);
EXPECT_EQ(Bytes(kOverflowOutput, len), Bytes(buf.get(), len));
}
}

#if defined(CHACHA20_ASM) && defined(SUPPORTS_ABI_TEST)
TEST(ChaChaTest, ABI) {
uint32_t key[8];
Expand Down
9 changes: 8 additions & 1 deletion crypto/chacha/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,14 @@ void CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32],
defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
#define CHACHA20_ASM

// ChaCha20_ctr32 is defined in asm/chacha-*.pl.
// ChaCha20_ctr32 encrypts |in_len| bytes from |in| and writes the result to
// |out|. If |in| and |out| alias, they must be equal.
//
// |counter[0]| is the initial 32-bit block counter, and the remainder is the
// 96-bit nonce. If the counter overflows, the output is undefined. The function
// will produce output, but the output may vary by machine and may not be
// self-consistent. (On some architectures, the assembly implements a mix of
// 64-bit and 32-bit counters.)
void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
const uint32_t key[8], const uint32_t counter[4]);
#endif
Expand Down
4 changes: 2 additions & 2 deletions crypto/curve25519/curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,6 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
}

// The all-zero output results when the input is a point of small order.
// See https://www.rfc-editor.org/rfc/rfc7748#section-6.1.
return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0;
return constant_time_declassify_int(
CRYPTO_memcmp(kZeros, out_shared_key, 32)) != 0;
}
3 changes: 2 additions & 1 deletion crypto/curve25519/curve25519_nohw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1946,7 +1946,7 @@ void x25519_scalar_mult_generic_nohw(uint8_t out[32],
}

void x25519_public_from_private_nohw(uint8_t out_public_value[32],
const uint8_t private_key[32]) {
const uint8_t private_key[32]) {

uint8_t e[32];
OPENSSL_memcpy(e, private_key, 32);
Expand All @@ -1966,4 +1966,5 @@ void x25519_public_from_private_nohw(uint8_t out_public_value[32],
fe_loose_invert(&zminusy_inv, &zminusy);
fe_mul_tlt(&zminusy_inv, &zplusy, &zminusy_inv);
fe_tobytes(out_public_value, &zminusy_inv);
CONSTTIME_DECLASSIFY(out_public_value, 32);
}
9 changes: 9 additions & 0 deletions crypto/curve25519/ed25519_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@ TEST(Ed25519Test, TestVectors) {
ASSERT_TRUE(t->GetBytes(&expected_signature, "SIG"));
ASSERT_EQ(64u, expected_signature.size());

// Signing should not leak the private key or the message.
CONSTTIME_SECRET(private_key.data(), private_key.size());
CONSTTIME_SECRET(message.data(), message.size());
uint8_t signature[64];
ASSERT_TRUE(ED25519_sign(signature, message.data(), message.size(),
private_key.data()));
CONSTTIME_DECLASSIFY(signature, sizeof(signature));
CONSTTIME_DECLASSIFY(message.data(), message.size());

EXPECT_EQ(Bytes(expected_signature), Bytes(signature));
EXPECT_TRUE(ED25519_verify(message.data(), message.size(), signature,
public_key.data()));
Expand Down Expand Up @@ -114,9 +120,12 @@ TEST(Ed25519Test, KeypairFromSeed) {

uint8_t seed[32];
OPENSSL_memcpy(seed, private_key1, sizeof(seed));
CONSTTIME_SECRET(seed, sizeof(seed));

uint8_t public_key2[32], private_key2[64];
ED25519_keypair_from_seed(public_key2, private_key2, seed);
CONSTTIME_DECLASSIFY(public_key2, sizeof(public_key2));
CONSTTIME_DECLASSIFY(private_key2, sizeof(private_key2));

EXPECT_EQ(Bytes(public_key1), Bytes(public_key2));
EXPECT_EQ(Bytes(private_key1), Bytes(private_key2));
Expand Down
87 changes: 76 additions & 11 deletions crypto/curve25519/x25519_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,31 @@
#include "../test/wycheproof_util.h"
#include "internal.h"

static inline int ctwrapX25519(uint8_t out_shared_key[32],
const uint8_t private_key[32],
const uint8_t peer_public_value[32]) {
uint8_t scalar[32], point[32];
// Copy all the secrets into a temporary buffer, so we can run constant-time
// validation on them.
OPENSSL_memcpy(scalar, private_key, sizeof(scalar));
OPENSSL_memcpy(point, peer_public_value, sizeof(point));

// X25519 should not leak the private key.
CONSTTIME_SECRET(scalar, sizeof(scalar));
// All other inputs are also marked as secret. This is not to support any
// particular use case for calling X25519 with a secret *point*, but
// rather to ensure that the choice of the point cannot influence whether
// the scalar is leaked or not. Same for the initial contents of the
// output buffer. This conservative choice may be revised in the future.
CONSTTIME_SECRET(point, sizeof(point));
CONSTTIME_SECRET(out_shared_key, 32);
int r = X25519(out_shared_key, scalar, point);
CONSTTIME_DECLASSIFY(out_shared_key, 32);
return r;
}

TEST(X25519Test, TestVector) {
// Taken from https://tools.ietf.org/html/rfc7748#section-5.2
// Taken from https://www.rfc-editor.org/rfc/rfc7748#section-5.2
static const uint8_t kScalar1[32] = {
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
Expand All @@ -41,9 +63,8 @@ TEST(X25519Test, TestVector) {
0x35, 0x3b, 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c,
};

uint8_t out[32];
EXPECT_TRUE(X25519(out, kScalar1, kPoint1));

uint8_t out[32], secret[32];
EXPECT_TRUE(ctwrapX25519(out, kScalar1, kPoint1));
static const uint8_t kExpected1[32] = {
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
Expand All @@ -61,15 +82,58 @@ TEST(X25519Test, TestVector) {
0x9d, 0x05, 0x38, 0xae, 0x2c, 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0,
0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
};

EXPECT_TRUE(X25519(out, kScalar2, kPoint2));

EXPECT_TRUE(ctwrapX25519(out, kScalar2, kPoint2));
static const uint8_t kExpected2[32] = {
0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
};
EXPECT_EQ(Bytes(kExpected2), Bytes(out));

// Taken from https://www.rfc-editor.org/rfc/rfc7748.html#section-6.1
static const uint8_t kPrivateA[32] = {
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1,
0x72, 0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0,
0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a,
};
static const uint8_t kPublicA[32] = {
0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d,
0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38,
0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a,
};
static const uint8_t kPrivateB[32] = {
0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 0x79, 0xe1, 0x7f,
0x8b, 0x83, 0x80, 0x0e, 0xe6, 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18,
0xb6, 0xfd, 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb,
};
static const uint8_t kPublicB[32] = {
0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b, 0x61,
0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78,
0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f,
};
static const uint8_t kSecret[32] = {
0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 0x72, 0x8e, 0x3b,
0xf4, 0x80, 0x35, 0x0f, 0x25, 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1,
0x9e, 0x33, 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42,
};

OPENSSL_memcpy(secret, kPrivateA, sizeof(secret));
CONSTTIME_SECRET(secret, sizeof(secret));
X25519_public_from_private(out, secret);
CONSTTIME_DECLASSIFY(out, sizeof(out));
EXPECT_EQ(Bytes(out), Bytes(kPublicA));

OPENSSL_memcpy(secret, kPrivateB, sizeof(secret));
CONSTTIME_SECRET(secret, sizeof(secret));
X25519_public_from_private(out, secret);
CONSTTIME_DECLASSIFY(out, sizeof(out));
EXPECT_EQ(Bytes(out), Bytes(kPublicB));

ctwrapX25519(out, kPrivateA, kPublicB);
EXPECT_EQ(Bytes(out), Bytes(kSecret));

ctwrapX25519(out, kPrivateB, kPublicA);
EXPECT_EQ(Bytes(out), Bytes(kSecret));
}

TEST(X25519Test, SmallOrder) {
Expand All @@ -83,7 +147,7 @@ TEST(X25519Test, SmallOrder) {
OPENSSL_memset(private_key, 0x11, sizeof(private_key));

OPENSSL_memset(out, 0xff, sizeof(out));
EXPECT_FALSE(X25519(out, private_key, kSmallOrderPoint))
EXPECT_FALSE(ctwrapX25519(out, private_key, kSmallOrderPoint))
<< "X25519 returned success with a small-order input.";

// For callers which don't check, |out| should still be filled with zeros.
Expand All @@ -96,7 +160,7 @@ TEST(X25519Test, Iterated) {
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];

for (unsigned i = 0; i < 1000; i++) {
EXPECT_TRUE(X25519(out, scalar, point));
EXPECT_TRUE(ctwrapX25519(out, scalar, point));
OPENSSL_memcpy(point, scalar, sizeof(point));
OPENSSL_memcpy(scalar, out, sizeof(scalar));
}
Expand All @@ -115,7 +179,7 @@ TEST(X25519Test, DISABLED_IteratedLarge) {
uint8_t scalar[32] = {9}, point[32] = {9}, out[32];

for (unsigned i = 0; i < 1000000; i++) {
EXPECT_TRUE(X25519(out, scalar, point));
EXPECT_TRUE(ctwrapX25519(out, scalar, point));
OPENSSL_memcpy(point, scalar, sizeof(point));
OPENSSL_memcpy(scalar, out, sizeof(scalar));
}
Expand Down Expand Up @@ -143,8 +207,9 @@ TEST(X25519Test, Wycheproof) {
ASSERT_TRUE(t->GetBytes(&shared, "shared"));
ASSERT_EQ(32u, priv.size());
ASSERT_EQ(32u, pub.size());

uint8_t secret[32];
int ret = X25519(secret, priv.data(), pub.data());
int ret = ctwrapX25519(secret, priv.data(), pub.data());
EXPECT_EQ(ret, result.IsValid({"NonCanonicalPublic", "Twist"}) ? 1 : 0);
EXPECT_EQ(Bytes(secret), Bytes(shared));
});
Expand Down
Loading