return ret;
}
+
+static int ecdh_cofactor_derive_test(int tstid)
+{
+ int ret = 0;
+ const struct ecdh_cofactor_derive_st *t = &ecdh_cofactor_derive_data[tstid];
+ unsigned char secret1[16];
+ size_t secret1_len = sizeof(secret1);
+ const char *curve = "K-283"; /* A curve that has a cofactor that it not 1 */
+ EVP_PKEY *peer1 = NULL, *peer2 = NULL;
+ EVP_PKEY_CTX *p1ctx = NULL;
+ OSSL_PARAM params[2], *prms = NULL;
+ int use_cofactordh = t->key_cofactor;
+ int cofactor_mode = t->derive_cofactor_mode;
+
+ if (!TEST_ptr(peer1 = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve))
+ || !TEST_ptr(peer2 = EVP_PKEY_Q_keygen(libctx, NULL, "EC", curve)))
+ goto err;
+
+ params[1] = OSSL_PARAM_construct_end();
+
+ prms = NULL;
+ if (t->key_cofactor != COFACTOR_NOT_SET) {
+ params[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
+ &use_cofactordh);
+ prms = params;
+ }
+ if (!TEST_int_eq(EVP_PKEY_set_params(peer1, prms), 1)
+ || !TEST_ptr(p1ctx = EVP_PKEY_CTX_new_from_pkey(libctx, peer1, NULL)))
+ goto err;
+
+ prms = NULL;
+ if (t->derive_cofactor_mode != COFACTOR_NOT_SET) {
+ params[0] = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
+ &cofactor_mode);
+ prms = params;
+ }
+ if (!TEST_int_eq(EVP_PKEY_derive_init_ex(p1ctx, prms), 1)
+ || !TEST_int_eq(EVP_PKEY_derive_set_peer(p1ctx, peer2), 1)
+ || !TEST_int_eq(EVP_PKEY_derive(p1ctx, secret1, &secret1_len),
+ t->expected))
+ goto err;
+
+ ret = 1;
+err:
+ if (ret == 0) {
+ static const char *state[] = { "unset", "-1", "disabled", "enabled" };
+
+ TEST_note("ECDH derive() was expected to %s if key cofactor is"
+ "%s and derive mode is %s", t->expected ? "Pass" : "Fail",
+ state[2 + t->key_cofactor], state[2 + t->derive_cofactor_mode]);
+ }
+ EVP_PKEY_free(peer1);
+ EVP_PKEY_free(peer2);
+ EVP_PKEY_CTX_free(p1ctx);
+ return ret;
+}
+
#endif /* OPENSSL_NO_EC */
#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECX)
ADD_ALL_TESTS(ecdsa_pub_verify_test, OSSL_NELEM(ecdsa_pv_data));
ADD_ALL_TESTS(ecdsa_siggen_test, OSSL_NELEM(ecdsa_siggen_data));
ADD_ALL_TESTS(ecdsa_sigver_test, OSSL_NELEM(ecdsa_sigver_data));
+ ADD_ALL_TESTS(ecdh_cofactor_derive_test,
+ OSSL_NELEM(ecdh_cofactor_derive_data));
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_ECX
int pass;
};
+struct ecdh_cofactor_derive_st {
+ int derive_cofactor_mode;
+ int key_cofactor;
+ int expected;
+};
+
static const struct ecdsa_keygen_st ecdsa_keygen_data[] = {
{ "P-224" },
};
},
};
+/*
+ * FIPS EC DH key derivation requires the use of the cofactor if a curve has a
+ * cofactor that is not 1. The cofactor option is determined by either
+ * (1) The derive ctx using OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE or via
+ * (2) The EVP_PKEY (used by the derive) using OSSL_PKEY_PARAM_USE_COFACTOR_ECDH
+ * Test all combinations of these.
+ * Notes:
+ * COFACTOR_MODE is -1 by default. (It can be -1, 0, or 1).
+ * OSSL_PKEY_PARAM_USE_COFACTOR_ECDH is 0 by default. (It can be 0 or 1)
+ *
+ * OSSL_PKEY_PARAM_USE_COFACTOR_ECDH is only used if the COFACTOR_MODE is -1.
+ *
+ * If the cofactor is not set by either then the derived is expected to fail.
+ */
+# define COFACTOR_NOT_SET -2 /* Use the default by not setting the param */
+static const struct ecdh_cofactor_derive_st ecdh_cofactor_derive_data[] = {
+ { COFACTOR_NOT_SET, COFACTOR_NOT_SET, 0 },
+ { COFACTOR_NOT_SET, 0, 0 },
+ { COFACTOR_NOT_SET, 1, 1 },
+ { -1, COFACTOR_NOT_SET, 0 },
+ { -1, 0, 0 },
+ { -1, 1, 1 },
+ { 0, COFACTOR_NOT_SET, 0 },
+ { 0, 0, 0 },
+ { 0, 1, 0 },
+ { 1, COFACTOR_NOT_SET, 1 },
+ { 1, 0, 1 },
+ { 1, 1, 1 }
+};
+
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_ECX