OLD | NEW |
(Empty) | |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 |
| 5 #include "ecp.h" |
| 6 #include "mpi.h" |
| 7 #include "mplogic.h" |
| 8 #include "mpi-priv.h" |
| 9 |
| 10 /* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be
r. |
| 11 * Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to |
| 12 * Elliptic Curve Cryptography. */ |
| 13 static mp_err |
| 14 ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth) |
| 15 { |
| 16 mp_err res = MP_OKAY; |
| 17 int a_bits = mpl_significant_bits(a); |
| 18 int i; |
| 19 |
| 20 /* m1, m2 are statically-allocated mp_int of exactly the size we need */ |
| 21 mp_int m[10]; |
| 22 |
| 23 #ifdef ECL_THIRTY_TWO_BIT |
| 24 mp_digit s[10][12]; |
| 25 for (i = 0; i < 10; i++) { |
| 26 MP_SIGN(&m[i]) = MP_ZPOS; |
| 27 MP_ALLOC(&m[i]) = 12; |
| 28 MP_USED(&m[i]) = 12; |
| 29 MP_DIGITS(&m[i]) = s[i]; |
| 30 } |
| 31 #else |
| 32 mp_digit s[10][6]; |
| 33 for (i = 0; i < 10; i++) { |
| 34 MP_SIGN(&m[i]) = MP_ZPOS; |
| 35 MP_ALLOC(&m[i]) = 6; |
| 36 MP_USED(&m[i]) = 6; |
| 37 MP_DIGITS(&m[i]) = s[i]; |
| 38 } |
| 39 #endif |
| 40 |
| 41 #ifdef ECL_THIRTY_TWO_BIT |
| 42 /* for polynomials larger than twice the field size or polynomials |
| 43 * not using all words, use regular reduction */ |
| 44 if ((a_bits > 768) || (a_bits <= 736)) { |
| 45 MP_CHECKOK(mp_mod(a, &meth->irr, r)); |
| 46 } else { |
| 47 for (i = 0; i < 12; i++) { |
| 48 s[0][i] = MP_DIGIT(a, i); |
| 49 } |
| 50 s[1][0] = 0; |
| 51 s[1][1] = 0; |
| 52 s[1][2] = 0; |
| 53 s[1][3] = 0; |
| 54 s[1][4] = MP_DIGIT(a, 21); |
| 55 s[1][5] = MP_DIGIT(a, 22); |
| 56 s[1][6] = MP_DIGIT(a, 23); |
| 57 s[1][7] = 0; |
| 58 s[1][8] = 0; |
| 59 s[1][9] = 0; |
| 60 s[1][10] = 0; |
| 61 s[1][11] = 0; |
| 62 for (i = 0; i < 12; i++) { |
| 63 s[2][i] = MP_DIGIT(a, i+12); |
| 64 } |
| 65 s[3][0] = MP_DIGIT(a, 21); |
| 66 s[3][1] = MP_DIGIT(a, 22); |
| 67 s[3][2] = MP_DIGIT(a, 23); |
| 68 for (i = 3; i < 12; i++) { |
| 69 s[3][i] = MP_DIGIT(a, i+9); |
| 70 } |
| 71 s[4][0] = 0; |
| 72 s[4][1] = MP_DIGIT(a, 23); |
| 73 s[4][2] = 0; |
| 74 s[4][3] = MP_DIGIT(a, 20); |
| 75 for (i = 4; i < 12; i++) { |
| 76 s[4][i] = MP_DIGIT(a, i+8); |
| 77 } |
| 78 s[5][0] = 0; |
| 79 s[5][1] = 0; |
| 80 s[5][2] = 0; |
| 81 s[5][3] = 0; |
| 82 s[5][4] = MP_DIGIT(a, 20); |
| 83 s[5][5] = MP_DIGIT(a, 21); |
| 84 s[5][6] = MP_DIGIT(a, 22); |
| 85 s[5][7] = MP_DIGIT(a, 23); |
| 86 s[5][8] = 0; |
| 87 s[5][9] = 0; |
| 88 s[5][10] = 0; |
| 89 s[5][11] = 0; |
| 90 s[6][0] = MP_DIGIT(a, 20); |
| 91 s[6][1] = 0; |
| 92 s[6][2] = 0; |
| 93 s[6][3] = MP_DIGIT(a, 21); |
| 94 s[6][4] = MP_DIGIT(a, 22); |
| 95 s[6][5] = MP_DIGIT(a, 23); |
| 96 s[6][6] = 0; |
| 97 s[6][7] = 0; |
| 98 s[6][8] = 0; |
| 99 s[6][9] = 0; |
| 100 s[6][10] = 0; |
| 101 s[6][11] = 0; |
| 102 s[7][0] = MP_DIGIT(a, 23); |
| 103 for (i = 1; i < 12; i++) { |
| 104 s[7][i] = MP_DIGIT(a, i+11); |
| 105 } |
| 106 s[8][0] = 0; |
| 107 s[8][1] = MP_DIGIT(a, 20); |
| 108 s[8][2] = MP_DIGIT(a, 21); |
| 109 s[8][3] = MP_DIGIT(a, 22); |
| 110 s[8][4] = MP_DIGIT(a, 23); |
| 111 s[8][5] = 0; |
| 112 s[8][6] = 0; |
| 113 s[8][7] = 0; |
| 114 s[8][8] = 0; |
| 115 s[8][9] = 0; |
| 116 s[8][10] = 0; |
| 117 s[8][11] = 0; |
| 118 s[9][0] = 0; |
| 119 s[9][1] = 0; |
| 120 s[9][2] = 0; |
| 121 s[9][3] = MP_DIGIT(a, 23); |
| 122 s[9][4] = MP_DIGIT(a, 23); |
| 123 s[9][5] = 0; |
| 124 s[9][6] = 0; |
| 125 s[9][7] = 0; |
| 126 s[9][8] = 0; |
| 127 s[9][9] = 0; |
| 128 s[9][10] = 0; |
| 129 s[9][11] = 0; |
| 130 |
| 131 MP_CHECKOK(mp_add(&m[0], &m[1], r)); |
| 132 MP_CHECKOK(mp_add(r, &m[1], r)); |
| 133 MP_CHECKOK(mp_add(r, &m[2], r)); |
| 134 MP_CHECKOK(mp_add(r, &m[3], r)); |
| 135 MP_CHECKOK(mp_add(r, &m[4], r)); |
| 136 MP_CHECKOK(mp_add(r, &m[5], r)); |
| 137 MP_CHECKOK(mp_add(r, &m[6], r)); |
| 138 MP_CHECKOK(mp_sub(r, &m[7], r)); |
| 139 MP_CHECKOK(mp_sub(r, &m[8], r)); |
| 140 MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); |
| 141 s_mp_clamp(r); |
| 142 } |
| 143 #else |
| 144 /* for polynomials larger than twice the field size or polynomials |
| 145 * not using all words, use regular reduction */ |
| 146 if ((a_bits > 768) || (a_bits <= 736)) { |
| 147 MP_CHECKOK(mp_mod(a, &meth->irr, r)); |
| 148 } else { |
| 149 for (i = 0; i < 6; i++) { |
| 150 s[0][i] = MP_DIGIT(a, i); |
| 151 } |
| 152 s[1][0] = 0; |
| 153 s[1][1] = 0; |
| 154 s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); |
| 155 s[1][3] = MP_DIGIT(a, 11) >> 32; |
| 156 s[1][4] = 0; |
| 157 s[1][5] = 0; |
| 158 for (i = 0; i < 6; i++) { |
| 159 s[2][i] = MP_DIGIT(a, i+6); |
| 160 } |
| 161 s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); |
| 162 s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); |
| 163 for (i = 2; i < 6; i++) { |
| 164 s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) <
< 32); |
| 165 } |
| 166 s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32; |
| 167 s[4][1] = MP_DIGIT(a, 10) << 32; |
| 168 for (i = 2; i < 6; i++) { |
| 169 s[4][i] = MP_DIGIT(a, i+4); |
| 170 } |
| 171 s[5][0] = 0; |
| 172 s[5][1] = 0; |
| 173 s[5][2] = MP_DIGIT(a, 10); |
| 174 s[5][3] = MP_DIGIT(a, 11); |
| 175 s[5][4] = 0; |
| 176 s[5][5] = 0; |
| 177 s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32; |
| 178 s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32; |
| 179 s[6][2] = MP_DIGIT(a, 11); |
| 180 s[6][3] = 0; |
| 181 s[6][4] = 0; |
| 182 s[6][5] = 0; |
| 183 s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); |
| 184 for (i = 1; i < 6; i++) { |
| 185 s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) <
< 32); |
| 186 } |
| 187 s[8][0] = MP_DIGIT(a, 10) << 32; |
| 188 s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); |
| 189 s[8][2] = MP_DIGIT(a, 11) >> 32; |
| 190 s[8][3] = 0; |
| 191 s[8][4] = 0; |
| 192 s[8][5] = 0; |
| 193 s[9][0] = 0; |
| 194 s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32; |
| 195 s[9][2] = MP_DIGIT(a, 11) >> 32; |
| 196 s[9][3] = 0; |
| 197 s[9][4] = 0; |
| 198 s[9][5] = 0; |
| 199 |
| 200 MP_CHECKOK(mp_add(&m[0], &m[1], r)); |
| 201 MP_CHECKOK(mp_add(r, &m[1], r)); |
| 202 MP_CHECKOK(mp_add(r, &m[2], r)); |
| 203 MP_CHECKOK(mp_add(r, &m[3], r)); |
| 204 MP_CHECKOK(mp_add(r, &m[4], r)); |
| 205 MP_CHECKOK(mp_add(r, &m[5], r)); |
| 206 MP_CHECKOK(mp_add(r, &m[6], r)); |
| 207 MP_CHECKOK(mp_sub(r, &m[7], r)); |
| 208 MP_CHECKOK(mp_sub(r, &m[8], r)); |
| 209 MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); |
| 210 s_mp_clamp(r); |
| 211 } |
| 212 #endif |
| 213 |
| 214 CLEANUP: |
| 215 return res; |
| 216 } |
| 217 |
| 218 /* Compute the square of polynomial a, reduce modulo p384. Store the |
| 219 * result in r. r could be a. Uses optimized modular reduction for p384. |
| 220 */ |
| 221 static mp_err |
| 222 ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) |
| 223 { |
| 224 mp_err res = MP_OKAY; |
| 225 |
| 226 MP_CHECKOK(mp_sqr(a, r)); |
| 227 MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); |
| 228 CLEANUP: |
| 229 return res; |
| 230 } |
| 231 |
| 232 /* Compute the product of two polynomials a and b, reduce modulo p384. |
| 233 * Store the result in r. r could be a or b; a could be b. Uses |
| 234 * optimized modular reduction for p384. */ |
| 235 static mp_err |
| 236 ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r, |
| 237 const GFMethod *meth) |
| 238 { |
| 239 mp_err res = MP_OKAY; |
| 240 |
| 241 MP_CHECKOK(mp_mul(a, b, r)); |
| 242 MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); |
| 243 CLEANUP: |
| 244 return res; |
| 245 } |
| 246 |
| 247 /* Wire in fast field arithmetic and precomputation of base point for |
| 248 * named curves. */ |
| 249 mp_err |
| 250 ec_group_set_gfp384(ECGroup *group, ECCurveName name) |
| 251 { |
| 252 if (name == ECCurve_NIST_P384) { |
| 253 group->meth->field_mod = &ec_GFp_nistp384_mod; |
| 254 group->meth->field_mul = &ec_GFp_nistp384_mul; |
| 255 group->meth->field_sqr = &ec_GFp_nistp384_sqr; |
| 256 } |
| 257 return MP_OKAY; |
| 258 } |
OLD | NEW |