micro-ECC for mbed, ported from GCC version from Github,

Dependents:   mbed_microECC Wallet_v1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers curve-specific.h Source File

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_ */