-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathreduce.h
More file actions
139 lines (122 loc) · 4.32 KB
/
reduce.h
File metadata and controls
139 lines (122 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
* Copyright (c) The mldsa-native project authors
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
*/
#ifndef MLD_REDUCE_H
#define MLD_REDUCE_H
#include "cbmc.h"
#include "common.h"
#include "ct.h"
#include "debug.h"
/* check-magic: -4186625 == pow(2,32,MLDSA_Q) */
#define MLD_MONT -4186625
/* Upper bound for domain of mld_reduce32() */
#define MLD_REDUCE32_DOMAIN_MAX (INT32_MAX - (1 << 22))
/* Absolute bound for range of mld_reduce32() */
/* check-magic: 6283009 == (MLD_REDUCE32_DOMAIN_MAX - 255 * MLDSA_Q + 1) */
#define MLD_REDUCE32_RANGE_MAX 6283009
/*************************************************
* Name: mld_montgomery_reduce
*
* Description: Generic Montgomery reduction; given a 64-bit integer a, computes
* 32-bit integer congruent to a * R^-1 mod q, where R=2^32
*
* Arguments: - int64_t a: input integer to be reduced, of absolute value
* smaller or equal to INT64_MAX - 2^31 * MLDSA_Q.
*
* Returns: Integer congruent to a * R^-1 modulo q, with absolute value
* <= |a| / 2^32 + MLDSA_Q / 2
*
* In particular, if |a| < 2^31 * MLDSA_Q, the absolute value
* of the return value is < MLDSA_Q.
**************************************************/
MLD_MUST_CHECK_RETURN_VALUE
static MLD_INLINE int32_t mld_montgomery_reduce(int64_t a)
__contract__(
/* We don't attempt to express an input-dependent output bound
* as the post-condition here, as all call-sites satisfy the
* absolute input bound 2^31 * MLDSA_Q and higher-level
* reasoning can be conducted using |return_value| < MLDSA_Q. */
requires(a > -(((int64_t)1 << 31) * MLDSA_Q) &&
a < (((int64_t)1 << 31) * MLDSA_Q))
ensures(return_value > -MLDSA_Q && return_value < MLDSA_Q)
)
{
/* check-magic: 58728449 == unsigned_mod(pow(MLDSA_Q, -1, 2^32), 2^32) */
const uint64_t QINV = 58728449;
/* Compute a*q^{-1} mod 2^32 in unsigned representatives */
const uint32_t a_reduced = mld_cast_int64_to_uint32(a);
const uint32_t a_inverted = (a_reduced * QINV) & UINT32_MAX;
/* Lift to signed canonical representative mod 2^32. */
const int32_t t = mld_cast_uint32_to_int32(a_inverted);
int64_t r;
mld_assert(a < +(INT64_MAX - (((int64_t)1 << 31) * MLDSA_Q)) &&
a > -(INT64_MAX - (((int64_t)1 << 31) * MLDSA_Q)));
r = a - (int64_t)t * MLDSA_Q;
/*
* PORTABILITY: Right-shift on a signed integer is, strictly-speaking,
* implementation-defined for negative left argument. Here,
* we assume it's sign-preserving "arithmetic" shift right. (C99 6.5.7 (5))
*/
r = r >> 32;
/* Bounds:
*
* By construction of the Montgomery multiplication, by the time we
* compute r >> 32, r is divisible by 2^32, and hence
*
* |r >> 32| = |r| / 2^32
* <= |a| / 2^32 + MLDSA_Q / 2
*
* (In general, we would only have |x >> n| <= ceil(|x| / 2^n)).
*
* In particular, if |a| < 2^31 * MLDSA_Q, then |return_value| < MLDSA_Q.
*/
return (int32_t)r;
}
/*************************************************
* Name: mld_reduce32
*
* Description: For finite field element a with a <= 2^{31} - 2^{22} - 1,
* compute r \equiv a (mod MLDSA_Q) such that
* -MLD_REDUCE32_RANGE_MAX <= r < MLD_REDUCE32_RANGE_MAX.
*
* Arguments: - int32_t: finite field element a
*
* Returns r.
**************************************************/
MLD_MUST_CHECK_RETURN_VALUE
static MLD_INLINE int32_t mld_reduce32(int32_t a)
__contract__(
requires(a <= MLD_REDUCE32_DOMAIN_MAX)
ensures(return_value >= -MLD_REDUCE32_RANGE_MAX)
ensures(return_value < MLD_REDUCE32_RANGE_MAX)
)
{
int32_t t;
t = (a + (1 << 22)) >> 23;
t = a - t * MLDSA_Q;
mld_assert((t - a) % MLDSA_Q == 0);
return t;
}
/*************************************************
* Name: mld_caddq
*
* Description: Add MLDSA_Q if input coefficient is negative.
*
* Arguments: - int32_t: finite field element a
*
* Returns r.
**************************************************/
MLD_MUST_CHECK_RETURN_VALUE
static MLD_INLINE int32_t mld_caddq(int32_t a)
__contract__(
requires(a > -MLDSA_Q)
requires(a < MLDSA_Q)
ensures(return_value >= 0)
ensures(return_value < MLDSA_Q)
ensures(return_value == ((a >= 0) ? a : (a + MLDSA_Q)))
)
{
return mld_ct_sel_int32(a + MLDSA_Q, a, mld_ct_cmask_neg_i32(a));
}
#endif /* !MLD_REDUCE_H */