]>
Commit | Line | Data |
---|---|---|
440e5d80 RS |
1 | /* |
2 | * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
e172d60d BM |
10 | /* ==================================================================== |
11 | * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | |
12 | * | |
13 | * The Elliptic Curve Public-Key Crypto Library (ECC Code) included | |
14 | * herein is developed by SUN MICROSYSTEMS, INC., and is contributed | |
15 | * to the OpenSSL project. | |
16 | * | |
17 | * The ECC Code is licensed pursuant to the OpenSSL open source | |
18 | * license provided below. | |
19 | * | |
e172d60d BM |
20 | * The ECDH software is originally written by Douglas Stebila of |
21 | * Sun Microsystems Laboratories. | |
22 | * | |
23 | */ | |
e172d60d BM |
24 | |
25 | #include <stdio.h> | |
26 | #include <stdlib.h> | |
27 | #include <string.h> | |
55f78baf RL |
28 | |
29 | #include "../e_os.h" | |
30 | ||
10bf4fc2 | 31 | #include <openssl/opensslconf.h> /* for OPENSSL_NO_EC */ |
e172d60d BM |
32 | #include <openssl/crypto.h> |
33 | #include <openssl/bio.h> | |
34 | #include <openssl/bn.h> | |
e172d60d BM |
35 | #include <openssl/objects.h> |
36 | #include <openssl/rand.h> | |
176f31dd | 37 | #include <openssl/sha.h> |
e172d60d BM |
38 | #include <openssl/err.h> |
39 | ||
10bf4fc2 | 40 | #ifdef OPENSSL_NO_EC |
e172d60d BM |
41 | int main(int argc, char *argv[]) |
42 | { | |
43 | printf("No ECDH support\n"); | |
0f113f3e | 44 | return (0); |
e172d60d BM |
45 | } |
46 | #else | |
0f113f3e | 47 | # include <openssl/ec.h> |
e172d60d | 48 | |
0f113f3e MC |
49 | static const char rnd_seed[] = |
50 | "string to make the random number generator think it has entropy"; | |
176f31dd BM |
51 | |
52 | static const int KDF1_SHA1_len = 20; | |
0f113f3e MC |
53 | static void *KDF1_SHA1(const void *in, size_t inlen, void *out, |
54 | size_t *outlen) | |
55 | { | |
0f113f3e MC |
56 | if (*outlen < SHA_DIGEST_LENGTH) |
57 | return NULL; | |
474e469b | 58 | *outlen = SHA_DIGEST_LENGTH; |
0f113f3e | 59 | return SHA1(in, inlen, out); |
0f113f3e | 60 | } |
176f31dd | 61 | |
b438f0ed | 62 | static int test_ecdh_curve(int nid, BN_CTX *ctx, BIO *out) |
0f113f3e MC |
63 | { |
64 | EC_KEY *a = NULL; | |
65 | EC_KEY *b = NULL; | |
66 | BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; | |
67 | char buf[12]; | |
68 | unsigned char *abuf = NULL, *bbuf = NULL; | |
69 | int i, alen, blen, aout, bout, ret = 0; | |
70 | const EC_GROUP *group; | |
71 | ||
72 | a = EC_KEY_new_by_curve_name(nid); | |
73 | b = EC_KEY_new_by_curve_name(nid); | |
74 | if (a == NULL || b == NULL) | |
75 | goto err; | |
76 | ||
77 | group = EC_KEY_get0_group(a); | |
78 | ||
79 | if ((x_a = BN_new()) == NULL) | |
80 | goto err; | |
81 | if ((y_a = BN_new()) == NULL) | |
82 | goto err; | |
83 | if ((x_b = BN_new()) == NULL) | |
84 | goto err; | |
85 | if ((y_b = BN_new()) == NULL) | |
86 | goto err; | |
87 | ||
88 | BIO_puts(out, "Testing key generation with "); | |
b438f0ed | 89 | BIO_puts(out, OBJ_nid2sn(nid)); |
0f113f3e MC |
90 | # ifdef NOISY |
91 | BIO_puts(out, "\n"); | |
92 | # else | |
93 | (void)BIO_flush(out); | |
94 | # endif | |
95 | ||
96 | if (!EC_KEY_generate_key(a)) | |
97 | goto err; | |
98 | ||
99 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == | |
100 | NID_X9_62_prime_field) { | |
101 | if (!EC_POINT_get_affine_coordinates_GFp | |
102 | (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx)) | |
103 | goto err; | |
104 | } | |
105 | # ifndef OPENSSL_NO_EC2M | |
106 | else { | |
107 | if (!EC_POINT_get_affine_coordinates_GF2m(group, | |
108 | EC_KEY_get0_public_key(a), | |
109 | x_a, y_a, ctx)) | |
110 | goto err; | |
111 | } | |
112 | # endif | |
113 | # ifdef NOISY | |
114 | BIO_puts(out, " pri 1="); | |
115 | BN_print(out, a->priv_key); | |
116 | BIO_puts(out, "\n pub 1="); | |
117 | BN_print(out, x_a); | |
118 | BIO_puts(out, ","); | |
119 | BN_print(out, y_a); | |
120 | BIO_puts(out, "\n"); | |
121 | # else | |
122 | BIO_printf(out, " ."); | |
123 | (void)BIO_flush(out); | |
124 | # endif | |
125 | ||
126 | if (!EC_KEY_generate_key(b)) | |
127 | goto err; | |
128 | ||
129 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == | |
130 | NID_X9_62_prime_field) { | |
131 | if (!EC_POINT_get_affine_coordinates_GFp | |
132 | (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx)) | |
133 | goto err; | |
134 | } | |
135 | # ifndef OPENSSL_NO_EC2M | |
136 | else { | |
137 | if (!EC_POINT_get_affine_coordinates_GF2m(group, | |
138 | EC_KEY_get0_public_key(b), | |
139 | x_b, y_b, ctx)) | |
140 | goto err; | |
141 | } | |
142 | # endif | |
143 | ||
144 | # ifdef NOISY | |
145 | BIO_puts(out, " pri 2="); | |
146 | BN_print(out, b->priv_key); | |
147 | BIO_puts(out, "\n pub 2="); | |
148 | BN_print(out, x_b); | |
149 | BIO_puts(out, ","); | |
150 | BN_print(out, y_b); | |
151 | BIO_puts(out, "\n"); | |
152 | # else | |
153 | BIO_printf(out, "."); | |
154 | (void)BIO_flush(out); | |
155 | # endif | |
156 | ||
157 | alen = KDF1_SHA1_len; | |
b196e7d9 | 158 | abuf = OPENSSL_malloc(alen); |
0f113f3e MC |
159 | aout = |
160 | ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); | |
161 | ||
162 | # ifdef NOISY | |
163 | BIO_puts(out, " key1 ="); | |
164 | for (i = 0; i < aout; i++) { | |
165 | sprintf(buf, "%02X", abuf[i]); | |
166 | BIO_puts(out, buf); | |
167 | } | |
168 | BIO_puts(out, "\n"); | |
169 | # else | |
170 | BIO_printf(out, "."); | |
171 | (void)BIO_flush(out); | |
172 | # endif | |
173 | ||
174 | blen = KDF1_SHA1_len; | |
b196e7d9 | 175 | bbuf = OPENSSL_malloc(blen); |
0f113f3e MC |
176 | bout = |
177 | ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); | |
178 | ||
179 | # ifdef NOISY | |
180 | BIO_puts(out, " key2 ="); | |
181 | for (i = 0; i < bout; i++) { | |
182 | sprintf(buf, "%02X", bbuf[i]); | |
183 | BIO_puts(out, buf); | |
184 | } | |
185 | BIO_puts(out, "\n"); | |
186 | # else | |
187 | BIO_printf(out, "."); | |
188 | (void)BIO_flush(out); | |
189 | # endif | |
190 | ||
191 | if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { | |
192 | # ifndef NOISY | |
193 | BIO_printf(out, " failed\n\n"); | |
194 | BIO_printf(out, "key a:\n"); | |
195 | BIO_printf(out, "private key: "); | |
196 | BN_print(out, EC_KEY_get0_private_key(a)); | |
197 | BIO_printf(out, "\n"); | |
198 | BIO_printf(out, "public key (x,y): "); | |
199 | BN_print(out, x_a); | |
200 | BIO_printf(out, ","); | |
201 | BN_print(out, y_a); | |
202 | BIO_printf(out, "\nkey b:\n"); | |
203 | BIO_printf(out, "private key: "); | |
204 | BN_print(out, EC_KEY_get0_private_key(b)); | |
205 | BIO_printf(out, "\n"); | |
206 | BIO_printf(out, "public key (x,y): "); | |
207 | BN_print(out, x_b); | |
208 | BIO_printf(out, ","); | |
209 | BN_print(out, y_b); | |
210 | BIO_printf(out, "\n"); | |
211 | BIO_printf(out, "generated key a: "); | |
212 | for (i = 0; i < bout; i++) { | |
213 | sprintf(buf, "%02X", bbuf[i]); | |
214 | BIO_puts(out, buf); | |
215 | } | |
216 | BIO_printf(out, "\n"); | |
217 | BIO_printf(out, "generated key b: "); | |
218 | for (i = 0; i < aout; i++) { | |
219 | sprintf(buf, "%02X", abuf[i]); | |
220 | BIO_puts(out, buf); | |
221 | } | |
222 | BIO_printf(out, "\n"); | |
223 | # endif | |
224 | fprintf(stderr, "Error in ECDH routines\n"); | |
225 | ret = 0; | |
226 | } else { | |
227 | # ifndef NOISY | |
228 | BIO_printf(out, " ok\n"); | |
229 | # endif | |
230 | ret = 1; | |
231 | } | |
232 | err: | |
233 | ERR_print_errors_fp(stderr); | |
234 | ||
b548a1f1 RS |
235 | OPENSSL_free(abuf); |
236 | OPENSSL_free(bbuf); | |
23a1d5e9 RS |
237 | BN_free(x_a); |
238 | BN_free(y_a); | |
239 | BN_free(x_b); | |
240 | BN_free(y_b); | |
8fdc3734 RS |
241 | EC_KEY_free(b); |
242 | EC_KEY_free(a); | |
0f113f3e MC |
243 | return (ret); |
244 | } | |
e172d60d | 245 | |
b438f0ed BB |
246 | typedef struct { |
247 | const int nid; | |
248 | const char *da; | |
249 | const char *db; | |
250 | const char *Z; | |
251 | } ecdh_kat_t; | |
252 | ||
253 | static const ecdh_kat_t ecdh_kats[] = { | |
254 | /* Keys and shared secrets from RFC 5114 */ | |
255 | { NID_X9_62_prime192v1, | |
256 | "323FA3169D8E9C6593F59476BC142000AB5BE0E249C43426", | |
257 | "631F95BB4A67632C9C476EEE9AB695AB240A0499307FCF62", | |
258 | "AD420182633F8526BFE954ACDA376F05E5FF4F837F54FEBE" }, | |
259 | { NID_secp224r1, | |
260 | "B558EB6C288DA707BBB4F8FBAE2AB9E9CB62E3BC5C7573E22E26D37F", | |
261 | "AC3B1ADD3D9770E6F6A708EE9F3B8E0AB3B480E9F27F85C88B5E6D18", | |
262 | "52272F50F46F4EDC9151569092F46DF2D96ECC3B6DC1714A4EA949FA" }, | |
263 | { NID_X9_62_prime256v1, | |
264 | "814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF", | |
265 | "2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41", | |
266 | "DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788" }, | |
267 | { NID_secp384r1, | |
268 | "D27335EA71664AF244DD14E9FD1260715DFD8A7965571C48D709EE7A7962A156" | |
269 | "D706A90CBCB5DF2986F05FEADB9376F1", | |
270 | "52D1791FDB4B70F89C0F00D456C2F7023B6125262C36A7DF1F80231121CCE3D3" | |
271 | "9BE52E00C194A4132C4A6C768BCD94D2", | |
272 | "5EA1FC4AF7256D2055981B110575E0A8CAE53160137D904C59D926EB1B8456E4" | |
273 | "27AA8A4540884C37DE159A58028ABC0E" }, | |
274 | { NID_secp521r1, | |
275 | "0113F82DA825735E3D97276683B2B74277BAD27335EA71664AF2430CC4F33459" | |
276 | "B9669EE78B3FFB9B8683015D344DCBFEF6FB9AF4C6C470BE254516CD3C1A1FB4" | |
277 | "7362", | |
278 | "00CEE3480D8645A17D249F2776D28BAE616952D1791FDB4B70F7C3378732AA1B" | |
279 | "22928448BCD1DC2496D435B01048066EBE4F72903C361B1A9DC1193DC2C9D089" | |
280 | "1B96", | |
281 | "00CDEA89621CFA46B132F9E4CFE2261CDE2D4368EB5656634C7CC98C7A00CDE5" | |
282 | "4ED1866A0DD3E6126C9D2F845DAFF82CEB1DA08F5D87521BB0EBECA77911169C" | |
283 | "20CC" }, | |
284 | /* Keys and shared secrets from RFC 5903 */ | |
285 | { NID_X9_62_prime256v1, | |
286 | "C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433", | |
287 | "C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53", | |
288 | "D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE" }, | |
289 | { NID_secp384r1, | |
290 | "099F3C7034D4A2C699884D73A375A67F7624EF7C6B3C0F160647B67414DCE655" | |
291 | "E35B538041E649EE3FAEF896783AB194", | |
292 | "41CB0779B4BDB85D47846725FBEC3C9430FAB46CC8DC5060855CC9BDA0AA2942" | |
293 | "E0308312916B8ED2960E4BD55A7448FC", | |
294 | "11187331C279962D93D604243FD592CB9D0A926F422E47187521287E7156C5C4" | |
295 | "D603135569B9E9D09CF5D4A270F59746" }, | |
296 | { NID_secp521r1, | |
297 | "0037ADE9319A89F4DABDB3EF411AACCCA5123C61ACAB57B5393DCE47608172A0" | |
298 | "95AA85A30FE1C2952C6771D937BA9777F5957B2639BAB072462F68C27A57382D" | |
299 | "4A52", | |
300 | "0145BA99A847AF43793FDD0E872E7CDFA16BE30FDC780F97BCCC3F078380201E" | |
301 | "9C677D600B343757A3BDBF2A3163E4C2F869CCA7458AA4A4EFFC311F5CB15168" | |
302 | "5EB9", | |
303 | "01144C7D79AE6956BC8EDB8E7C787C4521CB086FA64407F97894E5E6B2D79B04" | |
304 | "D1427E73CA4BAA240A34786859810C06B3C715A3A8CC3151F2BEE417996D19F3" | |
305 | "DDEA" }, | |
306 | /* Keys and shared secrets from RFC 7027 */ | |
307 | { NID_brainpoolP256r1, | |
308 | "81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B063039804F1D", | |
309 | "55E40BC41E37E3E2AD25C3C6654511FFA8474A91A0032087593852D3E7D76BD3", | |
310 | "89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A18BF2B" }, | |
311 | { NID_brainpoolP384r1, | |
312 | "1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0BD65D6" | |
313 | "F15EB5D1EE1610DF870795143627D042", | |
314 | "032640BC6003C59260F7250C3DB58CE647F98E1260ACCE4ACDA3DD869F74E01F" | |
315 | "8BA5E0324309DB6A9831497ABAC96670", | |
316 | "0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBCE239BB" | |
317 | "ADF6403715C35D4FB2A5444F575D4F42" }, | |
318 | { NID_brainpoolP512r1, | |
319 | "16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59" | |
320 | "B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422", | |
321 | "230E18E1BCC88A362FA54E4EA3902009292F7F8033624FD471B5D8ACE49D12CF" | |
322 | "ABBC19963DAB8E2F1EBA00BFFB29E4D72D13F2224562F405CB80503666B25429", | |
323 | "A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76" | |
324 | "D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F" } | |
da317b94 DSH |
325 | }; |
326 | ||
327 | /* Given private value and NID, create EC_KEY structure */ | |
328 | ||
b438f0ed | 329 | static EC_KEY *mk_eckey(int nid, const char *str) |
0f113f3e MC |
330 | { |
331 | int ok = 0; | |
332 | EC_KEY *k = NULL; | |
333 | BIGNUM *priv = NULL; | |
334 | EC_POINT *pub = NULL; | |
335 | const EC_GROUP *grp; | |
336 | k = EC_KEY_new_by_curve_name(nid); | |
337 | if (!k) | |
338 | goto err; | |
b438f0ed BB |
339 | if(!BN_hex2bn(&priv, str)) |
340 | goto err; | |
0f113f3e MC |
341 | if (!priv) |
342 | goto err; | |
343 | if (!EC_KEY_set_private_key(k, priv)) | |
344 | goto err; | |
345 | grp = EC_KEY_get0_group(k); | |
346 | pub = EC_POINT_new(grp); | |
347 | if (!pub) | |
348 | goto err; | |
349 | if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL)) | |
350 | goto err; | |
351 | if (!EC_KEY_set_public_key(k, pub)) | |
352 | goto err; | |
353 | ok = 1; | |
354 | err: | |
23a1d5e9 | 355 | BN_clear_free(priv); |
8fdc3734 | 356 | EC_POINT_free(pub); |
0f113f3e MC |
357 | if (ok) |
358 | return k; | |
8fdc3734 | 359 | EC_KEY_free(k); |
0f113f3e MC |
360 | return NULL; |
361 | } | |
362 | ||
363 | /* | |
364 | * Known answer test: compute shared secret and check it matches expected | |
365 | * value. | |
da317b94 DSH |
366 | */ |
367 | ||
b438f0ed | 368 | static int ecdh_kat(BIO *out, const ecdh_kat_t *kat) |
0f113f3e MC |
369 | { |
370 | int rv = 0; | |
371 | EC_KEY *key1 = NULL, *key2 = NULL; | |
b438f0ed BB |
372 | BIGNUM *bnz = NULL; |
373 | unsigned char *Ztmp = NULL, *Z = NULL; | |
374 | size_t Ztmplen, Zlen; | |
0f113f3e | 375 | BIO_puts(out, "Testing ECDH shared secret with "); |
b438f0ed BB |
376 | BIO_puts(out, OBJ_nid2sn(kat->nid)); |
377 | if(!BN_hex2bn(&bnz, kat->Z)) | |
378 | goto err; | |
379 | key1 = mk_eckey(kat->nid, kat->da); | |
380 | key2 = mk_eckey(kat->nid, kat->db); | |
0f113f3e MC |
381 | if (!key1 || !key2) |
382 | goto err; | |
383 | Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8; | |
b438f0ed BB |
384 | Zlen = BN_num_bytes(bnz); |
385 | if (Zlen > Ztmplen) | |
386 | goto err; | |
387 | if((Ztmp = OPENSSL_zalloc(Ztmplen)) == NULL) | |
388 | goto err; | |
389 | if((Z = OPENSSL_zalloc(Ztmplen)) == NULL) | |
390 | goto err; | |
61f6774e | 391 | if(!BN_bn2binpad(bnz, Z, Ztmplen)) |
0f113f3e | 392 | goto err; |
0f113f3e MC |
393 | if (!ECDH_compute_key(Ztmp, Ztmplen, |
394 | EC_KEY_get0_public_key(key2), key1, 0)) | |
395 | goto err; | |
b438f0ed | 396 | if (memcmp(Ztmp, Z, Ztmplen)) |
0f113f3e | 397 | goto err; |
b438f0ed | 398 | memset(Ztmp, 0, Ztmplen); |
0f113f3e MC |
399 | if (!ECDH_compute_key(Ztmp, Ztmplen, |
400 | EC_KEY_get0_public_key(key1), key2, 0)) | |
401 | goto err; | |
b438f0ed | 402 | if (memcmp(Ztmp, Z, Ztmplen)) |
0f113f3e MC |
403 | goto err; |
404 | rv = 1; | |
405 | err: | |
8fdc3734 RS |
406 | EC_KEY_free(key1); |
407 | EC_KEY_free(key2); | |
b548a1f1 | 408 | OPENSSL_free(Ztmp); |
b438f0ed BB |
409 | OPENSSL_free(Z); |
410 | BN_free(bnz); | |
0f113f3e MC |
411 | if (rv) |
412 | BIO_puts(out, " ok\n"); | |
413 | else { | |
414 | fprintf(stderr, "Error in ECDH routines\n"); | |
415 | ERR_print_errors_fp(stderr); | |
416 | } | |
417 | return rv; | |
418 | } | |
e172d60d | 419 | |
61f6774e BB |
420 | #include "ecdhtest_cavs.h" |
421 | ||
0543603a BB |
422 | /* |
423 | * NIST SP800-56A co-factor ECDH tests. | |
424 | * KATs taken from NIST documents with parameters: | |
425 | * | |
426 | * - (QCAVSx,QCAVSy) is the public key for CAVS. | |
427 | * - dIUT is the private key for IUT. | |
428 | * - (QIUTx,QIUTy) is the public key for IUT. | |
429 | * - ZIUT is the shared secret KAT. | |
430 | * | |
431 | * CAVS: Cryptographic Algorithm Validation System | |
432 | * IUT: Implementation Under Test | |
433 | * | |
434 | * This function tests two things: | |
435 | * | |
436 | * 1. dIUT * G = (QIUTx,QIUTy) | |
437 | * i.e. public key for IUT computes correctly. | |
438 | * 2. x-coord of cofactor * dIUT * (QCAVSx,QCAVSy) = ZIUT | |
439 | * i.e. co-factor ECDH key computes correctly. | |
440 | * | |
441 | * returns zero on failure or unsupported curve. One otherwise. | |
442 | */ | |
61f6774e BB |
443 | static int ecdh_cavs_kat(BIO *out, const ecdh_cavs_kat_t *kat) |
444 | { | |
445 | int rv = 0, is_char_two = 0; | |
446 | EC_KEY *key1 = NULL; | |
447 | EC_POINT *pub = NULL; | |
448 | const EC_GROUP *group = NULL; | |
449 | BIGNUM *bnz = NULL, *x = NULL, *y = NULL; | |
450 | unsigned char *Ztmp = NULL, *Z = NULL; | |
451 | size_t Ztmplen, Zlen; | |
452 | BIO_puts(out, "Testing ECC CDH Primitive SP800-56A with "); | |
453 | BIO_puts(out, OBJ_nid2sn(kat->nid)); | |
454 | ||
455 | /* dIUT is IUT's private key */ | |
456 | if ((key1 = mk_eckey(kat->nid, kat->dIUT)) == NULL) | |
457 | goto err; | |
458 | /* these are cofactor ECDH KATs */ | |
459 | EC_KEY_set_flags(key1, EC_FLAG_COFACTOR_ECDH); | |
460 | ||
461 | if ((group = EC_KEY_get0_group(key1)) == NULL) | |
462 | goto err; | |
463 | if ((pub = EC_POINT_new(group)) == NULL) | |
464 | goto err; | |
465 | ||
466 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_characteristic_two_field) | |
467 | is_char_two = 1; | |
468 | ||
469 | /* (QIUTx, QIUTy) is IUT's public key */ | |
470 | if(!BN_hex2bn(&x, kat->QIUTx)) | |
471 | goto err; | |
472 | if(!BN_hex2bn(&y, kat->QIUTy)) | |
473 | goto err; | |
474 | if (is_char_two) { | |
0543603a BB |
475 | #ifdef OPENSSL_NO_EC2M |
476 | goto err; | |
477 | #else | |
61f6774e | 478 | if (!EC_POINT_set_affine_coordinates_GF2m(group, pub, x, y, NULL)) |
61f6774e | 479 | goto err; |
a67788c1 | 480 | #endif |
61f6774e BB |
481 | } |
482 | else { | |
483 | if (!EC_POINT_set_affine_coordinates_GFp(group, pub, x, y, NULL)) | |
484 | goto err; | |
485 | } | |
486 | /* dIUT * G = (QIUTx, QIUTy) should hold */ | |
487 | if (EC_POINT_cmp(group, EC_KEY_get0_public_key(key1), pub, NULL)) | |
488 | goto err; | |
489 | ||
490 | /* (QCAVSx, QCAVSy) is CAVS's public key */ | |
491 | if(!BN_hex2bn(&x, kat->QCAVSx)) | |
492 | goto err; | |
493 | if(!BN_hex2bn(&y, kat->QCAVSy)) | |
494 | goto err; | |
495 | if (is_char_two) { | |
0543603a BB |
496 | #ifdef OPENSSL_NO_EC2M |
497 | goto err; | |
498 | #else | |
61f6774e | 499 | if (!EC_POINT_set_affine_coordinates_GF2m(group, pub, x, y, NULL)) |
61f6774e | 500 | goto err; |
a67788c1 | 501 | #endif |
61f6774e BB |
502 | } |
503 | else { | |
504 | if (!EC_POINT_set_affine_coordinates_GFp(group, pub, x, y, NULL)) | |
505 | goto err; | |
506 | } | |
507 | ||
508 | /* ZIUT is the shared secret */ | |
509 | if(!BN_hex2bn(&bnz, kat->ZIUT)) | |
510 | goto err; | |
511 | Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8; | |
512 | Zlen = BN_num_bytes(bnz); | |
513 | if (Zlen > Ztmplen) | |
514 | goto err; | |
515 | if((Ztmp = OPENSSL_zalloc(Ztmplen)) == NULL) | |
516 | goto err; | |
517 | if((Z = OPENSSL_zalloc(Ztmplen)) == NULL) | |
518 | goto err; | |
519 | if(!BN_bn2binpad(bnz, Z, Ztmplen)) | |
520 | goto err; | |
521 | if (!ECDH_compute_key(Ztmp, Ztmplen, pub, key1, 0)) | |
522 | goto err; | |
523 | /* shared secrets should be identical */ | |
524 | if (memcmp(Ztmp, Z, Ztmplen)) | |
525 | goto err; | |
526 | rv = 1; | |
527 | err: | |
528 | EC_KEY_free(key1); | |
529 | EC_POINT_free(pub); | |
530 | BN_free(bnz); | |
531 | BN_free(x); | |
532 | BN_free(y); | |
533 | OPENSSL_free(Ztmp); | |
534 | OPENSSL_free(Z); | |
0543603a | 535 | if (rv) { |
61f6774e | 536 | BIO_puts(out, " ok\n"); |
0543603a | 537 | } |
61f6774e BB |
538 | else { |
539 | fprintf(stderr, "Error in ECC CDH routines\n"); | |
540 | ERR_print_errors_fp(stderr); | |
541 | } | |
542 | return rv; | |
543 | } | |
544 | ||
0f113f3e MC |
545 | int main(int argc, char *argv[]) |
546 | { | |
547 | BN_CTX *ctx = NULL; | |
b438f0ed BB |
548 | int nid, ret = 1; |
549 | EC_builtin_curve *curves = NULL; | |
550 | size_t crv_len = 0, n = 0; | |
0f113f3e MC |
551 | BIO *out; |
552 | ||
bbd86bf5 | 553 | CRYPTO_set_mem_debug(1); |
0f113f3e MC |
554 | CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); |
555 | ||
0f113f3e MC |
556 | RAND_seed(rnd_seed, sizeof rnd_seed); |
557 | ||
558 | out = BIO_new(BIO_s_file()); | |
559 | if (out == NULL) | |
560 | EXIT(1); | |
0f81f5f7 | 561 | BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); |
0f113f3e MC |
562 | |
563 | if ((ctx = BN_CTX_new()) == NULL) | |
564 | goto err; | |
565 | ||
b438f0ed BB |
566 | /* get a list of all internal curves */ |
567 | crv_len = EC_get_builtin_curves(NULL, 0); | |
568 | curves = OPENSSL_malloc(sizeof(*curves) * crv_len); | |
569 | if (curves == NULL) goto err; | |
570 | ||
571 | if (!EC_get_builtin_curves(curves, crv_len)) goto err; | |
572 | ||
573 | /* NAMED CURVES TESTS */ | |
574 | for (n = 0; n < crv_len; n++) { | |
575 | nid = curves[n].nid; | |
4a5bbc4e DSH |
576 | /* |
577 | * Skipped for X25519 because affine coordinate operations are not | |
578 | * supported for this curve. | |
579 | * Higher level ECDH tests are performed in evptests.txt instead. | |
580 | */ | |
581 | if (nid == NID_X25519) | |
582 | continue; | |
b438f0ed BB |
583 | if (!test_ecdh_curve(nid, ctx, out)) goto err; |
584 | } | |
585 | ||
586 | /* KATs */ | |
587 | for (n = 0; n < (sizeof(ecdh_kats)/sizeof(ecdh_kat_t)); n++) { | |
588 | if (!ecdh_kat(out, &ecdh_kats[n])) | |
589 | goto err; | |
590 | } | |
0f113f3e | 591 | |
61f6774e BB |
592 | /* NIST SP800-56A co-factor ECDH KATs */ |
593 | for (n = 0; n < (sizeof(ecdh_cavs_kats)/sizeof(ecdh_cavs_kat_t)); n++) { | |
594 | if (!ecdh_cavs_kat(out, &ecdh_cavs_kats[n])) | |
595 | goto err; | |
596 | } | |
597 | ||
0f113f3e MC |
598 | ret = 0; |
599 | ||
600 | err: | |
601 | ERR_print_errors_fp(stderr); | |
b438f0ed | 602 | OPENSSL_free(curves); |
23a1d5e9 | 603 | BN_CTX_free(ctx); |
0f113f3e | 604 | BIO_free(out); |
8793f012 | 605 | |
c2e27310 | 606 | #ifndef OPENSSL_NO_CRYPTO_MDEBUG |
541e9565 DSH |
607 | if (CRYPTO_mem_leaks_fp(stderr) <= 0) |
608 | ret = 1; | |
bbd86bf5 | 609 | #endif |
0f113f3e | 610 | EXIT(ret); |
0f113f3e | 611 | } |
c787525a | 612 | #endif |