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>
95 static const char rnd_seed[] =
96 "string to make the random number generator think it has entropy";
98 static const int KDF1_SHA1_len = 20;
99 static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
102 if (*outlen < SHA_DIGEST_LENGTH)
104 *outlen = SHA_DIGEST_LENGTH;
105 return SHA1(in, inlen, out);
108 static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
112 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
114 unsigned char *abuf = NULL, *bbuf = NULL;
115 int i, alen, blen, aout, bout, ret = 0;
116 const EC_GROUP *group;
118 a = EC_KEY_new_by_curve_name(nid);
119 b = EC_KEY_new_by_curve_name(nid);
120 if (a == NULL || b == NULL)
123 group = EC_KEY_get0_group(a);
125 if ((x_a = BN_new()) == NULL)
127 if ((y_a = BN_new()) == NULL)
129 if ((x_b = BN_new()) == NULL)
131 if ((y_b = BN_new()) == NULL)
134 BIO_puts(out, "Testing key generation with ");
139 (void)BIO_flush(out);
142 if (!EC_KEY_generate_key(a))
145 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
146 NID_X9_62_prime_field) {
147 if (!EC_POINT_get_affine_coordinates_GFp
148 (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
151 # ifndef OPENSSL_NO_EC2M
153 if (!EC_POINT_get_affine_coordinates_GF2m(group,
154 EC_KEY_get0_public_key(a),
160 BIO_puts(out, " pri 1=");
161 BN_print(out, a->priv_key);
162 BIO_puts(out, "\n pub 1=");
168 BIO_printf(out, " .");
169 (void)BIO_flush(out);
172 if (!EC_KEY_generate_key(b))
175 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
176 NID_X9_62_prime_field) {
177 if (!EC_POINT_get_affine_coordinates_GFp
178 (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
181 # ifndef OPENSSL_NO_EC2M
183 if (!EC_POINT_get_affine_coordinates_GF2m(group,
184 EC_KEY_get0_public_key(b),
191 BIO_puts(out, " pri 2=");
192 BN_print(out, b->priv_key);
193 BIO_puts(out, "\n pub 2=");
199 BIO_printf(out, ".");
200 (void)BIO_flush(out);
203 alen = KDF1_SHA1_len;
204 abuf = (unsigned char *)OPENSSL_malloc(alen);
206 ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
209 BIO_puts(out, " key1 =");
210 for (i = 0; i < aout; i++) {
211 sprintf(buf, "%02X", abuf[i]);
216 BIO_printf(out, ".");
217 (void)BIO_flush(out);
220 blen = KDF1_SHA1_len;
221 bbuf = (unsigned char *)OPENSSL_malloc(blen);
223 ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
226 BIO_puts(out, " key2 =");
227 for (i = 0; i < bout; i++) {
228 sprintf(buf, "%02X", bbuf[i]);
233 BIO_printf(out, ".");
234 (void)BIO_flush(out);
237 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
239 BIO_printf(out, " failed\n\n");
240 BIO_printf(out, "key a:\n");
241 BIO_printf(out, "private key: ");
242 BN_print(out, EC_KEY_get0_private_key(a));
243 BIO_printf(out, "\n");
244 BIO_printf(out, "public key (x,y): ");
246 BIO_printf(out, ",");
248 BIO_printf(out, "\nkey b:\n");
249 BIO_printf(out, "private key: ");
250 BN_print(out, EC_KEY_get0_private_key(b));
251 BIO_printf(out, "\n");
252 BIO_printf(out, "public key (x,y): ");
254 BIO_printf(out, ",");
256 BIO_printf(out, "\n");
257 BIO_printf(out, "generated key a: ");
258 for (i = 0; i < bout; i++) {
259 sprintf(buf, "%02X", bbuf[i]);
262 BIO_printf(out, "\n");
263 BIO_printf(out, "generated key b: ");
264 for (i = 0; i < aout; i++) {
265 sprintf(buf, "%02X", abuf[i]);
268 BIO_printf(out, "\n");
270 fprintf(stderr, "Error in ECDH routines\n");
274 BIO_printf(out, " ok\n");
279 ERR_print_errors_fp(stderr);
300 /* Keys and shared secrets from RFC 7027 */
302 static const unsigned char bp256_da[] = {
303 0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
304 0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
305 0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
308 static const unsigned char bp256_db[] = {
309 0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
310 0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
311 0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
314 static const unsigned char bp256_Z[] = {
315 0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
316 0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
317 0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
320 static const unsigned char bp384_da[] = {
321 0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
322 0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
323 0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
324 0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
327 static const unsigned char bp384_db[] = {
328 0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
329 0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
330 0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
331 0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
334 static const unsigned char bp384_Z[] = {
335 0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
336 0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
337 0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
338 0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
341 static const unsigned char bp512_da[] = {
342 0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
343 0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
344 0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
345 0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
346 0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
347 0x57, 0x66, 0x54, 0x22
350 static const unsigned char bp512_db[] = {
351 0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
352 0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
353 0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
354 0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
355 0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
356 0x66, 0xB2, 0x54, 0x29
359 static const unsigned char bp512_Z[] = {
360 0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
361 0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
362 0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
363 0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
364 0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
365 0x21, 0xC4, 0xCD, 0x1F
368 /* Given private value and NID, create EC_KEY structure */
370 static EC_KEY *mk_eckey(int nid, const unsigned char *p, size_t plen)
375 EC_POINT *pub = NULL;
377 k = EC_KEY_new_by_curve_name(nid);
380 priv = BN_bin2bn(p, plen, NULL);
383 if (!EC_KEY_set_private_key(k, priv))
385 grp = EC_KEY_get0_group(k);
386 pub = EC_POINT_new(grp);
389 if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
391 if (!EC_KEY_set_public_key(k, pub))
407 * Known answer test: compute shared secret and check it matches expected
411 static int ecdh_kat(BIO *out, const char *cname, int nid,
412 const unsigned char *k1, size_t k1_len,
413 const unsigned char *k2, size_t k2_len,
414 const unsigned char *Z, size_t Zlen)
417 EC_KEY *key1 = NULL, *key2 = NULL;
418 unsigned char *Ztmp = NULL;
420 BIO_puts(out, "Testing ECDH shared secret with ");
421 BIO_puts(out, cname);
422 key1 = mk_eckey(nid, k1, k1_len);
423 key2 = mk_eckey(nid, k2, k2_len);
426 Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8;
429 Ztmp = OPENSSL_malloc(Ztmplen);
430 if (!ECDH_compute_key(Ztmp, Ztmplen,
431 EC_KEY_get0_public_key(key2), key1, 0))
433 if (memcmp(Ztmp, Z, Zlen))
435 memset(Ztmp, 0, Zlen);
436 if (!ECDH_compute_key(Ztmp, Ztmplen,
437 EC_KEY_get0_public_key(key1), key2, 0))
439 if (memcmp(Ztmp, Z, Zlen))
450 BIO_puts(out, " ok\n");
452 fprintf(stderr, "Error in ECDH routines\n");
453 ERR_print_errors_fp(stderr);
458 # define test_ecdh_kat(bio, curve, bits) \
459 ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
460 bp##bits##_da, sizeof(bp##bits##_da), \
461 bp##bits##_db, sizeof(bp##bits##_db), \
462 bp##bits##_Z, sizeof(bp##bits##_Z))
464 int main(int argc, char *argv[])
470 CRYPTO_malloc_debug_init();
471 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
472 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
474 # ifdef OPENSSL_SYS_WIN32
475 CRYPTO_malloc_init();
478 RAND_seed(rnd_seed, sizeof rnd_seed);
480 out = BIO_new(BIO_s_file());
483 BIO_set_fp(out, stdout, BIO_NOCLOSE);
485 if ((ctx = BN_CTX_new()) == NULL)
488 /* NIST PRIME CURVES TESTS */
490 (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
492 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
495 (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
497 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
499 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
501 # ifndef OPENSSL_NO_EC2M
502 /* NIST BINARY CURVES TESTS */
503 if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
505 if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
507 if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
509 if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
511 if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
513 if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
515 if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
517 if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
519 if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
521 if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
524 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
526 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
528 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
534 ERR_print_errors_fp(stderr);
538 CRYPTO_cleanup_all_ex_data();
539 ERR_remove_thread_state(NULL);
540 CRYPTO_mem_leaks_fp(stderr);