zeroing extra files
Karel Miko
9 years ago
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->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_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 |
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 |
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(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ltc_ecc_set_type *dp) | |
20 | { | |
21 | unsigned char buf[ECC_BUF_SIZE]; | |
22 | unsigned long len; | |
23 | ||
24 | /* a */ | |
25 | mp_tohex(a, (char *)buf); | |
26 | len = (unsigned long)strlen((char *)buf); | |
27 | if ((dp->A = XMALLOC(1+len)) == NULL) goto cleanup1; | |
28 | strncpy(dp->A, (char*)buf, 1+len); | |
29 | /* b */ | |
30 | mp_tohex(b, (char *)buf); | |
31 | len = (unsigned long)strlen((char *)buf); | |
32 | if ((dp->B = XMALLOC(1+len)) == NULL) goto cleanup2; | |
33 | strncpy(dp->B, (char*)buf, 1+len); | |
34 | /* order */ | |
35 | mp_tohex(order, (char *)buf); | |
36 | len = (unsigned long)strlen((char *)buf); | |
37 | if ((dp->order = XMALLOC(1+len)) == NULL) goto cleanup3; | |
38 | strncpy(dp->order, (char*)buf, 1+len); | |
39 | /* prime */ | |
40 | mp_tohex(prime, (char *)buf); | |
41 | len = (unsigned long)strlen((char *)buf); | |
42 | if ((dp->prime = XMALLOC(1+len)) == NULL) goto cleanup4; | |
43 | strncpy(dp->prime, (char*)buf, 1+len); | |
44 | /* gx */ | |
45 | mp_tohex(gx, (char *)buf); | |
46 | len = (unsigned long)strlen((char *)buf); | |
47 | if ((dp->Gx = XMALLOC(1+len)) == NULL) goto cleanup5; | |
48 | strncpy(dp->Gx, (char*)buf, 1+len); | |
49 | /* gy */ | |
50 | mp_tohex(gy, (char *)buf); | |
51 | len = (unsigned long)strlen((char *)buf); | |
52 | if ((dp->Gy = XMALLOC(1+len)) == NULL) goto cleanup6; | |
53 | strncpy(dp->Gy, (char*)buf, 1+len); | |
54 | /* cofactor & size */ | |
55 | dp->cofactor = cofactor; | |
56 | dp->size = mp_unsigned_bin_size(prime); | |
57 | /* name */ | |
58 | if ((dp->name = XMALLOC(7)) == NULL) goto cleanup7; | |
59 | strcpy(dp->name, "custom"); /* XXX-TODO check this */ | |
60 | /* done - success */ | |
61 | return CRYPT_OK; | |
62 | ||
63 | /* XFREE(dp->name); **** warning: statement not reached *** */ | |
64 | cleanup7: | |
65 | XFREE(dp->Gy); | |
66 | cleanup6: | |
67 | XFREE(dp->Gx); | |
68 | cleanup5: | |
69 | XFREE(dp->prime); | |
70 | cleanup4: | |
71 | XFREE(dp->order); | |
72 | cleanup3: | |
73 | XFREE(dp->B); | |
74 | cleanup2: | |
75 | XFREE(dp->A); | |
76 | cleanup1: | |
77 | return CRYPT_MEM; | |
78 | } | |
79 | ||
80 | int ecc_import_full(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp) | |
81 | { | |
82 | void *prime, *order, *a, *b, *gx, *gy; | |
83 | ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4]; | |
84 | 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]; | |
85 | unsigned long len_a, len_b, len_k, len_g, len_xy; | |
86 | unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; | |
87 | /*oid_st oid;*/ | |
88 | int err; | |
89 | ||
90 | if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) return err; | |
91 | ||
92 | /* ### 1. try to load public key */ | |
93 | ||
94 | /* ECParameters SEQUENCE */ | |
95 | LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); | |
96 | LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); | |
97 | LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); | |
98 | LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1); | |
99 | LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); | |
100 | LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); | |
101 | seq_ecparams[5].optional = 1; | |
102 | /* FieldID SEQUENCE */ | |
103 | LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); | |
104 | LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); | |
105 | /* Curve SEQUENCE */ | |
106 | LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE); | |
107 | LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE); | |
108 | LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128); | |
109 | seq_curve[2].optional = 1; | |
110 | ||
111 | /* try to load public key */ | |
112 | len_xy = sizeof(bin_xy); | |
113 | err = der_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, 6); | |
114 | if (err == CRYPT_OK) { | |
115 | len_a = seq_curve[0].size; | |
116 | len_b = seq_curve[1].size; | |
117 | len_g = seq_ecparams[3].size; | |
118 | /* create bignums */ | |
119 | if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } | |
120 | if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } | |
121 | if ((err = ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } | |
122 | /* load curve parameters */ | |
123 | if ((err = _populate_dp(a, b, prime, order, gx, gy, cofactor, dp)) != CRYPT_OK) { goto error; } | |
124 | /* load public key */ | |
125 | if ((err = ecc_import_raw(bin_xy, len_xy, key, dp)) != CRYPT_OK) { goto error; } | |
126 | goto success; | |
127 | } | |
128 | ||
129 | /* ### 2. try to load private key */ | |
130 | ||
131 | /* ECPrivateKey SEQUENCE */ | |
132 | LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); | |
133 | LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, (unsigned long)ECC_MAXSIZE); | |
134 | LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); | |
135 | LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING, bin_xy, (unsigned long)8*(2*ECC_MAXSIZE+2)); | |
136 | seq_priv[2].tag = 0xA0; | |
137 | seq_priv[3].tag = 0xA1; | |
138 | /* ECParameters SEQUENCE */ | |
139 | LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); | |
140 | LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); | |
141 | LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); | |
142 | LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, (unsigned long)2*ECC_MAXSIZE+1); | |
143 | LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); | |
144 | LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); | |
145 | seq_ecparams[5].optional = 1; | |
146 | /* FieldID SEQUENCE */ | |
147 | LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); | |
148 | LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); | |
149 | /* Curve SEQUENCE */ | |
150 | LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, (unsigned long)ECC_MAXSIZE); | |
151 | LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, (unsigned long)ECC_MAXSIZE); | |
152 | LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, (unsigned long)8*128); | |
153 | seq_curve[2].optional = 1; | |
154 | ||
155 | /* try to load private key */ | |
156 | err = der_decode_sequence(in, inlen, seq_priv, 3); | |
157 | if (err == CRYPT_OK) { | |
158 | len_k = seq_priv[1].size; | |
159 | len_xy = seq_priv[3].size; | |
160 | len_a = seq_curve[0].size; | |
161 | len_b = seq_curve[1].size; | |
162 | len_g = seq_ecparams[3].size; | |
163 | /* create bignums */ | |
164 | if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } | |
165 | if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } | |
166 | if ((err = ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } | |
167 | /* load curve parameters */ | |
168 | if ((err = _populate_dp(a, b, prime, order, gx, gy, cofactor, dp)) != CRYPT_OK) { goto error; } | |
169 | /* load private+public key */ | |
170 | if ((err = ecc_import_raw(bin_k, len_k, key, dp)) != CRYPT_OK) { goto error; } | |
171 | goto success; | |
172 | } | |
173 | ||
174 | fprintf(stderr, "XXX-DEBUG: error=%s", error_to_string(err)); | |
175 | ||
176 | /* ### 3. backward compatibility - try to load old-DER format */ | |
177 | if ((err = ecc_import(in, inlen, key)) != CRYPT_OK) { goto error; } | |
178 | ||
179 | success: | |
180 | err = CRYPT_OK; | |
181 | error: | |
182 | mp_clear_multi(prime, order, a, b, gx, gy, NULL); | |
183 | return err; | |
184 | } | |
185 | ||
186 | #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 |
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 |