libtomcrypt ecc enhancements
Karel Miko
9 years ago
436 | 436 | #ifdef LTC_MECC |
437 | 437 | /* Supported ECC Key Sizes */ |
438 | 438 | #ifndef LTC_NO_CURVES |
439 | #define LTC_ECC_SECP112R1 | |
440 | #define LTC_ECC_SECP112R2 | |
441 | #define LTC_ECC_SECP128R1 | |
442 | #define LTC_ECC_SECP128R2 | |
443 | #define LTC_ECC_SECP160R1 | |
444 | #define LTC_ECC_SECP160R2 | |
445 | #define LTC_ECC_SECP160K1 | |
446 | #define LTC_ECC_BRAINPOOLP160R1 | |
447 | #define LTC_ECC_SECP192R1 | |
448 | #define LTC_ECC_PRIME192V2 | |
449 | #define LTC_ECC_PRIME192V3 | |
450 | #define LTC_ECC_SECP192K1 | |
451 | #define LTC_ECC_BRAINPOOLP192R1 | |
452 | #define LTC_ECC_SECP224R1 | |
453 | #define LTC_ECC_SECP224K1 | |
454 | #define LTC_ECC_BRAINPOOLP224R1 | |
455 | #define LTC_ECC_PRIME239V1 | |
456 | #define LTC_ECC_PRIME239V2 | |
457 | #define LTC_ECC_PRIME239V3 | |
458 | #define LTC_ECC_SECP256R1 | |
459 | #define LTC_ECC_SECP256K1 | |
460 | #define LTC_ECC_BRAINPOOLP256R1 | |
461 | #define LTC_ECC_BRAINPOOLP320R1 | |
462 | #define LTC_ECC_SECP384R1 | |
463 | #define LTC_ECC_BRAINPOOLP384R1 | |
464 | #define LTC_ECC_BRAINPOOLP512R1 | |
465 | #define LTC_ECC_SECP521R1 | |
466 | /* OLD deprecated (but still working) defines */ | |
439 | 467 | #define LTC_ECC112 |
440 | 468 | #define LTC_ECC128 |
441 | 469 | #define LTC_ECC160 |
216 | 216 | @return CRYPT_OK on success |
217 | 217 | */ |
218 | 218 | int (*sqr)(void *a, void *b); |
219 | ||
220 | /** Square root (mod prime) | |
221 | @param a The integer to compute square root mod prime from | |
222 | @param b The prime | |
223 | @param c The destination | |
224 | @return CRYPT_OK on success | |
225 | */ | |
226 | int (*sqrtmod_prime)(void *a, void *b, void *c); | |
219 | 227 | |
220 | 228 | /** Divide an integer |
221 | 229 | @param a The dividend |
337 | 345 | @param k The integer to multiply the point by |
338 | 346 | @param G The point to multiply |
339 | 347 | @param R The destination for kG |
348 | @param a ECC curve parameter a (if NULL we assume a == -3) | |
340 | 349 | @param modulus The modulus for the field |
341 | 350 | @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only) |
342 | 351 | @return CRYPT_OK on success |
343 | 352 | */ |
344 | int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); | |
353 | int (*ecc_ptmul)(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); | |
345 | 354 | |
346 | 355 | /** ECC GF(p) point addition |
347 | 356 | @param P The first point |
348 | 357 | @param Q The second point |
349 | 358 | @param R The destination of P + Q |
359 | @param a ECC curve parameter a (if NULL we assume a == -3) | |
350 | 360 | @param modulus The modulus |
351 | 361 | @param mp The "b" value from montgomery_setup() |
352 | 362 | @return CRYPT_OK on success |
353 | 363 | */ |
354 | int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); | |
364 | int (*ecc_ptadd)(ecc_point *P, ecc_point *Q, ecc_point *R, void *a, void *modulus, void *mp); | |
355 | 365 | |
356 | 366 | /** ECC GF(p) point double |
357 | 367 | @param P The first point |
358 | 368 | @param R The destination of 2P |
369 | @param a ECC curve parameter a (if NULL we assume a == -3) | |
359 | 370 | @param modulus The modulus |
360 | 371 | @param mp The "b" value from montgomery_setup() |
361 | 372 | @return CRYPT_OK on success |
362 | 373 | */ |
363 | int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *modulus, void *mp); | |
374 | int (*ecc_ptdbl)(ecc_point *P, ecc_point *R, void *a, void *modulus, void *mp); | |
364 | 375 | |
365 | 376 | /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1) |
366 | 377 | @param P The point to map |
384 | 395 | int (*ecc_mul2add)(ecc_point *A, void *kA, |
385 | 396 | ecc_point *B, void *kB, |
386 | 397 | ecc_point *C, |
398 | void *a, | |
387 | 399 | void *modulus); |
388 | 400 | |
389 | 401 | /* ---- (optional) rsa optimized math (for internal CRT) ---- */ |
497 | 509 | #define mp_mul(a, b, c) ltc_mp.mul(a, b, c) |
498 | 510 | #define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) |
499 | 511 | #define mp_sqr(a, b) ltc_mp.sqr(a, b) |
512 | #define mp_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c) | |
500 | 513 | #define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) |
501 | 514 | #define mp_div_2(a, b) ltc_mp.div_2(a, b) |
502 | 515 | #define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c) |
1 | 1 | |
2 | 2 | enum { |
3 | 3 | PK_PUBLIC=0, |
4 | PK_PRIVATE=1 | |
4 | PK_PRIVATE=1, | |
5 | PK_PUBLIC_COMPRESSED=2 /* used only when exporting public ECC key */ | |
5 | 6 | }; |
6 | 7 | |
7 | 8 | /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */ |
13 | 14 | |
14 | 15 | enum { |
15 | 16 | PKA_RSA, |
16 | PKA_DSA | |
17 | PKA_DSA, | |
18 | PKA_EC, | |
19 | EC_PRIME_FIELD | |
17 | 20 | }; |
18 | 21 | |
19 | 22 | typedef struct Oid { |
226 | 229 | /** The prime that defines the field the curve is in (encoded in hex) */ |
227 | 230 | char *prime; |
228 | 231 | |
232 | /** The fields A param (hex) */ | |
233 | char *A; | |
234 | ||
229 | 235 | /** The fields B param (hex) */ |
230 | 236 | char *B; |
231 | 237 | |
237 | 243 | |
238 | 244 | /** The y co-ordinate of the base point on the curve (hex) */ |
239 | 245 | char *Gy; |
246 | ||
247 | /** The co-factor */ | |
248 | unsigned long cofactor; | |
249 | ||
250 | /** The OID stucture */ | |
251 | oid_st oid; | |
240 | 252 | } ltc_ecc_set_type; |
241 | 253 | |
242 | 254 | /** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ |
276 | 288 | void ecc_sizes(int *low, int *high); |
277 | 289 | int ecc_get_size(ecc_key *key); |
278 | 290 | |
291 | int ecc_dp_init(ltc_ecc_set_type *dp); | |
292 | int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name); | |
293 | int ecc_dp_clear(ltc_ecc_set_type *dp); | |
294 | ||
279 | 295 | int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); |
280 | 296 | int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp); |
281 | 297 | void ecc_free(ecc_key *key); |
287 | 303 | int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen); |
288 | 304 | int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); |
289 | 305 | int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); |
306 | ||
307 | int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); | |
308 | int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); | |
309 | ||
310 | int ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed); | |
311 | int ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y); | |
312 | int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *key); | |
313 | int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp); | |
290 | 314 | |
291 | 315 | int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, |
292 | 316 | unsigned char *out, unsigned long *outlen); |
308 | 332 | const unsigned char *hash, unsigned long hashlen, |
309 | 333 | int *stat, ecc_key *key); |
310 | 334 | |
335 | int ecc_verify_key(ecc_key *key); | |
336 | ||
311 | 337 | /* low level functions */ |
312 | 338 | ecc_point *ltc_ecc_new_point(void); |
313 | 339 | void ltc_ecc_del_point(ecc_point *p); |
314 | 340 | int ltc_ecc_is_valid_idx(int n); |
341 | int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y); | |
315 | 342 | |
316 | 343 | /* point ops (mp == montgomery digit) */ |
317 | 344 | #if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) |
318 | 345 | /* R = 2P */ |
319 | int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp); | |
346 | int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *a, void *modulus, void *mp); | |
320 | 347 | |
321 | 348 | /* R = P + Q */ |
322 | int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp); | |
349 | int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *a, void *modulus, void *mp); | |
323 | 350 | #endif |
324 | 351 | |
325 | 352 | #if defined(LTC_MECC_FP) |
326 | 353 | /* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ |
327 | int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); | |
354 | int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); | |
328 | 355 | |
329 | 356 | /* functions for saving/loading/freeing/adding to fixed point cache */ |
330 | 357 | int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); |
337 | 364 | #endif |
338 | 365 | |
339 | 366 | /* R = kG */ |
340 | int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map); | |
367 | int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); | |
341 | 368 | |
342 | 369 | #ifdef LTC_ECC_SHAMIR |
343 | 370 | /* kA*A + kB*B = C */ |
344 | 371 | int ltc_ecc_mul2add(ecc_point *A, void *kA, |
345 | 372 | ecc_point *B, void *kB, |
346 | 373 | ecc_point *C, |
374 | void *a, | |
347 | 375 | void *modulus); |
348 | 376 | |
349 | 377 | #ifdef LTC_MECC_FP |
350 | 378 | /* Shamir's trick with optimized point multiplication using fixed point cache */ |
351 | 379 | int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, |
352 | 380 | ecc_point *B, void *kB, |
353 | ecc_point *C, void *modulus); | |
381 | ecc_point *C, | |
382 | void *a, | |
383 | void *modulus); | |
354 | 384 | #endif |
355 | 385 | |
356 | 386 | #endif |
470 | 500 | unsigned long size; |
471 | 501 | /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */ |
472 | 502 | int used; |
503 | /** Flag used to indicate optional items in ASN.1 sequences */ | |
504 | int optional; | |
505 | /** Flag used to indicate context specific tags on ASN.1 sequence items */ | |
506 | unsigned char tag; | |
473 | 507 | /** prev/next entry in the list */ |
474 | 508 | struct ltc_asn1_list_ *prev, *next, *child, *parent; |
475 | 509 | } ltc_asn1_list; |
482 | 516 | LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \ |
483 | 517 | LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ |
484 | 518 | LTC_MACRO_list[LTC_MACRO_temp].used = 0; \ |
519 | LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \ | |
520 | LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \ | |
485 | 521 | } while (0) |
486 | 522 | |
487 | 523 | /* SEQUENCE */ |
506 | 542 | int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, |
507 | 543 | unsigned int algorithm, void* public_key, unsigned long* public_key_len, |
508 | 544 | unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len); |
545 | ||
546 | int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen, | |
547 | unsigned int algorithm, void* public_key, unsigned long* public_key_len, | |
548 | unsigned long parameters_type, void* parameters, unsigned long parameters_len, | |
549 | unsigned long *parameters_outsize); | |
509 | 550 | |
510 | 551 | /* SET */ |
511 | 552 | #define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0) |
669 | 669 | * The algorithm builds patterns in increasing bit order by first making all |
670 | 670 | * single bit input patterns, then all two bit input patterns and so on |
671 | 671 | */ |
672 | static int build_lut(int idx, void *modulus, void *mp, void *mu) | |
672 | static int build_lut(int idx, void *a, void *modulus, void *mp, void *mu) | |
673 | 673 | { |
674 | 674 | unsigned x, y, err, bitlen, lut_gap; |
675 | 675 | void *tmp; |
708 | 708 | |
709 | 709 | /* now double it bitlen/FP_LUT times */ |
710 | 710 | for (y = 0; y < lut_gap; y++) { |
711 | if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<<x], fp_cache[idx].LUT[1<<x], modulus, mp)) != CRYPT_OK) { | |
711 | if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<<x], fp_cache[idx].LUT[1<<x], a, modulus, mp)) != CRYPT_OK) { | |
712 | 712 | goto ERR; |
713 | 713 | } |
714 | 714 | } |
721 | 721 | |
722 | 722 | /* perform the add */ |
723 | 723 | if ((err = ltc_mp.ecc_ptadd(fp_cache[idx].LUT[lut_orders[y].terma], fp_cache[idx].LUT[lut_orders[y].termb], |
724 | fp_cache[idx].LUT[y], modulus, mp)) != CRYPT_OK) { | |
724 | fp_cache[idx].LUT[y], a, modulus, mp)) != CRYPT_OK) { | |
725 | 725 | goto ERR; |
726 | 726 | } |
727 | 727 | } |
776 | 776 | } |
777 | 777 | |
778 | 778 | /* perform a fixed point ECC mulmod */ |
779 | static int accel_fp_mul(int idx, void *k, ecc_point *R, void *modulus, void *mp, int map) | |
779 | static int accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus, void *mp, int map) | |
780 | 780 | { |
781 | 781 | unsigned char kb[128]; |
782 | 782 | int x; |
869 | 869 | |
870 | 870 | /* double if not first */ |
871 | 871 | if (!first) { |
872 | if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { | |
872 | if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { | |
873 | 873 | return err; |
874 | 874 | } |
875 | 875 | } |
876 | 876 | |
877 | 877 | /* add if not first, otherwise copy */ |
878 | 878 | if (!first && z) { |
879 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, modulus, mp)) != CRYPT_OK) { | |
879 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) { | |
880 | 880 | return err; |
881 | 881 | } |
882 | 882 | } else if (z) { |
901 | 901 | /* perform a fixed point ECC mulmod */ |
902 | 902 | static int accel_fp_mul2add(int idx1, int idx2, |
903 | 903 | void *kA, void *kB, |
904 | ecc_point *R, void *modulus, void *mp) | |
904 | ecc_point *R, void *a, void *modulus, void *mp) | |
905 | 905 | { |
906 | 906 | unsigned char kb[2][128]; |
907 | 907 | int x; |
1057 | 1057 | |
1058 | 1058 | /* double if not first */ |
1059 | 1059 | if (!first) { |
1060 | if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { | |
1060 | if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { | |
1061 | 1061 | return err; |
1062 | 1062 | } |
1063 | 1063 | } |
1065 | 1065 | /* add if not first, otherwise copy */ |
1066 | 1066 | if (!first) { |
1067 | 1067 | if (zA) { |
1068 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, modulus, mp)) != CRYPT_OK) { | |
1068 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { | |
1069 | 1069 | return err; |
1070 | 1070 | } |
1071 | 1071 | } |
1072 | 1072 | if (zB) { |
1073 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, modulus, mp)) != CRYPT_OK) { | |
1073 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { | |
1074 | 1074 | return err; |
1075 | 1075 | } |
1076 | 1076 | } |
1083 | 1083 | } |
1084 | 1084 | if (zB && first == 0) { |
1085 | 1085 | if (zB) { |
1086 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, modulus, mp)) != CRYPT_OK) { | |
1086 | if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { | |
1087 | 1087 | return err; |
1088 | 1088 | } |
1089 | 1089 | } |
1111 | 1111 | */ |
1112 | 1112 | int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, |
1113 | 1113 | ecc_point *B, void *kB, |
1114 | ecc_point *C, void *modulus) | |
1114 | ecc_point *C, | |
1115 | void *a, | |
1116 | void *modulus) | |
1115 | 1117 | { |
1116 | 1118 | int idx1, idx2, err; |
1117 | 1119 | void *mp, *mu; |
1167 | 1169 | } |
1168 | 1170 | |
1169 | 1171 | /* build the LUT */ |
1170 | if ((err = build_lut(idx1, modulus, mp, mu)) != CRYPT_OK) { | |
1172 | if ((err = build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) { | |
1171 | 1173 | goto LBL_ERR;; |
1172 | 1174 | } |
1173 | 1175 | } |
1188 | 1190 | } |
1189 | 1191 | |
1190 | 1192 | /* build the LUT */ |
1191 | if ((err = build_lut(idx2, modulus, mp, mu)) != CRYPT_OK) { | |
1193 | if ((err = build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) { | |
1192 | 1194 | goto LBL_ERR;; |
1193 | 1195 | } |
1194 | 1196 | } |
1199 | 1201 | /* compute mp */ |
1200 | 1202 | if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } |
1201 | 1203 | } |
1202 | err = accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, mp); | |
1204 | err = accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); | |
1203 | 1205 | } else { |
1204 | err = ltc_ecc_mul2add(A, kA, B, kB, C, modulus); | |
1206 | err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus); | |
1205 | 1207 | } |
1206 | 1208 | LBL_ERR: |
1207 | 1209 | LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); |
1219 | 1221 | @param k The multiplicand |
1220 | 1222 | @param G Base point to multiply |
1221 | 1223 | @param R [out] Destination of product |
1224 | @param a ECC curve parameter a | |
1222 | 1225 | @param modulus The modulus for the curve |
1223 | 1226 | @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form |
1224 | 1227 | @return CRYPT_OK if successful |
1225 | 1228 | */ |
1226 | int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) | |
1229 | int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) | |
1227 | 1230 | { |
1228 | 1231 | int idx, err; |
1229 | 1232 | void *mp, *mu; |
1265 | 1268 | } |
1266 | 1269 | |
1267 | 1270 | /* build the LUT */ |
1268 | if ((err = build_lut(idx, modulus, mp, mu)) != CRYPT_OK) { | |
1271 | if ((err = build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { | |
1269 | 1272 | goto LBL_ERR;; |
1270 | 1273 | } |
1271 | 1274 | } |
1275 | 1278 | /* compute mp */ |
1276 | 1279 | if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } |
1277 | 1280 | } |
1278 | err = accel_fp_mul(idx, k, R, modulus, mp, map); | |
1281 | err = accel_fp_mul(idx, k, R, a, modulus, mp, map); | |
1279 | 1282 | } else { |
1280 | err = ltc_ecc_mulmod(k, G, R, modulus, map); | |
1283 | err = ltc_ecc_mulmod(k, G, R, a, modulus, map); | |
1281 | 1284 | } |
1282 | 1285 | LBL_ERR: |
1283 | 1286 | LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); |
1364 | 1367 | } |
1365 | 1368 | |
1366 | 1369 | /* build the LUT */ |
1367 | if ((err = build_lut(idx, modulus, mp, mu)) != CRYPT_OK) { | |
1370 | if ((err = build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { | |
1368 | 1371 | goto LBL_ERR; |
1369 | 1372 | } |
1370 | 1373 | fp_cache[idx].lru_count = 2; |
258 | 258 | return mpi_to_ltc_error(mp_sqr(a, b)); |
259 | 259 | } |
260 | 260 | |
261 | /* sqrtmod_prime */ | |
262 | static int sqrtmod_prime(void *a, void *b, void *c) | |
263 | { | |
264 | LTC_ARGCHK(a != NULL); | |
265 | LTC_ARGCHK(b != NULL); | |
266 | LTC_ARGCHK(c != NULL); | |
267 | return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c)); | |
268 | } | |
269 | ||
261 | 270 | /* div */ |
262 | 271 | static int divide(void *a, void *b, void *c, void *d) |
263 | 272 | { |
453 | 462 | &mul, |
454 | 463 | &muli, |
455 | 464 | &sqr, |
465 | &sqrtmod_prime, | |
456 | 466 | ÷, |
457 | 467 | &div_2, |
458 | 468 | &modi, |
19 | 19 | 6, |
20 | 20 | }; |
21 | 21 | |
22 | static const oid_st ec_oid = { | |
23 | { 1, 2, 840, 10045, 2, 1 }, | |
24 | 6, | |
25 | }; | |
26 | ||
27 | static const oid_st ec_primef = { | |
28 | { 1, 2, 840, 10045, 1, 1 }, | |
29 | 6, | |
30 | }; | |
31 | ||
22 | 32 | /* |
23 | 33 | Returns the OID of the public key algorithm. |
24 | 34 | @return CRYPT_OK if valid |
32 | 42 | case PKA_DSA: |
33 | 43 | XMEMCPY(st, &dsa_oid, sizeof(*st)); |
34 | 44 | break; |
45 | case PKA_EC: | |
46 | XMEMCPY(st, &ec_oid, sizeof(*st)); | |
47 | break; | |
48 | case EC_PRIME_FIELD: | |
49 | XMEMCPY(st, &ec_primef, sizeof(*st)); | |
50 | break; | |
35 | 51 | default: |
36 | 52 | return CRYPT_INVALID_ARG; |
37 | 53 | } |
96 | 96 | break; |
97 | 97 | } |
98 | 98 | |
99 | /* handle context specific tags - just skip the tag + len bytes */ | |
100 | z = 0; | |
101 | if (list[i].tag > 0 && list[i].tag == in[x + z++]) { | |
102 | if (in[x+z] & 0x80) { | |
103 | y = in[x + z++] & 0x7F; | |
104 | if (y == 0 || y > 2) { return CRYPT_INVALID_PACKET; } | |
105 | z += y; | |
106 | } else { | |
107 | z++; | |
108 | } | |
109 | x += z; | |
110 | inlen -= z; | |
111 | } | |
112 | ||
99 | 113 | switch (type) { |
100 | 114 | case LTC_ASN1_BOOLEAN: |
101 | 115 | z = inlen; |
102 | 116 | if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { |
117 | if (!ordered || list[i].optional) { continue; } | |
103 | 118 | goto LBL_ERR; |
104 | 119 | } |
105 | 120 | if ((err = der_length_boolean(&z)) != CRYPT_OK) { |
110 | 125 | case LTC_ASN1_INTEGER: |
111 | 126 | z = inlen; |
112 | 127 | if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { |
113 | if (!ordered) { continue; } | |
128 | if (!ordered || list[i].optional) { continue; } | |
114 | 129 | goto LBL_ERR; |
115 | 130 | } |
116 | 131 | if ((err = der_length_integer(data, &z)) != CRYPT_OK) { |
121 | 136 | case LTC_ASN1_SHORT_INTEGER: |
122 | 137 | z = inlen; |
123 | 138 | if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { |
124 | if (!ordered) { continue; } | |
139 | if (!ordered || list[i].optional) { continue; } | |
125 | 140 | goto LBL_ERR; |
126 | 141 | } |
127 | 142 | if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { |
133 | 148 | case LTC_ASN1_BIT_STRING: |
134 | 149 | z = inlen; |
135 | 150 | if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { |
136 | if (!ordered) { continue; } | |
151 | if (!ordered || list[i].optional) { continue; } | |
137 | 152 | goto LBL_ERR; |
138 | 153 | } |
139 | 154 | list[i].size = size; |
145 | 160 | case LTC_ASN1_RAW_BIT_STRING: |
146 | 161 | z = inlen; |
147 | 162 | if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { |
148 | if (!ordered) { continue; } | |
163 | if (!ordered || list[i].optional) { continue; } | |
149 | 164 | goto LBL_ERR; |
150 | 165 | } |
151 | 166 | list[i].size = size; |
157 | 172 | case LTC_ASN1_OCTET_STRING: |
158 | 173 | z = inlen; |
159 | 174 | if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { |
160 | if (!ordered) { continue; } | |
175 | if (!ordered || list[i].optional) { continue; } | |
161 | 176 | goto LBL_ERR; |
162 | 177 | } |
163 | 178 | list[i].size = size; |
168 | 183 | |
169 | 184 | case LTC_ASN1_NULL: |
170 | 185 | if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { |
171 | if (!ordered) { continue; } | |
186 | if (!ordered || list[i].optional) { continue; } | |
172 | 187 | err = CRYPT_INVALID_PACKET; |
173 | 188 | goto LBL_ERR; |
174 | 189 | } |
178 | 193 | case LTC_ASN1_OBJECT_IDENTIFIER: |
179 | 194 | z = inlen; |
180 | 195 | if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { |
181 | if (!ordered) { continue; } | |
196 | if (!ordered || list[i].optional) { continue; } | |
182 | 197 | goto LBL_ERR; |
183 | 198 | } |
184 | 199 | list[i].size = size; |
190 | 205 | case LTC_ASN1_TELETEX_STRING: |
191 | 206 | z = inlen; |
192 | 207 | if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) { |
193 | if (!ordered) { continue; } | |
208 | if (!ordered || list[i].optional) { continue; } | |
194 | 209 | goto LBL_ERR; |
195 | 210 | } |
196 | 211 | list[i].size = size; |
202 | 217 | case LTC_ASN1_IA5_STRING: |
203 | 218 | z = inlen; |
204 | 219 | if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { |
205 | if (!ordered) { continue; } | |
220 | if (!ordered || list[i].optional) { continue; } | |
206 | 221 | goto LBL_ERR; |
207 | 222 | } |
208 | 223 | list[i].size = size; |
215 | 230 | case LTC_ASN1_PRINTABLE_STRING: |
216 | 231 | z = inlen; |
217 | 232 | if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { |
218 | if (!ordered) { continue; } | |
233 | if (!ordered || list[i].optional) { continue; } | |
219 | 234 | goto LBL_ERR; |
220 | 235 | } |
221 | 236 | list[i].size = size; |
227 | 242 | case LTC_ASN1_UTF8_STRING: |
228 | 243 | z = inlen; |
229 | 244 | if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) { |
230 | if (!ordered) { continue; } | |
245 | if (!ordered || list[i].optional) { continue; } | |
231 | 246 | goto LBL_ERR; |
232 | 247 | } |
233 | 248 | list[i].size = size; |
239 | 254 | case LTC_ASN1_UTCTIME: |
240 | 255 | z = inlen; |
241 | 256 | if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) { |
242 | if (!ordered) { continue; } | |
257 | if (!ordered || list[i].optional) { continue; } | |
243 | 258 | goto LBL_ERR; |
244 | 259 | } |
245 | 260 | break; |
247 | 262 | case LTC_ASN1_SET: |
248 | 263 | z = inlen; |
249 | 264 | if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { |
250 | if (!ordered) { continue; } | |
265 | if (!ordered || list[i].optional) { continue; } | |
251 | 266 | goto LBL_ERR; |
252 | 267 | } |
253 | 268 | if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { |
265 | 280 | |
266 | 281 | z = inlen; |
267 | 282 | if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) { |
268 | if (!ordered) { continue; } | |
283 | if (!ordered || list[i].optional) { continue; } | |
269 | 284 | goto LBL_ERR; |
270 | 285 | } |
271 | 286 | if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { |
277 | 292 | case LTC_ASN1_CHOICE: |
278 | 293 | z = inlen; |
279 | 294 | if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) { |
280 | if (!ordered) { continue; } | |
295 | if (!ordered || list[i].optional) { continue; } | |
281 | 296 | goto LBL_ERR; |
282 | 297 | } |
283 | 298 | break; |
298 | 313 | } |
299 | 314 | |
300 | 315 | for (i = 0; i < (int)outlen; i++) { |
301 | if (list[i].used == 0) { | |
316 | if (list[i].used == 0 && list[i].optional == 0) { | |
302 | 317 | err = CRYPT_INVALID_PACKET; |
303 | 318 | goto LBL_ERR; |
304 | 319 | } |
34 | 34 | int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, |
35 | 35 | unsigned int algorithm, void* public_key, unsigned long* public_key_len, |
36 | 36 | unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) |
37 | { | |
38 | return der_decode_subject_public_key_info_ex(in, inlen, algorithm, public_key, public_key_len, | |
39 | parameters_type, parameters, parameters_len, NULL); | |
40 | } | |
41 | ||
42 | int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen, | |
43 | unsigned int algorithm, void* public_key, unsigned long* public_key_len, | |
44 | unsigned long parameters_type, void* parameters, unsigned long parameters_len, | |
45 | unsigned long *parameters_outsize) | |
37 | 46 | { |
38 | 47 | int err; |
39 | 48 | unsigned long len; |
74 | 83 | goto LBL_ERR; |
75 | 84 | } |
76 | 85 | |
86 | if (parameters_outsize) *parameters_outsize = alg_id[1].size; | |
87 | ||
77 | 88 | if ((alg_id[0].size != oid.OIDlen) || |
78 | 89 | XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) { |
79 | 90 | /* OID mismatch */ |
26 | 26 | int der_length_sequence(ltc_asn1_list *list, unsigned long inlen, |
27 | 27 | unsigned long *outlen) |
28 | 28 | { |
29 | return der_length_sequence_ex(list, inlen, outlen, NULL); | |
30 | } | |
31 | ||
32 | int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen, | |
33 | unsigned long *outlen, unsigned long *payloadlen) | |
34 | { | |
29 | 35 | int err; |
30 | 36 | ltc_asn1_type type; |
31 | unsigned long size, x, y, i; | |
37 | unsigned long size, x, y, i, z; | |
32 | 38 | void *data; |
33 | 39 | |
34 | 40 | LTC_ARGCHK(list != NULL); |
44 | 50 | if (type == LTC_ASN1_EOL) { |
45 | 51 | break; |
46 | 52 | } |
53 | ||
54 | /* some items may be optional during import */ | |
55 | if (!list[i].used && list[i].optional) continue; | |
47 | 56 | |
48 | 57 | switch (type) { |
49 | 58 | case LTC_ASN1_BOOLEAN: |
145 | 154 | err = CRYPT_INVALID_ARG; |
146 | 155 | goto LBL_ERR; |
147 | 156 | } |
157 | ||
158 | /* handle context specific tags size */ | |
159 | if (list[i].tag > 0) { | |
160 | if (x < 128) { | |
161 | y += 2; | |
162 | } else if (x < 256) { | |
163 | y += 3; | |
164 | } else if (x < 65536UL) { | |
165 | y += 4; | |
166 | } else if (x < 16777216UL) { | |
167 | y += 5; | |
168 | } else { | |
169 | err = CRYPT_INVALID_ARG; | |
170 | goto LBL_ERR; | |
171 | } | |
172 | } | |
148 | 173 | } |
149 | 174 | |
150 | 175 | /* calc header size */ |
176 | z = y; | |
151 | 177 | if (y < 128) { |
152 | 178 | y += 2; |
153 | 179 | } else if (y < 256) { |
165 | 191 | } |
166 | 192 | |
167 | 193 | /* store size */ |
194 | if (payloadlen) *payloadlen = z; | |
168 | 195 | *outlen = y; |
169 | 196 | err = CRYPT_OK; |
170 | 197 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
22 | 20 | |
23 | 21 | #ifdef LTC_MECC |
24 | 22 | |
25 | /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ | |
23 | /* This array holds the curve parameters: | |
24 | * - it ***MUST*** be organized by size from smallest to largest | |
25 | * - due to curve lookup by keysize the ordering is very important | |
26 | * - be careful when adding/removing items to/from this list | |
27 | * Curves (prime field only) are taken from: | |
28 | * - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*) | |
29 | * - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*) | |
30 | * - ANS X9.62 (named: PRIMEP*) | |
31 | * - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*) | |
32 | */ | |
26 | 33 | const ltc_ecc_set_type ltc_ecc_sets[] = { |
27 | #ifdef LTC_ECC112 | |
28 | { | |
29 | 14, | |
30 | "SECP112R1", | |
31 | "DB7C2ABF62E35E668076BEAD208B", | |
32 | "659EF8BA043916EEDE8911702B22", | |
33 | "DB7C2ABF62E35E7628DFAC6561C5", | |
34 | "09487239995A5EE76B55F9C2F098", | |
35 | "A89CE5AF8724C0A23E0E0FF77500" | |
36 | }, | |
37 | #endif | |
38 | #ifdef LTC_ECC128 | |
39 | { | |
40 | 16, | |
41 | "SECP128R1", | |
42 | "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", | |
43 | "E87579C11079F43DD824993C2CEE5ED3", | |
44 | "FFFFFFFE0000000075A30D1B9038A115", | |
45 | "161FF7528B899B2D0C28607CA52C5B86", | |
46 | "CF5AC8395BAFEB13C02DA292DDED7A83", | |
47 | }, | |
48 | #endif | |
49 | #ifdef LTC_ECC160 | |
50 | { | |
51 | 20, | |
52 | "SECP160R1", | |
53 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", | |
54 | "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", | |
55 | "0100000000000000000001F4C8F927AED3CA752257", | |
56 | "4A96B5688EF573284664698968C38BB913CBFC82", | |
57 | "23A628553168947D59DCC912042351377AC5FB32", | |
58 | }, | |
59 | #endif | |
60 | #ifdef LTC_ECC192 | |
61 | { | |
62 | 24, | |
63 | "ECC-192", | |
64 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", | |
65 | "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", | |
66 | "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", | |
67 | "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", | |
68 | "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", | |
69 | }, | |
70 | #endif | |
71 | #ifdef LTC_ECC224 | |
72 | { | |
73 | 28, | |
74 | "ECC-224", | |
75 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", | |
76 | "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", | |
77 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", | |
78 | "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", | |
79 | "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", | |
80 | }, | |
81 | #endif | |
82 | #ifdef LTC_ECC256 | |
83 | { | |
84 | 32, | |
85 | "ECC-256", | |
86 | "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", | |
87 | "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", | |
88 | "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", | |
89 | "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", | |
90 | "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", | |
91 | }, | |
92 | #endif | |
93 | #ifdef LTC_ECC384 | |
94 | { | |
95 | 48, | |
96 | "ECC-384", | |
97 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", | |
98 | "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", | |
99 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", | |
100 | "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", | |
101 | "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", | |
102 | }, | |
103 | #endif | |
104 | #ifdef LTC_ECC521 | |
105 | { | |
106 | 66, | |
107 | "ECC-521", | |
108 | "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", | |
109 | "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", | |
110 | "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", | |
111 | "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", | |
112 | "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", | |
34 | #if defined(LTC_ECC_SECP112R1) || defined(LTC_ECC112) | |
35 | { /* this curve ***MUST*** be the first from all with size 14 (backward compatibility reasons) */ | |
36 | /* size/bytes */ 14, | |
37 | /* curve name */ "SECP112R1", | |
38 | /* prime */ "DB7C2ABF62E35E668076BEAD208B", | |
39 | /* A */ "DB7C2ABF62E35E668076BEAD2088", | |
40 | /* B */ "659EF8BA043916EEDE8911702B22", | |
41 | /* order */ "DB7C2ABF62E35E7628DFAC6561C5", | |
42 | /* Gx */ "09487239995A5EE76B55F9C2F098", | |
43 | /* Gy */ "A89CE5AF8724C0A23E0E0FF77500", | |
44 | /* cofactor */ 1, | |
45 | /* OID struct */ { {1,3,132,0,6}, 5 } | |
46 | }, | |
47 | #endif | |
48 | #ifdef LTC_ECC_SECP112R2 | |
49 | { | |
50 | /* size/bytes */ 14, | |
51 | /* curve name */ "SECP112R2", | |
52 | /* prime */ "DB7C2ABF62E35E668076BEAD208B", | |
53 | /* A */ "6127C24C05F38A0AAAF65C0EF02C", | |
54 | /* B */ "51DEF1815DB5ED74FCC34C85D709", | |
55 | /* order */ "36DF0AAFD8B8D7597CA10520D04B", | |
56 | /* Gx */ "4BA30AB5E892B4E1649DD0928643", | |
57 | /* Gy */ "ADCD46F5882E3747DEF36E956E97", | |
58 | /* cofactor */ 4, | |
59 | /* OID struct */ { {1,3,132,0,7}, 5 } | |
60 | }, | |
61 | #endif | |
62 | #if defined(LTC_ECC_SECP128R1) || defined(LTC_ECC128) | |
63 | { /* this curve ***MUST*** be the first from all with size 16 (backward compatibility reasons) */ | |
64 | /* size/bytes */ 16, | |
65 | /* curve name */ "SECP128R1", | |
66 | /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", | |
67 | /* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", | |
68 | /* B */ "E87579C11079F43DD824993C2CEE5ED3", | |
69 | /* order */ "FFFFFFFE0000000075A30D1B9038A115", | |
70 | /* Gx */ "161FF7528B899B2D0C28607CA52C5B86", | |
71 | /* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83", | |
72 | /* cofactor */ 1, | |
73 | /* OID struct */ { {1,3,132,0,28}, 5 } | |
74 | }, | |
75 | #endif | |
76 | #ifdef LTC_ECC_SECP128R2 | |
77 | { | |
78 | /* size/bytes */ 16, | |
79 | /* curve name */ "SECP128R2", | |
80 | /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", | |
81 | /* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", | |
82 | /* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D", | |
83 | /* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3", | |
84 | /* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140", | |
85 | /* Gy */ "27B6916A894D3AEE7106FE805FC34B44", | |
86 | /* cofactor */ 4, | |
87 | /* OID struct */ { {1,3,132,0,29}, 5 } | |
88 | }, | |
89 | #endif | |
90 | #if defined(LTC_ECC_SECP160R1) || defined(LTC_ECC160) | |
91 | { /* this curve ***MUST*** be the first from all with size 20 (backward compatibility reasons) */ | |
92 | /* size/bytes */ 20, | |
93 | /* curve name */ "SECP160R1", | |
94 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", | |
95 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", | |
96 | /* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", | |
97 | /* order */ "0100000000000000000001F4C8F927AED3CA752257", | |
98 | /* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82", | |
99 | /* Gy */ "23A628553168947D59DCC912042351377AC5FB32", | |
100 | /* cofactor */ 1, | |
101 | /* OID struct */ { {1,3,132,0,8}, 5 } | |
102 | }, | |
103 | #endif | |
104 | #ifdef LTC_ECC_SECP160R2 | |
105 | { | |
106 | /* size/bytes */ 20, | |
107 | /* curve name */ "SECP160R2", | |
108 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", | |
109 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", | |
110 | /* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", | |
111 | /* order */ "0100000000000000000000351EE786A818F3A1A16B", | |
112 | /* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", | |
113 | /* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", | |
114 | /* cofactor */ 1, | |
115 | /* OID struct */ { {1,3,132,0,30}, 5 } | |
116 | }, | |
117 | #endif | |
118 | #ifdef LTC_ECC_SECP160K1 | |
119 | { | |
120 | /* size/bytes */ 20, | |
121 | /* curve name */ "SECP160K1", | |
122 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", | |
123 | /* A */ "0000000000000000000000000000000000000000", | |
124 | /* B */ "0000000000000000000000000000000000000007", | |
125 | /* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3", | |
126 | /* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", | |
127 | /* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE", | |
128 | /* cofactor */ 1, | |
129 | /* OID struct */ { {1,3,132,0,9}, 5 } | |
130 | }, | |
131 | #endif | |
132 | #ifdef LTC_ECC_BRAINPOOLP160R1 | |
133 | { | |
134 | /* size/bytes */ 20, | |
135 | /* curve name */ "BRAINPOOLP160R1", | |
136 | /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", | |
137 | /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", | |
138 | /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58", | |
139 | /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", | |
140 | /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", | |
141 | /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321", | |
142 | /* cofactor */ 1, | |
143 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,1}, 10 } | |
144 | }, | |
145 | #endif | |
146 | #if defined(LTC_ECC_SECP192R1) || defined(LTC_ECC192) | |
147 | { /* this curve ***MUST*** be the first from all with size 24 (backward compatibility reasons) */ | |
148 | /* size/bytes */ 24, | |
149 | /* curve name */ "SECP192R1", /* same as: NISTP192 PRIME192V1, old libtomcrypt name: ECC-192 */ | |
150 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", | |
151 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", | |
152 | /* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", | |
153 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", | |
154 | /* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", | |
155 | /* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", | |
156 | /* cofactor */ 1, | |
157 | /* OID struct */ { {1,2,840,10045,3,1,1}, 7 } | |
158 | }, | |
159 | #endif | |
160 | #ifdef LTC_ECC_PRIME192V2 | |
161 | { | |
162 | /* size/bytes */ 24, | |
163 | /* curve name */ "PRIME192V2", | |
164 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", | |
165 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", | |
166 | /* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", | |
167 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", | |
168 | /* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", | |
169 | /* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", | |
170 | /* cofactor */ 1, | |
171 | /* OID struct */ { {1,2,840,10045,3,1,2}, 7 } | |
172 | }, | |
173 | #endif | |
174 | #ifdef LTC_ECC_PRIME192V3 | |
175 | { | |
176 | /* size/bytes */ 24, | |
177 | /* curve name */ "PRIME192V3", | |
178 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", | |
179 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", | |
180 | /* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", | |
181 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", | |
182 | /* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", | |
183 | /* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", | |
184 | /* cofactor */ 1, | |
185 | /* OID struct */ { {1,2,840,10045,3,1,3}, 7 } | |
186 | }, | |
187 | #endif | |
188 | #ifdef LTC_ECC_SECP192K1 | |
189 | { | |
190 | /* size/bytes */ 24, | |
191 | /* curve name */ "SECP192K1", | |
192 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", | |
193 | /* A */ "000000000000000000000000000000000000000000000000", | |
194 | /* B */ "000000000000000000000000000000000000000000000003", | |
195 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", | |
196 | /* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", | |
197 | /* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", | |
198 | /* cofactor */ 1, | |
199 | /* OID struct */ { {1,3,132,0,31}, 5 } | |
200 | }, | |
201 | #endif | |
202 | #ifdef LTC_ECC_BRAINPOOLP192R1 | |
203 | { | |
204 | /* size/bytes */ 24, | |
205 | /* curve name */ "BRAINPOOLP192R1", | |
206 | /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", | |
207 | /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", | |
208 | /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", | |
209 | /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", | |
210 | /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", | |
211 | /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", | |
212 | /* cofactor */ 1, | |
213 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,3}, 10 } | |
214 | }, | |
215 | #endif | |
216 | #if defined(LTC_ECC_SECP224R1) || defined(LTC_ECC224) | |
217 | { /* this curve ***MUST*** be the first from all with size 28 (backward compatibility reasons) */ | |
218 | /* size/bytes */ 28, | |
219 | /* curve name */ "SECP224R1", /* same as: NISTP224, old libtomcrypt name: ECC-224 */ | |
220 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", | |
221 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", | |
222 | /* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", | |
223 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", | |
224 | /* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", | |
225 | /* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", | |
226 | /* cofactor */ 1, | |
227 | /* OID struct */ { {1,3,132,0,33}, 5 } | |
228 | }, | |
229 | #endif | |
230 | #ifdef LTC_ECC_SECP224K1 | |
231 | { | |
232 | /* size/bytes */ 28, | |
233 | /* curve name */ "SECP224K1", | |
234 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", | |
235 | /* A */ "00000000000000000000000000000000000000000000000000000000", | |
236 | /* B */ "00000000000000000000000000000000000000000000000000000005", | |
237 | /* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", | |
238 | /* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", | |
239 | /* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", | |
240 | /* cofactor */ 1, | |
241 | /* OID struct */ { {1,3,132,0,32}, 5 } | |
242 | }, | |
243 | #endif | |
244 | #ifdef LTC_ECC_BRAINPOOLP224R1 | |
245 | { | |
246 | /* size/bytes */ 28, | |
247 | /* curve name */ "BRAINPOOLP224R1", | |
248 | /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", | |
249 | /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", | |
250 | /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", | |
251 | /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", | |
252 | /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", | |
253 | /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", | |
254 | /* cofactor */ 1, | |
255 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,5}, 10 } | |
256 | }, | |
257 | #endif | |
258 | #ifdef LTC_ECC_PRIME239V1 | |
259 | { | |
260 | /* size/bytes */ 30, | |
261 | /* curve name */ "PRIME239V1", | |
262 | /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", | |
263 | /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", | |
264 | /* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", | |
265 | /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", | |
266 | /* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", | |
267 | /* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", | |
268 | /* cofactor */ 1, | |
269 | /* OID struct */ { {1,2,840,10045,3,1,4}, 7 } | |
270 | }, | |
271 | #endif | |
272 | #ifdef LTC_ECC_PRIME239V2 | |
273 | { | |
274 | /* size/bytes */ 30, | |
275 | /* curve name */ "PRIME239V2", | |
276 | /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", | |
277 | /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", | |
278 | /* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", | |
279 | /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", | |
280 | /* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", | |
281 | /* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", | |
282 | /* cofactor */ 1, | |
283 | /* OID struct */ { {1,2,840,10045,3,1,5}, 7 } | |
284 | }, | |
285 | #endif | |
286 | #ifdef LTC_ECC_PRIME239V3 | |
287 | { | |
288 | /* size/bytes */ 30, | |
289 | /* curve name */ "PRIME239V3", | |
290 | /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", | |
291 | /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", | |
292 | /* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", | |
293 | /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", | |
294 | /* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", | |
295 | /* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", | |
296 | /* cofactor */ 1, | |
297 | /* OID struct */ { {1,2,840,10045,3,1,6}, 7 } | |
298 | }, | |
299 | #endif | |
300 | #if defined(LTC_ECC_SECP256R1) || defined(LTC_ECC256) | |
301 | { /* this curve ***MUST*** be the first from all with size 32 (backward compatibility reasons) */ | |
302 | /* size/bytes */ 32, | |
303 | /* curve name */ "SECP256R1", /* same as: NISTP256 PRIME256V1, old libtomcrypt name: ECC-256 */ | |
304 | /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", | |
305 | /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", | |
306 | /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", | |
307 | /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", | |
308 | /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", | |
309 | /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", | |
310 | /* cofactor */ 1, | |
311 | /* OID struct */ { {1,2,840,10045,3,1,7}, 7 } | |
312 | }, | |
313 | #endif | |
314 | #ifdef LTC_ECC_SECP256K1 | |
315 | { | |
316 | /* size/bytes */ 32, | |
317 | /* curve name */ "SECP256K1", | |
318 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", | |
319 | /* A */ "0000000000000000000000000000000000000000000000000000000000000000", | |
320 | /* B */ "0000000000000000000000000000000000000000000000000000000000000007", | |
321 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", | |
322 | /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", | |
323 | /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", | |
324 | /* cofactor */ 1, | |
325 | /* OID struct */ { {1,3,132,0,10}, 5 } | |
326 | }, | |
327 | #endif | |
328 | #ifdef LTC_ECC_BRAINPOOLP256R1 | |
329 | { | |
330 | /* size/bytes */ 32, | |
331 | /* curve name */ "BRAINPOOLP256R1", | |
332 | /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", | |
333 | /* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", | |
334 | /* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", | |
335 | /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", | |
336 | /* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", | |
337 | /* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", | |
338 | /* cofactor */ 1, | |
339 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,7}, 10 } | |
340 | }, | |
341 | #endif | |
342 | #ifdef LTC_ECC_BRAINPOOLP320R1 | |
343 | { | |
344 | /* size/bytes */ 40, | |
345 | /* curve name */ "BRAINPOOLP320R1", | |
346 | /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", | |
347 | /* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", | |
348 | /* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", | |
349 | /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", | |
350 | /* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", | |
351 | /* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", | |
352 | /* cofactor */ 1, | |
353 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,9}, 10 } | |
354 | }, | |
355 | #endif | |
356 | #if defined(LTC_ECC_SECP384R1) || defined(LTC_ECC384) | |
357 | { /* this curve ***MUST*** be the first from all with size 48 (backward compatibility reasons) */ | |
358 | /* size/bytes */ 48, | |
359 | /* curve name */ "SECP384R1", /* same as: NISTP384, old libtomcrypt name: ECC-384 */ | |
360 | /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", | |
361 | /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", | |
362 | /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", | |
363 | /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", | |
364 | /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", | |
365 | /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", | |
366 | /* cofactor */ 1, | |
367 | /* OID struct */ { {1,3,132,0,34}, 5 } | |
368 | }, | |
369 | #endif | |
370 | #ifdef LTC_ECC_BRAINPOOLP384R1 | |
371 | { | |
372 | /* size/bytes */ 48, | |
373 | /* curve name */ "BRAINPOOLP384R1", | |
374 | /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", | |
375 | /* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", | |
376 | /* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", | |
377 | /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", | |
378 | /* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", | |
379 | /* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", | |
380 | /* cofactor */ 1, | |
381 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,11}, 10 } | |
382 | }, | |
383 | #endif | |
384 | #ifdef LTC_ECC_BRAINPOOLP512R1 | |
385 | { | |
386 | /* size/bytes */ 64, | |
387 | /* curve name */ "BRAINPOOLP512R1", | |
388 | /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", | |
389 | /* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", | |
390 | /* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", | |
391 | /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", | |
392 | /* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", | |
393 | /* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", | |
394 | /* cofactor */ 1, | |
395 | /* OID struct */ { {1,3,36,3,3,2,8,1,1,13}, 10 } | |
396 | }, | |
397 | #endif | |
398 | #if defined(LTC_ECC_SECP521R1) || defined(LTC_ECC521) | |
399 | { /* this curve ***MUST*** be the first from all with size 66 (backward compatibility reasons) */ | |
400 | /* size/bytes */ 66, | |
401 | /* curve name */ "SECP521R1", /* same as: NISTP521, old libtomcrypt name: ECC-521 */ | |
402 | /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", | |
403 | /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", | |
404 | /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", | |
405 | /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", | |
406 | /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", | |
407 | /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", | |
408 | /* cofactor */ 1, | |
409 | /* OID struct */ { {1,3,132,0,35}, 5 } | |
113 | 410 | }, |
114 | 411 | #endif |
115 | 412 | { |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
66 | 64 | if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; } |
67 | 65 | |
68 | 66 | if (dp == NULL) { |
67 | /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid), | |
68 | * which might be ambiguous (there can more than one curve for given keysize). | |
69 | * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file. | |
70 | */ | |
69 | 71 | /* determine the idx */ |
70 | 72 | for (x = 0; ltc_ecc_sets[x].size != 0; x++) { |
71 | 73 | if ((unsigned)ltc_ecc_sets[x].size >= ((inlen-1)>>1)) { |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
90 | 88 | } |
91 | 89 | |
92 | 90 | /* import ECC key from packet */ |
93 | if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) { | |
91 | if ((err = ecc_import_raw(decode[1].data, decode[1].size, &pubkey, (ltc_ecc_set_type *)key->dp)) != CRYPT_OK) { | |
94 | 92 | goto LBL_ERR; |
95 | 93 | } |
96 | 94 |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | #ifdef LTC_MECC | |
17 | ||
18 | int ecc_dp_clear(ltc_ecc_set_type *dp) | |
19 | { | |
20 | if (dp == NULL) return CRYPT_INVALID_ARG; | |
21 | ||
22 | if (dp->name != NULL) { XFREE(dp->name ); dp->name = NULL; } | |
23 | if (dp->prime != NULL) { XFREE(dp->prime); dp->prime = NULL; } | |
24 | if (dp->A != NULL) { XFREE(dp->A ); dp->A = NULL; } | |
25 | if (dp->B != NULL) { XFREE(dp->B ); dp->B = NULL; } | |
26 | if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; } | |
27 | if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; } | |
28 | if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; } | |
29 | dp->cofactor = 0; | |
30 | ||
31 | return CRYPT_OK; | |
32 | } | |
33 | ||
34 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | #ifdef LTC_MECC | |
17 | ||
18 | int ecc_dp_init(ltc_ecc_set_type *dp) | |
19 | { | |
20 | if (dp == NULL) return CRYPT_INVALID_ARG; | |
21 | ||
22 | dp->name = NULL; | |
23 | dp->prime = NULL; | |
24 | dp->A = NULL; | |
25 | dp->B = NULL; | |
26 | dp->order = NULL; | |
27 | dp->Gx = NULL; | |
28 | dp->Gy = NULL; | |
29 | dp->oid.OIDlen = 0; | |
30 | dp->cofactor = 0; | |
31 | ||
32 | return CRYPT_OK; | |
33 | } | |
34 | ||
35 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | #ifdef LTC_MECC | |
17 | ||
18 | int ecc_dp_set(ltc_ecc_set_type *dp, char *ch_prime, char *ch_A, char *ch_B, char *ch_order, char *ch_Gx, char *ch_Gy, unsigned long cofactor, char *ch_name) | |
19 | { | |
20 | unsigned long l_name, l_prime, l_A, l_B, l_order, l_Gx, l_Gy; | |
21 | ||
22 | if (!dp || !ch_prime || !ch_A || !ch_B || !ch_order || !ch_Gx || !ch_Gy || cofactor==0) return CRYPT_INVALID_ARG; | |
23 | ||
24 | l_name = (unsigned long)strlen(ch_name); | |
25 | l_prime = (unsigned long)strlen(ch_prime); | |
26 | l_A = (unsigned long)strlen(ch_A); | |
27 | l_B = (unsigned long)strlen(ch_B); | |
28 | l_order = (unsigned long)strlen(ch_order); | |
29 | l_Gx = (unsigned long)strlen(ch_Gx); | |
30 | l_Gy = (unsigned long)strlen(ch_Gy); | |
31 | ||
32 | dp->cofactor = cofactor; | |
33 | ||
34 | { /* calculate size */ | |
35 | void *p_num; | |
36 | mp_init(&p_num); | |
37 | mp_read_radix(p_num, ch_prime, 16); | |
38 | dp->size = mp_unsigned_bin_size(p_num); | |
39 | mp_clear(p_num); | |
40 | } | |
41 | ||
42 | if (dp->name != NULL) { XFREE(dp->name ); dp->name = NULL; } | |
43 | if (dp->prime != NULL) { XFREE(dp->prime); dp->prime = NULL; } | |
44 | if (dp->A != NULL) { XFREE(dp->A ); dp->A = NULL; } | |
45 | if (dp->B != NULL) { XFREE(dp->B ); dp->B = NULL; } | |
46 | if (dp->order != NULL) { XFREE(dp->order); dp->order = NULL; } | |
47 | if (dp->Gx != NULL) { XFREE(dp->Gx ); dp->Gx = NULL; } | |
48 | if (dp->Gy != NULL) { XFREE(dp->Gy ); dp->Gy = NULL; } | |
49 | ||
50 | dp->name = XMALLOC(1+l_name); strncpy(dp->name, ch_name, 1+l_name); | |
51 | dp->prime = XMALLOC(1+l_prime); strncpy(dp->prime, ch_prime, 1+l_prime); | |
52 | dp->A = XMALLOC(1+l_A); strncpy(dp->A, ch_A, 1+l_A); | |
53 | dp->B = XMALLOC(1+l_B); strncpy(dp->B, ch_B, 1+l_B); | |
54 | dp->order = XMALLOC(1+l_order); strncpy(dp->order, ch_order, 1+l_order); | |
55 | dp->Gx = XMALLOC(1+l_Gx); strncpy(dp->Gx, ch_Gx, 1+l_Gx); | |
56 | dp->Gy = XMALLOC(1+l_Gy); strncpy(dp->Gy, ch_Gy, 1+l_Gy); | |
57 | ||
58 | return CRYPT_OK; | |
59 | } | |
60 | ||
61 | #endif |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
85 | 83 | } |
86 | 84 | |
87 | 85 | pubkeysize = ECC_BUF_SIZE; |
88 | if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) { | |
86 | if ((err = ecc_export_raw(pub_expt, &pubkeysize, PK_PUBLIC_COMPRESSED, &pubkey)) != CRYPT_OK) { | |
89 | 87 | ecc_free(&pubkey); |
90 | 88 | goto LBL_ERR; |
91 | 89 | } |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | #ifdef LTC_MECC | |
17 | ||
18 | /** | |
19 | Export an ECC key as a binary packet | |
20 | @param out [out] Destination for the key | |
21 | @param outlen [in/out] Max size and resulting size of the exported key | |
22 | @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) | |
23 | @param key The key to export | |
24 | @return CRYPT_OK if successful | |
25 | */ | |
26 | ||
27 | int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key) | |
28 | { | |
29 | int err; | |
30 | void *prime, *order, *a, *b, *gx, *gy; | |
31 | unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512]; | |
32 | unsigned long len_a, len_b, len_k, len_g, len_xy; | |
33 | unsigned long cofactor, one = 1; | |
34 | oid_st oid; | |
35 | ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4]; | |
36 | ||
37 | LTC_ARGCHK(out != NULL); | |
38 | LTC_ARGCHK(outlen != NULL); | |
39 | LTC_ARGCHK(key != NULL); | |
40 | ||
41 | if (key->type != PK_PRIVATE && type == PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; | |
42 | if (ltc_ecc_is_valid_idx(key->idx) == 0) return CRYPT_INVALID_ARG; | |
43 | ||
44 | if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err; | |
45 | ||
46 | if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) goto error; | |
47 | if ((err = mp_read_radix(order, key->dp->order, 16)) != CRYPT_OK) goto error; | |
48 | if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) goto error; | |
49 | if ((err = mp_read_radix(a, key->dp->A, 16)) != CRYPT_OK) goto error; | |
50 | if ((err = mp_read_radix(gx, key->dp->Gx, 16)) != CRYPT_OK) goto error; | |
51 | if ((err = mp_read_radix(gy, key->dp->Gy, 16)) != CRYPT_OK) goto error; | |
52 | ||
53 | /* curve param a */ | |
54 | len_a = mp_unsigned_bin_size(a); | |
55 | if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } | |
56 | if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) goto error; | |
57 | if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* XXX-TODO hack to handle case a == 0 */ | |
58 | ||
59 | /* curve param b */ | |
60 | len_b = mp_unsigned_bin_size(b); | |
61 | if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } | |
62 | if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) goto error; | |
63 | if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* XXX-TODO hack to handle case b == 0 */ | |
64 | ||
65 | /* base point - we export uncompressed form */ | |
66 | len_g = sizeof(bin_g); | |
67 | if ((err = ecc_export_point(bin_g, &len_g, gx, gy, key->dp->size, 0)) != CRYPT_OK) goto error; | |
68 | ||
69 | /* public key */ | |
70 | len_xy = sizeof(bin_xy); | |
71 | if ((err = ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp->size, 0)) != CRYPT_OK) goto error; | |
72 | ||
73 | /* co-factor */ | |
74 | cofactor = key->dp->cofactor; | |
75 | ||
76 | /* we support only prime-field EC */ | |
77 | if ((err = pk_get_oid(EC_PRIME_FIELD, &oid)) != CRYPT_OK) goto error; | |
78 | ||
79 | /* FieldID SEQUENCE */ | |
80 | LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID, oid.OIDlen); | |
81 | LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); | |
82 | ||
83 | /* Curve SEQUENCE */ | |
84 | LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a); | |
85 | LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b); | |
86 | ||
87 | /* ECParameters SEQUENCE */ | |
88 | LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL); | |
89 | LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); | |
90 | LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL); | |
91 | LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g); | |
92 | LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); | |
93 | LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); | |
94 | ||
95 | if (type == PK_PRIVATE) { | |
96 | /* private key format: http://tools.ietf.org/html/rfc5915 | |
97 | ||
98 | ECPrivateKey ::= SEQUENCE { # SEQUENCE | |
99 | version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), # INTEGER :01 | |
100 | privateKey OCTET STRING, # OCTET STRING | |
101 | [0] ECParameters ::= SEQUENCE { # SEQUENCE | |
102 | version INTEGER { ecpVer1(1) } (ecpVer1), # INTEGER :01 | |
103 | FieldID ::= SEQUENCE { # SEQUENCE | |
104 | fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field | |
105 | parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER | |
106 | } | |
107 | Curve ::= SEQUENCE { # SEQUENCE | |
108 | a FieldElement ::= OCTET STRING # OCTET STRING | |
109 | b FieldElement ::= OCTET STRING # OCTET STRING | |
110 | seed BIT STRING OPTIONAL | |
111 | } | |
112 | base ECPoint ::= OCTET STRING # OCTET STRING | |
113 | order INTEGER, # INTEGER | |
114 | cofactor INTEGER OPTIONAL # INTEGER | |
115 | } | |
116 | [1] publicKey # BIT STRING | |
117 | } | |
118 | */ | |
119 | ||
120 | /* private key */ | |
121 | len_k = mp_unsigned_bin_size(key->k); | |
122 | if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } | |
123 | if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) goto error; | |
124 | ||
125 | LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL); | |
126 | LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k); | |
127 | LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); | |
128 | LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy); | |
129 | seq_priv[2].tag = 0xA0; | |
130 | seq_priv[3].tag = 0xA1; | |
131 | ||
132 | err = der_encode_sequence(seq_priv, 4, out, outlen); | |
133 | } | |
134 | else { | |
135 | /* public key format: http://tools.ietf.org/html/rfc5480 | |
136 | ||
137 | SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE | |
138 | AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE | |
139 | algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey | |
140 | ECParameters ::= SEQUENCE { # SEQUENCE | |
141 | version INTEGER { ecpVer1(1) } (ecpVer1), # INTEGER :01 | |
142 | FieldID ::= SEQUENCE { # SEQUENCE | |
143 | fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field | |
144 | parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER | |
145 | } | |
146 | Curve ::= SEQUENCE { # SEQUENCE | |
147 | a FieldElement ::= OCTET STRING # OCTET STRING | |
148 | b FieldElement ::= OCTET STRING # OCTET STRING | |
149 | seed BIT STRING OPTIONAL | |
150 | } | |
151 | base ECPoint ::= OCTET STRING # OCTET STRING | |
152 | order INTEGER, # INTEGER | |
153 | cofactor INTEGER OPTIONAL # INTEGER | |
154 | } | |
155 | } | |
156 | subjectPublicKey BIT STRING # BIT STRING | |
157 | } | |
158 | */ | |
159 | ||
160 | err = der_encode_subject_public_key_info( out, outlen, | |
161 | PKA_EC, bin_xy, len_xy, | |
162 | LTC_ASN1_SEQUENCE, seq_ecparams, 6 ); | |
163 | } | |
164 | ||
165 | error: | |
166 | mp_clear_multi(prime, order, a, b, gx, gy, NULL); | |
167 | return err; | |
168 | } | |
169 | ||
170 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | #ifdef LTC_MECC | |
17 | ||
18 | int ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed) | |
19 | { | |
20 | int err; | |
21 | unsigned char buf[ECC_BUF_SIZE]; | |
22 | unsigned long xsize, ysize; | |
23 | ||
24 | if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW; | |
25 | if ((xsize = mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW; | |
26 | if ((ysize = mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW; | |
27 | ||
28 | if(compressed) { | |
29 | if (*outlen < (1 + size)) { | |
30 | *outlen = 1 + size; | |
31 | return CRYPT_BUFFER_OVERFLOW; | |
32 | } | |
33 | /* store first byte */ | |
34 | out[0] = mp_isodd(y) ? 0x03 : 0x02; | |
35 | /* pad and store x */ | |
36 | zeromem(buf, sizeof(buf)); | |
37 | if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; | |
38 | XMEMCPY(out+1, buf, size); | |
39 | /* adjust outlen */ | |
40 | *outlen = 1 + size; | |
41 | } | |
42 | else { | |
43 | if (*outlen < (1 + 2*size)) { | |
44 | *outlen = 1 + 2*size; | |
45 | return CRYPT_BUFFER_OVERFLOW; | |
46 | } | |
47 | /* store byte 0x04 */ | |
48 | out[0] = 0x04; | |
49 | /* pad and store x */ | |
50 | zeromem(buf, sizeof(buf)); | |
51 | if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; | |
52 | XMEMCPY(out+1, buf, size); | |
53 | /* pad and store y */ | |
54 | zeromem(buf, sizeof(buf)); | |
55 | if ((err = mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err; | |
56 | XMEMCPY(out+1+size, buf, size); | |
57 | /* adjust outlen */ | |
58 | *outlen = 1 + 2*size; | |
59 | } | |
60 | return CRYPT_OK; | |
61 | } | |
62 | ||
63 | /** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes) | |
64 | @param out [out] destination of export | |
65 | @param outlen [in/out] Length of destination and final output size | |
66 | @param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC_COMPRESSED | |
67 | @param key Key to export | |
68 | Return CRYPT_OK on success | |
69 | */ | |
70 | ||
71 | int ecc_export_raw(unsigned char *out, unsigned long *outlen, int type, ecc_key *key) | |
72 | { | |
73 | unsigned long size, ksize; | |
74 | int err; | |
75 | ||
76 | LTC_ARGCHK(key != NULL); | |
77 | LTC_ARGCHK(out != NULL); | |
78 | LTC_ARGCHK(outlen != NULL); | |
79 | ||
80 | if (ltc_ecc_is_valid_idx(key->idx) == 0) { | |
81 | return CRYPT_INVALID_ARG; | |
82 | } | |
83 | size = key->dp->size; | |
84 | ||
85 | if (type == PK_PUBLIC_COMPRESSED) { | |
86 | if ((err = ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, 1)) != CRYPT_OK) return err; | |
87 | } | |
88 | else if (type == PK_PUBLIC) { | |
89 | if ((err = ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, 0)) != CRYPT_OK) return err; | |
90 | } | |
91 | else if (type == PK_PRIVATE) { | |
92 | if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; | |
93 | *outlen = size; | |
94 | if (size > *outlen) return CRYPT_BUFFER_OVERFLOW; | |
95 | if ((ksize = mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW; | |
96 | /* pad and store k */ | |
97 | if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err; | |
98 | zeromem(out, size - ksize); | |
99 | } | |
100 | else { | |
101 | return CRYPT_INVALID_ARG; | |
102 | } | |
103 | ||
104 | return CRYPT_OK; | |
105 | } | |
106 | ||
107 | #endif |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
21 | 19 | */ |
22 | 20 | |
23 | 21 | #ifdef LTC_MECC |
24 | ||
25 | static int is_point(ecc_key *key) | |
26 | { | |
27 | void *prime, *b, *t1, *t2; | |
28 | int err; | |
29 | ||
30 | if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { | |
31 | return err; | |
32 | } | |
33 | ||
34 | /* load prime and b */ | |
35 | if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } | |
36 | if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } | |
37 | ||
38 | /* compute y^2 */ | |
39 | if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } | |
40 | ||
41 | /* compute x^3 */ | |
42 | if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } | |
43 | if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } | |
44 | if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } | |
45 | ||
46 | /* compute y^2 - x^3 */ | |
47 | if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } | |
48 | ||
49 | /* compute y^2 - x^3 + 3x */ | |
50 | if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
51 | if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
52 | if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
53 | if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
54 | while (mp_cmp_d(t1, 0) == LTC_MP_LT) { | |
55 | if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
56 | } | |
57 | while (mp_cmp(t1, prime) != LTC_MP_LT) { | |
58 | if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
59 | } | |
60 | ||
61 | /* compare to b */ | |
62 | if (mp_cmp(t1, b) != LTC_MP_EQ) { | |
63 | err = CRYPT_INVALID_PACKET; | |
64 | } else { | |
65 | err = CRYPT_OK; | |
66 | } | |
67 | ||
68 | error: | |
69 | mp_clear_multi(prime, b, t1, t2, NULL); | |
70 | return err; | |
71 | } | |
72 | 22 | |
73 | 23 | /** |
74 | 24 | Import an ECC key from a binary packet |
139 | 89 | } |
140 | 90 | |
141 | 91 | if (dp == NULL) { |
92 | /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid), | |
93 | * which might be ambiguous (there can more than one curve for given keysize). | |
94 | * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file. | |
95 | */ | |
142 | 96 | /* find the idx */ |
143 | 97 | for (key->idx = 0; ltc_ecc_sets[key->idx].size && (unsigned long)ltc_ecc_sets[key->idx].size != key_size; ++key->idx); |
144 | 98 | if (ltc_ecc_sets[key->idx].size == 0) { |
154 | 108 | if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; } |
155 | 109 | |
156 | 110 | /* is it a point on the curve? */ |
157 | if ((err = is_point(key)) != CRYPT_OK) { | |
111 | if ((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { | |
158 | 112 | goto done; |
159 | 113 | } |
160 | 114 |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org | |
9 | */ | |
10 | ||
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | * | |
13 | */ | |
14 | ||
15 | #include "tomcrypt.h" | |
16 | ||
17 | #ifdef LTC_MECC | |
18 | ||
19 | static int _populate_dp_from_oid(unsigned long *oid, unsigned long size, ltc_ecc_set_type *dp) | |
20 | { | |
21 | int i; | |
22 | unsigned long len; | |
23 | ||
24 | for(i=0; ltc_ecc_sets[i].size != 0; i++) { | |
25 | if ((size == ltc_ecc_sets[i].oid.OIDlen) && | |
26 | (XMEM_NEQ(oid, ltc_ecc_sets[i].oid.OID, sizeof(unsigned long) * ltc_ecc_sets[i].oid.OIDlen) == 0)) { | |
27 | break; | |
28 | } | |
29 | } | |
30 | if (ltc_ecc_sets[i].size == 0) return CRYPT_INVALID_ARG; /* not found */ | |
31 | ||
32 | /* a */ | |
33 | len = (unsigned long)strlen(ltc_ecc_sets[i].A); | |
34 | if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1; | |
35 | strncpy(dp->A, ltc_ecc_sets[i].A, 1+len); | |
36 | /* b */ | |
37 | len = (unsigned long)strlen(ltc_ecc_sets[i].B); | |
38 | if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2; | |
39 | strncpy(dp->B, ltc_ecc_sets[i].B, 1+len); | |
40 | /* order */ | |
41 | len = (unsigned long)strlen(ltc_ecc_sets[i].order); | |
42 | if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3; | |
43 | strncpy(dp->order, ltc_ecc_sets[i].order, 1+len); | |
44 | /* prime */ | |
45 | len = (unsigned long)strlen(ltc_ecc_sets[i].prime); | |
46 | if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4; | |
47 | strncpy(dp->prime, ltc_ecc_sets[i].prime, 1+len); | |
48 | /* gx */ | |
49 | len = (unsigned long)strlen(ltc_ecc_sets[i].Gx); | |
50 | if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5; | |
51 | strncpy(dp->Gx, ltc_ecc_sets[i].Gx, 1+len); | |
52 | /* gy */ | |
53 | len = (unsigned long)strlen(ltc_ecc_sets[i].Gy); | |
54 | if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6; | |
55 | strncpy(dp->Gy, ltc_ecc_sets[i].Gy, 1+len); | |
56 | /* cofactor & size */ | |
57 | dp->cofactor = ltc_ecc_sets[i].cofactor; | |
58 | dp->size = ltc_ecc_sets[i].size; | |
59 | /* name */ | |
60 | len = (unsigned long)strlen(ltc_ecc_sets[i].name); | |
61 | if ((dp->name = XMALLOC(1+len)) == NULL) goto cleanup6; | |
62 | strncpy(dp->name, ltc_ecc_sets[i].name, 1+len); | |
63 | /* done - success */ | |
64 | return CRYPT_OK; | |
65 | ||
66 | cleanup7: | |
67 | XFREE(dp->Gy); | |
68 | cleanup6: | |
69 | XFREE(dp->Gx); | |
70 | cleanup5: | |
71 | XFREE(dp->prime); | |
72 | cleanup4: | |
73 | XFREE(dp->order); | |
74 | cleanup3: | |
75 | XFREE(dp->B); | |
76 | cleanup2: | |
77 | XFREE(dp->A); | |
78 | cleanup1: | |
79 | return CRYPT_MEM; | |
80 | } | |
81 | ||
82 | static int _populate_dp(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ltc_ecc_set_type *dp) | |
83 | { | |
84 | unsigned char buf[ECC_BUF_SIZE]; | |
85 | unsigned long len; | |
86 | ||
87 | /* a */ | |
88 | mp_tohex(a, (char *)buf); | |
89 | len = (unsigned long)strlen((char *)buf); | |
90 | if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1; | |
91 | strncpy(dp->A, (char*)buf, 1+len); | |
92 | /* b */ | |
93 | mp_tohex(b, (char *)buf); | |
94 | len = (unsigned long)strlen((char *)buf); | |
95 | if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2; | |
96 | strncpy(dp->B, (char*)buf, 1+len); | |
97 | /* order */ | |
98 | mp_tohex(order, (char *)buf); | |
99 | len = (unsigned long)strlen((char *)buf); | |
100 | if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3; | |
101 | strncpy(dp->order, (char*)buf, 1+len); | |
102 | /* prime */ | |
103 | mp_tohex(prime, (char *)buf); | |
104 | len = (unsigned long)strlen((char *)buf); | |
105 | if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4; | |
106 | strncpy(dp->prime, (char*)buf, 1+len); | |
107 | /* gx */ | |
108 | mp_tohex(gx, (char *)buf); | |
109 | len = (unsigned long)strlen((char *)buf); | |
110 | if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5; | |
111 | strncpy(dp->Gx, (char*)buf, 1+len); | |
112 | /* gy */ | |
113 | mp_tohex(gy, (char *)buf); | |
114 | len = (unsigned long)strlen((char *)buf); | |
115 | if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6; | |
116 | strncpy(dp->Gy, (char*)buf, 1+len); | |
117 | /* cofactor & size */ | |
118 | dp->cofactor = cofactor; | |
119 | dp->size = mp_unsigned_bin_size(prime); | |
120 | /* name */ | |
121 | if ((dp->name = XMALLOC(7)) == NULL) goto cleanup7; | |
122 | strcpy(dp->name, "custom"); /* XXX-TODO check this */ | |
123 | /* done - success */ | |
124 | return CRYPT_OK; | |
125 | ||
126 | /* XFREE(dp->name); **** warning: statement not reached *** */ | |
127 | cleanup7: | |
128 | XFREE(dp->Gy); | |
129 | cleanup6: | |
130 | XFREE(dp->Gx); | |
131 | cleanup5: | |
132 | XFREE(dp->prime); | |
133 | cleanup4: | |
134 | XFREE(dp->order); | |
135 | cleanup3: | |
136 | XFREE(dp->B); | |
137 | cleanup2: | |
138 | XFREE(dp->A); | |
139 | cleanup1: | |
140 | return CRYPT_MEM; | |
141 | } | |
142 | ||
143 | int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp) | |
144 | { | |
145 | void *prime, *order, *a, *b, *gx, *gy; | |
146 | ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], seq_pub[2]; | |
147 | unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE], bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; | |
148 | unsigned long len_a, len_b, len_k, len_g, len_xy, len_oid; | |
149 | unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16], curveoid[16]; | |
150 | /*oid_st oid;*/ | |
151 | int err; | |
152 | ||
153 | if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err; | |
154 | ||
155 | /* ### 1. try to load public key - no curve parameters just curve OID */ | |
156 | ||
157 | len_xy = sizeof(bin_xy); | |
158 | err = der_decode_subject_public_key_info_ex(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL, &len_oid); | |
159 | if (err == CRYPT_OK) { | |
160 | /* load curve parameters for given curve OID */ | |
161 | if ((err = _populate_dp_from_oid(curveoid, len_oid, dp)) != CRYPT_OK) { goto error; } | |
162 | /* load public key */ | |
163 | if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; } | |
164 | goto success; | |
165 | } | |
166 | ||
167 | /* ### 2. try to load public key - curve parameters included */ | |
168 | ||
169 | /* ECParameters SEQUENCE */ | |
170 | LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); | |
171 | LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); | |
172 | LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); | |
173 | LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1); | |
174 | LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); | |
175 | LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); | |
176 | seq_ecparams[5].optional = 1; | |
177 | /* FieldID SEQUENCE */ | |
178 | LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); | |
179 | LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); | |
180 | /* Curve SEQUENCE */ | |
181 | LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE); | |
182 | LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE); | |
183 | LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128); | |
184 | seq_curve[2].optional = 1; | |
185 | /* try to load public key */ | |
186 | len_xy = sizeof(bin_xy); | |
187 | err = der_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, 6); | |
188 | if (err == CRYPT_OK) { | |
189 | len_a = seq_curve[0].size; | |
190 | len_b = seq_curve[1].size; | |
191 | len_g = seq_ecparams[3].size; | |
192 | /* create bignums */ | |
193 | if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } | |
194 | if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } | |
195 | if ((err = ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } | |
196 | /* load curve parameters */ | |
197 | if ((err = _populate_dp(a, b, prime, order, gx, gy, cofactor, dp)) != CRYPT_OK) { goto error; } | |
198 | /* load public key */ | |
199 | if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; } | |
200 | goto success; | |
201 | } | |
202 | ||
203 | /* ### 3. try to load private key - no curve parameters just curve OID */ | |
204 | ||
205 | /* ECPrivateKey SEQUENCE */ | |
206 | LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); | |
207 | LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE); | |
208 | LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL); | |
209 | LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2)); | |
210 | seq_priv[2].tag = 0xA0; /* context specific 0 */ | |
211 | seq_priv[3].tag = 0xA1; /* context specific 1 */ | |
212 | /* try to load private key */ | |
213 | err = der_decode_sequence(in, inlen, seq_priv, 4); | |
214 | if (err == CRYPT_OK) { | |
215 | /* load curve parameters for given curve OID */ | |
216 | if ((err = _populate_dp_from_oid(curveoid, seq_priv[2].size, dp)) != CRYPT_OK) { goto error; } | |
217 | /* load private+public key */ | |
218 | if ((err = ecc_import_raw(bin_k, seq_priv[1].size, key, dp)) != CRYPT_OK) { goto error; } | |
219 | goto success; | |
220 | } | |
221 | ||
222 | /* ### 4. try to load private key - curve parameters included */ | |
223 | ||
224 | /* ECPrivateKey SEQUENCE */ | |
225 | LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); | |
226 | LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE); | |
227 | LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); | |
228 | LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2)); | |
229 | seq_priv[2].tag = 0xA0; /* context specific 0 */ | |
230 | seq_priv[3].tag = 0xA1; /* context specific 1 */ | |
231 | /* ECParameters SEQUENCE */ | |
232 | LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); | |
233 | LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); | |
234 | LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); | |
235 | LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1); | |
236 | LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); | |
237 | LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); | |
238 | seq_ecparams[5].optional = 1; | |
239 | /* FieldID SEQUENCE */ | |
240 | LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); | |
241 | LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); | |
242 | /* Curve SEQUENCE */ | |
243 | LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE); | |
244 | LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE); | |
245 | LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128); | |
246 | seq_curve[2].optional = 1; | |
247 | /* try to load private key */ | |
248 | err = der_decode_sequence(in, inlen, seq_priv, 4); | |
249 | if (err == CRYPT_OK) { | |
250 | len_k = seq_priv[1].size; | |
251 | len_xy = seq_priv[3].size; | |
252 | len_a = seq_curve[0].size; | |
253 | len_b = seq_curve[1].size; | |
254 | len_g = seq_ecparams[3].size; | |
255 | /* create bignums */ | |
256 | if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } | |
257 | if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } | |
258 | if ((err = ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } | |
259 | /* load curve parameters */ | |
260 | if ((err = _populate_dp(a, b, prime, order, gx, gy, cofactor, dp)) != CRYPT_OK) { goto error; } | |
261 | /* load private+public key */ | |
262 | if ((err = ecc_import_raw(bin_k, len_k, key, dp)) != CRYPT_OK) { goto error; } | |
263 | goto success; | |
264 | } | |
265 | ||
266 | /* ### 5. backward compatibility - try to load old-DER format */ | |
267 | if ((err = ecc_import(in, inlen, key)) != CRYPT_OK) { goto error; } | |
268 | ||
269 | success: | |
270 | err = CRYPT_OK; | |
271 | error: | |
272 | mp_clear_multi(prime, order, a, b, gx, gy, NULL); | |
273 | return err; | |
274 | } | |
275 | ||
276 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | #ifdef LTC_MECC | |
17 | ||
18 | int ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y) | |
19 | { | |
20 | int err; | |
21 | unsigned long size; | |
22 | void *t1, *t2; | |
23 | ||
24 | /* init key + temporary numbers */ | |
25 | if (mp_init_multi(&t1, &t2, NULL) != CRYPT_OK) { | |
26 | return CRYPT_MEM; | |
27 | } | |
28 | ||
29 | size = mp_unsigned_bin_size(prime); | |
30 | ||
31 | if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) { | |
32 | /* read uncompressed point */ | |
33 | /* load x */ | |
34 | if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { | |
35 | goto cleanup; | |
36 | } | |
37 | /* load y */ | |
38 | if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { | |
39 | goto cleanup; | |
40 | } | |
41 | } | |
42 | else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size) { | |
43 | /* read compressed point */ | |
44 | /* load x */ | |
45 | if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { | |
46 | goto cleanup; | |
47 | } | |
48 | /* compute x^3 */ | |
49 | if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; } | |
50 | if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; } | |
51 | /* compute x^3 + a*x */ | |
52 | if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; } | |
53 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } | |
54 | /* compute x^3 + a*x + b */ | |
55 | if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } | |
56 | /* compute sqrt(x^3 + a*x + b) */ | |
57 | if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } | |
58 | /* adjust y */ | |
59 | if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) { | |
60 | if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; } | |
61 | } | |
62 | else { | |
63 | if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; } | |
64 | } | |
65 | } | |
66 | else { | |
67 | err = CRYPT_INVALID_PACKET; | |
68 | goto cleanup; | |
69 | } | |
70 | ||
71 | err = CRYPT_OK; | |
72 | cleanup: | |
73 | mp_clear_multi(t1, t2, NULL); | |
74 | return err; | |
75 | } | |
76 | ||
77 | /** Import raw public or private key (public keys = ANSI X9.63 compressed or uncompressed; private keys = raw bytes) | |
78 | @param in The input data to read | |
79 | @param inlen The length of the input data | |
80 | @param key [out] destination to store imported key | |
81 | @param dp Curve parameters | |
82 | Return CRYPT_OK on success | |
83 | */ | |
84 | ||
85 | int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp) | |
86 | { | |
87 | int err, type = -1; | |
88 | unsigned long size = 0; | |
89 | void *prime, *a, *b; | |
90 | ecc_point *base; | |
91 | ||
92 | LTC_ARGCHK(in != NULL); | |
93 | LTC_ARGCHK(key != NULL); | |
94 | LTC_ARGCHK(dp != NULL); | |
95 | ||
96 | /* init key + temporary numbers */ | |
97 | if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &a, &b, NULL) != CRYPT_OK) { | |
98 | return CRYPT_MEM; | |
99 | } | |
100 | ||
101 | if (inlen == (unsigned long)dp->size) { | |
102 | /* read PRIVATE key */ | |
103 | type = PK_PRIVATE; | |
104 | size = inlen; | |
105 | /* load private k */ | |
106 | if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, size)) != CRYPT_OK) { | |
107 | goto cleanup; | |
108 | } | |
109 | if (mp_iszero(key->k)) { | |
110 | err = CRYPT_INVALID_PACKET; | |
111 | goto cleanup; | |
112 | } | |
113 | /* init base point */ | |
114 | if ((base = ltc_ecc_new_point()) == NULL) { | |
115 | err = CRYPT_MEM; | |
116 | goto cleanup; | |
117 | } | |
118 | /* load prime + base point */ | |
119 | if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; } | |
120 | if ((err = mp_read_radix(base->x, dp->Gx, 16)) != CRYPT_OK) { goto cleanup; } | |
121 | if ((err = mp_read_radix(base->y, dp->Gy, 16)) != CRYPT_OK) { goto cleanup; } | |
122 | if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto cleanup; } | |
123 | /* make the public key */ | |
124 | if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; } | |
125 | if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { | |
126 | goto cleanup; | |
127 | } | |
128 | /* cleanup */ | |
129 | ltc_ecc_del_point(base); | |
130 | } | |
131 | else { | |
132 | /* read PUBLIC key */ | |
133 | type = PK_PUBLIC; | |
134 | /* load prime + A + B */ | |
135 | if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; } | |
136 | if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) { goto cleanup; } | |
137 | if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; } | |
138 | err = ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y); | |
139 | if (err != CRYPT_OK) { goto cleanup; } | |
140 | if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto cleanup; } | |
141 | } | |
142 | ||
143 | if ((err = ltc_ecc_is_point(dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { | |
144 | err = CRYPT_INVALID_PACKET; | |
145 | goto cleanup; | |
146 | } | |
147 | ||
148 | key->type = type; | |
149 | key->idx = -1; | |
150 | key->dp = dp; | |
151 | ||
152 | /* we're done */ | |
153 | mp_clear_multi(prime, a, b, NULL); | |
154 | return CRYPT_OK; | |
155 | cleanup: | |
156 | mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, prime, a, b, NULL); | |
157 | return err; | |
158 | } | |
159 | ||
160 | #endif |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
32 | 30 | */ |
33 | 31 | int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) |
34 | 32 | { |
33 | /* BEWARE: Here we are looking up the curve params by keysize (neither curve name nor curve oid), | |
34 | * which might be ambiguous (there can more than one curve for given keysize). | |
35 | * Thus the chosen curve depends on order of items in ltc_ecc_sets[] - see ecc.c file. | |
36 | */ | |
35 | 37 | int x, err; |
36 | 38 | |
37 | 39 | /* find key size */ |
50 | 52 | { |
51 | 53 | int err; |
52 | 54 | ecc_point *base; |
53 | void *prime, *order; | |
55 | void *prime, *order, *a; | |
54 | 56 | unsigned char *buf; |
55 | int keysize; | |
57 | int keysize, orderbits; | |
56 | 58 | |
57 | 59 | LTC_ARGCHK(key != NULL); |
58 | 60 | LTC_ARGCHK(ltc_mp.name != NULL); |
81 | 83 | } |
82 | 84 | |
83 | 85 | /* setup the key variables */ |
84 | if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, NULL)) != CRYPT_OK) { | |
86 | if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, &a, NULL)) != CRYPT_OK) { | |
85 | 87 | goto ERR_BUF; |
86 | 88 | } |
87 | 89 | base = ltc_ecc_new_point(); |
98 | 100 | if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto errkey; } |
99 | 101 | if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) { goto errkey; } |
100 | 102 | |
101 | /* the key should be smaller than the order of base point */ | |
102 | if (mp_cmp(key->k, order) != LTC_MP_LT) { | |
103 | if((err = mp_mod(key->k, order, key->k)) != CRYPT_OK) { goto errkey; } | |
104 | } | |
103 | /* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates): | |
104 | * the generated private key k should be the range [1, order–1] | |
105 | * a/ N = bitlen(order) | |
106 | * b/ generate N random bits and convert them into big integer k | |
107 | * c/ if k not in [1, order-1] go to b/ | |
108 | * e/ Q = k*G | |
109 | */ | |
110 | orderbits = mp_count_bits(order); | |
111 | do { | |
112 | if ((err = rand_bn_bits(key->k, orderbits, prng, wprng)) != CRYPT_OK) { goto errkey; } | |
113 | } while (mp_iszero(key->k) || mp_cmp(key->k, order) != LTC_MP_LT); | |
114 | ||
105 | 115 | /* make the public key */ |
106 | if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK) { goto errkey; } | |
116 | if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto errkey; } | |
117 | if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto errkey; } | |
107 | 118 | key->type = PK_PRIVATE; |
108 | 119 | |
109 | 120 | /* free up ram */ |
113 | 124 | mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); |
114 | 125 | cleanup: |
115 | 126 | ltc_ecc_del_point(base); |
116 | mp_clear_multi(prime, order, NULL); | |
127 | mp_clear_multi(prime, order, a, NULL); | |
117 | 128 | ERR_BUF: |
118 | 129 | #ifdef LTC_CLEAN_STACK |
119 | 130 | zeromem(buf, ECC_MAXSIZE); |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
35 | 33 | { |
36 | 34 | unsigned long x; |
37 | 35 | ecc_point *result; |
38 | void *prime; | |
36 | void *prime, *a; | |
39 | 37 | int err; |
40 | 38 | |
41 | 39 | LTC_ARGCHK(private_key != NULL); |
62 | 60 | return CRYPT_MEM; |
63 | 61 | } |
64 | 62 | |
65 | if ((err = mp_init(&prime)) != CRYPT_OK) { | |
63 | if ((err = mp_init_multi(&prime, &a, NULL)) != CRYPT_OK) { | |
66 | 64 | ltc_ecc_del_point(result); |
67 | 65 | return err; |
68 | 66 | } |
69 | 67 | |
70 | 68 | if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) { goto done; } |
71 | if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK) { goto done; } | |
69 | if ((err = mp_read_radix(a, (char *)private_key->dp->A, 16)) != CRYPT_OK) { goto done; } | |
70 | if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; } | |
72 | 71 | |
73 | 72 | x = (unsigned long)mp_unsigned_bin_size(prime); |
74 | 73 | if (*outlen < x) { |
82 | 81 | err = CRYPT_OK; |
83 | 82 | *outlen = x; |
84 | 83 | done: |
85 | mp_clear(prime); | |
84 | mp_clear_multi(prime, a, NULL); | |
86 | 85 | ltc_ecc_del_point(result); |
87 | 86 | return err; |
88 | 87 | } |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
40 | 38 | ecc_key pubkey; |
41 | 39 | void *r, *s, *e, *p; |
42 | 40 | int err; |
41 | unsigned long pbits, pbytes, i, shift_right; | |
42 | unsigned char ch, buf[MAXBLOCKSIZE]; | |
43 | 43 | |
44 | 44 | LTC_ARGCHK(in != NULL); |
45 | 45 | LTC_ARGCHK(out != NULL); |
60 | 60 | return err; |
61 | 61 | } |
62 | 62 | |
63 | /* get the hash and load it as a bignum into 'e' */ | |
64 | 63 | /* init the bignums */ |
65 | 64 | if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) { |
66 | 65 | return err; |
67 | 66 | } |
68 | 67 | if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; } |
69 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto errnokey; } | |
68 | ||
69 | /* get the hash and load it as a bignum into 'e' */ | |
70 | pbits = mp_count_bits(p); | |
71 | pbytes = (pbits+7) >> 3; | |
72 | if (pbits > inlen*8) { | |
73 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } | |
74 | } | |
75 | else if (pbits % 8 == 0) { | |
76 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } | |
77 | } | |
78 | else { | |
79 | shift_right = 8 - pbits % 8; | |
80 | for (i=0, ch=0; i<pbytes; i++) { | |
81 | buf[i] = ch; | |
82 | ch = (in[i] << (8-shift_right)); | |
83 | buf[i] = buf[i] ^ (in[i] >> shift_right); | |
84 | } | |
85 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } | |
86 | } | |
70 | 87 | |
71 | 88 | /* make up a key and export the public copy */ |
72 | 89 | for (;;) { |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
47 | 45 | int *stat, ecc_key *key) |
48 | 46 | { |
49 | 47 | ecc_point *mG, *mQ; |
50 | void *r, *s, *v, *w, *u1, *u2, *e, *p, *m; | |
48 | void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a; | |
51 | 49 | void *mp; |
52 | 50 | int err; |
51 | unsigned long pbits, pbytes, i, shift_right; | |
52 | unsigned char ch, buf[MAXBLOCKSIZE]; | |
53 | 53 | |
54 | 54 | LTC_ARGCHK(sig != NULL); |
55 | 55 | LTC_ARGCHK(hash != NULL); |
66 | 66 | } |
67 | 67 | |
68 | 68 | /* allocate ints */ |
69 | if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) { | |
69 | if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, &a, NULL)) != CRYPT_OK) { | |
70 | 70 | return CRYPT_MEM; |
71 | 71 | } |
72 | 72 | |
92 | 92 | /* get the modulus */ |
93 | 93 | if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; } |
94 | 94 | |
95 | /* get the a */ | |
96 | if ((err = mp_read_radix(a, (char *)key->dp->A, 16)) != CRYPT_OK) { goto error; } | |
97 | ||
95 | 98 | /* check for zero */ |
96 | 99 | if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { |
97 | 100 | err = CRYPT_INVALID_PACKET; |
98 | 101 | goto error; |
99 | 102 | } |
100 | 103 | |
101 | /* read hash */ | |
102 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK) { goto error; } | |
104 | /* read hash - truncate if needed */ | |
105 | pbits = mp_count_bits(p); | |
106 | pbytes = (pbits+7) >> 3; | |
107 | if (pbits > hashlen*8) { | |
108 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } | |
109 | } | |
110 | else if (pbits % 8 == 0) { | |
111 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } | |
112 | } | |
113 | else { | |
114 | shift_right = 8 - pbits % 8; | |
115 | for (i=0, ch=0; i<pbytes; i++) { | |
116 | buf[i] = ch; | |
117 | ch = (hash[i] << (8-shift_right)); | |
118 | buf[i] = buf[i] ^ (hash[i] >> shift_right); | |
119 | } | |
120 | if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } | |
121 | } | |
103 | 122 | |
104 | 123 | /* w = s^-1 mod n */ |
105 | 124 | if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } |
121 | 140 | |
122 | 141 | /* compute u1*mG + u2*mQ = mG */ |
123 | 142 | if (ltc_mp.ecc_mul2add == NULL) { |
124 | if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK) { goto error; } | |
125 | if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK) { goto error; } | |
126 | ||
143 | if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } | |
144 | if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } | |
145 | ||
127 | 146 | /* find the montgomery mp */ |
128 | 147 | if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } |
129 | 148 | |
130 | 149 | /* add them */ |
131 | if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK) { goto error; } | |
132 | ||
150 | if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, a, m, mp)) != CRYPT_OK) { goto error; } | |
151 | ||
133 | 152 | /* reduce */ |
134 | 153 | if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; } |
135 | 154 | } else { |
136 | 155 | /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ |
137 | if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK) { goto error; } | |
156 | if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, a, m)) != CRYPT_OK) { goto error; } | |
138 | 157 | } |
139 | 158 | |
140 | 159 | /* v = X_x1 mod n */ |
150 | 169 | error: |
151 | 170 | ltc_ecc_del_point(mG); |
152 | 171 | ltc_ecc_del_point(mQ); |
153 | mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL); | |
154 | if (mp != NULL) { | |
172 | mp_clear_multi(r, s, v, w, u1, u2, p, e, m, a, NULL); | |
173 | if (mp != NULL) { | |
155 | 174 | mp_montgomery_free(mp); |
156 | 175 | } |
157 | 176 | return err; |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "tomcrypt.h" | |
15 | ||
16 | /* origin of this code - OLPC */ | |
17 | ||
18 | #ifdef LTC_MECC | |
19 | ||
20 | /** | |
21 | Verify a key according to ANSI spec | |
22 | @param key The key to validate | |
23 | @return CRYPT_OK if successful | |
24 | */ | |
25 | ||
26 | int ecc_verify_key(ecc_key *key) | |
27 | { | |
28 | int err; | |
29 | void *prime = NULL; | |
30 | void *order = NULL; | |
31 | void *a = NULL; | |
32 | ecc_point *test_output = NULL; | |
33 | test_output = malloc(sizeof(ecc_point)); | |
34 | ||
35 | /* XXX test_output->infinity = 0; */ | |
36 | if (mp_init_multi(&(test_output->x), &(test_output->y), &(test_output->z), &order, &prime, NULL) != CRYPT_OK) { | |
37 | return CRYPT_MEM; | |
38 | } | |
39 | ||
40 | /* Test 1: Are the x amd y points of the public key in the field? */ | |
41 | if((err = ltc_mp.read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error;} | |
42 | ||
43 | if(ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) { | |
44 | if( | |
45 | (ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) | |
46 | || (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) | |
47 | || (ltc_mp.compare_d(key->pubkey.x, 0) != LTC_MP_GT) | |
48 | || (ltc_mp.compare_d(key->pubkey.y, 0) != LTC_MP_GT) ) | |
49 | { | |
50 | err = CRYPT_INVALID_PACKET; | |
51 | goto error; | |
52 | } | |
53 | } | |
54 | ||
55 | /* Test 2: is the public key on the curve? */ | |
56 | if((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error;} | |
57 | ||
58 | /* Test 3: does nG = O? (n = order, 0 = point at infinity, G = public key) */ | |
59 | if((err = ltc_mp.read_radix(order, key->dp->order, 16)) != CRYPT_OK) { goto error;} | |
60 | if((err = ltc_mp.read_radix(a, key->dp->A, 16)) != CRYPT_OK) { goto error;} | |
61 | if((err = ltc_ecc_mulmod(order, &(key->pubkey), test_output, a, prime, 1)) != CRYPT_OK) { | |
62 | goto error; | |
63 | } | |
64 | ||
65 | /* XXX | |
66 | if(!test_output->infinity){ | |
67 | err = CRYPT_INVALID_PACKET; | |
68 | goto error; | |
69 | } | |
70 | */ | |
71 | ||
72 | err = CRYPT_OK; | |
73 | error: | |
74 | mp_clear_multi(prime, order, test_output->z, test_output->y, test_output->x, NULL); | |
75 | return err; | |
76 | } | |
77 | ||
78 | #endif |
0 | /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
1 | * | |
2 | * LibTomCrypt is a library that provides various cryptographic | |
3 | * algorithms in a highly modular and flexible manner. | |
4 | * | |
5 | * The library is free for all purposes without any express | |
6 | * guarantee it works. | |
7 | * | |
8 | */ | |
9 | ||
10 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
11 | */ | |
12 | ||
13 | #include "tomcrypt.h" | |
14 | ||
15 | #ifdef LTC_MECC | |
16 | ||
17 | /** Returns whether [x,y] is a point on curve defined by dp | |
18 | @param dp curve parameters | |
19 | @param x x point coordinate | |
20 | @param y y point coordinate | |
21 | @return CRYPT_OK if valid | |
22 | */ | |
23 | ||
24 | int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y) | |
25 | { | |
26 | void *prime, *a, *b, *t1, *t2; | |
27 | int err; | |
28 | ||
29 | if ((err = mp_init_multi(&prime, &a, &b, &t1, &t2, NULL)) != CRYPT_OK) { | |
30 | return err; | |
31 | } | |
32 | ||
33 | /* load prime, a and b */ | |
34 | if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) goto cleanup; | |
35 | if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) goto cleanup; | |
36 | if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) goto cleanup; | |
37 | ||
38 | /* compute y^2 */ | |
39 | if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; | |
40 | ||
41 | /* compute x^3 */ | |
42 | if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; | |
43 | if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; | |
44 | if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; | |
45 | ||
46 | /* compute y^2 - x^3 */ | |
47 | if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; | |
48 | ||
49 | /* compute y^2 - x^3 - a*x */ | |
50 | if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; | |
51 | if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; | |
52 | if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; | |
53 | ||
54 | /* adjust range (0, prime) */ | |
55 | while (mp_cmp_d(t1, 0) == LTC_MP_LT) { | |
56 | if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; | |
57 | } | |
58 | while (mp_cmp(t1, prime) != LTC_MP_LT) { | |
59 | if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; | |
60 | } | |
61 | ||
62 | /* compare to b */ | |
63 | if (mp_cmp(t1, b) != LTC_MP_EQ) { | |
64 | err = CRYPT_INVALID_PACKET; | |
65 | } else { | |
66 | err = CRYPT_OK; | |
67 | } | |
68 | ||
69 | cleanup: | |
70 | mp_clear_multi(prime, b, t1, t2, NULL); | |
71 | return err; | |
72 | } | |
73 | ||
74 | #endif |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
12 | * | |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | * | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
36 | 34 | int ltc_ecc_mul2add(ecc_point *A, void *kA, |
37 | 35 | ecc_point *B, void *kB, |
38 | 36 | ecc_point *C, |
37 | void *a, | |
39 | 38 | void *modulus) |
40 | 39 | { |
41 | 40 | ecc_point *precomp[16]; |
113 | 112 | if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; } |
114 | 113 | |
115 | 114 | /* precomp [i,0](A + B) table */ |
116 | if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
117 | if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
115 | if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
116 | if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
118 | 117 | |
119 | 118 | /* precomp [0,i](A + B) table */ |
120 | if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
121 | if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
119 | if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
120 | if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
122 | 121 | |
123 | 122 | /* precomp [i,j](A + B) table (i != 0, j != 0) */ |
124 | 123 | for (x = 1; x < 4; x++) { |
125 | 124 | for (y = 1; y < 4; y++) { |
126 | if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
125 | if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
127 | 126 | } |
128 | 127 | } |
129 | 128 | |
156 | 155 | /* double twice, only if this isn't the first */ |
157 | 156 | if (first == 0) { |
158 | 157 | /* double twice */ |
159 | if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
160 | if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
158 | if ((err = ltc_mp.ecc_ptdbl(C, C, a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
159 | if ((err = ltc_mp.ecc_ptdbl(C, C, a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
161 | 160 | } |
162 | 161 | |
163 | 162 | /* if not both zero */ |
170 | 169 | if ((err = mp_copy(precomp[nA + (nB<<2)]->z, C->z)) != CRYPT_OK) { goto ERR_MU; } |
171 | 170 | } else { |
172 | 171 | /* if not first, add from table */ |
173 | if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
172 | if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, a, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } | |
174 | 173 | } |
175 | 174 | } |
176 | 175 | } |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
12 | * | |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | * | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
35 | 33 | @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) |
36 | 34 | @return CRYPT_OK on success |
37 | 35 | */ |
38 | int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) | |
36 | int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) | |
39 | 37 | { |
40 | 38 | ecc_point *tG, *M[8]; |
41 | 39 | int i, j, err; |
94 | 92 | |
95 | 93 | /* calc the M tab, which holds kG for k==8..15 */ |
96 | 94 | /* M[0] == 8G */ |
97 | if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; } | |
98 | if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } | |
99 | if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; } | |
95 | if ((err = ltc_mp.ecc_ptdbl(tG, M[0], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
96 | if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
97 | if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
100 | 98 | |
101 | 99 | /* now find (8+k)G for k=1..7 */ |
102 | 100 | for (j = 9; j < 16; j++) { |
103 | if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; } | |
101 | if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
104 | 102 | } |
105 | 103 | |
106 | 104 | /* setup sliding window */ |
134 | 132 | |
135 | 133 | /* if the bit is zero and mode == 1 then we double */ |
136 | 134 | if (mode == 1 && i == 0) { |
137 | if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } | |
135 | if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { goto done; } | |
138 | 136 | continue; |
139 | 137 | } |
140 | 138 | |
155 | 153 | /* ok window is filled so double as required and add */ |
156 | 154 | /* double first */ |
157 | 155 | for (j = 0; j < WINSIZE; j++) { |
158 | if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } | |
156 | if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { goto done; } | |
159 | 157 | } |
160 | 158 | |
161 | 159 | /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ |
162 | if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; } | |
160 | if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, a, modulus, mp)) != CRYPT_OK) { goto done; } | |
163 | 161 | } |
164 | 162 | /* empty window and reset */ |
165 | 163 | bitcpy = bitbuf = 0; |
173 | 171 | for (j = 0; j < bitcpy; j++) { |
174 | 172 | /* only double if we have had at least one add first */ |
175 | 173 | if (first == 0) { |
176 | if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; } | |
174 | if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { goto done; } | |
177 | 175 | } |
178 | 176 | |
179 | 177 | bitbuf <<= 1; |
186 | 184 | first = 0; |
187 | 185 | } else { |
188 | 186 | /* then add */ |
189 | if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; } | |
187 | if ((err = ltc_mp.ecc_ptadd(R, tG, R, a, modulus, mp)) != CRYPT_OK) { goto done; } | |
190 | 188 | } |
191 | 189 | } |
192 | 190 | } |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
29 | 27 | @param k The scalar to multiply by |
30 | 28 | @param G The base point |
31 | 29 | @param R [out] Destination for kG |
30 | @param a ECC curve parameter a | |
32 | 31 | @param modulus The modulus of the field the ECC curve is in |
33 | 32 | @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) |
34 | 33 | @return CRYPT_OK on success |
35 | 34 | */ |
36 | int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map) | |
35 | int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) | |
37 | 36 | { |
38 | 37 | ecc_point *tG, *M[3]; |
39 | 38 | int i, j, err; |
90 | 89 | if ((err = mp_copy(tG->y, M[0]->y)) != CRYPT_OK) { goto done; } |
91 | 90 | if ((err = mp_copy(tG->z, M[0]->z)) != CRYPT_OK) { goto done; } |
92 | 91 | /* M[1] == 2G */ |
93 | if ((err = ltc_mp.ecc_ptdbl(tG, M[1], modulus, mp)) != CRYPT_OK) { goto done; } | |
92 | if ((err = ltc_mp.ecc_ptdbl(tG, M[1], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
94 | 93 | |
95 | 94 | /* setup sliding window */ |
96 | 95 | mode = 0; |
116 | 115 | |
117 | 116 | if (mode == 0 && i == 0) { |
118 | 117 | /* dummy operations */ |
119 | if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } | |
120 | if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } | |
118 | if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
119 | if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
121 | 120 | continue; |
122 | 121 | } |
123 | 122 | |
124 | 123 | if (mode == 0 && i == 1) { |
125 | 124 | mode = 1; |
126 | 125 | /* dummy operations */ |
127 | if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } | |
128 | if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; } | |
126 | if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
127 | if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
129 | 128 | continue; |
130 | 129 | } |
131 | 130 | |
132 | if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], modulus, mp)) != CRYPT_OK) { goto done; } | |
133 | if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], modulus, mp)) != CRYPT_OK) { goto done; } | |
131 | if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
132 | if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], a, modulus, mp)) != CRYPT_OK) { goto done; } | |
134 | 133 | } |
135 | 134 | |
136 | 135 | /* copy result out */ |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
17 | 15 | |
31 | 29 | @param mp The "b" value from montgomery_setup() |
32 | 30 | @return CRYPT_OK on success |
33 | 31 | */ |
34 | int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp) | |
32 | int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *a, void *modulus, void *mp) | |
35 | 33 | { |
36 | 34 | void *t1, *t2, *x, *y, *z; |
37 | 35 | int err; |
53 | 51 | (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) && |
54 | 52 | (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) { |
55 | 53 | mp_clear_multi(t1, t2, x, y, z, NULL); |
56 | return ltc_ecc_projective_dbl_point(P, R, modulus, mp); | |
54 | return ltc_ecc_projective_dbl_point(P, R, a, modulus, mp); | |
57 | 55 | } |
58 | 56 | |
59 | 57 | if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; } |
8 | 8 | * Tom St Denis, tomstdenis@gmail.com, http://libtom.org |
9 | 9 | */ |
10 | 10 | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
11 | /* Implements ECC over Z/pZ for curve y^2 = x^3 + a*x + b | |
12 | 12 | * |
13 | * All curves taken from NIST recommendation paper of July 1999 | |
14 | * Available at http://csrc.nist.gov/cryptval/dss.htm | |
15 | 13 | */ |
16 | 14 | #include "tomcrypt.h" |
15 | ||
16 | /* ### Point doubling in Jacobian coordinate system ### | |
17 | * | |
18 | * let us have a curve: y^2 = x^3 + a*x + b | |
19 | * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 | |
20 | * | |
21 | * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: | |
22 | * Xr = M^2 - 2*S | |
23 | * Yr = M * (S - Xr) - 8*T | |
24 | * Zr = 2 * Yp * Zp | |
25 | * | |
26 | * M = 3 * Xp^2 + a*Zp^4 | |
27 | * T = Yp^4 | |
28 | * S = 4 * Xp * Yp^2 | |
29 | * | |
30 | * SPECIAL CASE: when a == -3 we can compute M as | |
31 | * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) | |
32 | */ | |
17 | 33 | |
18 | 34 | /** |
19 | 35 | @file ltc_ecc_projective_dbl_point.c |
26 | 42 | Double an ECC point |
27 | 43 | @param P The point to double |
28 | 44 | @param R [out] The destination of the double |
45 | @param a ECC curve parameter a (if NULL we assume a == -3) | |
29 | 46 | @param modulus The modulus of the field the ECC curve is in |
30 | 47 | @param mp The "b" value from montgomery_setup() |
31 | 48 | @return CRYPT_OK on success |
32 | 49 | */ |
33 | int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp) | |
50 | int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *a, void *modulus, void *mp) | |
34 | 51 | { |
35 | 52 | void *t1, *t2; |
36 | 53 | int err; |
62 | 79 | if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; } |
63 | 80 | } |
64 | 81 | |
65 | /* T2 = X - T1 */ | |
66 | if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } | |
67 | if (mp_cmp_d(t2, 0) == LTC_MP_LT) { | |
68 | if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } | |
82 | if (a == NULL) { /* special case for a == -3 (slightly faster than general case) */ | |
83 | /* T2 = X - T1 */ | |
84 | if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } | |
85 | if (mp_cmp_d(t2, 0) == LTC_MP_LT) { | |
86 | if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } | |
87 | } | |
88 | /* T1 = X + T1 */ | |
89 | if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; } | |
90 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
91 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
92 | } | |
93 | /* T2 = T1 * T2 */ | |
94 | if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; } | |
95 | if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } | |
96 | /* T1 = 2T2 */ | |
97 | if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; } | |
98 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
99 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
100 | } | |
101 | /* T1 = T1 + T2 */ | |
102 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } | |
103 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
104 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
105 | } | |
69 | 106 | } |
70 | /* T1 = X + T1 */ | |
71 | if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; } | |
72 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
73 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
74 | } | |
75 | /* T2 = T1 * T2 */ | |
76 | if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; } | |
77 | if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } | |
78 | /* T1 = 2T2 */ | |
79 | if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; } | |
80 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
81 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
82 | } | |
83 | /* T1 = T1 + T2 */ | |
84 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } | |
85 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
86 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
107 | else { | |
108 | /* T2 = T1 * T1 */ | |
109 | if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } | |
110 | if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } | |
111 | /* T1 = T2 * a */ | |
112 | if ((err = mp_mulmod(t2, a, modulus, t1)) != CRYPT_OK) { goto done; } | |
113 | /* T2 = X * X */ | |
114 | if ((err = mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; } | |
115 | if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } | |
116 | /* T1 = T2 + T1 */ | |
117 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } | |
118 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
119 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
120 | } | |
121 | /* T1 = T2 + T1 */ | |
122 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } | |
123 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
124 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
125 | } | |
126 | /* T1 = T2 + T1 */ | |
127 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } | |
128 | if (mp_cmp(t1, modulus) != LTC_MP_LT) { | |
129 | if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } | |
130 | } | |
87 | 131 | } |
88 | 132 | |
89 | 133 | /* Y = 2Y */ |