1 /* ====================================================================
2 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
5 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
6 * to the OpenSSL project.
8 * The ECC Code is licensed pursuant to the OpenSSL open source
9 * license provided below.
11 * The ECDH software is originally written by Douglas Stebila of
12 * Sun Microsystems Laboratories.
15 /* ====================================================================
16 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
30 * 3. All advertising materials mentioning features or use of this
31 * software must display the following acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
36 * endorse or promote products derived from this software without
37 * prior written permission. For written permission, please contact
38 * openssl-core@openssl.org.
40 * 5. Products derived from this software may not be called "OpenSSL"
41 * nor may "OpenSSL" appear in their names without prior written
42 * permission of the OpenSSL Project.
44 * 6. Redistributions of any form whatsoever must retain the following
46 * "This product includes software developed by the OpenSSL Project
47 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
50 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
53 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
60 * OF THE POSSIBILITY OF SUCH DAMAGE.
61 * ====================================================================
63 * This product includes cryptographic software written by Eric Young
64 * (eay@cryptsoft.com). This product includes software written by Tim
65 * Hudson (tjh@cryptsoft.com).
75 #include <openssl/opensslconf.h> /* for OPENSSL_NO_EC */
76 #include <openssl/crypto.h>
77 #include <openssl/bio.h>
78 #include <openssl/bn.h>
79 #include <openssl/objects.h>
80 #include <openssl/rand.h>
81 #include <openssl/sha.h>
82 #include <openssl/err.h>
85 int main(int argc, char *argv[])
87 printf("No ECDH support\n");
91 # include <openssl/ec.h>
93 static const char rnd_seed[] =
94 "string to make the random number generator think it has entropy";
96 static const int KDF1_SHA1_len = 20;
97 static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
100 if (*outlen < SHA_DIGEST_LENGTH)
102 *outlen = SHA_DIGEST_LENGTH;
103 return SHA1(in, inlen, out);
106 static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out)
110 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
112 unsigned char *abuf = NULL, *bbuf = NULL;
113 int i, alen, blen, aout, bout, ret = 0;
114 const EC_GROUP *group;
116 a = EC_KEY_new_by_curve_name(nid);
117 b = EC_KEY_new_by_curve_name(nid);
118 if (a == NULL || b == NULL)
121 group = EC_KEY_get0_group(a);
123 if ((x_a = BN_new()) == NULL)
125 if ((y_a = BN_new()) == NULL)
127 if ((x_b = BN_new()) == NULL)
129 if ((y_b = BN_new()) == NULL)
132 BIO_puts(out, "Testing key generation with ");
137 (void)BIO_flush(out);
140 if (!EC_KEY_generate_key(a))
143 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
144 NID_X9_62_prime_field) {
145 if (!EC_POINT_get_affine_coordinates_GFp
146 (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
149 # ifndef OPENSSL_NO_EC2M
151 if (!EC_POINT_get_affine_coordinates_GF2m(group,
152 EC_KEY_get0_public_key(a),
158 BIO_puts(out, " pri 1=");
159 BN_print(out, a->priv_key);
160 BIO_puts(out, "\n pub 1=");
166 BIO_printf(out, " .");
167 (void)BIO_flush(out);
170 if (!EC_KEY_generate_key(b))
173 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
174 NID_X9_62_prime_field) {
175 if (!EC_POINT_get_affine_coordinates_GFp
176 (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
179 # ifndef OPENSSL_NO_EC2M
181 if (!EC_POINT_get_affine_coordinates_GF2m(group,
182 EC_KEY_get0_public_key(b),
189 BIO_puts(out, " pri 2=");
190 BN_print(out, b->priv_key);
191 BIO_puts(out, "\n pub 2=");
197 BIO_printf(out, ".");
198 (void)BIO_flush(out);
201 alen = KDF1_SHA1_len;
202 abuf = OPENSSL_malloc(alen);
204 ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);
207 BIO_puts(out, " key1 =");
208 for (i = 0; i < aout; i++) {
209 sprintf(buf, "%02X", abuf[i]);
214 BIO_printf(out, ".");
215 (void)BIO_flush(out);
218 blen = KDF1_SHA1_len;
219 bbuf = OPENSSL_malloc(blen);
221 ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);
224 BIO_puts(out, " key2 =");
225 for (i = 0; i < bout; i++) {
226 sprintf(buf, "%02X", bbuf[i]);
231 BIO_printf(out, ".");
232 (void)BIO_flush(out);
235 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
237 BIO_printf(out, " failed\n\n");
238 BIO_printf(out, "key a:\n");
239 BIO_printf(out, "private key: ");
240 BN_print(out, EC_KEY_get0_private_key(a));
241 BIO_printf(out, "\n");
242 BIO_printf(out, "public key (x,y): ");
244 BIO_printf(out, ",");
246 BIO_printf(out, "\nkey b:\n");
247 BIO_printf(out, "private key: ");
248 BN_print(out, EC_KEY_get0_private_key(b));
249 BIO_printf(out, "\n");
250 BIO_printf(out, "public key (x,y): ");
252 BIO_printf(out, ",");
254 BIO_printf(out, "\n");
255 BIO_printf(out, "generated key a: ");
256 for (i = 0; i < bout; i++) {
257 sprintf(buf, "%02X", bbuf[i]);
260 BIO_printf(out, "\n");
261 BIO_printf(out, "generated key b: ");
262 for (i = 0; i < aout; i++) {
263 sprintf(buf, "%02X", abuf[i]);
266 BIO_printf(out, "\n");
268 fprintf(stderr, "Error in ECDH routines\n");
272 BIO_printf(out, " ok\n");
277 ERR_print_errors_fp(stderr);
290 /* Keys and shared secrets from RFC 7027 */
292 static const unsigned char bp256_da[] = {
293 0x81, 0xDB, 0x1E, 0xE1, 0x00, 0x15, 0x0F, 0xF2, 0xEA, 0x33, 0x8D, 0x70,
294 0x82, 0x71, 0xBE, 0x38, 0x30, 0x0C, 0xB5, 0x42, 0x41, 0xD7, 0x99, 0x50,
295 0xF7, 0x7B, 0x06, 0x30, 0x39, 0x80, 0x4F, 0x1D
298 static const unsigned char bp256_db[] = {
299 0x55, 0xE4, 0x0B, 0xC4, 0x1E, 0x37, 0xE3, 0xE2, 0xAD, 0x25, 0xC3, 0xC6,
300 0x65, 0x45, 0x11, 0xFF, 0xA8, 0x47, 0x4A, 0x91, 0xA0, 0x03, 0x20, 0x87,
301 0x59, 0x38, 0x52, 0xD3, 0xE7, 0xD7, 0x6B, 0xD3
304 static const unsigned char bp256_Z[] = {
305 0x89, 0xAF, 0xC3, 0x9D, 0x41, 0xD3, 0xB3, 0x27, 0x81, 0x4B, 0x80, 0x94,
306 0x0B, 0x04, 0x25, 0x90, 0xF9, 0x65, 0x56, 0xEC, 0x91, 0xE6, 0xAE, 0x79,
307 0x39, 0xBC, 0xE3, 0x1F, 0x3A, 0x18, 0xBF, 0x2B
310 static const unsigned char bp384_da[] = {
311 0x1E, 0x20, 0xF5, 0xE0, 0x48, 0xA5, 0x88, 0x6F, 0x1F, 0x15, 0x7C, 0x74,
312 0xE9, 0x1B, 0xDE, 0x2B, 0x98, 0xC8, 0xB5, 0x2D, 0x58, 0xE5, 0x00, 0x3D,
313 0x57, 0x05, 0x3F, 0xC4, 0xB0, 0xBD, 0x65, 0xD6, 0xF1, 0x5E, 0xB5, 0xD1,
314 0xEE, 0x16, 0x10, 0xDF, 0x87, 0x07, 0x95, 0x14, 0x36, 0x27, 0xD0, 0x42
317 static const unsigned char bp384_db[] = {
318 0x03, 0x26, 0x40, 0xBC, 0x60, 0x03, 0xC5, 0x92, 0x60, 0xF7, 0x25, 0x0C,
319 0x3D, 0xB5, 0x8C, 0xE6, 0x47, 0xF9, 0x8E, 0x12, 0x60, 0xAC, 0xCE, 0x4A,
320 0xCD, 0xA3, 0xDD, 0x86, 0x9F, 0x74, 0xE0, 0x1F, 0x8B, 0xA5, 0xE0, 0x32,
321 0x43, 0x09, 0xDB, 0x6A, 0x98, 0x31, 0x49, 0x7A, 0xBA, 0xC9, 0x66, 0x70
324 static const unsigned char bp384_Z[] = {
325 0x0B, 0xD9, 0xD3, 0xA7, 0xEA, 0x0B, 0x3D, 0x51, 0x9D, 0x09, 0xD8, 0xE4,
326 0x8D, 0x07, 0x85, 0xFB, 0x74, 0x4A, 0x6B, 0x35, 0x5E, 0x63, 0x04, 0xBC,
327 0x51, 0xC2, 0x29, 0xFB, 0xBC, 0xE2, 0x39, 0xBB, 0xAD, 0xF6, 0x40, 0x37,
328 0x15, 0xC3, 0x5D, 0x4F, 0xB2, 0xA5, 0x44, 0x4F, 0x57, 0x5D, 0x4F, 0x42
331 static const unsigned char bp512_da[] = {
332 0x16, 0x30, 0x2F, 0xF0, 0xDB, 0xBB, 0x5A, 0x8D, 0x73, 0x3D, 0xAB, 0x71,
333 0x41, 0xC1, 0xB4, 0x5A, 0xCB, 0xC8, 0x71, 0x59, 0x39, 0x67, 0x7F, 0x6A,
334 0x56, 0x85, 0x0A, 0x38, 0xBD, 0x87, 0xBD, 0x59, 0xB0, 0x9E, 0x80, 0x27,
335 0x96, 0x09, 0xFF, 0x33, 0x3E, 0xB9, 0xD4, 0xC0, 0x61, 0x23, 0x1F, 0xB2,
336 0x6F, 0x92, 0xEE, 0xB0, 0x49, 0x82, 0xA5, 0xF1, 0xD1, 0x76, 0x4C, 0xAD,
337 0x57, 0x66, 0x54, 0x22
340 static const unsigned char bp512_db[] = {
341 0x23, 0x0E, 0x18, 0xE1, 0xBC, 0xC8, 0x8A, 0x36, 0x2F, 0xA5, 0x4E, 0x4E,
342 0xA3, 0x90, 0x20, 0x09, 0x29, 0x2F, 0x7F, 0x80, 0x33, 0x62, 0x4F, 0xD4,
343 0x71, 0xB5, 0xD8, 0xAC, 0xE4, 0x9D, 0x12, 0xCF, 0xAB, 0xBC, 0x19, 0x96,
344 0x3D, 0xAB, 0x8E, 0x2F, 0x1E, 0xBA, 0x00, 0xBF, 0xFB, 0x29, 0xE4, 0xD7,
345 0x2D, 0x13, 0xF2, 0x22, 0x45, 0x62, 0xF4, 0x05, 0xCB, 0x80, 0x50, 0x36,
346 0x66, 0xB2, 0x54, 0x29
349 static const unsigned char bp512_Z[] = {
350 0xA7, 0x92, 0x70, 0x98, 0x65, 0x5F, 0x1F, 0x99, 0x76, 0xFA, 0x50, 0xA9,
351 0xD5, 0x66, 0x86, 0x5D, 0xC5, 0x30, 0x33, 0x18, 0x46, 0x38, 0x1C, 0x87,
352 0x25, 0x6B, 0xAF, 0x32, 0x26, 0x24, 0x4B, 0x76, 0xD3, 0x64, 0x03, 0xC0,
353 0x24, 0xD7, 0xBB, 0xF0, 0xAA, 0x08, 0x03, 0xEA, 0xFF, 0x40, 0x5D, 0x3D,
354 0x24, 0xF1, 0x1A, 0x9B, 0x5C, 0x0B, 0xEF, 0x67, 0x9F, 0xE1, 0x45, 0x4B,
355 0x21, 0xC4, 0xCD, 0x1F
358 /* Given private value and NID, create EC_KEY structure */
360 static EC_KEY *mk_eckey(int nid, const unsigned char *p, size_t plen)
365 EC_POINT *pub = NULL;
367 k = EC_KEY_new_by_curve_name(nid);
370 priv = BN_bin2bn(p, plen, NULL);
373 if (!EC_KEY_set_private_key(k, priv))
375 grp = EC_KEY_get0_group(k);
376 pub = EC_POINT_new(grp);
379 if (!EC_POINT_mul(grp, pub, priv, NULL, NULL, NULL))
381 if (!EC_KEY_set_public_key(k, pub))
394 * Known answer test: compute shared secret and check it matches expected
398 static int ecdh_kat(BIO *out, const char *cname, int nid,
399 const unsigned char *k1, size_t k1_len,
400 const unsigned char *k2, size_t k2_len,
401 const unsigned char *Z, size_t Zlen)
404 EC_KEY *key1 = NULL, *key2 = NULL;
405 unsigned char *Ztmp = NULL;
407 BIO_puts(out, "Testing ECDH shared secret with ");
408 BIO_puts(out, cname);
409 key1 = mk_eckey(nid, k1, k1_len);
410 key2 = mk_eckey(nid, k2, k2_len);
413 Ztmplen = (EC_GROUP_get_degree(EC_KEY_get0_group(key1)) + 7) / 8;
416 Ztmp = OPENSSL_malloc(Ztmplen);
417 if (!ECDH_compute_key(Ztmp, Ztmplen,
418 EC_KEY_get0_public_key(key2), key1, 0))
420 if (memcmp(Ztmp, Z, Zlen))
422 memset(Ztmp, 0, Zlen);
423 if (!ECDH_compute_key(Ztmp, Ztmplen,
424 EC_KEY_get0_public_key(key1), key2, 0))
426 if (memcmp(Ztmp, Z, Zlen))
434 BIO_puts(out, " ok\n");
436 fprintf(stderr, "Error in ECDH routines\n");
437 ERR_print_errors_fp(stderr);
442 # define test_ecdh_kat(bio, curve, bits) \
443 ecdh_kat(bio, curve, NID_brainpoolP##bits##r1, \
444 bp##bits##_da, sizeof(bp##bits##_da), \
445 bp##bits##_db, sizeof(bp##bits##_db), \
446 bp##bits##_Z, sizeof(bp##bits##_Z))
448 int main(int argc, char *argv[])
454 CRYPTO_set_mem_debug(1);
455 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
457 RAND_seed(rnd_seed, sizeof rnd_seed);
459 out = BIO_new(BIO_s_file());
462 BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
464 if ((ctx = BN_CTX_new()) == NULL)
467 /* NIST PRIME CURVES TESTS */
469 (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out))
471 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out))
474 (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out))
476 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out))
478 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out))
480 # ifndef OPENSSL_NO_EC2M
481 /* NIST BINARY CURVES TESTS */
482 if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out))
484 if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out))
486 if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out))
488 if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out))
490 if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out))
492 if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out))
494 if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out))
496 if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out))
498 if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out))
500 if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out))
503 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP256r1", 256))
505 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP384r1", 384))
507 if (!test_ecdh_kat(out, "Brainpool Prime-Curve brainpoolP512r1", 512))
513 ERR_print_errors_fp(stderr);
516 CRYPTO_cleanup_all_ex_data();
517 ERR_remove_thread_state(NULL);
518 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
519 CRYPTO_mem_leaks_fp(stderr);