/*
 * This file was generated automatically by ExtUtils::ParseXS version 3.35 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>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/ssl.h>

typedef struct
{
    RSA* 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"

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)
{
    const BIGNUM *d;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
    d = p_rsa->rsa->d;
#else
    RSA_get0_key(p_rsa->rsa, NULL, NULL, &d);
#endif
    return(d != NULL);
}

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

    CHECK_NEW(rsa, 1, rsaData);
    rsa->rsa = p_rsa;
#ifdef SHA512_DIGEST_LENGTH
    rsa->hashMode = NID_sha256;
#else
    rsa->hashMode = NID_sha1;
#endif
    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;
    }
}

unsigned char* get_message_digest(SV* text_SV, int hash_method)
{
    STRLEN text_length;
    unsigned char* text;

    text = (unsigned char*) SvPV(text_SV, text_length);

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

SV* 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;
    BUF_MEM* bptr;

    CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1);
    BIO_get_mem_ptr(p_stringBio, &bptr);
    sv = newSVpv(bptr->data, bptr->length);

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

RSA* _load_rsa_key(SV* p_keyStringSv,
                   RSA*(*p_loader)(BIO*, RSA**, pem_password_cb*, void*))
{
    STRLEN keyStringLength;
    char* keyString;

    RSA* rsa;
    BIO* stringBIO;

    keyString = SvPV(p_keyStringSv, keyStringLength);

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

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

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

    CHECK_OPEN_SSL(rsa);
    return rsa;
}

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

    from = (unsigned char*) SvPV(p_from, from_length);
    size = RSA_size(p_rsa->rsa);
    CHECK_NEW(to, size, char);

    to_length = p_crypt(
       from_length, from, (unsigned char*) to, p_rsa->rsa, p_rsa->padding);

    if (to_length < 0)
    {
        Safefree(to);
        CHECK_OPEN_SSL(0);
    }
    sv = newSVpv(to, to_length);
    Safefree(to);
    return sv;
}


#line 240 "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 384 "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)
       croak_xs_usage(cv,  "proto, key_string_SV");
    {
	SV*	proto = ST(0)
;
	SV*	key_string_SV = ST(1)
;
	SV *	RETVAL;
#line 241 "RSA.xs"
    RETVAL = make_rsa_obj(
        proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSAPrivateKey));
#line 401 "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 251 "RSA.xs"
    RETVAL = make_rsa_obj(
        proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSAPublicKey));
#line 424 "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 261 "RSA.xs"
    RETVAL = make_rsa_obj(
        proto, _load_rsa_key(key_string_SV, PEM_read_bio_RSA_PUBKEY));
#line 447 "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 270 "RSA.xs"
    RSA_free(p_rsa->rsa);
    Safefree(p_rsa);
#line 473 "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)
       croak_xs_usage(cv,  "p_rsa");
    {
	rsaData*	p_rsa;
#line 277 "RSA.xs"
    BIO* stringBIO;
#line 489 "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 279 "RSA.xs"
    CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem()));
    PEM_write_bio_RSAPrivateKey(
        stringBIO, p_rsa->rsa, NULL, NULL, 0, NULL, NULL);
    RETVAL = extractBioString(stringBIO);

#line 504 "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 291 "RSA.xs"
    BIO* stringBIO;
#line 522 "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 293 "RSA.xs"
    CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem()));
    PEM_write_bio_RSAPublicKey(stringBIO, p_rsa->rsa);
    RETVAL = extractBioString(stringBIO);

#line 536 "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 304 "RSA.xs"
    BIO* stringBIO;
#line 554 "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 306 "RSA.xs"
    CHECK_OPEN_SSL(stringBIO = BIO_new(BIO_s_mem()));
    PEM_write_bio_RSA_PUBKEY(stringBIO, p_rsa->rsa);
    RETVAL = extractBioString(stringBIO);

#line 568 "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 319 "RSA.xs"
    RSA* rsa;
#line 590 "RSA.c"
	SV *	RETVAL;

	if (items < 3)
	    exponent = 65537;
	else {
	    exponent = (unsigned long)SvUV(ST(2))
;
	}
#line 321 "RSA.xs"
#if OPENSSL_VERSION_NUMBER >= 0x00908000L
    BIGNUM *e;
    int rc;
    e = BN_new();
    BN_set_word(e, exponent);
    rsa = RSA_new();
    rc = RSA_generate_key_ex(rsa, SvIV(bitsSV), e, NULL);
    BN_free(e);
    e = NULL;
    CHECK_OPEN_SSL(rc != -1);
#else
    rsa = RSA_generate_key(SvIV(bitsSV), exponent, NULL, NULL);
#endif
    CHECK_OPEN_SSL(rsa);
    RETVAL = make_rsa_obj(proto, rsa);
#line 615 "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 349 "RSA.xs"
    RSA* rsa;
    BN_CTX* ctx;
    BIGNUM* p_minus_1 = NULL;
    BIGNUM* q_minus_1 = NULL;
    BIGNUM* dmp1 = NULL;
    BIGNUM* dmq1 = NULL;
    BIGNUM* iqmp = NULL;
    int error;
#line 651 "RSA.c"
	SV *	RETVAL;
#line 358 "RSA.xs"
{
    if (!(n && e))
    {
        croak("At least a modulus and public key must be provided");
    }
    CHECK_OPEN_SSL(rsa = RSA_new());
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
    rsa->n = n;
    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 OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
        rsa->p = p;
        rsa->q = q;
#else
        THROW(RSA_set0_factors(rsa, p, q));
#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 OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
        rsa->d = d;
#else
        THROW(RSA_set0_key(rsa, n, e, d));
#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 OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
        rsa->dmp1 = dmp1;
        rsa->dmq1 = dmq1;
        rsa->iqmp = iqmp;
#else
        THROW(RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp));
#endif
        dmp1 = dmq1 = iqmp = NULL;
        THROW(RSA_check_key(rsa) == 1);
     err:
        if (p_minus_1) BN_clear_free(p_minus_1);
        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)
        {
            RSA_free(rsa);
            CHECK_OPEN_SSL(0);
        }
    }
    else
    {
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
        rsa->d = d;
#else
        CHECK_OPEN_SSL(RSA_set0_key(rsa, n, e, d));
#endif
    }
    RETVAL = make_rsa_obj(proto, rsa);
}
#line 737 "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 448 "RSA.xs"
    const BIGNUM* n;
    const BIGNUM* e;
    const BIGNUM* d;
    const BIGNUM* p;
    const BIGNUM* q;
    const BIGNUM* dmp1;
    const BIGNUM* dmq1;
    const BIGNUM* iqmp;
#line 764 "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 457 "RSA.xs"
{
    RSA* rsa;
    rsa = p_rsa->rsa;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
    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
    RSA_get0_key(rsa, &n, &e, &d);
    RSA_get0_factors(rsa, &p, &q);
    RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
#endif
    XPUSHs(bn2sv(n));
    XPUSHs(bn2sv(e));
    XPUSHs(bn2sv(d));
    XPUSHs(bn2sv(p));
    XPUSHs(bn2sv(q));
    XPUSHs(bn2sv(dmp1));
    XPUSHs(bn2sv(dmq1));
    XPUSHs(bn2sv(iqmp));
}
#line 799 "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 489 "RSA.xs"
    RETVAL = rsa_crypt(p_rsa, p_plaintext, RSA_public_encrypt);
#line 826 "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 498 "RSA.xs"
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot decrypt");
    }
    RETVAL = rsa_crypt(p_rsa, p_ciphertext, RSA_private_decrypt);
#line 858 "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 511 "RSA.xs"
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot private_encrypt");
    }
    RETVAL = rsa_crypt(p_rsa, p_plaintext, RSA_private_encrypt);
#line 890 "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 524 "RSA.xs"
    RETVAL = rsa_crypt(p_rsa, p_ciphertext, RSA_public_decrypt);
#line 918 "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 532 "RSA.xs"
    RETVAL = RSA_size(p_rsa->rsa);
#line 945 "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 540 "RSA.xs"
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot be checked");
    }
    RETVAL = RSA_check_key(p_rsa->rsa);
#line 975 "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 555 "RSA.xs"
    STRLEN random_bytes_length;
    char* random_bytes;
#line 994 "RSA.c"
	int	RETVAL;
	dXSTARG;
#line 558 "RSA.xs"
    random_bytes = SvPV(random_bytes_SV, random_bytes_length);
    RAND_seed(random_bytes, random_bytes_length);
    RETVAL = RAND_status();
#line 1001 "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 569 "RSA.xs"
    RETVAL = RAND_status();
#line 1019 "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 577 "RSA.xs"
    p_rsa->hashMode = NID_md5;
#line 1043 "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 583 "RSA.xs"
    p_rsa->hashMode =  NID_sha1;
#line 1066 "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 591 "RSA.xs"
    p_rsa->hashMode =  NID_sha224;
#line 1092 "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 597 "RSA.xs"
    p_rsa->hashMode =  NID_sha256;
#line 1115 "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 603 "RSA.xs"
    p_rsa->hashMode =  NID_sha384;
#line 1138 "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 609 "RSA.xs"
    p_rsa->hashMode =  NID_sha512;
#line 1161 "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 617 "RSA.xs"
    p_rsa->hashMode =  NID_ripemd160;
#line 1185 "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 625 "RSA.xs"
    p_rsa->hashMode =  NID_whirlpool;
#line 1211 "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 633 "RSA.xs"
    p_rsa->padding = RSA_NO_PADDING;
#line 1235 "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 639 "RSA.xs"
    p_rsa->padding = RSA_PKCS1_PADDING;
#line 1258 "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 645 "RSA.xs"
    p_rsa->padding = RSA_PKCS1_OAEP_PADDING;
#line 1281 "RSA.c"
    }
    XSRETURN_EMPTY;
}


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 651 "RSA.xs"
    p_rsa->padding = RSA_SSLV23_PADDING;
#line 1304 "RSA.c"
    }
    XSRETURN_EMPTY;
}


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 660 "RSA.xs"
    char* signature;
    unsigned char* digest;
    unsigned int signature_length;
#line 1324 "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 664 "RSA.xs"
{
    if (!_is_private(p_rsa))
    {
        croak("Public keys cannot sign messages");
    }

    CHECK_NEW(signature, RSA_size(p_rsa->rsa), char);

    CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode));
    CHECK_OPEN_SSL(RSA_sign(p_rsa->hashMode,
                            digest,
                            get_digest_length(p_rsa->hashMode),
                            (unsigned char*) signature,
                            &signature_length,
                            p_rsa->rsa));
    RETVAL = newSVpvn(signature, signature_length);
    Safefree(signature);
}
#line 1352 "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 693 "RSA.xs"
{
    unsigned char* sig;
    unsigned char* digest;
    STRLEN sig_length;

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

    CHECK_OPEN_SSL(digest = get_message_digest(text_SV, p_rsa->hashMode));
    switch(RSA_verify(p_rsa->hashMode,
                      digest,
                      get_digest_length(p_rsa->hashMode),
                      sig,
                      sig_length,
                      p_rsa->rsa))
    {
        case 0:
            CHECK_OPEN_SSL(ERR_peek_error());
            XSRETURN_NO;
            break;
        case 1:
            XSRETURN_YES;
            break;
        default:
            CHECK_OPEN_SSL(0);
            break;
    }
}
#line 1413 "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 729 "RSA.xs"
    RETVAL = _is_private(p_rsa);
#line 1439 "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_REVISION == 5 && PERL_VERSION < 9)
    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_sslv23_padding", XS_Crypt__OpenSSL__RSA_use_sslv23_padding);
        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 234 "RSA.xs"
    ERR_load_crypto_strings();

#if XSubPPtmpAAAA
#endif
#if XSubPPtmpAAAB
#endif
#line 1520 "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
}

