+/**
+*** PKEY KDF TESTS
+**/
+
+typedef struct pkey_kdf_data_st {
+ /* Context for this operation */
+ EVP_PKEY_CTX *ctx;
+ /* Expected output */
+ unsigned char *output;
+ size_t output_len;
+} PKEY_KDF_DATA;
+
+/*
+ * Perform public key operation setup: lookup key, allocated ctx and call
+ * the appropriate initialisation function
+ */
+static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
+{
+ PKEY_KDF_DATA *kdata;
+ int kdf_nid = OBJ_sn2nid(name);
+
+#ifdef OPENSSL_NO_SCRYPT
+ if (strcmp(name, "scrypt") == 0) {
+ t->skip = 1;
+ return 1;
+ }
+#endif
+
+ if (kdf_nid == NID_undef)
+ kdf_nid = OBJ_ln2nid(name);
+
+ if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
+ return 0;
+ kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL);
+ if (kdata->ctx == NULL) {
+ OPENSSL_free(kdata);
+ return 0;
+ }
+ if (EVP_PKEY_derive_init(kdata->ctx) <= 0) {
+ EVP_PKEY_CTX_free(kdata->ctx);
+ OPENSSL_free(kdata);
+ return 0;
+ }
+ t->data = kdata;
+ return 1;
+}
+
+static void pkey_kdf_test_cleanup(EVP_TEST *t)
+{
+ PKEY_KDF_DATA *kdata = t->data;
+ OPENSSL_free(kdata->output);
+ EVP_PKEY_CTX_free(kdata->ctx);
+}
+
+static int pkey_kdf_test_parse(EVP_TEST *t,
+ const char *keyword, const char *value)
+{
+ PKEY_KDF_DATA *kdata = t->data;
+
+ if (strcmp(keyword, "Output") == 0)
+ return parse_bin(value, &kdata->output, &kdata->output_len);
+ if (strncmp(keyword, "Ctrl", 4) == 0)
+ return pkey_test_ctrl(t, kdata->ctx, value);
+ return 0;
+}
+
+static int pkey_kdf_test_run(EVP_TEST *t)
+{
+ PKEY_KDF_DATA *expected = t->data;
+ unsigned char *got = NULL;
+ size_t got_len = expected->output_len;
+
+ if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
+ t->err = "INTERNAL_ERROR";
+ goto err;
+ }
+ if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) {
+ t->err = "KDF_DERIVE_ERROR";
+ goto err;
+ }
+ if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
+ t->err = "KDF_MISMATCH";
+ goto err;
+ }
+ t->err = NULL;
+
+ err:
+ OPENSSL_free(got);
+ return 1;
+}
+
+static const EVP_TEST_METHOD pkey_kdf_test_method = {
+ "PKEYKDF",
+ pkey_kdf_test_init,
+ pkey_kdf_test_cleanup,
+ pkey_kdf_test_parse,
+ pkey_kdf_test_run
+};
+
+