Name the hash functions in the Kyber implementation
When I was experimenting with different hash functions, it was useful to
split them out, and I think this is clearer anyway. E.g. there are two
uses of SHAKE-256 in the round3 submission, but the spec gives them
different names.
XOF doesn't get its own abstraction because we need to stream data out
of it.
ML-KEM similarly names things, though it will replace the KDF with a
hash J that only gets applied to the rejection value.
Change-Id: I67f1ac0216e05f61557023229572ff5fb36ed529
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64407
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/kyber/kyber.c b/crypto/kyber/kyber.c
index 5d7971f..e9e3a91 100644
--- a/crypto/kyber/kyber.c
+++ b/crypto/kyber/kyber.c
@@ -28,6 +28,22 @@
// See
// https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf
+static void prf(uint8_t *out, size_t out_len, const uint8_t in[33]) {
+ BORINGSSL_keccak(out, out_len, in, 33, boringssl_shake256);
+}
+
+static void hash_h(uint8_t out[32], const uint8_t *in, size_t len) {
+ BORINGSSL_keccak(out, 32, in, len, boringssl_sha3_256);
+}
+
+static void hash_g(uint8_t out[64], const uint8_t *in, size_t len) {
+ BORINGSSL_keccak(out, 64, in, len, boringssl_sha3_512);
+}
+
+static void kdf(uint8_t *out, size_t out_len, const uint8_t *in, size_t len) {
+ BORINGSSL_keccak(out, out_len, in, len, boringssl_shake256);
+}
+
#define DEGREE 256
#define RANK 3
@@ -315,7 +331,7 @@
scalar *out, const uint8_t input[33]) {
uint8_t entropy[128];
static_assert(sizeof(entropy) == 2 * /*kEta=*/2 * DEGREE / 8, "");
- BORINGSSL_keccak(entropy, sizeof(entropy), input, 33, boringssl_shake256);
+ prf(entropy, sizeof(entropy), input);
for (int i = 0; i < DEGREE; i += 2) {
uint8_t byte = entropy[i / 2];
@@ -611,7 +627,7 @@
const uint8_t entropy[KYBER_GENERATE_KEY_ENTROPY]) {
struct private_key *priv = private_key_from_external(out_private_key);
uint8_t hashed[64];
- BORINGSSL_keccak(hashed, sizeof(hashed), entropy, 32, boringssl_sha3_512);
+ hash_g(hashed, entropy, 32);
const uint8_t *const rho = hashed;
const uint8_t *const sigma = hashed + 32;
OPENSSL_memcpy(priv->pub.rho, hashed, sizeof(priv->pub.rho));
@@ -631,9 +647,8 @@
abort();
}
- BORINGSSL_keccak(priv->pub.public_key_hash, sizeof(priv->pub.public_key_hash),
- out_encoded_public_key, KYBER_PUBLIC_KEY_BYTES,
- boringssl_sha3_256);
+ hash_h(priv->pub.public_key_hash, out_encoded_public_key,
+ KYBER_PUBLIC_KEY_BYTES);
OPENSSL_memcpy(priv->fo_failure_secret, entropy + 32, 32);
}
@@ -707,14 +722,11 @@
OPENSSL_memcpy(input + KYBER_ENCAP_ENTROPY, pub->public_key_hash,
sizeof(input) - KYBER_ENCAP_ENTROPY);
uint8_t prekey_and_randomness[64];
- BORINGSSL_keccak(prekey_and_randomness, sizeof(prekey_and_randomness), input,
- sizeof(input), boringssl_sha3_512);
+ hash_g(prekey_and_randomness, input, sizeof(input));
encrypt_cpa(out_ciphertext, pub, entropy, prekey_and_randomness + 32);
- BORINGSSL_keccak(prekey_and_randomness + 32, 32, out_ciphertext,
- KYBER_CIPHERTEXT_BYTES, boringssl_sha3_256);
- BORINGSSL_keccak(out_shared_secret, KYBER_SHARED_SECRET_BYTES,
- prekey_and_randomness, sizeof(prekey_and_randomness),
- boringssl_shake256);
+ hash_h(prekey_and_randomness + 32, out_ciphertext, KYBER_CIPHERTEXT_BYTES);
+ kdf(out_shared_secret, KYBER_SHARED_SECRET_BYTES, prekey_and_randomness,
+ sizeof(prekey_and_randomness));
}
// Algorithm 6 of the Kyber spec.
@@ -749,8 +761,7 @@
OPENSSL_memcpy(decrypted + 32, priv->pub.public_key_hash,
sizeof(decrypted) - 32);
uint8_t prekey_and_randomness[64];
- BORINGSSL_keccak(prekey_and_randomness, sizeof(prekey_and_randomness),
- decrypted, sizeof(decrypted), boringssl_sha3_512);
+ hash_g(prekey_and_randomness, decrypted, sizeof(decrypted));
uint8_t expected_ciphertext[KYBER_CIPHERTEXT_BYTES];
encrypt_cpa(expected_ciphertext, &priv->pub, decrypted,
prekey_and_randomness + 32);
@@ -763,10 +774,8 @@
input[i] = constant_time_select_8(mask, prekey_and_randomness[i],
priv->fo_failure_secret[i]);
}
- BORINGSSL_keccak(input + 32, 32, ciphertext, KYBER_CIPHERTEXT_BYTES,
- boringssl_sha3_256);
- BORINGSSL_keccak(out_shared_secret, KYBER_SHARED_SECRET_BYTES, input,
- sizeof(input), boringssl_shake256);
+ hash_h(input + 32, ciphertext, KYBER_CIPHERTEXT_BYTES);
+ kdf(out_shared_secret, KYBER_SHARED_SECRET_BYTES, input, sizeof(input));
}
int KYBER_marshal_public_key(CBB *out,
@@ -794,8 +803,7 @@
CBS_len(in) != 0) {
return 0;
}
- BORINGSSL_keccak(pub->public_key_hash, sizeof(pub->public_key_hash),
- CBS_data(&orig_in), CBS_len(&orig_in), boringssl_sha3_256);
+ hash_h(pub->public_key_hash, CBS_data(&orig_in), CBS_len(&orig_in));
return 1;
}