EVP_KEYEXCH *EVP_KEYEXCH_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                               const char *properties)
{
    /*
     * Key exchange cannot work without a key, and we key management
     * from the same provider to manage its keys.
     */
    EVP_KEYEXCH *keyexch =
        evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties,
                          evp_keyexch_from_dispatch,
                          (int (*)(void *))EVP_KEYEXCH_up_ref,
                          (void (*)(void *))EVP_KEYEXCH_free);

    /* If the method is newly created, there's no keymgmt attached */
    if (keyexch->keymgmt == NULL) {
        EVP_KEYMGMT *keymgmt = EVP_KEYMGMT_fetch(ctx, algorithm, properties);

        if (keymgmt == NULL
            || (EVP_KEYEXCH_provider(keyexch)
                != EVP_KEYMGMT_provider(keymgmt))) {
            EVP_KEYEXCH_free(keyexch);
            EVP_KEYMGMT_free(keymgmt);
            EVPerr(EVP_F_EVP_KEYEXCH_FETCH, EVP_R_NO_KEYMGMT_PRESENT);
            return NULL;
        }

        keyexch->keymgmt = keymgmt;
    }
    return keyexch;
}