Crypt-Sodium-XS
view release on metacpan or search on metacpan
inc/aead.xs view on Meta::CPAN
=for documentation
libsodium aead provides only algorithm-specific functions.
=cut
MODULE = Crypt::Sodium::XS PACKAGE = Crypt::Sodium::XS::aead
void
_define_constants()
PREINIT:
HV *stash = gv_stashpv("Crypt::Sodium::XS::aead", 0);
PPCODE:
newCONSTSUB(stash, "aead_chacha20poly1305_ABYTES",
newSVuv(crypto_aead_chacha20poly1305_ABYTES));
newCONSTSUB(stash, "aead_chacha20poly1305_ietf_ABYTES",
newSVuv(crypto_aead_chacha20poly1305_ietf_ABYTES));
newCONSTSUB(stash, "aead_aes256gcm_ABYTES",
newSVuv(crypto_aead_aes256gcm_ABYTES));
newCONSTSUB(stash, "aead_xchacha20poly1305_ietf_ABYTES",
newSVuv(crypto_aead_xchacha20poly1305_ietf_ABYTES));
newCONSTSUB(stash, "aead_chacha20poly1305_KEYBYTES",
newSVuv(crypto_aead_chacha20poly1305_KEYBYTES));
newCONSTSUB(stash, "aead_chacha20poly1305_ietf_KEYBYTES",
newSVuv(crypto_aead_chacha20poly1305_ietf_KEYBYTES));
newCONSTSUB(stash, "aead_aes256gcm_KEYBYTES",
newSVuv(crypto_aead_aes256gcm_KEYBYTES));
newCONSTSUB(stash, "aead_xchacha20poly1305_ietf_KEYBYTES",
newSVuv(crypto_aead_xchacha20poly1305_ietf_KEYBYTES));
newCONSTSUB(stash, "aead_chacha20poly1305_MESSAGEBYTES_MAX",
newSVuv(crypto_aead_chacha20poly1305_KEYBYTES));
newCONSTSUB(stash, "aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX",
newSVuv(crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX));
newCONSTSUB(stash, "aead_aes256gcm_MESSAGEBYTES_MAX",
newSVuv(crypto_aead_aes256gcm_MESSAGEBYTES_MAX));
newCONSTSUB(stash, "aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX",
newSVuv(crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX));
newCONSTSUB(stash, "aead_chacha20poly1305_NPUBBYTES",
newSVuv(crypto_aead_chacha20poly1305_NPUBBYTES));
newCONSTSUB(stash, "aead_chacha20poly1305_ietf_NPUBBYTES",
newSVuv(crypto_aead_chacha20poly1305_ietf_NPUBBYTES));
newCONSTSUB(stash, "aead_aes256gcm_NPUBBYTES",
newSVuv(crypto_aead_aes256gcm_NPUBBYTES));
newCONSTSUB(stash, "aead_xchacha20poly1305_ietf_NPUBBYTES",
newSVuv(crypto_aead_xchacha20poly1305_ietf_NPUBBYTES));
#ifdef SODIUM_HAS_AEGIS
newCONSTSUB(stash, "aead_aegis128l_ABYTES",
newSVuv(crypto_aead_aegis128l_ABYTES));
newCONSTSUB(stash, "aead_aegis256_ABYTES",
newSVuv(crypto_aead_aegis256_ABYTES));
newCONSTSUB(stash, "aead_aegis128l_KEYBYTES",
newSVuv(crypto_aead_aegis128l_KEYBYTES));
newCONSTSUB(stash, "aead_aegis256_KEYBYTES",
newSVuv(crypto_aead_aegis256_KEYBYTES));
newCONSTSUB(stash, "aead_aegis128l_MESSAGEBYTES_MAX",
newSVuv(crypto_aead_aegis128l_MESSAGEBYTES_MAX));
newCONSTSUB(stash, "aead_aegis256_MESSAGEBYTES_MAX",
newSVuv(crypto_aead_aegis256_MESSAGEBYTES_MAX));
newCONSTSUB(stash, "aead_aegis128l_NPUBBYTES",
newSVuv(crypto_aead_aegis128l_NPUBBYTES));
newCONSTSUB(stash, "aead_aegis256_NPUBBYTES",
newSVuv(crypto_aead_aegis256_NPUBBYTES));
#endif
=for notes
nsec is not used by libsodium aead algorithms. provided for completeness.
=cut
newCONSTSUB(stash, "aead_chacha20poly1305_NSECBYTES", newSVuv(0));
newCONSTSUB(stash, "aead_chacha20poly1305_ietf_NSECBYTES", newSVuv(0));
newCONSTSUB(stash, "aead_aes256gcm_NSECBYTES", newSVuv(0));
#ifdef SODIUM_HAS_AEGIS
newCONSTSUB(stash, "aead_aegis128l_NSECBYTES", newSVuv(0));
newCONSTSUB(stash, "aead_aegis256_NSECBYTES", newSVuv(0));
#endif
inc/aead.xs view on Meta::CPAN
croak("aead_decrypt_detached: Failed to grant key protmem RO");
}
ret = func(msg_pm->pm_ptr, NULL, ct_buf, ct_len, mac_buf,
adata_buf, adata_len, nonce_buf, key_buf);
if (key_pm && protmem_release(aTHX_ key_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("aead_decrypt_detached: Failed to release key protmem RO");
}
if (protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
protmem_free(aTHX_ msg_pm);
croak("aead_decrypt_detached: Failed to release msg protmem RW");
}
if (ret == 0)
RETVAL = protmem_to_sv(aTHX_ msg_pm, MEMVAULT_CLASS);
else {
protmem_free(aTHX_ msg_pm);
croak("aead_decrypt_detached: Message forged");
}
OUTPUT:
RETVAL
void aead_chacha20poly1305_encrypt( \
SV * msg, \
SV * nonce, \
SV * key, \
SV * adata = &PL_sv_undef \
)
ALIAS:
aead_chacha20poly1305_encrypt_detached = 1
aead_chacha20poly1305_ietf_encrypt = 2
aead_chacha20poly1305_ietf_encrypt_detached = 3
aead_aes256gcm_encrypt = 4
aead_aes256gcm_encrypt_detached = 5
aead_xchacha20poly1305_ietf_encrypt = 6
aead_xchacha20poly1305_ietf_encrypt_detached = 7
aead_aegis128l_encrypt = 8
aead_aegis128l_encrypt_detached = 9
aead_aegis256_encrypt = 10
aead_aegis256_encrypt_detached = 11
PREINIT:
protmem *msg_pm = NULL, *key_pm = NULL;
SV *ct, *adata_out = NULL;
unsigned char *msg_buf, *adata_buf = NULL, *nonce_buf, *key_buf, *ct_buf, *adata_out_buf;
STRLEN msg_len, adata_len = 0, nonce_len, key_len;
STRLEN adata_req_len, nonce_req_len, key_req_len, out_len;
int (*comb_func)(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 *);
int (*detached_func)(unsigned char *, 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 *);
PPCODE:
switch(ix) {
case 2: /* fallthrough */
case 3:
adata_req_len = crypto_aead_chacha20poly1305_ietf_ABYTES;
nonce_req_len = crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
key_req_len = crypto_aead_chacha20poly1305_ietf_KEYBYTES;
comb_func = crypto_aead_chacha20poly1305_ietf_encrypt;
detached_func = crypto_aead_chacha20poly1305_ietf_encrypt_detached;
break;
case 4: /* fallthrough */
case 5:
if (!has_aes256gcm)
croak("aead_encrypt: AES256GCM is not supported by this CPU");
adata_req_len = crypto_aead_aes256gcm_ABYTES;
nonce_req_len = crypto_aead_aes256gcm_NPUBBYTES;
key_req_len = crypto_aead_aes256gcm_KEYBYTES;
comb_func = crypto_aead_aes256gcm_encrypt;
detached_func = crypto_aead_aes256gcm_encrypt_detached;
break;
case 6: /* fallthrough */
case 7:
adata_req_len = crypto_aead_xchacha20poly1305_ietf_ABYTES;
nonce_req_len = crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
key_req_len = crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
comb_func = crypto_aead_xchacha20poly1305_ietf_encrypt;
detached_func = crypto_aead_xchacha20poly1305_ietf_encrypt_detached;
break;
case 8: /* fallthrough */
case 9:
#ifndef SODIUM_HAS_AEGIS
croak("aead_encrypt: AEGIS not supported by this version of libsodium");
#else
adata_req_len = crypto_aead_aegis128l_ABYTES;
nonce_req_len = crypto_aead_aegis128l_NPUBBYTES;
key_req_len = crypto_aead_aegis128l_KEYBYTES;
comb_func = crypto_aead_aegis128l_encrypt;
detached_func = crypto_aead_aegis128l_encrypt_detached;
#endif
break;
case 10: /* fallthrough */
case 11:
#ifndef SODIUM_HAS_AEGIS
croak("aead_encrypt: AEGIS not supported by this version of libsodium");
#else
adata_req_len = crypto_aead_aegis256_ABYTES;
nonce_req_len = crypto_aead_aegis256_NPUBBYTES;
key_req_len = crypto_aead_aegis256_KEYBYTES;
comb_func = crypto_aead_aegis256_encrypt;
detached_func = crypto_aead_aegis256_encrypt_detached;
#endif
break;
case 1: /* fallthrough */
default:
adata_req_len = crypto_aead_chacha20poly1305_ABYTES;
nonce_req_len = crypto_aead_chacha20poly1305_NPUBBYTES;
key_req_len = crypto_aead_chacha20poly1305_KEYBYTES;
comb_func = crypto_aead_chacha20poly1305_encrypt;
detached_func = crypto_aead_chacha20poly1305_encrypt_detached;
}
inc/aead.xs view on Meta::CPAN
RETVAL = sv_keygen(aTHX_ crypto_aead_aegis256_KEYBYTES, flags);
#endif
break;
default:
RETVAL = sv_keygen(aTHX_ crypto_aead_chacha20poly1305_KEYBYTES, flags);
}
OUTPUT:
RETVAL
SV * aead_chacha20poly1305_nonce(SV * base = &PL_sv_undef)
ALIAS:
aead_chacha20poly1305_ietf_nonce = 1
aead_aes256gcm_nonce = 2
aead_xchacha20poly1305_ietf_nonce = 3
aead_aegis128l_nonce = 4
aead_aegis256_nonce = 5
CODE:
switch(ix) {
case 1:
RETVAL = nonce_generate(aTHX_ crypto_aead_chacha20poly1305_ietf_NPUBBYTES, base);
break;
case 2:
if (!has_aes256gcm)
croak("aead_nonce: AES256GCM is not supported by this CPU");
RETVAL = nonce_generate(aTHX_ crypto_aead_aes256gcm_NPUBBYTES, base);
break;
case 3:
RETVAL = nonce_generate(aTHX_ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, base);
break;
case 4:
#ifndef SODIUM_HAS_AEGIS
croak("aead_nonce: AEGIS not supported by this version of libsodium");
#else
RETVAL = nonce_generate(aTHX_ crypto_aead_aegis128l_NPUBBYTES, base);
#endif
break;
case 5:
#ifndef SODIUM_HAS_AEGIS
croak("aead_nonce: AEGIS not supported by this version of libsodium");
#else
RETVAL = nonce_generate(aTHX_ crypto_aead_aegis256_NPUBBYTES, base);
#endif
break;
default:
RETVAL = nonce_generate(aTHX_ crypto_aead_chacha20poly1305_NPUBBYTES, base);
}
OUTPUT:
RETVAL
MODULE = Crypt::Sodium::XS PACKAGE = Crypt::Sodium::XS::aead::precalc
void DESTROY(SV * self)
PREINIT:
protmem *precalc_pm;
PPCODE:
precalc_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::aead::precalc");
protmem_free(aTHX_ precalc_pm);
SV * decrypt( \
SV * self, \
SV * ciphertext, \
SV * nonce, \
SV * adata = &PL_sv_undef, \
SV * flags = &PL_sv_undef \
)
PREINIT:
protmem *precalc_pm, *msg_pm;
unsigned char *ct_buf, *adata_buf = NULL, *nonce_buf;
STRLEN ct_len, adata_len = 0, nonce_len;
unsigned int msg_flags = g_protmem_default_flags_decrypt;
int ret;
CODE:
if (!has_aes256gcm)
croak("decrypt: AES256GCM is not supported by this CPU");
ct_buf = (unsigned char *)SvPVbyte(ciphertext, ct_len);
if (ct_len < crypto_aead_aes256gcm_ABYTES)
croak("decrypt: Invalid ciphertext length (too short)");
nonce_buf = (unsigned char *)SvPVbyte(nonce, nonce_len);
if (nonce_len != crypto_aead_aes256gcm_NPUBBYTES)
croak("decrypt: Invalid nonce length %lu", nonce_len);
SvGETMAGIC(adata);
if (SvOK(adata))
adata_buf = (unsigned char *)SvPVbyte_nomg(adata, adata_len);
SvGETMAGIC(flags);
if (SvOK(flags))
msg_flags = SvUV_nomg(flags);
msg_pm = protmem_init(aTHX_ ct_len - crypto_aead_aes256gcm_ABYTES, msg_flags);
if (msg_pm == NULL)
croak("decrypt: Failed to allocate protmem");
precalc_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::aead::precalc");
if (protmem_grant(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to grant protmem RO");
}
ret = crypto_aead_aes256gcm_decrypt_afternm(msg_pm->pm_ptr, NULL, NULL,
ct_buf, ct_len, adata_buf, adata_len, nonce_buf,
(crypto_aead_aes256gcm_state *)precalc_pm->pm_ptr);
if (protmem_release(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to release procmem RO");
}
if (protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt: Failed to release msg protmem RW");
inc/aead.xs view on Meta::CPAN
croak("decrypt_detached: Invalid mac length %lu", mac_len);
nonce_buf = (unsigned char *)SvPVbyte(nonce, nonce_len);
if (nonce_len != crypto_aead_aes256gcm_NPUBBYTES)
croak("decrypt_detached: Invalid nonce length %lu", nonce_len);
SvGETMAGIC(adata);
if (SvOK(adata))
adata_buf = (unsigned char *)SvPVbyte_nomg(adata, adata_len);
SvGETMAGIC(flags);
if (SvOK(flags))
msg_flags = SvUV_nomg(flags);
msg_pm = protmem_init(aTHX_ ct_len, msg_flags);
if (msg_pm == NULL)
croak("decrypt_detached: Failed to allocate protmem");
precalc_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::aead::precalc");
if (protmem_grant(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt_detached: Failed to grant protmem RO");
}
ret = crypto_aead_aes256gcm_decrypt_detached_afternm(
msg_pm->pm_ptr, NULL, ct_buf, ct_len, mac_buf, adata_buf, adata_len,
nonce_buf, (crypto_aead_aes256gcm_state *)precalc_pm->pm_ptr
);
if (protmem_release(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RO) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt_detached: Failed to release protmem RO");
}
if (protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
protmem_free(aTHX_ msg_pm);
croak("decrypt_detached: Failed to release msg protmem RW");
}
if (ret == 0)
RETVAL = protmem_to_sv(aTHX_ msg_pm, MEMVAULT_CLASS);
else {
protmem_free(aTHX_ msg_pm);
croak("decrypt_detached: Message forged");
}
OUTPUT:
RETVAL
void encrypt(SV * self, SV * msg, SV * nonce, SV * adata = &PL_sv_undef)
ALIAS:
encrypt_detached = 1
PREINIT:
protmem *precalc_pm, *msg_pm = NULL;
SV *ct, *adata_out = NULL;
unsigned char *msg_buf, *adata_buf = NULL, *nonce_buf, *ct_buf, *adata_out_buf;
STRLEN msg_len, adata_len = 0, nonce_len, out_len;
PPCODE:
nonce_buf = (unsigned char *)SvPVbyte(nonce, nonce_len);
if (nonce_len != crypto_aead_aes256gcm_NPUBBYTES)
croak("encrypt: Invalid nonce length %lu", nonce_len);
SvGETMAGIC(adata);
if (SvOK(adata))
adata_buf = (unsigned char *)SvPVbyte_nomg(adata, adata_len);
if (sv_derived_from(msg, MEMVAULT_CLASS)) {
msg_pm = protmem_get(aTHX_ msg, MEMVAULT_CLASS);
msg_buf = msg_pm->pm_ptr;
msg_len = msg_pm->size;
}
else
msg_buf = (unsigned char *)SvPVbyte(msg, msg_len);
if (msg_pm && protmem_grant(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO) != 0)
croak("encrypt: Failed to grant msg protmem RO");
precalc_pm = protmem_get(aTHX_ self, "Crypt::Sodium::XS::aead::precalc");
if (protmem_grant(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RW) != 0) {
if (msg_pm)
protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO);
croak("encrypt: Failed to grant protmem RW");
}
if (ix == 1) {
Newx(ct_buf, msg_len + 1, unsigned char);
if (ct_buf == NULL) {
protmem_release(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RW);
if (msg_pm)
protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO);
croak("encrypt: Failed to allocate memory");
}
ct_buf[msg_len] = '\0';
Newx(adata_out_buf, crypto_aead_aes256gcm_ABYTES + 1, unsigned char);
if (adata_out_buf == NULL) {
protmem_release(aTHX_ precalc_pm, PROTMEM_FLAG_MPROTECT_RW);
if (msg_pm)
protmem_release(aTHX_ msg_pm, PROTMEM_FLAG_MPROTECT_RO);
croak("encrypt: Failed to allocate memory");
}
adata_out_buf[crypto_aead_aes256gcm_ABYTES] = '\0';
crypto_aead_aes256gcm_encrypt_detached_afternm(
ct_buf, adata_out_buf, NULL, msg_buf, msg_len, adata_buf, adata_len,
NULL, nonce_buf, (crypto_aead_aes256gcm_state *)precalc_pm->pm_ptr
);
ct = newSV(0);
sv_usepvn_flags(ct, (char *)ct_buf, msg_len, SV_HAS_TRAILING_NUL);
adata_out = newSV(0);
sv_usepvn_flags(adata_out, (char *)adata_out_buf,
crypto_aead_aes256gcm_ABYTES, SV_HAS_TRAILING_NUL);
}
else {
if (SIZE_MAX - crypto_aead_aes256gcm_ABYTES < msg_len)
croak("Message too large");
out_len = crypto_aead_aes256gcm_ABYTES + msg_len;
( run in 0.574 second using v1.01-cache-2.11-cpan-71847e10f99 )