Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_microECC Wallet_v1
curve-specific.h
00001 /* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ 00002 00003 #ifndef _UECC_CURVE_SPECIFIC_H_ 00004 #define _UECC_CURVE_SPECIFIC_H_ 00005 00006 #define num_bytes_secp160r1 20 00007 #define num_bytes_secp192r1 24 00008 #define num_bytes_secp224r1 28 00009 #define num_bytes_secp256r1 32 00010 #define num_bytes_secp256k1 32 00011 00012 #if (uECC_WORD_SIZE == 1) 00013 00014 #define num_words_secp160r1 20 00015 #define num_words_secp192r1 24 00016 #define num_words_secp224r1 28 00017 #define num_words_secp256r1 32 00018 #define num_words_secp256k1 32 00019 00020 #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \ 00021 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h 00022 #define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d 00023 00024 #elif (uECC_WORD_SIZE == 4) 00025 00026 #define num_words_secp160r1 5 00027 #define num_words_secp192r1 6 00028 #define num_words_secp224r1 7 00029 #define num_words_secp256r1 8 00030 #define num_words_secp256k1 8 00031 00032 #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e 00033 #define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a 00034 00035 #elif (uECC_WORD_SIZE == 8) 00036 00037 #define num_words_secp160r1 3 00038 #define num_words_secp192r1 3 00039 #define num_words_secp224r1 4 00040 #define num_words_secp256r1 4 00041 #define num_words_secp256k1 4 00042 00043 #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##ull 00044 #define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##ull 00045 00046 #endif /* uECC_WORD_SIZE */ 00047 00048 #if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ 00049 uECC_SUPPORTS_secp224r1 || uECC_SUPPORTS_secp256r1 00050 static void double_jacobian_default(uECC_word_t * X1, 00051 uECC_word_t * Y1, 00052 uECC_word_t * Z1, 00053 uECC_Curve curve) { 00054 /* t1 = X, t2 = Y, t3 = Z */ 00055 uECC_word_t t4[uECC_MAX_WORDS]; 00056 uECC_word_t t5[uECC_MAX_WORDS]; 00057 wordcount_t num_words = curve->num_words; 00058 00059 if (uECC_vli_isZero(Z1, num_words)) { 00060 return; 00061 } 00062 00063 uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ 00064 uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ 00065 uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ 00066 uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ 00067 uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ 00068 00069 uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ 00070 uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ 00071 uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ 00072 uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ 00073 00074 uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ 00075 uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ 00076 if (uECC_vli_testBit(X1, 0)) { 00077 uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); 00078 uECC_vli_rshift1(X1, num_words); 00079 X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); 00080 } else { 00081 uECC_vli_rshift1(X1, num_words); 00082 } 00083 /* t1 = 3/2*(x1^2 - z1^4) = B */ 00084 00085 uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ 00086 uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ 00087 uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ 00088 uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ 00089 uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ 00090 uECC_vli_modSub(t4, X1, t4, curve->p, num_words); /* t4 = B * (A - x3) - y1^4 = y3 */ 00091 00092 uECC_vli_set(X1, Z1, num_words); 00093 uECC_vli_set(Z1, Y1, num_words); 00094 uECC_vli_set(Y1, t4, num_words); 00095 } 00096 00097 /* Computes result = x^3 + ax + b. result must not overlap x. */ 00098 static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { 00099 uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */ 00100 wordcount_t num_words = curve->num_words; 00101 00102 uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ 00103 uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ 00104 uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ 00105 uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); /* r = x^3 - 3x + b */ 00106 } 00107 #endif /* uECC_SUPPORTS_secp... */ 00108 00109 #if uECC_SUPPORT_COMPRESSED_POINT 00110 #if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ 00111 uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 00112 /* Compute a = sqrt(a) (mod curve_p). */ 00113 static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { 00114 bitcount_t i; 00115 uECC_word_t p1[uECC_MAX_WORDS] = {1}; 00116 uECC_word_t l_result[uECC_MAX_WORDS] = {1}; 00117 wordcount_t num_words = curve->num_words; 00118 00119 /* When curve->p == 3 (mod 4), we can compute 00120 sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */ 00121 uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */ 00122 for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) { 00123 uECC_vli_modSquare_fast(l_result, l_result, curve); 00124 if (uECC_vli_testBit(p1, i)) { 00125 uECC_vli_modMult_fast(l_result, l_result, a, curve); 00126 } 00127 } 00128 uECC_vli_set(a, l_result, num_words); 00129 } 00130 #endif /* uECC_SUPPORTS_secp... */ 00131 #endif /* uECC_SUPPORT_COMPRESSED_POINT */ 00132 00133 #if uECC_SUPPORTS_secp160r1 00134 00135 #if (uECC_OPTIMIZATION_LEVEL > 0) 00136 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product); 00137 #endif 00138 00139 static const struct uECC_Curve_t curve_secp160r1 = { 00140 num_words_secp160r1, 00141 num_bytes_secp160r1, 00142 161, /* num_n_bits */ 00143 { BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF), 00144 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 00145 BYTES_TO_WORDS_4(FF, FF, FF, FF) }, 00146 { BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9), 00147 BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00), 00148 BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00) }, 00149 { BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68), 00150 BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E), 00151 BYTES_TO_WORDS_4(68, B5, 96, 4A), 00152 00153 BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04), 00154 BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31), 00155 BYTES_TO_WORDS_4(55, 28, A6, 23) }, 00156 { BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81), 00157 BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54), 00158 BYTES_TO_WORDS_4(FC, BE, 97, 1C) }, 00159 &double_jacobian_default, 00160 #if uECC_SUPPORT_COMPRESSED_POINT 00161 &mod_sqrt_default, 00162 #endif 00163 &x_side_default, 00164 #if (uECC_OPTIMIZATION_LEVEL > 0) 00165 &vli_mmod_fast_secp160r1 00166 #endif 00167 }; 00168 00169 uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; } 00170 00171 #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) 00172 /* Computes result = product % curve_p 00173 see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354 00174 00175 Note that this only works if log2(omega) < log2(p) / 2 */ 00176 static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right); 00177 #if uECC_WORD_SIZE == 8 00178 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { 00179 uECC_word_t tmp[2 * num_words_secp160r1]; 00180 uECC_word_t copy; 00181 00182 uECC_vli_clear(tmp, num_words_secp160r1); 00183 uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1); 00184 00185 omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */ 00186 00187 product[num_words_secp160r1 - 1] &= 0xffffffff; 00188 copy = tmp[num_words_secp160r1 - 1]; 00189 tmp[num_words_secp160r1 - 1] &= 0xffffffff; 00190 uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */ 00191 uECC_vli_clear(product, num_words_secp160r1); 00192 tmp[num_words_secp160r1 - 1] = copy; 00193 omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */ 00194 uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */ 00195 00196 while (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) { 00197 uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); 00198 } 00199 } 00200 00201 static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) { 00202 uint32_t carry; 00203 unsigned i; 00204 00205 /* Multiply by (2^31 + 1). */ 00206 carry = 0; 00207 for (i = 0; i < num_words_secp160r1; ++i) { 00208 uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32); 00209 result[i] = (tmp << 31) + tmp + carry; 00210 carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp)); 00211 } 00212 result[i] = carry; 00213 } 00214 #else 00215 static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { 00216 uECC_word_t tmp[2 * num_words_secp160r1]; 00217 uECC_word_t carry; 00218 00219 uECC_vli_clear(tmp, num_words_secp160r1); 00220 uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1); 00221 00222 omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */ 00223 00224 carry = uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */ 00225 uECC_vli_clear(product, num_words_secp160r1); 00226 omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */ 00227 carry += uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */ 00228 00229 while (carry > 0) { 00230 --carry; 00231 uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); 00232 } 00233 if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) { 00234 uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); 00235 } 00236 } 00237 #endif 00238 00239 #if uECC_WORD_SIZE == 1 00240 static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) { 00241 uint8_t carry; 00242 uint8_t i; 00243 00244 /* Multiply by (2^31 + 1). */ 00245 uECC_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */ 00246 uECC_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */ 00247 result[3] = right[0] << 7; /* get last bit from shift */ 00248 00249 carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */ 00250 for (i = num_words_secp160r1; carry; ++i) { 00251 uint16_t sum = (uint16_t)result[i] + carry; 00252 result[i] = (uint8_t)sum; 00253 carry = sum >> 8; 00254 } 00255 } 00256 #elif uECC_WORD_SIZE == 4 00257 static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) { 00258 uint32_t carry; 00259 unsigned i; 00260 00261 /* Multiply by (2^31 + 1). */ 00262 uECC_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */ 00263 uECC_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */ 00264 result[0] = right[0] << 31; /* get last bit from shift */ 00265 00266 carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */ 00267 for (i = num_words_secp160r1; carry; ++i) { 00268 uint64_t sum = (uint64_t)result[i] + carry; 00269 result[i] = (uint32_t)sum; 00270 carry = sum >> 32; 00271 } 00272 } 00273 #endif /* uECC_WORD_SIZE */ 00274 #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */ 00275 00276 #endif /* uECC_SUPPORTS_secp160r1 */ 00277 00278 #if uECC_SUPPORTS_secp192r1 00279 00280 #if (uECC_OPTIMIZATION_LEVEL > 0) 00281 static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product); 00282 #endif 00283 00284 static const struct uECC_Curve_t curve_secp192r1 = { 00285 num_words_secp192r1, 00286 num_bytes_secp192r1, 00287 192, /* num_n_bits */ 00288 { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 00289 BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF), 00290 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, 00291 { BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14), 00292 BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF), 00293 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, 00294 { BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4), 00295 BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C), 00296 BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18), 00297 00298 BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73), 00299 BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63), 00300 BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07) }, 00301 { BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE), 00302 BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F), 00303 BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64) }, 00304 &double_jacobian_default, 00305 #if uECC_SUPPORT_COMPRESSED_POINT 00306 &mod_sqrt_default, 00307 #endif 00308 &x_side_default, 00309 #if (uECC_OPTIMIZATION_LEVEL > 0) 00310 &vli_mmod_fast_secp192r1 00311 #endif 00312 }; 00313 00314 uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; } 00315 00316 #if (uECC_OPTIMIZATION_LEVEL > 0) 00317 /* Computes result = product % curve_p. 00318 See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */ 00319 #if uECC_WORD_SIZE == 1 00320 static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) { 00321 uint8_t tmp[num_words_secp192r1]; 00322 uint8_t carry; 00323 00324 uECC_vli_set(result, product, num_words_secp192r1); 00325 00326 uECC_vli_set(tmp, &product[24], num_words_secp192r1); 00327 carry = uECC_vli_add(result, result, tmp, num_words_secp192r1); 00328 00329 tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; 00330 tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27]; 00331 tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31]; 00332 tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35]; 00333 tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39]; 00334 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); 00335 00336 tmp[0] = tmp[8] = product[40]; 00337 tmp[1] = tmp[9] = product[41]; 00338 tmp[2] = tmp[10] = product[42]; 00339 tmp[3] = tmp[11] = product[43]; 00340 tmp[4] = tmp[12] = product[44]; 00341 tmp[5] = tmp[13] = product[45]; 00342 tmp[6] = tmp[14] = product[46]; 00343 tmp[7] = tmp[15] = product[47]; 00344 tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; 00345 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); 00346 00347 while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { 00348 carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); 00349 } 00350 } 00351 #elif uECC_WORD_SIZE == 4 00352 static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) { 00353 uint32_t tmp[num_words_secp192r1]; 00354 int carry; 00355 00356 uECC_vli_set(result, product, num_words_secp192r1); 00357 00358 uECC_vli_set(tmp, &product[6], num_words_secp192r1); 00359 carry = uECC_vli_add(result, result, tmp, num_words_secp192r1); 00360 00361 tmp[0] = tmp[1] = 0; 00362 tmp[2] = product[6]; 00363 tmp[3] = product[7]; 00364 tmp[4] = product[8]; 00365 tmp[5] = product[9]; 00366 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); 00367 00368 tmp[0] = tmp[2] = product[10]; 00369 tmp[1] = tmp[3] = product[11]; 00370 tmp[4] = tmp[5] = 0; 00371 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); 00372 00373 while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { 00374 carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); 00375 } 00376 } 00377 #else 00378 static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) { 00379 uint64_t tmp[num_words_secp192r1]; 00380 int carry; 00381 00382 uECC_vli_set(result, product, num_words_secp192r1); 00383 00384 uECC_vli_set(tmp, &product[3], num_words_secp192r1); 00385 carry = (int)uECC_vli_add(result, result, tmp, num_words_secp192r1); 00386 00387 tmp[0] = 0; 00388 tmp[1] = product[3]; 00389 tmp[2] = product[4]; 00390 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); 00391 00392 tmp[0] = tmp[1] = product[5]; 00393 tmp[2] = 0; 00394 carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); 00395 00396 while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { 00397 carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); 00398 } 00399 } 00400 #endif /* uECC_WORD_SIZE */ 00401 #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */ 00402 00403 #endif /* uECC_SUPPORTS_secp192r1 */ 00404 00405 #if uECC_SUPPORTS_secp224r1 00406 00407 #if uECC_SUPPORT_COMPRESSED_POINT 00408 static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve); 00409 #endif 00410 #if (uECC_OPTIMIZATION_LEVEL > 0) 00411 static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product); 00412 #endif 00413 00414 static const struct uECC_Curve_t curve_secp224r1 = { 00415 num_words_secp224r1, 00416 num_bytes_secp224r1, 00417 224, /* num_n_bits */ 00418 { BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00), 00419 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF), 00420 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 00421 BYTES_TO_WORDS_4(FF, FF, FF, FF) }, 00422 { BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13), 00423 BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF), 00424 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 00425 BYTES_TO_WORDS_4(FF, FF, FF, FF) }, 00426 { BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34), 00427 BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A), 00428 BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B), 00429 BYTES_TO_WORDS_4(BD, 0C, 0E, B7), 00430 00431 BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44), 00432 BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD), 00433 BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5), 00434 BYTES_TO_WORDS_4(88, 63, 37, BD) }, 00435 { BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27), 00436 BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50), 00437 BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C), 00438 BYTES_TO_WORDS_4(85, 0A, 05, B4) }, 00439 &double_jacobian_default, 00440 #if uECC_SUPPORT_COMPRESSED_POINT 00441 &mod_sqrt_secp224r1, 00442 #endif 00443 &x_side_default, 00444 #if (uECC_OPTIMIZATION_LEVEL > 0) 00445 &vli_mmod_fast_secp224r1 00446 #endif 00447 }; 00448 00449 uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; } 00450 00451 00452 #if uECC_SUPPORT_COMPRESSED_POINT 00453 /* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00454 static void mod_sqrt_secp224r1_rs(uECC_word_t *d1, 00455 uECC_word_t *e1, 00456 uECC_word_t *f1, 00457 const uECC_word_t *d0, 00458 const uECC_word_t *e0, 00459 const uECC_word_t *f0) { 00460 uECC_word_t t[num_words_secp224r1]; 00461 00462 uECC_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */ 00463 uECC_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */ 00464 uECC_vli_modAdd(d1, t, f0, curve_secp224r1.p, num_words_secp224r1); /* d1 <-- t + f0 */ 00465 uECC_vli_modAdd(e1, e1, e1, curve_secp224r1.p, num_words_secp224r1); /* e1 <-- e1 + e1 */ 00466 uECC_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */ 00467 uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */ 00468 uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */ 00469 } 00470 00471 /* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00472 static void mod_sqrt_secp224r1_rss(uECC_word_t *d1, 00473 uECC_word_t *e1, 00474 uECC_word_t *f1, 00475 const uECC_word_t *d0, 00476 const uECC_word_t *e0, 00477 const uECC_word_t *f0, 00478 const bitcount_t j) { 00479 bitcount_t i; 00480 00481 uECC_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */ 00482 uECC_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */ 00483 uECC_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */ 00484 for (i = 1; i <= j; i++) { 00485 mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */ 00486 } 00487 } 00488 00489 /* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00490 static void mod_sqrt_secp224r1_rm(uECC_word_t *d2, 00491 uECC_word_t *e2, 00492 uECC_word_t *f2, 00493 const uECC_word_t *c, 00494 const uECC_word_t *d0, 00495 const uECC_word_t *e0, 00496 const uECC_word_t *d1, 00497 const uECC_word_t *e1) { 00498 uECC_word_t t1[num_words_secp224r1]; 00499 uECC_word_t t2[num_words_secp224r1]; 00500 00501 uECC_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */ 00502 uECC_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */ 00503 /* t1 <-- p - t1 */ 00504 uECC_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p, num_words_secp224r1); 00505 uECC_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */ 00506 uECC_vli_modAdd(t2, t2, t1, curve_secp224r1.p, num_words_secp224r1); /* t2 <-- t2 + t1 */ 00507 uECC_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */ 00508 uECC_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */ 00509 uECC_vli_modAdd(e2, e2, t1, curve_secp224r1.p, num_words_secp224r1); /* e2 <-- e2 + t1 */ 00510 uECC_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */ 00511 uECC_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */ 00512 /* f2 <-- p - f2 */ 00513 uECC_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p, num_words_secp224r1); 00514 uECC_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */ 00515 } 00516 00517 /* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00518 static void mod_sqrt_secp224r1_rp(uECC_word_t *d1, 00519 uECC_word_t *e1, 00520 uECC_word_t *f1, 00521 const uECC_word_t *c, 00522 const uECC_word_t *r) { 00523 wordcount_t i; 00524 wordcount_t pow2i = 1; 00525 uECC_word_t d0[num_words_secp224r1]; 00526 uECC_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */ 00527 uECC_word_t f0[num_words_secp224r1]; 00528 00529 uECC_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */ 00530 /* f0 <-- p - c */ 00531 uECC_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p, num_words_secp224r1); 00532 for (i = 0; i <= 6; i++) { 00533 mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */ 00534 mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */ 00535 uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */ 00536 uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */ 00537 uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */ 00538 pow2i *= 2; 00539 } 00540 } 00541 00542 /* Compute a = sqrt(a) (mod curve_p). */ 00543 /* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00544 static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) { 00545 bitcount_t i; 00546 uECC_word_t e1[num_words_secp224r1]; 00547 uECC_word_t f1[num_words_secp224r1]; 00548 uECC_word_t d0[num_words_secp224r1]; 00549 uECC_word_t e0[num_words_secp224r1]; 00550 uECC_word_t f0[num_words_secp224r1]; 00551 uECC_word_t d1[num_words_secp224r1]; 00552 00553 /* s = a; using constant instead of random value */ 00554 mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */ 00555 mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */ 00556 for (i = 1; i <= 95; i++) { 00557 uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */ 00558 uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */ 00559 uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */ 00560 mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */ 00561 if (uECC_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */ 00562 break; 00563 } 00564 } 00565 uECC_vli_modInv(f1, e0, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- 1 / e0 */ 00566 uECC_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */ 00567 } 00568 #endif /* uECC_SUPPORT_COMPRESSED_POINT */ 00569 00570 #if (uECC_OPTIMIZATION_LEVEL > 0) 00571 /* Computes result = product % curve_p 00572 from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00573 #if uECC_WORD_SIZE == 1 00574 static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) { 00575 uint8_t tmp[num_words_secp224r1]; 00576 int8_t carry; 00577 00578 /* t */ 00579 uECC_vli_set(result, product, num_words_secp224r1); 00580 00581 /* s1 */ 00582 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; 00583 tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; 00584 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; 00585 tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31]; 00586 tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35]; 00587 tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39]; 00588 tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43]; 00589 carry = uECC_vli_add(result, result, tmp, num_words_secp224r1); 00590 00591 /* s2 */ 00592 tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47]; 00593 tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51]; 00594 tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55]; 00595 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; 00596 carry += uECC_vli_add(result, result, tmp, num_words_secp224r1); 00597 00598 /* d1 */ 00599 tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31]; 00600 tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35]; 00601 tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39]; 00602 tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43]; 00603 tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47]; 00604 tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51]; 00605 tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55]; 00606 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); 00607 00608 /* d2 */ 00609 tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47]; 00610 tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51]; 00611 tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55]; 00612 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; 00613 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; 00614 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; 00615 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; 00616 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); 00617 00618 if (carry < 0) { 00619 do { 00620 carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); 00621 } while (carry < 0); 00622 } else { 00623 while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { 00624 carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); 00625 } 00626 } 00627 } 00628 #elif uECC_WORD_SIZE == 4 00629 static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product) 00630 { 00631 uint32_t tmp[num_words_secp224r1]; 00632 int carry; 00633 00634 /* t */ 00635 uECC_vli_set(result, product, num_words_secp224r1); 00636 00637 /* s1 */ 00638 tmp[0] = tmp[1] = tmp[2] = 0; 00639 tmp[3] = product[7]; 00640 tmp[4] = product[8]; 00641 tmp[5] = product[9]; 00642 tmp[6] = product[10]; 00643 carry = uECC_vli_add(result, result, tmp, num_words_secp224r1); 00644 00645 /* s2 */ 00646 tmp[3] = product[11]; 00647 tmp[4] = product[12]; 00648 tmp[5] = product[13]; 00649 tmp[6] = 0; 00650 carry += uECC_vli_add(result, result, tmp, num_words_secp224r1); 00651 00652 /* d1 */ 00653 tmp[0] = product[7]; 00654 tmp[1] = product[8]; 00655 tmp[2] = product[9]; 00656 tmp[3] = product[10]; 00657 tmp[4] = product[11]; 00658 tmp[5] = product[12]; 00659 tmp[6] = product[13]; 00660 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); 00661 00662 /* d2 */ 00663 tmp[0] = product[11]; 00664 tmp[1] = product[12]; 00665 tmp[2] = product[13]; 00666 tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0; 00667 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); 00668 00669 if (carry < 0) { 00670 do { 00671 carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); 00672 } while (carry < 0); 00673 } else { 00674 while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { 00675 carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); 00676 } 00677 } 00678 } 00679 #else 00680 static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product) 00681 { 00682 uint64_t tmp[num_words_secp224r1]; 00683 int carry = 0; 00684 00685 /* t */ 00686 uECC_vli_set(result, product, num_words_secp224r1); 00687 result[num_words_secp224r1 - 1] &= 0xffffffff; 00688 00689 /* s1 */ 00690 tmp[0] = 0; 00691 tmp[1] = product[3] & 0xffffffff00000000ull; 00692 tmp[2] = product[4]; 00693 tmp[3] = product[5] & 0xffffffff; 00694 uECC_vli_add(result, result, tmp, num_words_secp224r1); 00695 00696 /* s2 */ 00697 tmp[1] = product[5] & 0xffffffff00000000ull; 00698 tmp[2] = product[6]; 00699 tmp[3] = 0; 00700 uECC_vli_add(result, result, tmp, num_words_secp224r1); 00701 00702 /* d1 */ 00703 tmp[0] = (product[3] >> 32) | (product[4] << 32); 00704 tmp[1] = (product[4] >> 32) | (product[5] << 32); 00705 tmp[2] = (product[5] >> 32) | (product[6] << 32); 00706 tmp[3] = product[6] >> 32; 00707 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); 00708 00709 /* d2 */ 00710 tmp[0] = (product[5] >> 32) | (product[6] << 32); 00711 tmp[1] = product[6] >> 32; 00712 tmp[2] = tmp[3] = 0; 00713 carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); 00714 00715 if (carry < 0) { 00716 do { 00717 carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); 00718 } while (carry < 0); 00719 } else { 00720 while (uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { 00721 uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); 00722 } 00723 } 00724 } 00725 #endif /* uECC_WORD_SIZE */ 00726 #endif /* (uECC_OPTIMIZATION_LEVEL > 0) */ 00727 00728 #endif /* uECC_SUPPORTS_secp224r1 */ 00729 00730 #if uECC_SUPPORTS_secp256r1 00731 00732 #if (uECC_OPTIMIZATION_LEVEL > 0) 00733 static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product); 00734 #endif 00735 00736 static const struct uECC_Curve_t curve_secp256r1 = { 00737 num_words_secp256r1, 00738 num_bytes_secp256r1, 00739 256, /* num_n_bits */ 00740 { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 00741 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), 00742 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), 00743 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) }, 00744 { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), 00745 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), 00746 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 00747 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) }, 00748 { BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), 00749 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), 00750 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), 00751 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), 00752 00753 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), 00754 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), 00755 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), 00756 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) }, 00757 { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), 00758 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), 00759 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), 00760 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) }, 00761 &double_jacobian_default, 00762 #if uECC_SUPPORT_COMPRESSED_POINT 00763 &mod_sqrt_default, 00764 #endif 00765 &x_side_default, 00766 #if (uECC_OPTIMIZATION_LEVEL > 0) 00767 &vli_mmod_fast_secp256r1 00768 #endif 00769 }; 00770 00771 uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; } 00772 00773 00774 #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) 00775 /* Computes result = product % curve_p 00776 from http://www.nsa.gov/ia/_files/nist-routines.pdf */ 00777 #if uECC_WORD_SIZE == 1 00778 static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) { 00779 uint8_t tmp[num_words_secp256r1]; 00780 int8_t carry; 00781 00782 /* t */ 00783 uECC_vli_set(result, product, num_words_secp256r1); 00784 00785 /* s1 */ 00786 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; 00787 tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; 00788 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; 00789 tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47]; 00790 tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51]; 00791 tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55]; 00792 tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59]; 00793 tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63]; 00794 carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); 00795 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00796 00797 /* s2 */ 00798 tmp[12] = product[48]; tmp[13] = product[49]; tmp[14] = product[50]; tmp[15] = product[51]; 00799 tmp[16] = product[52]; tmp[17] = product[53]; tmp[18] = product[54]; tmp[19] = product[55]; 00800 tmp[20] = product[56]; tmp[21] = product[57]; tmp[22] = product[58]; tmp[23] = product[59]; 00801 tmp[24] = product[60]; tmp[25] = product[61]; tmp[26] = product[62]; tmp[27] = product[63]; 00802 tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0; 00803 carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); 00804 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00805 00806 /* s3 */ 00807 tmp[0] = product[32]; tmp[1] = product[33]; tmp[2] = product[34]; tmp[3] = product[35]; 00808 tmp[4] = product[36]; tmp[5] = product[37]; tmp[6] = product[38]; tmp[7] = product[39]; 00809 tmp[8] = product[40]; tmp[9] = product[41]; tmp[10] = product[42]; tmp[11] = product[43]; 00810 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; 00811 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; 00812 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; 00813 tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59]; 00814 tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63]; 00815 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00816 00817 /* s4 */ 00818 tmp[0] = product[36]; tmp[1] = product[37]; tmp[2] = product[38]; tmp[3] = product[39]; 00819 tmp[4] = product[40]; tmp[5] = product[41]; tmp[6] = product[42]; tmp[7] = product[43]; 00820 tmp[8] = product[44]; tmp[9] = product[45]; tmp[10] = product[46]; tmp[11] = product[47]; 00821 tmp[12] = product[52]; tmp[13] = product[53]; tmp[14] = product[54]; tmp[15] = product[55]; 00822 tmp[16] = product[56]; tmp[17] = product[57]; tmp[18] = product[58]; tmp[19] = product[59]; 00823 tmp[20] = product[60]; tmp[21] = product[61]; tmp[22] = product[62]; tmp[23] = product[63]; 00824 tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55]; 00825 tmp[28] = product[32]; tmp[29] = product[33]; tmp[30] = product[34]; tmp[31] = product[35]; 00826 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00827 00828 /* d1 */ 00829 tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47]; 00830 tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51]; 00831 tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55]; 00832 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; 00833 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; 00834 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; 00835 tmp[24] = product[32]; tmp[25] = product[33]; tmp[26] = product[34]; tmp[27] = product[35]; 00836 tmp[28] = product[40]; tmp[29] = product[41]; tmp[30] = product[42]; tmp[31] = product[43]; 00837 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00838 00839 /* d2 */ 00840 tmp[0] = product[48]; tmp[1] = product[49]; tmp[2] = product[50]; tmp[3] = product[51]; 00841 tmp[4] = product[52]; tmp[5] = product[53]; tmp[6] = product[54]; tmp[7] = product[55]; 00842 tmp[8] = product[56]; tmp[9] = product[57]; tmp[10] = product[58]; tmp[11] = product[59]; 00843 tmp[12] = product[60]; tmp[13] = product[61]; tmp[14] = product[62]; tmp[15] = product[63]; 00844 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; 00845 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; 00846 tmp[24] = product[36]; tmp[25] = product[37]; tmp[26] = product[38]; tmp[27] = product[39]; 00847 tmp[28] = product[44]; tmp[29] = product[45]; tmp[30] = product[46]; tmp[31] = product[47]; 00848 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00849 00850 /* d3 */ 00851 tmp[0] = product[52]; tmp[1] = product[53]; tmp[2] = product[54]; tmp[3] = product[55]; 00852 tmp[4] = product[56]; tmp[5] = product[57]; tmp[6] = product[58]; tmp[7] = product[59]; 00853 tmp[8] = product[60]; tmp[9] = product[61]; tmp[10] = product[62]; tmp[11] = product[63]; 00854 tmp[12] = product[32]; tmp[13] = product[33]; tmp[14] = product[34]; tmp[15] = product[35]; 00855 tmp[16] = product[36]; tmp[17] = product[37]; tmp[18] = product[38]; tmp[19] = product[39]; 00856 tmp[20] = product[40]; tmp[21] = product[41]; tmp[22] = product[42]; tmp[23] = product[43]; 00857 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; 00858 tmp[28] = product[48]; tmp[29] = product[49]; tmp[30] = product[50]; tmp[31] = product[51]; 00859 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00860 00861 /* d4 */ 00862 tmp[0] = product[56]; tmp[1] = product[57]; tmp[2] = product[58]; tmp[3] = product[59]; 00863 tmp[4] = product[60]; tmp[5] = product[61]; tmp[6] = product[62]; tmp[7] = product[63]; 00864 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; 00865 tmp[12] = product[36]; tmp[13] = product[37]; tmp[14] = product[38]; tmp[15] = product[39]; 00866 tmp[16] = product[40]; tmp[17] = product[41]; tmp[18] = product[42]; tmp[19] = product[43]; 00867 tmp[20] = product[44]; tmp[21] = product[45]; tmp[22] = product[46]; tmp[23] = product[47]; 00868 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; 00869 tmp[28] = product[52]; tmp[29] = product[53]; tmp[30] = product[54]; tmp[31] = product[55]; 00870 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00871 00872 if (carry < 0) { 00873 do { 00874 carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); 00875 } while (carry < 0); 00876 } else { 00877 while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { 00878 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); 00879 } 00880 } 00881 } 00882 #elif uECC_WORD_SIZE == 4 00883 static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) { 00884 uint32_t tmp[num_words_secp256r1]; 00885 int carry; 00886 00887 /* t */ 00888 uECC_vli_set(result, product, num_words_secp256r1); 00889 00890 /* s1 */ 00891 tmp[0] = tmp[1] = tmp[2] = 0; 00892 tmp[3] = product[11]; 00893 tmp[4] = product[12]; 00894 tmp[5] = product[13]; 00895 tmp[6] = product[14]; 00896 tmp[7] = product[15]; 00897 carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); 00898 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00899 00900 /* s2 */ 00901 tmp[3] = product[12]; 00902 tmp[4] = product[13]; 00903 tmp[5] = product[14]; 00904 tmp[6] = product[15]; 00905 tmp[7] = 0; 00906 carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); 00907 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00908 00909 /* s3 */ 00910 tmp[0] = product[8]; 00911 tmp[1] = product[9]; 00912 tmp[2] = product[10]; 00913 tmp[3] = tmp[4] = tmp[5] = 0; 00914 tmp[6] = product[14]; 00915 tmp[7] = product[15]; 00916 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00917 00918 /* s4 */ 00919 tmp[0] = product[9]; 00920 tmp[1] = product[10]; 00921 tmp[2] = product[11]; 00922 tmp[3] = product[13]; 00923 tmp[4] = product[14]; 00924 tmp[5] = product[15]; 00925 tmp[6] = product[13]; 00926 tmp[7] = product[8]; 00927 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00928 00929 /* d1 */ 00930 tmp[0] = product[11]; 00931 tmp[1] = product[12]; 00932 tmp[2] = product[13]; 00933 tmp[3] = tmp[4] = tmp[5] = 0; 00934 tmp[6] = product[8]; 00935 tmp[7] = product[10]; 00936 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00937 00938 /* d2 */ 00939 tmp[0] = product[12]; 00940 tmp[1] = product[13]; 00941 tmp[2] = product[14]; 00942 tmp[3] = product[15]; 00943 tmp[4] = tmp[5] = 0; 00944 tmp[6] = product[9]; 00945 tmp[7] = product[11]; 00946 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00947 00948 /* d3 */ 00949 tmp[0] = product[13]; 00950 tmp[1] = product[14]; 00951 tmp[2] = product[15]; 00952 tmp[3] = product[8]; 00953 tmp[4] = product[9]; 00954 tmp[5] = product[10]; 00955 tmp[6] = 0; 00956 tmp[7] = product[12]; 00957 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00958 00959 /* d4 */ 00960 tmp[0] = product[14]; 00961 tmp[1] = product[15]; 00962 tmp[2] = 0; 00963 tmp[3] = product[9]; 00964 tmp[4] = product[10]; 00965 tmp[5] = product[11]; 00966 tmp[6] = 0; 00967 tmp[7] = product[13]; 00968 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 00969 00970 if (carry < 0) { 00971 do { 00972 carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); 00973 } while (carry < 0); 00974 } else { 00975 while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { 00976 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); 00977 } 00978 } 00979 } 00980 #else 00981 static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) { 00982 uint64_t tmp[num_words_secp256r1]; 00983 int carry; 00984 00985 /* t */ 00986 uECC_vli_set(result, product, num_words_secp256r1); 00987 00988 /* s1 */ 00989 tmp[0] = 0; 00990 tmp[1] = product[5] & 0xffffffff00000000ull; 00991 tmp[2] = product[6]; 00992 tmp[3] = product[7]; 00993 carry = (int)uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); 00994 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 00995 00996 /* s2 */ 00997 tmp[1] = product[6] << 32; 00998 tmp[2] = (product[6] >> 32) | (product[7] << 32); 00999 tmp[3] = product[7] >> 32; 01000 carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); 01001 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 01002 01003 /* s3 */ 01004 tmp[0] = product[4]; 01005 tmp[1] = product[5] & 0xffffffff; 01006 tmp[2] = 0; 01007 tmp[3] = product[7]; 01008 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 01009 01010 /* s4 */ 01011 tmp[0] = (product[4] >> 32) | (product[5] << 32); 01012 tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull); 01013 tmp[2] = product[7]; 01014 tmp[3] = (product[6] >> 32) | (product[4] << 32); 01015 carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); 01016 01017 /* d1 */ 01018 tmp[0] = (product[5] >> 32) | (product[6] << 32); 01019 tmp[1] = (product[6] >> 32); 01020 tmp[2] = 0; 01021 tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32); 01022 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 01023 01024 /* d2 */ 01025 tmp[0] = product[6]; 01026 tmp[1] = product[7]; 01027 tmp[2] = 0; 01028 tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull); 01029 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 01030 01031 /* d3 */ 01032 tmp[0] = (product[6] >> 32) | (product[7] << 32); 01033 tmp[1] = (product[7] >> 32) | (product[4] << 32); 01034 tmp[2] = (product[4] >> 32) | (product[5] << 32); 01035 tmp[3] = (product[6] << 32); 01036 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 01037 01038 /* d4 */ 01039 tmp[0] = product[7]; 01040 tmp[1] = product[4] & 0xffffffff00000000ull; 01041 tmp[2] = product[5]; 01042 tmp[3] = product[6] & 0xffffffff00000000ull; 01043 carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); 01044 01045 if (carry < 0) { 01046 do { 01047 carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); 01048 } while (carry < 0); 01049 } else { 01050 while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { 01051 carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); 01052 } 01053 } 01054 } 01055 #endif /* uECC_WORD_SIZE */ 01056 #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */ 01057 01058 #endif /* uECC_SUPPORTS_secp256r1 */ 01059 01060 #if uECC_SUPPORTS_secp256k1 01061 01062 static void double_jacobian_secp256k1(uECC_word_t * X1, 01063 uECC_word_t * Y1, 01064 uECC_word_t * Z1, 01065 uECC_Curve curve); 01066 static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); 01067 #if (uECC_OPTIMIZATION_LEVEL > 0) 01068 static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product); 01069 #endif 01070 01071 static const struct uECC_Curve_t curve_secp256k1 = { 01072 num_words_secp256k1, 01073 num_bytes_secp256k1, 01074 256, /* num_n_bits */ 01075 { BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF), 01076 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 01077 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), 01078 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, 01079 { BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF), 01080 BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA), 01081 BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF), 01082 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, 01083 { BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59), 01084 BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02), 01085 BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55), 01086 BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79), 01087 01088 BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C), 01089 BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD), 01090 BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D), 01091 BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) }, 01092 { BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00), 01093 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), 01094 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), 01095 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) }, 01096 &double_jacobian_secp256k1, 01097 #if uECC_SUPPORT_COMPRESSED_POINT 01098 &mod_sqrt_default, 01099 #endif 01100 &x_side_secp256k1, 01101 #if (uECC_OPTIMIZATION_LEVEL > 0) 01102 &vli_mmod_fast_secp256k1 01103 #endif 01104 }; 01105 01106 uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; } 01107 01108 01109 /* Double in place */ 01110 static void double_jacobian_secp256k1(uECC_word_t * X1, 01111 uECC_word_t * Y1, 01112 uECC_word_t * Z1, 01113 uECC_Curve curve) { 01114 /* t1 = X, t2 = Y, t3 = Z */ 01115 uECC_word_t t4[num_words_secp256k1]; 01116 uECC_word_t t5[num_words_secp256k1]; 01117 01118 if (uECC_vli_isZero(Z1, num_words_secp256k1)) { 01119 return; 01120 } 01121 01122 uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */ 01123 uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */ 01124 uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */ 01125 uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */ 01126 uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ 01127 01128 uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ 01129 uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */ 01130 if (uECC_vli_testBit(Y1, 0)) { 01131 uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1); 01132 uECC_vli_rshift1(Y1, num_words_secp256k1); 01133 Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1); 01134 } else { 01135 uECC_vli_rshift1(Y1, num_words_secp256k1); 01136 } 01137 /* t2 = 3/2*(x1^2) = B */ 01138 01139 uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */ 01140 uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */ 01141 uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */ 01142 01143 uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */ 01144 uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */ 01145 uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */ 01146 } 01147 01148 /* Computes result = x^3 + b. result must not overlap x. */ 01149 static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { 01150 uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ 01151 uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */ 01152 uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */ 01153 } 01154 01155 #if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256k1) 01156 static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right); 01157 static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { 01158 uECC_word_t tmp[2 * num_words_secp256k1]; 01159 uECC_word_t carry; 01160 01161 uECC_vli_clear(tmp, num_words_secp256k1); 01162 uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1); 01163 01164 omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */ 01165 01166 carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */ 01167 uECC_vli_clear(product, num_words_secp256k1); 01168 omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */ 01169 carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */ 01170 01171 while (carry > 0) { 01172 --carry; 01173 uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); 01174 } 01175 if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) { 01176 uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); 01177 } 01178 } 01179 01180 #if uECC_WORD_SIZE == 1 01181 static void omega_mult_secp256k1(uint8_t * result, const uint8_t * right) { 01182 /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ 01183 uECC_word_t r0 = 0; 01184 uECC_word_t r1 = 0; 01185 uECC_word_t r2 = 0; 01186 wordcount_t k; 01187 01188 /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ 01189 muladd(0xD1, right[0], &r0, &r1, &r2); 01190 result[0] = r0; 01191 r0 = r1; 01192 r1 = r2; 01193 /* r2 is still 0 */ 01194 01195 for (k = 1; k < num_words_secp256k1; ++k) { 01196 muladd(0x03, right[k - 1], &r0, &r1, &r2); 01197 muladd(0xD1, right[k], &r0, &r1, &r2); 01198 result[k] = r0; 01199 r0 = r1; 01200 r1 = r2; 01201 r2 = 0; 01202 } 01203 muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2); 01204 result[num_words_secp256k1] = r0; 01205 result[num_words_secp256k1 + 1] = r1; 01206 /* add the 2^32 multiple */ 01207 result[4 + num_words_secp256k1] = 01208 uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1); 01209 } 01210 #elif uECC_WORD_SIZE == 4 01211 static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) { 01212 /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ 01213 uint32_t carry = 0; 01214 wordcount_t k; 01215 01216 for (k = 0; k < num_words_secp256k1; ++k) { 01217 uint64_t p = (uint64_t)0x3D1 * right[k] + carry; 01218 result[k] = (uint32_t) p; 01219 carry = p >> 32; 01220 } 01221 result[num_words_secp256k1] = carry; 01222 /* add the 2^32 multiple */ 01223 result[1 + num_words_secp256k1] = 01224 uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1); 01225 } 01226 #else 01227 static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) { 01228 uECC_word_t r0 = 0; 01229 uECC_word_t r1 = 0; 01230 uECC_word_t r2 = 0; 01231 wordcount_t k; 01232 01233 /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ 01234 for (k = 0; k < num_words_secp256k1; ++k) { 01235 muladd(0x1000003D1ull, right[k], &r0, &r1, &r2); 01236 result[k] = r0; 01237 r0 = r1; 01238 r1 = r2; 01239 r2 = 0; 01240 } 01241 result[num_words_secp256k1] = r0; 01242 } 01243 #endif /* uECC_WORD_SIZE */ 01244 #endif /* (uECC_OPTIMIZATION_LEVEL > 0 && && !asm_mmod_fast_secp256k1) */ 01245 01246 #endif /* uECC_SUPPORTS_secp256k1 */ 01247 01248 #endif /* _UECC_CURVE_SPECIFIC_H_ */
Generated on Wed Jul 13 2022 03:48:20 by
1.7.2