88#include <stdint.h>
99#include "cbmc.h"
1010#include "common.h"
11+ #include "ct.h"
1112
1213#define MONT -4186625 /* 2^32 % MLDSA_Q */
1314
2425#define MONTGOMERY_REDUCE_STRONG_DOMAIN_MAX ((int64_t)INT32_MIN * -MLDSA_Q)
2526
2627
27- #define mld_montgomery_reduce MLD_NAMESPACE(montgomery_reduce)
28+
29+ /*************************************************
30+ * Name: mld_cast_uint32_to_int32
31+ *
32+ * Description: Cast uint32 value to int32
33+ *
34+ * Returns:
35+ * input x in 0 .. 2^31-1: returns value unchanged
36+ * input x in 2^31 .. 2^32-1: returns (x - 2^32)
37+ **************************************************/
38+ #ifdef CBMC
39+ #pragma CPROVER check push
40+ #pragma CPROVER check disable "conversion"
41+ #endif
42+ static MLD_INLINE int32_t mld_cast_uint32_to_int32 (uint32_t x )
43+ {
44+ /*
45+ * PORTABILITY: This relies on uint32_t -> int32_t
46+ * being implemented as the inverse of int32_t -> uint32_t,
47+ * which is implementation-defined (C99 6.3.1.3 (3))
48+ * CBMC (correctly) fails to prove this conversion is OK,
49+ * so we have to suppress that check here
50+ */
51+ return (int32_t )x ;
52+ }
53+ #ifdef CBMC
54+ #pragma CPROVER check pop
55+ #endif
56+
2857/*************************************************
2958 * Name: mld_montgomery_reduce
3059 *
4675 *
4776 * Returns r.
4877 **************************************************/
49- int32_t mld_montgomery_reduce (int64_t a )
78+ static MLD_INLINE int32_t mld_montgomery_reduce (int64_t a )
5079__contract__ (
5180 requires (a >= - MONTGOMERY_REDUCE_DOMAIN_MAX && a <= MONTGOMERY_REDUCE_DOMAIN_MAX )
5281 ensures (return_value >= INT32_MIN && return_value < REDUCE32_DOMAIN_MAX )
5382
5483 /* Special case - for stronger input bounds, we can ensure stronger bounds on the output */
5584 ensures ((a >= - MONTGOMERY_REDUCE_STRONG_DOMAIN_MAX && a < MONTGOMERY_REDUCE_STRONG_DOMAIN_MAX ) == >
5685 (return_value > - MLDSA_Q && return_value < MLDSA_Q ))
57- );
86+ )
87+ {
88+ /* check-magic: 58728449 == unsigned_mod(pow(MLDSA_Q, -1, 2^32), 2^32) */
89+ const uint64_t QINV = 58728449 ;
90+
91+ /* Compute a*q^{-1} mod 2^32 in unsigned representatives */
92+ const uint32_t a_reduced = a & UINT32_MAX ;
93+ const uint32_t a_inverted = (a_reduced * QINV ) & UINT32_MAX ;
94+
95+ /* Lift to signed canonical representative mod 2^32. */
96+ const int32_t t = mld_cast_uint32_to_int32 (a_inverted );
97+
98+ int64_t r ;
99+
100+ r = a - ((int64_t )t * MLDSA_Q );
101+
102+ /*
103+ * PORTABILITY: Right-shift on a signed integer is, strictly-speaking,
104+ * implementation-defined for negative left argument. Here,
105+ * we assume it's sign-preserving "arithmetic" shift right. (C99 6.5.7 (5))
106+ */
107+ r = r >> 32 ;
108+ return (int32_t )r ;
109+ }
58110
59- #define mld_reduce32 MLD_NAMESPACE(reduce32)
60111/*************************************************
61112 * Name: mld_reduce32
62113 *
@@ -68,14 +119,21 @@ __contract__(
68119 *
69120 * Returns r.
70121 **************************************************/
71- int32_t mld_reduce32 (int32_t a )
122+ static MLD_INLINE int32_t mld_reduce32 (int32_t a )
72123__contract__ (
73124 requires (a <= REDUCE32_DOMAIN_MAX )
74125 ensures (return_value >= - REDUCE32_RANGE_MAX )
75126 ensures (return_value < REDUCE32_RANGE_MAX )
76- );
127+ )
128+ {
129+ int32_t t ;
130+
131+ t = (a + (1 << 22 )) >> 23 ;
132+ t = a - t * MLDSA_Q ;
133+ cassert ((t - a ) % MLDSA_Q == 0 );
134+ return t ;
135+ }
77136
78- #define mld_caddq MLD_NAMESPACE(caddq)
79137/*************************************************
80138 * Name: mld_caddq
81139 *
@@ -85,14 +143,17 @@ __contract__(
85143 *
86144 * Returns r.
87145 **************************************************/
88- int32_t mld_caddq (int32_t a )
146+ static MLD_INLINE int32_t mld_caddq (int32_t a )
89147__contract__ (
90148 requires (a > - MLDSA_Q )
91149 requires (a < MLDSA_Q )
92150 ensures (return_value >= 0 )
93151 ensures (return_value < MLDSA_Q )
94152 ensures (return_value == (a >= 0 ) ? a : (a + MLDSA_Q ))
95- );
153+ )
154+ {
155+ return mld_ct_sel_int32 (a + MLDSA_Q , a , mld_ct_cmask_neg_i32 (a ));
156+ }
96157
97158
98159#endif /* !MLD_REDUCE_H */
0 commit comments