summaryrefslogtreecommitdiff
path: root/inc
diff options
context:
space:
mode:
authorKarel Miko <karel.miko@gmail.com>2017-10-23 11:40:15 +0200
committerKarel Miko <karel.miko@gmail.com>2017-10-23 11:40:39 +0200
commitf7f681817d1f1592bf26f307b60014d054163c3c (patch)
tree4bff004d02b9cebe0575d254f0af33ecbaadb6d7 /inc
parent5d507df65fe49edd28acc7f8b984fa3f1a817344 (diff)
Crypt::Stream::Salsa20
Diffstat (limited to 'inc')
-rw-r--r--inc/CryptX_Stream_Salsa20.xs.inc93
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