| ... | @@ -329,17 +329,19 @@ fn Kyber(comptime p: Params) type { | ... | @@ -329,17 +329,19 @@ fn Kyber(comptime p: Params) type { |
| 329 | // ct' = innerEnc(pk, m', r') | 329 | // ct' = innerEnc(pk, m', r') |
| 330 | const ct2 = sk.pk.encrypt(&m2, kr2[32..64]); | 330 | const ct2 = sk.pk.encrypt(&m2, kr2[32..64]); |
| 331 | | 331 | |
| 332 | // Compute H(ct) and put in the second slot of kr2 which will be (K'', H(ct)). | | |
| 333 | sha3.Sha3_256.hash(ct, kr2[32..], .{}); | | |
| 334 | | | |
| 335 | // Replace K'' by z in the first slot of kr2 if ct ≠ ct'. | | |
| 336 | cmov(32, kr2[0..32], sk.z, ctneq(ciphertext_length, ct.*, ct2)); | | |
| 337 | | | |
| 338 | if (p.ml_kem) { | 332 | if (p.ml_kem) { |
| 339 | // ML-KEM: K = K''/z | 333 | // ML-KEM: K = K'' if ct == ct', else K = J(z || c) per FIPS 203 |
| | 334 | var k_bar: [shared_length]u8 = undefined; |
| | 335 | var j = sha3.Shake256.init(.{}); |
| | 336 | j.update(&sk.z); |
| | 337 | j.update(ct); |
| | 338 | j.squeeze(&k_bar); |
| | 339 | cmov(shared_length, kr2[0..shared_length], k_bar, ctneq(ciphertext_length, ct.*, ct2)); |
| 340 | return kr2[0..shared_length].*; | 340 | return kr2[0..shared_length].*; |
| 341 | } else { | 341 | } else { |
| 342 | // Kyber: K = KDF(K''/z ‖ H(c)) | 342 | // Kyber: K = KDF(K''/z ‖ H(c)) |
| | 343 | sha3.Sha3_256.hash(ct, kr2[32..], .{}); |
| | 344 | cmov(32, kr2[0..32], sk.z, ctneq(ciphertext_length, ct.*, ct2)); |
| 343 | var ss: [shared_length]u8 = undefined; | 345 | var ss: [shared_length]u8 = undefined; |
| 344 | sha3.Shake256.hash(&kr2, &ss, .{}); | 346 | sha3.Shake256.hash(&kr2, &ss, .{}); |
| 345 | return ss; | 347 | return ss; |