@@ -655,6 +655,48 @@ void mld_polyt0_unpack(mld_poly *r, const uint8_t a[MLDSA_POLYT0_PACKEDBYTES])
655655 (1 << (MLDSA_D - 1 )) + 1 );
656656}
657657
658+ MLD_STATIC_TESTABLE uint32_t mld_poly_chknorm_c (const mld_poly * a , int32_t B )
659+ __contract__ (
660+ requires (memory_no_alias (a , sizeof (mld_poly )))
661+ requires (0 <= B && B <= MLDSA_Q - REDUCE32_RANGE_MAX )
662+ requires (array_bound (a - > coeffs , 0 , MLDSA_N , - REDUCE32_RANGE_MAX , REDUCE32_RANGE_MAX ))
663+ ensures (return_value == 0 || return_value == 0xFFFFFFFF )
664+ ensures ((return_value == 0 ) == array_abs_bound (a - > coeffs , 0 , MLDSA_N , B ))
665+ )
666+ {
667+ unsigned int i ;
668+ uint32_t t = 0 ;
669+ mld_assert_bound (a -> coeffs , MLDSA_N , - REDUCE32_RANGE_MAX , REDUCE32_RANGE_MAX );
670+ for (i = 0 ; i < MLDSA_N ; ++ i )
671+ __loop__ (
672+ invariant (i <= MLDSA_N )
673+ invariant (t == 0 || t == 0xFFFFFFFF )
674+ invariant ((t == 0 ) == array_abs_bound (a -> coeffs , 0 , i , B ))
675+ )
676+ {
677+ /*
678+ * Since we know that -REDUCE32_RANGE_MAX <= a < REDUCE32_RANGE_MAX,
679+ * and B <= MLDSA_Q - REDUCE32_RANGE_MAX, to check if
680+ * -B < (a mod± MLDSA_Q) < B, it suffices to check if -B < a < B.
681+ *
682+ * We prove this to be true using the following CBMC assertions.
683+ * a ==> b expressed as !a || b to also allow run-time assertion.
684+ */
685+ mld_assert (a -> coeffs [i ] < B || a -> coeffs [i ] - MLDSA_Q <= - B );
686+ mld_assert (a -> coeffs [i ] > - B || a -> coeffs [i ] + MLDSA_Q >= B );
687+
688+ /* Reference: Leaks which coefficient violates the bound via a conditional.
689+ * We are more conservative to reduce the number of declassifications in
690+ * constant-time testing.
691+ */
692+
693+ /* if (abs(a[i]) >= B) */
694+ t |= mld_ct_cmask_neg_i32 (B - 1 - mld_ct_abs_i32 (a -> coeffs [i ]));
695+ }
696+
697+ return t ;
698+ }
699+
658700/* Reference: explicitly checks the bound B to be <= (MLDSA_Q - 1) / 8).
659701 * This is unnecessary as it's always a compile-time constant.
660702 * We instead model it as a precondition.
@@ -668,8 +710,6 @@ void mld_polyt0_unpack(mld_poly *r, const uint8_t a[MLDSA_POLYT0_PACKEDBYTES])
668710MLD_INTERNAL_API
669711uint32_t mld_poly_chknorm (const mld_poly * a , int32_t B )
670712{
671- unsigned int i ;
672- uint32_t t = 0 ;
673713 mld_assert_bound (a -> coeffs , MLDSA_N , - REDUCE32_RANGE_MAX , REDUCE32_RANGE_MAX );
674714#if defined(MLD_USE_NATIVE_POLY_CHKNORM )
675715 {
@@ -699,34 +739,7 @@ uint32_t mld_poly_chknorm(const mld_poly *a, int32_t B)
699739 }
700740 }
701741#endif /* MLD_USE_NATIVE_POLY_CHKNORM */
702- for (i = 0 ; i < MLDSA_N ; ++ i )
703- __loop__ (
704- invariant (i <= MLDSA_N )
705- invariant (t == 0 || t == 0xFFFFFFFF )
706- invariant ((t == 0 ) == array_abs_bound (a -> coeffs , 0 , i , B ))
707- )
708- {
709- /*
710- * Since we know that -REDUCE32_RANGE_MAX <= a < REDUCE32_RANGE_MAX,
711- * and B <= MLDSA_Q - REDUCE32_RANGE_MAX, to check if
712- * -B < (a mod± MLDSA_Q) < B, it suffices to check if -B < a < B.
713- *
714- * We prove this to be true using the following CBMC assertions.
715- * a ==> b expressed as !a || b to also allow run-time assertion.
716- */
717- mld_assert (a -> coeffs [i ] < B || a -> coeffs [i ] - MLDSA_Q <= - B );
718- mld_assert (a -> coeffs [i ] > - B || a -> coeffs [i ] + MLDSA_Q >= B );
719-
720- /* Reference: Leaks which coefficient violates the bound via a conditional.
721- * We are more conservative to reduce the number of declassifications in
722- * constant-time testing.
723- */
724-
725- /* if (abs(a[i]) >= B) */
726- t |= mld_ct_cmask_neg_i32 (B - 1 - mld_ct_abs_i32 (a -> coeffs [i ]));
727- }
728-
729- return t ;
742+ return mld_poly_chknorm_c (a , B );
730743}
731744
732745#else /* !MLD_CONFIG_MULTILEVEL_NO_SHARED */
0 commit comments