X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=apps%2Fspeed.c;h=1fef0d31c0bf4aa1a0ed1309951b7efa941e722a;hb=a8c5ed812d1537728807059b4182d358bb2ca7c1;hp=5a1d92b43c75d0525735c5f93fb0bce07bde7193;hpb=db1dd9368a153d6eac2256f86936207f9d777b32;p=openssl.git diff --git a/apps/speed.c b/apps/speed.c index 5a1d92b43c..1fef0d31c0 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -1,5 +1,6 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,23 +8,8 @@ * https://www.openssl.org/source/license.html */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * - * Portions of the attached software ("Contribution") are developed by - * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. - * - * The Contribution is licensed pursuant to the OpenSSL open source - * license provided above. - * - * The ECDH and ECDSA speed test software is originally written by - * Sumit Gupta of Sun Microsystems Laboratories. - * - */ - #undef SECONDS #define SECONDS 3 -#define PRIME_SECONDS 10 #define RSA_SECONDS 10 #define DSA_SECONDS 10 #define ECDSA_SECONDS 10 @@ -131,7 +117,6 @@ #define ALGOR_NUM 30 #define SIZE_NUM 6 -#define PRIME_NUM 3 #define RSA_NUM 7 #define DSA_NUM 3 @@ -144,9 +129,6 @@ static volatile int run = 0; static int mr = 0; static int usertime = 1; -typedef void *(*kdf_fn) (const void *in, size_t inlen, void *out, - size_t *xoutlen); - typedef struct loopargs_st { ASYNC_JOB *inprogress_job; ASYNC_WAIT_CTX *wait_ctx; @@ -167,7 +149,6 @@ typedef struct loopargs_st { unsigned char *secret_a; unsigned char *secret_b; size_t outlen[EC_NUM]; - kdf_fn kdf; #endif EVP_CIPHER_CTX *ctx; HMAC_CTX *hctx; @@ -264,11 +245,6 @@ static double ecdsa_results[EC_NUM][2]; static double ecdh_results[EC_NUM][1]; #endif -#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC) -static const char rnd_seed[] = - "string to make the random number generator think it has entropy"; -#endif - #ifdef SIGALRM # if defined(__STDC__) || defined(sgi) || defined(_AIX) # define SIGRETTYPE void @@ -292,7 +268,8 @@ static SIGRETTYPE sig_done(int sig) # if !defined(SIGALRM) # define SIGALRM # endif -static unsigned int lapse, schlock; +static unsigned int lapse; +static volatile unsigned int schlock; static void alarm_win32(unsigned int secs) { lapse = secs * 1000; @@ -359,7 +336,7 @@ static int found(const char *name, const OPT_PAIR *pairs, int *result) typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, - OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS + OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM } OPTION_CHOICE; const OPTIONS speed_options[] = { @@ -382,6 +359,7 @@ const OPTIONS speed_options[] = { {"async_jobs", OPT_ASYNCJOBS, 'p', "Enable async mode and start pnum jobs"}, #endif + OPT_R_OPTIONS, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif @@ -1040,11 +1018,8 @@ static int ECDH_EVP_derive_key_loop(void *args) size_t *outlen = &(tempargs->outlen[testnum]); for (count = 0; COND(ecdh_c[testnum][0]); count++) - if (EVP_PKEY_derive(ctx, derived_secret, outlen) <= 0) { - BIO_printf(bio_err, "ECDH EVP_PKEY_derive failure\n"); - ERR_print_errors(bio_err); - break; - } + EVP_PKEY_derive(ctx, derived_secret, outlen); + return count; } @@ -1221,7 +1196,7 @@ int speed_main(int argc, char **argv) #ifndef NO_FORK int multi = 0; #endif - int async_jobs = 0; + unsigned int async_jobs = 0; #if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \ || !defined(OPENSSL_NO_EC) long rsa_count = 1; @@ -1364,6 +1339,7 @@ int speed_main(int argc, char **argv) usertime = 0; break; case OPT_EVP: + evp_md = NULL; evp_cipher = EVP_get_cipherbyname(opt_arg()); if (evp_cipher == NULL) evp_md = EVP_get_digestbyname(opt_arg()); @@ -1400,6 +1376,12 @@ int speed_main(int argc, char **argv) prog); goto opterr; } + if (async_jobs > 99999) { + BIO_printf(bio_err, + "%s: too many async_jobs\n", + prog); + goto opterr; + } #endif break; case OPT_MISALIGN: @@ -1423,6 +1405,10 @@ int speed_main(int argc, char **argv) goto end; #endif break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; } } argc = opt_num_rest(); @@ -1445,12 +1431,8 @@ int speed_main(int argc, char **argv) continue; } #ifndef OPENSSL_NO_RSA -# ifndef RSA_NULL - if (strcmp(*argv, "openssl") == 0) { - RSA_set_default_method(RSA_PKCS1_OpenSSL()); + if (strcmp(*argv, "openssl") == 0) continue; - } -# endif if (strcmp(*argv, "rsa") == 0) { rsa_doit[R_RSA_512] = rsa_doit[R_RSA_1024] = rsa_doit[R_RSA_2048] = rsa_doit[R_RSA_3072] = @@ -1599,9 +1581,9 @@ int speed_main(int argc, char **argv) #endif #ifndef OPENSSL_NO_DSA for (i = 0; i < loopargs_len; i++) { - loopargs[i].dsa_key[0] = get_dsa512(); - loopargs[i].dsa_key[1] = get_dsa1024(); - loopargs[i].dsa_key[2] = get_dsa2048(); + loopargs[i].dsa_key[0] = get_dsa(512); + loopargs[i].dsa_key[1] = get_dsa(1024); + loopargs[i].dsa_key[2] = get_dsa(2048); } #endif #ifndef OPENSSL_NO_DES @@ -2281,7 +2263,6 @@ int speed_main(int argc, char **argv) #endif if (doit[D_EVP]) { -#ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK if (multiblock && evp_cipher) { if (! (EVP_CIPHER_flags(evp_cipher) & @@ -2298,7 +2279,6 @@ int speed_main(int argc, char **argv) ret = 0; goto end; } -#endif for (testnum = 0; testnum < SIZE_NUM; testnum++) { if (evp_cipher) { @@ -2369,7 +2349,7 @@ int speed_main(int argc, char **argv) mr ? "+R1:%ld:%d:%.2f\n" : "%ld %d bit private RSA's in %.2fs\n", count, rsa_bits[testnum], d); - rsa_results[testnum][0] = d / (double)count; + rsa_results[testnum][0] = (double)count / d; rsa_count = count; } @@ -2395,7 +2375,7 @@ int speed_main(int argc, char **argv) mr ? "+R2:%ld:%d:%.2f\n" : "%ld %d bit public RSA's in %.2fs\n", count, rsa_bits[testnum], d); - rsa_results[testnum][1] = d / (double)count; + rsa_results[testnum][1] = (double)count / d; } if (rsa_count <= 1) { @@ -2410,9 +2390,6 @@ int speed_main(int argc, char **argv) RAND_bytes(loopargs[i].buf, 36); #ifndef OPENSSL_NO_DSA - if (RAND_status() != 1) { - RAND_seed(rnd_seed, sizeof rnd_seed); - } for (testnum = 0; testnum < DSA_NUM; testnum++) { int st = 0; if (!dsa_doit[testnum]) @@ -2442,7 +2419,7 @@ int speed_main(int argc, char **argv) mr ? "+R3:%ld:%d:%.2f\n" : "%ld %d bit DSA signs in %.2fs\n", count, dsa_bits[testnum], d); - dsa_results[testnum][0] = d / (double)count; + dsa_results[testnum][0] = (double)count / d; rsa_count = count; } @@ -2468,7 +2445,7 @@ int speed_main(int argc, char **argv) mr ? "+R4:%ld:%d:%.2f\n" : "%ld %d bit DSA verify in %.2fs\n", count, dsa_bits[testnum], d); - dsa_results[testnum][1] = d / (double)count; + dsa_results[testnum][1] = (double)count / d; } if (rsa_count <= 1) { @@ -2480,9 +2457,6 @@ int speed_main(int argc, char **argv) #endif /* OPENSSL_NO_DSA */ #ifndef OPENSSL_NO_EC - if (RAND_status() != 1) { - RAND_seed(rnd_seed, sizeof rnd_seed); - } for (testnum = 0; testnum < EC_NUM; testnum++) { int st = 1; @@ -2528,7 +2502,7 @@ int speed_main(int argc, char **argv) mr ? "+R5:%ld:%d:%.2f\n" : "%ld %d bit ECDSA signs in %.2fs \n", count, test_curves_bits[testnum], d); - ecdsa_results[testnum][0] = d / (double)count; + ecdsa_results[testnum][0] = (double)count / d; rsa_count = count; } @@ -2556,7 +2530,7 @@ int speed_main(int argc, char **argv) mr ? "+R6:%ld:%d:%.2f\n" : "%ld %d bit ECDSA verify in %.2fs\n", count, test_curves_bits[testnum], d); - ecdsa_results[testnum][1] = d / (double)count; + ecdsa_results[testnum][1] = (double)count / d; } if (rsa_count <= 1) { @@ -2567,9 +2541,6 @@ int speed_main(int argc, char **argv) } } - if (RAND_status() != 1) { - RAND_seed(rnd_seed, sizeof rnd_seed); - } for (testnum = 0; testnum < EC_NUM; testnum++) { int ecdh_checks = 1; @@ -2578,17 +2549,50 @@ int speed_main(int argc, char **argv) for (i = 0; i < loopargs_len; i++) { EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY_CTX *test_ctx = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *key_A = NULL; EVP_PKEY *key_B = NULL; size_t outlen; + size_t test_outlen; - if (testnum == R_EC_X25519) { - kctx = EVP_PKEY_CTX_new_id(test_curves[testnum], NULL); /* keygen ctx from NID */ - } else { + /* Ensure that the error queue is empty */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); + ERR_print_errors(bio_err); + } + + /* Let's try to create a ctx directly from the NID: this works for + * curves like Curve25519 that are not implemented through the low + * level EC interface. + * If this fails we try creating a EVP_PKEY_EC generic param ctx, + * then we set the curve by NID before deriving the actual keygen + * ctx for that specific curve. */ + kctx = EVP_PKEY_CTX_new_id(test_curves[testnum], NULL); /* keygen ctx from NID */ + if (!kctx) { EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *params = NULL; + /* If we reach this code EVP_PKEY_CTX_new_id() failed and a + * "int_ctx_new:unsupported algorithm" error was added to the + * error queue. + * We remove it from the error queue as we are handling it. */ + unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */ + if (error == ERR_peek_last_error() && /* oldest and latest errors match */ + /* check that the error origin matches */ + ERR_GET_LIB(error) == ERR_LIB_EVP && + ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW && + ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM) + ERR_get_error(); /* pop error from queue */ + if (ERR_peek_error()) { + BIO_printf(bio_err, + "Unhandled error in the error queue during ECDH init.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + if ( /* Create the context for parameter generation */ !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) || /* Initialise the parameter generation */ @@ -2600,7 +2604,7 @@ int speed_main(int argc, char **argv) /* Create the parameter object params */ !EVP_PKEY_paramgen(pctx, ¶ms)) { ecdh_checks = 0; - BIO_printf(bio_err, "ECDH init failure.\n"); + BIO_printf(bio_err, "ECDH EC params init failure.\n"); ERR_print_errors(bio_err); rsa_count = 1; break; @@ -2613,7 +2617,7 @@ int speed_main(int argc, char **argv) EVP_PKEY_CTX_free(pctx); pctx = NULL; } - if (!kctx || /* keygen ctx is not null */ + if (kctx == NULL || /* keygen ctx is not null */ !EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH keygen failure.\n"); @@ -2628,6 +2632,7 @@ int speed_main(int argc, char **argv) !EVP_PKEY_derive_init(ctx) || /* init derivation ctx */ !EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */ !EVP_PKEY_derive(ctx, NULL, &outlen) || /* determine max length */ + outlen == 0 || /* ensure outlen is a valid size */ outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH key generation failure.\n"); @@ -2636,11 +2641,41 @@ int speed_main(int argc, char **argv) break; } + /* Here we perform a test run, comparing the output of a*B and b*A; + * we try this here and assume that further EVP_PKEY_derive calls + * never fail, so we can skip checks in the actually benchmarked + * code, for maximum performance. */ + if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */ + !EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */ + !EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */ + !EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */ + !EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */ + !EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */ + test_outlen != outlen /* compare output length */ ) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH computation failure.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + + /* Compare the computation results: CRYPTO_memcmp() returns 0 if equal */ + if (CRYPTO_memcmp(loopargs[i].secret_a, + loopargs[i].secret_b, outlen)) { + ecdh_checks = 0; + BIO_printf(bio_err, "ECDH computations don't match.\n"); + ERR_print_errors(bio_err); + rsa_count = 1; + break; + } + loopargs[i].ecdh_ctx[testnum] = ctx; loopargs[i].outlen[testnum] = outlen; EVP_PKEY_CTX_free(kctx); kctx = NULL; + EVP_PKEY_CTX_free(test_ctx); + test_ctx = NULL; } if (ecdh_checks != 0) { pkey_print_message("", "ecdh", @@ -2654,7 +2689,7 @@ int speed_main(int argc, char **argv) mr ? "+R7:%ld:%d:%.2f\n" : "%ld %d-bit ECDH ops in %.2fs\n", count, test_curves_bits[testnum], d); - ecdh_results[testnum][0] = d / (double)count; + ecdh_results[testnum][0] = (double)count / d; rsa_count = count; } @@ -2734,8 +2769,8 @@ int speed_main(int argc, char **argv) k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]); else printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", - rsa_bits[k], rsa_results[k][0], rsa_results[k][1], - 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1]); + rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1], + rsa_results[k][0], rsa_results[k][1]); } #endif #ifndef OPENSSL_NO_DSA @@ -2752,8 +2787,8 @@ int speed_main(int argc, char **argv) k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]); else printf("dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", - dsa_bits[k], dsa_results[k][0], dsa_results[k][1], - 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1]); + dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1], + dsa_results[k][0], dsa_results[k][1]); } #endif #ifndef OPENSSL_NO_EC @@ -2774,8 +2809,8 @@ int speed_main(int argc, char **argv) printf("%4u bit ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n", test_curves_bits[k], test_curves_names[k], - ecdsa_results[k][0], ecdsa_results[k][1], - 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1]); + 1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1], + ecdsa_results[k][0], ecdsa_results[k][1]); } testnum = 1; @@ -2795,7 +2830,7 @@ int speed_main(int argc, char **argv) printf("%4u bit ecdh (%s) %8.4fs %8.1f\n", test_curves_bits[k], test_curves_names[k], - ecdh_results[k][0], 1.0 / ecdh_results[k][0]); + 1.0 / ecdh_results[k][0], ecdh_results[k][0]); } #endif @@ -2982,16 +3017,10 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - rsa_results[k][0] = 1 / (1 / rsa_results[k][0] + 1 / d); - else - rsa_results[k][0] = d; + rsa_results[k][0] += d; d = atof(sstrsep(&p, sep)); - if (n) - rsa_results[k][1] = 1 / (1 / rsa_results[k][1] + 1 / d); - else - rsa_results[k][1] = d; + rsa_results[k][1] += d; } # ifndef OPENSSL_NO_DSA else if (strncmp(buf, "+F3:", 4) == 0) { @@ -3003,16 +3032,10 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - dsa_results[k][0] = 1 / (1 / dsa_results[k][0] + 1 / d); - else - dsa_results[k][0] = d; + dsa_results[k][0] += d; d = atof(sstrsep(&p, sep)); - if (n) - dsa_results[k][1] = 1 / (1 / dsa_results[k][1] + 1 / d); - else - dsa_results[k][1] = d; + dsa_results[k][1] += d; } # endif # ifndef OPENSSL_NO_EC @@ -3025,16 +3048,10 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - ecdsa_results[k][0] = 1 / (1 / ecdsa_results[k][0] + 1 / d); - else - ecdsa_results[k][0] = d; + ecdsa_results[k][0] += d; d = atof(sstrsep(&p, sep)); - if (n) - ecdsa_results[k][1] = 1 / (1 / ecdsa_results[k][1] + 1 / d); - else - ecdsa_results[k][1] = d; + ecdsa_results[k][1] += d; } else if (strncmp(buf, "+F5:", 4) == 0) { int k; double d; @@ -3044,11 +3061,7 @@ static int do_multi(int multi) sstrsep(&p, sep); d = atof(sstrsep(&p, sep)); - if (n) - ecdh_results[k][0] = 1 / (1 / ecdh_results[k][0] + 1 / d); - else - ecdh_results[k][0] = d; - + ecdh_results[k][0] += d; } # endif