c448_error_t c448_ed448_verify(
                    const uint8_t signature[EDDSA_448_SIGNATURE_BYTES],
                    const uint8_t pubkey[EDDSA_448_PUBLIC_BYTES],
                    const uint8_t *message, size_t message_len,
                    uint8_t prehashed, const uint8_t *context,
                    uint8_t context_len)
{
    curve448_point_t pk_point, r_point;
    c448_error_t error =
        curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pubkey);
    curve448_scalar_t challenge_scalar;
    curve448_scalar_t response_scalar;

    if (C448_SUCCESS != error)
        return error;

    error =
        curve448_point_decode_like_eddsa_and_mul_by_ratio(r_point, signature);
    if (C448_SUCCESS != error)
        return error;

    {
        /* Compute the challenge */
        EVP_MD_CTX *hashctx = EVP_MD_CTX_new();
        uint8_t challenge[2 * EDDSA_448_PRIVATE_BYTES];

        if (hashctx == NULL
                || !hash_init_with_dom(hashctx, prehashed, 0, context,
                                       context_len)
                || !EVP_DigestUpdate(hashctx, signature, EDDSA_448_PUBLIC_BYTES)
                || !EVP_DigestUpdate(hashctx, pubkey, EDDSA_448_PUBLIC_BYTES)
                || !EVP_DigestUpdate(hashctx, message, message_len)
                || !EVP_DigestFinalXOF(hashctx, challenge, sizeof(challenge))) {
            EVP_MD_CTX_free(hashctx);
            return C448_FAILURE;
        }

        EVP_MD_CTX_free(hashctx);
        curve448_scalar_decode_long(challenge_scalar, challenge,
                                    sizeof(challenge));
        OPENSSL_cleanse(challenge, sizeof(challenge));
    }
    curve448_scalar_sub(challenge_scalar, curve448_scalar_zero,
                        challenge_scalar);

    curve448_scalar_decode_long(response_scalar,
                                &signature[EDDSA_448_PUBLIC_BYTES],
                                EDDSA_448_PRIVATE_BYTES);

    /* pk_point = -c(x(P)) + (cx + k)G = kG */
    curve448_base_double_scalarmul_non_secret(pk_point,
                                              response_scalar,
                                              pk_point, challenge_scalar);
    return c448_succeed_if(curve448_point_eq(pk_point, r_point));
}