Merge pull request #21161 from jedisct1/mlkem-update

Update ML-KEM to the final specification
This commit is contained in:
Andrew Kelley 2024-08-22 12:54:40 -07:00 committed by GitHub
commit 205e17a73c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 23 deletions

View file

@ -74,8 +74,9 @@ pub const dh = struct {
/// Key Encapsulation Mechanisms. /// Key Encapsulation Mechanisms.
pub const kem = struct { pub const kem = struct {
pub const kyber_d00 = @import("crypto/ml_kem.zig").kyber_d00; pub const kyber_d00 = @import("crypto/ml_kem.zig").d00;
pub const ml_kem_01 = @import("crypto/ml_kem.zig").ml_kem_01; pub const ml_kem = @import("crypto/ml_kem.zig").nist;
pub const ml_kem_01 = @compileError("deprecated: final version of the specification has been published, use ml_kem instead");
}; };
/// Elliptic-curve arithmetic. /// Elliptic-curve arithmetic.

View file

@ -1,15 +1,8 @@
//! Implementation of the IND-CCA2 post-quantum secure key encapsulation mechanism (KEM) //! Implementation of the IND-CCA2 post-quantum secure key encapsulation mechanism (KEM)
//! ML-KEM (NIST FIPS-203 publication) and CRYSTALS-Kyber (v3.02/"draft00" CFRG draft). //! ML-KEM (NIST FIPS-203 publication) and CRYSTALS-Kyber (v3.02/"draft00" CFRG draft).
//! //!
//! The schemes are not finalized yet, and are still subject to breaking changes. //! The namespace `d00` refers to the version currently implemented, in accordance with the CFRG draft.
//! //! The `nist` namespace refers to the FIPS-203 publication.
//! The Kyber namespace suffix (currently `_d00`) refers to the version currently
//! implemented, in accordance with the draft.
//! The ML-KEM namespace suffix (currently `_01`) refers to the NIST FIPS-203 draft
//! published on August 24, 2023, with the unintentional transposition of  having been reverted.
//!
//! Suffixes may not be updated if new versions of the documents only include editorial changes.
//! The suffixes will be removed once the schemes are finalized.
//! //!
//! Quoting from the CFRG I-D: //! Quoting from the CFRG I-D:
//! //!
@ -148,7 +141,7 @@ const Params = struct {
dv: u8, dv: u8,
}; };
pub const kyber_d00 = struct { pub const d00 = struct {
pub const Kyber512 = Kyber(.{ pub const Kyber512 = Kyber(.{
.name = "Kyber512", .name = "Kyber512",
.k = 2, .k = 2,
@ -174,7 +167,7 @@ pub const kyber_d00 = struct {
}); });
}; };
pub const ml_kem_01 = struct { pub const nist = struct {
pub const MLKem512 = Kyber(.{ pub const MLKem512 = Kyber(.{
.name = "ML-KEM-512", .name = "ML-KEM-512",
.ml_kem = true, .ml_kem = true,
@ -204,12 +197,12 @@ pub const ml_kem_01 = struct {
}; };
const modes = [_]type{ const modes = [_]type{
kyber_d00.Kyber512, d00.Kyber512,
kyber_d00.Kyber768, d00.Kyber768,
kyber_d00.Kyber1024, d00.Kyber1024,
ml_kem_01.MLKem512, nist.MLKem512,
ml_kem_01.MLKem768, nist.MLKem768,
ml_kem_01.MLKem1024, nist.MLKem1024,
}; };
const h_length: usize = 32; const h_length: usize = 32;
const inner_seed_length: usize = 32; const inner_seed_length: usize = 32;
@ -505,7 +498,10 @@ fn Kyber(comptime p: Params) type {
// Derives inner PKE keypair from given seed. // Derives inner PKE keypair from given seed.
fn innerKeyFromSeed(seed: [inner_seed_length]u8, pk: *InnerPk, sk: *InnerSk) void { fn innerKeyFromSeed(seed: [inner_seed_length]u8, pk: *InnerPk, sk: *InnerSk) void {
var expanded_seed: [64]u8 = undefined; var expanded_seed: [64]u8 = undefined;
sha3.Sha3_512.hash(&seed, &expanded_seed, .{}); var h = sha3.Sha3_512.init(.{});
if (p.ml_kem) h.update(&[1]u8{p.k});
h.update(&seed);
h.final(&expanded_seed);
pk.rho = expanded_seed[0..32].*; pk.rho = expanded_seed[0..32].*;
const sigma = expanded_seed[32..64]; const sigma = expanded_seed[32..64];
pk.aT = M.uniform(pk.rho, false); // Expand ρ to A; we'll transpose later on pk.aT = M.uniform(pk.rho, false); // Expand ρ to A; we'll transpose later on
@ -1722,9 +1718,9 @@ const sha2 = crypto.hash.sha2;
test "NIST KAT test" { test "NIST KAT test" {
inline for (.{ inline for (.{
.{ kyber_d00.Kyber512, "e9c2bd37133fcb40772f81559f14b1f58dccd1c816701be9ba6214d43baf4547" }, .{ d00.Kyber512, "e9c2bd37133fcb40772f81559f14b1f58dccd1c816701be9ba6214d43baf4547" },
.{ kyber_d00.Kyber1024, "89248f2f33f7f4f7051729111f3049c409a933ec904aedadf035f30fa5646cd5" }, .{ d00.Kyber1024, "89248f2f33f7f4f7051729111f3049c409a933ec904aedadf035f30fa5646cd5" },
.{ kyber_d00.Kyber768, "a1e122cad3c24bc51622e4c242d8b8acbcd3f618fee4220400605ca8f9ea02c2" }, .{ d00.Kyber768, "a1e122cad3c24bc51622e4c242d8b8acbcd3f618fee4220400605ca8f9ea02c2" },
}) |modeHash| { }) |modeHash| {
const mode = modeHash[0]; const mode = modeHash[0];
var seed: [48]u8 = undefined; var seed: [48]u8 = undefined;