ECC ecc_import_point
Karel Miko
10 years ago
15 | 15 | |
16 | 16 | #ifdef LTC_MECC |
17 | 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, size; | |
21 | void *t1, *t2; | |
22 | ||
23 | /* init key + temporary numbers */ | |
24 | if (mp_init_multi(&t1, &t2, NULL) != CRYPT_OK) { | |
25 | return CRYPT_MEM; | |
26 | } | |
27 | ||
28 | size = mp_unsigned_bin_size(prime); | |
29 | ||
30 | if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) { | |
31 | /* read uncompressed point */ | |
32 | /* load x */ | |
33 | if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { | |
34 | goto cleanup; | |
35 | } | |
36 | /* load y */ | |
37 | if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { | |
38 | goto cleanup; | |
39 | } | |
40 | } | |
41 | else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size) { | |
42 | /* read compressed point */ | |
43 | /* load x */ | |
44 | if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { | |
45 | goto cleanup; | |
46 | } | |
47 | /* compute x^3 */ | |
48 | if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; } | |
49 | if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; } | |
50 | /* compute x^3 + a*x */ | |
51 | if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; } | |
52 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } | |
53 | /* compute x^3 + a*x + b */ | |
54 | if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } | |
55 | /* compute sqrt(x^3 + a*x + b) */ | |
56 | if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } | |
57 | /* adjust y */ | |
58 | if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) { | |
59 | if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; } | |
60 | } | |
61 | else { | |
62 | if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; } | |
63 | } | |
64 | } | |
65 | else { | |
66 | err = CRYPT_INVALID_PACKET; | |
67 | goto cleanup; | |
68 | } | |
69 | ||
70 | err = CRYPT_OK; | |
71 | cleanup: | |
72 | mp_clear_multi(t1, t2, NULL); | |
73 | return err; | |
74 | } | |
75 | ||
18 | 76 | /** Import raw public or private key (public keys = ANSI X9.63 compressed or uncompressed; private keys = raw bytes) |
19 | 77 | @param in The input data to read |
20 | 78 | @param inlen The length of the input data |
26 | 84 | int ecc_import_raw(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp) |
27 | 85 | { |
28 | 86 | int err, size = 0, type = -1; |
29 | void *t1, *t2, *prime, *a, *b; | |
87 | void *prime, *a, *b; | |
30 | 88 | ecc_point *base; |
31 | 89 | |
32 | 90 | LTC_ARGCHK(in != NULL); |
34 | 92 | LTC_ARGCHK(dp != NULL); |
35 | 93 | |
36 | 94 | /* init key + temporary numbers */ |
37 | if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &t1, &t2, &prime, &a, &b, NULL) != CRYPT_OK) { | |
95 | if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &a, &b, NULL) != CRYPT_OK) { | |
38 | 96 | return CRYPT_MEM; |
39 | 97 | } |
40 | 98 | |
41 | 99 | if (inlen == dp->size) { |
42 | /* ######## read PRIVATE key */ | |
100 | /* read PRIVATE key */ | |
43 | 101 | type = PK_PRIVATE; |
44 | 102 | size = inlen; |
45 | 103 | /* load private k */ |
68 | 126 | /* cleanup */ |
69 | 127 | ltc_ecc_del_point(base); |
70 | 128 | } |
71 | else if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == dp->size) { | |
72 | /* ######## read PUBLIC key - uncompressed point */ | |
129 | else { | |
130 | /* read PUBLIC key */ | |
73 | 131 | type = PK_PUBLIC; |
74 | size = (inlen-1)>>1; | |
75 | /* load public.x */ | |
76 | if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in+1, size)) != CRYPT_OK) { | |
77 | goto cleanup; | |
78 | } | |
79 | /* load public.y */ | |
80 | if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { | |
81 | goto cleanup; | |
82 | } | |
83 | /* set public.z */ | |
84 | if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto cleanup; } | |
85 | } | |
86 | else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == dp->size) { | |
87 | /* ######## read PUBLIC key - compressed point */ | |
88 | type = PK_PUBLIC; | |
89 | size = inlen-1; | |
90 | /* load public.x */ | |
91 | if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in+1, size)) != CRYPT_OK) { | |
92 | goto cleanup; | |
93 | } | |
94 | /* load prime + base point */ | |
132 | /* load prime + A + B */ | |
95 | 133 | if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) { goto cleanup; } |
96 | 134 | if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) { goto cleanup; } |
97 | 135 | if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) { goto cleanup; } |
98 | /* compute x^3 */ | |
99 | if ((err = mp_sqr(key->pubkey.x, t1)) != CRYPT_OK) { goto cleanup; } | |
100 | if ((err = mp_mulmod(t1, key->pubkey.x, prime, t1)) != CRYPT_OK) { goto cleanup; } | |
101 | /* compute x^3 + a*x */ | |
102 | if ((err = mp_mulmod(a, key->pubkey.x, prime, t2)) != CRYPT_OK) { goto cleanup; } | |
103 | if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } | |
104 | /* compute x^3 + a*x + b */ | |
105 | if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } | |
106 | /* compute sqrt(x^3 + a*x + b) */ | |
107 | if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } | |
108 | /* adjust y */ | |
109 | if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) { | |
110 | if ((err = mp_mod(t2, prime, key->pubkey.y)) != CRYPT_OK) { goto cleanup; } | |
111 | } | |
112 | else { | |
113 | if ((err = mp_submod(prime, t2, prime, key->pubkey.y)) != CRYPT_OK) { goto cleanup; } | |
114 | } | |
115 | /* set public.z */ | |
136 | err = ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y); | |
137 | if (err != CRYPT_OK) { goto cleanup; } | |
116 | 138 | if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto cleanup; } |
117 | 139 | } |
118 | else { | |
119 | err = CRYPT_INVALID_PACKET; | |
120 | goto cleanup; | |
121 | } | |
122 | ||
140 | ||
123 | 141 | if ((err = ltc_ecc_is_point(dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { |
124 | 142 | err = CRYPT_INVALID_PACKET; |
125 | 143 | goto cleanup; |
130 | 148 | key->dp = dp; |
131 | 149 | |
132 | 150 | /* we're done */ |
133 | mp_clear_multi(t1, t2, prime, a, b, NULL); | |
151 | mp_clear_multi(prime, a, b, NULL); | |
134 | 152 | return CRYPT_OK; |
135 | 153 | cleanup: |
136 | mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, t1, t2, prime, a, b, NULL); | |
154 | mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, prime, a, b, NULL); | |
137 | 155 | return err; |
138 | 156 | } |
139 | 157 |