#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <openssl/ssl.h>
#include <openssl/bn.h>
#define checkOpenSslCall( result ) if( ! ( result ) ) \
croak( "OpenSSL error: %s", ERR_reason_error_string( ERR_get_error() ) );
SV* new_obj( SV * p_proto, void* obj )
{
return sv_2mortal( sv_bless( newRV_noinc( newSViv( (IV)obj ) ),
( SvROK( p_proto )
? SvSTASH( SvRV( p_proto ) )
: gv_stashsv( p_proto, 1 ) ) ) );
}
#define proto_obj( obj ) new_obj( ST(0), obj )
BIGNUM* sv2bn( SV* sv )
{
if( ! SvROK( sv ) )
{
croak( "argument is not a Crypt::OpenSSL::Bignum object" );
}
return (BIGNUM*) SvIV( SvRV( sv ) );
}
MODULE = Crypt::OpenSSL::Bignum PACKAGE = Crypt::OpenSSL::Bignum PREFIX=BN_
BOOT:
ERR_load_crypto_strings();
void
_free_BN(self)
BIGNUM* self;
CODE:
BN_clear_free( self );
BIGNUM*
new_from_word(p_proto, p_word)
SV* p_proto;
unsigned long p_word;
PREINIT:
BIGNUM* bn;
CODE:
checkOpenSslCall( bn = BN_new() );
checkOpenSslCall( BN_set_word( bn, p_word ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
new_from_decimal(p_proto, p_dec_string)
SV* p_proto;
char* p_dec_string;
PREINIT:
BIGNUM* bn;
CODE:
bn = NULL;
checkOpenSslCall( BN_dec2bn( &bn, p_dec_string ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
new_from_hex(p_proto, p_hex_string)
SV* p_proto;
char* p_hex_string;
PREINIT:
BIGNUM* bn;
CODE:
bn = NULL;
checkOpenSslCall( BN_hex2bn( &bn, p_hex_string ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
new_from_bin(p_proto, p_bin_string_SV)
SV* p_proto;
SV* p_bin_string_SV;
PREINIT:
BIGNUM* bn;
char* bin;
STRLEN bin_length;
CODE:
bin = SvPV( p_bin_string_SV, bin_length );
checkOpenSslCall( bn = BN_bin2bn( bin, bin_length, NULL ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
zero(p_proto)
SV* p_proto;
PREINIT:
BIGNUM *bn;
CODE:
checkOpenSslCall( bn = BN_new() );
checkOpenSslCall( BN_zero( bn ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
one(p_proto)
SV* p_proto;
PREINIT:
BIGNUM *bn;
CODE:
checkOpenSslCall( bn = BN_new() );
checkOpenSslCall( BN_one( bn ) );
RETVAL = bn;
OUTPUT:
RETVAL
char*
to_decimal(self)
BIGNUM* self;
CODE:
checkOpenSslCall( RETVAL = BN_bn2dec( self ) );
OUTPUT:
RETVAL
CLEANUP:
OPENSSL_free( RETVAL );
char*
to_hex(self)
BIGNUM* self;
CODE:
checkOpenSslCall( RETVAL = BN_bn2hex( self ) );
OUTPUT:
RETVAL
CLEANUP:
OPENSSL_free( RETVAL );
SV*
to_bin(self)
BIGNUM* self;
PREINIT:
char* bin;
int length;
CODE:
length = BN_num_bytes( self );
New( 0, bin, length, char );
BN_bn2bin( self, bin );
RETVAL = newSVpv( bin, length );
Safefree( bin );
OUTPUT:
RETVAL
unsigned long
BN_get_word(self)
BIGNUM* self;
PROTOTYPES: DISABLE
SV*
add(a, b, ...)
BIGNUM* a;
BIGNUM* b;
PREINIT:
BIGNUM *bn;
PPCODE:
if( items > 3 )
croak( "usage: $bn->add( $bn2[, $target] )" );
bn = ( items < 3 ) ? BN_new() : sv2bn( ST(2) );
checkOpenSslCall( BN_add( bn, a, b ) );
ST(0) = ( (items < 3 ) ? proto_obj( bn ) : ST(2) );
XSRETURN(1);
SV*
sub(a, b, ...)
BIGNUM* a;
BIGNUM* b;
PREINIT:
BIGNUM *bn;
PPCODE:
if( items > 3 )
croak( "usage: $bn->sub( $bn2[, $target] )" );
bn = ( items < 3 ) ? BN_new() : sv2bn( ST(2) );
checkOpenSslCall( BN_sub( bn, a, b ) );
ST(0) = ( (items < 3 ) ? proto_obj( bn ) : ST(2) );
XSRETURN(1);
SV*
mul(a, b, ctx, ...)
BIGNUM* a;
BIGNUM* b;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
PPCODE:
if( items > 4 )
croak( "usage: $bn->mul( $bn2, $ctx, [, $target] )" );
bn = ( items < 4 ) ? BN_new() : sv2bn( ST(3) );
checkOpenSslCall( BN_mul( bn, a, b, ctx ) );
ST(0) = ( (items < 4 ) ? proto_obj( bn ) : ST(3) );
XSRETURN(1);
SV*
div(a, b, ctx, ...)
BIGNUM* a;
BIGNUM* b;
BN_CTX* ctx;
PREINIT:
BIGNUM* quotient;
BIGNUM* remainder;
PPCODE:
if( items > 5 )
croak( "usage: $bn->add( $bn2, $ctx, [, $quotient [, $remainder ] ] )" );
quotient = ( items < 4 ) ? BN_new() : sv2bn( ST(3) );
remainder = ( items < 5 ) ? BN_new() : sv2bn( ST(4) );
checkOpenSslCall( BN_div( quotient, remainder, a, b, ctx ) );
ST(0) = ( (items < 4 ) ? proto_obj( quotient ) : ST(3) );
ST(1) = ( (items < 5 ) ? proto_obj( remainder ) : ST(4) );
XSRETURN(2);
BIGNUM*
sqr(a, ctx)
BIGNUM* a;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
SV* p_proto;
CODE:
p_proto = ST(0);
bn = BN_new();
checkOpenSslCall( BN_sqr( bn, a, ctx ) );
RETVAL = bn;
OUTPUT:
RETVAL
SV*
mod(a, b, ctx, ...)
BIGNUM* a;
BIGNUM* b;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
PPCODE:
if( items > 4 )
croak( "usage: $bn->add( $bn2, $ctx, [, $target] )" );
bn = ( items < 4 ) ? BN_new() : sv2bn( ST(3) );
checkOpenSslCall( BN_mod( bn, a, b, ctx ) );
ST(0) = ( (items < 4 ) ? proto_obj( bn ) : ST(3) );
XSRETURN(1);
BIGNUM*
mod_mul(a, b, m, ctx)
BIGNUM* a;
BIGNUM* b;
BIGNUM* m;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
SV* p_proto;
CODE:
p_proto = ST(0);
bn = BN_new();
checkOpenSslCall( BN_mod_mul( bn, a, b, m, ctx ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
exp(a, p, ctx)
BIGNUM* a;
BIGNUM* p;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
SV* p_proto;
CODE:
p_proto = ST(0);
bn = BN_new();
checkOpenSslCall( BN_exp( bn, a, p, ctx ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
mod_exp(a, p, m, ctx)
BIGNUM* a;
BIGNUM* p;
BIGNUM* m;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
SV* p_proto;
CODE:
p_proto = ST(0);
bn = BN_new();
checkOpenSslCall( BN_mod_exp( bn, a, p, m, ctx ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
mod_inverse(a, n, ctx)
BIGNUM* a;
BIGNUM* n;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
SV* p_proto;
CODE:
p_proto = ST(0);
bn = BN_new();
checkOpenSslCall( BN_mod_inverse( bn, a, n, ctx ) );
RETVAL = bn;
OUTPUT:
RETVAL
BIGNUM*
gcd(a, b, ctx)
BIGNUM* a;
BIGNUM* b;
BN_CTX* ctx;
PREINIT:
BIGNUM* bn;
SV* p_proto;
CODE:
p_proto = ST(0);
bn = BN_new();
checkOpenSslCall( BN_gcd( bn, a, b, ctx ) );
RETVAL = bn;
OUTPUT:
RETVAL
int
BN_cmp(a, b)
BIGNUM* a;
BIGNUM* b;
int
BN_is_zero(a)
BIGNUM* a;
int
BN_is_one(a)
BIGNUM* a;
int
BN_is_odd(a)
BIGNUM* a;
BIGNUM*
copy(a)
BIGNUM* a;
PREINIT:
SV* p_proto;
CODE:
p_proto = ST(0);
checkOpenSslCall( RETVAL = BN_dup(a) );
OUTPUT:
RETVAL
IV
pointer_copy(a)
BIGNUM* a;
PREINIT:
CODE:
checkOpenSslCall( RETVAL = (IV) BN_dup(a) );
OUTPUT:
RETVAL
MODULE = Crypt::OpenSSL::Bignum PACKAGE = Crypt::OpenSSL::Bignum::CTX PREFIX=BN_CTX_
BN_CTX*
BN_CTX_new(p_proto)
SV* p_proto;
C_ARGS:
void
_free_BN_CTX(self)
BN_CTX* self;
CODE:
BN_CTX_free( self );