ecdhtest.c revision 296341
1/* crypto/ecdh/ecdhtest.c */ 2/* ==================================================================== 3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 4 * 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. 8 * 9 * The ECC Code is licensed pursuant to the OpenSSL open source 10 * license provided below. 11 * 12 * The ECDH software is originally written by Douglas Stebila of 13 * Sun Microsystems Laboratories. 14 * 15 */ 16/* ==================================================================== 17 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 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 29 * distribution. 30 * 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/)" 35 * 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. 40 * 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. 44 * 45 * 6. Redistributions of any form whatsoever must retain the following 46 * acknowledgment: 47 * "This product includes software developed by the OpenSSL Project 48 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 49 * 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 * ==================================================================== 63 * 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). 67 * 68 */ 69 70#include <stdio.h> 71#include <stdlib.h> 72#include <string.h> 73 74#include "../e_os.h" 75 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> 84 85#ifdef OPENSSL_NO_ECDH 86int main(int argc, char *argv[]) 87{ 88 printf("No ECDH support\n"); 89 return (0); 90} 91#else 92# include <openssl/ec.h> 93# include <openssl/ecdh.h> 94 95# ifdef OPENSSL_SYS_WIN16 96# define MS_CALLBACK _far _loadds 97# else 98# define MS_CALLBACK 99# endif 100 101# if 0 102static void MS_CALLBACK cb(int p, int n, void *arg); 103# endif 104 105static const char rnd_seed[] = 106 "string to make the random number generator think it has entropy"; 107 108static const int KDF1_SHA1_len = 20; 109static void *KDF1_SHA1(const void *in, size_t inlen, void *out, 110 size_t *outlen) 111{ 112# ifndef OPENSSL_NO_SHA 113 if (*outlen < SHA_DIGEST_LENGTH) 114 return NULL; 115 else 116 *outlen = SHA_DIGEST_LENGTH; 117 return SHA1(in, inlen, out); 118# else 119 return NULL; 120# endif 121} 122 123static int test_ecdh_curve(int nid, const char *text, BN_CTX *ctx, BIO *out) 124{ 125 EC_KEY *a = NULL; 126 EC_KEY *b = NULL; 127 BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL; 128 char buf[12]; 129 unsigned char *abuf = NULL, *bbuf = NULL; 130 int i, alen, blen, aout, bout, ret = 0; 131 const EC_GROUP *group; 132 133 a = EC_KEY_new_by_curve_name(nid); 134 b = EC_KEY_new_by_curve_name(nid); 135 if (a == NULL || b == NULL) 136 goto err; 137 138 group = EC_KEY_get0_group(a); 139 140 if ((x_a = BN_new()) == NULL) 141 goto err; 142 if ((y_a = BN_new()) == NULL) 143 goto err; 144 if ((x_b = BN_new()) == NULL) 145 goto err; 146 if ((y_b = BN_new()) == NULL) 147 goto err; 148 149 BIO_puts(out, "Testing key generation with "); 150 BIO_puts(out, text); 151# ifdef NOISY 152 BIO_puts(out, "\n"); 153# else 154 (void)BIO_flush(out); 155# endif 156 157 if (!EC_KEY_generate_key(a)) 158 goto err; 159 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)) 164 goto err; 165 } 166# ifndef OPENSSL_NO_EC2M 167 else { 168 if (!EC_POINT_get_affine_coordinates_GF2m(group, 169 EC_KEY_get0_public_key(a), 170 x_a, y_a, ctx)) 171 goto err; 172 } 173# endif 174# ifdef NOISY 175 BIO_puts(out, " pri 1="); 176 BN_print(out, a->priv_key); 177 BIO_puts(out, "\n pub 1="); 178 BN_print(out, x_a); 179 BIO_puts(out, ","); 180 BN_print(out, y_a); 181 BIO_puts(out, "\n"); 182# else 183 BIO_printf(out, " ."); 184 (void)BIO_flush(out); 185# endif 186 187 if (!EC_KEY_generate_key(b)) 188 goto err; 189 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)) 194 goto err; 195 } 196# ifndef OPENSSL_NO_EC2M 197 else { 198 if (!EC_POINT_get_affine_coordinates_GF2m(group, 199 EC_KEY_get0_public_key(b), 200 x_b, y_b, ctx)) 201 goto err; 202 } 203# endif 204 205# ifdef NOISY 206 BIO_puts(out, " pri 2="); 207 BN_print(out, b->priv_key); 208 BIO_puts(out, "\n pub 2="); 209 BN_print(out, x_b); 210 BIO_puts(out, ","); 211 BN_print(out, y_b); 212 BIO_puts(out, "\n"); 213# else 214 BIO_printf(out, "."); 215 (void)BIO_flush(out); 216# endif 217 218 alen = KDF1_SHA1_len; 219 abuf = (unsigned char *)OPENSSL_malloc(alen); 220 aout = 221 ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1); 222 223# ifdef NOISY 224 BIO_puts(out, " key1 ="); 225 for (i = 0; i < aout; i++) { 226 sprintf(buf, "%02X", abuf[i]); 227 BIO_puts(out, buf); 228 } 229 BIO_puts(out, "\n"); 230# else 231 BIO_printf(out, "."); 232 (void)BIO_flush(out); 233# endif 234 235 blen = KDF1_SHA1_len; 236 bbuf = (unsigned char *)OPENSSL_malloc(blen); 237 bout = 238 ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1); 239 240# ifdef NOISY 241 BIO_puts(out, " key2 ="); 242 for (i = 0; i < bout; i++) { 243 sprintf(buf, "%02X", bbuf[i]); 244 BIO_puts(out, buf); 245 } 246 BIO_puts(out, "\n"); 247# else 248 BIO_printf(out, "."); 249 (void)BIO_flush(out); 250# endif 251 252 if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { 253# ifndef NOISY 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): "); 260 BN_print(out, x_a); 261 BIO_printf(out, ","); 262 BN_print(out, y_a); 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): "); 268 BN_print(out, x_b); 269 BIO_printf(out, ","); 270 BN_print(out, y_b); 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]); 275 BIO_puts(out, buf); 276 } 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]); 281 BIO_puts(out, buf); 282 } 283 BIO_printf(out, "\n"); 284# endif 285 fprintf(stderr, "Error in ECDH routines\n"); 286 ret = 0; 287 } else { 288# ifndef NOISY 289 BIO_printf(out, " ok\n"); 290# endif 291 ret = 1; 292 } 293 err: 294 ERR_print_errors_fp(stderr); 295 296 if (abuf != NULL) 297 OPENSSL_free(abuf); 298 if (bbuf != NULL) 299 OPENSSL_free(bbuf); 300 if (x_a) 301 BN_free(x_a); 302 if (y_a) 303 BN_free(y_a); 304 if (x_b) 305 BN_free(x_b); 306 if (y_b) 307 BN_free(y_b); 308 if (b) 309 EC_KEY_free(b); 310 if (a) 311 EC_KEY_free(a); 312 return (ret); 313} 314 315int main(int argc, char *argv[]) 316{ 317 BN_CTX *ctx = NULL; 318 int ret = 1; 319 BIO *out; 320 321 CRYPTO_malloc_debug_init(); 322 CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); 323 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 324 325# ifdef OPENSSL_SYS_WIN32 326 CRYPTO_malloc_init(); 327# endif 328 329 RAND_seed(rnd_seed, sizeof rnd_seed); 330 331 out = BIO_new(BIO_s_file()); 332 if (out == NULL) 333 EXIT(1); 334 BIO_set_fp(out, stdout, BIO_NOCLOSE); 335 336 if ((ctx = BN_CTX_new()) == NULL) 337 goto err; 338 339 /* NIST PRIME CURVES TESTS */ 340 if (!test_ecdh_curve 341 (NID_X9_62_prime192v1, "NIST Prime-Curve P-192", ctx, out)) 342 goto err; 343 if (!test_ecdh_curve(NID_secp224r1, "NIST Prime-Curve P-224", ctx, out)) 344 goto err; 345 if (!test_ecdh_curve 346 (NID_X9_62_prime256v1, "NIST Prime-Curve P-256", ctx, out)) 347 goto err; 348 if (!test_ecdh_curve(NID_secp384r1, "NIST Prime-Curve P-384", ctx, out)) 349 goto err; 350 if (!test_ecdh_curve(NID_secp521r1, "NIST Prime-Curve P-521", ctx, out)) 351 goto err; 352# ifndef OPENSSL_NO_EC2M 353 /* NIST BINARY CURVES TESTS */ 354 if (!test_ecdh_curve(NID_sect163k1, "NIST Binary-Curve K-163", ctx, out)) 355 goto err; 356 if (!test_ecdh_curve(NID_sect163r2, "NIST Binary-Curve B-163", ctx, out)) 357 goto err; 358 if (!test_ecdh_curve(NID_sect233k1, "NIST Binary-Curve K-233", ctx, out)) 359 goto err; 360 if (!test_ecdh_curve(NID_sect233r1, "NIST Binary-Curve B-233", ctx, out)) 361 goto err; 362 if (!test_ecdh_curve(NID_sect283k1, "NIST Binary-Curve K-283", ctx, out)) 363 goto err; 364 if (!test_ecdh_curve(NID_sect283r1, "NIST Binary-Curve B-283", ctx, out)) 365 goto err; 366 if (!test_ecdh_curve(NID_sect409k1, "NIST Binary-Curve K-409", ctx, out)) 367 goto err; 368 if (!test_ecdh_curve(NID_sect409r1, "NIST Binary-Curve B-409", ctx, out)) 369 goto err; 370 if (!test_ecdh_curve(NID_sect571k1, "NIST Binary-Curve K-571", ctx, out)) 371 goto err; 372 if (!test_ecdh_curve(NID_sect571r1, "NIST Binary-Curve B-571", ctx, out)) 373 goto err; 374# endif 375 376 ret = 0; 377 378 err: 379 ERR_print_errors_fp(stderr); 380 if (ctx) 381 BN_CTX_free(ctx); 382 BIO_free(out); 383 CRYPTO_cleanup_all_ex_data(); 384 ERR_remove_thread_state(NULL); 385 CRYPTO_mem_leaks_fp(stderr); 386 EXIT(ret); 387 return (ret); 388} 389 390# if 0 391static void MS_CALLBACK cb(int p, int n, void *arg) 392{ 393 char c = '*'; 394 395 if (p == 0) 396 c = '.'; 397 if (p == 1) 398 c = '+'; 399 if (p == 2) 400 c = '*'; 401 if (p == 3) 402 c = '\n'; 403 BIO_write((BIO *)arg, &c, 1); 404 (void)BIO_flush((BIO *)arg); 405# ifdef LINT 406 p = n; 407# endif 408} 409# endif 410#endif 411