+void *ecx_load(const void *reference, size_t reference_sz)
+{
+ ECX_KEY *key = NULL;
+
+ if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
+ /* The contents of the reference is the address to our object */
+ key = *(ECX_KEY **)reference;
+ /* We grabbed, so we detach it */
+ *(ECX_KEY **)reference = NULL;
+ return key;
+ }
+ return NULL;
+}
+
+static void *ecx_dup(const void *keydata_from, int selection)
+{
+ if (ossl_prov_is_running())
+ return ossl_ecx_key_dup(keydata_from, selection);
+ return NULL;
+}
+
+static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
+{
+ uint8_t pub[64];
+
+ switch (type) {
+ case ECX_KEY_TYPE_X25519:
+ ossl_x25519_public_from_private(pub, ecx->privkey);
+ break;
+ case ECX_KEY_TYPE_X448:
+ ossl_x448_public_from_private(pub, ecx->privkey);
+ break;
+ default:
+ return 0;
+ }
+ return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
+}
+
+#ifdef FIPS_MODULE
+static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
+{
+ return ecd_fips140_pairwise_test(ecx, type, 0);
+}
+#else
+static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
+{
+ uint8_t pub[64];
+
+ switch (type) {
+ case ECX_KEY_TYPE_ED25519:
+ if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
+ ecx->propq))
+ return 0;
+ break;
+ case ECX_KEY_TYPE_ED448:
+ if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
+ ecx->propq))
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
+}
+#endif
+
+static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
+{
+ const ECX_KEY *ecx = keydata;
+ int ok = keylen == ecx->keylen;
+
+ if (!ossl_prov_is_running())
+ return 0;
+
+ if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
+ return 1; /* nothing to validate */
+
+ if (!ok) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
+ return 0;
+ }
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
+ ok = ok && ecx->haspubkey;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
+ ok = ok && ecx->privkey != NULL;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
+ return ok;
+
+ if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448)
+ ok = ok && ecd_key_pairwise_check(ecx, type);
+ else
+ ok = ok && ecx_key_pairwise_check(ecx, type);
+
+ return ok;
+}
+
+static int x25519_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
+}
+
+static int x448_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
+}
+
+static int ed25519_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
+}
+
+static int ed448_validate(const void *keydata, int selection, int checktype)
+{
+ return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
+}
+