Mercurial > dropbear
comparison ecc.c @ 765:5503e05ab3a4 ecc
- Rename buf_put_ecc_pubkey_string() to buf_put_ecc_raw_pubkey_string()
- Reindent ecc.c properly
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 08 Apr 2013 23:56:31 +0800 |
parents | f744321ac048 |
children | d1575fdc29a6 |
comparison
equal
deleted
inserted
replaced
764:2202e854d187 | 765:5503e05ab3a4 |
---|---|
29 .name = "nistp521" | 29 .name = "nistp521" |
30 }; | 30 }; |
31 #endif | 31 #endif |
32 | 32 |
33 static ecc_key * new_ecc_key(void) { | 33 static ecc_key * new_ecc_key(void) { |
34 ecc_key *key = m_malloc(sizeof(*key)); | 34 ecc_key *key = m_malloc(sizeof(*key)); |
35 key->pubkey.x = m_malloc(sizeof(mp_int)); | 35 key->pubkey.x = m_malloc(sizeof(mp_int)); |
36 key->pubkey.y = m_malloc(sizeof(mp_int)); | 36 key->pubkey.y = m_malloc(sizeof(mp_int)); |
37 key->pubkey.z = m_malloc(sizeof(mp_int)); | 37 key->pubkey.z = m_malloc(sizeof(mp_int)); |
38 key->k = m_malloc(sizeof(mp_int)); | 38 key->k = m_malloc(sizeof(mp_int)); |
39 m_mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); | 39 m_mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); |
40 return key; | 40 return key; |
41 } | 41 } |
42 | 42 |
43 void buf_put_ecc_pubkey_string(buffer *buf, ecc_key *key) { | 43 // Copied from libtomcrypt ecc_import.c (version there is static), modified |
44 // for different mp_int pointer without LTC_SOURCE | |
45 static int ecc_is_point(ecc_key *key) | |
46 { | |
47 mp_int *prime, *b, *t1, *t2; | |
48 int err; | |
49 | |
50 prime = m_malloc(sizeof(mp_int)); | |
51 b = m_malloc(sizeof(mp_int)); | |
52 t1 = m_malloc(sizeof(mp_int)); | |
53 t2 = m_malloc(sizeof(mp_int)); | |
54 | |
55 m_mp_init_multi(prime, b, t1, t2, NULL); | |
56 | |
57 /* load prime and b */ | |
58 if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } | |
59 if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } | |
60 | |
61 /* compute y^2 */ | |
62 if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } | |
63 | |
64 /* compute x^3 */ | |
65 if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } | |
66 if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } | |
67 if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } | |
68 | |
69 /* compute y^2 - x^3 */ | |
70 if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } | |
71 | |
72 /* compute y^2 - x^3 + 3x */ | |
73 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
74 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
75 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | |
76 if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
77 while (mp_cmp_d(t1, 0) == LTC_MP_LT) { | |
78 if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
79 } | |
80 while (mp_cmp(t1, prime) != LTC_MP_LT) { | |
81 if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
82 } | |
83 | |
84 /* compare to b */ | |
85 if (mp_cmp(t1, b) != LTC_MP_EQ) { | |
86 err = CRYPT_INVALID_PACKET; | |
87 } else { | |
88 err = CRYPT_OK; | |
89 } | |
90 | |
91 error: | |
92 mp_clear_multi(prime, b, t1, t2, NULL); | |
93 m_free(prime); | |
94 m_free(b); | |
95 m_free(t1); | |
96 m_free(t2); | |
97 return err; | |
98 } | |
99 | |
100 /* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */ | |
101 void buf_put_ecc_raw_pubkey_string(buffer *buf, ecc_key *key) { | |
44 unsigned long len = key->dp->size*2 + 1; | 102 unsigned long len = key->dp->size*2 + 1; |
45 buf_putint(buf, len); | 103 buf_putint(buf, len); |
46 int err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len); | 104 int err = ecc_ansi_x963_export(key, buf_getwriteptr(buf, len), &len); |
47 if (err != CRYPT_OK) { | 105 if (err != CRYPT_OK) { |
48 dropbear_exit("ECC error"); | 106 dropbear_exit("ECC error"); |
49 } | 107 } |
50 buf_incrwritepos(buf, len); | 108 buf_incrwritepos(buf, len); |
51 } | 109 } |
52 | 110 |
53 // Copied from libtomcrypt ecc_import.c (version there is static), modified | 111 /* For the "ephemeral public key octet string" in ECDH (rfc5656 section 4) */ |
54 // for different mp_int pointer without LTC_SOURCE | 112 ecc_key * buf_get_ecc_raw_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve) { |
55 static int ecc_is_point(ecc_key *key) | 113 ecc_key *key = NULL; |
56 { | 114 int ret = DROPBEAR_FAILURE; |
57 mp_int *prime, *b, *t1, *t2; | 115 const unsigned int size = curve->dp->size; |
58 int err; | 116 buf_setpos(buf, 0); |
59 | 117 unsigned int len = buf->len; |
60 prime = m_malloc(sizeof(mp_int)); | 118 unsigned char first = buf_getbyte(buf); |
61 b = m_malloc(sizeof(mp_int)); | 119 if (first == 2 || first == 3) { |
62 t1 = m_malloc(sizeof(mp_int)); | 120 dropbear_log(LOG_WARNING, "Dropbear doesn't support ECC point compression"); |
63 t2 = m_malloc(sizeof(mp_int)); | 121 return NULL; |
64 | 122 } |
65 m_mp_init_multi(prime, b, t1, t2, NULL); | 123 if (first != 4 || len != 1+2*size) { |
66 | 124 return NULL; |
67 /* load prime and b */ | 125 } |
68 if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } | 126 |
69 if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } | 127 key = new_ecc_key(); |
70 | 128 key->dp = curve->dp; |
71 /* compute y^2 */ | 129 |
72 if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } | 130 if (mp_read_unsigned_bin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) { |
73 | 131 goto out; |
74 /* compute x^3 */ | 132 } |
75 if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } | 133 buf_incrpos(buf, size); |
76 if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } | 134 |
77 if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } | 135 if (mp_read_unsigned_bin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) { |
78 | 136 goto out; |
79 /* compute y^2 - x^3 */ | 137 } |
80 if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } | 138 buf_incrpos(buf, size); |
81 | 139 |
82 /* compute y^2 - x^3 + 3x */ | 140 mp_set(key->pubkey.z, 1); |
83 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | 141 |
84 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | 142 if (ecc_is_point(key) != CRYPT_OK) { |
85 if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } | 143 goto out; |
86 if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } | 144 } |
87 while (mp_cmp_d(t1, 0) == LTC_MP_LT) { | |
88 if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
89 } | |
90 while (mp_cmp(t1, prime) != LTC_MP_LT) { | |
91 if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } | |
92 } | |
93 | |
94 /* compare to b */ | |
95 if (mp_cmp(t1, b) != LTC_MP_EQ) { | |
96 err = CRYPT_INVALID_PACKET; | |
97 } else { | |
98 err = CRYPT_OK; | |
99 } | |
100 | |
101 error: | |
102 mp_clear_multi(prime, b, t1, t2, NULL); | |
103 m_free(prime); | |
104 m_free(b); | |
105 m_free(t1); | |
106 m_free(t2); | |
107 return err; | |
108 } | |
109 | |
110 ecc_key * buf_get_ecc_pubkey(buffer *buf, const struct dropbear_ecc_curve *curve) { | |
111 ecc_key *key = NULL; | |
112 int ret = DROPBEAR_FAILURE; | |
113 const unsigned int size = curve->dp->size; | |
114 buf_setpos(buf, 0); | |
115 unsigned int len = buf->len; | |
116 unsigned char first = buf_getbyte(buf); | |
117 if (first == 2 || first == 3) { | |
118 dropbear_log(LOG_WARNING, "Dropbear doesn't support ECC point compression"); | |
119 return NULL; | |
120 } | |
121 if (first != 4 || len != 1+2*size) { | |
122 return NULL; | |
123 } | |
124 | |
125 key = new_ecc_key(); | |
126 key->dp = curve->dp; | |
127 | |
128 if (mp_read_unsigned_bin(key->pubkey.x, buf_getptr(buf, size), size) != MP_OKAY) { | |
129 goto out; | |
130 } | |
131 buf_incrpos(buf, size); | |
132 | |
133 if (mp_read_unsigned_bin(key->pubkey.y, buf_getptr(buf, size), size) != MP_OKAY) { | |
134 goto out; | |
135 } | |
136 buf_incrpos(buf, size); | |
137 | |
138 mp_set(key->pubkey.z, 1); | |
139 | |
140 if (ecc_is_point(key) != CRYPT_OK) { | |
141 goto out; | |
142 } | |
143 | 145 |
144 // SEC1 3.2.3.1 Check that Q != 0 | 146 // SEC1 3.2.3.1 Check that Q != 0 |
145 if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) { | 147 if (mp_cmp_d(key->pubkey.x, 0) == LTC_MP_EQ) { |
146 goto out; | 148 goto out; |
147 } | 149 } |
148 if (mp_cmp_d(key->pubkey.y, 0) == LTC_MP_EQ) { | 150 if (mp_cmp_d(key->pubkey.y, 0) == LTC_MP_EQ) { |
149 goto out; | 151 goto out; |
150 } | 152 } |
151 | 153 |
152 ret = DROPBEAR_SUCCESS; | 154 ret = DROPBEAR_SUCCESS; |
153 | 155 |
154 out: | 156 out: |
155 if (ret == DROPBEAR_FAILURE) { | 157 if (ret == DROPBEAR_FAILURE) { |
156 if (key) { | 158 if (key) { |
157 ecc_free(key); | 159 ecc_free(key); |
158 m_free(key); | 160 m_free(key); |
159 key = NULL; | 161 key = NULL; |
160 } | 162 } |
161 } | 163 } |
162 | 164 |
163 return key; | 165 return key; |
164 | 166 |
165 } | 167 } |
166 | 168 |
167 // a modified version of libtomcrypt's "ecc_shared_secret" to output | 169 // a modified version of libtomcrypt's "ecc_shared_secret" to output |
168 // a mp_int instead. | 170 // a mp_int instead. |
169 mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key) | 171 mp_int * dropbear_ecc_shared_secret(ecc_key *public_key, ecc_key *private_key) |
170 { | 172 { |
171 ecc_point *result = NULL; | 173 ecc_point *result = NULL; |
172 mp_int *prime = NULL, *shared_secret = NULL; | 174 mp_int *prime = NULL, *shared_secret = NULL; |
173 int err = DROPBEAR_FAILURE; | 175 int err = DROPBEAR_FAILURE; |
174 | 176 |
175 /* type valid? */ | 177 /* type valid? */ |
176 if (private_key->type != PK_PRIVATE) { | 178 if (private_key->type != PK_PRIVATE) { |
177 goto done; | 179 goto done; |
178 } | 180 } |
179 | 181 |
180 if (private_key->dp != public_key->dp) { | 182 if (private_key->dp != public_key->dp) { |
181 goto done; | 183 goto done; |
182 } | 184 } |
183 | 185 |
184 /* make new point */ | 186 /* make new point */ |
185 result = ltc_ecc_new_point(); | 187 result = ltc_ecc_new_point(); |
186 if (result == NULL) { | 188 if (result == NULL) { |
187 goto done; | 189 goto done; |
188 } | 190 } |
189 | 191 |
190 prime = m_malloc(sizeof(*prime)); | 192 prime = m_malloc(sizeof(*prime)); |
191 m_mp_init(prime); | 193 m_mp_init(prime); |
192 | 194 |
193 if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) { | 195 if (mp_read_radix(prime, (char *)private_key->dp->prime, 16) != CRYPT_OK) { |
194 goto done; | 196 goto done; |
195 } | 197 } |
196 if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) { | 198 if (ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1) != CRYPT_OK) { |
197 goto done; | 199 goto done; |
198 } | 200 } |
199 | 201 |
200 err = DROPBEAR_SUCCESS; | 202 err = DROPBEAR_SUCCESS; |
201 done: | 203 done: |
202 if (err == DROPBEAR_SUCCESS) { | 204 if (err == DROPBEAR_SUCCESS) { |
203 shared_secret = m_malloc(sizeof(*shared_secret)); | 205 shared_secret = m_malloc(sizeof(*shared_secret)); |
204 m_mp_init(shared_secret); | 206 m_mp_init(shared_secret); |
205 mp_copy(result->x, shared_secret); | 207 mp_copy(result->x, shared_secret); |
206 } | 208 } |
207 | 209 |
208 if (prime) { | 210 if (prime) { |
209 mp_clear(prime); | 211 mp_clear(prime); |
210 m_free(prime); | 212 m_free(prime); |
211 } | 213 } |
212 if (result) | 214 if (result) |
213 { | 215 { |
214 ltc_ecc_del_point(result); | 216 ltc_ecc_del_point(result); |
215 } | 217 } |
216 | 218 |
217 if (err == DROPBEAR_FAILURE) { | 219 if (err == DROPBEAR_FAILURE) { |
218 dropbear_exit("ECC error"); | 220 dropbear_exit("ECC error"); |
219 } | 221 } |
220 return shared_secret; | 222 return shared_secret; |
221 } | 223 } |
222 | 224 |
223 #endif | 225 #endif |