Crypt-Sodium-XS
view release on metacpan or search on metacpan
inc/secretstream.xs view on Meta::CPAN
=for documentation
libsodium secretstream includes only xchacha20poly1305-specific functions.
=cut
MODULE = Crypt::Sodium::XS PACKAGE = Crypt::Sodium::XS::secretstream
void _define_constants()
PREINIT:
HV *stash = gv_stashpv("Crypt::Sodium::XS::secretstream", 0);
PPCODE:
newCONSTSUB(stash, "secretstream_xchacha20poly1305_ABYTES",
newSVuv(crypto_secretstream_xchacha20poly1305_ABYTES));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_HEADERBYTES",
newSVuv(crypto_secretstream_xchacha20poly1305_HEADERBYTES));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_KEYBYTES",
newSVuv(crypto_secretstream_xchacha20poly1305_KEYBYTES));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_MESSAGEBYTES_MAX",
newSVuv(crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_TAG_MESSAGE",
newSVuv(crypto_secretstream_xchacha20poly1305_TAG_MESSAGE));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_TAG_PUSH",
newSVuv(crypto_secretstream_xchacha20poly1305_TAG_PUSH));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_TAG_REKEY",
newSVuv(crypto_secretstream_xchacha20poly1305_TAG_REKEY));
newCONSTSUB(stash, "secretstream_xchacha20poly1305_TAG_FINAL",
newSVuv(crypto_secretstream_xchacha20poly1305_TAG_FINAL));
SV * secretstream_xchacha20poly1305_init_decrypt( \
SV * header, \
SV * key, \
SV * flags = &PL_sv_undef \
)
ALIAS:
secretstream_xchacha20poly1305_init_pull = 1
PREINIT:
PERL_UNUSED_VAR(ix);
protmem *state_pm, *key_pm = NULL;
unsigned char *header_buf, *key_buf;
STRLEN header_len, key_len;
unsigned int state_flags = g_protmem_default_flags_key;
CODE:
SvGETMAGIC(flags);
if (SvOK(flags))
state_flags = SvUV_nomg(flags);
header_buf = (unsigned char *)SvPVbyte(header, header_len);
if (header_len != crypto_secretstream_xchacha20poly1305_HEADERBYTES)
croak("secretstream_init_decrypt: Invalid header length %lu", header_len);
if (sv_derived_from(key, MEMVAULT_CLASS)) {
key_pm = protmem_get(aTHX_ key, MEMVAULT_CLASS);
key_buf = key_pm->pm_ptr;
key_len = key_pm->size;
}
else
key_buf = (unsigned char *)SvPVbyte(key, key_len);
if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES)
croak("secretstream_init_decrypt: Invalid key length %lu", key_len);
state_pm = protmem_init(aTHX_ sizeof(crypto_secretstream_xchacha20poly1305_state), state_flags);
if (state_pm == NULL)
croak("secretstream_init_decrypt: Failed to allocate state protmem");
if (key_pm && protmem_grant(aTHX_ key_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ state_pm);
croak("secretstream_init_decrypt: Failed to grant key protmem RO");
}
crypto_secretstream_xchacha20poly1305_init_pull(state_pm->pm_ptr, header_buf, key_buf);
if (key_pm && protmem_release(aTHX_ key_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ state_pm);
croak("secretstream_init_decrypt: Failed to release key protmem RO");
}
if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
protmem_free(aTHX_ state_pm);
croak("secretstream_init_decrypt: Failed to release state protmem RW");
}
RETVAL = protmem_to_sv(aTHX_ state_pm,
"Crypt::Sodium::XS::secretstream::xchacha20poly1305_decrypt");
OUTPUT:
RETVAL
void secretstream_xchacha20poly1305_init_encrypt(SV * key, SV * flags = &PL_sv_undef)
ALIAS:
secretstream_xchacha20poly1305_init_push = 1
PREINIT:
PERL_UNUSED_VAR(ix);
protmem *state_pm, *key_pm = NULL;
SV * header;
unsigned char *key_buf, *header_buf;
STRLEN key_len;
unsigned int state_flags = g_protmem_default_flags_key;
PPCODE:
SvGETMAGIC(flags);
if (SvOK(flags))
state_flags = SvUV_nomg(flags);
if (sv_derived_from(key, MEMVAULT_CLASS)) {
key_pm = protmem_get(aTHX_ key, MEMVAULT_CLASS);
key_buf = key_pm->pm_ptr;
key_len = key_pm->size;
}
else
key_buf = (unsigned char *)SvPVbyte(key, key_len);
if (key_len != crypto_secretstream_xchacha20poly1305_KEYBYTES)
croak("secretstream_init_encrypt: Invalid key length %lu", key_len);
state_pm = protmem_init(aTHX_ sizeof(crypto_secretstream_xchacha20poly1305_state), state_flags);
if (state_pm == NULL)
croak("secretstream_init_encrypt: Failed to allocate state protmem");
Newx(header_buf,
crypto_secretstream_xchacha20poly1305_HEADERBYTES + 1, unsigned char);
if (header_buf == NULL) {
protmem_free(aTHX_ state_pm);
croak("secretstream_init_encrypt: Failed to allocate memory");
}
header_buf[crypto_secretstream_xchacha20poly1305_HEADERBYTES] = '\0';
if (key_pm && protmem_grant(aTHX_ key_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ state_pm);
Safefree(header_buf);
croak("secretstream_init_encrypt: Failed to grant key protmem RO");
}
crypto_secretstream_xchacha20poly1305_init_push(state_pm->pm_ptr, header_buf, key_buf);
if (key_pm && protmem_release(aTHX_ key_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ state_pm);
croak("secretstream_init_encrypt: Failed to release key protmem RO");
}
if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
protmem_free(aTHX_ state_pm);
Safefree(header_buf);
croak("secretstream_init_encrypt: Failed to release state protmem RW");
}
header = newSV(0);
sv_usepvn_flags(header, (char *)header_buf,
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
SV_HAS_TRAILING_NUL);
mXPUSHs(header);
mXPUSHs(protmem_to_sv(aTHX_ state_pm, "Crypt::Sodium::XS::secretstream::xchacha20poly1305_encrypt"));
XSRETURN(2);
SV * secretstream_xchacha20poly1305_keygen(SV * flags = &PL_sv_undef)
CODE:
RETVAL = sv_keygen(aTHX_ crypto_secretstream_xchacha20poly1305_KEYBYTES, flags);
OUTPUT:
RETVAL
MODULE = Crypt::Sodium::XS PACKAGE = Crypt::Sodium::XS::secretstream::xchacha20poly1305_decrypt
void DESTROY(SV * self)
ALIAS:
Crypt::Sodium::XS::secretstream::xchachapoly1305_encrypt = 1
PREINIT:
protmem *state_pm;
PPCODE:
switch(ix) {
case 1:
state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::secretstream::xchacha20poly1305_encrypt");
break;
default:
state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::secretstream::xchacha20poly1305_decrypt");
}
protmem_free(aTHX_ state_pm);
void decrypt( \
SV * self, \
SV * ciphertext, \
SV * adata = &PL_sv_undef, \
SV * flags = &PL_sv_undef \
)
ALIAS:
pull = 1
PREINIT:
PERL_UNUSED_VAR(ix);
protmem *state_pm, *ct_pm = NULL, *msg_pm;
unsigned char *ct_buf, *adata_buf = NULL, tag;
STRLEN ct_len, adata_len = 0;
unsigned int msg_flags = g_protmem_default_flags_decrypt;
int ret;
PPCODE:
SvGETMAGIC(flags);
if (SvOK(flags))
msg_flags = SvUV_nomg(flags);
if (sv_derived_from(ciphertext, MEMVAULT_CLASS)) {
ct_pm = protmem_get(aTHX_ ciphertext, MEMVAULT_CLASS);
ct_buf = ct_pm->pm_ptr;
ct_len = ct_pm->size;
}
else
ct_buf = (unsigned char *)SvPVbyte(ciphertext, ct_len);
if (ct_len < crypto_secretstream_xchacha20poly1305_ABYTES)
croak("decrypt: Invalid ciphertext (too short): %lu", ct_len);
SvGETMAGIC(adata);
if (SvOK(adata))
adata_buf = (unsigned char *)SvPVbyte_nomg(adata, adata_len);
msg_pm = protmem_init(aTHX_
ct_len - crypto_secretstream_xchacha20poly1305_ABYTES, msg_flags);
if (msg_pm == NULL)
croak("decrypt: Failed to allocate protmem");
if (ct_pm && protmem_grant(aTHX_ ct_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to grant ciphertext protmem RO");
}
state_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::secretstream::xchacha20poly1305_decrypt");
if (protmem_grant(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
if (ct_pm)
protmem_release(aTHX_ ct_pm, PROTMEM_FLAG_MPROTECT_RO);
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to grant state protmem RW");
}
ret = crypto_secretstream_xchacha20poly1305_pull(state_pm->pm_ptr,
msg_pm->pm_ptr, NULL, &tag, ct_buf, ct_len, adata_buf, adata_len);
if (protmem_release(aTHX_ state_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
if (ct_pm)
protmem_release(aTHX_ ct_pm, PROTMEM_FLAG_MPROTECT_RO);
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to release state protmem RW");
}
if (ct_pm && protmem_release(aTHX_ ct_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to release ciphertext protmem RO");
}
if (protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
protmem_free(aTHX_ msg_pm);
croak("Failed to protect memvault");
}
if (ret != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt: Message forged");
}
( run in 0.651 second using v1.01-cache-2.11-cpan-71847e10f99 )