1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2017 - 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_modinv.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_add.h> 20*f0865ec9SKyle Evans #include <libecc/nn/nn_mod_pow.h> 21*f0865ec9SKyle Evans #include <libecc/nn/nn.h> 22*f0865ec9SKyle Evans /* Include the "internal" header as we use non public API here */ 23*f0865ec9SKyle Evans #include "../nn/nn_mul.h" 24*f0865ec9SKyle Evans 25*f0865ec9SKyle Evans /* 26*f0865ec9SKyle Evans * Compute out = x^-1 mod m, i.e. out such that (out * x) = 1 mod m 27*f0865ec9SKyle Evans * out is initialized by the function, i.e. caller needs not initialize 28*f0865ec9SKyle Evans * it; only provide the associated storage space. Done in *constant 29*f0865ec9SKyle Evans * time* if underlying routines are. 30*f0865ec9SKyle Evans * 31*f0865ec9SKyle Evans * Asserts that m is odd and that x is smaller than m. 32*f0865ec9SKyle Evans * This second condition is not strictly necessary, 33*f0865ec9SKyle Evans * but it allows to perform all operations on nn's of the same length, 34*f0865ec9SKyle Evans * namely the length of m. 35*f0865ec9SKyle Evans * 36*f0865ec9SKyle Evans * Uses a binary xgcd algorithm, 37*f0865ec9SKyle Evans * only keeps track of coefficient for inverting x, 38*f0865ec9SKyle Evans * and performs reduction modulo m at each step. 39*f0865ec9SKyle Evans * 40*f0865ec9SKyle Evans * This does not normalize out on return. 41*f0865ec9SKyle Evans * 42*f0865ec9SKyle Evans * 0 is returned on success (everything went ok and x has reciprocal), -1 43*f0865ec9SKyle Evans * on error or if x has no reciprocal. On error, out is not meaningful. 44*f0865ec9SKyle Evans * 45*f0865ec9SKyle Evans * The function is an internal helper: caller MUST check params have been 46*f0865ec9SKyle Evans * initialized, i.e. this is not done by the function. 47*f0865ec9SKyle Evans * 48*f0865ec9SKyle Evans */ 49*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _nn_modinv_odd(nn_t out, nn_src_t x, nn_src_t m) 50*f0865ec9SKyle Evans { 51*f0865ec9SKyle Evans int isodd, swap, smaller, ret, cmp, iszero, tmp_isodd; 52*f0865ec9SKyle Evans nn a, b, u, tmp, mp1d2; 53*f0865ec9SKyle Evans nn_t uu = out; 54*f0865ec9SKyle Evans bitcnt_t cnt; 55*f0865ec9SKyle Evans a.magic = b.magic = u.magic = tmp.magic = mp1d2.magic = WORD(0); 56*f0865ec9SKyle Evans 57*f0865ec9SKyle Evans ret = nn_init(out, 0); EG(ret, err); 58*f0865ec9SKyle Evans ret = nn_init(&a, (u16)(m->wlen * WORD_BYTES)); EG(ret, err); 59*f0865ec9SKyle Evans ret = nn_init(&b, (u16)(m->wlen * WORD_BYTES)); EG(ret, err); 60*f0865ec9SKyle Evans ret = nn_init(&u, (u16)(m->wlen * WORD_BYTES)); EG(ret, err); 61*f0865ec9SKyle Evans ret = nn_init(&mp1d2, (u16)(m->wlen * WORD_BYTES)); EG(ret, err); 62*f0865ec9SKyle Evans /* 63*f0865ec9SKyle Evans * Temporary space needed to only deal with positive stuff. 64*f0865ec9SKyle Evans */ 65*f0865ec9SKyle Evans ret = nn_init(&tmp, (u16)(m->wlen * WORD_BYTES)); EG(ret, err); 66*f0865ec9SKyle Evans 67*f0865ec9SKyle Evans MUST_HAVE((!nn_isodd(m, &isodd)) && isodd, ret, err); 68*f0865ec9SKyle Evans MUST_HAVE((!nn_cmp(x, m, &cmp)) && (cmp < 0), ret, err); 69*f0865ec9SKyle Evans MUST_HAVE((!nn_iszero(x, &iszero)) && (!iszero), ret, err); 70*f0865ec9SKyle Evans 71*f0865ec9SKyle Evans /* 72*f0865ec9SKyle Evans * Maintain: 73*f0865ec9SKyle Evans * 74*f0865ec9SKyle Evans * a = u * x (mod m) 75*f0865ec9SKyle Evans * b = uu * x (mod m) 76*f0865ec9SKyle Evans * 77*f0865ec9SKyle Evans * and b odd at all times. Initially, 78*f0865ec9SKyle Evans * 79*f0865ec9SKyle Evans * a = x, u = 1 80*f0865ec9SKyle Evans * b = m, uu = 0 81*f0865ec9SKyle Evans */ 82*f0865ec9SKyle Evans ret = nn_copy(&a, x); EG(ret, err); 83*f0865ec9SKyle Evans ret = nn_set_wlen(&a, m->wlen); EG(ret, err); 84*f0865ec9SKyle Evans ret = nn_copy(&b, m); EG(ret, err); 85*f0865ec9SKyle Evans ret = nn_one(&u); EG(ret, err); 86*f0865ec9SKyle Evans ret = nn_zero(uu); EG(ret, err); 87*f0865ec9SKyle Evans 88*f0865ec9SKyle Evans /* 89*f0865ec9SKyle Evans * The lengths of u and uu should not affect constant timeness but it 90*f0865ec9SKyle Evans * does not hurt to set them already. 91*f0865ec9SKyle Evans * They will always be strictly smaller than m. 92*f0865ec9SKyle Evans */ 93*f0865ec9SKyle Evans ret = nn_set_wlen(&u, m->wlen); EG(ret, err); 94*f0865ec9SKyle Evans ret = nn_set_wlen(uu, m->wlen); EG(ret, err); 95*f0865ec9SKyle Evans 96*f0865ec9SKyle Evans /* 97*f0865ec9SKyle Evans * Precompute inverse of 2 mod m: 98*f0865ec9SKyle Evans * 2^-1 = (m+1)/2 99*f0865ec9SKyle Evans * computed as (m >> 1) + 1. 100*f0865ec9SKyle Evans */ 101*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&mp1d2, m, 1); EG(ret, err); 102*f0865ec9SKyle Evans 103*f0865ec9SKyle Evans ret = nn_inc(&mp1d2, &mp1d2); EG(ret, err); /* no carry can occur here 104*f0865ec9SKyle Evans because of prev. shift */ 105*f0865ec9SKyle Evans 106*f0865ec9SKyle Evans cnt = (bitcnt_t)((a.wlen + b.wlen) * WORD_BITS); 107*f0865ec9SKyle Evans while (cnt > 0) { 108*f0865ec9SKyle Evans cnt = (bitcnt_t)(cnt - 1); 109*f0865ec9SKyle Evans /* 110*f0865ec9SKyle Evans * Always maintain b odd. The logic of the iteration is as 111*f0865ec9SKyle Evans * follows. 112*f0865ec9SKyle Evans */ 113*f0865ec9SKyle Evans 114*f0865ec9SKyle Evans /* 115*f0865ec9SKyle Evans * For a, b: 116*f0865ec9SKyle Evans * 117*f0865ec9SKyle Evans * odd = a & 1 118*f0865ec9SKyle Evans * swap = odd & (a < b) 119*f0865ec9SKyle Evans * if (swap) 120*f0865ec9SKyle Evans * swap(a, b) 121*f0865ec9SKyle Evans * if (odd) 122*f0865ec9SKyle Evans * a -= b 123*f0865ec9SKyle Evans * a /= 2 124*f0865ec9SKyle Evans */ 125*f0865ec9SKyle Evans 126*f0865ec9SKyle Evans MUST_HAVE((!nn_isodd(&b, &tmp_isodd)) && tmp_isodd, ret, err); 127*f0865ec9SKyle Evans 128*f0865ec9SKyle Evans ret = nn_isodd(&a, &isodd); EG(ret, err); 129*f0865ec9SKyle Evans ret = nn_cmp(&a, &b, &cmp); EG(ret, err); 130*f0865ec9SKyle Evans swap = isodd & (cmp == -1); 131*f0865ec9SKyle Evans 132*f0865ec9SKyle Evans ret = nn_cnd_swap(swap, &a, &b); EG(ret, err); 133*f0865ec9SKyle Evans ret = nn_cnd_sub(isodd, &a, &a, &b); EG(ret, err); 134*f0865ec9SKyle Evans 135*f0865ec9SKyle Evans MUST_HAVE((!nn_isodd(&a, &tmp_isodd)) && (!tmp_isodd), ret, err); /* a is now even */ 136*f0865ec9SKyle Evans 137*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&a, &a, 1); EG(ret, err);/* division by 2 */ 138*f0865ec9SKyle Evans 139*f0865ec9SKyle Evans /* 140*f0865ec9SKyle Evans * For u, uu: 141*f0865ec9SKyle Evans * 142*f0865ec9SKyle Evans * if (swap) 143*f0865ec9SKyle Evans * swap u, uu 144*f0865ec9SKyle Evans * smaller = (u < uu) 145*f0865ec9SKyle Evans * if (odd) 146*f0865ec9SKyle Evans * if (smaller) 147*f0865ec9SKyle Evans * u += m - uu 148*f0865ec9SKyle Evans * else 149*f0865ec9SKyle Evans * u -= uu 150*f0865ec9SKyle Evans * u >>= 1 151*f0865ec9SKyle Evans * if (u was odd) 152*f0865ec9SKyle Evans * u += (m+1)/2 153*f0865ec9SKyle Evans */ 154*f0865ec9SKyle Evans ret = nn_cnd_swap(swap, &u, uu); EG(ret, err); 155*f0865ec9SKyle Evans 156*f0865ec9SKyle Evans /* This parameter is used to avoid handling negative numbers. */ 157*f0865ec9SKyle Evans ret = nn_cmp(&u, uu, &cmp); EG(ret, err); 158*f0865ec9SKyle Evans smaller = (cmp == -1); 159*f0865ec9SKyle Evans 160*f0865ec9SKyle Evans /* Computation of 'm - uu' can always be performed. */ 161*f0865ec9SKyle Evans ret = nn_sub(&tmp, m, uu); EG(ret, err); 162*f0865ec9SKyle Evans 163*f0865ec9SKyle Evans /* Selection btw 'm-uu' and '-uu' is made by the following function calls. */ 164*f0865ec9SKyle Evans ret = nn_cnd_add(isodd & smaller, &u, &u, &tmp); EG(ret, err); /* no carry can occur as 'u+(m-uu) = m-(uu-u) < m' */ 165*f0865ec9SKyle Evans ret = nn_cnd_sub(isodd & (!smaller), &u, &u, uu); EG(ret, err); 166*f0865ec9SKyle Evans 167*f0865ec9SKyle Evans /* Divide u by 2 */ 168*f0865ec9SKyle Evans ret = nn_isodd(&u, &isodd); EG(ret, err); 169*f0865ec9SKyle Evans ret = nn_rshift_fixedlen(&u, &u, 1); EG(ret, err); 170*f0865ec9SKyle Evans ret = nn_cnd_add(isodd, &u, &u, &mp1d2); EG(ret, err); /* no carry can occur as u=1+u' with u'<m-1 and u' even so u'/2+(m+1)/2<(m-1)/2+(m+1)/2=m */ 171*f0865ec9SKyle Evans 172*f0865ec9SKyle Evans MUST_HAVE((!nn_cmp(&u, m, &cmp)) && (cmp < 0), ret, err); 173*f0865ec9SKyle Evans MUST_HAVE((!nn_cmp(uu, m, &cmp)) && (cmp < 0), ret, err); 174*f0865ec9SKyle Evans 175*f0865ec9SKyle Evans /* 176*f0865ec9SKyle Evans * As long as a > 0, the quantity 177*f0865ec9SKyle Evans * (bitsize of a) + (bitsize of b) 178*f0865ec9SKyle Evans * is reduced by at least one bit per iteration, 179*f0865ec9SKyle Evans * hence after (bitsize of x) + (bitsize of m) - 1 180*f0865ec9SKyle Evans * iterations we surely have a = 0. Then b = gcd(x, m) 181*f0865ec9SKyle Evans * and if b = 1 then also uu = x^{-1} (mod m). 182*f0865ec9SKyle Evans */ 183*f0865ec9SKyle Evans } 184*f0865ec9SKyle Evans 185*f0865ec9SKyle Evans MUST_HAVE((!nn_iszero(&a, &iszero)) && iszero, ret, err); 186*f0865ec9SKyle Evans 187*f0865ec9SKyle Evans /* Check that gcd is one. */ 188*f0865ec9SKyle Evans ret = nn_cmp_word(&b, WORD(1), &cmp); EG(ret, err); 189*f0865ec9SKyle Evans 190*f0865ec9SKyle Evans /* If not, set "inverse" to zero. */ 191*f0865ec9SKyle Evans ret = nn_cnd_sub(cmp != 0, uu, uu, uu); EG(ret, err); 192*f0865ec9SKyle Evans 193*f0865ec9SKyle Evans ret = cmp ? -1 : 0; 194*f0865ec9SKyle Evans 195*f0865ec9SKyle Evans err: 196*f0865ec9SKyle Evans nn_uninit(&a); 197*f0865ec9SKyle Evans nn_uninit(&b); 198*f0865ec9SKyle Evans nn_uninit(&u); 199*f0865ec9SKyle Evans nn_uninit(&mp1d2); 200*f0865ec9SKyle Evans nn_uninit(&tmp); 201*f0865ec9SKyle Evans 202*f0865ec9SKyle Evans PTR_NULLIFY(uu); 203*f0865ec9SKyle Evans 204*f0865ec9SKyle Evans return ret; 205*f0865ec9SKyle Evans } 206*f0865ec9SKyle Evans 207*f0865ec9SKyle Evans /* 208*f0865ec9SKyle Evans * Same as above without restriction on m. 209*f0865ec9SKyle Evans * No attempt to make it constant time. 210*f0865ec9SKyle Evans * Uses the above constant-time binary xgcd when m is odd 211*f0865ec9SKyle Evans * and a not constant time plain Euclidean xgcd when m is even. 212*f0865ec9SKyle Evans * 213*f0865ec9SKyle Evans * _out parameter need not be initialized; this will be done by the function. 214*f0865ec9SKyle Evans * x and m must be initialized nn. 215*f0865ec9SKyle Evans * 216*f0865ec9SKyle Evans * Return -1 on error or if if x has no reciprocal modulo m. out is zeroed. 217*f0865ec9SKyle Evans * Return 0 if x has reciprocal modulo m. 218*f0865ec9SKyle Evans * 219*f0865ec9SKyle Evans * The function supports aliasing. 220*f0865ec9SKyle Evans */ 221*f0865ec9SKyle Evans int nn_modinv(nn_t _out, nn_src_t x, nn_src_t m) 222*f0865ec9SKyle Evans { 223*f0865ec9SKyle Evans int sign, ret, cmp, isodd, isone; 224*f0865ec9SKyle Evans nn_t x_mod_m; 225*f0865ec9SKyle Evans nn u, v, out; /* Out to support aliasing */ 226*f0865ec9SKyle Evans out.magic = u.magic = v.magic = WORD(0); 227*f0865ec9SKyle Evans 228*f0865ec9SKyle Evans ret = nn_check_initialized(x); EG(ret, err); 229*f0865ec9SKyle Evans ret = nn_check_initialized(m); EG(ret, err); 230*f0865ec9SKyle Evans 231*f0865ec9SKyle Evans /* Initialize out */ 232*f0865ec9SKyle Evans ret = nn_init(&out, 0); EG(ret, err); 233*f0865ec9SKyle Evans ret = nn_isodd(m, &isodd); EG(ret, err); 234*f0865ec9SKyle Evans if (isodd) { 235*f0865ec9SKyle Evans ret = nn_cmp(x, m, &cmp); EG(ret, err); 236*f0865ec9SKyle Evans if (cmp >= 0) { 237*f0865ec9SKyle Evans /* 238*f0865ec9SKyle Evans * If x >= m, (x^-1) mod m = ((x mod m)^-1) mod m 239*f0865ec9SKyle Evans * Hence, compute x mod m. In order to avoid 240*f0865ec9SKyle Evans * additional stack usage, we use 'u' (not 241*f0865ec9SKyle Evans * already useful at that point in the function). 242*f0865ec9SKyle Evans */ 243*f0865ec9SKyle Evans x_mod_m = &u; 244*f0865ec9SKyle Evans ret = nn_mod(x_mod_m, x, m); EG(ret, err); 245*f0865ec9SKyle Evans ret = _nn_modinv_odd(&out, x_mod_m, m); EG(ret, err); 246*f0865ec9SKyle Evans } else { 247*f0865ec9SKyle Evans ret = _nn_modinv_odd(&out, x, m); EG(ret, err); 248*f0865ec9SKyle Evans } 249*f0865ec9SKyle Evans ret = nn_copy(_out, &out); 250*f0865ec9SKyle Evans goto err; 251*f0865ec9SKyle Evans } 252*f0865ec9SKyle Evans 253*f0865ec9SKyle Evans /* Now m is even */ 254*f0865ec9SKyle Evans ret = nn_isodd(x, &isodd); EG(ret, err); 255*f0865ec9SKyle Evans MUST_HAVE(isodd, ret, err); 256*f0865ec9SKyle Evans 257*f0865ec9SKyle Evans ret = nn_init(&u, 0); EG(ret, err); 258*f0865ec9SKyle Evans ret = nn_init(&v, 0); EG(ret, err); 259*f0865ec9SKyle Evans ret = nn_xgcd(&out, &u, &v, x, m, &sign); EG(ret, err); 260*f0865ec9SKyle Evans ret = nn_isone(&out, &isone); EG(ret, err); 261*f0865ec9SKyle Evans MUST_HAVE(isone, ret, err); 262*f0865ec9SKyle Evans 263*f0865ec9SKyle Evans ret = nn_mod(&out, &u, m); EG(ret, err); 264*f0865ec9SKyle Evans if (sign == -1) { 265*f0865ec9SKyle Evans ret = nn_sub(&out, m, &out); EG(ret, err); 266*f0865ec9SKyle Evans } 267*f0865ec9SKyle Evans ret = nn_copy(_out, &out); 268*f0865ec9SKyle Evans 269*f0865ec9SKyle Evans err: 270*f0865ec9SKyle Evans nn_uninit(&out); 271*f0865ec9SKyle Evans nn_uninit(&u); 272*f0865ec9SKyle Evans nn_uninit(&v); 273*f0865ec9SKyle Evans 274*f0865ec9SKyle Evans PTR_NULLIFY(x_mod_m); 275*f0865ec9SKyle Evans 276*f0865ec9SKyle Evans return ret; 277*f0865ec9SKyle Evans } 278*f0865ec9SKyle Evans 279*f0865ec9SKyle Evans /* 280*f0865ec9SKyle Evans * Compute (A - B) % 2^(storagebitsizeof(B) + 1). A and B must be initialized nn. 281*f0865ec9SKyle Evans * the function is an internal helper and does not verify params have been 282*f0865ec9SKyle Evans * initialized; this must be done by the caller. No assumption on A and B values 283*f0865ec9SKyle Evans * such as A >= B. Done in *constant time. Returns 0 on success, -1 on error. 284*f0865ec9SKyle Evans */ 285*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static inline int _nn_sub_mod_2exp(nn_t A, nn_src_t B) 286*f0865ec9SKyle Evans { 287*f0865ec9SKyle Evans u8 Awlen = A->wlen; 288*f0865ec9SKyle Evans int ret; 289*f0865ec9SKyle Evans 290*f0865ec9SKyle Evans ret = nn_set_wlen(A, (u8)(Awlen + 1)); EG(ret, err); 291*f0865ec9SKyle Evans 292*f0865ec9SKyle Evans /* Make sure A > B */ 293*f0865ec9SKyle Evans /* NOTE: A->wlen - 1 is not an issue here thant to the nn_set_wlen above */ 294*f0865ec9SKyle Evans A->val[A->wlen - 1] = WORD(1); 295*f0865ec9SKyle Evans ret = nn_sub(A, A, B); EG(ret, err); 296*f0865ec9SKyle Evans 297*f0865ec9SKyle Evans /* The artificial word will be cleared in the following function call */ 298*f0865ec9SKyle Evans ret = nn_set_wlen(A, Awlen); 299*f0865ec9SKyle Evans 300*f0865ec9SKyle Evans err: 301*f0865ec9SKyle Evans return ret; 302*f0865ec9SKyle Evans } 303*f0865ec9SKyle Evans 304*f0865ec9SKyle Evans /* 305*f0865ec9SKyle Evans * Invert x modulo 2^exp using Hensel lifting. Returns 0 on success, -1 on 306*f0865ec9SKyle Evans * error. On success, x_isodd is 1 if x is odd, 0 if it is even. 307*f0865ec9SKyle Evans * Please note that the result is correct (inverse of x) only when x is prime 308*f0865ec9SKyle Evans * to 2^exp, i.e. x is odd (x_odd is 1). 309*f0865ec9SKyle Evans * 310*f0865ec9SKyle Evans * Operations are done in *constant time*. 311*f0865ec9SKyle Evans * 312*f0865ec9SKyle Evans * Aliasing is supported. 313*f0865ec9SKyle Evans */ 314*f0865ec9SKyle Evans int nn_modinv_2exp(nn_t _out, nn_src_t x, bitcnt_t exp, int *x_isodd) 315*f0865ec9SKyle Evans { 316*f0865ec9SKyle Evans bitcnt_t cnt; 317*f0865ec9SKyle Evans u8 exp_wlen = (u8)BIT_LEN_WORDS(exp); 318*f0865ec9SKyle Evans bitcnt_t exp_cnt = exp % WORD_BITS; 319*f0865ec9SKyle Evans word_t mask = (word_t)((exp_cnt == 0) ? WORD_MASK : (word_t)((WORD(1) << exp_cnt) - WORD(1))); 320*f0865ec9SKyle Evans nn tmp_sqr, tmp_mul; 321*f0865ec9SKyle Evans /* for aliasing */ 322*f0865ec9SKyle Evans int isodd, ret; 323*f0865ec9SKyle Evans nn out; 324*f0865ec9SKyle Evans out.magic = tmp_sqr.magic = tmp_mul.magic = WORD(0); 325*f0865ec9SKyle Evans 326*f0865ec9SKyle Evans MUST_HAVE((x_isodd != NULL), ret, err); 327*f0865ec9SKyle Evans ret = nn_check_initialized(x); EG(ret, err); 328*f0865ec9SKyle Evans ret = nn_check_initialized(_out); EG(ret, err); 329*f0865ec9SKyle Evans 330*f0865ec9SKyle Evans ret = nn_init(&out, 0); EG(ret, err); 331*f0865ec9SKyle Evans ret = nn_init(&tmp_sqr, 0); EG(ret, err); 332*f0865ec9SKyle Evans ret = nn_init(&tmp_mul, 0); EG(ret, err); 333*f0865ec9SKyle Evans ret = nn_isodd(x, &isodd); EG(ret, err); 334*f0865ec9SKyle Evans if (exp == (bitcnt_t)0){ 335*f0865ec9SKyle Evans /* Specific case of zero exponent, output 0 */ 336*f0865ec9SKyle Evans (*x_isodd) = isodd; 337*f0865ec9SKyle Evans goto err; 338*f0865ec9SKyle Evans } 339*f0865ec9SKyle Evans if (!isodd) { 340*f0865ec9SKyle Evans ret = nn_zero(_out); EG(ret, err); 341*f0865ec9SKyle Evans (*x_isodd) = 0; 342*f0865ec9SKyle Evans goto err; 343*f0865ec9SKyle Evans } 344*f0865ec9SKyle Evans 345*f0865ec9SKyle Evans /* 346*f0865ec9SKyle Evans * Inverse modulo 2. 347*f0865ec9SKyle Evans */ 348*f0865ec9SKyle Evans cnt = 1; 349*f0865ec9SKyle Evans ret = nn_one(&out); EG(ret, err); 350*f0865ec9SKyle Evans 351*f0865ec9SKyle Evans /* 352*f0865ec9SKyle Evans * Inverse modulo 2^(2^i) <= 2^WORD_BITS. 353*f0865ec9SKyle Evans * Assumes WORD_BITS is a power of two. 354*f0865ec9SKyle Evans */ 355*f0865ec9SKyle Evans for (; cnt < WORD_MIN(WORD_BITS, exp); cnt = (bitcnt_t)(cnt << 1)) { 356*f0865ec9SKyle Evans ret = nn_sqr_low(&tmp_sqr, &out, out.wlen); EG(ret, err); 357*f0865ec9SKyle Evans ret = nn_mul_low(&tmp_mul, &tmp_sqr, x, out.wlen); EG(ret, err); 358*f0865ec9SKyle Evans ret = nn_lshift_fixedlen(&out, &out, 1); EG(ret, err); 359*f0865ec9SKyle Evans 360*f0865ec9SKyle Evans /* 361*f0865ec9SKyle Evans * Allowing "negative" results for a subtraction modulo 362*f0865ec9SKyle Evans * a power of two would allow to use directly: 363*f0865ec9SKyle Evans * nn_sub(out, out, tmp_mul) 364*f0865ec9SKyle Evans * which is always negative in ZZ except when x is one. 365*f0865ec9SKyle Evans * 366*f0865ec9SKyle Evans * Another solution is to add the opposite of tmp_mul. 367*f0865ec9SKyle Evans * nn_modopp_2exp(tmp_mul, tmp_mul); 368*f0865ec9SKyle Evans * nn_add(out, out, tmp_mul); 369*f0865ec9SKyle Evans * 370*f0865ec9SKyle Evans * The current solution is to add a sufficiently large power 371*f0865ec9SKyle Evans * of two to out unconditionally to absorb the potential 372*f0865ec9SKyle Evans * borrow. The result modulo 2^(2^i) is correct whether the 373*f0865ec9SKyle Evans * borrow occurs or not. 374*f0865ec9SKyle Evans */ 375*f0865ec9SKyle Evans ret = _nn_sub_mod_2exp(&out, &tmp_mul); EG(ret, err); 376*f0865ec9SKyle Evans } 377*f0865ec9SKyle Evans 378*f0865ec9SKyle Evans /* 379*f0865ec9SKyle Evans * Inverse modulo 2^WORD_BITS < 2^(2^i) < 2^exp. 380*f0865ec9SKyle Evans */ 381*f0865ec9SKyle Evans for (; cnt < ((exp + 1) >> 1); cnt = (bitcnt_t)(cnt << 1)) { 382*f0865ec9SKyle Evans ret = nn_set_wlen(&out, (u8)(2 * out.wlen)); EG(ret, err); 383*f0865ec9SKyle Evans ret = nn_sqr_low(&tmp_sqr, &out, out.wlen); EG(ret, err); 384*f0865ec9SKyle Evans ret = nn_mul_low(&tmp_mul, &tmp_sqr, x, out.wlen); EG(ret, err); 385*f0865ec9SKyle Evans ret = nn_lshift_fixedlen(&out, &out, 1); EG(ret, err); 386*f0865ec9SKyle Evans ret = _nn_sub_mod_2exp(&out, &tmp_mul); EG(ret, err); 387*f0865ec9SKyle Evans } 388*f0865ec9SKyle Evans 389*f0865ec9SKyle Evans /* 390*f0865ec9SKyle Evans * Inverse modulo 2^(2^i + j) >= 2^exp. 391*f0865ec9SKyle Evans */ 392*f0865ec9SKyle Evans if (exp > WORD_BITS) { 393*f0865ec9SKyle Evans ret = nn_set_wlen(&out, exp_wlen); EG(ret, err); 394*f0865ec9SKyle Evans ret = nn_sqr_low(&tmp_sqr, &out, out.wlen); EG(ret, err); 395*f0865ec9SKyle Evans ret = nn_mul_low(&tmp_mul, &tmp_sqr, x, out.wlen); EG(ret, err); 396*f0865ec9SKyle Evans ret = nn_lshift_fixedlen(&out, &out, 1); EG(ret, err); 397*f0865ec9SKyle Evans ret = _nn_sub_mod_2exp(&out, &tmp_mul); EG(ret, err); 398*f0865ec9SKyle Evans } 399*f0865ec9SKyle Evans 400*f0865ec9SKyle Evans /* 401*f0865ec9SKyle Evans * Inverse modulo 2^exp. 402*f0865ec9SKyle Evans */ 403*f0865ec9SKyle Evans out.val[exp_wlen - 1] &= mask; 404*f0865ec9SKyle Evans 405*f0865ec9SKyle Evans ret = nn_copy(_out, &out); EG(ret, err); 406*f0865ec9SKyle Evans 407*f0865ec9SKyle Evans (*x_isodd) = 1; 408*f0865ec9SKyle Evans 409*f0865ec9SKyle Evans err: 410*f0865ec9SKyle Evans nn_uninit(&out); 411*f0865ec9SKyle Evans nn_uninit(&tmp_sqr); 412*f0865ec9SKyle Evans nn_uninit(&tmp_mul); 413*f0865ec9SKyle Evans 414*f0865ec9SKyle Evans return ret; 415*f0865ec9SKyle Evans } 416*f0865ec9SKyle Evans 417*f0865ec9SKyle Evans /* 418*f0865ec9SKyle Evans * Invert word w modulo m. 419*f0865ec9SKyle Evans * 420*f0865ec9SKyle Evans * The function supports aliasing. 421*f0865ec9SKyle Evans */ 422*f0865ec9SKyle Evans int nn_modinv_word(nn_t out, word_t w, nn_src_t m) 423*f0865ec9SKyle Evans { 424*f0865ec9SKyle Evans nn nn_tmp; 425*f0865ec9SKyle Evans int ret; 426*f0865ec9SKyle Evans nn_tmp.magic = WORD(0); 427*f0865ec9SKyle Evans 428*f0865ec9SKyle Evans ret = nn_init(&nn_tmp, 0); EG(ret, err); 429*f0865ec9SKyle Evans ret = nn_set_word_value(&nn_tmp, w); EG(ret, err); 430*f0865ec9SKyle Evans ret = nn_modinv(out, &nn_tmp, m); 431*f0865ec9SKyle Evans 432*f0865ec9SKyle Evans err: 433*f0865ec9SKyle Evans nn_uninit(&nn_tmp); 434*f0865ec9SKyle Evans 435*f0865ec9SKyle Evans return ret; 436*f0865ec9SKyle Evans } 437*f0865ec9SKyle Evans 438*f0865ec9SKyle Evans 439*f0865ec9SKyle Evans /* 440*f0865ec9SKyle Evans * Internal function for nn_modinv_fermat and nn_modinv_fermat_redc used 441*f0865ec9SKyle Evans * hereafter. 442*f0865ec9SKyle Evans */ 443*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int _nn_modinv_fermat_common(nn_t out, nn_src_t x, nn_src_t p, nn_t p_minus_two, int *lesstwo) 444*f0865ec9SKyle Evans { 445*f0865ec9SKyle Evans int ret, cmp, isodd; 446*f0865ec9SKyle Evans nn two; 447*f0865ec9SKyle Evans two.magic = WORD(0); 448*f0865ec9SKyle Evans 449*f0865ec9SKyle Evans /* Sanity checks on inputs */ 450*f0865ec9SKyle Evans ret = nn_check_initialized(x); EG(ret, err); 451*f0865ec9SKyle Evans ret = nn_check_initialized(p); EG(ret, err); 452*f0865ec9SKyle Evans /* NOTE: since this is an internal function, we are ensured that p_minus_two, 453*f0865ec9SKyle Evans * two and regular are OK. 454*f0865ec9SKyle Evans */ 455*f0865ec9SKyle Evans 456*f0865ec9SKyle Evans /* 0 is not invertible in any case */ 457*f0865ec9SKyle Evans ret = nn_iszero(x, &cmp); EG(ret, err); 458*f0865ec9SKyle Evans if(cmp){ 459*f0865ec9SKyle Evans /* Zero the output and return an error */ 460*f0865ec9SKyle Evans ret = nn_init(out, 0); EG(ret, err); 461*f0865ec9SKyle Evans ret = nn_zero(out); EG(ret, err); 462*f0865ec9SKyle Evans ret = -1; 463*f0865ec9SKyle Evans goto err; 464*f0865ec9SKyle Evans } 465*f0865ec9SKyle Evans 466*f0865ec9SKyle Evans /* For p <= 2, p being prime either p = 1 or p = 2. 467*f0865ec9SKyle Evans * When p = 2, only 1 has an inverse, if p = 1 no one has an inverse. 468*f0865ec9SKyle Evans */ 469*f0865ec9SKyle Evans (*lesstwo) = 0; 470*f0865ec9SKyle Evans ret = nn_cmp_word(p, WORD(2), &cmp); EG(ret, err); 471*f0865ec9SKyle Evans if(cmp == 0){ 472*f0865ec9SKyle Evans /* This is the p = 2 case, parity of x provides the result */ 473*f0865ec9SKyle Evans ret = nn_isodd(x, &isodd); EG(ret, err); 474*f0865ec9SKyle Evans if(isodd){ 475*f0865ec9SKyle Evans /* x is odd, 1 is its inverse */ 476*f0865ec9SKyle Evans ret = nn_init(out, 0); EG(ret, err); 477*f0865ec9SKyle Evans ret = nn_one(out); EG(ret, err); 478*f0865ec9SKyle Evans ret = 0; 479*f0865ec9SKyle Evans } 480*f0865ec9SKyle Evans else{ 481*f0865ec9SKyle Evans /* x is even, no inverse. Zero the output */ 482*f0865ec9SKyle Evans ret = nn_init(out, 0); EG(ret, err); 483*f0865ec9SKyle Evans ret = nn_zero(out); EG(ret, err); 484*f0865ec9SKyle Evans ret = -1; 485*f0865ec9SKyle Evans } 486*f0865ec9SKyle Evans (*lesstwo) = 1; 487*f0865ec9SKyle Evans goto err; 488*f0865ec9SKyle Evans } else if (cmp < 0){ 489*f0865ec9SKyle Evans /* This is the p = 1 case, no inverse here: hence return an error */ 490*f0865ec9SKyle Evans /* Zero the output */ 491*f0865ec9SKyle Evans ret = nn_init(out, 0); EG(ret, err); 492*f0865ec9SKyle Evans ret = nn_zero(out); EG(ret, err); 493*f0865ec9SKyle Evans ret = -1; 494*f0865ec9SKyle Evans (*lesstwo) = 1; 495*f0865ec9SKyle Evans goto err; 496*f0865ec9SKyle Evans } 497*f0865ec9SKyle Evans 498*f0865ec9SKyle Evans /* Else we compute (p-2) for the upper layer */ 499*f0865ec9SKyle Evans if(p != p_minus_two){ 500*f0865ec9SKyle Evans /* Handle aliasing of p and p_minus_two */ 501*f0865ec9SKyle Evans ret = nn_init(p_minus_two, 0); EG(ret, err); 502*f0865ec9SKyle Evans } 503*f0865ec9SKyle Evans 504*f0865ec9SKyle Evans ret = nn_init(&two, 0); EG(ret, err); 505*f0865ec9SKyle Evans ret = nn_set_word_value(&two, WORD(2)); EG(ret, err); 506*f0865ec9SKyle Evans ret = nn_sub(p_minus_two, p, &two); 507*f0865ec9SKyle Evans 508*f0865ec9SKyle Evans err: 509*f0865ec9SKyle Evans nn_uninit(&two); 510*f0865ec9SKyle Evans 511*f0865ec9SKyle Evans return ret; 512*f0865ec9SKyle Evans } 513*f0865ec9SKyle Evans 514*f0865ec9SKyle Evans /* 515*f0865ec9SKyle Evans * Invert NN x modulo p using Fermat's little theorem for our inversion: 516*f0865ec9SKyle Evans * 517*f0865ec9SKyle Evans * p prime means that: 518*f0865ec9SKyle Evans * x^(p-1) = 1 mod (p) 519*f0865ec9SKyle Evans * which means that x^(p-2) mod(p) is the modular inverse of x mod (p) 520*f0865ec9SKyle Evans * for x != 0 521*f0865ec9SKyle Evans * 522*f0865ec9SKyle Evans * NOTE: the input hypothesis is that p is prime. 523*f0865ec9SKyle Evans * XXX WARNING: using this function with p not prime will produce wrong 524*f0865ec9SKyle Evans * results without triggering an error! 525*f0865ec9SKyle Evans * 526*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error 527*f0865ec9SKyle Evans * (e.g. if x has no inverse modulo p, i.e. x = 0). 528*f0865ec9SKyle Evans * 529*f0865ec9SKyle Evans * Aliasing is supported. 530*f0865ec9SKyle Evans */ 531*f0865ec9SKyle Evans int nn_modinv_fermat(nn_t out, nn_src_t x, nn_src_t p) 532*f0865ec9SKyle Evans { 533*f0865ec9SKyle Evans int ret, lesstwo; 534*f0865ec9SKyle Evans nn p_minus_two; 535*f0865ec9SKyle Evans p_minus_two.magic = WORD(0); 536*f0865ec9SKyle Evans 537*f0865ec9SKyle Evans /* Call our helper. 538*f0865ec9SKyle Evans * NOTE: "marginal" cases where x = 0 and p <= 2 should be caught in this helper. 539*f0865ec9SKyle Evans */ 540*f0865ec9SKyle Evans ret = _nn_modinv_fermat_common(out, x, p, &p_minus_two, &lesstwo); EG(ret, err); 541*f0865ec9SKyle Evans 542*f0865ec9SKyle Evans if(!lesstwo){ 543*f0865ec9SKyle Evans /* Compute x^(p-2) mod (p) */ 544*f0865ec9SKyle Evans ret = nn_mod_pow(out, x, &p_minus_two, p); 545*f0865ec9SKyle Evans } 546*f0865ec9SKyle Evans 547*f0865ec9SKyle Evans err: 548*f0865ec9SKyle Evans nn_uninit(&p_minus_two); 549*f0865ec9SKyle Evans 550*f0865ec9SKyle Evans return ret; 551*f0865ec9SKyle Evans } 552*f0865ec9SKyle Evans 553*f0865ec9SKyle Evans /* 554*f0865ec9SKyle Evans * Invert NN x modulo m using Fermat's little theorem for our inversion. 555*f0865ec9SKyle Evans * 556*f0865ec9SKyle Evans * This is a version with already (pre)computed Montgomery coefficients. 557*f0865ec9SKyle Evans * 558*f0865ec9SKyle Evans * NOTE: the input hypothesis is that p is prime. 559*f0865ec9SKyle Evans * XXX WARNING: using this function with p not prime will produce wrong 560*f0865ec9SKyle Evans * results without triggering an error! 561*f0865ec9SKyle Evans * 562*f0865ec9SKyle Evans * The function returns 0 on success, -1 on error 563*f0865ec9SKyle Evans * (e.g. if x has no inverse modulo p, i.e. x = 0). 564*f0865ec9SKyle Evans * 565*f0865ec9SKyle Evans * Aliasing is supported. 566*f0865ec9SKyle Evans */ 567*f0865ec9SKyle Evans int nn_modinv_fermat_redc(nn_t out, nn_src_t x, nn_src_t p, nn_src_t r, nn_src_t r_square, word_t mpinv) 568*f0865ec9SKyle Evans { 569*f0865ec9SKyle Evans int ret, lesstwo; 570*f0865ec9SKyle Evans nn p_minus_two; 571*f0865ec9SKyle Evans p_minus_two.magic = WORD(0); 572*f0865ec9SKyle Evans 573*f0865ec9SKyle Evans /* Call our helper. 574*f0865ec9SKyle Evans * NOTE: "marginal" cases where x = 0 and p <= 2 should be caught in this helper. 575*f0865ec9SKyle Evans */ 576*f0865ec9SKyle Evans ret = _nn_modinv_fermat_common(out, x, p, &p_minus_two, &lesstwo); EG(ret, err); 577*f0865ec9SKyle Evans 578*f0865ec9SKyle Evans if(!lesstwo){ 579*f0865ec9SKyle Evans /* Compute x^(p-2) mod (p) using precomputed Montgomery coefficients as input */ 580*f0865ec9SKyle Evans ret = nn_mod_pow_redc(out, x, &p_minus_two, p, r, r_square, mpinv); 581*f0865ec9SKyle Evans } 582*f0865ec9SKyle Evans 583*f0865ec9SKyle Evans err: 584*f0865ec9SKyle Evans nn_uninit(&p_minus_two); 585*f0865ec9SKyle Evans 586*f0865ec9SKyle Evans return ret; 587*f0865ec9SKyle Evans } 588