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