CryptX
view release on metacpan or search on metacpan
inc/CryptX_AuthEnc_SIV.xs.inc view on Meta::CPAN
STRLEN k_len = 0, pt_len = 0;
unsigned char *k, *pt, *ct;
unsigned long ct_len;
int rv, id;
const unsigned char *ad_ptrs[126];
unsigned long ad_lens[126];
unsigned long n_ad = 0;
STRLEN tmp;
id = cryptx_internal_find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *)SvPVbyte(key, k_len);
if (!SvPOK_spec(plaintext)) croak("FATAL: plaintext must be string/buffer scalar");
pt = (unsigned char *)SvPVbyte(plaintext, pt_len);
if (SvOK(aad)) {
if (SvROK(aad) && SvTYPE(SvRV(aad)) == SVt_PVAV) {
AV *av = (AV *)SvRV(aad);
SSize_t i, alen = av_len(av);
for (i = 0; i <= alen; i++) {
SV **svp = av_fetch(av, i, 0);
if (svp && SvOK(*svp)) {
if (n_ad >= 126) croak("FATAL: too many associated data components (max 126)");
if (!SvPOK_spec(*svp)) croak("FATAL: associated data component must be string/buffer scalar");
ad_ptrs[n_ad] = (const unsigned char *)SvPVbyte(*svp, tmp);
ad_lens[n_ad] = (unsigned long)tmp;
n_ad++;
}
}
} else {
if (!SvPOK_spec(aad)) croak("FATAL: associated data must be string/buffer scalar or arrayref");
ad_ptrs[0] = (const unsigned char *)SvPVbyte(aad, tmp);
ad_lens[0] = (unsigned long)tmp;
n_ad = 1;
}
}
ct_len = (unsigned long)pt_len + 16;
RETVAL = NEWSV(0, ct_len > 0 ? ct_len : 1);
SvPOK_only(RETVAL);
SvCUR_set(RETVAL, ct_len);
ct = (unsigned char *)SvPVX(RETVAL);
rv = siv_encrypt_memory(id, k, (unsigned long)k_len,
n_ad,
ad_ptrs, ad_lens,
pt, (unsigned long)pt_len,
ct, &ct_len);
if (rv != CRYPT_OK) {
SvREFCNT_dec(RETVAL);
croak("FATAL: siv_encrypt_memory failed: %s", error_to_string(rv));
}
SvCUR_set(RETVAL, ct_len);
}
OUTPUT:
RETVAL
void
siv_decrypt_verify(char *cipher_name, SV *key, SV *ciphertext, SV *aad = &PL_sv_undef)
PPCODE:
{
STRLEN k_len = 0, ct_len = 0;
unsigned char *k, *ct, *pt;
unsigned long pt_len;
int rv, id;
SV *output;
const unsigned char *ad_ptrs[126];
unsigned long ad_lens[126];
unsigned long n_ad = 0;
STRLEN tmp;
id = cryptx_internal_find_cipher(cipher_name);
if (id == -1) croak("FATAL: find_cipher failed for '%s'", cipher_name);
if (!SvPOK_spec(key)) croak("FATAL: key must be string/buffer scalar");
k = (unsigned char *)SvPVbyte(key, k_len);
if (!SvPOK_spec(ciphertext)) croak("FATAL: ciphertext must be string/buffer scalar");
ct = (unsigned char *)SvPVbyte(ciphertext, ct_len);
if (ct_len < 16) croak("FATAL: ciphertext too short");
if (SvOK(aad)) {
if (SvROK(aad) && SvTYPE(SvRV(aad)) == SVt_PVAV) {
AV *av = (AV *)SvRV(aad);
SSize_t i, alen = av_len(av);
for (i = 0; i <= alen; i++) {
SV **svp = av_fetch(av, i, 0);
if (svp && SvOK(*svp)) {
if (n_ad >= 126) croak("FATAL: too many associated data components (max 126)");
if (!SvPOK_spec(*svp)) croak("FATAL: associated data component must be string/buffer scalar");
ad_ptrs[n_ad] = (const unsigned char *)SvPVbyte(*svp, tmp);
ad_lens[n_ad] = (unsigned long)tmp;
n_ad++;
}
}
} else {
if (!SvPOK_spec(aad)) croak("FATAL: associated data must be string/buffer scalar or arrayref");
ad_ptrs[0] = (const unsigned char *)SvPVbyte(aad, tmp);
ad_lens[0] = (unsigned long)tmp;
n_ad = 1;
}
}
pt_len = (unsigned long)ct_len - 16;
output = NEWSV(0, pt_len > 0 ? pt_len : 1);
SvPOK_only(output);
SvCUR_set(output, pt_len);
pt = (unsigned char *)SvPVX(output);
rv = siv_decrypt_memory(id, k, (unsigned long)k_len,
n_ad,
ad_ptrs, ad_lens,
ct, (unsigned long)ct_len,
pt, &pt_len);
if (rv != CRYPT_OK) {
SvREFCNT_dec(output);
XPUSHs(sv_2mortal(newSVpvn(NULL, 0))); /* undef */
} else {
SvCUR_set(output, pt_len);
XPUSHs(sv_2mortal(output));
}
}
( run in 1.304 second using v1.01-cache-2.11-cpan-71847e10f99 )