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 # ifdef OPENSSL_SYS_WIN16
96 # define MS_CALLBACK _far _loadds
102 static void MS_CALLBACK cb(int p, int n, void *arg);
105 static const char rnd_seed[] =
106 "string to make the random number generator think it has entropy";
108 static const int KDF1_SHA1_len = 20;
109 static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
112 # ifndef OPENSSL_NO_SHA
113 if (*outlen < SHA_DIGEST_LENGTH)
116 *outlen = SHA_DIGEST_LENGTH;
117 return SHA1(in, inlen, out);
123 static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
127 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
129 unsigned char *abuf = NULL, *bbuf = NULL;
130 int i, alen, blen, aout, bout, ret = 0;
131 const EC_GROUP *group;
133 a = EC_KEY_new_by_curve_name(nid);
134 b = EC_KEY_new_by_curve_name(nid);
135 if (a == NULL || b == NULL)
138 group = EC_KEY_get0_group(a);
140 if ((x_a = BN_new()) == NULL)
142 if ((y_a = BN_new()) == NULL)
144 if ((x_b = BN_new()) == NULL)
146 if ((y_b = BN_new()) == NULL)
149 BIO_puts(out, "Testing key generation with ");
154 (void)BIO_flush(out);
157 if (!EC_KEY_generate_key(a))
160 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
161 NID_X9_62_prime_field) {
162 if (!EC_POINT_get_affine_coordinates_GFp
163 (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
166 # ifndef OPENSSL_NO_EC2M
168 if (!EC_POINT_get_affine_coordinates_GF2m(group,
169 EC_KEY_get0_public_key(a),
175 BIO_puts(out, " pri 1=");
176 BN_print(out, a->priv_key);
177 BIO_puts(out, "\n pub 1=");
183 BIO_printf(out, " .");
184 (void)BIO_flush(out);
187 if (!EC_KEY_generate_key(b))
190 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
191 NID_X9_62_prime_field) {
192 if (!EC_POINT_get_affine_coordinates_GFp
193 (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
196 # ifndef OPENSSL_NO_EC2M
198 if (!EC_POINT_get_affine_coordinates_GF2m(group,
199 EC_KEY_get0_public_key(b),
206 BIO_puts(out, " pri 2=");
207 BN_print(out, b->priv_key);
208 BIO_puts(out, "\n pub 2=");
214 BIO_printf(out, ".");
215 (void)BIO_flush(out);
218 alen = KDF1_SHA1_len;
219 abuf = (unsigned char *)OPENSSL_malloc(alen);
221 ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
224 BIO_puts(out, " key1 =");
225 for (i = 0; i < aout; i++) {
226 sprintf(buf, "%02X", abuf[i]);
231 BIO_printf(out, ".");
232 (void)BIO_flush(out);
235 blen = KDF1_SHA1_len;
236 bbuf = (unsigned char *)OPENSSL_malloc(blen);
238 ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
241 BIO_puts(out, " key2 =");
242 for (i = 0; i < bout; i++) {
243 sprintf(buf, "%02X", bbuf[i]);
248 BIO_printf(out, ".");
249 (void)BIO_flush(out);
252 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
254 BIO_printf(out, " failed\n\n");
255 BIO_printf(out, "key a:\n");
256 BIO_printf(out, "private key: ");
257 BN_print(out, EC_KEY_get0_private_key(a));
258 BIO_printf(out, "\n");
259 BIO_printf(out, "public key (x,y): ");
261 BIO_printf(out, ",");
263 BIO_printf(out, "\nkey b:\n");
264 BIO_printf(out, "private key: ");
265 BN_print(out, EC_KEY_get0_private_key(b));
266 BIO_printf(out, "\n");
267 BIO_printf(out, "public key (x,y): ");
269 BIO_printf(out, ",");
271 BIO_printf(out, "\n");
272 BIO_printf(out, "generated key a: ");
273 for (i = 0; i < bout; i++) {
274 sprintf(buf, "%02X", bbuf[i]);
277 BIO_printf(out, "\n");
278 BIO_printf(out, "generated key b: ");
279 for (i = 0; i < aout; i++) {
280 sprintf(buf, "%02X", abuf[i]);
283 BIO_printf(out, "\n");
285 fprintf(stderr, "Error in ECDH routines\n");
289 BIO_printf(out, " ok\n");
294 ERR_print_errors_fp(stderr);
315 /* Keys and shared secrets from RFC 7027 */
317 static const unsigned char bp256_da[] = {
318 0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
319 0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
320 0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
323 static const unsigned char bp256_db[] = {
324 0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
325 0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
326 0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
329 static const unsigned char bp256_Z[] = {
330 0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
331 0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
332 0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
335 static const unsigned char bp384_da[] = {
336 0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
337 0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
338 0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
339 0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
342 static const unsigned char bp384_db[] = {
343 0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
344 0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
345 0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
346 0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
349 static const unsigned char bp384_Z[] = {
350 0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
351 0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
352 0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
353 0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
356 static const unsigned char bp512_da[] = {
357 0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
358 0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
359 0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
360 0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
361 0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
362 0x57, 0x66, 0x54, 0x22
365 static const unsigned char bp512_db[] = {
366 0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
367 0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
368 0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
369 0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
370 0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
371 0x66, 0xB2, 0x54, 0x29
374 static const unsigned char bp512_Z[] = {
375 0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
376 0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
377 0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
378 0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
379 0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
380 0x21, 0xC4, 0xCD, 0x1F
383 /* Given private value and NID, create EC_KEY structure */
385 static EC_KEY *mk_eckey(int nid, const unsigned char *p, size_t plen)
390 EC_POINT *pub = NULL;
392 k = EC_KEY_new_by_curve_name(nid);
395 priv = BN_bin2bn(p, plen, NULL);
398 if (!EC_KEY_set_private_key(k, priv))
400 grp = EC_KEY_get0_group(k);
401 pub = EC_POINT_new(grp);
404 if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
406 if (!EC_KEY_set_public_key(k, pub))
422 * Known answer test: compute shared secret and check it matches expected
426 static int ecdh_kat(BIO *out, const char *cname, int nid,
427 const unsigned char *k1, size_t k1_len,
428 const unsigned char *k2, size_t k2_len,
429 const unsigned char *Z, size_t Zlen)
432 EC_KEY *key1 = NULL, *key2 = NULL;
433 unsigned char *Ztmp = NULL;
435 BIO_puts(out, "Testing ECDH shared secret with ");
436 BIO_puts(out, cname);
437 key1 = mk_eckey(nid, k1, k1_len);
438 key2 = mk_eckey(nid, k2, k2_len);
441 Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8;
444 Ztmp = OPENSSL_malloc(Ztmplen);
445 if (!ECDH_compute_key(Ztmp, Ztmplen,
446 EC_KEY_get0_public_key(key2), key1, 0))
448 if (memcmp(Ztmp, Z, Zlen))
450 memset(Ztmp, 0, Zlen);
451 if (!ECDH_compute_key(Ztmp, Ztmplen,
452 EC_KEY_get0_public_key(key1), key2, 0))
454 if (memcmp(Ztmp, Z, Zlen))
465 BIO_puts(out, " ok\n");
467 fprintf(stderr, "Error in ECDH routines\n");
468 ERR_print_errors_fp(stderr);
473 # define test_ecdh_kat(bio, curve, bits) \
474 ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
475 bp##bits##_da, sizeof(bp##bits##_da), \
476 bp##bits##_db, sizeof(bp##bits##_db), \
477 bp##bits##_Z, sizeof(bp##bits##_Z))
479 int main(int argc, char *argv[])
485 CRYPTO_malloc_debug_init();
486 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
487 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
489 # ifdef OPENSSL_SYS_WIN32
490 CRYPTO_malloc_init();
493 RAND_seed(rnd_seed, sizeof(rnd_seed));
495 out = BIO_new(BIO_s_file());
498 BIO_set_fp(out, stdout, BIO_NOCLOSE);
500 if ((ctx = BN_CTX_new()) == NULL)
503 /* NIST PRIME CURVES TESTS */
505 (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
507 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
510 (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
512 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
514 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
516 # ifndef OPENSSL_NO_EC2M
517 /* NIST BINARY CURVES TESTS */
518 if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
520 if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
522 if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
524 if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
526 if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
528 if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
530 if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
532 if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
534 if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
536 if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
539 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
541 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
543 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
549 ERR_print_errors_fp(stderr);
553 CRYPTO_cleanup_all_ex_data();
554 ERR_remove_thread_state(NULL);
555 CRYPTO_mem_leaks_fp(stderr);
561 static void MS_CALLBACK cb(int p, int n, void *arg)
573 BIO_write((BIO *)arg, &c, 1);
574 (void)BIO_flush((BIO *)arg);