1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/freebl/ecl/ecp_384.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,258 @@ 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 +#include "ecp.h" 1.9 +#include "mpi.h" 1.10 +#include "mplogic.h" 1.11 +#include "mpi-priv.h" 1.12 + 1.13 +/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r. 1.14 + * Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to 1.15 + * Elliptic Curve Cryptography. */ 1.16 +static mp_err 1.17 +ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth) 1.18 +{ 1.19 + mp_err res = MP_OKAY; 1.20 + int a_bits = mpl_significant_bits(a); 1.21 + int i; 1.22 + 1.23 + /* m1, m2 are statically-allocated mp_int of exactly the size we need */ 1.24 + mp_int m[10]; 1.25 + 1.26 +#ifdef ECL_THIRTY_TWO_BIT 1.27 + mp_digit s[10][12]; 1.28 + for (i = 0; i < 10; i++) { 1.29 + MP_SIGN(&m[i]) = MP_ZPOS; 1.30 + MP_ALLOC(&m[i]) = 12; 1.31 + MP_USED(&m[i]) = 12; 1.32 + MP_DIGITS(&m[i]) = s[i]; 1.33 + } 1.34 +#else 1.35 + mp_digit s[10][6]; 1.36 + for (i = 0; i < 10; i++) { 1.37 + MP_SIGN(&m[i]) = MP_ZPOS; 1.38 + MP_ALLOC(&m[i]) = 6; 1.39 + MP_USED(&m[i]) = 6; 1.40 + MP_DIGITS(&m[i]) = s[i]; 1.41 + } 1.42 +#endif 1.43 + 1.44 +#ifdef ECL_THIRTY_TWO_BIT 1.45 + /* for polynomials larger than twice the field size or polynomials 1.46 + * not using all words, use regular reduction */ 1.47 + if ((a_bits > 768) || (a_bits <= 736)) { 1.48 + MP_CHECKOK(mp_mod(a, &meth->irr, r)); 1.49 + } else { 1.50 + for (i = 0; i < 12; i++) { 1.51 + s[0][i] = MP_DIGIT(a, i); 1.52 + } 1.53 + s[1][0] = 0; 1.54 + s[1][1] = 0; 1.55 + s[1][2] = 0; 1.56 + s[1][3] = 0; 1.57 + s[1][4] = MP_DIGIT(a, 21); 1.58 + s[1][5] = MP_DIGIT(a, 22); 1.59 + s[1][6] = MP_DIGIT(a, 23); 1.60 + s[1][7] = 0; 1.61 + s[1][8] = 0; 1.62 + s[1][9] = 0; 1.63 + s[1][10] = 0; 1.64 + s[1][11] = 0; 1.65 + for (i = 0; i < 12; i++) { 1.66 + s[2][i] = MP_DIGIT(a, i+12); 1.67 + } 1.68 + s[3][0] = MP_DIGIT(a, 21); 1.69 + s[3][1] = MP_DIGIT(a, 22); 1.70 + s[3][2] = MP_DIGIT(a, 23); 1.71 + for (i = 3; i < 12; i++) { 1.72 + s[3][i] = MP_DIGIT(a, i+9); 1.73 + } 1.74 + s[4][0] = 0; 1.75 + s[4][1] = MP_DIGIT(a, 23); 1.76 + s[4][2] = 0; 1.77 + s[4][3] = MP_DIGIT(a, 20); 1.78 + for (i = 4; i < 12; i++) { 1.79 + s[4][i] = MP_DIGIT(a, i+8); 1.80 + } 1.81 + s[5][0] = 0; 1.82 + s[5][1] = 0; 1.83 + s[5][2] = 0; 1.84 + s[5][3] = 0; 1.85 + s[5][4] = MP_DIGIT(a, 20); 1.86 + s[5][5] = MP_DIGIT(a, 21); 1.87 + s[5][6] = MP_DIGIT(a, 22); 1.88 + s[5][7] = MP_DIGIT(a, 23); 1.89 + s[5][8] = 0; 1.90 + s[5][9] = 0; 1.91 + s[5][10] = 0; 1.92 + s[5][11] = 0; 1.93 + s[6][0] = MP_DIGIT(a, 20); 1.94 + s[6][1] = 0; 1.95 + s[6][2] = 0; 1.96 + s[6][3] = MP_DIGIT(a, 21); 1.97 + s[6][4] = MP_DIGIT(a, 22); 1.98 + s[6][5] = MP_DIGIT(a, 23); 1.99 + s[6][6] = 0; 1.100 + s[6][7] = 0; 1.101 + s[6][8] = 0; 1.102 + s[6][9] = 0; 1.103 + s[6][10] = 0; 1.104 + s[6][11] = 0; 1.105 + s[7][0] = MP_DIGIT(a, 23); 1.106 + for (i = 1; i < 12; i++) { 1.107 + s[7][i] = MP_DIGIT(a, i+11); 1.108 + } 1.109 + s[8][0] = 0; 1.110 + s[8][1] = MP_DIGIT(a, 20); 1.111 + s[8][2] = MP_DIGIT(a, 21); 1.112 + s[8][3] = MP_DIGIT(a, 22); 1.113 + s[8][4] = MP_DIGIT(a, 23); 1.114 + s[8][5] = 0; 1.115 + s[8][6] = 0; 1.116 + s[8][7] = 0; 1.117 + s[8][8] = 0; 1.118 + s[8][9] = 0; 1.119 + s[8][10] = 0; 1.120 + s[8][11] = 0; 1.121 + s[9][0] = 0; 1.122 + s[9][1] = 0; 1.123 + s[9][2] = 0; 1.124 + s[9][3] = MP_DIGIT(a, 23); 1.125 + s[9][4] = MP_DIGIT(a, 23); 1.126 + s[9][5] = 0; 1.127 + s[9][6] = 0; 1.128 + s[9][7] = 0; 1.129 + s[9][8] = 0; 1.130 + s[9][9] = 0; 1.131 + s[9][10] = 0; 1.132 + s[9][11] = 0; 1.133 + 1.134 + MP_CHECKOK(mp_add(&m[0], &m[1], r)); 1.135 + MP_CHECKOK(mp_add(r, &m[1], r)); 1.136 + MP_CHECKOK(mp_add(r, &m[2], r)); 1.137 + MP_CHECKOK(mp_add(r, &m[3], r)); 1.138 + MP_CHECKOK(mp_add(r, &m[4], r)); 1.139 + MP_CHECKOK(mp_add(r, &m[5], r)); 1.140 + MP_CHECKOK(mp_add(r, &m[6], r)); 1.141 + MP_CHECKOK(mp_sub(r, &m[7], r)); 1.142 + MP_CHECKOK(mp_sub(r, &m[8], r)); 1.143 + MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); 1.144 + s_mp_clamp(r); 1.145 + } 1.146 +#else 1.147 + /* for polynomials larger than twice the field size or polynomials 1.148 + * not using all words, use regular reduction */ 1.149 + if ((a_bits > 768) || (a_bits <= 736)) { 1.150 + MP_CHECKOK(mp_mod(a, &meth->irr, r)); 1.151 + } else { 1.152 + for (i = 0; i < 6; i++) { 1.153 + s[0][i] = MP_DIGIT(a, i); 1.154 + } 1.155 + s[1][0] = 0; 1.156 + s[1][1] = 0; 1.157 + s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); 1.158 + s[1][3] = MP_DIGIT(a, 11) >> 32; 1.159 + s[1][4] = 0; 1.160 + s[1][5] = 0; 1.161 + for (i = 0; i < 6; i++) { 1.162 + s[2][i] = MP_DIGIT(a, i+6); 1.163 + } 1.164 + s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); 1.165 + s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); 1.166 + for (i = 2; i < 6; i++) { 1.167 + s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32); 1.168 + } 1.169 + s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32; 1.170 + s[4][1] = MP_DIGIT(a, 10) << 32; 1.171 + for (i = 2; i < 6; i++) { 1.172 + s[4][i] = MP_DIGIT(a, i+4); 1.173 + } 1.174 + s[5][0] = 0; 1.175 + s[5][1] = 0; 1.176 + s[5][2] = MP_DIGIT(a, 10); 1.177 + s[5][3] = MP_DIGIT(a, 11); 1.178 + s[5][4] = 0; 1.179 + s[5][5] = 0; 1.180 + s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32; 1.181 + s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32; 1.182 + s[6][2] = MP_DIGIT(a, 11); 1.183 + s[6][3] = 0; 1.184 + s[6][4] = 0; 1.185 + s[6][5] = 0; 1.186 + s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); 1.187 + for (i = 1; i < 6; i++) { 1.188 + s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32); 1.189 + } 1.190 + s[8][0] = MP_DIGIT(a, 10) << 32; 1.191 + s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); 1.192 + s[8][2] = MP_DIGIT(a, 11) >> 32; 1.193 + s[8][3] = 0; 1.194 + s[8][4] = 0; 1.195 + s[8][5] = 0; 1.196 + s[9][0] = 0; 1.197 + s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32; 1.198 + s[9][2] = MP_DIGIT(a, 11) >> 32; 1.199 + s[9][3] = 0; 1.200 + s[9][4] = 0; 1.201 + s[9][5] = 0; 1.202 + 1.203 + MP_CHECKOK(mp_add(&m[0], &m[1], r)); 1.204 + MP_CHECKOK(mp_add(r, &m[1], r)); 1.205 + MP_CHECKOK(mp_add(r, &m[2], r)); 1.206 + MP_CHECKOK(mp_add(r, &m[3], r)); 1.207 + MP_CHECKOK(mp_add(r, &m[4], r)); 1.208 + MP_CHECKOK(mp_add(r, &m[5], r)); 1.209 + MP_CHECKOK(mp_add(r, &m[6], r)); 1.210 + MP_CHECKOK(mp_sub(r, &m[7], r)); 1.211 + MP_CHECKOK(mp_sub(r, &m[8], r)); 1.212 + MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); 1.213 + s_mp_clamp(r); 1.214 + } 1.215 +#endif 1.216 + 1.217 + CLEANUP: 1.218 + return res; 1.219 +} 1.220 + 1.221 +/* Compute the square of polynomial a, reduce modulo p384. Store the 1.222 + * result in r. r could be a. Uses optimized modular reduction for p384. 1.223 + */ 1.224 +static mp_err 1.225 +ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) 1.226 +{ 1.227 + mp_err res = MP_OKAY; 1.228 + 1.229 + MP_CHECKOK(mp_sqr(a, r)); 1.230 + MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); 1.231 + CLEANUP: 1.232 + return res; 1.233 +} 1.234 + 1.235 +/* Compute the product of two polynomials a and b, reduce modulo p384. 1.236 + * Store the result in r. r could be a or b; a could be b. Uses 1.237 + * optimized modular reduction for p384. */ 1.238 +static mp_err 1.239 +ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r, 1.240 + const GFMethod *meth) 1.241 +{ 1.242 + mp_err res = MP_OKAY; 1.243 + 1.244 + MP_CHECKOK(mp_mul(a, b, r)); 1.245 + MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); 1.246 + CLEANUP: 1.247 + return res; 1.248 +} 1.249 + 1.250 +/* Wire in fast field arithmetic and precomputation of base point for 1.251 + * named curves. */ 1.252 +mp_err 1.253 +ec_group_set_gfp384(ECGroup *group, ECCurveName name) 1.254 +{ 1.255 + if (name == ECCurve_NIST_P384) { 1.256 + group->meth->field_mod = &ec_GFp_nistp384_mod; 1.257 + group->meth->field_mul = &ec_GFp_nistp384_mul; 1.258 + group->meth->field_sqr = &ec_GFp_nistp384_sqr; 1.259 + } 1.260 + return MP_OKAY; 1.261 +}