+
+ /* 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",
+ ecdh_c[testnum][0],
+ test_curves_bits[testnum], ECDH_SECONDS);
+ Time_F(START);
+ count =
+ run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs);
+ d = Time_F(STOP);
+ BIO_printf(bio_err,
+ 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;
+ rsa_count = count;