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_EC */
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>
86 int main(int argc, char *argv[])
88 printf("No ECDH support\n");
92 # include <openssl/ec.h>
94 static const char rnd_seed[] =
95 "string to make the random number generator think it has entropy";
97 static const int KDF1_SHA1_len = 20;
98 static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
101 if (*outlen < SHA_DIGEST_LENGTH)
103 *outlen = SHA_DIGEST_LENGTH;
104 return SHA1(in, inlen, out);
107 static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
111 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
113 unsigned char *abuf = NULL, *bbuf = NULL;
114 int i, alen, blen, aout, bout, ret = 0;
115 const EC_GROUP *group;
117 a = EC_KEY_new_by_curve_name(nid);
118 b = EC_KEY_new_by_curve_name(nid);
119 if (a == NULL || b == NULL)
122 group = EC_KEY_get0_group(a);
124 if ((x_a = BN_new()) == NULL)
126 if ((y_a = BN_new()) == NULL)
128 if ((x_b = BN_new()) == NULL)
130 if ((y_b = BN_new()) == NULL)
133 BIO_puts(out, "Testing key generation with ");
138 (void)BIO_flush(out);
141 if (!EC_KEY_generate_key(a))
144 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
145 NID_X9_62_prime_field) {
146 if (!EC_POINT_get_affine_coordinates_GFp
147 (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
150 # ifndef OPENSSL_NO_EC2M
152 if (!EC_POINT_get_affine_coordinates_GF2m(group,
153 EC_KEY_get0_public_key(a),
159 BIO_puts(out, " pri 1=");
160 BN_print(out, a->priv_key);
161 BIO_puts(out, "\n pub 1=");
167 BIO_printf(out, " .");
168 (void)BIO_flush(out);
171 if (!EC_KEY_generate_key(b))
174 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
175 NID_X9_62_prime_field) {
176 if (!EC_POINT_get_affine_coordinates_GFp
177 (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
180 # ifndef OPENSSL_NO_EC2M
182 if (!EC_POINT_get_affine_coordinates_GF2m(group,
183 EC_KEY_get0_public_key(b),
190 BIO_puts(out, " pri 2=");
191 BN_print(out, b->priv_key);
192 BIO_puts(out, "\n pub 2=");
198 BIO_printf(out, ".");
199 (void)BIO_flush(out);
202 alen = KDF1_SHA1_len;
203 abuf = OPENSSL_malloc(alen);
205 ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
208 BIO_puts(out, " key1 =");
209 for (i = 0; i < aout; i++) {
210 sprintf(buf, "%02X", abuf[i]);
215 BIO_printf(out, ".");
216 (void)BIO_flush(out);
219 blen = KDF1_SHA1_len;
220 bbuf = OPENSSL_malloc(blen);
222 ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
225 BIO_puts(out, " key2 =");
226 for (i = 0; i < bout; i++) {
227 sprintf(buf, "%02X", bbuf[i]);
232 BIO_printf(out, ".");
233 (void)BIO_flush(out);
236 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
238 BIO_printf(out, " failed\n\n");
239 BIO_printf(out, "key a:\n");
240 BIO_printf(out, "private key: ");
241 BN_print(out, EC_KEY_get0_private_key(a));
242 BIO_printf(out, "\n");
243 BIO_printf(out, "public key (x,y): ");
245 BIO_printf(out, ",");
247 BIO_printf(out, "\nkey b:\n");
248 BIO_printf(out, "private key: ");
249 BN_print(out, EC_KEY_get0_private_key(b));
250 BIO_printf(out, "\n");
251 BIO_printf(out, "public key (x,y): ");
253 BIO_printf(out, ",");
255 BIO_printf(out, "\n");
256 BIO_printf(out, "generated key a: ");
257 for (i = 0; i < bout; i++) {
258 sprintf(buf, "%02X", bbuf[i]);
261 BIO_printf(out, "\n");
262 BIO_printf(out, "generated key b: ");
263 for (i = 0; i < aout; i++) {
264 sprintf(buf, "%02X", abuf[i]);
267 BIO_printf(out, "\n");
269 fprintf(stderr, "Error in ECDH routines\n");
273 BIO_printf(out, " ok\n");
278 ERR_print_errors_fp(stderr);
291 /* Keys and shared secrets from RFC 7027 */
293 static const unsigned char bp256_da[] = {
294 0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
295 0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
296 0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
299 static const unsigned char bp256_db[] = {
300 0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
301 0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
302 0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
305 static const unsigned char bp256_Z[] = {
306 0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
307 0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
308 0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
311 static const unsigned char bp384_da[] = {
312 0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
313 0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
314 0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
315 0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
318 static const unsigned char bp384_db[] = {
319 0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
320 0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
321 0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
322 0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
325 static const unsigned char bp384_Z[] = {
326 0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
327 0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
328 0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
329 0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
332 static const unsigned char bp512_da[] = {
333 0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
334 0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
335 0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
336 0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
337 0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
338 0x57, 0x66, 0x54, 0x22
341 static const unsigned char bp512_db[] = {
342 0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
343 0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
344 0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
345 0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
346 0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
347 0x66, 0xB2, 0x54, 0x29
350 static const unsigned char bp512_Z[] = {
351 0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
352 0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
353 0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
354 0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
355 0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
356 0x21, 0xC4, 0xCD, 0x1F
359 /* Given private value and NID, create EC_KEY structure */
361 static EC_KEY *mk_eckey(int nid, const unsigned char *p, size_t plen)
366 EC_POINT *pub = NULL;
368 k = EC_KEY_new_by_curve_name(nid);
371 priv = BN_bin2bn(p, plen, NULL);
374 if (!EC_KEY_set_private_key(k, priv))
376 grp = EC_KEY_get0_group(k);
377 pub = EC_POINT_new(grp);
380 if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
382 if (!EC_KEY_set_public_key(k, pub))
395 * Known answer test: compute shared secret and check it matches expected
399 static int ecdh_kat(BIO *out, const char *cname, int nid,
400 const unsigned char *k1, size_t k1_len,
401 const unsigned char *k2, size_t k2_len,
402 const unsigned char *Z, size_t Zlen)
405 EC_KEY *key1 = NULL, *key2 = NULL;
406 unsigned char *Ztmp = NULL;
408 BIO_puts(out, "Testing ECDH shared secret with ");
409 BIO_puts(out, cname);
410 key1 = mk_eckey(nid, k1, k1_len);
411 key2 = mk_eckey(nid, k2, k2_len);
414 Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8;
417 Ztmp = OPENSSL_malloc(Ztmplen);
418 if (!ECDH_compute_key(Ztmp, Ztmplen,
419 EC_KEY_get0_public_key(key2), key1, 0))
421 if (memcmp(Ztmp, Z, Zlen))
423 memset(Ztmp, 0, Zlen);
424 if (!ECDH_compute_key(Ztmp, Ztmplen,
425 EC_KEY_get0_public_key(key1), key2, 0))
427 if (memcmp(Ztmp, Z, Zlen))
435 BIO_puts(out, " ok\n");
437 fprintf(stderr, "Error in ECDH routines\n");
438 ERR_print_errors_fp(stderr);
443 # define test_ecdh_kat(bio, curve, bits) \
444 ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
445 bp##bits##_da, sizeof(bp##bits##_da), \
446 bp##bits##_db, sizeof(bp##bits##_db), \
447 bp##bits##_Z, sizeof(bp##bits##_Z))
449 int main(int argc, char *argv[])
455 CRYPTO_malloc_debug_init();
456 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
457 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
459 # ifdef OPENSSL_SYS_WIN32
460 CRYPTO_malloc_init();
463 RAND_seed(rnd_seed, sizeof rnd_seed);
465 out = BIO_new(BIO_s_file());
468 BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
470 if ((ctx = BN_CTX_new()) == NULL)
473 /* NIST PRIME CURVES TESTS */
475 (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
477 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
480 (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
482 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
484 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
486 # ifndef OPENSSL_NO_EC2M
487 /* NIST BINARY CURVES TESTS */
488 if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
490 if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
492 if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
494 if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
496 if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
498 if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
500 if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
502 if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
504 if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
506 if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
509 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
511 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
513 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
519 ERR_print_errors_fp(stderr);
522 CRYPTO_cleanup_all_ex_data();
523 ERR_remove_thread_state(NULL);
524 CRYPTO_mem_leaks_fp(stderr);