@@ -27,6 +27,7 @@ pub(crate) const ROOT_OF_UNITY: i32 = 1753;
2727pub const SEED_LEN : usize = 32 ;
2828pub const RND_LEN : usize = 32 ;
2929pub const TR_LEN : usize = 64 ;
30+ pub const MU_LEN : usize = 64 ;
3031pub ( crate ) const POLY_T1PACKED_LEN : usize = 320 ;
3132pub ( crate ) const POLY_T0PACKED_LEN : usize = 416 ;
3233
@@ -287,7 +288,7 @@ impl<
287288 /// specifically takes a 32-byte [KeyMaterial256] and checks that it has [KeyType::Seed] and
288289 /// [SecurityStrength::_256bit].
289290 /// If you happen to have your seed in a larger KeyMaterial, you'll have to copy it using
290- /// [KeyMaterial::from_key] -- todo: make sure this works and copies key type and security strength correctly.
291+ /// [KeyMaterial::from_key]
291292 fn keygen_internal (
292293 seed : & KeyMaterial256 ,
293294 ) -> Result <
@@ -312,15 +313,11 @@ impl<
312313 let mut rho_prime: [ u8 ; 64 ] = [ 0u8 ; 64 ] ;
313314 let mut K : [ u8 ; 32 ] = [ 0u8 ; 32 ] ;
314315
315- // TODO: optimization: re-use variables rather than allocating new ones?
316- // TODO: do with benches because it might not actually be faster. Rust seems to like local vars.
317-
318316 let mut h = H :: default ( ) ;
319317 h. absorb ( seed. ref_to_bytes ( ) ) ;
320318 h. absorb ( & ( k as u8 ) . to_le_bytes ( ) ) ;
321319 h. absorb ( & ( l as u8 ) . to_le_bytes ( ) ) ;
322320 let bytes_written = h. squeeze_out ( & mut rho) ;
323- debug_assert_eq ! ( bytes_written, 32 ) ; // todo: remove these asserts once we have unit tests that pass?
324321 let bytes_written = h. squeeze_out ( & mut rho_prime) ;
325322 debug_assert_eq ! ( bytes_written, 64 ) ;
326323 let bytes_written = h. squeeze_out ( & mut K ) ;
@@ -421,14 +418,17 @@ impl<
421418 /// (in which case a keygen_from_seed is run and then the pk's compared).
422419 ///
423420 /// Returns either `()` or [SignatureError::ConsistencyCheckFailed].
424- ///
425- /// TODO -- sync with openssl implementation
426- /// TODO -- https://github.com/openssl/openssl/blob/master/crypto/ml_dsa/ml_dsa_key.c#L385
427421 pub fn keypair_consistency_check (
428422 pk : & PK ,
429423 sk : & SK ,
430424 ) -> Result < ( ) , SignatureError > {
431- todo ! ( )
425+ // This is maybe a computationally heavy way to compare them, but it works
426+ let derived_pk = sk. derive_public_key ( ) ;
427+ if derived_pk. compute_tr ( ) == pk. compute_tr ( ) {
428+ Ok ( ( ) )
429+ } else {
430+ Err ( SignatureError :: ConsistencyCheckFailed ( ) )
431+ }
432432 }
433433
434434 /// This provides the first half of the "External Mu" interface to ML-DSA which is described
@@ -465,8 +465,8 @@ impl<
465465 pub fn compute_mu_from_tr (
466466 msg : & [ u8 ] ,
467467 ctx : Option < & [ u8 ] > ,
468- tr : & [ u8 ; 64 ] ,
469- ) -> Result < [ u8 ; 64 ] , SignatureError > {
468+ tr : & [ u8 ; TR_LEN ] ,
469+ ) -> Result < [ u8 ; TR_LEN ] , SignatureError > {
470470 MuBuilder :: compute_mu ( msg, ctx, tr)
471471 }
472472
@@ -475,7 +475,7 @@ impl<
475475 msg : & [ u8 ] ,
476476 ctx : Option < & [ u8 ] > ,
477477 pk : & PK ,
478- ) -> Result < [ u8 ; 64 ] , SignatureError > {
478+ ) -> Result < [ u8 ; MU_LEN ] , SignatureError > {
479479 MuBuilder :: compute_mu ( msg, ctx, & pk. compute_tr ( ) )
480480 }
481481
@@ -494,7 +494,7 @@ impl<
494494 /// This mode uses randomized signing (called "hedged mode" in FIPS 204) using an internal RNG.
495495 fn sign_mu (
496496 sk : & SK ,
497- mu : & [ u8 ; 64 ] ,
497+ mu : & [ u8 ; MU_LEN ] ,
498498 ) -> Result < [ u8 ; SIG_LEN ] , SignatureError > {
499499 let mut out: [ u8 ; SIG_LEN ] = [ 0u8 ; SIG_LEN ] ;
500500 Self :: sign_mu_out ( sk, mu, & mut out) ?;
@@ -509,10 +509,10 @@ impl<
509509 /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
510510 fn sign_mu_out (
511511 sk : & SK ,
512- mu : & [ u8 ; 64 ] ,
512+ mu : & [ u8 ; MU_LEN ] ,
513513 output : & mut [ u8 ; SIG_LEN ] ,
514514 ) -> Result < usize , SignatureError > {
515- let mut rnd: [ u8 ; 32 ] = [ 0u8 ; 32 ] ;
515+ let mut rnd: [ u8 ; RND_LEN ] = [ 0u8 ; RND_LEN ] ;
516516 HashDRBG_SHA512 :: new_from_os ( ) . next_bytes_out ( & mut rnd) ?;
517517
518518 Self :: sign_mu_deterministic_out ( sk, mu, rnd, output)
@@ -553,8 +553,8 @@ impl<
553553 /// Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
554554 pub ( crate ) fn sign_mu_deterministic_out (
555555 sk : & SK ,
556- mu : & [ u8 ; 64 ] ,
557- rnd : [ u8 ; 32 ] ,
556+ mu : & [ u8 ; MU_LEN ] ,
557+ rnd : [ u8 ; RND_LEN ] ,
558558 output : & mut [ u8 ; SIG_LEN ] ,
559559 ) -> Result < usize , SignatureError > {
560560 // 1: (π, πΎ, π‘π, π¬1, π¬2, π0) β skDecode(π π)
@@ -608,9 +608,6 @@ impl<
608608 // 11: π² β π
^β β ExpandMask(πβ³, π
)
609609 let mut y = expand_mask :: < l , GAMMA1 , GAMMA1_MASK_LEN > ( & rho_p_p, kappa) ;
610610
611- // last use of rho_p_p, so zeroizing it
612- rho_p_p. fill ( 0u8 ) ;
613-
614611 // 12: π° β NTTβ1(π_hat * NTT(π²))
615612 let mut y_hat = y. clone ( ) ;
616613 y_hat. ntt ( ) ;
@@ -696,12 +693,16 @@ impl<
696693 } ;
697694
698695 // "In addition, there is an alternative way of implementing the validity checks on π³ and the computation of
699- // π‘, which is described in Section 5.1 of. This method may also be used in implementations of ML-DSA."
700- // todo -- check this out
696+ // π‘, which is described in Section 5.1 of [6] (dilithium-specification-round3-20210208.pdf).
697+ // This method may also be used in implementations of ML-DSA."
698+ // todo -- I believe this code is already using this optimization, but it could use a deeper look to see if more optimization is possible.
701699
702700 break ;
703701 }
704702
703+ // zeroize rho_p_p before returning it to the OS
704+ rho_p_p. fill ( 0u8 ) ;
705+
705706 // 33: π β sigEncode(π, π³Μ modΒ±π, π‘)
706707 let bytes_written = sig_encode :: < GAMMA1 , k , l , LAMBDA_over_4 , OMEGA , POLY_Z_PACKED_LEN , SIG_LEN >
707708 ( & sig_val_c_tilde, & sig_val_z, & sig_val_h, output) ;
@@ -721,7 +722,7 @@ impl<
721722 /// Input: Signature π β πΉπ/4+ββ
32β
(1+bitlen (πΎ1β1))+π+π.
722723 fn verify_mu_internal (
723724 pk : & PK ,
724- mu : & [ u8 ; 64 ] ,
725+ mu : & [ u8 ; MU_LEN ] ,
725726 sig : & [ u8 ; SIG_LEN ] ,
726727 ) -> bool {
727728 // 1: (π, π1) β pkDecode(ππ)
0 commit comments