@@ -444,13 +444,18 @@ __contract__(
444444)
445445{
446446 MLD_ALIGN uint8_t challenge_bytes [MLDSA_CTILDEBYTES ];
447- unsigned int n ;
447+ unsigned int n , i ;
448448 union
449449 {
450- mld_polyvecl z ;
451- mld_polyvecl s1 ;
450+ mld_poly z ;
451+ mld_poly s1 ;
452452 } zs1 ;
453- mld_polyveck w1 , w0 ;
453+ mld_polyveck w0 ;
454+ union
455+ {
456+ mld_polyveck w1 ;
457+ mld_polyvecl tmp ;
458+ } w1tmp ;
454459
455460 union
456461 {
@@ -468,16 +473,16 @@ __contract__(
468473 mld_polyvecl_uniform_gamma1 (& yht0s2 .y , rhoprime , nonce );
469474
470475 /* Matrix-vector multiplication */
471- zs1 . z = yht0s2 .y ;
472- mld_polyvecl_ntt (& zs1 . z );
473- mld_polyvec_matrix_pointwise_montgomery (& w0 , mat , & zs1 . z );
476+ w1tmp . tmp = yht0s2 .y ;
477+ mld_polyvecl_ntt (& w1tmp . tmp );
478+ mld_polyvec_matrix_pointwise_montgomery (& w0 , mat , & w1tmp . tmp );
474479 mld_polyveck_reduce (& w0 );
475480 mld_polyveck_invntt_tomont (& w0 );
476481
477482 /* Decompose w and call the random oracle */
478483 mld_polyveck_caddq (& w0 );
479- mld_polyveck_decompose (& w1 , & w0 );
480- mld_polyveck_pack_w1 (sig , & w1 );
484+ mld_polyveck_decompose (& w1tmp . w1 , & w0 );
485+ mld_polyveck_pack_w1 (sig , & w1tmp . w1 );
481486
482487 mld_H (challenge_bytes , MLDSA_CTILDEBYTES , mu , MLDSA_CRHBYTES , sig ,
483488 MLDSA_K * MLDSA_POLYW1_PACKEDBYTES , NULL , 0 );
@@ -490,31 +495,36 @@ __contract__(
490495 mld_poly_ntt (& cp );
491496
492497 /* Compute z, reject if it reveals secret */
493- mld_polyvecl_unpack_eta (
494- & zs1 .s1 , sk + MLDSA_SEEDBYTES + MLDSA_SEEDBYTES + MLDSA_TRBYTES );
495- mld_polyvecl_ntt (& zs1 .s1 );
496- mld_polyvecl_pointwise_poly_montgomery (& zs1 .z , & cp , & zs1 .s1 );
497- mld_polyvecl_invntt_tomont (& zs1 .z );
498- mld_polyvecl_add (& zs1 .z , & yht0s2 .y );
499- mld_polyvecl_reduce (& zs1 .z );
500-
501- z_invalid = mld_polyvecl_chknorm (& zs1 .z , MLDSA_GAMMA1 - MLDSA_BETA );
502- /* Constant time: It is fine (and prohibitively expensive to avoid)
503- * leaking the result of the norm check. In case of rejection it
504- * would even be okay to leak which coefficient led to rejection
505- * as the candidate signature will be discarded anyway.
506- * See Section 5.5 of @[Round3_Spec]. */
507- MLD_CT_TESTING_DECLASSIFY (& z_invalid , sizeof (uint32_t ));
508- if (z_invalid )
498+ for (i = 0 ; i < MLDSA_L ; i ++ )
509499 {
510- res = -1 ; /* reject */
511- goto cleanup ;
512- }
500+ mld_polyeta_unpack (& zs1 .s1 , sk + MLDSA_SEEDBYTES + MLDSA_SEEDBYTES +
501+ MLDSA_TRBYTES +
502+ i * MLDSA_POLYETA_PACKEDBYTES );
503+ mld_poly_ntt (& zs1 .s1 );
504+ mld_poly_pointwise_montgomery (& zs1 .z , & cp , & zs1 .s1 );
505+ mld_poly_invntt_tomont (& zs1 .z );
506+ mld_poly_add (& zs1 .z , & yht0s2 .y .vec [i ]);
507+ mld_poly_reduce (& zs1 .z );
508+
509+ z_invalid = mld_poly_chknorm (& zs1 .z , MLDSA_GAMMA1 - MLDSA_BETA );
510+ /* Constant time: It is fine (and prohibitively expensive to avoid)
511+ * leaking the result of the norm check. In case of rejection it
512+ * would even be okay to leak which coefficient led to rejection
513+ * as the candidate signature will be discarded anyway.
514+ * See Section 5.5 of @[Round3_Spec]. */
515+ MLD_CT_TESTING_DECLASSIFY (& z_invalid , sizeof (uint32_t ));
516+ if (z_invalid )
517+ {
518+ res = -1 ; /* reject */
519+ goto cleanup ;
520+ }
513521
514- /* If z is valid, then its coefficients are bounded by */
515- /* MLDSA_GAMMA1 - MLDSA_BETA. This will be needed below */
516- /* to prove the pre-condition of pack_sig() */
517- mld_assert_abs_bound_2d (z .vec , MLDSA_L , MLDSA_N , (MLDSA_GAMMA1 - MLDSA_BETA ));
522+ /* If z is valid, then its coefficients are bounded by */
523+ /* MLDSA_GAMMA1 - MLDSA_BETA. This will be needed below */
524+ /* to prove the pre-condition of pack_sig() */
525+ mld_assert_abs_bound (& zs1 .z , MLDSA_N , (MLDSA_GAMMA1 - MLDSA_BETA ));
526+ mld_pack_sig_z (sig , & zs1 .z , i );
527+ }
518528
519529 /* Check that subtracting cs2 does not change high bits of w and low bits
520530 * do not reveal secret information */
@@ -568,7 +578,7 @@ __contract__(
568578 */
569579 MLD_CT_TESTING_DECLASSIFY (& w0 , sizeof (w0 ));
570580 MLD_CT_TESTING_DECLASSIFY (& w1 , sizeof (w1 ));
571- n = mld_polyveck_make_hint (& yht0s2 .h , & w0 , & w1 );
581+ n = mld_polyveck_make_hint (& yht0s2 .h , & w0 , & w1tmp . w1 );
572582 if (n > MLDSA_OMEGA )
573583 {
574584 res = -1 ; /* reject */
@@ -580,16 +590,16 @@ __contract__(
580590 * can, hence, be considered public. */
581591 MLD_CT_TESTING_DECLASSIFY (& h , sizeof (h ));
582592 MLD_CT_TESTING_DECLASSIFY (& zs1 .z , sizeof (mld_polyvecl ));
583- mld_pack_sig (sig , challenge_bytes , & zs1 . z , & yht0s2 .h , n );
593+ mld_pack_sig (sig , challenge_bytes , & yht0s2 .h , n );
584594
585595 res = 0 ; /* success */
586596
587597cleanup :
588598 /* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
589599 mld_zeroize (challenge_bytes , MLDSA_CTILDEBYTES );
590600 mld_zeroize (& zs1 , sizeof (zs1 ));
591- mld_zeroize (& w1 , sizeof (w1 ));
592601 mld_zeroize (& w0 , sizeof (w0 ));
602+ mld_zeroize (& w1tmp , sizeof (w1tmp ));
593603 mld_zeroize (& yht0s2 , sizeof (yht0s2 ));
594604 mld_zeroize (& cp , sizeof (cp ));
595605
0 commit comments