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;
/* ******************************************************************** */
static long ecdh_c[EC_NUM][1];
-static int ECDH_EVP_derive_key(unsigned char *derived_secret,
- size_t *outlen, EVP_PKEY_CTX *ctx)
-{
- int rt = 1;
- if ((rt = EVP_PKEY_derive(ctx, derived_secret, outlen)) <= 0) {
- BIO_printf(bio_err, "ECDH EVP_PKEY_derive failure: returned %d\n", rt);
- ERR_print_errors(bio_err);
- return rt;
- }
- return rt;
-}
-
static int ECDH_EVP_derive_key_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
int count;
size_t *outlen = &(tempargs->outlen[testnum]);
- for (count = 0; COND(ecdh_c[testnum][0]); count++) {
- if (!ECDH_EVP_derive_key(derived_secret, outlen, ctx))
- break;
- }
+ for (count = 0; COND(ecdh_c[testnum][0]); count++)
+ EVP_PKEY_derive(ctx, derived_secret, outlen);
+
return count;
}
continue;
for (i = 0; i < loopargs_len; i++) {
- EVP_PKEY_CTX *kctx = NULL, *ctx = NULL;
- EVP_PKEY *key_A = NULL, *key_B = NULL;
+ 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 */
test_curves
[testnum]) ||
/* Create the parameter object params */
- !EVP_PKEY_paramgen(pctx, ¶ms) || 0) {
+ !EVP_PKEY_paramgen(pctx, ¶ms)) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH init failure.\n");
ERR_print_errors(bio_err);
pctx = NULL;
}
if (!kctx || /* keygen ctx is not null */
- !EVP_PKEY_keygen_init(kctx) || /* init keygen ctx */
- 0) {
+ !EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH keygen failure.\n");
ERR_print_errors(bio_err);
!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 > MAX_ECDH_SIZE || /* avoid buffer overflow */
- 0) {
+ 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");
ERR_print_errors(bio_err);
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",