File Coverage

CryptX.xs
Criterion Covered Total %
statement 228 301 75.7
branch 161 274 58.7
condition n/a
subroutine n/a
pod n/a
total 389 575 67.6


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT /* we want efficiency */
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5              
6             #define NEED_sv_2pvbyte_GLOBAL
7             #define NEED_sv_2pv_flags_GLOBAL
8             #define NEED_newRV_noinc_GLOBAL
9             #include "ppport.h"
10              
11             /* assert_not_ROK is broken in 5.8.1 */
12             #if PERL_VERSION == 8 && PERL_SUBVERSION == 1
13             # undef assert_not_ROK
14             # if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
15             # define assert_not_ROK(sv) ({assert(!SvROK(sv) || !SvRV(sv));}),
16             # else
17             # define assert_not_ROK(sv)
18             # endif
19             #endif
20              
21             /* HACK: https://github.com/DCIT/perl-CryptX/issues/105 (replacement for SvPOK(sv) suggestet by Leont) */
22             #define SvPOK_spec(sv) (SvOK(sv) && (!SvROK(sv) || SvAMAGIC(sv)))
23              
24             #undef LTC_SOURCE
25             #include "tomcrypt.h"
26             #include "tommath.h"
27              
28             typedef adler32_state *Crypt__Checksum__Adler32;
29             typedef crc32_state *Crypt__Checksum__CRC32;
30              
31             typedef ccm_state *Crypt__AuthEnc__CCM;
32             typedef eax_state *Crypt__AuthEnc__EAX;
33             typedef gcm_state *Crypt__AuthEnc__GCM;
34             typedef chacha20poly1305_state *Crypt__AuthEnc__ChaCha20Poly1305;
35             typedef ocb3_state *Crypt__AuthEnc__OCB;
36              
37             typedef chacha_state *Crypt__Stream__ChaCha;
38             typedef salsa20_state *Crypt__Stream__Salsa20;
39             typedef sosemanuk_state *Crypt__Stream__Sosemanuk;
40             typedef rabbit_state *Crypt__Stream__Rabbit;
41             typedef rc4_state *Crypt__Stream__RC4;
42             typedef sober128_state *Crypt__Stream__Sober128;
43              
44             typedef f9_state *Crypt__Mac__F9;
45             typedef hmac_state *Crypt__Mac__HMAC;
46             typedef omac_state *Crypt__Mac__OMAC;
47             typedef pelican_state *Crypt__Mac__Pelican;
48             typedef pmac_state *Crypt__Mac__PMAC;
49             typedef xcbc_state *Crypt__Mac__XCBC;
50             typedef poly1305_state *Crypt__Mac__Poly1305;
51             typedef blake2smac_state *Crypt__Mac__BLAKE2s;
52             typedef blake2bmac_state *Crypt__Mac__BLAKE2b;
53              
54             typedef struct cipher_struct { /* used by Crypt::Cipher */
55             symmetric_key skey;
56             struct ltc_cipher_descriptor *desc;
57             } *Crypt__Cipher;
58              
59             typedef struct digest_struct { /* used by Crypt::Digest */
60             hash_state state;
61             struct ltc_hash_descriptor *desc;
62             } *Crypt__Digest;
63              
64             typedef struct digest_shake_struct { /* used by Crypt::Digest::SHAKE */
65             hash_state state;
66             int num;
67             } *Crypt__Digest__SHAKE;
68              
69             typedef struct cbc_struct { /* used by Crypt::Mode::CBC */
70             int cipher_id, cipher_rounds;
71             symmetric_CBC state;
72             unsigned char pad[MAXBLOCKSIZE];
73             int padlen;
74             int padding_mode;
75             int direction;
76             } *Crypt__Mode__CBC;
77              
78             typedef struct ecb_struct { /* used by Crypt::Mode::ECB */
79             int cipher_id, cipher_rounds;
80             symmetric_ECB state;
81             unsigned char pad[MAXBLOCKSIZE];
82             int padlen;
83             int padding_mode;
84             int direction;
85             } *Crypt__Mode__ECB;
86              
87             typedef struct cfb_struct { /* used by Crypt::Mode::CFB */
88             int cipher_id, cipher_rounds;
89             symmetric_CFB state;
90             int direction;
91             } *Crypt__Mode__CFB;
92              
93             typedef struct ctr_struct { /* used by Crypt::Mode::CTR */
94             int cipher_id, cipher_rounds;
95             int ctr_mode_param;
96             symmetric_CTR state;
97             int direction;
98             } *Crypt__Mode__CTR;
99              
100             typedef struct f8_struct { /* used by Crypt::Mode::F8 */
101             int cipher_id, cipher_rounds;
102             symmetric_F8 state;
103             int direction;
104             } *Crypt__Mode__F8;
105              
106             typedef struct lrw_struct { /* used by Crypt::Mode::LRW */
107             int cipher_id, cipher_rounds;
108             symmetric_LRW state;
109             int direction;
110             } *Crypt__Mode__LRW;
111              
112             typedef struct ofb_struct { /* used by Crypt::Mode::OFB */
113             int cipher_id, cipher_rounds;
114             symmetric_OFB state;
115             int direction;
116             } *Crypt__Mode__OFB;
117              
118             typedef struct xts_struct { /* used by Crypt::Mode::XTS */
119             int cipher_id, cipher_rounds;
120             symmetric_xts state;
121             int direction;
122             } *Crypt__Mode__XTS;
123              
124             typedef struct prng_struct { /* used by Crypt::PRNG */
125             prng_state state;
126             struct ltc_prng_descriptor *desc;
127             IV last_pid;
128             } *Crypt__PRNG;
129              
130             typedef struct rsa_struct { /* used by Crypt::PK::RSA */
131             prng_state pstate;
132             int pindex;
133             rsa_key key;
134             } *Crypt__PK__RSA;
135              
136             typedef struct dsa_struct { /* used by Crypt::PK::DSA */
137             prng_state pstate;
138             int pindex;
139             dsa_key key;
140             } *Crypt__PK__DSA;
141              
142             typedef struct dh_struct { /* used by Crypt::PK::DH */
143             prng_state pstate;
144             int pindex;
145             dh_key key;
146             } *Crypt__PK__DH;
147              
148             typedef struct ecc_struct { /* used by Crypt::PK::ECC */
149             prng_state pstate;
150             int pindex;
151             ecc_key key;
152             } *Crypt__PK__ECC;
153              
154             typedef struct ed25519_struct { /* used by Crypt::PK::Ed25519 */
155             prng_state pstate;
156             int pindex;
157             curve25519_key key;
158             int initialized;
159             } *Crypt__PK__Ed25519;
160              
161             typedef struct x25519_struct { /* used by Crypt::PK::X25519 */
162             prng_state pstate;
163             int pindex;
164             curve25519_key key;
165             int initialized;
166             } *Crypt__PK__X25519;
167              
168 64           STATIC int cryptx_internal_password_cb_getpw(void **p, unsigned long *l, void *u) {
169             dTHX; /* fetch context */
170 64           SV *passwd = u;
171 64           void *pwd = NULL;
172 64           STRLEN pwd_len = 0;
173              
174 64 50         if (p == NULL) {
175 0           *l = 0;
176 0           return 1;
177             }
178 64 50         if (passwd == NULL || !SvOK(passwd)) {
    50          
179 0           *p = NULL;
180 0           *l = 0;
181 0           return 1;
182             }
183 64           pwd = SvPVbyte(passwd, pwd_len);
184 64 50         if (pwd == NULL || pwd_len == 0) {
    50          
185 0           *p = NULL;
186 0           *l = 0;
187 0           return 1;
188             }
189 64           Newz(0, *p, pwd_len, unsigned char);
190 64 50         if (*p == NULL) {
191 0           *l = 0;
192 0           return 1;
193             }
194 64           Copy(pwd, *p, pwd_len, unsigned char);
195 64           *l = (unsigned long)pwd_len;
196              
197 64           return 0;
198             }
199              
200 64           STATIC void cryptx_internal_password_cb_free(void *p) {
201             dTHX; /* fetch context */
202 64           Safefree(p);
203 64           return;
204             }
205              
206 1304           STATIC int cryptx_internal_mp2hex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) {
207             int len, rv;
208              
209 1304 50         if (mp_isneg(a) == MP_YES) {
210 0           *str = '\0';
211 0           return MP_VAL;
212             }
213              
214 1304           rv = mp_to_radix(a, str, maxlen, NULL, 16);
215 1304 50         if (rv != MP_OKAY) {
216 0           *str = '\0';
217 0           return rv;
218             }
219              
220 1304           len = (int)strlen(str);
221 1304 50         if (len > 0 && len % 2 && len < maxlen-2) {
    100          
    50          
222 259           memmove(str+1, str, len+1); /* incl. NUL byte */
223 259           *str = '0'; /* add leading zero */
224             }
225              
226 1304           len = (int)strlen(str);
227 1304 100         if (len < minlen && minlen < maxlen-1) {
    50          
228 6           memmove(str+(minlen-len), str, len+1); /* incl. NUL byte */
229 6           memset(str, '0', minlen-len); /* add leading zero */
230             }
231              
232 1304           return MP_OKAY;
233             }
234              
235 14319           STATIC size_t cryptx_internal_find_start(const char *name, char *ltcname, size_t ltclen)
236             {
237 14319           size_t i, start = 0;
238 14319 50         if (name == NULL || strlen(name) + 1 > ltclen) croak("FATAL: invalid name") ;
    50          
239             /* normalize */
240 132777 50         for (i = 0; i < ltclen && name[i] > 0; i++) {
    100          
241 118458 100         if (name[i] >= 'A' && name[i] <= 'Z') {
    100          
242 50575           ltcname[i] = name[i] + 32; /* lowecase */
243             }
244 67883 100         else if (name[i] == '_') {
245 1713           ltcname[i] = '-';
246             }
247             else {
248 66170           ltcname[i] = name[i];
249             }
250 118458 100         if (name[i] == ':') start = i + 1;
251             }
252 14319           return start;
253             }
254              
255 8277           STATIC int cryptx_internal_find_hash(const char *name)
256             {
257 8277           char ltcname[100] = { 0 };
258 8277           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
259             /* special cases */
260 8277 100         if (strcmp(ltcname + start, "ripemd128") == 0) return find_hash("rmd128");
261 7813 100         if (strcmp(ltcname + start, "ripemd160") == 0) return find_hash("rmd160");
262 7349 100         if (strcmp(ltcname + start, "ripemd256") == 0) return find_hash("rmd256");
263 7273 100         if (strcmp(ltcname + start, "ripemd320") == 0) return find_hash("rmd320");
264 7197 100         if (strcmp(ltcname + start, "tiger192") == 0) return find_hash("tiger");
265 6715 100         if (strcmp(ltcname + start, "chaes") == 0) return find_hash("chc_hash");
266 6539 50         if (strcmp(ltcname + start, "chc-hash") == 0) return find_hash("chc_hash");
267 6539           return find_hash(ltcname + start);
268             }
269              
270 6029           STATIC int cryptx_internal_find_cipher(const char *name)
271             {
272 6029           char ltcname[100] = { 0 };
273 6029           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
274             /* special cases */
275 6029 100         if (strcmp(ltcname + start, "des-ede") == 0) return find_cipher("3des");
276 5904 100         if (strcmp(ltcname + start, "saferp") == 0) return find_cipher("safer+");
277 5647           return find_cipher(ltcname + start);
278             }
279              
280 13           STATIC int cryptx_internal_find_prng(const char *name)
281             {
282 13           char ltcname[100] = { 0 };
283 13           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
284 13           return find_prng(ltcname + start);
285             }
286              
287             /* Math::BigInt::LTM related */
288             typedef mp_int * Math__BigInt__LTM;
289 181           STATIC SV * sv_from_mpi(mp_int *mpi) {
290             dTHX; /* fetch context */
291 181           SV *obj = newSV(0);
292 181           sv_setref_pv(obj, "Math::BigInt::LTM", (void*)mpi);
293 181           return obj;
294             }
295              
296 2           STATIC void cryptx_internal_ecc_oid_lookup(ecc_key *key)
297             {
298             int err;
299             unsigned i, j;
300             void *tmp;
301             const ltc_ecc_curve *cu;
302              
303 2           key->dp.oidlen = 0;
304 2 50         if ((err = ltc_mp.init(&tmp)) != CRYPT_OK) return;
305 51 100         for (cu = ltc_ecc_curves; cu->prime != NULL; cu++) {
306 50 50         if ((err = mp_read_radix(tmp, cu->prime, 16)) != CRYPT_OK) continue;
307 50 100         if ((mp_cmp(tmp, key->dp.prime) != LTC_MP_EQ)) continue;
308 2 50         if ((err = mp_read_radix(tmp, cu->order, 16)) != CRYPT_OK) continue;
309 2 50         if ((mp_cmp(tmp, key->dp.order) != LTC_MP_EQ)) continue;
310 2 50         if ((err = mp_read_radix(tmp, cu->A, 16)) != CRYPT_OK) continue;
311 2 50         if ((mp_cmp(tmp, key->dp.A) != LTC_MP_EQ)) continue;
312 2 50         if ((err = mp_read_radix(tmp, cu->B, 16)) != CRYPT_OK) continue;
313 2 50         if ((mp_cmp(tmp, key->dp.B) != LTC_MP_EQ)) continue;
314 2 50         if ((err = mp_read_radix(tmp, cu->Gx, 16)) != CRYPT_OK) continue;
315 2 50         if ((mp_cmp(tmp, key->dp.base.x) != LTC_MP_EQ)) continue;
316 2 50         if ((err = mp_read_radix(tmp, cu->Gy, 16)) != CRYPT_OK) continue;
317 2 50         if ((mp_cmp(tmp, key->dp.base.y) != LTC_MP_EQ)) continue;
318 2 100         if (key->dp.cofactor != cu->cofactor) continue;
319 1           break; /* found */
320             }
321 2           ltc_mp.deinit(tmp);
322 2 100         if (cu->prime && cu->OID) {
    50          
323 17 100         for (i = 0; i < 16; i++) key->dp.oid[i] = 0;
324 13 100         for (i = 0, j = 0; i < strlen(cu->OID); i++) {
325 12 100         if (cu->OID[i] == '.') {
326 4 50         if (++j >= 16) return;
327             }
328 8 50         else if(cu->OID[i] >= '0' && cu->OID[i] <= '9') {
    50          
329 8           key->dp.oid[j] = key->dp.oid[j] * 10 + (cu->OID[i] - '0');
330             }
331             else {
332 0           return;
333             }
334             }
335 1           key->dp.oidlen = j + 1;
336             }
337             }
338              
339 193           STATIC int cryptx_internal_ecc_set_curve_from_SV(ecc_key *key, SV *curve)
340             {
341             dTHX; /* fetch context */
342             HV *hc, *h;
343             SV *sv_crv, **pref;
344             SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy, **sv_oid;
345             char *ptr_crv;
346             STRLEN len_crv;
347             int err;
348              
349 193 50         if (!SvOK(curve)) croak("FATAL: undefined curve");
350              
351 193 100         if (SvPOK(curve)) {
352             /* string */
353 191           ptr_crv = SvPV(curve, len_crv);
354 191 50         if ((hc = get_hv("Crypt::PK::ECC::curve", 0)) == NULL) croak("FATAL: no curve register");
355 191           pref = hv_fetch(hc, ptr_crv, (U32)len_crv, 0);
356 191 50         if (pref && SvOK(*pref)) {
    0          
357 0           sv_crv = *pref; /* found in %curve */
358             }
359             else {
360 191           sv_crv = curve;
361             }
362             }
363 2 50         else if (SvROK(curve) && SvTYPE(SvRV(curve)) == SVt_PVHV) {
    50          
364             /* hashref */
365 2           sv_crv = curve;
366             }
367             else {
368 0           croak("FATAL: curve has to be a string or a hashref");
369             }
370              
371 193 100         if (SvPOK(sv_crv)) {
372             /* string - curve name */
373             const ltc_ecc_curve *cu;
374 191           ptr_crv = SvPV(sv_crv, len_crv);
375 191 50         if (ecc_find_curve(ptr_crv, &cu) != CRYPT_OK) croak("FATAL: ecparams: unknown curve '%s'", ptr_crv);
376 191           return ecc_set_curve(cu, key);
377             }
378             else {
379             /* hashref */
380 2           ltc_ecc_curve cu = { 0 };
381              
382 2 50         if ((h = (HV*)(SvRV(sv_crv))) == NULL) croak("FATAL: ecparams: param is not valid hashref");
383              
384 2 50         if ((sv_prime = hv_fetchs(h, "prime", 0)) == NULL) croak("FATAL: ecparams: missing param prime");
385 2 50         if ((sv_A = hv_fetchs(h, "A", 0)) == NULL) croak("FATAL: ecparams: missing param A");
386 2 50         if ((sv_B = hv_fetchs(h, "B", 0)) == NULL) croak("FATAL: ecparams: missing param B");
387 2 50         if ((sv_order = hv_fetchs(h, "order", 0)) == NULL) croak("FATAL: ecparams: missing param order");
388 2 50         if ((sv_Gx = hv_fetchs(h, "Gx", 0)) == NULL) croak("FATAL: ecparams: missing param Gx");
389 2 50         if ((sv_Gy = hv_fetchs(h, "Gy", 0)) == NULL) croak("FATAL: ecparams: missing param Gy");
390 2 50         if ((sv_cofactor = hv_fetchs(h, "cofactor", 0)) == NULL) croak("FATAL: ecparams: missing param cofactor");
391              
392 2 50         if (!SvOK(*sv_prime )) croak("FATAL: ecparams: undefined param prime");
393 2 50         if (!SvOK(*sv_A )) croak("FATAL: ecparams: undefined param A");
394 2 50         if (!SvOK(*sv_B )) croak("FATAL: ecparams: undefined param B");
395 2 50         if (!SvOK(*sv_order )) croak("FATAL: ecparams: undefined param order");
396 2 50         if (!SvOK(*sv_Gx )) croak("FATAL: ecparams: undefined param Gx");
397 2 50         if (!SvOK(*sv_Gy )) croak("FATAL: ecparams: undefined param Gy");
398 2 50         if (!SvOK(*sv_cofactor)) croak("FATAL: ecparams: undefined param cofactor");
399              
400 2           sv_oid = hv_fetchs(h, "oid", 0); /* 'oid' is optional */
401 2 50         cu.OID = (sv_oid && SvOK(*sv_oid)) ? SvPV_nolen(*sv_oid) : NULL;
    0          
402              
403 2           cu.prime = SvPV_nolen(*sv_prime);
404 2           cu.A = SvPV_nolen(*sv_A);
405 2           cu.B = SvPV_nolen(*sv_B);
406 2           cu.order = SvPV_nolen(*sv_order);
407 2           cu.Gx = SvPV_nolen(*sv_Gx);
408 2           cu.Gy = SvPV_nolen(*sv_Gy);
409 2           cu.cofactor = (unsigned long)SvUV(*sv_cofactor);
410              
411 2 50         if ((err = ecc_set_curve(&cu, key)) != CRYPT_OK) return err;
412 2 50         if (key->dp.oidlen == 0) cryptx_internal_ecc_oid_lookup(key);
413 2           return CRYPT_OK;
414             }
415             }
416              
417             MODULE = CryptX PACKAGE = CryptX PREFIX = CryptX_
418              
419             PROTOTYPES: DISABLE
420              
421             BOOT:
422 133 50         if(register_all_ciphers() != CRYPT_OK) { croak("FATAL: register_all_ciphers failed"); }
423 133 50         if(register_all_hashes() != CRYPT_OK) { croak("FATAL: register_all_hashes failed"); }
424 133 50         if(register_all_prngs() != CRYPT_OK) { croak("FATAL: register_all_prngs failed"); }
425 133 50         if(crypt_mp_init("ltm") != CRYPT_OK) { croak("FATAL: crypt_mp_init failed"); }
426              
427             SV *
428             CryptX__ltc_build_settings()
429             CODE:
430 1           RETVAL = newSVpv(crypt_build_settings, 0);
431             OUTPUT:
432             RETVAL
433              
434             SV *
435             CryptX__ltc_mp_name()
436             CODE:
437 1           RETVAL = newSVpv(ltc_mp.name, 0);
438             OUTPUT:
439             RETVAL
440              
441             int
442             CryptX__ltc_mp_bits_per_digit()
443             CODE:
444 1 50         RETVAL = ltc_mp.bits_per_digit;
445             OUTPUT:
446             RETVAL
447              
448             MODULE = CryptX PACKAGE = Crypt::Misc
449              
450             PROTOTYPES: DISABLE
451              
452             SV *
453             _radix_to_bin(char *in, int radix)
454             CODE:
455             {
456             STRLEN len;
457             unsigned char *out_data;
458             mp_int mpi;
459              
460 265 50         if (in == NULL) XSRETURN_UNDEF;
461 265 50         if (mp_init(&mpi) != MP_OKAY) XSRETURN_UNDEF;
462 265 50         if (strlen(in) == 0) {
463 0           RETVAL = newSVpvn("", 0);
464             }
465 265 50         else if (mp_read_radix(&mpi, in, radix) == MP_OKAY) {
466 265           len = mp_ubin_size(&mpi);
467 265 50         if (len == 0) {
468 0           RETVAL = newSVpvn("", 0);
469             }
470             else {
471 265           RETVAL = NEWSV(0, len); /* avoid zero! */
472 265           SvPOK_only(RETVAL);
473 265           SvCUR_set(RETVAL, len);
474 265           out_data = (unsigned char *)SvPVX(RETVAL);
475 265 50         if (mp_to_ubin(&mpi, out_data, len, NULL) != MP_OKAY) {
476 0           SvREFCNT_dec(RETVAL);
477 0           RETVAL = newSVpvn(NULL, 0); /* undef */
478             }
479             }
480             }
481             else {
482 0           RETVAL = newSVpvn(NULL, 0); /* undef */
483             }
484 265           mp_clear(&mpi);
485             }
486             OUTPUT:
487             RETVAL
488              
489             SV *
490             _bin_to_radix(SV *in, int radix)
491             CODE:
492             {
493             STRLEN len;
494             unsigned char *in_data;
495             char *out_data;
496             mp_int mpi, tmp;
497             mp_digit d;
498             mp_err merr;
499 290           int digits = 0;
500              
501 290 50         if (!SvPOK(in) || radix < 2 || radix > 64) XSRETURN_UNDEF;
    50          
    50          
502 290           in_data = (unsigned char *) SvPVbyte(in, len);
503 290 50         if (mp_init_multi(&mpi, &tmp, NULL) != MP_OKAY) XSRETURN_UNDEF;
504 290 50         if (len == 0) {
505 0           RETVAL = newSVpvn("", 0);
506             }
507             else {
508 290 50         if (mp_from_ubin(&mpi, in_data, (size_t)len) == MP_OKAY) {
509 290           merr = mp_copy(&mpi, &tmp);
510 5655 50         while (merr == MP_OKAY && mp_iszero(&tmp) == MP_NO) {
    100          
511 5365           merr = mp_div_d(&tmp, (mp_digit)radix, &tmp, &d);
512 5365           digits++;
513             }
514 290 50         if (merr != MP_OKAY) {
515 0           RETVAL = newSVpvn(NULL, 0); /* undef */
516             }
517 290 100         else if (digits == 0) {
518 25           RETVAL = newSVpvn("", 0);
519             }
520             else {
521 265           RETVAL = NEWSV(0, digits + 2); /* +2 for sign and NUL byte */
522 265           SvPOK_only(RETVAL);
523 265           out_data = SvPVX(RETVAL);
524 265 50         if (mp_to_radix(&mpi, out_data, digits + 2, NULL, radix) == MP_OKAY) {
525 265           SvCUR_set(RETVAL, strlen(out_data));
526             }
527             else {
528 0           SvREFCNT_dec(RETVAL);
529 0           RETVAL = newSVpvn(NULL, 0); /* undef */
530             }
531             }
532             }
533             else {
534 0           RETVAL = newSVpvn(NULL, 0); /* undef */
535             }
536             }
537 290           mp_clear_multi(&tmp, &mpi, NULL);
538             }
539             OUTPUT:
540             RETVAL
541              
542             SV *
543             encode_b64(SV * in)
544             ALIAS:
545             encode_b64u = 1
546             CODE:
547             {
548             int rv;
549             STRLEN in_len;
550             unsigned long out_len;
551             unsigned char *in_data;
552             char *out_data;
553              
554 139 50         if (!SvPOK(in)) XSRETURN_UNDEF;
555 139           in_data = (unsigned char *) SvPVbyte(in, in_len);
556 139 50         if (in_len == 0) {
557 0           RETVAL = newSVpvn("", 0);
558             }
559             else {
560 139           out_len = (unsigned long)(4 * ((in_len + 2) / 3) + 1);
561 139           RETVAL = NEWSV(0, out_len); /* avoid zero! */
562 139           SvPOK_only(RETVAL);
563 139           out_data = SvPVX(RETVAL);
564 139 100         if (ix == 1)
565 59           rv = base64url_encode(in_data, (unsigned long)in_len, out_data, &out_len);
566             else
567 80           rv = base64_encode(in_data, (unsigned long)in_len, out_data, &out_len);
568 139 50         if (rv != CRYPT_OK) {
569 0           SvREFCNT_dec(RETVAL);
570 0           XSRETURN_UNDEF;
571             }
572 139           SvCUR_set(RETVAL, out_len);
573             }
574             }
575             OUTPUT:
576             RETVAL
577              
578             SV *
579             decode_b64(SV * in)
580             ALIAS:
581             decode_b64u = 1
582             CODE:
583             {
584             int rv;
585             STRLEN in_len;
586             unsigned long out_len;
587             unsigned char *out_data;
588             char *in_data;
589              
590 386 50         if (!SvPOK(in)) XSRETURN_UNDEF;
591 386           in_data = SvPVbyte(in, in_len);
592 386 50         if (in_len == 0) {
593 0           RETVAL = newSVpvn("", 0);
594             }
595             else {
596 386           out_len = (unsigned long)in_len;
597 386           RETVAL = NEWSV(0, out_len); /* avoid zero! */
598 386           SvPOK_only(RETVAL);
599 386           out_data = (unsigned char *)SvPVX(RETVAL);
600 386 100         if (ix == 1)
601 76           rv = base64url_sane_decode(in_data, (unsigned long)in_len, out_data, &out_len);
602             else
603 310           rv = base64_sane_decode(in_data, (unsigned long)in_len, out_data, &out_len);
604 386 50         if (rv != CRYPT_OK) {
605 0           SvREFCNT_dec(RETVAL);
606 0           XSRETURN_UNDEF;
607             }
608 386           SvCUR_set(RETVAL, out_len);
609             }
610             }
611             OUTPUT:
612             RETVAL
613              
614             SV *
615             encode_b32r(SV *in)
616             ALIAS:
617             encode_b32b = 1
618             encode_b32z = 2
619             encode_b32c = 3
620             CODE:
621             {
622             STRLEN in_len;
623             unsigned long out_len;
624             unsigned char *in_data;
625             char *out_data;
626 232           int id = -1, err;
627              
628 232 50         if (!SvPOK(in)) XSRETURN_UNDEF;
629 232 100         if (ix == 0) id = BASE32_RFC4648;
630 232 100         if (ix == 1) id = BASE32_BASE32HEX;
631 232 100         if (ix == 2) id = BASE32_ZBASE32;
632 232 100         if (ix == 3) id = BASE32_CROCKFORD;
633 232 50         if (id == -1) XSRETURN_UNDEF;
634 232           in_data = (unsigned char *) SvPVbyte(in, in_len);
635 232 50         if (in_len == 0) {
636 0           RETVAL = newSVpvn("", 0);
637             }
638             else {
639 232           out_len = (unsigned long)((8 * in_len + 4) / 5 + 1);
640 232           RETVAL = NEWSV(0, out_len); /* avoid zero! */
641 232           SvPOK_only(RETVAL);
642 232           out_data = SvPVX(RETVAL);
643 232           err = base32_encode(in_data, (unsigned long)in_len, out_data, &out_len, id);
644 232 50         if (err != CRYPT_OK) {
645 0           SvREFCNT_dec(RETVAL);
646 0           XSRETURN_UNDEF;
647             }
648 232           SvCUR_set(RETVAL, out_len);
649             }
650             }
651             OUTPUT:
652             RETVAL
653              
654             SV *
655             decode_b32r(SV *in)
656             ALIAS:
657             decode_b32b = 1
658             decode_b32z = 2
659             decode_b32c = 3
660             CODE:
661             {
662             STRLEN in_len;
663             unsigned long out_len;
664             unsigned char *out_data;
665             char *in_data;
666 232           int id = -1, err;
667              
668 232 50         if (!SvPOK(in)) XSRETURN_UNDEF;
669 232 100         if (ix == 0) id = BASE32_RFC4648;
670 232 100         if (ix == 1) id = BASE32_BASE32HEX;
671 232 100         if (ix == 2) id = BASE32_ZBASE32;
672 232 100         if (ix == 3) id = BASE32_CROCKFORD;
673 232 50         if (id == -1) XSRETURN_UNDEF;
674 232           in_data = SvPVbyte(in, in_len);
675 232 50         if (in_len == 0) {
676 0           RETVAL = newSVpvn("", 0);
677             }
678             else {
679 232           out_len = (unsigned long)in_len;
680 232           RETVAL = NEWSV(0, out_len); /* avoid zero! */
681 232           SvPOK_only(RETVAL);
682 232           out_data = (unsigned char *)SvPVX(RETVAL);
683 232           err = base32_decode(in_data, (unsigned long)in_len, out_data, &out_len, id);
684 232 50         if (err != CRYPT_OK) {
685 0           SvREFCNT_dec(RETVAL);
686 0           XSRETURN_UNDEF;
687             }
688 232           SvCUR_set(RETVAL, out_len);
689             }
690             }
691             OUTPUT:
692             RETVAL
693              
694             SV *
695             increment_octets_le(SV * in)
696             CODE:
697             {
698 0           STRLEN len, i = 0;
699             unsigned char *out_data, *in_data;
700              
701 0 0         if (!SvPOK(in)) XSRETURN_UNDEF;
702 0           in_data = (unsigned char *)SvPVbyte(in, len);
703 0 0         if (len == 0) {
704 0           RETVAL = newSVpvn("", 0);
705             }
706             else {
707 0           RETVAL = NEWSV(0, len); /* avoid zero! */
708 0           SvPOK_only(RETVAL);
709 0           SvCUR_set(RETVAL, len);
710 0           out_data = (unsigned char *)SvPVX(RETVAL);
711 0           Copy(in_data, out_data, len, unsigned char);
712 0 0         while (i < len) {
713 0           out_data[i]++;
714 0 0         if (0 != out_data[i]) break;
715 0           i++;
716             }
717 0 0         if (i == len) {
718 0           SvREFCNT_dec(RETVAL);
719 0           croak("FATAL: increment_octets_le overflow");
720             }
721             }
722             }
723             OUTPUT:
724             RETVAL
725              
726             SV *
727             increment_octets_be(SV * in)
728             CODE:
729             {
730 0           STRLEN len, i = 0;
731             unsigned char *out_data, *in_data;
732              
733 0 0         if (!SvPOK(in)) XSRETURN_UNDEF;
734 0           in_data = (unsigned char *)SvPVbyte(in, len);
735 0 0         if (len == 0) {
736 0           RETVAL = newSVpvn("", 0);
737             }
738             else {
739 0           RETVAL = NEWSV(0, len); /* avoid zero! */
740 0           SvPOK_only(RETVAL);
741 0           SvCUR_set(RETVAL, len);
742 0           out_data = (unsigned char *)SvPVX(RETVAL);
743 0           Copy(in_data, out_data, len, unsigned char);
744 0 0         while (i < len) {
745 0           out_data[len - 1 - i]++;
746 0 0         if (0 != out_data[len - 1 - i]) break;
747 0           i++;
748             }
749 0 0         if (i == len) {
750 0           SvREFCNT_dec(RETVAL);
751 0           croak("FATAL: increment_octets_be overflow");
752             }
753             }
754             }
755             OUTPUT:
756             RETVAL
757              
758             ###############################################################################
759              
760             INCLUDE: inc/CryptX_Digest.xs.inc
761             INCLUDE: inc/CryptX_Digest_SHAKE.xs.inc
762             INCLUDE: inc/CryptX_Cipher.xs.inc
763              
764             INCLUDE: inc/CryptX_Checksum_Adler32.xs.inc
765             INCLUDE: inc/CryptX_Checksum_CRC32.xs.inc
766              
767             INCLUDE: inc/CryptX_AuthEnc_EAX.xs.inc
768             INCLUDE: inc/CryptX_AuthEnc_GCM.xs.inc
769             INCLUDE: inc/CryptX_AuthEnc_OCB.xs.inc
770             INCLUDE: inc/CryptX_AuthEnc_CCM.xs.inc
771             INCLUDE: inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc
772              
773             INCLUDE: inc/CryptX_Stream_ChaCha.xs.inc
774             INCLUDE: inc/CryptX_Stream_Salsa20.xs.inc
775             INCLUDE: inc/CryptX_Stream_RC4.xs.inc
776             INCLUDE: inc/CryptX_Stream_Sober128.xs.inc
777             INCLUDE: inc/CryptX_Stream_Sosemanuk.xs.inc
778             INCLUDE: inc/CryptX_Stream_Rabbit.xs.inc
779              
780             INCLUDE: inc/CryptX_Mac_F9.xs.inc
781             INCLUDE: inc/CryptX_Mac_HMAC.xs.inc
782             INCLUDE: inc/CryptX_Mac_OMAC.xs.inc
783             INCLUDE: inc/CryptX_Mac_Pelican.xs.inc
784             INCLUDE: inc/CryptX_Mac_PMAC.xs.inc
785             INCLUDE: inc/CryptX_Mac_XCBC.xs.inc
786             INCLUDE: inc/CryptX_Mac_Poly1305.xs.inc
787             INCLUDE: inc/CryptX_Mac_BLAKE2s.xs.inc
788             INCLUDE: inc/CryptX_Mac_BLAKE2b.xs.inc
789              
790             INCLUDE: inc/CryptX_Mode_CBC.xs.inc
791             INCLUDE: inc/CryptX_Mode_ECB.xs.inc
792             INCLUDE: inc/CryptX_Mode_CFB.xs.inc
793             INCLUDE: inc/CryptX_Mode_OFB.xs.inc
794             INCLUDE: inc/CryptX_Mode_CTR.xs.inc
795             #INCLUDE: inc/CryptX_Mode_F8.xs.inc
796             #INCLUDE: inc/CryptX_Mode_LRW.xs.inc
797             #INCLUDE: inc/CryptX_Mode_XTS.xs.inc
798              
799             INCLUDE: inc/CryptX_PRNG.xs.inc
800              
801             INCLUDE: inc/CryptX_PK_RSA.xs.inc
802             INCLUDE: inc/CryptX_PK_DSA.xs.inc
803             INCLUDE: inc/CryptX_PK_DH.xs.inc
804             INCLUDE: inc/CryptX_PK_ECC.xs.inc
805             INCLUDE: inc/CryptX_PK_Ed25519.xs.inc
806             INCLUDE: inc/CryptX_PK_X25519.xs.inc
807              
808             INCLUDE: inc/CryptX_KeyDerivation.xs.inc
809              
810             INCLUDE: inc/CryptX_BigInt_LTM.xs.inc