/*
 * This file was generated automatically by ExtUtils::ParseXS version 3.51 from the
 * contents of RSA.xs. Do not edit this file, edit RSA.xs instead.
 *
 *    ANY CHANGES MADE HERE WILL BE LOST!
 *
 */

#line 1 "RSA.xs"
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/md5.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/ripemd.h>
#if OPENSSL_VERSION_NUMBER >= 0x10000000 && OPENSSL_VERSION_NUMBER < 0x30000000
#ifndef LIBRESSL_VERSION_NUMBER
#include <openssl/whrlpool.h>
#endif
#endif
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/encoder.h>
#endif

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#define UNSIGNED_CHAR unsigned char
#define SIZE_T_INT size_t
#define SIZE_T_UNSIGNED_INT size_t
#define EVP_PKEY EVP_PKEY
#define EVP_PKEY_free(p) EVP_PKEY_free(p)
#define EVP_PKEY_get_size(p) EVP_PKEY_get_size(p)
#define PEM_read_bio_PrivateKey PEM_read_bio_PrivateKey
#define PEM_read_bio_RSAPublicKey PEM_read_bio_PUBKEY
#define PEM_read_bio_RSA_PUBKEY PEM_read_bio_PUBKEY
#define PEM_write_bio_PUBKEY(o,p) PEM_write_bio_PUBKEY(o,p);
#define PEM_write_bio_PrivateKey_traditional(m, n, o, p, q, r, s) PEM_write_bio_PrivateKey_traditional(m, n, o, p, q, r, s)
#else
#define UNSIGNED_CHAR char
#define SIZE_T_INT int
#define SIZE_T_UNSIGNED_INT unsigned int
#define EVP_PKEY RSA
#define EVP_PKEY_free(p) RSA_free(p)
#define EVP_PKEY_get_size(p) RSA_size(p)
#define PEM_read_bio_PrivateKey PEM_read_bio_RSAPrivateKey
#define PEM_read_bio_RSAPublicKey PEM_read_bio_RSAPublicKey
#define PEM_read_bio_RSA_PUBKEY PEM_read_bio_RSA_PUBKEY
#define PEM_write_bio_PUBKEY(o,p) PEM_write_bio_RSA_PUBKEY(o,p)
#define PEM_write_bio_PrivateKey_traditional(m, n, o, p, q, r, s) PEM_write_bio_RSAPrivateKey(m, n , o, p, q, r, s)
#endif

typedef struct
{
    EVP_PKEY* rsa;
    int padding;
    int hashMode;
} rsaData;

/* Key names for the rsa hash structure */

#define KEY_KEY "_Key"
#define PADDING_KEY "_Padding"
#define HASH_KEY "_Hash_Mode"

#define PACKAGE_NAME "Crypt::OpenSSL::RSA"

#define OLD_CRUFTY_SSL_VERSION (OPENSSL_VERSION_NUMBER < 0x10100000L || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x03050000fL))

void croakSsl(char* p_file, int p_line)
{
    const char* errorReason;
    /* Just return the top error on the stack */
    errorReason = ERR_reason_error_string(ERR_get_error());
    ERR_clear_error();
    croak("%s:%d: OpenSSL error: %s", p_file, p_line, errorReason);
}

#define CHECK_OPEN_SSL(p_result) if (!(p_result)) croakSsl(__FILE__, __LINE__);

#define PACKAGE_CROAK(p_message) croak("%s", (p_message))
#define CHECK_NEW(p_var, p_size, p_type) \
  if (New(0, p_var, p_size, p_type) == NULL) \
    { PACKAGE_CROAK("unable to alloc buffer"); }

#define THROW(p_result) if (!(p_result)) { error = 1; goto err; }

char _is_private(rsaData* p_rsa)
{
    char ret = 0;
#if OLD_CRUFTY_SSL_VERSION
    const BIGNUM* d;
    d = p_rsa->rsa->d;
    ret = (d != NULL);
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    BIGNUM* d = NULL;
    EVP_PKEY_get_bn_param(p_rsa->rsa, OSSL_PKEY_PARAM_RSA_D, &d);
    ret = (d != NULL);
    BN_clear_free(d);
#else
    const BIGNUM* d = NULL;
    RSA_get0_key(p_rsa->rsa, NULL, NULL, &d);
    ret = (d != NULL);
#endif
#endif
    return ret;
}

SV* make_rsa_obj(SV* p_proto, EVP_PKEY* p_rsa)
{
    rsaData* rsa;

    CHECK_NEW(rsa, 1, rsaData);
    rsa->rsa = p_rsa;
    rsa->hashMode = NID_sha1;
    rsa->padding = RSA_PKCS1_OAEP_PADDING;
    return sv_bless(
        newRV_noinc(newSViv((IV) rsa)),
        (SvROK(p_proto) ? SvSTASH(SvRV(p_proto)) : gv_stashsv(p_proto, 1)));
}

int get_digest_length(int hash_method)
{
    switch(hash_method)
    {
        case NID_md5:
            return MD5_DIGEST_LENGTH;
            break;
        case NID_sha1:
            return SHA_DIGEST_LENGTH;
            break;
#ifdef SHA512_DIGEST_LENGTH
        case NID_sha224:
            return SHA224_DIGEST_LENGTH;
            break;
        case NID_sha256:
            return SHA256_DIGEST_LENGTH;
            break;
        case NID_sha384:
            return SHA384_DIGEST_LENGTH;
            break;
        case NID_sha512:
            return SHA512_DIGEST_LENGTH;
            break;
#endif
        case NID_ripemd160:
            return RIPEMD160_DIGEST_LENGTH;
            break;
#ifdef WHIRLPOOL_DIGEST_LENGTH
        case NID_whirlpool:
            return WHIRLPOOL_DIGEST_LENGTH;
            break;
#endif
        default:
            croak("Unknown digest hash mode %u", hash_method);
            break;
    }
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L

EVP_MD *get_md_bynid(int hash_method)
{
    switch(hash_method)
    {
        case NID_md5:
            return EVP_MD_fetch(NULL, "md5", NULL);
            break;
        case NID_sha1:
            return EVP_MD_fetch(NULL, "sha1", NULL);
            break;
#ifdef SHA512_DIGEST_LENGTH
        case NID_sha224:
            return EVP_MD_fetch(NULL, "sha224", NULL);
            break;
        case NID_sha256:
            return EVP_MD_fetch(NULL, "sha256", NULL);
            break;
        case NID_sha384:
            return EVP_MD_fetch(NULL, "sha384", NULL);
            break;
        case NID_sha512:
            return EVP_MD_fetch(NULL, "sha512", NULL);
            break;
#endif
        case NID_ripemd160:
            return EVP_MD_fetch(NULL, "ripemd160", NULL);
            break;
#ifdef WHIRLPOOL_DIGEST_LENGTH
        case NID_whirlpool:
            return EVP_MD_fetch(NULL, "whirlpool", NULL);
            break;
#endif
        default:
            croak("Unknown digest hash mode %u", hash_method);
            break;
    }
}
#endif
unsigned char* get_message_digest(SV* text_SV, int hash_method)
{
    STRLEN text_length;
    unsigned char* text;
    unsigned char *md;
    static unsigned char m[EVP_MAX_MD_SIZE];
    text = (unsigned char*) SvPV(text_SV, text_length);
    md = m;

    switch(hash_method)
    {
        case NID_md5:
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
            return EVP_Q_digest(NULL, "MD5", NULL, text, text_length, md, NULL) ? md : NULL;
#else
            return MD5(text, text_length, md);
#endif
            break;
        case NID_sha1:
            return SHA1(text, text_length, md);
            break;
#ifdef SHA512_DIGEST_LENGTH
        case NID_sha224:
            return SHA224(text, text_length, md);
            break;
        case NID_sha256:
            return SHA256(text, text_length, md);
            break;
        case NID_sha384:
            return SHA384(text, text_length, md);
            break;
        case NID_sha512:
            return SHA512(text, text_length, md);
            break;
#endif
        case NID_ripemd160:
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
            return EVP_Q_digest(NULL, "RIPEMD160", NULL, text, text_length, md, NULL) ? md : NULL;
#else
            return RIPEMD160(text, text_length, md);
#endif
            break;
#ifdef WHIRLPOOL_DIGEST_LENGTH
        case NID_whirlpool:
            return WHIRLPOOL(text, text_length, md);
            break;
#endif
        default:
            croak("Unknown digest hash mode %u", hash_method);
            break;
    }
}

SV* cor_bn2sv(const BIGNUM* p_bn)
{
    return p_bn != NULL
        ? sv_2mortal(newSViv((IV) BN_dup(p_bn)))
        : &PL_sv_undef;
}

SV* extractBioString(BIO* p_stringBio)
{
    SV* sv;
    char* datap;
    long datasize = 0;

    CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1);

    datasize = BIO_get_mem_data(p_stringBio, &datap);
    sv = newSVpv(datap, datasize);

    CHECK_OPEN_SSL(BIO_set_close(p_stringBio, BIO_CLOSE) == 1);
    BIO_free(p_stringBio);
    return sv;
}

EVP_PKEY*  _load_rsa_key(SV* p_keyStringSv,
                        EVP_PKEY*(*p_loader)(BIO *, EVP_PKEY**, pem_password_cb*, void*),
                   SV* p_passphaseSv)
{
    STRLEN keyStringLength;
    char* keyString;
    UNSIGNED_CHAR *passphase = NULL;

    EVP_PKEY* rsa;
    BIO* stringBIO;

    keyString = SvPV(p_keyStringSv, keyStringLength);

    if (SvPOK(p_passphaseSv)) {
        passphase = SvPV_nolen(p_passphaseSv);
    }

    CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, keyStringLength));

    rsa = p_loader(stringBIO, NULL, NULL, passphase);

    CHECK_OPEN_SSL(BIO_set_close(stringBIO, BIO_CLOSE) == 1);
    BIO_free(stringBIO);

    CHECK_OPEN_SSL(rsa);
    return rsa;
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L

SV* rsa_crypt(rsaData* p_rsa, SV* p_from,
              int (*p_crypt)(EVP_PKEY_CTX*, unsigned char*, size_t*, const unsigned char*, size_t),
              int (*init_crypt)(EVP_PKEY_CTX*), int public)
#else

SV* rsa_crypt(rsaData* p_rsa, SV* p_from,
              int (*p_crypt)(int, const unsigned char*, unsigned char*, RSA*, int))
#endif
{
    STRLEN from_length;
    SIZE_T_INT to_length;
    int size;
    unsigned char* from;
    UNSIGNED_CHAR *to;
    SV* sv;

    from = (unsigned char*) SvPV(p_from, from_length);
    size = EVP_PKEY_get_size(p_rsa->rsa);
    CHECK_NEW(to, size, UNSIGNED_CHAR);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L

    if(p_rsa->padding == RSA_PKCS1_PSS_PADDING)
        croak("PKCS#1 v2.1 RSA-PSS cannot be used for encryption operations call \"use_pkcs1_oaep_padding\" instead.");

    EVP_PKEY_CTX *ctx;

    OSSL_LIB_CTX *ossllibctx = OSSL_LIB_CTX_new();
    if (public) {
        ctx = EVP_PKEY_CTX_new_from_pkey(ossllibctx, (EVP_PKEY* )p_rsa->rsa, NULL);
    } else {
        ctx = EVP_PKEY_CTX_new((EVP_PKEY* )p_rsa->rsa, NULL);
    }

    CHECK_OPEN_SSL(ctx);

    CHECK_OPEN_SSL(init_crypt(ctx) == 1);
    CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_padding(ctx, p_rsa->padding) > 0);
    CHECK_OPEN_SSL(p_crypt(ctx, NULL, &to_length, from, from_length) == 1);
    CHECK_OPEN_SSL(p_crypt(ctx, to, &to_length, from, from_length) == 1);

    EVP_PKEY_CTX_free(ctx);
#else
    to_length = p_crypt(
       from_length, from, (unsigned char*) to, p_rsa->rsa, p_rsa->padding);
#endif
    if (to_length < 0)
    {
        Safefree(to);
        CHECK_OPEN_SSL(0);
    }
    sv = newSVpv((char* ) to, to_length);
    Safefree(to);
    return sv;
}

#line 371 "RSA.c"
#ifndef PERL_UNUSED_VAR
#  define PERL_UNUSED_VAR(var) if (0) var = var
#endif

#ifndef dVAR
#  define dVAR		dNOOP
#endif


/* This stuff is not part of the API! You have been warned. */
#ifndef PERL_VERSION_DECIMAL
#  define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#endif
#ifndef PERL_DECIMAL_VERSION
#  define PERL_DECIMAL_VERSION \
	  PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#endif
#ifndef PERL_VERSION_GE
#  define PERL_VERSION_GE(r,v,s) \
	  (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
#endif
#ifndef PERL_VERSION_LE
#  define PERL_VERSION_LE(r,v,s) \
	  (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
#endif

/* XS_INTERNAL is the explicit static-linkage variant of the default
 * XS macro.
 *
 * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
 * "STATIC", ie. it exports XSUB symbols. You probably don't want that
 * for anything but the BOOT XSUB.
 *
 * See XSUB.h in core!
 */


/* TODO: This might be compatible further back than 5.10.0. */
#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
#  undef XS_EXTERNAL
#  undef XS_INTERNAL
#  if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
#    define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
#    define XS_INTERNAL(name) STATIC XSPROTO(name)
#  endif
#  if defined(__SYMBIAN32__)
#    define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
#    define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
#  endif
#  ifndef XS_EXTERNAL
#    if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
#      define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
#      define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
#    else
#      ifdef __cplusplus
#        define XS_EXTERNAL(name) extern "C" XSPROTO(name)
#        define XS_INTERNAL(name) static XSPROTO(name)
#      else
#        define XS_EXTERNAL(name) XSPROTO(name)
#        define XS_INTERNAL(name) STATIC XSPROTO(name)
#      endif
#    endif
#  endif
#endif

/* perl >= 5.10.0 && perl <= 5.15.1 */


/* The XS_EXTERNAL macro is used for functions that must not be static
 * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
 * macro defined, the best we can do is assume XS is the same.
 * Dito for XS_INTERNAL.
 */
#ifndef XS_EXTERNAL
#  define XS_EXTERNAL(name) XS(name)
#endif
#ifndef XS_INTERNAL
#  define XS_INTERNAL(name) XS(name)
#endif

/* Now, finally, after all this mess, we want an ExtUtils::ParseXS
 * internal macro that we're free to redefine for varying linkage due
 * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
 * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
 */

#undef XS_EUPXS
#if defined(PERL_EUPXS_ALWAYS_EXPORT)
#  define XS_EUPXS(name) XS_EXTERNAL(name)
#else
   /* default to internal */
#  define XS_EUPXS(name) XS_INTERNAL(name)
#endif

#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)

/* prototype to pass -Wmissing-prototypes */
STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params);

STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params)
{
    const GV *const gv = CvGV(cv);

    PERL_ARGS_ASSERT_CROAK_XS_USAGE;

    if (gv) {
        const char *const gvname = GvNAME(gv);
        const HV *const stash = GvSTASH(gv);
        const char *const hvname = stash ? HvNAME(stash) : NULL;

        if (hvname)
	    Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
        else
	    Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
    } else {
        /* Pants. I don't think that it should be possible to get here. */
	Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
    }
}
#undef  PERL_ARGS_ASSERT_CROAK_XS_USAGE

#define croak_xs_usage        S_croak_xs_usage

#endif

/* NOTE: the prototype of newXSproto() is different in versions of perls,
 * so we define a portable version of newXSproto()
 */
#ifdef newXS_flags
#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
#else
#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
#endif /* !defined(newXS_flags) */

#if PERL_VERSION_LE(5, 21, 5)
#  define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
#else
#  define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
#endif

#line 515 "RSA.c"

XS_EUPXS(XS_Crypt__OpenSSL__RSA_new_private_key); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_new_private_key)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "proto, key_string_SV, passphase_SV=&PL_sv_undef");
    {
	SV*	proto = ST(0)
;
	SV*	key_string_SV = ST(1)
;
	SV*	passphase_SV;
	SV *	RETVAL;

	if (items < 3)
	    passphase_SV = &PL_sv_undef;
	else {
	    passphase_SV = ST(2)
;
	}
#line 380 "RSA.xs"
    RETVAL = make_rsa_obj(
        proto, _load_rsa_key(key_string_SV, PEM_read_bio_PrivateKey, passphase_SV));
#line 540 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA__new_public_key_pkcs1); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA__new_public_key_pkcs1)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "proto, key_string_SV");
    {
	SV*	proto = ST(0)
;
	SV*	key_string_SV = ST(1)
;
	SV *	RETVAL;
#line 390 "RSA.xs"
    RETVAL = make_rsa_obj(
        proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSAPublicKey, &PL_sv_undef));
#line 563 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA__new_public_key_x509); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA__new_public_key_x509)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "proto, key_string_SV");
    {
	SV*	proto = ST(0)
;
	SV*	key_string_SV = ST(1)
;
	SV *	RETVAL;
#line 400 "RSA.xs"
    RETVAL = make_rsa_obj(
        proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSA_PUBKEY, &PL_sv_undef));
#line 586 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 409 "RSA.xs"
    EVP_PKEY_free(p_rsa->rsa);
    Safefree(p_rsa);
#line 612 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_get_private_key_string); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_get_private_key_string)
{
    dVAR; dXSARGS;
    if (items < 1 || items > 3)
       croak_xs_usage(cv,  "p_rsa, passphase_SV=&PL_sv_undef, cipher_name_SV=&PL_sv_undef");
    {
	rsaData*	p_rsa;
	SV*	passphase_SV;
	SV*	cipher_name_SV;
#line 418 "RSA.xs"
    BIO* stringBIO;
    char* passphase = NULL;
    STRLEN passphaseLength = 0;
    char* cipher_name;
    const EVP_CIPHER* enc = NULL;
#line 634 "RSA.c"
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;

	if (items < 2)
	    passphase_SV = &PL_sv_undef;
	else {
	    passphase_SV = ST(1)
;
	}

	if (items < 3)
	    cipher_name_SV = &PL_sv_undef;
	else {
	    cipher_name_SV = ST(2)
;
	}
#line 424 "RSA.xs"
    if (SvPOK(cipher_name_SV) && !SvPOK(passphase_SV)) {
        croak("Passphrase is required for cipher");
    }
    if (SvPOK(passphase_SV)) {
        passphase = SvPV(passphase_SV, passphaseLength);
        if (SvPOK(cipher_name_SV)) {
            cipher_name = SvPV_nolen(cipher_name_SV);
        }
        else {
            cipher_name = "des3";
        }
        enc = EVP_get_cipherbyname(cipher_name);
        if (enc == NULL) {
            croak("Unsupported cipher: %s", cipher_name);
        }
    }

    CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem()));
    PEM_write_bio_PrivateKey_traditional(
        stringBIO, p_rsa->rsa, enc, (unsigned char* ) passphase, passphaseLength, NULL, NULL);
    RETVAL = extractBioString(stringBIO);

#line 680 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_get_public_key_string); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_get_public_key_string)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;
#line 453 "RSA.xs"
    BIO* stringBIO;
#line 698 "RSA.c"
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 455 "RSA.xs"
    CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem()));
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    OSSL_ENCODER_CTX *ctx = NULL;

    ctx = OSSL_ENCODER_CTX_new_for_pkey(p_rsa->rsa, OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
            "PEM", "PKCS1", NULL);
    CHECK_OPEN_SSL(ctx != NULL && OSSL_ENCODER_CTX_get_num_encoders(ctx));

    CHECK_OPEN_SSL(OSSL_ENCODER_to_bio(ctx, stringBIO) == 1);

    OSSL_ENCODER_CTX_free(ctx);
#else
    PEM_write_bio_RSAPublicKey(stringBIO, p_rsa->rsa);
#endif
    RETVAL = extractBioString(stringBIO);

#line 724 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_get_public_key_x509_string); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_get_public_key_x509_string)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;
#line 478 "RSA.xs"
    BIO* stringBIO;
#line 742 "RSA.c"
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 480 "RSA.xs"
    CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem()));
    PEM_write_bio_PUBKEY(stringBIO, p_rsa->rsa);
    RETVAL = extractBioString(stringBIO);

#line 756 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_generate_key); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_generate_key)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "proto, bitsSV, exponent = 65537");
    {
	SV*	proto = ST(0)
;
	SV*	bitsSV = ST(1)
;
	unsigned long	exponent;
#line 493 "RSA.xs"
    EVP_PKEY* rsa = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    EVP_PKEY_CTX *ctx;
#endif
#line 781 "RSA.c"
	SV *	RETVAL;

	if (items < 3)
	    exponent = 65537;
	else {
	    exponent = (unsigned long)SvUV(ST(2))
;
	}
#line 498 "RSA.xs"
    BIGNUM *e;
    e = BN_new();
    BN_set_word(e, exponent);
#if OPENSSL_VERSION_NUMBER < 0x00908000L
    rsa = RSA_generate_key(SvIV(bitsSV), exponent, NULL, NULL);
    CHECK_OPEN_SSL(rsa != NULL);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && OPENSSL_VERSION_NUMBER < 0x30000000L
    rsa = RSA_new();
    if (!RSA_generate_key_ex(rsa, SvIV(bitsSV), e, NULL))
       croak("Unable to generate a key");
    BN_free(e);
    CHECK_OPEN_SSL(rsa != NULL);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);

    CHECK_OPEN_SSL(ctx);
    CHECK_OPEN_SSL(EVP_PKEY_keygen_init(ctx) == 1);
    CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, SvIV(bitsSV)) > 0);
    CHECK_OPEN_SSL(EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) >0);
    CHECK_OPEN_SSL(EVP_PKEY_generate(ctx, &rsa) == 1);
    CHECK_OPEN_SSL(rsa != NULL);

    e = NULL;
    BN_free(e);
    EVP_PKEY_CTX_free(ctx);
#endif
    CHECK_OPEN_SSL(rsa);
    RETVAL = make_rsa_obj(proto, rsa);
#line 821 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA__new_key_from_parameters); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA__new_key_from_parameters)
{
    dVAR; dXSARGS;
    if (items != 6)
       croak_xs_usage(cv,  "proto, n, e, d, p, q");
    {
	SV*	proto = ST(0)
;
	BIGNUM*	n = INT2PTR(BIGNUM *,SvIV(ST(1)))
;
	BIGNUM*	e = INT2PTR(BIGNUM *,SvIV(ST(2)))
;
	BIGNUM*	d = INT2PTR(BIGNUM *,SvIV(ST(3)))
;
	BIGNUM*	p = INT2PTR(BIGNUM *,SvIV(ST(4)))
;
	BIGNUM*	q = INT2PTR(BIGNUM *,SvIV(ST(5)))
;
#line 541 "RSA.xs"
    EVP_PKEY* rsa = NULL;
    BN_CTX* ctx = NULL;
    BIGNUM* p_minus_1 = NULL;
    BIGNUM* q_minus_1 = NULL;
    BIGNUM* dmp1 = NULL;
    BIGNUM* dmq1 = NULL;
    BIGNUM* iqmp = NULL;
    int error;
#line 857 "RSA.c"
	SV *	RETVAL;
#line 550 "RSA.xs"
{
    if (!(n && e))
    {
        croak("At least a modulus and public key must be provided");
    }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    OSSL_PARAM *params = NULL;
    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
    CHECK_OPEN_SSL(pctx != NULL);
    CHECK_OPEN_SSL(EVP_PKEY_fromdata_init(pctx) > 0);
    OSSL_PARAM_BLD *params_build = OSSL_PARAM_BLD_new();
    CHECK_OPEN_SSL(params_build)
#else
    CHECK_OPEN_SSL(rsa = RSA_new());
#endif
#if OLD_CRUFTY_SSL_VERSION
    rsa->n = n;
    rsa->e = e;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    CHECK_OPEN_SSL(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_N, n));
    CHECK_OPEN_SSL(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_E, e));
#endif
    if (p || q)
    {
        error = 0;
        THROW(ctx = BN_CTX_new());
        if (!p)
        {
            THROW(p = BN_new());
            THROW(BN_div(p, NULL, n, q, ctx));
        }
        else if (!q)
        {
            q = BN_new();
            THROW(BN_div(q, NULL, n, p, ctx));
        }
#if OLD_CRUFTY_SSL_VERSION
        rsa->p = p;
        rsa->q = q;
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#else
        THROW(RSA_set0_factors(rsa, p, q));
#endif
#endif
        THROW(p_minus_1 = BN_new());
        THROW(BN_sub(p_minus_1, p, BN_value_one()));
        THROW(q_minus_1 = BN_new());
        THROW(BN_sub(q_minus_1, q, BN_value_one()));
        if (!d)
        {
            THROW(d = BN_new());
            THROW(BN_mul(d, p_minus_1, q_minus_1, ctx));
            THROW(BN_mod_inverse(d, e, d, ctx));
        }
#if OLD_CRUFTY_SSL_VERSION
        rsa->d = d;
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_D, d));
        THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_FACTOR1, p));
        THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_FACTOR2, q));
#else
        THROW(RSA_set0_key(rsa, n, e, d));
#endif
#endif
        THROW(dmp1 = BN_new());
        THROW(BN_mod(dmp1, d, p_minus_1, ctx));
        THROW(dmq1 = BN_new());
        THROW(BN_mod(dmq1, d, q_minus_1, ctx));
        THROW(iqmp = BN_new());
        THROW(BN_mod_inverse(iqmp, q, p, ctx));
#if OLD_CRUFTY_SSL_VERSION
        rsa->dmp1 = dmp1;
        rsa->dmq1 = dmq1;
        rsa->iqmp = iqmp;
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1));
        THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1));
        THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp));

        params = OSSL_PARAM_BLD_to_param(params_build);
        THROW(params != NULL);

        int status = EVP_PKEY_fromdata(pctx, &rsa, EVP_PKEY_KEYPAIR, params);
        THROW( status > 0 && rsa != NULL );
        EVP_PKEY_CTX* test_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, rsa, NULL);
        THROW(EVP_PKEY_check(test_ctx) == 1);
#else
        THROW(RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp));
#endif
#endif
        dmp1 = dmq1 = iqmp = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        OSSL_PARAM_BLD_free(params_build);
        OSSL_PARAM_free(params);
#else
        THROW(RSA_check_key(rsa) == 1);
#endif
    }
    else
    {
#if OLD_CRUFTY_SSL_VERSION
        rsa->d = d;
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
        if(d != NULL)
            THROW(OSSL_PARAM_BLD_push_BN(params_build, OSSL_PKEY_PARAM_RSA_D, d));
        params = OSSL_PARAM_BLD_to_param(params_build);
        THROW(params != NULL);

        int status = EVP_PKEY_fromdata(pctx, &rsa, EVP_PKEY_KEYPAIR, params);
        THROW( status > 0 && rsa != NULL );
#else
        CHECK_OPEN_SSL(RSA_set0_key(rsa, n, e, d));
#endif
#endif
    }

    RETVAL = make_rsa_obj(proto, rsa);
    if(RETVAL)
        goto end;

    err:
        //if (p) BN_clear_free(p);
        if (p_minus_1) BN_clear_free(p_minus_1);
        //if (q) BN_clear_free(q);
        //if (d) BN_clear_free(d);
        if (q_minus_1) BN_clear_free(q_minus_1);
        if (dmp1) BN_clear_free(dmp1);
        if (dmq1) BN_clear_free(dmq1);
        if (iqmp) BN_clear_free(iqmp);
        if (ctx) BN_CTX_free(ctx);
        if (error)
        {
            EVP_PKEY_free(rsa);
            CHECK_OPEN_SSL(0);
        }
    }
    end:

#line 1003 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA__get_key_parameters); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA__get_key_parameters)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	rsaData*	p_rsa;
#line 700 "RSA.xs"
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    BIGNUM* n = NULL;
    BIGNUM* e = NULL;
    BIGNUM* d = NULL;
    BIGNUM* p = NULL;
    BIGNUM* q = NULL;
    BIGNUM* dmp1 = NULL;
    BIGNUM* dmq1 = NULL;
    BIGNUM* iqmp = NULL;
#else
    const BIGNUM* n;
    const BIGNUM* e;
    const BIGNUM* d;
    const BIGNUM* p;
    const BIGNUM* q;
    const BIGNUM* dmp1;
    const BIGNUM* dmq1;
    const BIGNUM* iqmp;
#endif
#line 1041 "RSA.c"

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 720 "RSA.xs"
{
    EVP_PKEY* rsa;
    rsa = p_rsa->rsa;
#if OLD_CRUFTY_SSL_VERSION
    n = rsa->n;
    e = rsa->e;
    d = rsa->d;
    p = rsa->p;
    q = rsa->q;
    dmp1 = rsa->dmp1;
    dmq1 = rsa->dmq1;
    iqmp = rsa->iqmp;
#else
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_N, &n);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_E, &e);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_D, &d);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_FACTOR1, &p);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_FACTOR2, &q);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_EXPONENT1, &dmp1);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_EXPONENT2, &dmq1);
    EVP_PKEY_get_bn_param(rsa, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &iqmp);
#else
    RSA_get0_key(rsa, &n, &e, &d);
    RSA_get0_factors(rsa, &p, &q);
    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
#endif
#endif
    XPUSHs(cor_bn2sv(n));
    XPUSHs(cor_bn2sv(e));
    XPUSHs(cor_bn2sv(d));
    XPUSHs(cor_bn2sv(p));
    XPUSHs(cor_bn2sv(q));
    XPUSHs(cor_bn2sv(dmp1));
    XPUSHs(cor_bn2sv(dmq1));
    XPUSHs(cor_bn2sv(iqmp));
}
#line 1087 "RSA.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_encrypt); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_encrypt)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "p_rsa, p_plaintext");
    {
	rsaData*	p_rsa;
	SV*	p_plaintext = ST(1)
;
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 763 "RSA.xs"
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    RETVAL = rsa_crypt(p_rsa, p_plaintext, EVP_PKEY_encrypt, EVP_PKEY_encrypt_init, 1 /* public */);
#else
    RETVAL = rsa_crypt(p_rsa, p_plaintext, RSA_public_encrypt);
#endif
#line 1118 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_decrypt); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_decrypt)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "p_rsa, p_ciphertext");
    {
	rsaData*	p_rsa;
	SV*	p_ciphertext = ST(1)
;
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 776 "RSA.xs"
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot decrypt");
    }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    RETVAL = rsa_crypt(p_rsa, p_ciphertext, EVP_PKEY_decrypt, EVP_PKEY_decrypt_init, 0 /* private */);
#else
    RETVAL = rsa_crypt(p_rsa, p_ciphertext, RSA_private_decrypt);
#endif
#line 1154 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_private_encrypt); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_private_encrypt)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "p_rsa, p_plaintext");
    {
	rsaData*	p_rsa;
	SV*	p_plaintext = ST(1)
;
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 793 "RSA.xs"
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot private_encrypt");
    }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    RETVAL = rsa_crypt(p_rsa, p_plaintext, EVP_PKEY_sign, EVP_PKEY_sign_init,  0 /* private */);
#else
    RETVAL = rsa_crypt(p_rsa, p_plaintext, RSA_private_encrypt);
#endif
#line 1190 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_public_decrypt); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_public_decrypt)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "p_rsa, p_ciphertext");
    {
	rsaData*	p_rsa;
	SV*	p_ciphertext = ST(1)
;
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 810 "RSA.xs"
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    RETVAL = rsa_crypt(p_rsa, p_ciphertext, EVP_PKEY_verify_recover, EVP_PKEY_verify_recover_init, 1 /*public */);
#else
    RETVAL = rsa_crypt(p_rsa, p_ciphertext, RSA_public_decrypt);
#endif
#line 1222 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_size); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_size)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;
	int	RETVAL;
	dXSTARG;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 822 "RSA.xs"
    RETVAL = EVP_PKEY_get_size(p_rsa->rsa);
#line 1249 "RSA.c"
	XSprePUSH;
	PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_check_key); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_check_key)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;
	int	RETVAL;
	dXSTARG;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 830 "RSA.xs"
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot be checked");
    }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_pkey(NULL, p_rsa->rsa, NULL);
    RETVAL = EVP_PKEY_private_check(pctx);
#else
    RETVAL = RSA_check_key(p_rsa->rsa);
#endif
#line 1285 "RSA.c"
	XSprePUSH;
	PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA__random_seed); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA__random_seed)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "random_bytes_SV");
    {
	SV*	random_bytes_SV = ST(0)
;
#line 850 "RSA.xs"
    STRLEN random_bytes_length;
    char* random_bytes;
#line 1305 "RSA.c"
	int	RETVAL;
	dXSTARG;
#line 853 "RSA.xs"
    random_bytes = SvPV(random_bytes_SV, random_bytes_length);
    RAND_seed(random_bytes, random_bytes_length);
    RETVAL = RAND_status();
#line 1312 "RSA.c"
	XSprePUSH;
	PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA__random_status); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA__random_status)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    {
	int	RETVAL;
	dXSTARG;
#line 864 "RSA.xs"
    RETVAL = RAND_status();
#line 1331 "RSA.c"
	XSprePUSH;
	PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_md5_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_md5_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 872 "RSA.xs"
    p_rsa->hashMode = NID_md5;
#line 1356 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha1_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha1_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 878 "RSA.xs"
    p_rsa->hashMode =  NID_sha1;
#line 1379 "RSA.c"
    }
    XSRETURN_EMPTY;
}

#ifdef SHA512_DIGEST_LENGTH
#define XSubPPtmpAAAA 1


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha224_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha224_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 886 "RSA.xs"
    p_rsa->hashMode =  NID_sha224;
#line 1405 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha256_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha256_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 892 "RSA.xs"
    p_rsa->hashMode =  NID_sha256;
#line 1428 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha384_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha384_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 898 "RSA.xs"
    p_rsa->hashMode =  NID_sha384;
#line 1451 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha512_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sha512_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 904 "RSA.xs"
    p_rsa->hashMode =  NID_sha512;
#line 1474 "RSA.c"
    }
    XSRETURN_EMPTY;
}

#endif

XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_ripemd160_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_ripemd160_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 912 "RSA.xs"
    p_rsa->hashMode =  NID_ripemd160;
#line 1498 "RSA.c"
    }
    XSRETURN_EMPTY;
}

#ifdef WHIRLPOOL_DIGEST_LENGTH
#define XSubPPtmpAAAB 1


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_whirlpool_hash); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_whirlpool_hash)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 920 "RSA.xs"
    p_rsa->hashMode =  NID_whirlpool;
#line 1524 "RSA.c"
    }
    XSRETURN_EMPTY;
}

#endif

XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_no_padding); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_no_padding)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 928 "RSA.xs"
    p_rsa->padding = RSA_NO_PADDING;
#line 1548 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_pkcs1_padding); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_pkcs1_padding)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 934 "RSA.xs"
    croak("PKCS#1 1.5 is disabled as it is known to be vulnerable to marvin attacks.");
#line 1571 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_pkcs1_oaep_padding); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_pkcs1_oaep_padding)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 940 "RSA.xs"
    p_rsa->padding = RSA_PKCS1_OAEP_PADDING;
#line 1594 "RSA.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_pkcs1_pss_padding); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_pkcs1_pss_padding)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 946 "RSA.xs"
    p_rsa->padding = RSA_PKCS1_PSS_PADDING;
#line 1617 "RSA.c"
    }
    XSRETURN_EMPTY;
}

#if OPENSSL_VERSION_NUMBER < 0x30000000L
#define XSubPPtmpAAAC 1


XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sslv23_padding); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_use_sslv23_padding)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 954 "RSA.xs"
    p_rsa->padding = RSA_SSLV23_PADDING;
#line 1643 "RSA.c"
    }
    XSRETURN_EMPTY;
}

#endif

XS_EUPXS(XS_Crypt__OpenSSL__RSA_sign); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_sign)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "p_rsa, text_SV");
    {
	rsaData*	p_rsa;
	SV*	text_SV = ST(1)
;
#line 965 "RSA.xs"
    UNSIGNED_CHAR *signature;
    unsigned char* digest;
    SIZE_T_UNSIGNED_INT signature_length;
#line 1664 "RSA.c"
	SV *	RETVAL;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 969 "RSA.xs"
{
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot sign messages");
    }
    CHECK_NEW(signature, EVP_PKEY_get_size(p_rsa->rsa), UNSIGNED_CHAR);

    CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode));
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    EVP_PKEY_CTX *ctx;
    ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */);
    CHECK_OPEN_SSL(ctx);
    CHECK_OPEN_SSL(EVP_PKEY_sign_init(ctx));
    /* FIXME: Issue setting padding in some cases */
    CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_padding(ctx, p_rsa->padding) > 0);

    EVP_MD* md = get_md_bynid(p_rsa->hashMode);
    CHECK_OPEN_SSL(md != NULL);

    int md_status;
    CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_signature_md(ctx, md)) > 0);
    if (p_rsa->padding == RSA_PKCS1_PSS_PADDING) {
        CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md)) > 0);
        CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) > 0);
    }
    CHECK_OPEN_SSL(EVP_PKEY_sign(ctx, NULL, &signature_length, digest, get_digest_length(p_rsa->hashMode)) == 1);

    //signature = OPENSSL_malloc(signature_length);
    Newx(signature, signature_length, char);

    CHECK_OPEN_SSL(signature);

    CHECK_OPEN_SSL(EVP_PKEY_sign(ctx, signature, &signature_length, digest, get_digest_length(p_rsa->hashMode)) == 1);
    CHECK_OPEN_SSL(signature);
#else
    CHECK_OPEN_SSL(RSA_sign(p_rsa->hashMode,
                            digest,
                            get_digest_length(p_rsa->hashMode),
                            (unsigned char*) signature,
                            &signature_length,
                            p_rsa->rsa));
#endif
    RETVAL = newSVpvn((const char* )signature, signature_length);
    Safefree(signature);
}
#line 1719 "RSA.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_verify); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_verify)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "p_rsa, text_SV, sig_SV");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	rsaData*	p_rsa;
	SV*	text_SV = ST(1)
;
	SV*	sig_SV = ST(2)
;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 1025 "RSA.xs"
{
    unsigned char* sig;
    unsigned char* digest;
    STRLEN sig_length;

    sig = (unsigned char*) SvPV(sig_SV, sig_length);
    if (EVP_PKEY_get_size(p_rsa->rsa) < sig_length)
    {
        croak("Signature longer than key");
    }

    CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode));
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
    EVP_PKEY_CTX *ctx;
    ctx = EVP_PKEY_CTX_new(p_rsa->rsa, NULL /* no engine */);
    CHECK_OPEN_SSL(ctx);
    CHECK_OPEN_SSL(EVP_PKEY_verify_init(ctx) == 1);
    /* FIXME: Issue setting padding in some cases */
    CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_padding(ctx, p_rsa->padding) > 0);

    EVP_MD* md = get_md_bynid(p_rsa->hashMode);
    CHECK_OPEN_SSL(md != NULL);

    int md_status;
    CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_signature_md(ctx, md)) > 0);
    if (p_rsa->padding == RSA_PKCS1_PSS_PADDING) {
        CHECK_OPEN_SSL((md_status = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md)) > 0);
        CHECK_OPEN_SSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) > 0);
    }

    switch (EVP_PKEY_verify(ctx, sig, sig_length, digest, get_digest_length(p_rsa->hashMode)))
#else
    switch(RSA_verify(p_rsa->hashMode,
                      digest,
                      get_digest_length(p_rsa->hashMode),
                      sig,
                      sig_length,
                      p_rsa->rsa))
#endif
    {
        case 0:
            ERR_clear_error();
            XSRETURN_NO;
            break;
        case 1:
            XSRETURN_YES;
            break;
        default:
            CHECK_OPEN_SSL(0);
            break;
    }
}
#line 1801 "RSA.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Crypt__OpenSSL__RSA_is_private); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Crypt__OpenSSL__RSA_is_private)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;
	int	RETVAL;
	dXSTARG;

    if (!(SvROK(ST(0)) && sv_derived_from(ST(0), PACKAGE_NAME)))
    {
        croak("argument is not a rsaData * object");
    }
    p_rsa = (rsaData *) SvIV(SvRV(ST(0)))
;
#line 1082 "RSA.xs"
    RETVAL = _is_private(p_rsa);
#line 1827 "RSA.c"
	XSprePUSH;
	PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}

#ifdef __cplusplus
extern "C" {
#endif
XS_EXTERNAL(boot_Crypt__OpenSSL__RSA); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Crypt__OpenSSL__RSA)
{
#if PERL_VERSION_LE(5, 21, 5)
    dVAR; dXSARGS;
#else
    dVAR; dXSBOOTARGSXSAPIVERCHK;
#endif
#if PERL_VERSION_LE(5, 8, 999) /* PERL_VERSION_LT is 5.33+ */
    char* file = __FILE__;
#else
    const char* file = __FILE__;
#endif

    PERL_UNUSED_VAR(file);

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
#if PERL_VERSION_LE(5, 21, 5)
    XS_VERSION_BOOTCHECK;
#  ifdef XS_APIVERSION_BOOTCHECK
    XS_APIVERSION_BOOTCHECK;
#  endif
#endif

        newXS_deffile("Crypt::OpenSSL::RSA::new_private_key", XS_Crypt__OpenSSL__RSA_new_private_key);
        newXS_deffile("Crypt::OpenSSL::RSA::_new_public_key_pkcs1", XS_Crypt__OpenSSL__RSA__new_public_key_pkcs1);
        newXS_deffile("Crypt::OpenSSL::RSA::_new_public_key_x509", XS_Crypt__OpenSSL__RSA__new_public_key_x509);
        newXS_deffile("Crypt::OpenSSL::RSA::DESTROY", XS_Crypt__OpenSSL__RSA_DESTROY);
        newXS_deffile("Crypt::OpenSSL::RSA::get_private_key_string", XS_Crypt__OpenSSL__RSA_get_private_key_string);
        newXS_deffile("Crypt::OpenSSL::RSA::get_public_key_string", XS_Crypt__OpenSSL__RSA_get_public_key_string);
        newXS_deffile("Crypt::OpenSSL::RSA::get_public_key_x509_string", XS_Crypt__OpenSSL__RSA_get_public_key_x509_string);
        newXS_deffile("Crypt::OpenSSL::RSA::generate_key", XS_Crypt__OpenSSL__RSA_generate_key);
        newXS_deffile("Crypt::OpenSSL::RSA::_new_key_from_parameters", XS_Crypt__OpenSSL__RSA__new_key_from_parameters);
        newXS_deffile("Crypt::OpenSSL::RSA::_get_key_parameters", XS_Crypt__OpenSSL__RSA__get_key_parameters);
        newXS_deffile("Crypt::OpenSSL::RSA::encrypt", XS_Crypt__OpenSSL__RSA_encrypt);
        newXS_deffile("Crypt::OpenSSL::RSA::decrypt", XS_Crypt__OpenSSL__RSA_decrypt);
        newXS_deffile("Crypt::OpenSSL::RSA::private_encrypt", XS_Crypt__OpenSSL__RSA_private_encrypt);
        newXS_deffile("Crypt::OpenSSL::RSA::public_decrypt", XS_Crypt__OpenSSL__RSA_public_decrypt);
        newXS_deffile("Crypt::OpenSSL::RSA::size", XS_Crypt__OpenSSL__RSA_size);
        newXS_deffile("Crypt::OpenSSL::RSA::check_key", XS_Crypt__OpenSSL__RSA_check_key);
        newXS_deffile("Crypt::OpenSSL::RSA::_random_seed", XS_Crypt__OpenSSL__RSA__random_seed);
        newXS_deffile("Crypt::OpenSSL::RSA::_random_status", XS_Crypt__OpenSSL__RSA__random_status);
        newXS_deffile("Crypt::OpenSSL::RSA::use_md5_hash", XS_Crypt__OpenSSL__RSA_use_md5_hash);
        newXS_deffile("Crypt::OpenSSL::RSA::use_sha1_hash", XS_Crypt__OpenSSL__RSA_use_sha1_hash);
#if XSubPPtmpAAAA
        newXS_deffile("Crypt::OpenSSL::RSA::use_sha224_hash", XS_Crypt__OpenSSL__RSA_use_sha224_hash);
        newXS_deffile("Crypt::OpenSSL::RSA::use_sha256_hash", XS_Crypt__OpenSSL__RSA_use_sha256_hash);
        newXS_deffile("Crypt::OpenSSL::RSA::use_sha384_hash", XS_Crypt__OpenSSL__RSA_use_sha384_hash);
        newXS_deffile("Crypt::OpenSSL::RSA::use_sha512_hash", XS_Crypt__OpenSSL__RSA_use_sha512_hash);
#endif
        newXS_deffile("Crypt::OpenSSL::RSA::use_ripemd160_hash", XS_Crypt__OpenSSL__RSA_use_ripemd160_hash);
#if XSubPPtmpAAAB
        newXS_deffile("Crypt::OpenSSL::RSA::use_whirlpool_hash", XS_Crypt__OpenSSL__RSA_use_whirlpool_hash);
#endif
        newXS_deffile("Crypt::OpenSSL::RSA::use_no_padding", XS_Crypt__OpenSSL__RSA_use_no_padding);
        newXS_deffile("Crypt::OpenSSL::RSA::use_pkcs1_padding", XS_Crypt__OpenSSL__RSA_use_pkcs1_padding);
        newXS_deffile("Crypt::OpenSSL::RSA::use_pkcs1_oaep_padding", XS_Crypt__OpenSSL__RSA_use_pkcs1_oaep_padding);
        newXS_deffile("Crypt::OpenSSL::RSA::use_pkcs1_pss_padding", XS_Crypt__OpenSSL__RSA_use_pkcs1_pss_padding);
#if XSubPPtmpAAAC
        newXS_deffile("Crypt::OpenSSL::RSA::use_sslv23_padding", XS_Crypt__OpenSSL__RSA_use_sslv23_padding);
#endif
        newXS_deffile("Crypt::OpenSSL::RSA::sign", XS_Crypt__OpenSSL__RSA_sign);
        newXS_deffile("Crypt::OpenSSL::RSA::verify", XS_Crypt__OpenSSL__RSA_verify);
        newXS_deffile("Crypt::OpenSSL::RSA::is_private", XS_Crypt__OpenSSL__RSA_is_private);

    /* Initialisation Section */

#line 365 "RSA.xs"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();
#else
#endif

#if XSubPPtmpAAAA
#endif
#if XSubPPtmpAAAB
#endif
#if XSubPPtmpAAAC
#endif
#line 1918 "RSA.c"

    /* End of Initialisation Section */

#if PERL_VERSION_LE(5, 21, 5)
#  if PERL_VERSION_GE(5, 9, 0)
    if (PL_unitcheckav)
        call_list(PL_scopestack_ix, PL_unitcheckav);
#  endif
    XSRETURN_YES;
#else
    Perl_xs_boot_epilog(aTHX_ ax);
#endif
}

#ifdef __cplusplus
}
#endif
