Crypt-NaCl-Sodium
view release on metacpan or search on metacpan
}
}
croak("Failed to get Crypt::NaCl::Sodium::onetimeauth::stream pointer");
return (CryptNaClSodiumOnetimeauthStream*)0; /* some compilers insist on a return value */
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium
BOOT:
{
/* Initialise library */
if ( sodium_init() == -1 )
{
croak("Failed to initialze library");
}
}
PROTOTYPES: ENABLE
const char *
sodium_version_string()
SV *
add(left, right)
SV * left
SV * right
PREINIT:
unsigned char * copy;
INIT:
unsigned char * left_buf;
unsigned char * right_buf;
STRLEN copy_len;
STRLEN left_len;
STRLEN right_len;
CODE:
{
left_buf = (unsigned char *)SvPV(left, left_len);
right_buf = (unsigned char *)SvPV(right, right_len);
if (right_len > left_len) {
croak("You must have a RHS less than or equal in length to the LHS");
}
copy = sodium_malloc(left_len + 1);
if (copy == NULL) {
croak("Could not allocate memory");
}
strcpy(copy, left_buf);
sodium_add(copy, right_buf, right_len);
RETVAL = newSVpvn((const char * const)copy, left_len);
}
OUTPUT:
RETVAL
CLEANUP:
sodium_free(copy);
void
has_aes128ctr()
PPCODE:
{
#ifdef AES128CTR_IS_AVAILABLE
XSRETURN_YES;
#else
XSRETURN_NO;
#endif
}
void
memcmp(left, right, length = 0)
SV * left
SV * right
unsigned long length
INIT:
unsigned char * left_buf;
unsigned char * right_buf;
STRLEN left_len;
STRLEN right_len;
PPCODE:
{
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
left_buf = (unsigned char *)SvPV(left, left_len);
right_buf = (unsigned char *)SvPV(right, right_len);
if ( length == 0 ) {
if ( left_len != right_len ) {
croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
}
length = left_len;
} else {
if ( length > left_len ) {
croak("First argument is shorter then requested length");
}
else if ( length > right_len ) {
croak("Second argument is shorter then requested length");
}
}
if ( sodium_memcmp(left_buf, right_buf, length) == 0 ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
void
compare(left, right, length = 0)
SV * left
SV * right
unsigned long length
INIT:
unsigned char * left_buf;
unsigned char * right_buf;
STRLEN left_len;
STRLEN right_len;
PPCODE:
{
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
left_buf = (unsigned char *)SvPV(left, left_len);
right_buf = (unsigned char *)SvPV(right, right_len);
if ( length == 0 ) {
if ( left_len != right_len ) {
croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
}
length = left_len;
} else {
if ( length > left_len ) {
croak("First argument is shorter then requested length");
}
else if ( length > right_len ) {
croak("Second argument is shorter then requested length");
}
}
XSRETURN_IV( sodium_compare(left_buf, right_buf, length) );
}
void
increment(...)
INIT:
unsigned char * number_buf;
STRLEN len;
unsigned int i;
PPCODE:
{
for ( i = 0; i < items; i++ ) {
if (sv_derived_from(ST(i), "Data::BytesLocker")) {
croak("This function does not handle BytesLocker objects");
}
number_buf = (unsigned char *)SvPV(ST(i), len);
sodium_increment(number_buf, len);
}
XSRETURN_EMPTY;
}
void
memzero(...)
INIT:
unsigned char * buf;
STRLEN len;
unsigned int i;
PPCODE:
{
for ( i = 0; i < items; i++ ) {
buf = (unsigned char *)SvPV_force(ST(i), len);
sodium_memzero( buf, len);
}
XSRETURN_YES;
}
SV *
random_number(...)
INIT:
unsigned int num;
CODE:
{
if ( items == 1 ) {
unsigned int upper_bound = (unsigned int)SvUV(ST(0));
num = randombytes_uniform(upper_bound);
}
else {
num = randombytes_random();
}
RETVAL = newSVuv(num);
}
OUTPUT:
RETVAL
SV *
random_bytes(length)
SV * length
INIT:
size_t len;
DataBytesLocker *bl;
CODE:
{
len = (size_t)SvUV(length);
if ( len < 1 ) {
croak("Invalid length");
};
bl = InitDataBytesLocker(aTHX_ len);
randombytes_buf( bl->bytes, len );
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
SV *
bin2hex(bin_sv)
SV * bin_sv
PREINIT:
char * hex;
unsigned char * bin;
size_t hex_len;
STRLEN bin_len;
CODE:
}
OUTPUT:
RETVAL
SV *
nonce(self, ...)
SV * self
PROTOTYPE: $;$
INIT:
DataBytesLocker *bl;
CODE:
PERL_UNUSED_VAR(self);
if ( items > 2 ) {
croak("Invalid number of arguments");
}
if (items == 2 ) {
if ( SvOK(ST(1)) ) {
STRLEN prev_nonce_len;
unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
if ( prev_nonce_len > crypto_secretbox_NONCEBYTES ) {
croak("Base nonce too long");
}
bl = InitDataBytesLocker(aTHX_ crypto_secretbox_NONCEBYTES);
memcpy(bl->bytes, prev_nonce, prev_nonce_len);
sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
}
else {
croak("Base nonce invalid");
}
}
else {
bl = InitDataBytesLocker(aTHX_ crypto_secretbox_NONCEBYTES);
randombytes_buf(bl->bytes, bl->length);
}
RETVAL = DataBytesLocker2SV(aTHX_ bl);
OUTPUT:
RETVAL
void
encrypt(self, msg, nonce, key)
SV * self
SV * msg
SV * nonce
SV * key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN key_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_secretbox_NONCEBYTES ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_secretbox_KEYBYTES ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
/* detached mode */
if ( GIMME_V == G_ARRAY ) {
DataBytesLocker *bl_mac;
bl = InitDataBytesLocker(aTHX_ msg_len);
bl_mac = InitDataBytesLocker(aTHX_ crypto_secretbox_MACBYTES);
crypto_secretbox_detached( bl->bytes, bl_mac->bytes, (unsigned char *)msg_buf,
(unsigned long long) msg_len, nonce_buf, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl_mac) );
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(2);
}
/* combined mode */
else {
enc_len = crypto_secretbox_MACBYTES + msg_len;
bl = InitDataBytesLocker(aTHX_ enc_len);
crypto_secretbox_easy( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
}
void
decrypt(self, ciphertext, nonce, key)
SV * self
SV * ciphertext
SV * nonce
SV * key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN key_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_secretbox_NONCEBYTES ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_secretbox_KEYBYTES ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
if ( msg_len < crypto_secretbox_MACBYTES ) {
croak("Invalid ciphertext");
}
enc_len = msg_len - crypto_secretbox_MACBYTES;
bl = InitDataBytesLocker(aTHX_ enc_len);
if ( crypto_secretbox_open_easy( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf) == 0 ) {
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
else {
sodium_free(bl->bytes);
Safefree(bl);
croak("Message forged");
}
}
void
decrypt_detached(self, mac, ciphertext, nonce, key)
SV * self
SV * mac
SV * ciphertext
SV * nonce
SV * key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN key_len;
STRLEN mac_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
unsigned char * mac_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_secretbox_NONCEBYTES ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_secretbox_KEYBYTES ) {
croak("Invalid key");
}
mac_buf = (unsigned char *)SvPV(mac, mac_len);
if ( mac_len != crypto_secretbox_MACBYTES ) {
croak("Invalid mac");
}
msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
bl = InitDataBytesLocker(aTHX_ msg_len);
if ( crypto_secretbox_open_detached( bl->bytes, msg_buf, mac_buf, msg_len, nonce_buf, key_buf) == 0 ) {
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
else {
sodium_free(bl->bytes);
Safefree(bl);
croak("Message forged");
}
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth
PROTOTYPES: DISABLE
unsigned int
KEYBYTES(...)
ALIAS:
HMACSHA256_KEYBYTES = 1
HMACSHA512_KEYBYTES = 2
HMACSHA512256_KEYBYTES = 3
CODE:
switch(ix) {
case 1:
RETVAL = crypto_auth_hmacsha256_KEYBYTES;
break;
case 2:
RETVAL = crypto_auth_hmacsha512_KEYBYTES;
break;
case 3:
RETVAL = crypto_auth_hmacsha512256_KEYBYTES;
break;
default:
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 1:
mac_size = crypto_auth_hmacsha256_BYTES;
key_size = crypto_auth_hmacsha256_KEYBYTES;
mac_function = &crypto_auth_hmacsha256;
break;
case 2:
mac_size = crypto_auth_hmacsha512_BYTES;
key_size = crypto_auth_hmacsha512_KEYBYTES;
mac_function = &crypto_auth_hmacsha512;
break;
case 3:
mac_size = crypto_auth_hmacsha512256_BYTES;
key_size = crypto_auth_hmacsha512256_KEYBYTES;
mac_function = &crypto_auth_hmacsha512256;
break;
default:
mac_size = crypto_auth_BYTES;
key_size = crypto_auth_KEYBYTES;
mac_function = &crypto_auth;
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ mac_size);
(*mac_function)( bl->bytes, msg_buf, msg_len, key_buf);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
verify(self, mac, msg, key)
SV * self
SV * mac
SV * msg
SV * key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN key_len;
STRLEN mac_len;
unsigned char * msg_buf;
unsigned char * mac_buf;
unsigned char * key_buf;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
mac_buf = (unsigned char *)SvPV(mac, mac_len);
if ( mac_len != crypto_auth_BYTES ) {
croak("Invalid mac");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_auth_KEYBYTES ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
if ( crypto_auth_verify( mac_buf, msg_buf, msg_len, key_buf) == 0 ) {
XSRETURN_YES;
}
else {
XSRETURN_NO;
}
}
SV *
hmacsha256_verify(self, mac, msg, key)
SV * self
SV * mac
SV * msg
SV * key
PROTOTYPE: $$$$
ALIAS:
hmacsha512_verify = 2
hmacsha512256_verify = 3
INIT:
STRLEN msg_len;
STRLEN key_len;
STRLEN mac_len;
unsigned char * msg_buf;
unsigned char * mac_buf;
unsigned char * key_buf;
unsigned char * expected = NULL;
unsigned int mac_size;
unsigned int key_size;
int free_expected = 0;
int (*verify_function)(const unsigned char *, const unsigned char *, unsigned long long, const unsigned char *);
CODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 2:
msg_buf = (unsigned char *)SvPV(msg, msg_len);
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
expected = sodium_malloc(mac_size+1);
if ( expected == NULL ) {
croak("Could not allocate memory");
}
free_expected = 1;
switch(ix) {
case 2:
{
crypto_auth_hmacsha512_state state_exp;
crypto_auth_hmacsha512_init(&state_exp, key_buf, key_len);
crypto_auth_hmacsha512_update(&state_exp, msg_buf, msg_len);
crypto_auth_hmacsha512_final(&state_exp, expected);
break;
}
case 3:
{
crypto_auth_hmacsha512256_state state_exp;
crypto_auth_hmacsha512256_init(&state_exp, key_buf, key_len);
crypto_auth_hmacsha512256_update(&state_exp, msg_buf, msg_len);
crypto_auth_hmacsha512256_final(&state_exp, expected);
break;
}
default:
{
crypto_auth_hmacsha256_state state_exp;
crypto_auth_hmacsha256_init(&state_exp, key_buf, key_len);
crypto_auth_hmacsha256_update(&state_exp, msg_buf, msg_len);
crypto_auth_hmacsha256_final(&state_exp, expected);
}
}
RETVAL = sodium_memcmp( mac_buf, expected, mac_size ) == 0
? &PL_sv_yes : &PL_sv_no;
} else {
RETVAL = (*verify_function)( mac_buf, msg_buf, msg_len, key_buf ) == 0
? &PL_sv_yes : &PL_sv_no;
}
}
OUTPUT:
RETVAL
CLEANUP:
if ( free_expected ) {
sodium_free(expected);
}
void
hmacsha256_init(self, key)
SV * self
SV * key
PROTOTYPE: $$
INIT:
STRLEN key_len;
unsigned char * key_buf;
CryptNaClSodiumAuthHmacsha256Stream *stream;
PPCODE:
{
PERL_UNUSED_VAR(self);
key_buf = (unsigned char *)SvPV(key, key_len);
Newx(stream, 1, CryptNaClSodiumAuthHmacsha256Stream);
stream->state = sodium_malloc(sizeof(crypto_auth_hmacsha256_state));
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
crypto_auth_hmacsha256_init(stream->state, key_buf, key_len);
ST(0) = sv_2mortal(AuthHmacsha256Stream2SV(aTHX_ stream));
XSRETURN(1);
}
void
hmacsha512_init(self, key)
SV * self
SV * key
PROTOTYPE: $$
INIT:
STRLEN key_len;
unsigned char * key_buf;
CryptNaClSodiumAuthHmacsha512Stream *stream;
PPCODE:
{
PERL_UNUSED_VAR(self);
key_buf = (unsigned char *)SvPV(key, key_len);
Newx(stream, 1, CryptNaClSodiumAuthHmacsha512Stream);
stream->state = sodium_malloc(sizeof(crypto_auth_hmacsha512_state));
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
crypto_auth_hmacsha512_init(stream->state, key_buf, key_len);
ST(0) = sv_2mortal(AuthHmacsha512Stream2SV(aTHX_ stream));
XSRETURN(1);
}
void
hmacsha512256_init(self, key)
SV * self
SV * key
PROTOTYPE: $$
INIT:
STRLEN key_len;
unsigned char * key_buf;
CryptNaClSodiumAuthHmacsha512256Stream *stream;
PPCODE:
{
PERL_UNUSED_VAR(self);
key_buf = (unsigned char *)SvPV(key, key_len);
Newx(stream, 1, CryptNaClSodiumAuthHmacsha512256Stream);
stream->state = sodium_malloc(sizeof(crypto_auth_hmacsha512256_state));
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
crypto_auth_hmacsha512256_init(stream->state, key_buf, key_len);
ST(0) = sv_2mortal(AuthHmacsha512256Stream2SV(aTHX_ stream));
XSRETURN(1);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth::hmacsha256stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha256Stream* cur_stream = GetAuthHmacsha256Stream(aTHX_ self);
INIT:
CryptNaClSodiumAuthHmacsha256Stream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumAuthHmacsha256Stream, auth_hmacsha256, 0, ((void)0))
ST(0) = sv_2mortal(AuthHmacsha256Stream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha256Stream* stream = GetAuthHmacsha256Stream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_auth_hmacsha256_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
SV *
final(self)
SV * self
PROTOTYPE: $
PREINIT:
CryptNaClSodiumAuthHmacsha256Stream* stream = GetAuthHmacsha256Stream(aTHX_ self);
INIT:
DataBytesLocker *bl;
CODE:
{
bl = InitDataBytesLocker(aTHX_ crypto_auth_hmacsha256_BYTES);
crypto_auth_hmacsha256_final(stream->state, bl->bytes);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha256Stream* stream = GetAuthHmacsha256Stream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth::hmacsha512stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha512Stream* cur_stream = GetAuthHmacsha512Stream(aTHX_ self);
INIT:
CryptNaClSodiumAuthHmacsha512Stream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumAuthHmacsha512Stream, auth_hmacsha512, 0, ((void)0))
ST(0) = sv_2mortal(AuthHmacsha512Stream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha512Stream* stream = GetAuthHmacsha512Stream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_auth_hmacsha512_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
SV *
final(self)
SV * self
PROTOTYPE: $
PREINIT:
CryptNaClSodiumAuthHmacsha512Stream* stream = GetAuthHmacsha512Stream(aTHX_ self);
INIT:
DataBytesLocker *bl;
CODE:
{
bl = InitDataBytesLocker(aTHX_ crypto_auth_hmacsha512_BYTES);
crypto_auth_hmacsha512_final(stream->state, bl->bytes);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha512Stream* stream = GetAuthHmacsha512Stream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth::hmacsha512256stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha512256Stream* cur_stream = GetAuthHmacsha512256Stream(aTHX_ self);
INIT:
CryptNaClSodiumAuthHmacsha512256Stream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumAuthHmacsha512256Stream, auth_hmacsha512256, 0, ((void)0))
ST(0) = sv_2mortal(AuthHmacsha512256Stream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha512256Stream* stream = GetAuthHmacsha512256Stream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_auth_hmacsha512256_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
SV *
final(self)
SV * self
PROTOTYPE: $
PREINIT:
CryptNaClSodiumAuthHmacsha512256Stream* stream = GetAuthHmacsha512256Stream(aTHX_ self);
INIT:
DataBytesLocker *bl;
CODE:
{
bl = InitDataBytesLocker(aTHX_ crypto_auth_hmacsha512256_BYTES);
crypto_auth_hmacsha512256_final(stream->state, bl->bytes);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumAuthHmacsha512256Stream* stream = GetAuthHmacsha512256Stream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::aead
PROTOTYPES: DISABLE
unsigned int
KEYBYTES(...)
CODE:
RETVAL = crypto_aead_chacha20poly1305_KEYBYTES;
OUTPUT:
RETVAL
unsigned int
AES256GCM_KEYBYTES(...)
CODE:
#if defined(AES256GCM_IS_AVAILABLE)
RETVAL = crypto_aead_aes256gcm_KEYBYTES;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
OUTPUT:
RETVAL
unsigned int
AES256GCM_NPUBBYTES(...)
CODE:
#if defined(AES256GCM_IS_AVAILABLE)
RETVAL = crypto_aead_aes256gcm_NPUBBYTES;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
OUTPUT:
RETVAL
unsigned int
AES256GCM_ABYTES(...)
CODE:
#if defined(AES256GCM_IS_AVAILABLE)
RETVAL = crypto_aead_aes256gcm_ABYTES;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
OUTPUT:
RETVAL
unsigned int
NPUBBYTES(...)
CODE:
RETVAL = crypto_aead_chacha20poly1305_NPUBBYTES;
OUTPUT:
RETVAL
unsigned int
IETF_NPUBBYTES(...)
CODE:
RETVAL = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
OUTPUT:
RETVAL
unsigned int
ABYTES(...)
CODE:
RETVAL = crypto_aead_chacha20poly1305_ABYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
void
aes256gcm_is_available(self)
SV * self
PPCODE:
{
if ( crypto_aead_aes256gcm_is_available() ) {
XSRETURN_YES;
}
XSRETURN_NO;
}
SV *
keygen(self)
SV * self
ALIAS:
aes256gcm_keygen = 1
INIT:
unsigned int key_size;
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
switch(ix) {
case 1:
#if defined(AES256GCM_IS_AVAILABLE)
key_size = crypto_aead_aes256gcm_KEYBYTES;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
break;
default:
key_size = crypto_aead_chacha20poly1305_KEYBYTES;
}
bl = InitDataBytesLocker(aTHX_ key_size);
randombytes_buf(bl->bytes, key_size);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
SV *
nonce(self, ...)
SV * self
PROTOTYPE: $;$
ALIAS:
ietf_nonce = 1
aes256gcm_nonce = 2
INIT:
unsigned int nonce_size;
DataBytesLocker *bl;
CODE:
PERL_UNUSED_VAR(self);
switch(ix) {
case 1:
nonce_size = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
break;
case 2:
#if defined(AES256GCM_IS_AVAILABLE)
nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
default:
nonce_size = crypto_aead_chacha20poly1305_NPUBBYTES;
}
if ( items > 2 ) {
croak("Invalid number of arguments");
}
if (items == 2 ) {
if ( SvOK(ST(1)) ) {
STRLEN prev_nonce_len;
unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
if ( prev_nonce_len > nonce_size ) {
croak("Base nonce too long");
}
bl = InitDataBytesLocker(aTHX_ nonce_size);
memcpy(bl->bytes, prev_nonce, prev_nonce_len);
sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
}
else {
croak("Base nonce invalid");
}
}
else {
bl = InitDataBytesLocker(aTHX_ nonce_size);
randombytes_buf(bl->bytes, bl->length);
}
RETVAL = DataBytesLocker2SV(aTHX_ bl);
OUTPUT:
RETVAL
void
encrypt(self, msg, adata, nonce, key)
SV * self
SV * msg
SV * adata
SV * nonce
SV * key
PROTOTYPE: $$$$$
ALIAS:
ietf_encrypt = 1
aes256gcm_encrypt = 2
INIT:
STRLEN msg_len;
STRLEN adata_len;
STRLEN nonce_len;
STRLEN key_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * adata_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
unsigned int nonce_size;
unsigned int adlen_size;
unsigned int key_size;
int (*encrypt_function)(unsigned char *, unsigned long long *, const unsigned char *, unsigned long long,
const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *, const unsigned char *);
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 1:
nonce_size = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
key_size = crypto_aead_chacha20poly1305_KEYBYTES;
adlen_size = crypto_aead_chacha20poly1305_ABYTES;
encrypt_function = &crypto_aead_chacha20poly1305_ietf_encrypt;
break;
case 2:
#if defined(AES256GCM_IS_AVAILABLE)
nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
key_size = crypto_aead_aes256gcm_KEYBYTES;
adlen_size = crypto_aead_aes256gcm_ABYTES;
encrypt_function = &crypto_aead_aes256gcm_encrypt;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
break;
default:
nonce_size = crypto_aead_chacha20poly1305_NPUBBYTES;
key_size = crypto_aead_chacha20poly1305_KEYBYTES;
adlen_size = crypto_aead_chacha20poly1305_ABYTES;
encrypt_function = &crypto_aead_chacha20poly1305_encrypt;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != nonce_size ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
adata_buf = (unsigned char *)SvPV(adata, adata_len);
if (msg_len > SIZE_MAX - adlen_size) {
croak("Encrypted length exceeds system memory limit (size_t overflow)");
}
enc_len = msg_len + adlen_size;
bl = InitDataBytesLocker(aTHX_ enc_len);
(*encrypt_function)( bl->bytes, NULL, msg_buf, msg_len,
adata_buf, adata_len, NULL, nonce_buf, key_buf);
bl->bytes[enc_len] = '\0';
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
decrypt(self, msg, adata, nonce, key)
SV * self
SV * msg
SV * adata
SV * nonce
SV * key
PROTOTYPE: $$$$
ALIAS:
ietf_decrypt = 1
aes256gcm_decrypt = 2
INIT:
STRLEN msg_len;
STRLEN adata_len;
STRLEN nonce_len;
STRLEN key_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * adata_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
unsigned int nonce_size;
unsigned int adlen_size;
unsigned int key_size;
int (*decrypt_function)(unsigned char *, unsigned long long *, unsigned char *, const unsigned char *, unsigned long long,
const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 1:
nonce_size = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
key_size = crypto_aead_chacha20poly1305_KEYBYTES;
adlen_size = crypto_aead_chacha20poly1305_ABYTES;
decrypt_function = &crypto_aead_chacha20poly1305_ietf_decrypt;
break;
case 2:
#if defined(AES256GCM_IS_AVAILABLE)
nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
key_size = crypto_aead_aes256gcm_KEYBYTES;
adlen_size = crypto_aead_aes256gcm_ABYTES;
decrypt_function = &crypto_aead_aes256gcm_decrypt;
#else
croak("AES256-GCM is not supported by this CPU");
#endif
break;
default:
nonce_size = crypto_aead_chacha20poly1305_NPUBBYTES;
key_size = crypto_aead_chacha20poly1305_KEYBYTES;
adlen_size = crypto_aead_chacha20poly1305_ABYTES;
decrypt_function = &crypto_aead_chacha20poly1305_decrypt;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != nonce_size ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
if ( msg_len < adlen_size ) {
croak("Invalid ciphertext");
}
adata_buf = (unsigned char *)SvPV(adata, adata_len);
enc_len = msg_len - adlen_size;
bl = InitDataBytesLocker(aTHX_ enc_len);
if ( (*decrypt_function)( bl->bytes, NULL, NULL, msg_buf, msg_len, adata_buf, adata_len, nonce_buf, key_buf) == 0 ) {
bl->bytes[enc_len] = '\0';
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
else {
sodium_free(bl->bytes);
Safefree(bl);
croak("Message forged");
}
}
void
aes256gcm_beforenm(self, key)
SV * self
SV * key
PROTOTYPE: $;%
INIT:
STRLEN key_len = 0;
unsigned char * key_buf = NULL;
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState *state;
#endif
PPCODE:
{
PERL_UNUSED_VAR(self);
#if defined(AES256GCM_IS_AVAILABLE)
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_aead_aes256gcm_KEYBYTES ) {
croak("Invalid key");
}
state = InitAeadAes256gcmState(aTHX_ key_buf);
ST(0) = sv_2mortal(AeadAes256gcmState2SV(aTHX_ state));
XSRETURN(1);
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
void
aes256gcm_encrypt_afternm(self, msg, adata, nonce, precalculated_key)
SV * self
SV * msg
SV * adata
SV * nonce
SV * precalculated_key
PROTOTYPE: $$$$$
INIT:
STRLEN msg_len;
STRLEN adata_len;
STRLEN nonce_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * adata_buf;
unsigned char * nonce_buf;
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState * precal_key;
#endif
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
#if defined(AES256GCM_IS_AVAILABLE)
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_aead_aes256gcm_NPUBBYTES ) {
croak("Invalid nonce");
}
precal_key = GetAeadAes256gcmState(aTHX_ precalculated_key);
if ( precal_key->locked ) {
croak("Unlock AES256GCM precalculated key object before accessing the state");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
adata_buf = (unsigned char *)SvPV(adata, adata_len);
if (msg_len > SIZE_MAX - crypto_aead_aes256gcm_ABYTES) {
croak("Encrypted length exceeds system memory limit (size_t overflow)");
}
enc_len = msg_len + crypto_aead_aes256gcm_ABYTES;
bl = InitDataBytesLocker(aTHX_ enc_len);
crypto_aead_aes256gcm_encrypt_afternm( bl->bytes, NULL, msg_buf, msg_len,
adata_buf, adata_len, NULL, nonce_buf, (const crypto_aead_aes256gcm_state *)precal_key->ctx);
bl->bytes[enc_len] = '\0';
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
void
aes256gcm_decrypt_afternm(self, msg, adata, nonce, precalculated_key)
SV * self
SV * msg
SV * adata
SV * nonce
SV * precalculated_key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN adata_len;
STRLEN nonce_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * adata_buf;
unsigned char * nonce_buf;
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState * precal_key;
#endif
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
#if defined(AES256GCM_IS_AVAILABLE)
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_aead_aes256gcm_NPUBBYTES ) {
croak("Invalid nonce");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
if ( msg_len < crypto_aead_aes256gcm_ABYTES ) {
croak("Invalid ciphertext");
}
precal_key = GetAeadAes256gcmState(aTHX_ precalculated_key);
if ( precal_key->locked ) {
croak("Unlock AES256GCM precalculated key object before accessing the state");
}
adata_buf = (unsigned char *)SvPV(adata, adata_len);
enc_len = msg_len - crypto_aead_aes256gcm_ABYTES;
bl = InitDataBytesLocker(aTHX_ enc_len);
if ( crypto_aead_aes256gcm_decrypt_afternm( bl->bytes, NULL, NULL, msg_buf, msg_len, adata_buf, adata_len, nonce_buf, (const crypto_aead_aes256gcm_state *) precal_key->ctx) == 0 ) {
bl->bytes[enc_len] = '\0';
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
else {
sodium_free(bl->bytes);
Safefree(bl);
croak("Message forged");
}
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::aead::aes256gcmstate
void
lock(self)
SV * self
PPCODE:
{
int rc;
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState* state;
state = GetAeadAes256gcmState(aTHX_ self);
rc = sodium_mprotect_noaccess((void *)state->ctx);
if (rc == 0 ) {
state->locked = 1;
XSRETURN_YES;
}
croak("Unable to lock memory: %s", Strerror(errno));
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
void
unlock(self)
SV * self
PPCODE:
{
int rc;
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState* state;
state = GetAeadAes256gcmState(aTHX_ self);
rc = sodium_mprotect_readonly((void *)state->ctx);
if (rc == 0 ) {
state->locked = 0;
XSRETURN_YES;
}
croak("Unable to unlock memory: %s", Strerror(errno));
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
void
is_locked(self, ...)
SV * self
PPCODE:
{
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState* state;
state = GetAeadAes256gcmState(aTHX_ self);
if ( state->locked ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
void
DESTROY(self)
SV * self
PPCODE:
{
#if defined(AES256GCM_IS_AVAILABLE)
CryptNaClSodiumAeadAes256gcmState* state;
state = GetAeadAes256gcmState(aTHX_ self);
sodium_free( state->ctx );
Safefree(state);
#else
croak("AES256-GCM is not supported by this CPU");
#endif
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::box
PROTOTYPES: DISABLE
unsigned int
PUBLICKEYBYTES(...)
CODE:
RETVAL = crypto_box_PUBLICKEYBYTES;
OUTPUT:
RETVAL
unsigned int
SECRETKEYBYTES(...)
CODE:
RETVAL = crypto_box_SECRETKEYBYTES;
OUTPUT:
RETVAL
unsigned int
NONCEBYTES(...)
CODE:
RETVAL = crypto_box_NONCEBYTES;
OUTPUT:
RETVAL
unsigned int
MACBYTES(...)
CODE:
RETVAL = crypto_box_MACBYTES;
OUTPUT:
RETVAL
unsigned int
SEEDBYTES(...)
CODE:
RETVAL = crypto_box_SEEDBYTES;
OUTPUT:
RETVAL
unsigned int
BEFORENMBYTES(...)
CODE:
RETVAL = crypto_box_BEFORENMBYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
void
keypair(self, ...)
SV * self
PROTOTYPE: $;$
INIT:
DataBytesLocker *blp;
DataBytesLocker *bls;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( items > 2 ) {
croak("Invalid number of arguments");
}
/* from seed */
else if ( items == 2 ) {
if ( SvPOK(ST(1)) || (SvROK(ST(1)) && sv_derived_from(ST(1), "Data::BytesLocker"))) {
STRLEN seed_len;
unsigned char * seed_buf = (unsigned char *)SvPV(ST(1), seed_len);
if ( seed_len != crypto_box_SEEDBYTES ) {
croak("Invalid seed length: %" UVuf, (UV) seed_len);
}
blp = InitDataBytesLocker(aTHX_ crypto_box_PUBLICKEYBYTES);
bls = InitDataBytesLocker(aTHX_ crypto_box_SECRETKEYBYTES);
crypto_box_seed_keypair(blp->bytes, bls->bytes, seed_buf);
} else {
croak("Invalid seed");
}
}
/* regular */
else {
blp = InitDataBytesLocker(aTHX_ crypto_box_PUBLICKEYBYTES);
bls = InitDataBytesLocker(aTHX_ crypto_box_SECRETKEYBYTES);
crypto_box_keypair(blp->bytes, bls->bytes);
}
mXPUSHs( DataBytesLocker2SV(aTHX_ blp) );
mXPUSHs( DataBytesLocker2SV(aTHX_ bls) );
XSRETURN(2);
}
SV *
public_key(self, seckey)
SV * self
SV * seckey
INIT:
DataBytesLocker *bl;
STRLEN skey_len;
unsigned char * skey_buf;
CODE:
{
PERL_UNUSED_VAR(self);
skey_buf = (unsigned char *)SvPV(seckey, skey_len);
if ( skey_len != crypto_box_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
bl = InitDataBytesLocker(aTHX_ crypto_box_PUBLICKEYBYTES);
crypto_scalarmult_base(bl->bytes, skey_buf);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
SV *
nonce(self, ...)
SV * self
PROTOTYPE: $;$
INIT:
DataBytesLocker *bl;
CODE:
PERL_UNUSED_VAR(self);
if ( items > 2 ) {
croak("Invalid number of arguments");
}
if (items == 2 ) {
if ( SvOK(ST(1)) ) {
STRLEN prev_nonce_len;
unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
if ( prev_nonce_len > crypto_box_NONCEBYTES ) {
croak("Base nonce too long");
}
bl = InitDataBytesLocker(aTHX_ crypto_box_NONCEBYTES);
memcpy(bl->bytes, prev_nonce, prev_nonce_len);
sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
}
else {
croak("Base nonce invalid");
}
}
else {
bl = InitDataBytesLocker(aTHX_ crypto_box_NONCEBYTES);
randombytes_buf(bl->bytes, bl->length);
}
RETVAL = DataBytesLocker2SV(aTHX_ bl);
OUTPUT:
RETVAL
void
encrypt(self, msg, nonce, recipient_pubkey, sender_seckey)
SV * self
SV * msg
SV * nonce
SV * recipient_pubkey
SV * sender_seckey
PROTOTYPE: $$$$$
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN pkey_len;
STRLEN skey_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * pkey_buf;
unsigned char * skey_buf;
DataBytesLocker *bl;
DataBytesLocker *blm;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_box_NONCEBYTES ) {
croak("Invalid nonce");
}
pkey_buf = (unsigned char *)SvPV(recipient_pubkey, pkey_len);
if ( pkey_len != crypto_box_PUBLICKEYBYTES ) {
croak("Invalid public key");
}
skey_buf = (unsigned char *)SvPV(sender_seckey, skey_len);
if ( skey_len != crypto_box_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
/* detached mode */
if ( GIMME_V == G_ARRAY ) {
unsigned char *mac;
bl = InitDataBytesLocker(aTHX_ msg_len);
blm = InitDataBytesLocker(aTHX_ crypto_box_MACBYTES);
if ( crypto_box_detached( bl->bytes, blm->bytes, (unsigned char *)msg_buf,
(unsigned long long) msg_len, nonce_buf, pkey_buf, skey_buf) != 0 ) {
sodium_free(bl->bytes);
Safefree(bl);
sodium_free(blm->bytes);
Safefree(blm);
croak("Failed to encrypt data");
}
mXPUSHs( DataBytesLocker2SV(aTHX_ blm) );
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(2);
}
/* combined mode */
else {
enc_len = crypto_box_MACBYTES + msg_len;
bl = InitDataBytesLocker(aTHX_ enc_len);
if ( crypto_box_easy( bl->bytes, msg_buf, msg_len, nonce_buf, pkey_buf, skey_buf) != 0 ) {
sodium_free(bl->bytes);
Safefree(bl);
croak("Failed to encrypt data");
}
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
}
void
encrypt_afternm(self, msg, nonce, precalculated_key)
SV * self
SV * msg
SV * nonce
SV * precalculated_key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN key_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
DataBytesLocker *bl;
DataBytesLocker *blm;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_box_NONCEBYTES ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(precalculated_key, key_len);
if ( key_len != crypto_box_BEFORENMBYTES ) {
croak("Invalid precalculated key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
/* detached mode */
if ( GIMME_V == G_ARRAY ) {
bl = InitDataBytesLocker(aTHX_ msg_len);
blm = InitDataBytesLocker(aTHX_ crypto_box_MACBYTES);
crypto_box_detached_afternm( bl->bytes, blm->bytes, (unsigned char *)msg_buf,
(unsigned long long) msg_len, nonce_buf, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ blm) );
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(2);
}
/* combined mode */
else {
enc_len = crypto_box_MACBYTES + msg_len;
bl = InitDataBytesLocker(aTHX_ enc_len);
crypto_box_easy_afternm( bl->bytes, msg_buf, msg_len,
nonce_buf, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
}
SV *
decrypt(self, ciphertext, nonce, sender_pubkey, recipient_seckey)
SV * self
SV * ciphertext
SV * nonce
SV * sender_pubkey
SV * recipient_seckey
PROTOTYPE: $$$$$
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN pkey_len;
STRLEN skey_len;
STRLEN enc_len;
croak("Invalid mac");
}
msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
bl = InitDataBytesLocker(aTHX_ msg_len);
if ( crypto_box_open_detached_afternm( bl->bytes, msg_buf, mac_buf, msg_len, nonce_buf, key_buf) == 0 ) {
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
else {
sodium_free(bl->bytes);
Safefree(bl);
croak("Message forged");
}
}
OUTPUT:
RETVAL
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::sign
PROTOTYPES: DISABLE
unsigned int
PUBLICKEYBYTES(...)
CODE:
RETVAL = crypto_sign_PUBLICKEYBYTES;
OUTPUT:
RETVAL
unsigned int
SECRETKEYBYTES(...)
CODE:
RETVAL = crypto_sign_SECRETKEYBYTES;
OUTPUT:
RETVAL
unsigned int
BYTES(...)
CODE:
RETVAL = crypto_sign_BYTES;
OUTPUT:
RETVAL
unsigned int
SEEDBYTES(...)
CODE:
RETVAL = crypto_sign_SEEDBYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
void
keypair(self, ...)
SV * self
PROTOTYPE: $;$
INIT:
DataBytesLocker *blp;
DataBytesLocker *bls;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( items > 2 ) {
croak("Invalid number of arguments");
}
/* from seed */
else if ( items == 2 ) {
if ( SvPOK(ST(1)) || (SvROK(ST(1)) && sv_derived_from(ST(1), "Data::BytesLocker"))) {
STRLEN seed_len;
unsigned char * seed_buf = (unsigned char *)SvPV(ST(1), seed_len);
if ( seed_len != crypto_sign_SEEDBYTES ) {
croak("Invalid seed length: %" UVuf, (UV) seed_len);
}
blp = InitDataBytesLocker(aTHX_ crypto_sign_PUBLICKEYBYTES);
bls = InitDataBytesLocker(aTHX_ crypto_sign_SECRETKEYBYTES);
crypto_sign_seed_keypair(blp->bytes, bls->bytes, seed_buf);
} else {
croak("Invalid seed");
}
}
/* regular */
else {
blp = InitDataBytesLocker(aTHX_ crypto_sign_PUBLICKEYBYTES);
bls = InitDataBytesLocker(aTHX_ crypto_sign_SECRETKEYBYTES);
crypto_sign_keypair(blp->bytes, bls->bytes);
}
mXPUSHs( DataBytesLocker2SV(aTHX_ blp) );
mXPUSHs( DataBytesLocker2SV(aTHX_ bls) );
XSRETURN(2);
}
void
to_curve25519_keypair(self, pubkey, seckey)
SV * self
SV * pubkey
SV * seckey
PROTOTYPE: $$$
INIT:
STRLEN pkey_len;
STRLEN skey_len;
unsigned char * pkey_buf;
unsigned char * skey_buf;
DataBytesLocker *blp;
DataBytesLocker *bls;
PPCODE:
{
PERL_UNUSED_VAR(self);
pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
if ( pkey_len != crypto_sign_ed25519_PUBLICKEYBYTES ) {
croak("Invalid public key");
}
skey_buf = (unsigned char *)SvPV(seckey, skey_len);
if ( skey_len != crypto_sign_ed25519_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
blp = InitDataBytesLocker(aTHX_ crypto_scalarmult_curve25519_BYTES);
if ( crypto_sign_ed25519_pk_to_curve25519( blp->bytes, pkey_buf) != 0 ) {
sodium_free(blp->bytes);
Safefree(blp);
croak("Conversion of public key failed");
}
bls = InitDataBytesLocker(aTHX_ crypto_scalarmult_curve25519_BYTES);
if ( crypto_sign_ed25519_sk_to_curve25519( bls->bytes, skey_buf) != 0 ) {
sodium_free(bls->bytes);
Safefree(bls);
croak("Conversion of secret key failed");
}
mXPUSHs( DataBytesLocker2SV(aTHX_ blp) );
mXPUSHs( DataBytesLocker2SV(aTHX_ bls) );
XSRETURN(2);
}
void
public_key(self, seckey)
SV * self
SV * seckey
INIT:
STRLEN skey_len;
unsigned char * skey_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
skey_buf = (unsigned char *)SvPV(seckey, skey_len);
if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
bl = InitDataBytesLocker(aTHX_ crypto_sign_PUBLICKEYBYTES);
crypto_sign_ed25519_sk_to_pk(bl->bytes, skey_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
extract_seed(self, seckey)
SV * self
SV * seckey
INIT:
STRLEN skey_len;
unsigned char * skey_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
skey_buf = (unsigned char *)SvPV(seckey, skey_len);
if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
bl = InitDataBytesLocker(aTHX_ crypto_sign_SEEDBYTES);
crypto_sign_ed25519_sk_to_seed(bl->bytes, skey_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
seed(self)
SV * self
INIT:
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
bl = InitDataBytesLocker(aTHX_ crypto_sign_SEEDBYTES);
randombytes_buf(bl->bytes, bl->length);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
seal(self, msg, seckey)
SV * self
SV * msg
SV * seckey
PROTOTYPE: $$$
INIT:
STRLEN msg_len;
STRLEN skey_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * skey_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
skey_buf = (unsigned char *)SvPV(seckey, skey_len);
if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
if (msg_len > SIZE_MAX - crypto_sign_BYTES) {
croak("Encrypted length exceeds system memory limit (size_t overflow)");
}
enc_len = crypto_sign_BYTES + msg_len;
bl = InitDataBytesLocker(aTHX_ enc_len);
crypto_sign( bl->bytes, NULL, msg_buf, msg_len, skey_buf);
bl->bytes[enc_len] = '\0';
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
mac(self, msg, seckey)
SV * self
SV * msg
SV * seckey
PROTOTYPE: $$$
INIT:
STRLEN msg_len;
STRLEN skey_len;
unsigned char * msg_buf;
unsigned char * skey_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
skey_buf = (unsigned char *)SvPV(seckey, skey_len);
if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
croak("Invalid secret key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ crypto_sign_BYTES);
crypto_sign_detached( bl->bytes, NULL, (unsigned char *)msg_buf,
(unsigned long long) msg_len, skey_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
verify(self, sig, msg, pubkey)
SV * self
SV * sig
SV * msg
SV * pubkey
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN sig_len;
STRLEN pkey_len;
unsigned char * msg_buf;
unsigned char * sig_buf;
unsigned char * pkey_buf;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
sig_buf = (unsigned char *)SvPV(sig, sig_len);
if ( sig_len != crypto_sign_BYTES ) {
croak("Invalid signature");
}
pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
if ( pkey_len != crypto_sign_PUBLICKEYBYTES ) {
croak("Invalid public key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
if ( crypto_sign_verify_detached( sig_buf, msg_buf, msg_len, pkey_buf) == 0 ) {
XSRETURN_YES;
}
else {
XSRETURN_NO;
}
}
void
open(self, smsg, pubkey)
SV * self
SV * smsg
SV * pubkey
PROTOTYPE: $$$
INIT:
STRLEN msg_len;
STRLEN pkey_len;
STRLEN enc_len;
unsigned char * msg_buf;
unsigned char * pkey_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
if ( pkey_len != crypto_sign_PUBLICKEYBYTES ) {
croak("Invalid public key");
}
msg_buf = (unsigned char *)SvPV(smsg, msg_len);
if ( msg_len < crypto_sign_BYTES ) {
croak("Invalid input data");
}
enc_len = msg_len - crypto_sign_BYTES;
bl = InitDataBytesLocker(aTHX_ enc_len);
if ( crypto_sign_open( bl->bytes, NULL, msg_buf, msg_len, pkey_buf) == 0 ) {
bl->bytes[enc_len] = '\0';
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
else {
sodium_free(bl->bytes);
Safefree(bl);
croak("Message forged");
}
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::generichash
PROTOTYPES: DISABLE
unsigned int
BYTES(...)
CODE:
RETVAL = crypto_generichash_BYTES;
OUTPUT:
RETVAL
unsigned int
BYTES_MIN(...)
CODE:
RETVAL = crypto_generichash_BYTES_MIN;
OUTPUT:
RETVAL
unsigned int
BYTES_MAX(...)
CODE:
RETVAL = crypto_generichash_BYTES_MAX;
OUTPUT:
RETVAL
unsigned int
KEYBYTES(...)
CODE:
RETVAL = crypto_generichash_KEYBYTES;
OUTPUT:
RETVAL
unsigned int
KEYBYTES_MIN(...)
CODE:
RETVAL = crypto_generichash_KEYBYTES_MIN;
OUTPUT:
RETVAL
unsigned int
KEYBYTES_MAX(...)
CODE:
RETVAL = crypto_generichash_KEYBYTES_MAX;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
SV *
keygen(self, keybytes = crypto_generichash_KEYBYTES)
SV * self
size_t keybytes
INIT:
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
if ( keybytes < crypto_generichash_KEYBYTES_MIN || keybytes > crypto_generichash_KEYBYTES_MAX ) {
croak("Invalid keybytes value: %" UVuf, (UV) keybytes);
}
bl = InitDataBytesLocker(aTHX_ keybytes);
randombytes_buf(bl->bytes, bl->length);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
mac(self, msg, ...)
SV * self
SV * msg
PROTOTYPE: $$;%
INIT:
unsigned char * msg_buf;
DataBytesLocker *bl;
unsigned char * key_buf = NULL;
STRLEN msg_len = 0;
STRLEN key_len = 0;
size_t bytes = crypto_generichash_BYTES;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( items > 2 && ( items > 6 || items % 2 != 0 ) ) {
croak("Invalid number of arguments");
} else if ( items > 2 ) {
int i = 0;
STRLEN keylen = 0;
char * key;
for ( i = 2; i < items; i += 2 ) {
key = SvPV(ST(i), keylen);
if ( keylen == 3 && strnEQ(key, "key", 3) ) {
key_buf = (unsigned char *)SvPV(ST(i+1), key_len);
if ( key_len < crypto_generichash_KEYBYTES_MIN || key_len > crypto_generichash_KEYBYTES_MAX ) {
croak("Invalid key length: %" UVuf, (UV) key_len);
}
}
else if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
bytes = (size_t)SvUV(ST(i+1));
if ( bytes < crypto_generichash_BYTES_MIN || bytes > crypto_generichash_BYTES_MAX ) {
croak("Invalid bytes value: %" UVuf, (UV) bytes);
}
} else {
croak("Invalid argument: %s", key);
}
}
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ bytes);
crypto_generichash(bl->bytes, bytes, msg_buf, msg_len, key_buf, key_len);
ST(0) = sv_2mortal(DataBytesLocker2SV(aTHX_ bl));
XSRETURN(1);
}
void
init(self, ...)
SV * self
PROTOTYPE: $;%
INIT:
STRLEN key_len = 0;
unsigned char * key_buf = NULL;
CryptNaClSodiumGenerichashStream *stream;
size_t bytes = crypto_generichash_BYTES;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( items > 1 && ( items > 5 || (items + 1) % 2 != 0 ) ) {
croak("Invalid number of arguments");
} else if ( items > 1 ) {
int i = 0;
STRLEN keylen = 0;
char * key;
for ( i = 1; i < items; i += 2 ) {
key = (char *)SvPV(ST(i), keylen);
if ( keylen == 3 && strnEQ(key, "key", 3) ) {
key_buf = (unsigned char *)SvPV(ST(i+1), key_len);
if ( key_len < crypto_generichash_KEYBYTES_MIN || key_len > crypto_generichash_KEYBYTES_MAX ) {
croak("Invalid key length: %" UVuf, (UV) key_len);
}
}
else if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
bytes = SvUV(ST(i+1));
if ( bytes < crypto_generichash_BYTES_MIN || bytes > crypto_generichash_BYTES_MAX ) {
croak("Invalid bytes value: %" UVuf, (UV) bytes);
}
} else {
croak("Invalid argument: %s", key);
}
}
}
Newx(stream, 1, CryptNaClSodiumGenerichashStream);
stream->state = sodium_malloc(sizeof(crypto_generichash_state) + (size_t)63U & ~(size_t) 63U);
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
stream->init_bytes = bytes;
crypto_generichash_init(stream->state, key_buf, key_len, bytes);
ST(0) = sv_2mortal(GenerichashStream2SV(aTHX_ stream));
XSRETURN(1);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::generichash::stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumGenerichashStream* cur_stream = GetGenerichashStream(aTHX_ self);
INIT:
CryptNaClSodiumGenerichashStream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumGenerichashStream, generichash, (size_t)63U & ~(size_t) 63U, new_stream->init_bytes=cur_stream->init_bytes)
ST(0) = sv_2mortal(GenerichashStream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumGenerichashStream* stream = GetGenerichashStream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_generichash_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
void
final(self, ...)
SV * self
PROTOTYPE: $%
PREINIT:
CryptNaClSodiumGenerichashStream* stream = GetGenerichashStream(aTHX_ self);
INIT:
DataBytesLocker *bl;
size_t bytes;
PPCODE:
{
bytes = stream->init_bytes;
if ( items > 1 && items != 3 ) {
croak("Invalid number of arguments");
} else if ( items > 1 ) {
int i = 0;
STRLEN keylen = 0;
char * key;
for ( i = 1; i < items; i += 2 ) {
key = (char *)SvPV(ST(i), keylen);
if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
bytes = SvUV(ST(i+1));
if ( bytes < crypto_generichash_BYTES_MIN || bytes > crypto_generichash_BYTES_MAX ) {
croak("Invalid bytes value: %" UVuf, (UV) bytes);
}
} else {
croak("Invalid argument: %s", key);
}
}
}
bl = InitDataBytesLocker(aTHX_ bytes);
crypto_generichash_final(stream->state, bl->bytes, bytes);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumGenerichashStream* stream = GetGenerichashStream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::shorthash
PROTOTYPES: DISABLE
unsigned int
BYTES(...)
CODE:
RETVAL = crypto_shorthash_BYTES;
OUTPUT:
RETVAL
unsigned int
KEYBYTES(...)
CODE:
RETVAL = crypto_shorthash_KEYBYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
SV *
keygen(self)
SV * self
INIT:
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
bl = InitDataBytesLocker(aTHX_ crypto_shorthash_KEYBYTES);
randombytes_buf(bl->bytes, bl->length);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
SV *
mac(self, msg, key)
SV * self
SV * msg
SV * key
PROTOTYPE: $$$
INIT:
STRLEN msg_len = 0;
STRLEN key_len = 0;
unsigned char * msg_buf;
unsigned char * key_buf;
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
OUTPUT:
RETVAL
unsigned long
MEMLIMIT_INTERACTIVE(...)
CODE:
RETVAL = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
OUTPUT:
RETVAL
unsigned long
OPSLIMIT_SENSITIVE(...)
CODE:
RETVAL = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
OUTPUT:
RETVAL
unsigned long
MEMLIMIT_SENSITIVE(...)
CODE:
RETVAL = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
SV *
salt(self)
SV * self
INIT:
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
bl = InitDataBytesLocker(aTHX_ crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
randombytes_buf(bl->bytes, bl->length);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
key(self, passphrase, salt, ... )
SV * self
SV * salt
SV * passphrase
PROTOTYPE: $$$$;%
INIT:
DataBytesLocker *bl;
STRLEN pwd_len = 0;
STRLEN salt_len = 0;
char * pwd_buf;
unsigned char * salt_buf;
unsigned long long outlen = crypto_pwhash_scryptsalsa208sha256_STRBYTES;
unsigned long long opslimit = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
size_t memlimit = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( items > 3 && ( ( items + 1 ) % 2 != 0 || items > 9 ) ) {
croak("Invalid number of arguments");
} else if ( items > 4 ) {
int i = 0;
STRLEN keylen = 0;
char * key;
for ( i = 3; i < items; i += 2 ) {
key = (char *)SvPV(ST(i), keylen);
if ( keylen == 8 && strnEQ(key, "opslimit", 8) ) {
opslimit = (unsigned long long)SvUV(ST(i+1));
if ( opslimit < 1 ) {
croak("Invalid opslimit: %" UVuf, (UV) opslimit);
}
} else if ( keylen == 8 && strnEQ(key, "memlimit", 8) ) {
memlimit = (unsigned long long)SvUV(ST(i+1));
if ( memlimit < 1 ) {
croak("Invalid memlimit: %" UVuf, (UV) memlimit);
}
} else if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
outlen = (unsigned long long)SvUV(ST(i+1));
if ( outlen < 1 ) {
croak("Invalid bytes: %" UVuf, (UV) outlen);
}
} else {
croak("Invalid argument: %s", key);
}
}
}
salt_buf = (unsigned char *)SvPV(salt, salt_len);
if ( salt_len != crypto_pwhash_scryptsalsa208sha256_SALTBYTES ) {
croak("Invalid salt");
}
pwd_buf = (char *)SvPV(passphrase, pwd_len);
bl = InitDataBytesLocker(aTHX_ outlen);
if ( crypto_pwhash_scryptsalsa208sha256(bl->bytes, outlen, pwd_buf, pwd_len, salt_buf, opslimit, memlimit) != 0 ) {
sodium_free( bl->bytes );
Safefree(bl);
croak("Out of memory");
}
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
str(self, passphrase, ... )
SV * self
SV * passphrase
PROTOTYPE: $$;%
INIT:
DataBytesLocker *bl;
STRLEN pwd_len = 0;
char * pwd_buf;
unsigned long long opslimit = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
size_t memlimit = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( items > 2 && ( items % 2 != 0 || items > 6 ) ) {
croak("Invalid number of arguments");
} else if ( items > 2 ) {
int i = 0;
STRLEN keylen = 0;
char * key;
for ( i = 2; i < items; i += 2 ) {
key = (char *)SvPV(ST(i), keylen);
if ( keylen == 8 && strnEQ(key, "opslimit", 8) ) {
opslimit = SvUV(ST(i+1));
if ( opslimit < 1 ) {
croak("Invalid opslimit: %" UVuf, (UV) opslimit);
}
} else if ( keylen == 8 && strnEQ(key, "memlimit", 8) ) {
memlimit = SvUV(ST(i+1));
if ( memlimit < 1 ) {
croak("Invalid memlimit: %" UVuf, (UV) memlimit);
}
} else {
croak("Invalid argument: %s", key);
}
}
}
pwd_buf = (char *)SvPV(passphrase, pwd_len);
bl = InitDataBytesLocker(aTHX_ crypto_pwhash_scryptsalsa208sha256_STRBYTES);
if ( crypto_pwhash_scryptsalsa208sha256_str((char *)bl->bytes, pwd_buf, pwd_len, opslimit, memlimit) != 0 ) {
sodium_free( bl->bytes );
Safefree(bl);
croak("Out of memory");
}
bl->bytes[crypto_pwhash_scryptsalsa208sha256_STRBYTES] = 0;
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
SV *
verify(self, str, passphrase )
SV * self
SV * str
SV * passphrase
PROTOTYPE: $$$
INIT:
STRLEN str_len;
STRLEN pwd_len;
char * str_buf;
char * pwd_buf;
int res = 0;
CODE:
{
PERL_UNUSED_VAR(self);
str_buf = (char *)SvPV(str, str_len);
croak("Could not allocate memory");
}
memcpy(str102, str_buf, str_len);
str102[crypto_pwhash_scryptsalsa208sha256_STRBYTES-1] = 0;
res = crypto_pwhash_scryptsalsa208sha256_str_verify( str102, pwd_buf, pwd_len) == 0;
sodium_free(str102);
}
/* already includes null byte */
else if ( str_len == crypto_pwhash_scryptsalsa208sha256_STRBYTES
&&
str_buf[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1] == 0
) {
pwd_buf = (char *)SvPV(passphrase, pwd_len);
res = crypto_pwhash_scryptsalsa208sha256_str_verify( str_buf, pwd_buf, pwd_len) == 0;
}
else {
croak("Invalid string");
}
RETVAL = res ? &PL_sv_yes : &PL_sv_no;
}
OUTPUT:
RETVAL
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::hash
PROTOTYPES: DISABLE
unsigned int
SHA256_BYTES(...)
CODE:
RETVAL = crypto_hash_sha256_BYTES;
OUTPUT:
RETVAL
unsigned int
SHA512_BYTES(...)
CODE:
RETVAL = crypto_hash_sha512_BYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
void
sha256(self, msg)
SV * self
SV * msg
PROTOTYPE: $$
ALIAS:
sha512 = 1
INIT:
STRLEN msg_len = 0;
unsigned char * msg_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
msg_buf = (unsigned char *)SvPV(msg, msg_len);
switch(ix) {
case 1:
bl = InitDataBytesLocker(aTHX_ crypto_hash_sha512_BYTES);
crypto_hash_sha512(bl->bytes, msg_buf, msg_len);
break;
default:
bl = InitDataBytesLocker(aTHX_ crypto_hash_sha256_BYTES);
crypto_hash_sha256(bl->bytes, msg_buf, msg_len);
}
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
sha256_init(self)
SV * self
PROTOTYPE: $
INIT:
CryptNaClSodiumHashSha256Stream *stream;
PPCODE:
{
PERL_UNUSED_VAR(self);
Newx(stream, 1, CryptNaClSodiumHashSha256Stream);
stream->state = sodium_malloc(sizeof(crypto_hash_sha256_state));
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
crypto_hash_sha256_init(stream->state);
ST(0) = sv_2mortal(HashSha256Stream2SV(aTHX_ stream));
XSRETURN(1);
}
void
sha512_init(self)
SV * self
PROTOTYPE: $
INIT:
CryptNaClSodiumHashSha512Stream *stream;
PPCODE:
{
PERL_UNUSED_VAR(self);
Newx(stream, 1, CryptNaClSodiumHashSha512Stream);
stream->state = sodium_malloc(sizeof(crypto_hash_sha512_state));
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
crypto_hash_sha512_init(stream->state);
ST(0) = sv_2mortal(HashSha512Stream2SV(aTHX_ stream));
XSRETURN(1);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::hash::sha256stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumHashSha256Stream* cur_stream = GetHashSha256Stream(aTHX_ self);
INIT:
CryptNaClSodiumHashSha256Stream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumHashSha256Stream, hash_sha256, 0, ((void)0))
ST(0) = sv_2mortal(HashSha256Stream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumHashSha256Stream* stream = GetHashSha256Stream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_hash_sha256_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
void
final(self)
SV * self
PROTOTYPE: $
PREINIT:
CryptNaClSodiumHashSha256Stream* stream = GetHashSha256Stream(aTHX_ self);
INIT:
DataBytesLocker *bl;
PPCODE:
{
bl = InitDataBytesLocker(aTHX_ crypto_hash_sha256_BYTES);
crypto_hash_sha256_final(stream->state, bl->bytes);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumHashSha256Stream* stream = GetHashSha256Stream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::hash::sha512stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumHashSha512Stream* cur_stream = GetHashSha512Stream(aTHX_ self);
INIT:
CryptNaClSodiumHashSha512Stream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumHashSha512Stream, hash_sha512, 0, ((void)0))
ST(0) = sv_2mortal(HashSha512Stream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumHashSha512Stream* stream = GetHashSha512Stream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_hash_sha512_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
void
final(self)
SV * self
PROTOTYPE: $
PREINIT:
CryptNaClSodiumHashSha512Stream* stream = GetHashSha512Stream(aTHX_ self);
INIT:
DataBytesLocker *bl;
PPCODE:
{
bl = InitDataBytesLocker(aTHX_ crypto_hash_sha512_BYTES);
crypto_hash_sha512_final(stream->state, bl->bytes);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumHashSha512Stream* stream = GetHashSha512Stream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::onetimeauth
PROTOTYPES: DISABLE
unsigned int
BYTES(...)
CODE:
RETVAL = crypto_onetimeauth_BYTES;
OUTPUT:
RETVAL
unsigned int
KEYBYTES(...)
CODE:
RETVAL = crypto_onetimeauth_KEYBYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
SV *
keygen(self)
SV * self
INIT:
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
bl = InitDataBytesLocker(aTHX_ crypto_onetimeauth_KEYBYTES);
randombytes_buf(bl->bytes, bl->length);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
mac(self, msg, key)
SV * self
SV * msg
SV * key
PROTOTYPE: $$$
INIT:
STRLEN msg_len;
STRLEN key_len;
unsigned char * msg_buf;
unsigned char * key_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_onetimeauth_KEYBYTES ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ crypto_onetimeauth_BYTES);
crypto_onetimeauth(bl->bytes, msg_buf, msg_len, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
verify(self, mac, msg, key)
SV * self
SV * mac
SV * msg
SV * key
PROTOTYPE: $$$$
INIT:
STRLEN msg_len;
STRLEN key_len;
STRLEN mac_len;
unsigned char * msg_buf;
unsigned char * mac_buf;
unsigned char * key_buf;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
mac_buf = (unsigned char *)SvPV(mac, mac_len);
if ( mac_len != crypto_onetimeauth_BYTES ) {
croak("Invalid mac");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_onetimeauth_KEYBYTES ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
if ( crypto_onetimeauth_verify( mac_buf, msg_buf, msg_len, key_buf) == 0 ) {
XSRETURN_YES;
}
else {
XSRETURN_NO;
}
}
void
init(self, key)
SV * self
SV * key
PROTOTYPE: $;%
INIT:
STRLEN key_len;
unsigned char * key_buf;
CryptNaClSodiumOnetimeauthStream *stream;
PPCODE:
{
PERL_UNUSED_VAR(self);
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_onetimeauth_KEYBYTES ) {
croak("Invalid key");
}
Newx(stream, 1, CryptNaClSodiumOnetimeauthStream);
stream->state = sodium_malloc(sizeof(crypto_onetimeauth_state));
if ( stream->state == NULL ) {
croak("Could not allocate memory");
}
crypto_onetimeauth_init(stream->state, key_buf);
ST(0) = sv_2mortal(OnetimeauthStream2SV(aTHX_ stream));
XSRETURN(1);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::onetimeauth::stream
void
clone(self)
SV * self
PREINIT:
CryptNaClSodiumOnetimeauthStream* cur_stream = GetOnetimeauthStream(aTHX_ self);
INIT:
CryptNaClSodiumOnetimeauthStream* new_stream;
PPCODE:
{
CLONESTATE(CryptNaClSodiumOnetimeauthStream, onetimeauth, 0, ((void)0))
ST(0) = sv_2mortal(OnetimeauthStream2SV(aTHX_ new_stream));
XSRETURN(1);
}
void
update(self, ...)
SV * self
PREINIT:
CryptNaClSodiumOnetimeauthStream* stream = GetOnetimeauthStream(aTHX_ self);
INIT:
STRLEN msg_len;
unsigned char * msg_buf;
int i;
PPCODE:
{
for ( i = 1; i < items ; i++ ) {
msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
crypto_onetimeauth_update(stream->state, msg_buf, msg_len);
}
XSRETURN(1);
}
void
final(self)
SV * self
PROTOTYPE: $
PREINIT:
CryptNaClSodiumOnetimeauthStream* stream = GetOnetimeauthStream(aTHX_ self);
INIT:
DataBytesLocker *bl;
PPCODE:
{
bl = InitDataBytesLocker(aTHX_ crypto_onetimeauth_BYTES);
crypto_onetimeauth_final(stream->state, bl->bytes);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
DESTROY(self)
SV * self
PREINIT:
CryptNaClSodiumOnetimeauthStream* stream = GetOnetimeauthStream(aTHX_ self);
PPCODE:
{
sodium_free( stream->state );
Safefree(stream);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::scalarmult
PROTOTYPES: DISABLE
unsigned int
BYTES(...)
CODE:
RETVAL = crypto_scalarmult_BYTES;
OUTPUT:
RETVAL
unsigned int
SCALARBYTES(...)
CODE:
RETVAL = crypto_scalarmult_SCALARBYTES;
OUTPUT:
RETVAL
PROTOTYPES: ENABLE
SV *
keygen(self)
SV * self
INIT:
DataBytesLocker *bl;
CODE:
{
PERL_UNUSED_VAR(self);
bl = InitDataBytesLocker(aTHX_ crypto_scalarmult_SCALARBYTES);
randombytes_buf(bl->bytes, bl->length);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
base(self, secret_key)
SV * self
SV * secret_key
PROTOTYPE: $$
INIT:
STRLEN key_len;
unsigned char * key_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
key_buf = (unsigned char *)SvPV(secret_key, key_len);
if ( key_len != crypto_scalarmult_SCALARBYTES ) {
croak("Invalid key");
}
bl = InitDataBytesLocker(aTHX_ crypto_scalarmult_BYTES);
crypto_scalarmult_base( bl->bytes, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
shared_secret(self, secret_key, public_key)
SV * self
SV * secret_key
SV * public_key
PROTOTYPE: $$$$
INIT:
STRLEN skey_len;
STRLEN pkey_len;
unsigned char * skey_buf;
unsigned char * pkey_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
skey_buf = (unsigned char *)SvPV(secret_key, skey_len);
if ( skey_len != crypto_scalarmult_SCALARBYTES ) {
croak("Invalid secret key");
}
pkey_buf = (unsigned char *)SvPV(public_key, pkey_len);
if ( pkey_len != crypto_scalarmult_SCALARBYTES ) {
croak("Invalid public key");
}
bl = InitDataBytesLocker(aTHX_ crypto_scalarmult_BYTES);
if ( crypto_scalarmult( bl->bytes, skey_buf, pkey_buf) != 0 ) {
sodium_free(bl->bytes);
Safefree(bl);
croak("Failed to calculate shared secret");
}
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::stream
PROTOTYPES: DISABLE
unsigned int
NONCEBYTES(...)
CODE:
RETVAL = crypto_stream_NONCEBYTES;
OUTPUT:
RETVAL
unsigned int
KEYBYTES(...)
CODE:
RETVAL = crypto_stream_KEYBYTES;
OUTPUT:
RETVAL
unsigned int
CHACHA20_NONCEBYTES(...)
CODE:
RETVAL = crypto_stream_chacha20_NONCEBYTES;
OUTPUT:
RETVAL
unsigned int
CHACHA20_IETF_NONCEBYTES(...)
CODE:
RETVAL = crypto_stream_chacha20_IETF_NONCEBYTES;
OUTPUT:
case 4:
nonce_size = crypto_stream_chacha20_IETF_NONCEBYTES;
break;
default:
nonce_size = crypto_stream_NONCEBYTES;
}
if ( items > 2 ) {
croak("Invalid number of arguments");
}
if (items == 2 ) {
if ( SvOK(ST(1)) ) {
STRLEN prev_nonce_len;
unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
if ( prev_nonce_len > nonce_size ) {
croak("Base nonce too long");
}
bl = InitDataBytesLocker(aTHX_ nonce_size);
memcpy(bl->bytes, prev_nonce, prev_nonce_len);
sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
}
else {
croak("Base nonce invalid");
}
}
else {
bl = InitDataBytesLocker(aTHX_ nonce_size);
randombytes_buf(bl->bytes, bl->length);
}
RETVAL = DataBytesLocker2SV(aTHX_ bl);
OUTPUT:
RETVAL
void
bytes(self, length, nonce, key)
SV * self
SV * length
SV * nonce
SV * key
ALIAS:
chacha20_bytes = 1
salsa20_bytes = 2
aes128ctr_bytes = 3
salsa2012_bytes = 4
salsa208_bytes = 5
chacha20_ietf_bytes = 6
INIT:
STRLEN nonce_len;
STRLEN key_len;
unsigned char * nonce_buf;
unsigned char * key_buf;
unsigned int nonce_size;
unsigned int key_size;
unsigned int bytes_len;
int (*bytes_function)(unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 1:
nonce_size = crypto_stream_chacha20_NONCEBYTES;
key_size = crypto_stream_chacha20_KEYBYTES;
bytes_function = &crypto_stream_chacha20;
break;
case 2:
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
bytes_function = &crypto_stream_salsa20;
break;
case 3:
#ifdef AES128CTR_IS_AVAILABLE
nonce_size = crypto_stream_aes128ctr_NONCEBYTES;
key_size = crypto_stream_aes128ctr_KEYBYTES;
bytes_function = &crypto_stream_aes128ctr;
#else
croak("AES128CTR is only available in libsodium v1.0.14 and below");
#endif
break;
case 4:
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
bytes_function = &crypto_stream_salsa2012;
break;
case 5:
#ifdef INCLUDE_DEPRECATED
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
bytes_function = &crypto_stream_salsa208;
#else
croak("crypto_stream_salsa208 was deprecated in v1.0.18 define INCLUDE_DEPRECATED to use");
#endif
break;
case 6:
nonce_size = crypto_stream_chacha20_IETF_NONCEBYTES;
key_size = crypto_stream_chacha20_KEYBYTES;
bytes_function = &crypto_stream_chacha20_ietf;
break;
default:
nonce_size = crypto_stream_NONCEBYTES;
key_size = crypto_stream_KEYBYTES;
bytes_function = &crypto_stream;
}
bytes_len = SvUV(length);
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != nonce_size ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
croak("Invalid key");
}
bl = InitDataBytesLocker(aTHX_ bytes_len);
(*bytes_function)( bl->bytes, bytes_len, nonce_buf, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
xor(self, msg, nonce, key)
SV * self
SV * msg
SV * nonce
SV * key
ALIAS:
chacha20_xor = 1
salsa20_xor = 2
aes128ctr_xor = 3
salsa2012_xor = 4
salsa208_xor = 5
chacha20_ietf_xor = 6
INIT:
STRLEN msg_len;
STRLEN nonce_len;
STRLEN key_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
unsigned int nonce_size;
unsigned int key_size;
int (*xor_function)(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 1:
nonce_size = crypto_stream_chacha20_NONCEBYTES;
key_size = crypto_stream_chacha20_KEYBYTES;
xor_function = &crypto_stream_chacha20_xor;
break;
case 2:
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
xor_function = &crypto_stream_salsa20_xor;
break;
case 3:
#ifdef AES128CTR_IS_AVAILABLE
nonce_size = crypto_stream_aes128ctr_NONCEBYTES;
key_size = crypto_stream_aes128ctr_KEYBYTES;
xor_function = &crypto_stream_aes128ctr_xor;
#else
croak("AES128CTR is only available in libsodium v1.0.14 and below");
#endif
break;
case 4:
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
xor_function = &crypto_stream_salsa2012_xor;
break;
case 5:
#ifdef INCLUDE_DEPRECATED
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
xor_function = &crypto_stream_salsa208_xor;
#else
croak("crypto_stream_salsa208_xor was deprecated in v1.0.18 define INCLUDE_DEPRECATED to use");
#endif
break;
case 6:
nonce_size = crypto_stream_chacha20_IETF_NONCEBYTES;
key_size = crypto_stream_chacha20_KEYBYTES;
xor_function = &crypto_stream_chacha20_ietf_xor;
break;
default:
nonce_size = crypto_stream_NONCEBYTES;
key_size = crypto_stream_KEYBYTES;
xor_function = &crypto_stream_xor;
}
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != nonce_size ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ msg_len);
(*xor_function)( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
xor_ic(self, msg, nonce, ic, key)
SV * self
SV * msg
SV * nonce
SV * ic
SV * key
ALIAS:
chacha20_xor_ic = 1
salsa20_xor_ic = 2
INIT:
STRLEN msg_len;
STRLEN nonce_len;
unsigned int bc;
STRLEN key_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
unsigned int nonce_size;
unsigned int key_size;
int (*xor_ic_function)(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, uint64_t, const unsigned char *);
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
switch(ix) {
case 1:
nonce_size = crypto_stream_chacha20_NONCEBYTES;
key_size = crypto_stream_chacha20_KEYBYTES;
xor_ic_function = &crypto_stream_chacha20_xor_ic;
break;
case 2:
nonce_size = crypto_stream_salsa20_NONCEBYTES;
key_size = crypto_stream_salsa20_KEYBYTES;
xor_ic_function = &crypto_stream_salsa20_xor_ic;
break;
default:
nonce_size = crypto_stream_NONCEBYTES;
key_size = crypto_stream_KEYBYTES;
xor_ic_function = &crypto_stream_xsalsa20_xor_ic;
}
bc = SvUV(ic);
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != nonce_size ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != key_size ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ msg_len);
(*xor_ic_function)( bl->bytes, msg_buf, msg_len, nonce_buf, bc, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
chacha20_ietf_xor_ic(self, msg, nonce, ic, key)
SV * self
SV * msg
SV * nonce
SV * ic
SV * key
INIT:
STRLEN msg_len;
STRLEN nonce_len;
unsigned int bc;
STRLEN key_len;
unsigned char * msg_buf;
unsigned char * nonce_buf;
unsigned char * key_buf;
DataBytesLocker *bl;
PPCODE:
{
PERL_UNUSED_VAR(self);
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
bc = SvUV(ic);
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_stream_chacha20_IETF_NONCEBYTES ) {
croak("Invalid nonce");
}
key_buf = (unsigned char *)SvPV(key, key_len);
if ( key_len != crypto_stream_chacha20_KEYBYTES ) {
croak("Invalid key");
}
msg_buf = (unsigned char *)SvPV(msg, msg_len);
bl = InitDataBytesLocker(aTHX_ msg_len);
crypto_stream_chacha20_ietf_xor_ic( bl->bytes, msg_buf, msg_len, nonce_buf, bc, key_buf);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
MODULE = Crypt::NaCl::Sodium PACKAGE = Data::BytesLocker
FALLBACK: FALSE
SV *
new(class, bytes, ...)
SV * class
SV * bytes
PROTOTYPE: $$;%
INIT:
DataBytesLocker *bl;
unsigned char *buf;
STRLEN buf_len;
int wipe = 0;
int readonly = 0;
CODE:
{
if ( SvREADONLY(bytes) ) {
buf = (unsigned char *)SvPV(bytes, buf_len);
readonly = 1;
} else {
buf = (unsigned char *)SvPV_force(bytes, buf_len);
}
if ( items > 2 && items != 4 ) {
croak("Invalid number of arguments");
} else if ( items > 2 ) {
int i = 0;
STRLEN keylen = 0;
char * key;
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
count = SvUV(other);
bl = InitDataBytesLocker(aTHX_ sbl->length * count);
while(count--) {
memcpy(bl->bytes + sbl->length * cur++, sbl->bytes, sbl->length);
}
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
SV *
_overload_concat(self, other, swapped)
SV * self
SV * other
SV * swapped
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
unsigned char *buf;
STRLEN buf_len;
DataBytesLocker *bl;
OVERLOAD: .
CODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
buf = (unsigned char *)SvPV(other, buf_len);
bl = InitDataBytesLocker(aTHX_ sbl->length + buf_len);
if ( SvTRUE(swapped) ) {
memcpy(memcpy(bl->bytes, buf, buf_len) + buf_len, sbl->bytes, sbl->length);
}
else {
memcpy(memcpy(bl->bytes, sbl->bytes, sbl->length) + sbl->length, buf, buf_len);
}
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
_overload_bool(self, ...)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
int res;
OVERLOAD: bool
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
if ( sbl->length ) {
res = 1;
} else {
res = 0;
}
if ( res ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
void
_overload_not(self, ...)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
int res;
OVERLOAD: !
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
if ( sbl->length ) {
res = 0;
} else {
res = 1;
}
if ( res ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
void
_overload_eq(self, other, swapped)
SV * self
SV * other
SV * swapped
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
unsigned char *buf;
STRLEN buf_len;
int res;
OVERLOAD: eq
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
buf = (unsigned char *)SvPV(other, buf_len);
if ( sbl->length != buf_len ) {
croak("Variables of unequal length cannot be automatically compared. Please use memcmp() with the length argument provided");
}
if ( sodium_memcmp(sbl->bytes, buf, sbl->length) == 0 ) {
res = 1;
} else {
res = 0;
}
if ( res ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
void
_overload_ne(self, other, swapped)
SV * self
SV * other
SV * swapped
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
unsigned char *buf;
STRLEN buf_len;
int res;
OVERLOAD: ne
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
buf = (unsigned char *)SvPV(other, buf_len);
if ( sbl->length != buf_len ) {
croak("Variables of unequal length cannot be automatically compared. Please use memcmp() with the length argument provided");
}
if ( sodium_memcmp(sbl->bytes, buf, sbl->length) == 0 ) {
res = 0;
} else {
res = 1;
}
if ( res ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
void
_overload_str(self, ...)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
SV * pv;
OVERLOAD: \"\"
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
pv = newSVpvn((unsigned char *)sbl->bytes, sbl->length);
SvREADONLY_on(pv);
mXPUSHs(pv);
}
void
_overload_nomethod(self, ...)
SV * self
OVERLOAD: nomethod
INIT:
char * operator;
PPCODE:
{
operator = SvPV_nolen(ST(3));
croak("Operation \"%s\" is not supported", operator);
}
SV *
clone(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
DataBytesLocker *bl;
CODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
bl = InitDataBytesLocker(aTHX_ sbl->length);
memcpy(bl->bytes, sbl->bytes, sbl->length);
RETVAL = DataBytesLocker2SV(aTHX_ bl);
}
OUTPUT:
RETVAL
void
lock(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
int rc;
PPCODE:
{
rc = sodium_mprotect_noaccess((void *)sbl->bytes);
if (rc == 0 ) {
sbl->locked = 1;
XSRETURN_YES;
}
croak("Unable to lock memory: %s", Strerror(errno));
}
void
unlock(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
int rc;
PPCODE:
{
rc = sodium_mprotect_readonly((void *)sbl->bytes);
if (rc == 0 ) {
sbl->locked = 0;
XSRETURN_YES;
}
croak("Unable to unlock memory: %s", Strerror(errno));
}
SV *
length(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
CODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
RETVAL = newSVuv((UV)sbl->length);
}
OUTPUT:
RETVAL
void
is_locked(self, ...)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
PPCODE:
{
if ( sbl->locked ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
SV *
to_hex(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
char * hex;
size_t hex_len;
CODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
hex_len = sbl->length * 2;
hex = sodium_malloc(hex_len + 1);
if ( hex == NULL ) {
croak("Could not allocate memory");
}
sodium_bin2hex(hex, hex_len + 1, sbl->bytes, sbl->length);
RETVAL = newSVpvn((const char * const)hex, hex_len);
}
OUTPUT:
RETVAL
CLEANUP:
sodium_free(hex);
void
bytes(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
SV * pv;
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
pv = newSVpvn((unsigned char *)sbl->bytes, sbl->length);
mXPUSHs(pv);
}
void
memcmp(self, bytes, length = 0)
SV * self
SV * bytes
unsigned long length
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
unsigned char * bytes_buf;
STRLEN bytes_len;
PPCODE:
{
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
if (sv_derived_from(bytes, "Data::BytesLocker")) {
DataBytesLocker* rbl = GetBytesLocker(aTHX_ bytes);
if ( rbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
bytes_buf = rbl->bytes;
bytes_len = rbl->length;
}
else {
bytes_buf = (unsigned char *)SvPV(bytes, bytes_len);
}
if ( length == 0 ) {
if ( sbl->length != bytes_len ) {
croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
}
length = bytes_len;
} else {
if ( length > sbl->length ) {
croak("The data is shorter then requested length");
}
else if ( length > bytes_len ) {
croak("The argument is shorter then requested length");
}
}
if ( sodium_memcmp(sbl->bytes, bytes_buf, length) == 0 ) {
XSRETURN_YES;
} else {
XSRETURN_NO;
}
}
void
compare(self, num, length = 0)
SV * self
SV * num
unsigned long length
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
unsigned char * num_buf;
STRLEN num_len;
PPCODE:
{
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
if (sv_derived_from(num, "Data::BytesLocker")) {
DataBytesLocker* rbl = GetBytesLocker(aTHX_ num);
if ( rbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
num_buf = rbl->bytes;
num_len = rbl->length;
}
else {
num_buf = (unsigned char *)SvPV(num, num_len);
}
if ( length == 0 ) {
if ( sbl->length != num_len ) {
croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
}
length = num_len;
} else {
if ( length > sbl->length ) {
croak("The data is shorter then requested length");
}
else if ( length > num_len ) {
croak("The argument is shorter then requested length");
}
}
XSRETURN_IV( sodium_compare(sbl->bytes, num_buf, length) );
}
void
increment(self)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
SV * pv;
DataBytesLocker *bl;
PPCODE:
{
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
bl = InitDataBytesLocker(aTHX_ sbl->length);
memcpy(bl->bytes, sbl->bytes, sbl->length);
sodium_increment(bl->bytes, sbl->length);
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
add(self, num, ...)
SV * self
SV * num
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
unsigned char * num_buf;
STRLEN num_len;
STRLEN inc_len;
DataBytesLocker *bl;
PPCODE:
{
if ( GIMME_V == G_VOID ) {
XSRETURN_EMPTY;
}
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
if (sv_derived_from(num, "Data::BytesLocker")) {
DataBytesLocker* rbl = GetBytesLocker(aTHX_ num);
if ( rbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
num_buf = rbl->bytes;
num_len = rbl->length;
}
else {
num_buf = (unsigned char *)SvPV(num, num_len);
}
if ( items == 3 ) {
inc_len = (STRLEN)SvUV(ST(2));
if ( inc_len > sbl->length ) {
croak("The data is shorter then requested length");
}
else if ( inc_len > num_len ) {
croak("The argument is shorter then requested length");
}
} else {
if ( sbl->length != num_len ) {
croak("Length of argument has to be equal to the length of data. Please provide the length argument");
}
inc_len = num_len;
}
bl = InitDataBytesLocker(aTHX_ sbl->length);
memcpy(bl->bytes, sbl->bytes, sbl->length);
sodium_add( bl->bytes, num_buf, inc_len );
mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
XSRETURN(1);
}
void
is_zero(self, ...)
SV * self
PREINIT:
DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
SV * pv;
PPCODE:
{
if ( sbl->locked ) {
croak("Unlock BytesLocker object before accessing the data");
}
if ( sodium_is_zero(sbl->bytes, sbl->length) == 1 ) {
XSRETURN_YES;
}
XSRETURN_NO;
}
void
DESTROY(self)
SV * self
PREINIT:
DataBytesLocker* bl = GetBytesLocker(aTHX_ self);
PPCODE:
{
sodium_free( bl->bytes );
Safefree(bl);
}
( run in 1.577 second using v1.01-cache-2.11-cpan-71847e10f99 )