cyassl re-port with cellular comms, PSK test
Dependencies: VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src
ecc.c
00001 /* ecc.c 00002 * 00003 * Copyright (C) 2006-2012 Sawtooth Consulting Ltd. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * CyaSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 /* in case user set HAVE_ECC there */ 00028 #include <cyassl/ctaocrypt/settings.h> 00029 00030 #ifdef HAVE_ECC 00031 00032 #include <cyassl/ctaocrypt/ecc.h> 00033 #include <cyassl/ctaocrypt/asn.h> 00034 #include <cyassl/ctaocrypt/error.h> 00035 00036 00037 /* map 00038 00039 ptmul -> mulmod 00040 00041 */ 00042 00043 #define ECC112 00044 #define ECC128 00045 #define ECC160 00046 #define ECC192 00047 #define ECC224 00048 #define ECC256 00049 #define ECC384 00050 #define ECC521 00051 00052 00053 00054 /* This holds the key settings. ***MUST*** be organized by size from 00055 smallest to largest. */ 00056 00057 const ecc_set_type ecc_sets[] = { 00058 #ifdef ECC112 00059 { 00060 14, 00061 "SECP112R1", 00062 "DB7C2ABF62E35E668076BEAD208B", 00063 "659EF8BA043916EEDE8911702B22", 00064 "DB7C2ABF62E35E7628DFAC6561C5", 00065 "09487239995A5EE76B55F9C2F098", 00066 "A89CE5AF8724C0A23E0E0FF77500" 00067 }, 00068 #endif 00069 #ifdef ECC128 00070 { 00071 16, 00072 "SECP128R1", 00073 "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", 00074 "E87579C11079F43DD824993C2CEE5ED3", 00075 "FFFFFFFE0000000075A30D1B9038A115", 00076 "161FF7528B899B2D0C28607CA52C5B86", 00077 "CF5AC8395BAFEB13C02DA292DDED7A83", 00078 }, 00079 #endif 00080 #ifdef ECC160 00081 { 00082 20, 00083 "SECP160R1", 00084 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", 00085 "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", 00086 "0100000000000000000001F4C8F927AED3CA752257", 00087 "4A96B5688EF573284664698968C38BB913CBFC82", 00088 "23A628553168947D59DCC912042351377AC5FB32", 00089 }, 00090 #endif 00091 #ifdef ECC192 00092 { 00093 24, 00094 "ECC-192", 00095 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 00096 "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 00097 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 00098 "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 00099 "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 00100 }, 00101 #endif 00102 #ifdef ECC224 00103 { 00104 28, 00105 "ECC-224", 00106 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 00107 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 00108 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 00109 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 00110 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 00111 }, 00112 #endif 00113 #ifdef ECC256 00114 { 00115 32, 00116 "ECC-256", 00117 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 00118 "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", 00119 "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 00120 "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 00121 "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 00122 }, 00123 #endif 00124 #ifdef ECC384 00125 { 00126 48, 00127 "ECC-384", 00128 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", 00129 "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", 00130 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", 00131 "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", 00132 "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", 00133 }, 00134 #endif 00135 #ifdef ECC521 00136 { 00137 66, 00138 "ECC-521", 00139 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 00140 "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 00141 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 00142 "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", 00143 "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", 00144 }, 00145 #endif 00146 { 00147 0, 00148 NULL, NULL, NULL, NULL, NULL, NULL 00149 } 00150 }; 00151 00152 00153 ecc_point* ecc_new_point(void); 00154 void ecc_del_point(ecc_point* p); 00155 int ecc_map(ecc_point*, mp_int*, mp_digit*); 00156 int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, 00157 mp_int* modulus, mp_digit* mp); 00158 int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus, 00159 mp_digit* mp); 00160 00161 00162 /* helper for either lib */ 00163 static int get_digit_count(mp_int* a) 00164 { 00165 if (a == NULL) 00166 return 0; 00167 00168 return a->used; 00169 } 00170 00171 /* helper for either lib */ 00172 static unsigned long get_digit(mp_int* a, int n) 00173 { 00174 if (a == NULL) 00175 return 0; 00176 00177 return (n >= a->used || n < 0) ? 0 : a->dp[n]; 00178 } 00179 00180 00181 /** 00182 Add two ECC points 00183 P The point to add 00184 Q The point to add 00185 R [out] The destination of the double 00186 modulus The modulus of the field the ECC curve is in 00187 mp The "b" value from montgomery_setup() 00188 return MP_OKAY on success 00189 */ 00190 int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, 00191 mp_int* modulus, mp_digit* mp) 00192 { 00193 mp_int t1; 00194 mp_int t2; 00195 mp_int x; 00196 mp_int y; 00197 mp_int z; 00198 int err; 00199 00200 if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL) 00201 return ECC_BAD_ARG_E; 00202 00203 if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) { 00204 return err; 00205 } 00206 00207 /* should we dbl instead? */ 00208 err = mp_sub(modulus, &Q->y, &t1); 00209 00210 if (err == MP_OKAY) { 00211 if ( (mp_cmp(&P->x, &Q->x) == MP_EQ) && 00212 (get_digit_count(&Q->z) && mp_cmp(&P->z, &Q->z) == MP_EQ) && 00213 (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &t1) == MP_EQ)) { 00214 mp_clear(&t1); 00215 mp_clear(&t2); 00216 mp_clear(&x); 00217 mp_clear(&y); 00218 mp_clear(&z); 00219 00220 return ecc_projective_dbl_point(P, R, modulus, mp); 00221 } 00222 } 00223 00224 if (err == MP_OKAY) 00225 err = mp_copy(&P->x, &x); 00226 if (err == MP_OKAY) 00227 err = mp_copy(&P->y, &y); 00228 if (err == MP_OKAY) 00229 err = mp_copy(&P->z, &z); 00230 00231 /* if Z is one then these are no-operations */ 00232 if (err == MP_OKAY) { 00233 if (get_digit_count(&Q->z)) { 00234 /* T1 = Z' * Z' */ 00235 err = mp_sqr(&Q->z, &t1); 00236 if (err == MP_OKAY) 00237 err = mp_montgomery_reduce(&t1, modulus, *mp); 00238 00239 /* X = X * T1 */ 00240 if (err == MP_OKAY) 00241 err = mp_mul(&t1, &x, &x); 00242 if (err == MP_OKAY) 00243 err = mp_montgomery_reduce(&x, modulus, *mp); 00244 00245 /* T1 = Z' * T1 */ 00246 if (err == MP_OKAY) 00247 err = mp_mul(&Q->z, &t1, &t1); 00248 if (err == MP_OKAY) 00249 err = mp_montgomery_reduce(&t1, modulus, *mp); 00250 00251 /* Y = Y * T1 */ 00252 if (err == MP_OKAY) 00253 err = mp_mul(&t1, &y, &y); 00254 if (err == MP_OKAY) 00255 err = mp_montgomery_reduce(&y, modulus, *mp); 00256 } 00257 } 00258 00259 /* T1 = Z*Z */ 00260 if (err == MP_OKAY) 00261 err = mp_sqr(&z, &t1); 00262 if (err == MP_OKAY) 00263 err = mp_montgomery_reduce(&t1, modulus, *mp); 00264 00265 /* T2 = X' * T1 */ 00266 if (err == MP_OKAY) 00267 err = mp_mul(&Q->x, &t1, &t2); 00268 if (err == MP_OKAY) 00269 err = mp_montgomery_reduce(&t2, modulus, *mp); 00270 00271 /* T1 = Z * T1 */ 00272 if (err == MP_OKAY) 00273 err = mp_mul(&z, &t1, &t1); 00274 if (err == MP_OKAY) 00275 err = mp_montgomery_reduce(&t1, modulus, *mp); 00276 00277 /* T1 = Y' * T1 */ 00278 if (err == MP_OKAY) 00279 err = mp_mul(&Q->y, &t1, &t1); 00280 if (err == MP_OKAY) 00281 err = mp_montgomery_reduce(&t1, modulus, *mp); 00282 00283 /* Y = Y - T1 */ 00284 if (err == MP_OKAY) 00285 err = mp_sub(&y, &t1, &y); 00286 if (err == MP_OKAY) { 00287 if (mp_cmp_d(&y, 0) == MP_LT) 00288 err = mp_add(&y, modulus, &y); 00289 } 00290 /* T1 = 2T1 */ 00291 if (err == MP_OKAY) 00292 err = mp_add(&t1, &t1, &t1); 00293 if (err == MP_OKAY) { 00294 if (mp_cmp(&t1, modulus) != MP_LT) 00295 err = mp_sub(&t1, modulus, &t1); 00296 } 00297 /* T1 = Y + T1 */ 00298 if (err == MP_OKAY) 00299 err = mp_add(&t1, &y, &t1); 00300 if (err == MP_OKAY) { 00301 if (mp_cmp(&t1, modulus) != MP_LT) 00302 err = mp_sub(&t1, modulus, &t1); 00303 } 00304 /* X = X - T2 */ 00305 if (err == MP_OKAY) 00306 err = mp_sub(&x, &t2, &x); 00307 if (err == MP_OKAY) { 00308 if (mp_cmp_d(&x, 0) == MP_LT) 00309 err = mp_add(&x, modulus, &x); 00310 } 00311 /* T2 = 2T2 */ 00312 if (err == MP_OKAY) 00313 err = mp_add(&t2, &t2, &t2); 00314 if (err == MP_OKAY) { 00315 if (mp_cmp(&t2, modulus) != MP_LT) 00316 err = mp_sub(&t2, modulus, &t2); 00317 } 00318 /* T2 = X + T2 */ 00319 if (err == MP_OKAY) 00320 err = mp_add(&t2, &x, &t2); 00321 if (err == MP_OKAY) { 00322 if (mp_cmp(&t2, modulus) != MP_LT) 00323 err = mp_sub(&t2, modulus, &t2); 00324 } 00325 00326 if (err == MP_OKAY) { 00327 if (get_digit_count(&Q->z)) { 00328 /* Z = Z * Z' */ 00329 err = mp_mul(&z, &Q->z, &z); 00330 if (err == MP_OKAY) 00331 err = mp_montgomery_reduce(&z, modulus, *mp); 00332 } 00333 } 00334 00335 /* Z = Z * X */ 00336 if (err == MP_OKAY) 00337 err = mp_mul(&z, &x, &z); 00338 if (err == MP_OKAY) 00339 err = mp_montgomery_reduce(&z, modulus, *mp); 00340 00341 /* T1 = T1 * X */ 00342 if (err == MP_OKAY) 00343 err = mp_mul(&t1, &x, &t1); 00344 if (err == MP_OKAY) 00345 err = mp_montgomery_reduce(&t1, modulus, *mp); 00346 00347 /* X = X * X */ 00348 if (err == MP_OKAY) 00349 err = mp_sqr(&x, &x); 00350 if (err == MP_OKAY) 00351 err = mp_montgomery_reduce(&x, modulus, *mp); 00352 00353 /* T2 = T2 * x */ 00354 if (err == MP_OKAY) 00355 err = mp_mul(&t2, &x, &t2); 00356 if (err == MP_OKAY) 00357 err = mp_montgomery_reduce(&t2, modulus, *mp); 00358 00359 /* T1 = T1 * X */ 00360 if (err == MP_OKAY) 00361 err = mp_mul(&t1, &x, &t1); 00362 if (err == MP_OKAY) 00363 err = mp_montgomery_reduce(&t1, modulus, *mp); 00364 00365 /* X = Y*Y */ 00366 if (err == MP_OKAY) 00367 err = mp_sqr(&y, &x); 00368 if (err == MP_OKAY) 00369 err = mp_montgomery_reduce(&x, modulus, *mp); 00370 00371 /* X = X - T2 */ 00372 if (err == MP_OKAY) 00373 err = mp_sub(&x, &t2, &x); 00374 if (err == MP_OKAY) { 00375 if (mp_cmp_d(&x, 0) == MP_LT) 00376 err = mp_add(&x, modulus, &x); 00377 } 00378 /* T2 = T2 - X */ 00379 if (err == MP_OKAY) 00380 err = mp_sub(&t2, &x, &t2); 00381 if (err == MP_OKAY) { 00382 if (mp_cmp_d(&t2, 0) == MP_LT) 00383 err = mp_add(&t2, modulus, &t2); 00384 } 00385 /* T2 = T2 - X */ 00386 if (err == MP_OKAY) 00387 err = mp_sub(&t2, &x, &t2); 00388 if (err == MP_OKAY) { 00389 if (mp_cmp_d(&t2, 0) == MP_LT) 00390 err = mp_add(&t2, modulus, &t2); 00391 } 00392 /* T2 = T2 * Y */ 00393 if (err == MP_OKAY) 00394 err = mp_mul(&t2, &y, &t2); 00395 if (err == MP_OKAY) 00396 err = mp_montgomery_reduce(&t2, modulus, *mp); 00397 00398 /* Y = T2 - T1 */ 00399 if (err == MP_OKAY) 00400 err = mp_sub(&t2, &t1, &y); 00401 if (err == MP_OKAY) { 00402 if (mp_cmp_d(&y, 0) == MP_LT) 00403 err = mp_add(&y, modulus, &y); 00404 } 00405 /* Y = Y/2 */ 00406 if (err == MP_OKAY) { 00407 if (mp_isodd(&y)) 00408 err = mp_add(&y, modulus, &y); 00409 } 00410 if (err == MP_OKAY) 00411 err = mp_div_2(&y, &y); 00412 00413 if (err == MP_OKAY) 00414 err = mp_copy(&x, &R->x); 00415 if (err == MP_OKAY) 00416 err = mp_copy(&y, &R->y); 00417 if (err == MP_OKAY) 00418 err = mp_copy(&z, &R->z); 00419 00420 /* clean up */ 00421 mp_clear(&t1); 00422 mp_clear(&t2); 00423 mp_clear(&x); 00424 mp_clear(&y); 00425 mp_clear(&z); 00426 00427 return err; 00428 } 00429 00430 00431 /** 00432 Double an ECC point 00433 P The point to double 00434 R [out] The destination of the double 00435 modulus The modulus of the field the ECC curve is in 00436 mp The "b" value from montgomery_setup() 00437 return MP_OKAY on success 00438 */ 00439 int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, 00440 mp_digit* mp) 00441 { 00442 mp_int t1; 00443 mp_int t2; 00444 int err; 00445 00446 if (P == NULL || R == NULL || modulus == NULL || mp == NULL) 00447 return ECC_BAD_ARG_E; 00448 00449 if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { 00450 return err; 00451 } 00452 00453 if (P != R) { 00454 err = mp_copy(&P->x, &R->x); 00455 if (err == MP_OKAY) 00456 err = mp_copy(&P->y, &R->y); 00457 if (err == MP_OKAY) 00458 err = mp_copy(&P->z, &R->z); 00459 } 00460 00461 /* t1 = Z * Z */ 00462 if (err == MP_OKAY) 00463 err = mp_sqr(&R->z, &t1); 00464 if (err == MP_OKAY) 00465 err = mp_montgomery_reduce(&t1, modulus, *mp); 00466 00467 /* Z = Y * Z */ 00468 if (err == MP_OKAY) 00469 err = mp_mul(&R->z, &R->y, &R->z); 00470 if (err == MP_OKAY) 00471 err = mp_montgomery_reduce(&R->z, modulus, *mp); 00472 00473 /* Z = 2Z */ 00474 if (err == MP_OKAY) 00475 err = mp_add(&R->z, &R->z, &R->z); 00476 if (err == MP_OKAY) { 00477 if (mp_cmp(&R->z, modulus) != MP_LT) 00478 err = mp_sub(&R->z, modulus, &R->z); 00479 } 00480 00481 /* T2 = X - T1 */ 00482 if (err == MP_OKAY) 00483 err = mp_sub(&R->x, &t1, &t2); 00484 if (err == MP_OKAY) { 00485 if (mp_cmp_d(&t2, 0) == MP_LT) 00486 err = mp_add(&t2, modulus, &t2); 00487 } 00488 /* T1 = X + T1 */ 00489 if (err == MP_OKAY) 00490 err = mp_add(&t1, &R->x, &t1); 00491 if (err == MP_OKAY) { 00492 if (mp_cmp(&t1, modulus) != MP_LT) 00493 err = mp_sub(&t1, modulus, &t1); 00494 } 00495 /* T2 = T1 * T2 */ 00496 if (err == MP_OKAY) 00497 err = mp_mul(&t1, &t2, &t2); 00498 if (err == MP_OKAY) 00499 err = mp_montgomery_reduce(&t2, modulus, *mp); 00500 00501 /* T1 = 2T2 */ 00502 if (err == MP_OKAY) 00503 err = mp_add(&t2, &t2, &t1); 00504 if (err == MP_OKAY) { 00505 if (mp_cmp(&t1, modulus) != MP_LT) 00506 err = mp_sub(&t1, modulus, &t1); 00507 } 00508 /* T1 = T1 + T2 */ 00509 if (err == MP_OKAY) 00510 err = mp_add(&t1, &t2, &t1); 00511 if (err == MP_OKAY) { 00512 if (mp_cmp(&t1, modulus) != MP_LT) 00513 err = mp_sub(&t1, modulus, &t1); 00514 } 00515 /* Y = 2Y */ 00516 if (err == MP_OKAY) 00517 err = mp_add(&R->y, &R->y, &R->y); 00518 if (err == MP_OKAY) { 00519 if (mp_cmp(&R->y, modulus) != MP_LT) 00520 err = mp_sub(&R->y, modulus, &R->y); 00521 } 00522 /* Y = Y * Y */ 00523 if (err == MP_OKAY) 00524 err = mp_sqr(&R->y, &R->y); 00525 if (err == MP_OKAY) 00526 err = mp_montgomery_reduce(&R->y, modulus, *mp); 00527 00528 /* T2 = Y * Y */ 00529 if (err == MP_OKAY) 00530 err = mp_sqr(&R->y, &t2); 00531 if (err == MP_OKAY) 00532 err = mp_montgomery_reduce(&t2, modulus, *mp); 00533 00534 /* T2 = T2/2 */ 00535 if (err == MP_OKAY) { 00536 if (mp_isodd(&t2)) 00537 err = mp_add(&t2, modulus, &t2); 00538 } 00539 if (err == MP_OKAY) 00540 err = mp_div_2(&t2, &t2); 00541 00542 /* Y = Y * X */ 00543 if (err == MP_OKAY) 00544 err = mp_mul(&R->y, &R->x, &R->y); 00545 if (err == MP_OKAY) 00546 err = mp_montgomery_reduce(&R->y, modulus, *mp); 00547 00548 /* X = T1 * T1 */ 00549 if (err == MP_OKAY) 00550 err = mp_sqr(&t1, &R->x); 00551 if (err == MP_OKAY) 00552 err = mp_montgomery_reduce(&R->x, modulus, *mp); 00553 00554 /* X = X - Y */ 00555 if (err == MP_OKAY) 00556 err = mp_sub(&R->x, &R->y, &R->x); 00557 if (err == MP_OKAY) { 00558 if (mp_cmp_d(&R->x, 0) == MP_LT) 00559 err = mp_add(&R->x, modulus, &R->x); 00560 } 00561 /* X = X - Y */ 00562 if (err == MP_OKAY) 00563 err = mp_sub(&R->x, &R->y, &R->x); 00564 if (err == MP_OKAY) { 00565 if (mp_cmp_d(&R->x, 0) == MP_LT) 00566 err = mp_add(&R->x, modulus, &R->x); 00567 } 00568 /* Y = Y - X */ 00569 if (err == MP_OKAY) 00570 err = mp_sub(&R->y, &R->x, &R->y); 00571 if (err == MP_OKAY) { 00572 if (mp_cmp_d(&R->y, 0) == MP_LT) 00573 err = mp_add(&R->y, modulus, &R->y); 00574 } 00575 /* Y = Y * T1 */ 00576 if (err == MP_OKAY) 00577 err = mp_mul(&R->y, &t1, &R->y); 00578 if (err == MP_OKAY) 00579 err = mp_montgomery_reduce(&R->y, modulus, *mp); 00580 00581 /* Y = Y - T2 */ 00582 if (err == MP_OKAY) 00583 err = mp_sub(&R->y, &t2, &R->y); 00584 if (err == MP_OKAY) { 00585 if (mp_cmp_d(&R->y, 0) == MP_LT) 00586 err = mp_add(&R->y, modulus, &R->y); 00587 } 00588 00589 /* clean up */ 00590 mp_clear(&t1); 00591 mp_clear(&t2); 00592 00593 return err; 00594 } 00595 00596 00597 /** 00598 Map a projective jacbobian point back to affine space 00599 P [in/out] The point to map 00600 modulus The modulus of the field the ECC curve is in 00601 mp The "b" value from montgomery_setup() 00602 return MP_OKAY on success 00603 */ 00604 int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) 00605 { 00606 mp_int t1; 00607 mp_int t2; 00608 int err; 00609 00610 if (P == NULL || mp == NULL || modulus == NULL) 00611 return ECC_BAD_ARG_E; 00612 00613 if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { 00614 return MEMORY_E; 00615 } 00616 00617 /* first map z back to normal */ 00618 err = mp_montgomery_reduce(&P->z, modulus, *mp); 00619 00620 /* get 1/z */ 00621 if (err == MP_OKAY) 00622 err = mp_invmod(&P->z, modulus, &t1); 00623 00624 /* get 1/z^2 and 1/z^3 */ 00625 if (err == MP_OKAY) 00626 err = mp_sqr(&t1, &t2); 00627 if (err == MP_OKAY) 00628 err = mp_mod(&t2, modulus, &t2); 00629 if (err == MP_OKAY) 00630 err = mp_mul(&t1, &t2, &t1); 00631 if (err == MP_OKAY) 00632 err = mp_mod(&t1, modulus, &t1); 00633 00634 /* multiply against x/y */ 00635 if (err == MP_OKAY) 00636 err = mp_mul(&P->x, &t2, &P->x); 00637 if (err == MP_OKAY) 00638 err = mp_montgomery_reduce(&P->x, modulus, *mp); 00639 if (err == MP_OKAY) 00640 err = mp_mul(&P->y, &t1, &P->y); 00641 if (err == MP_OKAY) 00642 err = mp_montgomery_reduce(&P->y, modulus, *mp); 00643 00644 if (err == MP_OKAY) 00645 mp_set(&P->z, 1); 00646 00647 /* clean up */ 00648 mp_clear(&t1); 00649 mp_clear(&t2); 00650 00651 return err; 00652 } 00653 00654 00655 #ifndef ECC_TIMING_RESISTANT 00656 00657 /* size of sliding window, don't change this! */ 00658 #define WINSIZE 4 00659 00660 /** 00661 Perform a point multiplication 00662 k The scalar to multiply by 00663 G The base point 00664 R [out] Destination for kG 00665 modulus The modulus of the field the ECC curve is in 00666 map Boolean whether to map back to affine or not 00667 (1==map, 0 == leave in projective) 00668 return MP_OKAY on success 00669 */ 00670 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, 00671 int map) 00672 { 00673 ecc_point *tG, *M[8]; 00674 int i, j, err; 00675 mp_int mu; 00676 mp_digit mp; 00677 unsigned long buf; 00678 int first, bitbuf, bitcpy, bitcnt, mode, digidx; 00679 00680 if (k == NULL || G == NULL || R == NULL || modulus == NULL) 00681 return ECC_BAD_ARG_E; 00682 00683 /* init montgomery reduction */ 00684 if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { 00685 return err; 00686 } 00687 if ((err = mp_init(&mu)) != MP_OKAY) { 00688 return err; 00689 } 00690 if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { 00691 mp_clear(&mu); 00692 return err; 00693 } 00694 00695 /* alloc ram for window temps */ 00696 for (i = 0; i < 8; i++) { 00697 M[i] = ecc_new_point(); 00698 if (M[i] == NULL) { 00699 for (j = 0; j < i; j++) { 00700 ecc_del_point(M[j]); 00701 } 00702 mp_clear(&mu); 00703 return MEMORY_E; 00704 } 00705 } 00706 00707 /* make a copy of G incase R==G */ 00708 tG = ecc_new_point(); 00709 if (tG == NULL) 00710 err = MEMORY_E; 00711 00712 /* tG = G and convert to montgomery */ 00713 if (err == MP_OKAY) { 00714 if (mp_cmp_d(&mu, 1) == MP_EQ) { 00715 err = mp_copy(&G->x, &tG->x); 00716 if (err == MP_OKAY) 00717 err = mp_copy(&G->y, &tG->y); 00718 if (err == MP_OKAY) 00719 err = mp_copy(&G->z, &tG->z); 00720 } else { 00721 err = mp_mulmod(&G->x, &mu, modulus, &tG->x); 00722 if (err == MP_OKAY) 00723 err = mp_mulmod(&G->y, &mu, modulus, &tG->y); 00724 if (err == MP_OKAY) 00725 err = mp_mulmod(&G->z, &mu, modulus, &tG->z); 00726 } 00727 } 00728 mp_clear(&mu); 00729 00730 /* calc the M tab, which holds kG for k==8..15 */ 00731 /* M[0] == 8G */ 00732 if (err == MP_OKAY) 00733 err = ecc_projective_dbl_point(tG, M[0], modulus, &mp); 00734 if (err == MP_OKAY) 00735 err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp); 00736 if (err == MP_OKAY) 00737 err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp); 00738 00739 /* now find (8+k)G for k=1..7 */ 00740 if (err == MP_OKAY) 00741 for (j = 9; j < 16; j++) { 00742 err = ecc_projective_add_point(M[j-9], tG, M[j-8], modulus, &mp); 00743 if (err != MP_OKAY) break; 00744 } 00745 00746 /* setup sliding window */ 00747 if (err == MP_OKAY) { 00748 mode = 0; 00749 bitcnt = 1; 00750 buf = 0; 00751 digidx = get_digit_count(k) - 1; 00752 bitcpy = bitbuf = 0; 00753 first = 1; 00754 00755 /* perform ops */ 00756 for (;;) { 00757 /* grab next digit as required */ 00758 if (--bitcnt == 0) { 00759 if (digidx == -1) { 00760 break; 00761 } 00762 buf = get_digit(k, digidx); 00763 bitcnt = (int) DIGIT_BIT; 00764 --digidx; 00765 } 00766 00767 /* grab the next msb from the ltiplicand */ 00768 i = (int)(buf >> (DIGIT_BIT - 1)) & 1; 00769 buf <<= 1; 00770 00771 /* skip leading zero bits */ 00772 if (mode == 0 && i == 0) 00773 continue; 00774 00775 /* if the bit is zero and mode == 1 then we double */ 00776 if (mode == 1 && i == 0) { 00777 err = ecc_projective_dbl_point(R, R, modulus, &mp); 00778 if (err != MP_OKAY) break; 00779 continue; 00780 } 00781 00782 /* else we add it to the window */ 00783 bitbuf |= (i << (WINSIZE - ++bitcpy)); 00784 mode = 2; 00785 00786 if (bitcpy == WINSIZE) { 00787 /* if this is the first window we do a simple copy */ 00788 if (first == 1) { 00789 /* R = kG [k = first window] */ 00790 err = mp_copy(&M[bitbuf-8]->x, &R->x); 00791 if (err != MP_OKAY) break; 00792 00793 err = mp_copy(&M[bitbuf-8]->y, &R->y); 00794 if (err != MP_OKAY) break; 00795 00796 err = mp_copy(&M[bitbuf-8]->z, &R->z); 00797 first = 0; 00798 } else { 00799 /* normal window */ 00800 /* ok window is filled so double as required and add */ 00801 /* double first */ 00802 for (j = 0; j < WINSIZE; j++) { 00803 err = ecc_projective_dbl_point(R, R, modulus, &mp); 00804 if (err != MP_OKAY) break; 00805 } 00806 if (err != MP_OKAY) break; /* out of first for(;;) */ 00807 00808 /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranted */ 00809 err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp); 00810 } 00811 if (err != MP_OKAY) break; 00812 /* empty window and reset */ 00813 bitcpy = bitbuf = 0; 00814 mode = 1; 00815 } 00816 } 00817 } 00818 00819 /* if bits remain then double/add */ 00820 if (err == MP_OKAY) { 00821 if (mode == 2 && bitcpy > 0) { 00822 /* double then add */ 00823 for (j = 0; j < bitcpy; j++) { 00824 /* only double if we have had at least one add first */ 00825 if (first == 0) { 00826 err = ecc_projective_dbl_point(R, R, modulus, &mp); 00827 if (err != MP_OKAY) break; 00828 } 00829 00830 bitbuf <<= 1; 00831 if ((bitbuf & (1 << WINSIZE)) != 0) { 00832 if (first == 1) { 00833 /* first add, so copy */ 00834 err = mp_copy(&tG->x, &R->x); 00835 if (err != MP_OKAY) break; 00836 00837 err = mp_copy(&tG->y, &R->y); 00838 if (err != MP_OKAY) break; 00839 00840 err = mp_copy(&tG->z, &R->z); 00841 if (err != MP_OKAY) break; 00842 first = 0; 00843 } else { 00844 /* then add */ 00845 err = ecc_projective_add_point(R, tG, R, modulus, &mp); 00846 if (err != MP_OKAY) break; 00847 } 00848 } 00849 } 00850 } 00851 } 00852 00853 /* map R back from projective space */ 00854 if (err == MP_OKAY && map) 00855 err = ecc_map(R, modulus, &mp); 00856 00857 mp_clear(&mu); 00858 ecc_del_point(tG); 00859 for (i = 0; i < 8; i++) { 00860 ecc_del_point(M[i]); 00861 } 00862 return err; 00863 } 00864 00865 #undef WINSIZE 00866 #endif /* ECC_TIMING_RESISTANT */ 00867 00868 00869 /** 00870 Allocate a new ECC point 00871 return A newly allocated point or NULL on error 00872 */ 00873 ecc_point* ecc_new_point(void) 00874 { 00875 ecc_point* p; 00876 p = (ecc_point*)XMALLOC(sizeof(ecc_point), 0, DYNAMIC_TYPE_BIGINT); 00877 if (p == NULL) { 00878 return NULL; 00879 } 00880 XMEMSET(p, 0, sizeof(ecc_point)); 00881 if (mp_init_multi(&p->x, &p->y, &p->z, NULL, NULL, NULL) != MP_OKAY) { 00882 XFREE(p, 0, DYNAMIC_TYPE_BIGINT); 00883 return NULL; 00884 } 00885 return p; 00886 } 00887 00888 /** Free an ECC point from memory 00889 p The point to free 00890 */ 00891 void ecc_del_point(ecc_point* p) 00892 { 00893 /* prevents free'ing null arguments */ 00894 if (p != NULL) { 00895 mp_clear(&p->x); 00896 mp_clear(&p->y); 00897 mp_clear(&p->z); 00898 XFREE(p, 0, DYNAMIC_TYPE_BIGINT); 00899 } 00900 } 00901 00902 00903 /** Returns whether an ECC idx is valid or not 00904 n The idx number to check 00905 return 1 if valid, 0 if not 00906 */ 00907 static int ecc_is_valid_idx(int n) 00908 { 00909 int x; 00910 00911 for (x = 0; ecc_sets[x].size != 0; x++) 00912 ; 00913 /* -1 is a valid index --- indicating that the domain params 00914 were supplied by the user */ 00915 if ((n >= -1) && (n < x)) { 00916 return 1; 00917 } 00918 return 0; 00919 } 00920 00921 00922 /** 00923 Create an ECC shared secret between two keys 00924 private_key The private ECC key 00925 public_key The public key 00926 out [out] Destination of the shared secret 00927 Conforms to EC-DH from ANSI X9.63 00928 outlen [in/out] The max size and resulting size of the shared secret 00929 return MP_OKAY if successful 00930 */ 00931 int ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, 00932 word32* outlen) 00933 { 00934 word32 x = 0; 00935 ecc_point* result; 00936 mp_int prime; 00937 int err; 00938 00939 if (private_key == NULL || public_key == NULL || out == NULL || 00940 outlen == NULL) 00941 return BAD_FUNC_ARG; 00942 00943 /* type valid? */ 00944 if (private_key->type != ECC_PRIVATEKEY) { 00945 return ECC_BAD_ARG_E; 00946 } 00947 00948 if (ecc_is_valid_idx(private_key->idx) == 0 || 00949 ecc_is_valid_idx(public_key->idx) == 0) 00950 return ECC_BAD_ARG_E; 00951 00952 if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0) 00953 return ECC_BAD_ARG_E; 00954 00955 /* make new point */ 00956 result = ecc_new_point(); 00957 if (result == NULL) { 00958 return MEMORY_E; 00959 } 00960 00961 if ((err = mp_init(&prime)) != MP_OKAY) { 00962 ecc_del_point(result); 00963 return err; 00964 } 00965 00966 err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16); 00967 00968 if (err == MP_OKAY) 00969 err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime,1); 00970 00971 if (err == MP_OKAY) { 00972 x = mp_unsigned_bin_size(&prime); 00973 if (*outlen < x) 00974 err = BUFFER_E; 00975 } 00976 00977 if (err == MP_OKAY) { 00978 XMEMSET(out, 0, x); 00979 err = mp_to_unsigned_bin(&result->x,out + (x - 00980 mp_unsigned_bin_size(&result->x))); 00981 *outlen = x; 00982 } 00983 00984 mp_clear(&prime); 00985 ecc_del_point(result); 00986 00987 return err; 00988 } 00989 00990 00991 int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp); 00992 00993 /** 00994 Make a new ECC key 00995 rng An active RNG state 00996 keysize The keysize for the new key (in octets from 20 to 65 bytes) 00997 key [out] Destination of the newly created key 00998 return MP_OKAY if successful, 00999 upon error all allocated memory will be freed 01000 */ 01001 int ecc_make_key(RNG* rng, int keysize, ecc_key* key) 01002 { 01003 int x, err; 01004 01005 /* find key size */ 01006 for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++) 01007 ; 01008 keysize = ecc_sets[x].size; 01009 01010 if (keysize > ECC_MAXSIZE || ecc_sets[x].size == 0) { 01011 return BAD_FUNC_ARG; 01012 } 01013 err = ecc_make_key_ex(rng, key, &ecc_sets[x]); 01014 key->idx = x; 01015 01016 return err; 01017 } 01018 01019 int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp) 01020 { 01021 int err; 01022 ecc_point* base; 01023 mp_int prime; 01024 mp_int order; 01025 byte buf[ECC_MAXSIZE]; 01026 int keysize; 01027 01028 if (key == NULL || rng == NULL || dp == NULL) 01029 return ECC_BAD_ARG_E; 01030 01031 key->idx = -1; 01032 key->dp = dp; 01033 keysize = dp->size; 01034 01035 /* allocate ram */ 01036 base = NULL; 01037 01038 /* make up random string */ 01039 RNG_GenerateBlock(rng, buf, keysize); 01040 buf[0] |= 0x0c; 01041 01042 /* setup the key variables */ 01043 if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, 01044 &key->k, &prime, &order)) != MP_OKAY) 01045 return MEMORY_E; 01046 01047 base = ecc_new_point(); 01048 if (base == NULL) 01049 err = MEMORY_E; 01050 01051 /* read in the specs for this key */ 01052 if (err == MP_OKAY) 01053 err = mp_read_radix(&prime, (char *)key->dp->prime, 16); 01054 if (err == MP_OKAY) 01055 err = mp_read_radix(&order, (char *)key->dp->order, 16); 01056 if (err == MP_OKAY) 01057 err = mp_read_radix(&base->x, (char *)key->dp->Gx, 16); 01058 if (err == MP_OKAY) 01059 err = mp_read_radix(&base->y, (char *)key->dp->Gy, 16); 01060 01061 if (err == MP_OKAY) 01062 mp_set(&base->z, 1); 01063 if (err == MP_OKAY) 01064 err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize); 01065 01066 /* the key should be smaller than the order of base point */ 01067 if (err == MP_OKAY) { 01068 if (mp_cmp(&key->k, &order) != MP_LT) 01069 err = mp_mod(&key->k, &order, &key->k); 01070 } 01071 /* make the public key */ 01072 if (err == MP_OKAY) 01073 err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1); 01074 if (err == MP_OKAY) 01075 key->type = ECC_PRIVATEKEY; 01076 01077 if (err != MP_OKAY) { 01078 /* clean up */ 01079 mp_clear(&key->pubkey.x); 01080 mp_clear(&key->pubkey.y); 01081 mp_clear(&key->pubkey.z); 01082 mp_clear(&key->k); 01083 } 01084 ecc_del_point(base); 01085 mp_clear(&prime); 01086 mp_clear(&order); 01087 #ifdef ECC_CLEAN_STACK 01088 XMEMSET(buff, 0, ECC_MAXSIZE); 01089 #endif 01090 return err; 01091 } 01092 01093 01094 /* Setup dynamic pointers is using normal math for proper freeing */ 01095 void ecc_init(ecc_key* key) 01096 { 01097 (void)key; 01098 #ifndef USE_FAST_MATH 01099 key->pubkey.x.dp = NULL; 01100 key->pubkey.y.dp = NULL; 01101 key->pubkey.z.dp = NULL; 01102 01103 key->k.dp = NULL; 01104 #endif 01105 } 01106 01107 01108 /** 01109 Sign a message digest 01110 in The message digest to sign 01111 inlen The length of the digest 01112 out [out] The destination for the signature 01113 outlen [in/out] The max size and resulting size of the signature 01114 key A private ECC key 01115 return MP_OKAY if successful 01116 */ 01117 int ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, 01118 RNG* rng, ecc_key* key) 01119 { 01120 mp_int r; 01121 mp_int s; 01122 mp_int e; 01123 mp_int p; 01124 int err; 01125 01126 if (in == NULL || out == NULL || outlen == NULL || key == NULL || rng ==NULL) 01127 return ECC_BAD_ARG_E; 01128 01129 /* is this a private key? */ 01130 if (key->type != ECC_PRIVATEKEY) { 01131 return ECC_BAD_ARG_E; 01132 } 01133 01134 /* is the IDX valid ? */ 01135 if (ecc_is_valid_idx(key->idx) != 1) { 01136 return ECC_BAD_ARG_E; 01137 } 01138 01139 /* get the hash and load it as a bignum into 'e' */ 01140 /* init the bignums */ 01141 if ((err = mp_init_multi(&r, &s, &p, &e, NULL, NULL)) != MP_OKAY) { 01142 return err; 01143 } 01144 err = mp_read_radix(&p, (char *)key->dp->order, 16); 01145 01146 if (err == MP_OKAY) { 01147 int truncLen = (int)inlen; 01148 if (truncLen > ecc_size(key)) 01149 truncLen = ecc_size(key); 01150 err = mp_read_unsigned_bin(&e, (byte*)in, truncLen); 01151 } 01152 01153 /* make up a key and export the public copy */ 01154 if (err == MP_OKAY) { 01155 ecc_key pubkey; 01156 ecc_init(&pubkey); 01157 for (;;) { 01158 err = ecc_make_key_ex(rng, &pubkey, key->dp); 01159 if (err != MP_OKAY) break; 01160 01161 /* find r = x1 mod n */ 01162 err = mp_mod(&pubkey.pubkey.x, &p, &r); 01163 if (err != MP_OKAY) break; 01164 01165 if (mp_iszero(&r) == MP_YES) 01166 ecc_free(&pubkey); 01167 else { 01168 /* find s = (e + xr)/k */ 01169 err = mp_invmod(&pubkey.k, &p, &pubkey.k); 01170 if (err != MP_OKAY) break; 01171 01172 err = mp_mulmod(&key->k, &r, &p, &s); /* s = xr */ 01173 if (err != MP_OKAY) break; 01174 01175 err = mp_add(&e, &s, &s); /* s = e + xr */ 01176 if (err != MP_OKAY) break; 01177 01178 err = mp_mod(&s, &p, &s); /* s = e + xr */ 01179 if (err != MP_OKAY) break; 01180 01181 err = mp_mulmod(&s, &pubkey.k, &p, &s); /* s = (e + xr)/k */ 01182 if (err != MP_OKAY) break; 01183 01184 ecc_free(&pubkey); 01185 if (mp_iszero(&s) == MP_NO) 01186 break; 01187 } 01188 } 01189 ecc_free(&pubkey); 01190 } 01191 01192 /* store as SEQUENCE { r, s -- integer } */ 01193 if (err == MP_OKAY) 01194 err = StoreECC_DSA_Sig(out, outlen, &r, &s); 01195 01196 mp_clear(&r); 01197 mp_clear(&s); 01198 mp_clear(&p); 01199 mp_clear(&e); 01200 01201 return err; 01202 } 01203 01204 01205 /** 01206 Free an ECC key from memory 01207 key The key you wish to free 01208 */ 01209 void ecc_free(ecc_key* key) 01210 { 01211 if (key == NULL) 01212 return; 01213 01214 mp_clear(&key->pubkey.x); 01215 mp_clear(&key->pubkey.y); 01216 mp_clear(&key->pubkey.z); 01217 mp_clear(&key->k); 01218 } 01219 01220 01221 /* verify 01222 * 01223 * w = s^-1 mod n 01224 * u1 = xw 01225 * u2 = rw 01226 * X = u1*G + u2*Q 01227 * v = X_x1 mod n 01228 * accept if v == r 01229 */ 01230 01231 /** 01232 Verify an ECC signature 01233 sig The signature to verify 01234 siglen The length of the signature (octets) 01235 hash The hash (message digest) that was signed 01236 hashlen The length of the hash (octets) 01237 stat Result of signature, 1==valid, 0==invalid 01238 key The corresponding public ECC key 01239 return MP_OKAY if successful (even if the signature is not valid) 01240 */ 01241 int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen, 01242 int* stat, ecc_key* key) 01243 { 01244 ecc_point *mG, *mQ; 01245 mp_int r; 01246 mp_int s; 01247 mp_int v; 01248 mp_int w; 01249 mp_int u1; 01250 mp_int u2; 01251 mp_int e; 01252 mp_int p; 01253 mp_int m; 01254 mp_digit mp; 01255 int err; 01256 01257 if (sig == NULL || hash == NULL || stat == NULL || key == NULL) 01258 return ECC_BAD_ARG_E; 01259 01260 /* default to invalid signature */ 01261 *stat = 0; 01262 01263 /* is the IDX valid ? */ 01264 if (ecc_is_valid_idx(key->idx) != 1) { 01265 return ECC_BAD_ARG_E; 01266 } 01267 01268 /* allocate ints */ 01269 if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) { 01270 return MEMORY_E; 01271 } 01272 01273 if ((err = mp_init(&m)) != MP_OKAY) { 01274 mp_clear(&v); 01275 mp_clear(&w); 01276 mp_clear(&u1); 01277 mp_clear(&u2); 01278 mp_clear(&p); 01279 mp_clear(&e); 01280 return MEMORY_E; 01281 } 01282 01283 /* allocate points */ 01284 mG = ecc_new_point(); 01285 mQ = ecc_new_point(); 01286 if (mQ == NULL || mG == NULL) 01287 err = MEMORY_E; 01288 01289 /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. 01290 * If either of those don't allocate correctly, none of 01291 * the rest of this function will execute, and everything 01292 * gets cleaned up at the end. */ 01293 XMEMSET(&r, 0, sizeof(r)); 01294 XMEMSET(&s, 0, sizeof(s)); 01295 if (err == MP_OKAY) 01296 err = DecodeECC_DSA_Sig(sig, siglen, &r, &s); 01297 01298 /* get the order */ 01299 if (err == MP_OKAY) 01300 err = mp_read_radix(&p, (char *)key->dp->order, 16); 01301 01302 /* get the modulus */ 01303 if (err == MP_OKAY) 01304 err = mp_read_radix(&m, (char *)key->dp->prime, 16); 01305 01306 /* check for zero */ 01307 if (err == MP_OKAY) { 01308 if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT || 01309 mp_cmp(&s, &p) != MP_LT) 01310 err = MP_ZERO_E; 01311 } 01312 /* read hash */ 01313 if (err == MP_OKAY) { 01314 int truncLen = (int)hashlen; 01315 if (truncLen > ecc_size(key)) 01316 truncLen = ecc_size(key); 01317 err = mp_read_unsigned_bin(&e, (byte*)hash, truncLen); 01318 } 01319 01320 /* w = s^-1 mod n */ 01321 if (err == MP_OKAY) 01322 err = mp_invmod(&s, &p, &w); 01323 01324 /* u1 = ew */ 01325 if (err == MP_OKAY) 01326 err = mp_mulmod(&e, &w, &p, &u1); 01327 01328 /* u2 = rw */ 01329 if (err == MP_OKAY) 01330 err = mp_mulmod(&r, &w, &p, &u2); 01331 01332 /* find mG and mQ */ 01333 if (err == MP_OKAY) 01334 err = mp_read_radix(&mG->x, (char *)key->dp->Gx, 16); 01335 01336 if (err == MP_OKAY) 01337 err = mp_read_radix(&mG->y, (char *)key->dp->Gy, 16); 01338 if (err == MP_OKAY) 01339 mp_set(&mG->z, 1); 01340 01341 if (err == MP_OKAY) 01342 err = mp_copy(&key->pubkey.x, &mQ->x); 01343 if (err == MP_OKAY) 01344 err = mp_copy(&key->pubkey.y, &mQ->y); 01345 if (err == MP_OKAY) 01346 err = mp_copy(&key->pubkey.z, &mQ->z); 01347 01348 #ifndef ECC_SHAMIR 01349 /* compute u1*mG + u2*mQ = mG */ 01350 if (err == MP_OKAY) 01351 err = ecc_mulmod(&u1, mG, mG, &m, 0); 01352 if (err == MP_OKAY) 01353 err = ecc_mulmod(&u2, mQ, mQ, &m, 0); 01354 01355 /* find the montgomery mp */ 01356 if (err == MP_OKAY) 01357 err = mp_montgomery_setup(&m, &mp); 01358 01359 /* add them */ 01360 if (err == MP_OKAY) 01361 err = ecc_projective_add_point(mQ, mG, mG, &m, &mp); 01362 01363 /* reduce */ 01364 if (err == MP_OKAY) 01365 err = ecc_map(mG, &m, &mp); 01366 #else 01367 /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ 01368 if (err == MP_OKAY) 01369 err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &m); 01370 #endif /* ECC_SHAMIR */ 01371 01372 /* v = X_x1 mod n */ 01373 if (err == MP_OKAY) 01374 err = mp_mod(&mG->x, &p, &v); 01375 01376 /* does v == r */ 01377 if (err == MP_OKAY) { 01378 if (mp_cmp(&v, &r) == MP_EQ) 01379 *stat = 1; 01380 } 01381 01382 ecc_del_point(mG); 01383 ecc_del_point(mQ); 01384 01385 mp_clear(&r); 01386 mp_clear(&s); 01387 mp_clear(&v); 01388 mp_clear(&w); 01389 mp_clear(&u1); 01390 mp_clear(&u2); 01391 mp_clear(&p); 01392 mp_clear(&e); 01393 mp_clear(&m); 01394 01395 return err; 01396 } 01397 01398 01399 /* export public ECC key in ANSI X9.63 format */ 01400 int ecc_export_x963(ecc_key* key, byte* out, word32* outLen) 01401 { 01402 byte buf[ECC_BUFSIZE]; 01403 word32 numlen; 01404 01405 if (key == NULL || out == NULL || outLen == NULL) 01406 return ECC_BAD_ARG_E; 01407 01408 if (ecc_is_valid_idx(key->idx) == 0) { 01409 return ECC_BAD_ARG_E; 01410 } 01411 numlen = key->dp->size; 01412 01413 if (*outLen < (1 + 2*numlen)) { 01414 *outLen = 1 + 2*numlen; 01415 return BUFFER_E; 01416 } 01417 01418 /* store byte 0x04 */ 01419 out[0] = 0x04; 01420 01421 /* pad and store x */ 01422 XMEMSET(buf, 0, sizeof(buf)); 01423 mp_to_unsigned_bin(&key->pubkey.x, 01424 buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x))); 01425 XMEMCPY(out+1, buf, numlen); 01426 01427 /* pad and store y */ 01428 XMEMSET(buf, 0, sizeof(buf)); 01429 mp_to_unsigned_bin(&key->pubkey.y, 01430 buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y))); 01431 XMEMCPY(out+1+numlen, buf, numlen); 01432 01433 *outLen = 1 + 2*numlen; 01434 01435 return 0; 01436 } 01437 01438 01439 /* import public ECC key in ANSI X9.63 format */ 01440 int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) 01441 { 01442 int x, err; 01443 01444 01445 if (in == NULL || key == NULL) 01446 return ECC_BAD_ARG_E; 01447 01448 /* must be odd */ 01449 if ((inLen & 1) == 0) { 01450 return ECC_BAD_ARG_E; 01451 } 01452 01453 /* init key */ 01454 if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, 01455 NULL, NULL) != MP_OKAY) { 01456 return MEMORY_E; 01457 } 01458 err = MP_OKAY; 01459 01460 /* check for 4, 6 or 7 */ 01461 if (in[0] != 4 && in[0] != 6 && in[0] != 7) { 01462 err = ASN_PARSE_E; 01463 } 01464 01465 /* read data */ 01466 if (err == MP_OKAY) 01467 err = mp_read_unsigned_bin(&key->pubkey.x, (byte*)in+1, (inLen-1)>>1); 01468 01469 if (err == MP_OKAY) 01470 err = mp_read_unsigned_bin(&key->pubkey.y, (byte*)in+1+((inLen-1)>>1), 01471 (inLen-1)>>1); 01472 01473 if (err == MP_OKAY) 01474 mp_set(&key->pubkey.z, 1); 01475 01476 if (err == MP_OKAY) { 01477 /* determine the idx */ 01478 for (x = 0; ecc_sets[x].size != 0; x++) { 01479 if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) { 01480 break; 01481 } 01482 } 01483 if (ecc_sets[x].size == 0) { 01484 err = ASN_PARSE_E; 01485 } else { 01486 /* set the idx */ 01487 key->idx = x; 01488 key->dp = &ecc_sets[x]; 01489 key->type = ECC_PUBLICKEY; 01490 } 01491 } 01492 01493 if (err != MP_OKAY) { 01494 mp_clear(&key->pubkey.x); 01495 mp_clear(&key->pubkey.y); 01496 mp_clear(&key->pubkey.z); 01497 mp_clear(&key->k); 01498 } 01499 01500 return err; 01501 } 01502 01503 01504 /* ecc private key import, public key in ANSI X9.63 format, private raw */ 01505 int ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, 01506 word32 pubSz, ecc_key* key) 01507 { 01508 int ret = ecc_import_x963(pub, pubSz, key); 01509 if (ret != 0) 01510 return ret; 01511 01512 key->type = ECC_PRIVATEKEY; 01513 01514 return mp_read_unsigned_bin(&key->k, priv, privSz); 01515 } 01516 01517 01518 /* key size in octets */ 01519 int ecc_size(ecc_key* key) 01520 { 01521 if (key == NULL) return 0; 01522 01523 return key->dp->size; 01524 } 01525 01526 01527 /* signature size in octets */ 01528 int ecc_sig_size(ecc_key* key) 01529 { 01530 int sz = ecc_size(key); 01531 if (sz < 0) 01532 return sz; 01533 01534 return sz * 2 + SIG_HEADER_SZ; 01535 } 01536 01537 #endif /* HAVE_ECC */
Generated on Thu Jul 14 2022 00:25:23 by 1.7.2