1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans * Copyright (C) 2021 - This file is part of libecc project
3*f0865ec9SKyle Evans *
4*f0865ec9SKyle Evans * Authors:
5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans *
9*f0865ec9SKyle Evans * Contributors:
10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans *
13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans */
16*f0865ec9SKyle Evans #include <libecc/nn/nn_mul_redc1.h>
17*f0865ec9SKyle Evans #include <libecc/nn/nn_div_public.h>
18*f0865ec9SKyle Evans #include <libecc/nn/nn_logical.h>
19*f0865ec9SKyle Evans #include <libecc/nn/nn_mod_pow.h>
20*f0865ec9SKyle Evans #include <libecc/nn/nn_rand.h>
21*f0865ec9SKyle Evans #include <libecc/nn/nn.h>
22*f0865ec9SKyle Evans
23*f0865ec9SKyle Evans /*
24*f0865ec9SKyle Evans * NOT constant time with regard to the bitlength of exp.
25*f0865ec9SKyle Evans *
26*f0865ec9SKyle Evans * Implements a left to right Montgomery Ladder for modular exponentiation.
27*f0865ec9SKyle Evans * This is an internal common helper and assumes that all the initialization
28*f0865ec9SKyle Evans * and aliasing of inputs/outputs are handled by the callers. Depending on
29*f0865ec9SKyle Evans * the inputs, redcification is optionally used.
30*f0865ec9SKyle Evans * The base is reduced if necessary.
31*f0865ec9SKyle Evans *
32*f0865ec9SKyle Evans * Montgomery Ladder is masked using Itoh et al. anti-ADPA
33*f0865ec9SKyle Evans * (Address-bit DPA) countermeasure.
34*f0865ec9SKyle Evans * See "A Practical Countermeasure against Address-Bit Differential Power Analysis"
35*f0865ec9SKyle Evans * by Itoh, Izu and Takenaka for more information.
36*f0865ec9SKyle Evans
37*f0865ec9SKyle Evans * Returns 0 on success, -1 on error.
38*f0865ec9SKyle Evans */
_nn_exp_monty_ladder_ltr(nn_t out,nn_src_t base,nn_src_t exp,nn_src_t mod,nn_src_t r,nn_src_t r_square,word_t mpinv)39*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _nn_exp_monty_ladder_ltr(nn_t out, nn_src_t base, nn_src_t exp, nn_src_t mod, nn_src_t r, nn_src_t r_square, word_t mpinv)
40*f0865ec9SKyle Evans {
41*f0865ec9SKyle Evans nn T[3];
42*f0865ec9SKyle Evans nn mask;
43*f0865ec9SKyle Evans bitcnt_t explen, oldexplen;
44*f0865ec9SKyle Evans u8 expbit, rbit;
45*f0865ec9SKyle Evans int ret, cmp;
46*f0865ec9SKyle Evans T[0].magic = T[1].magic = T[2].magic = mask.magic = WORD(0);
47*f0865ec9SKyle Evans
48*f0865ec9SKyle Evans /* Initialize out */
49*f0865ec9SKyle Evans ret = nn_init(out, 0); EG(ret, err);
50*f0865ec9SKyle Evans
51*f0865ec9SKyle Evans ret = nn_init(&T[0], 0); EG(ret, err);
52*f0865ec9SKyle Evans ret = nn_init(&T[1], 0); EG(ret, err);
53*f0865ec9SKyle Evans ret = nn_init(&T[2], 0); EG(ret, err);
54*f0865ec9SKyle Evans
55*f0865ec9SKyle Evans /* Generate our Itoh random mask */
56*f0865ec9SKyle Evans ret = nn_get_random_len(&mask, NN_MAX_BYTE_LEN); EG(ret, err);
57*f0865ec9SKyle Evans
58*f0865ec9SKyle Evans ret = nn_bitlen(exp, &explen); EG(ret, err);
59*f0865ec9SKyle Evans
60*f0865ec9SKyle Evans
61*f0865ec9SKyle Evans /* From now on, since we deal with Itoh's countermeasure, we must have at
62*f0865ec9SKyle Evans * least 2 bits in the exponent. We will deal with the particular cases of 0 and 1
63*f0865ec9SKyle Evans * bit exponents later.
64*f0865ec9SKyle Evans */
65*f0865ec9SKyle Evans oldexplen = explen;
66*f0865ec9SKyle Evans explen = (explen < 2) ? 2 : explen;
67*f0865ec9SKyle Evans
68*f0865ec9SKyle Evans ret = nn_getbit(&mask, (bitcnt_t)(explen - 1), &rbit); EG(ret, err);
69*f0865ec9SKyle Evans
70*f0865ec9SKyle Evans /* Reduce the base if necessary */
71*f0865ec9SKyle Evans ret = nn_cmp(base, mod, &cmp); EG(ret, err);
72*f0865ec9SKyle Evans if(cmp >= 0){
73*f0865ec9SKyle Evans /* Modular reduction */
74*f0865ec9SKyle Evans ret = nn_mod(&T[rbit], base, mod); EG(ret, err);
75*f0865ec9SKyle Evans if(r != NULL){
76*f0865ec9SKyle Evans /* Redcify the base if necessary */
77*f0865ec9SKyle Evans ret = nn_mul_redc1(&T[rbit], &T[rbit], r_square, mod, mpinv); EG(ret, err);
78*f0865ec9SKyle Evans }
79*f0865ec9SKyle Evans }
80*f0865ec9SKyle Evans else{
81*f0865ec9SKyle Evans if(r != NULL){
82*f0865ec9SKyle Evans /* Redcify the base if necessary */
83*f0865ec9SKyle Evans ret = nn_mul_redc1(&T[rbit], base, r_square, mod, mpinv); EG(ret, err);
84*f0865ec9SKyle Evans }
85*f0865ec9SKyle Evans else{
86*f0865ec9SKyle Evans ret = nn_copy(&T[rbit], base); EG(ret, err);
87*f0865ec9SKyle Evans }
88*f0865ec9SKyle Evans }
89*f0865ec9SKyle Evans
90*f0865ec9SKyle Evans /* We implement the Montgomery ladder exponentiation with Itoh masking using three
91*f0865ec9SKyle Evans * registers T[0], T[1] and T[2]. The random mask is in 'mask'.
92*f0865ec9SKyle Evans */
93*f0865ec9SKyle Evans if(r != NULL){
94*f0865ec9SKyle Evans ret = nn_mul_redc1(&T[1-rbit], &T[rbit], &T[rbit], mod, mpinv); EG(ret, err);
95*f0865ec9SKyle Evans }
96*f0865ec9SKyle Evans else{
97*f0865ec9SKyle Evans ret = nn_mod_mul(&T[1-rbit], &T[rbit], &T[rbit], mod); EG(ret, err);
98*f0865ec9SKyle Evans }
99*f0865ec9SKyle Evans
100*f0865ec9SKyle Evans /* Now proceed with the Montgomery Ladder algorithm.
101*f0865ec9SKyle Evans */
102*f0865ec9SKyle Evans explen = (bitcnt_t)(explen - 1);
103*f0865ec9SKyle Evans while (explen > 0) {
104*f0865ec9SKyle Evans u8 rbit_next;
105*f0865ec9SKyle Evans explen = (bitcnt_t)(explen - 1);
106*f0865ec9SKyle Evans
107*f0865ec9SKyle Evans /* rbit is r[i+1], and rbit_next is r[i] */
108*f0865ec9SKyle Evans ret = nn_getbit(&mask, explen, &rbit_next); EG(ret, err);
109*f0865ec9SKyle Evans /* Get the exponent bit */
110*f0865ec9SKyle Evans ret = nn_getbit(exp, explen, &expbit); EG(ret, err);
111*f0865ec9SKyle Evans
112*f0865ec9SKyle Evans /* Square */
113*f0865ec9SKyle Evans if(r != NULL){
114*f0865ec9SKyle Evans ret = nn_mul_redc1(&T[2], &T[expbit ^ rbit], &T[expbit ^ rbit], mod, mpinv); EG(ret, err);
115*f0865ec9SKyle Evans }
116*f0865ec9SKyle Evans else{
117*f0865ec9SKyle Evans ret = nn_mod_mul(&T[2], &T[expbit ^ rbit], &T[expbit ^ rbit], mod); EG(ret, err);
118*f0865ec9SKyle Evans }
119*f0865ec9SKyle Evans /* Multiply */
120*f0865ec9SKyle Evans if(r != NULL){
121*f0865ec9SKyle Evans ret = nn_mul_redc1(&T[1], &T[0], &T[1], mod, mpinv); EG(ret, err);
122*f0865ec9SKyle Evans }
123*f0865ec9SKyle Evans else{
124*f0865ec9SKyle Evans ret = nn_mod_mul(&T[1], &T[0], &T[1], mod); EG(ret, err);
125*f0865ec9SKyle Evans }
126*f0865ec9SKyle Evans /* Copy */
127*f0865ec9SKyle Evans ret = nn_copy(&T[0], &T[2 - (expbit ^ rbit_next)]); EG(ret, err);
128*f0865ec9SKyle Evans ret = nn_copy(&T[1], &T[1 + (expbit ^ rbit_next)]); EG(ret, err);
129*f0865ec9SKyle Evans /* Update rbit */
130*f0865ec9SKyle Evans rbit = rbit_next;
131*f0865ec9SKyle Evans }
132*f0865ec9SKyle Evans ret = nn_one(&T[1 - rbit]);
133*f0865ec9SKyle Evans if(r != NULL){
134*f0865ec9SKyle Evans /* Unredcify in out */
135*f0865ec9SKyle Evans ret = nn_mul_redc1(&T[rbit], &T[rbit], &T[1 - rbit], mod, mpinv); EG(ret, err);
136*f0865ec9SKyle Evans }
137*f0865ec9SKyle Evans
138*f0865ec9SKyle Evans /* Deal with the particular cases of 0 and 1 bit exponents */
139*f0865ec9SKyle Evans /* Case with 0 bit exponent: T[1 - rbit] contains 1 modulo mod */
140*f0865ec9SKyle Evans ret = nn_mod(&T[1 - rbit], &T[1 - rbit], mod); EG(ret, err);
141*f0865ec9SKyle Evans /* Case with 1 bit exponent */
142*f0865ec9SKyle Evans ret = nn_mod(&T[2], base, mod); EG(ret, err);
143*f0865ec9SKyle Evans /* Proceed with the output */
144*f0865ec9SKyle Evans ret = nn_cnd_swap((oldexplen == 0), out, &T[1 - rbit]);
145*f0865ec9SKyle Evans ret = nn_cnd_swap((oldexplen == 1), out, &T[2]);
146*f0865ec9SKyle Evans ret = nn_cnd_swap(((oldexplen != 0) && (oldexplen != 1)), out, &T[rbit]);
147*f0865ec9SKyle Evans
148*f0865ec9SKyle Evans err:
149*f0865ec9SKyle Evans nn_uninit(&T[0]);
150*f0865ec9SKyle Evans nn_uninit(&T[1]);
151*f0865ec9SKyle Evans nn_uninit(&T[2]);
152*f0865ec9SKyle Evans nn_uninit(&mask);
153*f0865ec9SKyle Evans
154*f0865ec9SKyle Evans return ret;
155*f0865ec9SKyle Evans }
156*f0865ec9SKyle Evans
157*f0865ec9SKyle Evans /*
158*f0865ec9SKyle Evans * NOT constant time with regard to the bitlength of exp.
159*f0865ec9SKyle Evans *
160*f0865ec9SKyle Evans * Reduces the base modulo mod if it is not already reduced,
161*f0865ec9SKyle Evans * which is also a small divergence wrt constant time leaking
162*f0865ec9SKyle Evans * the information that base <= mod or not: please use with care
163*f0865ec9SKyle Evans * in the callers if this information is sensitive.
164*f0865ec9SKyle Evans *
165*f0865ec9SKyle Evans * Aliasing not supported. Expects caller to check parameters
166*f0865ec9SKyle Evans * have been initialized. This is an internal helper.
167*f0865ec9SKyle Evans *
168*f0865ec9SKyle Evans * Compute (base ** exp) mod (mod) using a Montgomery Ladder algorithm
169*f0865ec9SKyle Evans * with Montgomery redcification, hence the Montgomery coefficients as input.
170*f0865ec9SKyle Evans * The module "mod" is expected to be odd for redcification to be used.
171*f0865ec9SKyle Evans *
172*f0865ec9SKyle Evans * Returns 0 on success, -1 on error.
173*f0865ec9SKyle Evans */
_nn_mod_pow_redc(nn_t out,nn_src_t base,nn_src_t exp,nn_src_t mod,nn_src_t r,nn_src_t r_square,word_t mpinv)174*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _nn_mod_pow_redc(nn_t out, nn_src_t base, nn_src_t exp, nn_src_t mod, nn_src_t r, nn_src_t r_square, word_t mpinv)
175*f0865ec9SKyle Evans {
176*f0865ec9SKyle Evans return _nn_exp_monty_ladder_ltr(out, base, exp, mod, r, r_square, mpinv);
177*f0865ec9SKyle Evans }
178*f0865ec9SKyle Evans
179*f0865ec9SKyle Evans /*
180*f0865ec9SKyle Evans * NOT constant time with regard to the bitlength of exp.
181*f0865ec9SKyle Evans *
182*f0865ec9SKyle Evans * Reduces the base modulo mod if it is not already reduced,
183*f0865ec9SKyle Evans * which is also a small divergence wrt constant time leaking
184*f0865ec9SKyle Evans * the information that base <= mod or not: please use with care
185*f0865ec9SKyle Evans * in the callers if this information is sensitive.
186*f0865ec9SKyle Evans *
187*f0865ec9SKyle Evans * Aliasing is supported. Expects caller to check parameters
188*f0865ec9SKyle Evans * have been initialized. This is an internal helper.
189*f0865ec9SKyle Evans *
190*f0865ec9SKyle Evans * Compute (base ** exp) mod (mod) using a Montgomery Ladder algorithm.
191*f0865ec9SKyle Evans * This function works for all values of "mod", but is slower that the one
192*f0865ec9SKyle Evans * using Montgomery multiplication (which only works for odd "mod"). Hence,
193*f0865ec9SKyle Evans * it is only used on even "mod" by upper layers.
194*f0865ec9SKyle Evans *
195*f0865ec9SKyle Evans * Returns 0 on success, -1 on error.
196*f0865ec9SKyle Evans */
_nn_mod_pow(nn_t out,nn_src_t base,nn_src_t exp,nn_src_t mod)197*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _nn_mod_pow(nn_t out, nn_src_t base, nn_src_t exp, nn_src_t mod)
198*f0865ec9SKyle Evans {
199*f0865ec9SKyle Evans int ret;
200*f0865ec9SKyle Evans
201*f0865ec9SKyle Evans if ((out == base) || (out == exp) || (out == mod)) {
202*f0865ec9SKyle Evans nn _out;
203*f0865ec9SKyle Evans _out.magic = WORD(0);
204*f0865ec9SKyle Evans
205*f0865ec9SKyle Evans ret = nn_init(&_out, 0); EG(ret, err);
206*f0865ec9SKyle Evans ret = _nn_exp_monty_ladder_ltr(&_out, base, exp, mod, NULL, NULL, WORD(0)); EG(ret, err);
207*f0865ec9SKyle Evans ret = nn_copy(out, &_out);
208*f0865ec9SKyle Evans }
209*f0865ec9SKyle Evans else{
210*f0865ec9SKyle Evans ret = _nn_exp_monty_ladder_ltr(out, base, exp, mod, NULL, NULL, WORD(0));
211*f0865ec9SKyle Evans }
212*f0865ec9SKyle Evans
213*f0865ec9SKyle Evans err:
214*f0865ec9SKyle Evans return ret;
215*f0865ec9SKyle Evans }
216*f0865ec9SKyle Evans
217*f0865ec9SKyle Evans /*
218*f0865ec9SKyle Evans * Same purpose as above but handles aliasing.
219*f0865ec9SKyle Evans * Expects caller to check parameters
220*f0865ec9SKyle Evans * have been initialized. This is an internal helper.
221*f0865ec9SKyle Evans */
_nn_mod_pow_redc_aliased(nn_t out,nn_src_t base,nn_src_t exp,nn_src_t mod,nn_src_t r,nn_src_t r_square,word_t mpinv)222*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _nn_mod_pow_redc_aliased(nn_t out, nn_src_t base, nn_src_t exp, nn_src_t mod, nn_src_t r, nn_src_t r_square, word_t mpinv)
223*f0865ec9SKyle Evans {
224*f0865ec9SKyle Evans nn _out;
225*f0865ec9SKyle Evans int ret;
226*f0865ec9SKyle Evans _out.magic = WORD(0);
227*f0865ec9SKyle Evans
228*f0865ec9SKyle Evans ret = nn_init(&_out, 0); EG(ret, err);
229*f0865ec9SKyle Evans ret = _nn_mod_pow_redc(&_out, base, exp, mod, r, r_square, mpinv); EG(ret, err);
230*f0865ec9SKyle Evans ret = nn_copy(out, &_out);
231*f0865ec9SKyle Evans
232*f0865ec9SKyle Evans err:
233*f0865ec9SKyle Evans nn_uninit(&_out);
234*f0865ec9SKyle Evans
235*f0865ec9SKyle Evans return ret;
236*f0865ec9SKyle Evans }
237*f0865ec9SKyle Evans
238*f0865ec9SKyle Evans /* Aliased version of previous one.
239*f0865ec9SKyle Evans * NOTE: our nn_mod_pow_redc primitives suppose that the modulo is odd for Montgomery multiplication
240*f0865ec9SKyle Evans * primitives to provide consistent results.
241*f0865ec9SKyle Evans *
242*f0865ec9SKyle Evans * Aliasing is supported.
243*f0865ec9SKyle Evans */
nn_mod_pow_redc(nn_t out,nn_src_t base,nn_src_t exp,nn_src_t mod,nn_src_t r,nn_src_t r_square,word_t mpinv)244*f0865ec9SKyle Evans int nn_mod_pow_redc(nn_t out, nn_src_t base, nn_src_t exp, nn_src_t mod, nn_src_t r, nn_src_t r_square, word_t mpinv)
245*f0865ec9SKyle Evans {
246*f0865ec9SKyle Evans int ret, isodd;
247*f0865ec9SKyle Evans
248*f0865ec9SKyle Evans ret = nn_check_initialized(base); EG(ret, err);
249*f0865ec9SKyle Evans ret = nn_check_initialized(exp); EG(ret, err);
250*f0865ec9SKyle Evans ret = nn_check_initialized(mod); EG(ret, err);
251*f0865ec9SKyle Evans ret = nn_check_initialized(r); EG(ret, err);
252*f0865ec9SKyle Evans ret = nn_check_initialized(r_square); EG(ret, err);
253*f0865ec9SKyle Evans
254*f0865ec9SKyle Evans /* Check that we have an odd number for our modulo */
255*f0865ec9SKyle Evans ret = nn_isodd(mod, &isodd); EG(ret, err);
256*f0865ec9SKyle Evans MUST_HAVE(isodd, ret, err);
257*f0865ec9SKyle Evans
258*f0865ec9SKyle Evans /* Handle the case where our prime is less than two words size.
259*f0865ec9SKyle Evans * We need it to be >= 2 words size for the Montgomery multiplication to be
260*f0865ec9SKyle Evans * usable.
261*f0865ec9SKyle Evans */
262*f0865ec9SKyle Evans if(mod->wlen < 2){
263*f0865ec9SKyle Evans /* Local copy our modulo */
264*f0865ec9SKyle Evans nn _mod;
265*f0865ec9SKyle Evans _mod.magic = WORD(0);
266*f0865ec9SKyle Evans
267*f0865ec9SKyle Evans /* And set its length accordingly */
268*f0865ec9SKyle Evans ret = nn_copy(&_mod, mod); EG(ret, err1);
269*f0865ec9SKyle Evans ret = nn_set_wlen(&_mod, 2); EG(ret, err1);
270*f0865ec9SKyle Evans /* Handle output aliasing */
271*f0865ec9SKyle Evans if ((out == base) || (out == exp) || (out == mod) || (out == r) || (out == r_square)) {
272*f0865ec9SKyle Evans ret = _nn_mod_pow_redc_aliased(out, base, exp, &_mod, r, r_square, mpinv); EG(ret, err1);
273*f0865ec9SKyle Evans } else {
274*f0865ec9SKyle Evans ret = _nn_mod_pow_redc(out, base, exp, &_mod, r, r_square, mpinv); EG(ret, err1);
275*f0865ec9SKyle Evans }
276*f0865ec9SKyle Evans err1:
277*f0865ec9SKyle Evans nn_uninit(&_mod);
278*f0865ec9SKyle Evans EG(ret, err);
279*f0865ec9SKyle Evans }
280*f0865ec9SKyle Evans else{
281*f0865ec9SKyle Evans /* Handle output aliasing */
282*f0865ec9SKyle Evans if ((out == base) || (out == exp) || (out == mod) || (out == r) || (out == r_square)) {
283*f0865ec9SKyle Evans ret = _nn_mod_pow_redc_aliased(out, base, exp, mod, r, r_square, mpinv);
284*f0865ec9SKyle Evans } else {
285*f0865ec9SKyle Evans ret = _nn_mod_pow_redc(out, base, exp, mod, r, r_square, mpinv);
286*f0865ec9SKyle Evans }
287*f0865ec9SKyle Evans }
288*f0865ec9SKyle Evans
289*f0865ec9SKyle Evans err:
290*f0865ec9SKyle Evans return ret;
291*f0865ec9SKyle Evans }
292*f0865ec9SKyle Evans
293*f0865ec9SKyle Evans
294*f0865ec9SKyle Evans /*
295*f0865ec9SKyle Evans * NOT constant time with regard to the bitlength of exp.
296*f0865ec9SKyle Evans * Aliasing is supported.
297*f0865ec9SKyle Evans *
298*f0865ec9SKyle Evans * Compute (base ** exp) mod (mod) using a Montgomery Ladder algorithm.
299*f0865ec9SKyle Evans * Internally, this computes Montgomery coefficients and uses the redc
300*f0865ec9SKyle Evans * function.
301*f0865ec9SKyle Evans *
302*f0865ec9SKyle Evans * Returns 0 on success, -1 on error.
303*f0865ec9SKyle Evans */
nn_mod_pow(nn_t out,nn_src_t base,nn_src_t exp,nn_src_t mod)304*f0865ec9SKyle Evans int nn_mod_pow(nn_t out, nn_src_t base, nn_src_t exp, nn_src_t mod)
305*f0865ec9SKyle Evans {
306*f0865ec9SKyle Evans nn r, r_square;
307*f0865ec9SKyle Evans word_t mpinv;
308*f0865ec9SKyle Evans int ret, isodd;
309*f0865ec9SKyle Evans r.magic = r_square.magic = WORD(0);
310*f0865ec9SKyle Evans
311*f0865ec9SKyle Evans /* Handle the case where our modulo is even: in this case, we cannot
312*f0865ec9SKyle Evans * use our Montgomery multiplication primitives as they are only suitable
313*f0865ec9SKyle Evans * for odd numbers. We fallback to less efficient regular modular exponentiation.
314*f0865ec9SKyle Evans */
315*f0865ec9SKyle Evans ret = nn_isodd(mod, &isodd); EG(ret, err);
316*f0865ec9SKyle Evans if(!isodd){
317*f0865ec9SKyle Evans /* mod is even: use the regular unoptimized modular exponentiation */
318*f0865ec9SKyle Evans ret = _nn_mod_pow(out, base, exp, mod);
319*f0865ec9SKyle Evans }
320*f0865ec9SKyle Evans else{
321*f0865ec9SKyle Evans /* mod is odd */
322*f0865ec9SKyle Evans /* Compute the Montgomery coefficients */
323*f0865ec9SKyle Evans ret = nn_compute_redc1_coefs(&r, &r_square, mod, &mpinv); EG(ret, err);
324*f0865ec9SKyle Evans
325*f0865ec9SKyle Evans /* Now use the redc version */
326*f0865ec9SKyle Evans ret = nn_mod_pow_redc(out, base, exp, mod, &r, &r_square, mpinv);
327*f0865ec9SKyle Evans }
328*f0865ec9SKyle Evans
329*f0865ec9SKyle Evans err:
330*f0865ec9SKyle Evans nn_uninit(&r);
331*f0865ec9SKyle Evans nn_uninit(&r_square);
332*f0865ec9SKyle Evans
333*f0865ec9SKyle Evans return ret;
334*f0865ec9SKyle Evans }
335