diff options
author | Karel Miko <karel.miko@gmail.com> | 2017-10-23 11:40:15 +0200 |
---|---|---|
committer | Karel Miko <karel.miko@gmail.com> | 2017-10-23 11:40:39 +0200 |
commit | f7f681817d1f1592bf26f307b60014d054163c3c (patch) | |
tree | 4bff004d02b9cebe0575d254f0af33ecbaadb6d7 /inc | |
parent | 5d507df65fe49edd28acc7f8b984fa3f1a817344 (diff) |
Crypt::Stream::Salsa20
Diffstat (limited to 'inc')
-rw-r--r-- | inc/CryptX_Stream_Salsa20.xs.inc | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/inc/CryptX_Stream_Salsa20.xs.inc b/inc/CryptX_Stream_Salsa20.xs.inc new file mode 100644 index 00000000..6b593e35 --- /dev/null +++ b/inc/CryptX_Stream_Salsa20.xs.inc @@ -0,0 +1,93 @@ +MODULE = CryptX PACKAGE = Crypt::Stream::Salsa20 + +Crypt::Stream::Salsa20 +_new(SV * key, SV * nonce, UV counter = 0, int rounds = 20) + CODE: + { + int rv; + STRLEN iv_len=0, k_len=0; + unsigned char *iv=NULL, *k=NULL; + + if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar"); + if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar"); + k = (unsigned char *) SvPVbyte(key, k_len); + iv = (unsigned char *) SvPVbyte(nonce, iv_len); + + Newz(0, RETVAL, 1, struct salsa20_struct); + if (!RETVAL) croak("FATAL: Newz failed"); + + rv = salsa20_setup(&RETVAL->state, k, (unsigned long)k_len, rounds); + if (rv != CRYPT_OK) croak("FATAL: salsa20_setup failed: %s", error_to_string(rv)); + + if (iv_len == 8) { + rv = salsa20_ivctr64(&RETVAL->state, iv, (unsigned long)iv_len, (ulong64)counter); + if (rv != CRYPT_OK) croak("FATAL: salsa20_ivctr64 failed: %s", error_to_string(rv)); + } + else { + croak("FATAL: chacha IV length must be 8 or 12 bytes"); + } + } + OUTPUT: + RETVAL + +void +DESTROY(Crypt::Stream::Salsa20 self) + CODE: + salsa20_done(&self->state); + Safefree(self); + +Crypt::Stream::Salsa20 +clone(Crypt::Stream::Salsa20 self) + CODE: + Newz(0, RETVAL, 1, struct salsa20_struct); + if (!RETVAL) croak("FATAL: Newz failed"); + Copy(&self->state, &RETVAL->state, 1, struct salsa20_struct); + OUTPUT: + RETVAL + +SV * +keystream(Crypt::Stream::Salsa20 self, STRLEN out_len) + CODE: + { + int rv; + unsigned char *out_data; + + RETVAL = NEWSV(0, out_len); + SvPOK_only(RETVAL); + SvCUR_set(RETVAL, out_len); + out_data = (unsigned char *)SvPVX(RETVAL); + rv = salsa20_keystream(&self->state, out_data, out_len); + if (rv != CRYPT_OK) { + SvREFCNT_dec(RETVAL); + croak("FATAL: salsa20_keystream failed: %s", error_to_string(rv)); + } + } + OUTPUT: + RETVAL + +SV * +crypt(Crypt::Stream::Salsa20 self, SV * data) + CODE: + { + int rv; + STRLEN in_data_len; + unsigned char *in_data, *out_data; + + in_data = (unsigned char *)SvPVbyte(data, in_data_len); + if (in_data_len==0) { + RETVAL = newSVpvn("", 0); + } + else { + RETVAL = NEWSV(0, in_data_len); + SvPOK_only(RETVAL); + SvCUR_set(RETVAL, in_data_len); + out_data = (unsigned char *)SvPVX(RETVAL); + rv = salsa20_crypt(&self->state, in_data, (unsigned long)in_data_len, out_data); + if (rv != CRYPT_OK) { + SvREFCNT_dec(RETVAL); + croak("FATAL: salsa20_crypt failed: %s", error_to_string(rv)); + } + } + } + OUTPUT: + RETVAL |