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; }