Handle EVP_PKEY_derive errors and fix coding style issues
[openssl.git] / apps / speed.c
index 046882fbd63ef6cfaa54eb34f8a7ef4404ef4004..f40f9fa50cef978b745a5070c0fc34a12733eb4c 100644 (file)
@@ -163,8 +163,7 @@ typedef struct loopargs_st {
 #endif
 #ifndef OPENSSL_NO_EC
     EC_KEY *ecdsa[EC_NUM];
-    EC_KEY *ecdh_a[EC_NUM];
-    EC_KEY *ecdh_b[EC_NUM];
+    EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
     unsigned char *secret_a;
     unsigned char *secret_b;
     size_t      outlen;
@@ -225,7 +224,6 @@ static int DSA_verify_loop(void *args);
 #ifndef OPENSSL_NO_EC
 static int ECDSA_sign_loop(void *args);
 static int ECDSA_verify_loop(void *args);
-static int ECDH_compute_key_loop(void *args);
 #endif
 static int run_benchmark(int async_jobs, int (*loop_function)(void *), loopargs_t *loopargs);
 
@@ -1040,33 +1038,34 @@ static int ECDSA_verify_loop(void *args)
 /* ******************************************************************** */
 static long ecdh_c[EC_NUM][1];
 
-static int ECDH_compute_key_loop(void *args)
+static int ECDH_EVP_derive_key(unsigned char *derived_secret,
+                            size_t *outlen,
+                            EVP_PKEY_CTX *ctx)
 {
-    loopargs_t *tempargs = *(loopargs_t **)args;
-    EC_KEY **ecdh_a = tempargs->ecdh_a;
-    EC_KEY **ecdh_b = tempargs->ecdh_b;
-    unsigned char *secret_a = tempargs->secret_a;
+    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;
+    EVP_PKEY_CTX *ctx = tempargs->ecdh_ctx[testnum];
+    unsigned char *derived_secret = tempargs->secret_a;
     int count;
-    size_t outlen = tempargs->outlen;
-    kdf_fn kdf = tempargs->kdf;
+    size_t *outlen = &(tempargs->outlen);
 
     for (count = 0; COND(ecdh_c[testnum][0]); count++) {
-        ECDH_compute_key(secret_a, outlen,
-                EC_KEY_get0_public_key(ecdh_b[testnum]),
-                ecdh_a[testnum], kdf);
+        if ( !ECDH_EVP_derive_key(derived_secret, outlen, ctx) )
+            break;
     }
     return count;
 }
 
-static const size_t KDF1_SHA1_len = 20;
-static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
-                       size_t *outlen)
-{
-    if (*outlen < SHA_DIGEST_LENGTH)
-        return NULL;
-    *outlen = SHA_DIGEST_LENGTH;
-    return SHA1(in, inlen, out);
-}
 #endif                          /* OPENSSL_NO_EC */
 
 static int run_benchmark(int async_jobs,
@@ -1224,9 +1223,7 @@ int speed_main(int argc, char **argv)
     int async_init = 0;
     int loopargs_len = 0;
     char *prog;
-#ifndef OPENSSL_NO_ENGINE
     const char *engine_id = NULL;
-#endif
     const EVP_CIPHER *evp_cipher = NULL;
     double d = 0.0;
     OPTION_CHOICE o;
@@ -1400,9 +1397,7 @@ int speed_main(int argc, char **argv)
              * initialised by each child process, not by the parent.
              * So store the name here and run setup_engine() later on.
              */
-#ifndef OPENSSL_NO_ENGINE
             engine_id = opt_arg();
-#endif
             break;
         case OPT_MULTI:
 #ifndef NO_FORK
@@ -2562,85 +2557,78 @@ int speed_main(int argc, char **argv)
 
         if (!ecdh_doit[testnum])
             continue;
+
         for (i = 0; i < loopargs_len; i++) {
-            loopargs[i].ecdh_a[testnum] = EC_KEY_new_by_curve_name(test_curves[testnum]);
-            loopargs[i].ecdh_b[testnum] = EC_KEY_new_by_curve_name(test_curves[testnum]);
-            if (loopargs[i].ecdh_a[testnum] == NULL ||
-                loopargs[i].ecdh_b[testnum] == NULL) {
-                ecdh_checks = 0;
-                break;
-            }
-        }
-        if (ecdh_checks == 0) {
-            BIO_printf(bio_err, "ECDH failure.\n");
-            ERR_print_errors(bio_err);
-            rsa_count = 1;
-        } else {
-            for (i = 0; i < loopargs_len; i++) {
-                /* generate two ECDH key pairs */
-                if (!EC_KEY_generate_key(loopargs[i].ecdh_a[testnum]) ||
-                        !EC_KEY_generate_key(loopargs[i].ecdh_b[testnum])) {
-                    BIO_printf(bio_err, "ECDH key generation failure.\n");
-                    ERR_print_errors(bio_err);
+            EVP_PKEY_CTX *kctx = NULL, *ctx = NULL;
+            EVP_PKEY *key_A = NULL, *key_B = NULL;
+
+            if (testnum == R_EC_X25519) {
+                kctx = EVP_PKEY_CTX_new_id(test_curves[testnum], NULL); /* keygen ctx from NID */
+            } else {
+                EVP_PKEY_CTX *pctx = NULL;
+                EVP_PKEY *params = NULL;
+
+                if (    /* Create the context for parameter generation */
+                        !(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) ||
+                        /* Initialise the parameter generation */
+                        !EVP_PKEY_paramgen_init(pctx) ||
+                        /* Set the curve by NID */
+                        !EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, test_curves[testnum]) ||
+                        /* Create the parameter object params */
+                        !EVP_PKEY_paramgen(pctx, &params) ||
+                        0) {
                     ecdh_checks = 0;
+                    BIO_printf(bio_err, "ECDH init failure.\n");
+                    ERR_print_errors(bio_err);
                     rsa_count = 1;
-                } else {
-                    int secret_size_a, secret_size_b;
-                    /*
-                     * If field size is not more than 24 octets, then use SHA-1
-                     * hash of result; otherwise, use result (see section 4.8 of
-                     * draft-ietf-tls-ecc-03.txt).
-                     */
-                    int field_size = EC_GROUP_get_degree(
-                            EC_KEY_get0_group(loopargs[i].ecdh_a[testnum]));
-
-                    if (field_size <= 24 * 8) {                 /* 192 bits */
-                        loopargs[i].outlen = KDF1_SHA1_len;
-                        loopargs[i].kdf = KDF1_SHA1;
-                    } else {
-                        loopargs[i].outlen = (field_size + 7) / 8;
-                        loopargs[i].kdf = NULL;
-                    }
-                    secret_size_a =
-                        ECDH_compute_key(loopargs[i].secret_a, loopargs[i].outlen,
-                                EC_KEY_get0_public_key(loopargs[i].ecdh_b[testnum]),
-                                loopargs[i].ecdh_a[testnum], loopargs[i].kdf);
-                    secret_size_b =
-                        ECDH_compute_key(loopargs[i].secret_b, loopargs[i].outlen,
-                                EC_KEY_get0_public_key(loopargs[i].ecdh_a[testnum]),
-                                loopargs[i].ecdh_b[testnum], loopargs[i].kdf);
-                    if (secret_size_a != secret_size_b)
-                        ecdh_checks = 0;
-                    else
-                        ecdh_checks = 1;
-
-                    for (k = 0; k < secret_size_a && ecdh_checks == 1; k++) {
-                        if (loopargs[i].secret_a[k] != loopargs[i].secret_b[k])
-                            ecdh_checks = 0;
-                    }
-
-                    if (ecdh_checks == 0) {
-                        BIO_printf(bio_err, "ECDH computations don't match.\n");
-                        ERR_print_errors(bio_err);
-                        rsa_count = 1;
-                        break;
-                    }
+                    break;
                 }
+                /* Create the context for the key generation */
+                kctx = EVP_PKEY_CTX_new(params, NULL);
+
+                EVP_PKEY_free(params); params = NULL;
+                EVP_PKEY_CTX_free(pctx); pctx = 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_compute_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;
+            if (    !kctx || /* keygen ctx is not null */
+                    !EVP_PKEY_keygen_init(kctx) || /* init keygen ctx */
+                    0) {
+                ecdh_checks = 0;
+                BIO_printf(bio_err, "ECDH keygen failure.\n");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+                break;
             }
+
+            if (    !EVP_PKEY_keygen(kctx, &key_A) || /* generate secret key A */
+                    !EVP_PKEY_keygen(kctx, &key_B) || /* generate secret key B */
+                    !(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */
+                    !EVP_PKEY_derive_init(ctx) || /* init derivation ctx */
+                    !EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */
+                    0) {
+                ecdh_checks = 0;
+                BIO_printf(bio_err, "ECDH key generation failure.\n");
+                ERR_print_errors(bio_err);
+                rsa_count = 1;
+                break;
+            }
+
+            loopargs[i].ecdh_ctx[testnum] = ctx;
+
+            EVP_PKEY_CTX_free(kctx); kctx = 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;
         }
 
         if (rsa_count <= 1) {
@@ -2803,8 +2791,7 @@ int speed_main(int argc, char **argv)
 #ifndef OPENSSL_NO_EC
         for (k = 0; k < EC_NUM; k++) {
             EC_KEY_free(loopargs[i].ecdsa[k]);
-            EC_KEY_free(loopargs[i].ecdh_a[k]);
-            EC_KEY_free(loopargs[i].ecdh_b[k]);
+            EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
         }
         OPENSSL_free(loopargs[i].secret_a);
         OPENSSL_free(loopargs[i].secret_b);