1 /* crypto/ecdh/ecdhtest.c */
2 /* ====================================================================
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
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.
9 * The ECC Code is licensed pursuant to the OpenSSL open source
10 * license provided below.
12 * The ECDH software is originally written by Douglas Stebila of
13 * Sun Microsystems Laboratories.
16 /* ====================================================================
17 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
45 * 6. Redistributions of any form whatsoever must retain the following
47 * "This product includes software developed by the OpenSSL Project
48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
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).
76 #include <openssl/opensslconf.h> /* for OPENSSL_NO_ECDH */
77 #include <openssl/crypto.h>
78 #include <openssl/bio.h>
79 #include <openssl/bn.h>
80 #include <openssl/objects.h>
81 #include <openssl/rand.h>
82 #include <openssl/sha.h>
83 #include <openssl/err.h>
85 #ifdef OPENSSL_NO_ECDH
86 int main(int argc, char *argv[])
88 printf("No ECDH support\n");
92 # include <openssl/ec.h>
93 # include <openssl/ecdh.h>
96 static void cb(int p, int n, void *arg);
99 static const char rnd_seed[] =
100 "string to make the random number generator think it has entropy";
102 static const int KDF1_SHA1_len = 20;
103 static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
106 if (*outlen < SHA_DIGEST_LENGTH)
108 *outlen = SHA_DIGEST_LENGTH;
109 return SHA1(in, inlen, out);
112 static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
116 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
118 unsigned char *abuf = NULL, *bbuf = NULL;
119 int i, alen, blen, aout, bout, ret = 0;
120 const EC_GROUP *group;
122 a = EC_KEY_new_by_curve_name(nid);
123 b = EC_KEY_new_by_curve_name(nid);
124 if (a == NULL || b == NULL)
127 group = EC_KEY_get0_group(a);
129 if ((x_a = BN_new()) == NULL)
131 if ((y_a = BN_new()) == NULL)
133 if ((x_b = BN_new()) == NULL)
135 if ((y_b = BN_new()) == NULL)
138 BIO_puts(out, "Testing key generation with ");
143 (void)BIO_flush(out);
146 if (!EC_KEY_generate_key(a))
149 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
150 NID_X9_62_prime_field) {
151 if (!EC_POINT_get_affine_coordinates_GFp
152 (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
155 # ifndef OPENSSL_NO_EC2M
157 if (!EC_POINT_get_affine_coordinates_GF2m(group,
158 EC_KEY_get0_public_key(a),
164 BIO_puts(out, " pri 1=");
165 BN_print(out, a->priv_key);
166 BIO_puts(out, "\n pub 1=");
172 BIO_printf(out, " .");
173 (void)BIO_flush(out);
176 if (!EC_KEY_generate_key(b))
179 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
180 NID_X9_62_prime_field) {
181 if (!EC_POINT_get_affine_coordinates_GFp
182 (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
185 # ifndef OPENSSL_NO_EC2M
187 if (!EC_POINT_get_affine_coordinates_GF2m(group,
188 EC_KEY_get0_public_key(b),
195 BIO_puts(out, " pri 2=");
196 BN_print(out, b->priv_key);
197 BIO_puts(out, "\n pub 2=");
203 BIO_printf(out, ".");
204 (void)BIO_flush(out);
207 alen = KDF1_SHA1_len;
208 abuf = (unsigned char *)OPENSSL_malloc(alen);
210 ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
213 BIO_puts(out, " key1 =");
214 for (i = 0; i < aout; i++) {
215 sprintf(buf, "%02X", abuf[i]);
220 BIO_printf(out, ".");
221 (void)BIO_flush(out);
224 blen = KDF1_SHA1_len;
225 bbuf = (unsigned char *)OPENSSL_malloc(blen);
227 ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
230 BIO_puts(out, " key2 =");
231 for (i = 0; i < bout; i++) {
232 sprintf(buf, "%02X", bbuf[i]);
237 BIO_printf(out, ".");
238 (void)BIO_flush(out);
241 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
243 BIO_printf(out, " failed\n\n");
244 BIO_printf(out, "key a:\n");
245 BIO_printf(out, "private key: ");
246 BN_print(out, EC_KEY_get0_private_key(a));
247 BIO_printf(out, "\n");
248 BIO_printf(out, "public key (x,y): ");
250 BIO_printf(out, ",");
252 BIO_printf(out, "\nkey b:\n");
253 BIO_printf(out, "private key: ");
254 BN_print(out, EC_KEY_get0_private_key(b));
255 BIO_printf(out, "\n");
256 BIO_printf(out, "public key (x,y): ");
258 BIO_printf(out, ",");
260 BIO_printf(out, "\n");
261 BIO_printf(out, "generated key a: ");
262 for (i = 0; i < bout; i++) {
263 sprintf(buf, "%02X", bbuf[i]);
266 BIO_printf(out, "\n");
267 BIO_printf(out, "generated key b: ");
268 for (i = 0; i < aout; i++) {
269 sprintf(buf, "%02X", abuf[i]);
272 BIO_printf(out, "\n");
274 fprintf(stderr, "Error in ECDH routines\n");
278 BIO_printf(out, " ok\n");
283 ERR_print_errors_fp(stderr);
304 /* Keys and shared secrets from RFC 7027 */
306 static const unsigned char bp256_da[] = {
307 0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
308 0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
309 0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
312 static const unsigned char bp256_db[] = {
313 0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
314 0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
315 0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
318 static const unsigned char bp256_Z[] = {
319 0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
320 0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
321 0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
324 static const unsigned char bp384_da[] = {
325 0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
326 0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
327 0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
328 0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
331 static const unsigned char bp384_db[] = {
332 0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
333 0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
334 0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
335 0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
338 static const unsigned char bp384_Z[] = {
339 0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
340 0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
341 0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
342 0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
345 static const unsigned char bp512_da[] = {
346 0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
347 0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
348 0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
349 0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
350 0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
351 0x57, 0x66, 0x54, 0x22
354 static const unsigned char bp512_db[] = {
355 0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
356 0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
357 0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
358 0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
359 0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
360 0x66, 0xB2, 0x54, 0x29
363 static const unsigned char bp512_Z[] = {
364 0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
365 0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
366 0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
367 0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
368 0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
369 0x21, 0xC4, 0xCD, 0x1F
372 /* Given private value and NID, create EC_KEY structure */
374 static EC_KEY *mk_eckey(int nid, const unsigned char *p, size_t plen)
379 EC_POINT *pub = NULL;
381 k = EC_KEY_new_by_curve_name(nid);
384 priv = BN_bin2bn(p, plen, NULL);
387 if (!EC_KEY_set_private_key(k, priv))
389 grp = EC_KEY_get0_group(k);
390 pub = EC_POINT_new(grp);
393 if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
395 if (!EC_KEY_set_public_key(k, pub))
411 * Known answer test: compute shared secret and check it matches expected
415 static int ecdh_kat(BIO *out, const char *cname, int nid,
416 const unsigned char *k1, size_t k1_len,
417 const unsigned char *k2, size_t k2_len,
418 const unsigned char *Z, size_t Zlen)
421 EC_KEY *key1 = NULL, *key2 = NULL;
422 unsigned char *Ztmp = NULL;
424 BIO_puts(out, "Testing ECDH shared secret with ");
425 BIO_puts(out, cname);
426 key1 = mk_eckey(nid, k1, k1_len);
427 key2 = mk_eckey(nid, k2, k2_len);
430 Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8;
433 Ztmp = OPENSSL_malloc(Ztmplen);
434 if (!ECDH_compute_key(Ztmp, Ztmplen,
435 EC_KEY_get0_public_key(key2), key1, 0))
437 if (memcmp(Ztmp, Z, Zlen))
439 memset(Ztmp, 0, Zlen);
440 if (!ECDH_compute_key(Ztmp, Ztmplen,
441 EC_KEY_get0_public_key(key1), key2, 0))
443 if (memcmp(Ztmp, Z, Zlen))
454 BIO_puts(out, " ok\n");
456 fprintf(stderr, "Error in ECDH routines\n");
457 ERR_print_errors_fp(stderr);
462 # define test_ecdh_kat(bio, curve, bits) \
463 ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
464 bp##bits##_da, sizeof(bp##bits##_da), \
465 bp##bits##_db, sizeof(bp##bits##_db), \
466 bp##bits##_Z, sizeof(bp##bits##_Z))
468 int main(int argc, char *argv[])
474 CRYPTO_malloc_debug_init();
475 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
476 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
478 # ifdef OPENSSL_SYS_WIN32
479 CRYPTO_malloc_init();
482 RAND_seed(rnd_seed, sizeof rnd_seed);
484 out = BIO_new(BIO_s_file());
487 BIO_set_fp(out, stdout, BIO_NOCLOSE);
489 if ((ctx = BN_CTX_new()) == NULL)
492 /* NIST PRIME CURVES TESTS */
494 (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
496 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
499 (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
501 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
503 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
505 # ifndef OPENSSL_NO_EC2M
506 /* NIST BINARY CURVES TESTS */
507 if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
509 if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
511 if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
513 if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
515 if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
517 if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
519 if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
521 if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
523 if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
525 if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
528 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
530 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
532 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
538 ERR_print_errors_fp(stderr);
542 CRYPTO_cleanup_all_ex_data();
543 ERR_remove_thread_state(NULL);
544 CRYPTO_mem_leaks_fp(stderr);
549 static void cb(int p, int n, void *arg)
561 BIO_write((BIO *)arg, &c, 1);
562 (void)BIO_flush((BIO *)arg);