/*
- * 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
* 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
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;
unsigned char *secret_a;
unsigned char *secret_b;
size_t outlen[EC_NUM];
- kdf_fn kdf;
#endif
EVP_CIPHER_CTX *ctx;
HMAC_CTX *hctx;
#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";
+ "string to make the random number generator think it has randomness";
#endif
#ifdef SIGALRM
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;
}
#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;
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());
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:
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] =
#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
#endif
if (doit[D_EVP]) {
-#ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
if (multiblock && evp_cipher) {
if (!
(EVP_CIPHER_flags(evp_cipher) &
ret = 0;
goto end;
}
-#endif
for (testnum = 0; testnum < SIZE_NUM; testnum++) {
if (evp_cipher) {
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;
}
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) {
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;
}
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) {
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;
}
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) {
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 */
/* 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;
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");
!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");
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",
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;
}
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
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
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;
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
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) {
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
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;
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