xref: /openbsd-src/regress/lib/libcrypto/ecdh/ecdhtest.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*	$OpenBSD: ecdhtest.c,v 1.10 2018/07/17 17:06:49 tb Exp $	*/
2 /* ====================================================================
3  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4  *
5  * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6  * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7  * to the OpenSSL project.
8  *
9  * The ECC Code is licensed pursuant to the OpenSSL open source
10  * license provided below.
11  *
12  * The ECDH software is originally written by Douglas Stebila of
13  * Sun Microsystems Laboratories.
14  *
15  */
16 /* ====================================================================
17  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  *
23  * 1. Redistributions of source code must retain the above copyright
24  *    notice, this list of conditions and the following disclaimer.
25  *
26  * 2. Redistributions in binary form must reproduce the above copyright
27  *    notice, this list of conditions and the following disclaimer in
28  *    the documentation and/or other materials provided with the
29  *    distribution.
30  *
31  * 3. All advertising materials mentioning features or use of this
32  *    software must display the following acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35  *
36  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37  *    endorse or promote products derived from this software without
38  *    prior written permission. For written permission, please contact
39  *    openssl-core@openssl.org.
40  *
41  * 5. Products derived from this software may not be called "OpenSSL"
42  *    nor may "OpenSSL" appear in their names without prior written
43  *    permission of the OpenSSL Project.
44  *
45  * 6. Redistributions of any form whatsoever must retain the following
46  *    acknowledgment:
47  *    "This product includes software developed by the OpenSSL Project
48  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61  * OF THE POSSIBILITY OF SUCH DAMAGE.
62  * ====================================================================
63  *
64  * This product includes cryptographic software written by Eric Young
65  * (eay@cryptsoft.com).  This product includes software written by Tim
66  * Hudson (tjh@cryptsoft.com).
67  *
68  */
69 
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 
74 #include <openssl/crypto.h>
75 #include <openssl/bio.h>
76 #include <openssl/bn.h>
77 #include <openssl/objects.h>
78 #include <openssl/sha.h>
79 #include <openssl/err.h>
80 
81 #include <openssl/ec.h>
82 #include <openssl/ecdh.h>
83 
84 static const int KDF1_SHA1_len = 20;
85 static void *
86 KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
87 {
88 #ifndef OPENSSL_NO_SHA
89 	if (*outlen < SHA_DIGEST_LENGTH)
90 		return NULL;
91 	else
92 		*outlen = SHA_DIGEST_LENGTH;
93 	return SHA1(in, inlen, out);
94 #else
95 	return NULL;
96 #endif
97 }
98 
99 
100 static int
101 test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
102 {
103 	BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
104 	EC_KEY *a = NULL, *b = NULL;
105 	const EC_GROUP *group;
106 	unsigned char *abuf = NULL, *bbuf = NULL;
107 	int i, alen, blen, aout, bout, ret = 0;
108 	char buf[12];
109 
110 	a = EC_KEY_new_by_curve_name(nid);
111 	b = EC_KEY_new_by_curve_name(nid);
112 	if (a == NULL || b == NULL)
113 		goto err;
114 
115 	group = EC_KEY_get0_group(a);
116 
117 	if ((x_a = BN_new()) == NULL)
118 		goto err;
119 	if ((y_a = BN_new()) == NULL)
120 		goto err;
121 	if ((x_b = BN_new()) == NULL)
122 		goto err;
123 	if ((y_b = BN_new()) == NULL)
124 		goto err;
125 
126 	BIO_puts(out, "Testing key generation with ");
127 	BIO_puts(out, text);
128 	(void)BIO_flush(out);
129 
130 	if (!EC_KEY_generate_key(a))
131 		goto err;
132 
133 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
134 	    NID_X9_62_prime_field) {
135 		if (!EC_POINT_get_affine_coordinates_GFp(group,
136 		    EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err;
137 	}
138 #ifndef OPENSSL_NO_EC2M
139 	else {
140 		if (!EC_POINT_get_affine_coordinates_GF2m(group,
141 		    EC_KEY_get0_public_key(a), x_a, y_a, ctx)) goto err;
142 	}
143 #endif
144 	BIO_printf(out, " .");
145 	(void)BIO_flush(out);
146 
147 	if (!EC_KEY_generate_key(b))
148 		goto err;
149 
150 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
151 	    NID_X9_62_prime_field) {
152 		if (!EC_POINT_get_affine_coordinates_GFp(group,
153 		    EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err;
154 	}
155 #ifndef OPENSSL_NO_EC2M
156 	else {
157 		if (!EC_POINT_get_affine_coordinates_GF2m(group,
158 		    EC_KEY_get0_public_key(b), x_b, y_b, ctx)) goto err;
159 	}
160 #endif
161 
162 	BIO_printf(out, ".");
163 	(void)BIO_flush(out);
164 
165 	alen = KDF1_SHA1_len;
166 	abuf = malloc(alen);
167 	aout = ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b),
168 	    a, KDF1_SHA1);
169 
170 	BIO_printf(out, ".");
171 	(void)BIO_flush(out);
172 
173 	blen = KDF1_SHA1_len;
174 	bbuf = malloc(blen);
175 	bout = ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a),
176 	    b, KDF1_SHA1);
177 
178 	BIO_printf(out, ".");
179 	(void)BIO_flush(out);
180 
181 	if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
182 		BIO_printf(out, " failed\n\n");
183 		BIO_printf(out, "key a:\n");
184 		BIO_printf(out, "private key: ");
185 		BN_print(out, EC_KEY_get0_private_key(a));
186 		BIO_printf(out, "\n");
187 		BIO_printf(out, "public key (x,y): ");
188 		BN_print(out, x_a);
189 		BIO_printf(out, ",");
190 		BN_print(out, y_a);
191 		BIO_printf(out, "\nkey b:\n");
192 		BIO_printf(out, "private key: ");
193 		BN_print(out, EC_KEY_get0_private_key(b));
194 		BIO_printf(out, "\n");
195 		BIO_printf(out, "public key (x,y): ");
196 		BN_print(out, x_b);
197 		BIO_printf(out, ",");
198 		BN_print(out, y_b);
199 		BIO_printf(out, "\n");
200 		BIO_printf(out, "generated key a: ");
201 		for (i = 0; i < bout; i++) {
202 			snprintf(buf, sizeof buf, "%02X", bbuf[i]);
203 			BIO_puts(out, buf);
204 		}
205 		BIO_printf(out, "\n");
206 		BIO_printf(out, "generated key b: ");
207 		for (i = 0; i < aout; i++) {
208 			snprintf(buf, sizeof buf, "%02X", abuf[i]);
209 			BIO_puts(out, buf);
210 		}
211 		BIO_printf(out, "\n");
212 		fprintf(stderr, "Error in ECDH routines\n");
213 		ret = 0;
214 	} else {
215 		BIO_printf(out, " ok\n");
216 		ret = 1;
217 	}
218 
219 err:
220 	ERR_print_errors_fp(stderr);
221 
222 	free(abuf);
223 	free(bbuf);
224 	BN_free(x_a);
225 	BN_free(y_a);
226 	BN_free(x_b);
227 	BN_free(y_b);
228 	EC_KEY_free(b);
229 	EC_KEY_free(a);
230 
231 	return (ret);
232 }
233 
234 /* Keys and shared secrets from RFC 7027 */
235 
236 static const unsigned char bp256_da[] = {
237 	0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
238 	0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
239 	0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
240 };
241 
242 static const unsigned char bp256_db[] = {
243 	0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
244 	0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
245 	0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
246 };
247 
248 static const unsigned char bp256_Z[] = {
249 	0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
250 	0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
251 	0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
252 };
253 
254 static const unsigned char bp384_da[] = {
255 	0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
256 	0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
257 	0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
258 	0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
259 };
260 
261 static const unsigned char bp384_db[] = {
262 	0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
263 	0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
264 	0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
265 	0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
266 };
267 
268 static const unsigned char bp384_Z[] = {
269 	0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
270 	0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
271 	0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
272 	0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
273 };
274 
275 static const unsigned char bp512_da[] = {
276 	0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
277 	0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
278 	0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
279 	0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
280 	0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
281 	0x57, 0x66, 0x54, 0x22
282 };
283 
284 static const unsigned char bp512_db[] = {
285 	0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
286 	0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
287 	0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
288 	0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
289 	0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
290 	0x66, 0xB2, 0x54, 0x29
291 };
292 
293 
294 static const unsigned char bp512_Z[] = {
295 	0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
296 	0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
297 	0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
298 	0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
299 	0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
300 	0x21, 0xC4, 0xCD, 0x1F
301 };
302 
303 /* Given private value and NID, create EC_KEY structure */
304 
305 static EC_KEY *
306 mk_eckey(int nid, const unsigned char *p, size_t plen)
307 {
308 	EC_KEY *k = NULL;
309 	BIGNUM *priv = NULL;
310 	EC_POINT *pub = NULL;
311 	const EC_GROUP *grp;
312 	int ok = 0;
313 
314 	k = EC_KEY_new_by_curve_name(nid);
315 	if (!k)
316 		goto err;
317 	priv = BN_bin2bn(p, plen, NULL);
318 	if (!priv)
319 		goto err;
320 	if (!EC_KEY_set_private_key(k, priv))
321 		goto err;
322 	grp = EC_KEY_get0_group(k);
323 	pub = EC_POINT_new(grp);
324 	if (!pub)
325 		goto err;
326 	if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
327 		goto err;
328 	if (!EC_KEY_set_public_key(k, pub))
329 		goto err;
330 	ok = 1;
331 err:
332 	BN_clear_free(priv);
333 	EC_POINT_free(pub);
334 	if (!ok) {
335 		EC_KEY_free(k);
336 		k = NULL;
337 	}
338 	return (k);
339 }
340 
341 /* Known answer test: compute shared secret and check it matches
342  * expected value.
343  */
344 
345 static int
346 ecdh_kat(BIO *out, const char *cname, int nid,
347     const unsigned char *k1, size_t k1_len,
348     const unsigned char *k2, size_t k2_len,
349     const unsigned char *Z, size_t Zlen)
350 {
351 	int rv = 0;
352 	EC_KEY *key1 = NULL, *key2 = NULL;
353 	unsigned char *Ztmp = NULL;
354 	size_t Ztmplen;
355 	BIO_puts(out, "Testing ECDH shared secret with ");
356 	BIO_puts(out, cname);
357 	key1 = mk_eckey(nid, k1, k1_len);
358 	key2 = mk_eckey(nid, k2, k2_len);
359 	if (!key1 || !key2)
360 		goto err;
361 	Ztmplen = ECDH_size(key1);
362 	if (Ztmplen != Zlen)
363 		goto err;
364 	Ztmp = malloc(Ztmplen);
365 	if (!ECDH_compute_key(Ztmp, Ztmplen,
366 	    EC_KEY_get0_public_key(key2), key1, 0))
367 		goto err;
368 	if (memcmp(Ztmp, Z, Zlen))
369 		goto err;
370 	memset(Ztmp, 0, Zlen);
371 	if (!ECDH_compute_key(Ztmp, Ztmplen,
372 	    EC_KEY_get0_public_key(key1), key2, 0))
373 		goto err;
374 	if (memcmp(Ztmp, Z, Zlen))
375 		goto err;
376 	rv = 1;
377 
378 err:
379 	if (rv)
380 		BIO_puts(out, " ok\n");
381 	else {
382 		fprintf(stderr, "Error in ECDH routines\n");
383 		ERR_print_errors_fp(stderr);
384 	}
385 
386 	EC_KEY_free(key1);
387 	EC_KEY_free(key2);
388 	free(Ztmp);
389 
390 	return rv;
391 }
392 
393 #define test_ecdh_kat(bio, curve, bits) \
394 	ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
395 		bp##bits##_da, sizeof(bp##bits##_da), \
396 		bp##bits##_db, sizeof(bp##bits##_db), \
397 		bp##bits##_Z, sizeof(bp##bits##_Z))
398 
399 int
400 main(int argc, char *argv[])
401 {
402 	BN_CTX *ctx = NULL;
403 	int ret = 1;
404 	BIO *out;
405 
406 	out = BIO_new(BIO_s_file());
407 	if (out == NULL)
408 		exit(1);
409 	BIO_set_fp(out, stdout, BIO_NOCLOSE);
410 
411 	if ((ctx = BN_CTX_new()) == NULL)
412 		goto err;
413 
414 	/* NIST PRIME CURVES TESTS */
415 	if (!test_ecdh_curve(NID_X9_62_prime192v1, "NIST Prime-Curve P-192",
416 	    ctx, out))
417 		goto err;
418 	if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
419 		goto err;
420 	if (!test_ecdh_curve(NID_X9_62_prime256v1, "NIST Prime-Curve P-256",
421 	    ctx, out))
422 		goto err;
423 	if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
424 		goto err;
425 	if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
426 		goto err;
427 #ifndef OPENSSL_NO_EC2M
428 	/* NIST BINARY CURVES TESTS */
429 	if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163",
430 	    ctx, out))
431 		goto err;
432 	if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163",
433 	    ctx, out))
434 		goto err;
435 	if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233",
436 	    ctx, out))
437 		goto err;
438 	if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233",
439 	    ctx, out))
440 		goto err;
441 	if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283",
442 	    ctx, out))
443 		goto err;
444 	if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283",
445 	    ctx, out))
446 		goto err;
447 	if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409",
448 	    ctx, out))
449 		goto err;
450 	if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409",
451 	    ctx, out))
452 		goto err;
453 	if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571",
454 	    ctx, out))
455 		goto err;
456 	if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571",
457 	    ctx, out))
458 		goto err;
459 #endif
460 	if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
461 		goto err;
462 	if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
463 		goto err;
464 	if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
465 		goto err;
466 
467 	ret = 0;
468 
469 err:
470 	ERR_print_errors_fp(stderr);
471 	BN_CTX_free(ctx);
472 	BIO_free(out);
473 	CRYPTO_cleanup_all_ex_data();
474 	ERR_remove_thread_state(NULL);
475 	CRYPTO_mem_leaks_fp(stderr);
476 	exit(ret);
477 }
478