xwing: tweaks and cleanups. Change-Id: I4b349b08f6bd7268b9dc9964560cd58046d7f5db Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/79467 Auto-Submit: Adam Langley <agl@google.com> Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/xwing/xwing.cc b/crypto/xwing/xwing.cc index 2d054be..216f12a 100644 --- a/crypto/xwing/xwing.cc +++ b/crypto/xwing/xwing.cc
@@ -22,6 +22,7 @@ #include "../fipsmodule/bcm_interface.h" #include "../fipsmodule/keccak/internal.h" + struct private_key { MLKEM768_private_key mlkem_private_key; uint8_t x25519_private_key[32]; @@ -172,6 +173,7 @@ const uint8_t encoded_public_key[XWING_PUBLIC_KEY_BYTES], const uint8_t eseed[64]) { // X25519 + static_assert(XWING_PUBLIC_KEY_BYTES >= MLKEM768_PUBLIC_KEY_BYTES + 32); const uint8_t *x25519_public_key = encoded_public_key + MLKEM768_PUBLIC_KEY_BYTES; const uint8_t *x25519_ephemeral_private_key = eseed + 32; @@ -185,14 +187,9 @@ } // ML-KEM-768 - const uint8_t *mlkem_encoded_public_key = encoded_public_key; - CBS cbs; - CBS_init(&cbs, mlkem_encoded_public_key, XWING_PUBLIC_KEY_BYTES); - CBS mlkem_cbs; - if (!CBS_get_bytes(&cbs, &mlkem_cbs, MLKEM768_PUBLIC_KEY_BYTES)) { - return 0; - } + static_assert(MLKEM768_PUBLIC_KEY_BYTES <= XWING_PUBLIC_KEY_BYTES); + CBS_init(&mlkem_cbs, encoded_public_key, MLKEM768_PUBLIC_KEY_BYTES); BCM_mlkem768_public_key mlkem_public_key; if (!bcm_success( @@ -214,16 +211,16 @@ static int xwing_decap(uint8_t out_shared_secret[XWING_SHARED_SECRET_BYTES], const uint8_t ciphertext[XWING_CIPHERTEXT_BYTES], const struct private_key *private_key) { - // Define this upfront so that it doesn't cross a goto. + static_assert(XWING_CIPHERTEXT_BYTES >= MLKEM768_CIPHERTEXT_BYTES + 32); + const uint8_t *mlkem_ciphertext = ciphertext; const uint8_t *x25519_ciphertext = ciphertext + MLKEM768_CIPHERTEXT_BYTES; // ML-KEM-768 - const uint8_t *mlkem_ciphertext = ciphertext; uint8_t mlkem_shared_secret[MLKEM_SHARED_SECRET_BYTES]; if (!MLKEM768_decap(mlkem_shared_secret, mlkem_ciphertext, MLKEM768_CIPHERTEXT_BYTES, &private_key->mlkem_private_key)) { - goto error; + goto err; } // X25519 @@ -234,7 +231,7 @@ uint8_t x25519_shared_secret[32]; if (!X25519(x25519_shared_secret, private_key->x25519_private_key, x25519_ciphertext)) { - goto error; + goto err; } // Combine the shared secrets @@ -242,7 +239,7 @@ x25519_ciphertext, x25519_public_key); return 1; -error: +err: // In case of error, fill the shared secret with random bytes so that if the // caller forgets to check the return code: // - no intermediate information leaks,
diff --git a/crypto/xwing/xwing_test.cc b/crypto/xwing/xwing_test.cc index 916aee1..74dcdac 100644 --- a/crypto/xwing/xwing_test.cc +++ b/crypto/xwing/xwing_test.cc
@@ -22,31 +22,31 @@ namespace { TEST(XWingTest, EncapsulateDecapsulate) { - uint8_t public_key[1216]; + uint8_t public_key[XWING_PUBLIC_KEY_BYTES]; XWING_private_key private_key; ASSERT_TRUE(XWING_generate_key(public_key, &private_key)); - uint8_t ciphertext[1120]; - uint8_t shared_secret[32]; + uint8_t ciphertext[XWING_CIPHERTEXT_BYTES]; + uint8_t shared_secret[XWING_SHARED_SECRET_BYTES]; ASSERT_TRUE(XWING_encap(ciphertext, shared_secret, public_key)); - uint8_t decapsulated[32]; + uint8_t decapsulated[XWING_SHARED_SECRET_BYTES]; ASSERT_TRUE(XWING_decap(decapsulated, ciphertext, &private_key)); EXPECT_EQ(Bytes(decapsulated), Bytes(shared_secret)); } TEST(XWingTest, PublicFromPrivate) { - uint8_t public_key[1216]; + uint8_t public_key[XWING_PUBLIC_KEY_BYTES]; XWING_private_key private_key; ASSERT_TRUE(XWING_generate_key(public_key, &private_key)); - uint8_t public_key2[1216]; + uint8_t public_key2[XWING_PUBLIC_KEY_BYTES]; ASSERT_TRUE(XWING_public_from_private(public_key2, &private_key)); EXPECT_EQ(Bytes(public_key2), Bytes(public_key)); } TEST(XWingTest, MarshalParsePrivateKey) { - uint8_t public_key[1216]; + uint8_t public_key[XWING_PUBLIC_KEY_BYTES]; XWING_private_key private_key; ASSERT_TRUE(XWING_generate_key(public_key, &private_key)); @@ -64,11 +64,11 @@ ASSERT_TRUE(XWING_parse_private_key(&parsed_private_key, &cbs)); // Check that both have a consistent behavior. - uint8_t ciphertext[1120]; - uint8_t shared_secret[32]; + uint8_t ciphertext[XWING_CIPHERTEXT_BYTES]; + uint8_t shared_secret[XWING_SHARED_SECRET_BYTES]; ASSERT_TRUE(XWING_encap(ciphertext, shared_secret, public_key)); - uint8_t decapsulated[32]; + uint8_t decapsulated[XWING_SHARED_SECRET_BYTES]; ASSERT_TRUE(XWING_decap(decapsulated, ciphertext, &parsed_private_key)); EXPECT_EQ(Bytes(decapsulated), Bytes(shared_secret)); } @@ -77,11 +77,11 @@ // Taken from // https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-06, // Appendix C. - const uint8_t kPrivateKey[32] = { + const uint8_t kPrivateKey[XWING_PRIVATE_KEY_BYTES] = { 0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d, 0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e, 0xd7, 0x3b, 0x80, 0x93, 0xf6, 0xef, 0xbc, 0x88, 0xeb, 0x1a, 0x6e, 0xac, 0xfa, 0x66, 0xef, 0x26}; - const uint8_t kExpectedPublicKey[1216] = { + const uint8_t kExpectedPublicKey[XWING_PUBLIC_KEY_BYTES] = { 0xe2, 0x23, 0x6b, 0x35, 0xa8, 0xc2, 0x4b, 0x39, 0xb1, 0x0a, 0xa1, 0x32, 0x3a, 0x96, 0xa9, 0x19, 0xa2, 0xce, 0xd8, 0x84, 0x00, 0x63, 0x3a, 0x7b, 0x07, 0x13, 0x17, 0x13, 0xfc, 0x14, 0xb2, 0xb5, 0xb1, 0x9c, 0xfc, 0x3d, @@ -193,11 +193,11 @@ 0x9a, 0xfa, 0x2f, 0x75, 0xab, 0x91, 0x6a, 0x58, 0xd9, 0x74, 0x91, 0x88, 0x35, 0xd2, 0x5e, 0x6a, 0x43, 0x50, 0x85, 0xb2, }; - const uint8_t kExpectedSharedSecret[32] = { + const uint8_t kExpectedSharedSecret[XWING_SHARED_SECRET_BYTES] = { 0xd2, 0xdf, 0x05, 0x22, 0x12, 0x8f, 0x09, 0xdd, 0x8e, 0x2c, 0x92, 0xb1, 0xe9, 0x05, 0xc7, 0x93, 0xd8, 0xf5, 0x7a, 0x54, 0xc3, 0xda, 0x25, 0x86, 0x1f, 0x10, 0xbf, 0x4c, 0xa6, 0x13, 0xe3, 0x84}; - const uint8_t kExpectedCiphertext[1120] = { + const uint8_t kExpectedCiphertext[XWING_CIPHERTEXT_BYTES] = { 0xb8, 0x3a, 0xa8, 0x28, 0xd4, 0xd6, 0x2b, 0x9a, 0x83, 0xce, 0xff, 0xe1, 0xd3, 0xd3, 0xbb, 0x1e, 0xf3, 0x12, 0x64, 0x64, 0x3c, 0x07, 0x0c, 0x57, 0x98, 0x92, 0x7e, 0x41, 0xfb, 0x07, 0x91, 0x4a, 0x27, 0x3f, 0x8f, 0x96, @@ -298,18 +298,18 @@ XWING_private_key private_key; ASSERT_TRUE(XWING_parse_private_key(&private_key, &cbs)); - uint8_t public_key[1216]; + uint8_t public_key[XWING_PUBLIC_KEY_BYTES]; ASSERT_TRUE(XWING_public_from_private(public_key, &private_key)); EXPECT_EQ(Bytes(public_key), Bytes(kExpectedPublicKey)); - uint8_t ciphertext[1120]; - uint8_t shared_secret[32]; + uint8_t ciphertext[XWING_CIPHERTEXT_BYTES]; + uint8_t shared_secret[XWING_SHARED_SECRET_BYTES]; ASSERT_TRUE(XWING_encap_external_entropy(ciphertext, shared_secret, public_key, kEphemeralSeed)); EXPECT_EQ(Bytes(ciphertext), Bytes(kExpectedCiphertext)); EXPECT_EQ(Bytes(shared_secret), Bytes(kExpectedSharedSecret)); - uint8_t decapsulated[32]; + uint8_t decapsulated[XWING_SHARED_SECRET_BYTES]; ASSERT_TRUE(XWING_decap(decapsulated, ciphertext, &private_key)); EXPECT_EQ(Bytes(decapsulated), Bytes(shared_secret)); }