int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
                   const unsigned char *Z, size_t Zlen,
                   const unsigned char *sinfo, size_t sinfolen,
                   const EVP_MD *md)
{
    int ret;
    EVP_KDF_CTX *kctx = NULL;

    kctx = EVP_KDF_CTX_new(EVP_get_kdfbyname(SN_x963kdf));
    ret =
        kctx != NULL
        && EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, md) > 0
        && EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, Z, Zlen) > 0
        && EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SHARED_INFO, sinfo, sinfolen) > 0
        && EVP_KDF_derive(kctx, out, outlen) > 0;

    EVP_KDF_CTX_free(kctx);
    return ret;
}