1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/freebl/ecl/ecp_mont.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,155 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* Uses Montgomery reduction for field arithmetic. See mpi/mpmontg.c for 1.9 + * code implementation. */ 1.10 + 1.11 +#include "mpi.h" 1.12 +#include "mplogic.h" 1.13 +#include "mpi-priv.h" 1.14 +#include "ecl-priv.h" 1.15 +#include "ecp.h" 1.16 +#include <stdlib.h> 1.17 +#include <stdio.h> 1.18 + 1.19 +/* Construct a generic GFMethod for arithmetic over prime fields with 1.20 + * irreducible irr. */ 1.21 +GFMethod * 1.22 +GFMethod_consGFp_mont(const mp_int *irr) 1.23 +{ 1.24 + mp_err res = MP_OKAY; 1.25 + GFMethod *meth = NULL; 1.26 + mp_mont_modulus *mmm; 1.27 + 1.28 + meth = GFMethod_consGFp(irr); 1.29 + if (meth == NULL) 1.30 + return NULL; 1.31 + 1.32 + mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus)); 1.33 + if (mmm == NULL) { 1.34 + res = MP_MEM; 1.35 + goto CLEANUP; 1.36 + } 1.37 + 1.38 + meth->field_mul = &ec_GFp_mul_mont; 1.39 + meth->field_sqr = &ec_GFp_sqr_mont; 1.40 + meth->field_div = &ec_GFp_div_mont; 1.41 + meth->field_enc = &ec_GFp_enc_mont; 1.42 + meth->field_dec = &ec_GFp_dec_mont; 1.43 + meth->extra1 = mmm; 1.44 + meth->extra2 = NULL; 1.45 + meth->extra_free = &ec_GFp_extra_free_mont; 1.46 + 1.47 + mmm->N = meth->irr; 1.48 + mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0)); 1.49 + 1.50 + CLEANUP: 1.51 + if (res != MP_OKAY) { 1.52 + GFMethod_free(meth); 1.53 + return NULL; 1.54 + } 1.55 + return meth; 1.56 +} 1.57 + 1.58 +/* Wrapper functions for generic prime field arithmetic. */ 1.59 + 1.60 +/* Field multiplication using Montgomery reduction. */ 1.61 +mp_err 1.62 +ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r, 1.63 + const GFMethod *meth) 1.64 +{ 1.65 + mp_err res = MP_OKAY; 1.66 + 1.67 +#ifdef MP_MONT_USE_MP_MUL 1.68 + /* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont 1.69 + * is not implemented and we have to use mp_mul and s_mp_redc directly 1.70 + */ 1.71 + MP_CHECKOK(mp_mul(a, b, r)); 1.72 + MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1)); 1.73 +#else 1.74 + mp_int s; 1.75 + 1.76 + MP_DIGITS(&s) = 0; 1.77 + /* s_mp_mul_mont doesn't allow source and destination to be the same */ 1.78 + if ((a == r) || (b == r)) { 1.79 + MP_CHECKOK(mp_init(&s)); 1.80 + MP_CHECKOK(s_mp_mul_mont 1.81 + (a, b, &s, (mp_mont_modulus *) meth->extra1)); 1.82 + MP_CHECKOK(mp_copy(&s, r)); 1.83 + mp_clear(&s); 1.84 + } else { 1.85 + return s_mp_mul_mont(a, b, r, (mp_mont_modulus *) meth->extra1); 1.86 + } 1.87 +#endif 1.88 + CLEANUP: 1.89 + return res; 1.90 +} 1.91 + 1.92 +/* Field squaring using Montgomery reduction. */ 1.93 +mp_err 1.94 +ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth) 1.95 +{ 1.96 + return ec_GFp_mul_mont(a, a, r, meth); 1.97 +} 1.98 + 1.99 +/* Field division using Montgomery reduction. */ 1.100 +mp_err 1.101 +ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r, 1.102 + const GFMethod *meth) 1.103 +{ 1.104 + mp_err res = MP_OKAY; 1.105 + 1.106 + /* if A=aZ represents a encoded in montgomery coordinates with Z and # 1.107 + * and \ respectively represent multiplication and division in 1.108 + * montgomery coordinates, then A\B = (a/b)Z = (A/B)Z and Binv = 1.109 + * (1/b)Z = (1/B)(Z^2) where B # Binv = Z */ 1.110 + MP_CHECKOK(ec_GFp_div(a, b, r, meth)); 1.111 + MP_CHECKOK(ec_GFp_enc_mont(r, r, meth)); 1.112 + if (a == NULL) { 1.113 + MP_CHECKOK(ec_GFp_enc_mont(r, r, meth)); 1.114 + } 1.115 + CLEANUP: 1.116 + return res; 1.117 +} 1.118 + 1.119 +/* Encode a field element in Montgomery form. See s_mp_to_mont in 1.120 + * mpi/mpmontg.c */ 1.121 +mp_err 1.122 +ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth) 1.123 +{ 1.124 + mp_mont_modulus *mmm; 1.125 + mp_err res = MP_OKAY; 1.126 + 1.127 + mmm = (mp_mont_modulus *) meth->extra1; 1.128 + MP_CHECKOK(mp_copy(a, r)); 1.129 + MP_CHECKOK(s_mp_lshd(r, MP_USED(&mmm->N))); 1.130 + MP_CHECKOK(mp_mod(r, &mmm->N, r)); 1.131 + CLEANUP: 1.132 + return res; 1.133 +} 1.134 + 1.135 +/* Decode a field element from Montgomery form. */ 1.136 +mp_err 1.137 +ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth) 1.138 +{ 1.139 + mp_err res = MP_OKAY; 1.140 + 1.141 + if (a != r) { 1.142 + MP_CHECKOK(mp_copy(a, r)); 1.143 + } 1.144 + MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1)); 1.145 + CLEANUP: 1.146 + return res; 1.147 +} 1.148 + 1.149 +/* Free the memory allocated to the extra fields of Montgomery GFMethod 1.150 + * object. */ 1.151 +void 1.152 +ec_GFp_extra_free_mont(GFMethod *meth) 1.153 +{ 1.154 + if (meth->extra1 != NULL) { 1.155 + free(meth->extra1); 1.156 + meth->extra1 = NULL; 1.157 + } 1.158 +}