File Coverage

CryptX.xs
Criterion Covered Total %
statement 231 311 74.2
branch 162 282 57.4
condition n/a
subroutine n/a
pod n/a
total 393 593 66.2


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             IV last_pid;
134             rsa_key key;
135             } *Crypt__PK__RSA;
136              
137             typedef struct dsa_struct { /* used by Crypt::PK::DSA */
138             prng_state pstate;
139             int pindex;
140             IV last_pid;
141             dsa_key key;
142             } *Crypt__PK__DSA;
143              
144             typedef struct dh_struct { /* used by Crypt::PK::DH */
145             prng_state pstate;
146             int pindex;
147             IV last_pid;
148             dh_key key;
149             } *Crypt__PK__DH;
150              
151             typedef struct ecc_struct { /* used by Crypt::PK::ECC */
152             prng_state pstate;
153             int pindex;
154             IV last_pid;
155             ecc_key key;
156             } *Crypt__PK__ECC;
157              
158             typedef struct ed25519_struct { /* used by Crypt::PK::Ed25519 */
159             prng_state pstate;
160             int pindex;
161             IV last_pid;
162             curve25519_key key;
163             int initialized;
164             } *Crypt__PK__Ed25519;
165              
166             typedef struct x25519_struct { /* used by Crypt::PK::X25519 */
167             prng_state pstate;
168             int pindex;
169             IV last_pid;
170             curve25519_key key;
171             int initialized;
172             } *Crypt__PK__X25519;
173              
174 64           STATIC int cryptx_internal_password_cb_getpw(void **p, unsigned long *l, void *u) {
175             dTHX; /* fetch context */
176 64           SV *passwd = u;
177 64           void *pwd = NULL;
178 64           STRLEN pwd_len = 0;
179              
180 64 50         if (p == NULL) {
181 0           *l = 0;
182 0           return 1;
183             }
184 64 50         if (passwd == NULL || !SvOK(passwd)) {
    50          
185 0           *p = NULL;
186 0           *l = 0;
187 0           return 1;
188             }
189 64           pwd = SvPVbyte(passwd, pwd_len);
190 64 50         if (pwd == NULL || pwd_len == 0) {
    50          
191 0           *p = NULL;
192 0           *l = 0;
193 0           return 1;
194             }
195 64           Newz(0, *p, pwd_len, unsigned char);
196 64 50         if (*p == NULL) {
197 0           *l = 0;
198 0           return 1;
199             }
200 64           Copy(pwd, *p, pwd_len, unsigned char);
201 64           *l = (unsigned long)pwd_len;
202              
203 64           return 0;
204             }
205              
206 369           STATIC void cryptx_internal_pk_prng_reseed(prng_state *state, int pindex, IV *last_pid) {
207             dTHX; /* fetch context */
208 369           IV curpid = (IV)PerlProc_getpid();
209             unsigned char entropy_buf[40];
210             int rv;
211              
212 369 50         if (*last_pid == curpid) return;
213              
214 0 0         if (rng_get_bytes(entropy_buf, sizeof(entropy_buf), NULL) != sizeof(entropy_buf)) {
215 0           croak("FATAL: rng_get_bytes failed");
216             }
217 0           rv = prng_descriptor[pindex].add_entropy(entropy_buf, sizeof(entropy_buf), state);
218 0 0         if (rv != CRYPT_OK) croak("FATAL: PRNG_add_entropy failed: %s", error_to_string(rv));
219 0           rv = prng_descriptor[pindex].ready(state);
220 0 0         if (rv != CRYPT_OK) croak("FATAL: PRNG_ready failed: %s", error_to_string(rv));
221 0           *last_pid = curpid;
222             }
223              
224 64           STATIC void cryptx_internal_password_cb_free(void *p) {
225             dTHX; /* fetch context */
226 64           Safefree(p);
227 64           return;
228             }
229              
230 1330           STATIC int cryptx_internal_mp2hex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) {
231             int len, rv;
232              
233 1330 50         if (mp_isneg(a) == MP_YES) {
234 0           *str = '\0';
235 0           return MP_VAL;
236             }
237              
238 1330           rv = mp_to_radix(a, str, maxlen, NULL, 16);
239 1330 50         if (rv != MP_OKAY) {
240 0           *str = '\0';
241 0           return rv;
242             }
243              
244 1330           len = (int)strlen(str);
245 1330 50         if (len > 0 && len % 2 && len < maxlen-2) {
    100          
    50          
246 267           memmove(str+1, str, len+1); /* incl. NUL byte */
247 267           *str = '0'; /* add leading zero */
248             }
249              
250 1330           len = (int)strlen(str);
251 1330 100         if (len < minlen && minlen < maxlen-1) {
    50          
252 6           memmove(str+(minlen-len), str, len+1); /* incl. NUL byte */
253 6           memset(str, '0', minlen-len); /* add leading zero */
254             }
255              
256 1330           return MP_OKAY;
257             }
258              
259 14371           STATIC size_t cryptx_internal_find_start(const char *name, char *ltcname, size_t ltclen)
260             {
261 14371           size_t i, start = 0;
262 14371 50         if (name == NULL || strlen(name) + 1 > ltclen) croak("FATAL: invalid name") ;
    50          
263             /* normalize */
264 133175 50         for (i = 0; i < ltclen && name[i] > 0; i++) {
    100          
265 118804 100         if (name[i] >= 'A' && name[i] <= 'Z') {
    100          
266 50747           ltcname[i] = name[i] + 32; /* lowecase */
267             }
268 68057 100         else if (name[i] == '_') {
269 1713           ltcname[i] = '-';
270             }
271             else {
272 66344           ltcname[i] = name[i];
273             }
274 118804 100         if (name[i] == ':') start = i + 1;
275             }
276 14371           return start;
277             }
278              
279 8322           STATIC int cryptx_internal_find_hash(const char *name)
280             {
281 8322           char ltcname[100] = { 0 };
282 8322           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
283             /* special cases */
284 8322 100         if (strcmp(ltcname + start, "ripemd128") == 0) return find_hash("rmd128");
285 7858 100         if (strcmp(ltcname + start, "ripemd160") == 0) return find_hash("rmd160");
286 7394 100         if (strcmp(ltcname + start, "ripemd256") == 0) return find_hash("rmd256");
287 7318 100         if (strcmp(ltcname + start, "ripemd320") == 0) return find_hash("rmd320");
288 7242 100         if (strcmp(ltcname + start, "tiger192") == 0) return find_hash("tiger");
289 6760 100         if (strcmp(ltcname + start, "chaes") == 0) return find_hash("chc_hash");
290 6584 50         if (strcmp(ltcname + start, "chc-hash") == 0) return find_hash("chc_hash");
291 6584           return find_hash(ltcname + start);
292             }
293              
294 6030           STATIC int cryptx_internal_find_cipher(const char *name)
295             {
296 6030           char ltcname[100] = { 0 };
297 6030           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
298             /* special cases */
299 6030 100         if (strcmp(ltcname + start, "des-ede") == 0) return find_cipher("3des");
300 5905 100         if (strcmp(ltcname + start, "saferp") == 0) return find_cipher("safer+");
301 5648           return find_cipher(ltcname + start);
302             }
303              
304 19           STATIC int cryptx_internal_find_prng(const char *name)
305             {
306 19           char ltcname[100] = { 0 };
307 19           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
308 19           return find_prng(ltcname + start);
309             }
310              
311             /* Math::BigInt::LTM related */
312             typedef mp_int * Math__BigInt__LTM;
313 181           STATIC SV * sv_from_mpi(mp_int *mpi) {
314             dTHX; /* fetch context */
315 181           SV *obj = newSV(0);
316 181           sv_setref_pv(obj, "Math::BigInt::LTM", (void*)mpi);
317 181           return obj;
318             }
319              
320 2           STATIC void cryptx_internal_ecc_oid_lookup(ecc_key *key)
321             {
322             int err;
323             unsigned i, j;
324             void *tmp;
325             const ltc_ecc_curve *cu;
326              
327 2           key->dp.oidlen = 0;
328 2 50         if ((err = ltc_mp.init(&tmp)) != CRYPT_OK) return;
329 51 100         for (cu = ltc_ecc_curves; cu->prime != NULL; cu++) {
330 50 50         if ((err = mp_read_radix(tmp, cu->prime, 16)) != CRYPT_OK) continue;
331 50 100         if ((mp_cmp(tmp, key->dp.prime) != LTC_MP_EQ)) continue;
332 2 50         if ((err = mp_read_radix(tmp, cu->order, 16)) != CRYPT_OK) continue;
333 2 50         if ((mp_cmp(tmp, key->dp.order) != LTC_MP_EQ)) continue;
334 2 50         if ((err = mp_read_radix(tmp, cu->A, 16)) != CRYPT_OK) continue;
335 2 50         if ((mp_cmp(tmp, key->dp.A) != LTC_MP_EQ)) continue;
336 2 50         if ((err = mp_read_radix(tmp, cu->B, 16)) != CRYPT_OK) continue;
337 2 50         if ((mp_cmp(tmp, key->dp.B) != LTC_MP_EQ)) continue;
338 2 50         if ((err = mp_read_radix(tmp, cu->Gx, 16)) != CRYPT_OK) continue;
339 2 50         if ((mp_cmp(tmp, key->dp.base.x) != LTC_MP_EQ)) continue;
340 2 50         if ((err = mp_read_radix(tmp, cu->Gy, 16)) != CRYPT_OK) continue;
341 2 50         if ((mp_cmp(tmp, key->dp.base.y) != LTC_MP_EQ)) continue;
342 2 100         if (key->dp.cofactor != cu->cofactor) continue;
343 1           break; /* found */
344             }
345 2           ltc_mp.deinit(tmp);
346 2 100         if (cu->prime && cu->OID) {
    50          
347 17 100         for (i = 0; i < 16; i++) key->dp.oid[i] = 0;
348 13 100         for (i = 0, j = 0; i < strlen(cu->OID); i++) {
349 12 100         if (cu->OID[i] == '.') {
350 4 50         if (++j >= 16) return;
351             }
352 8 50         else if(cu->OID[i] >= '0' && cu->OID[i] <= '9') {
    50          
353 8           key->dp.oid[j] = key->dp.oid[j] * 10 + (cu->OID[i] - '0');
354             }
355             else {
356 0           return;
357             }
358             }
359 1           key->dp.oidlen = j + 1;
360             }
361             }
362              
363 195           STATIC int cryptx_internal_ecc_set_curve_from_SV(ecc_key *key, SV *curve)
364             {
365             dTHX; /* fetch context */
366             HV *hc, *h;
367             SV *sv_crv, **pref;
368             SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy, **sv_oid;
369             char *ptr_crv;
370             STRLEN len_crv;
371             int err;
372              
373 195 50         if (!SvOK(curve)) croak("FATAL: undefined curve");
374              
375 195 100         if (SvPOK(curve)) {
376             /* string */
377 193           ptr_crv = SvPV(curve, len_crv);
378 193 50         if ((hc = get_hv("Crypt::PK::ECC::curve", 0)) == NULL) croak("FATAL: no curve register");
379 193           pref = hv_fetch(hc, ptr_crv, (U32)len_crv, 0);
380 193 50         if (pref && SvOK(*pref)) {
    0          
381 0           sv_crv = *pref; /* found in %curve */
382             }
383             else {
384 193           sv_crv = curve;
385             }
386             }
387 2 50         else if (SvROK(curve) && SvTYPE(SvRV(curve)) == SVt_PVHV) {
    50          
388             /* hashref */
389 2           sv_crv = curve;
390             }
391             else {
392 0           croak("FATAL: curve has to be a string or a hashref");
393             }
394              
395 195 100         if (SvPOK(sv_crv)) {
396             /* string - curve name */
397             const ltc_ecc_curve *cu;
398 193           ptr_crv = SvPV(sv_crv, len_crv);
399 193 50         if (ecc_find_curve(ptr_crv, &cu) != CRYPT_OK) croak("FATAL: ecparams: unknown curve '%s'", ptr_crv);
400 193           return ecc_set_curve(cu, key);
401             }
402             else {
403             /* hashref */
404 2           ltc_ecc_curve cu = { 0 };
405              
406 2 50         if ((h = (HV*)(SvRV(sv_crv))) == NULL) croak("FATAL: ecparams: param is not valid hashref");
407              
408 2 50         if ((sv_prime = hv_fetchs(h, "prime", 0)) == NULL) croak("FATAL: ecparams: missing param prime");
409 2 50         if ((sv_A = hv_fetchs(h, "A", 0)) == NULL) croak("FATAL: ecparams: missing param A");
410 2 50         if ((sv_B = hv_fetchs(h, "B", 0)) == NULL) croak("FATAL: ecparams: missing param B");
411 2 50         if ((sv_order = hv_fetchs(h, "order", 0)) == NULL) croak("FATAL: ecparams: missing param order");
412 2 50         if ((sv_Gx = hv_fetchs(h, "Gx", 0)) == NULL) croak("FATAL: ecparams: missing param Gx");
413 2 50         if ((sv_Gy = hv_fetchs(h, "Gy", 0)) == NULL) croak("FATAL: ecparams: missing param Gy");
414 2 50         if ((sv_cofactor = hv_fetchs(h, "cofactor", 0)) == NULL) croak("FATAL: ecparams: missing param cofactor");
415              
416 2 50         if (!SvOK(*sv_prime )) croak("FATAL: ecparams: undefined param prime");
417 2 50         if (!SvOK(*sv_A )) croak("FATAL: ecparams: undefined param A");
418 2 50         if (!SvOK(*sv_B )) croak("FATAL: ecparams: undefined param B");
419 2 50         if (!SvOK(*sv_order )) croak("FATAL: ecparams: undefined param order");
420 2 50         if (!SvOK(*sv_Gx )) croak("FATAL: ecparams: undefined param Gx");
421 2 50         if (!SvOK(*sv_Gy )) croak("FATAL: ecparams: undefined param Gy");
422 2 50         if (!SvOK(*sv_cofactor)) croak("FATAL: ecparams: undefined param cofactor");
423              
424 2           sv_oid = hv_fetchs(h, "oid", 0); /* 'oid' is optional */
425 2 50         cu.OID = (sv_oid && SvOK(*sv_oid)) ? SvPV_nolen(*sv_oid) : NULL;
    0          
426              
427 2           cu.prime = SvPV_nolen(*sv_prime);
428 2           cu.A = SvPV_nolen(*sv_A);
429 2           cu.B = SvPV_nolen(*sv_B);
430 2           cu.order = SvPV_nolen(*sv_order);
431 2           cu.Gx = SvPV_nolen(*sv_Gx);
432 2           cu.Gy = SvPV_nolen(*sv_Gy);
433 2           cu.cofactor = (unsigned long)SvUV(*sv_cofactor);
434              
435 2 50         if ((err = ecc_set_curve(&cu, key)) != CRYPT_OK) return err;
436 2 50         if (key->dp.oidlen == 0) cryptx_internal_ecc_oid_lookup(key);
437 2           return CRYPT_OK;
438             }
439             }
440              
441             MODULE = CryptX PACKAGE = CryptX PREFIX = CryptX_
442              
443             PROTOTYPES: DISABLE
444              
445             BOOT:
446 134 50         if(register_all_ciphers() != CRYPT_OK) { croak("FATAL: register_all_ciphers failed"); }
447 134 50         if(register_all_hashes() != CRYPT_OK) { croak("FATAL: register_all_hashes failed"); }
448 134 50         if(register_all_prngs() != CRYPT_OK) { croak("FATAL: register_all_prngs failed"); }
449 134 50         if(crypt_mp_init("ltm") != CRYPT_OK) { croak("FATAL: crypt_mp_init failed"); }
450              
451             SV *
452             CryptX__ltc_build_settings()
453             CODE:
454 1           RETVAL = newSVpv(crypt_build_settings, 0);
455             OUTPUT:
456             RETVAL
457              
458             SV *
459             CryptX__ltc_mp_name()
460             CODE:
461 1           RETVAL = newSVpv(ltc_mp.name, 0);
462             OUTPUT:
463             RETVAL
464              
465             int
466             CryptX__ltc_mp_bits_per_digit()
467             CODE:
468 1 50         RETVAL = ltc_mp.bits_per_digit;
469             OUTPUT:
470             RETVAL
471              
472             MODULE = CryptX PACKAGE = Crypt::Misc
473              
474             PROTOTYPES: DISABLE
475              
476             SV *
477             _radix_to_bin(char *in, int radix)
478             CODE:
479             {
480             STRLEN len;
481             unsigned char *out_data;
482             mp_int mpi;
483              
484 265 50         if (in == NULL) XSRETURN_UNDEF;
485 265 50         if (mp_init(&mpi) != MP_OKAY) XSRETURN_UNDEF;
486 265 50         if (strlen(in) == 0) {
487 0           RETVAL = newSVpvn("", 0);
488             }
489 265 50         else if (mp_read_radix(&mpi, in, radix) == MP_OKAY) {
490 265           len = mp_ubin_size(&mpi);
491 265 50         if (len == 0) {
492 0           RETVAL = newSVpvn("", 0);
493             }
494             else {
495 265           RETVAL = NEWSV(0, len); /* avoid zero! */
496 265           SvPOK_only(RETVAL);
497 265           SvCUR_set(RETVAL, len);
498 265           out_data = (unsigned char *)SvPVX(RETVAL);
499 265 50         if (mp_to_ubin(&mpi, out_data, len, NULL) != MP_OKAY) {
500 0           SvREFCNT_dec(RETVAL);
501 0           RETVAL = newSVpvn(NULL, 0); /* undef */
502             }
503             }
504             }
505             else {
506 0           RETVAL = newSVpvn(NULL, 0); /* undef */
507             }
508 265           mp_clear(&mpi);
509             }
510             OUTPUT:
511             RETVAL
512              
513             SV *
514             _bin_to_radix(SV *in, int radix)
515             CODE:
516             {
517             STRLEN len;
518             unsigned char *in_data;
519             char *out_data;
520             mp_int mpi, tmp;
521             mp_digit d;
522             mp_err merr;
523 290           int digits = 0;
524              
525 290 50         if (!SvPOK(in) || radix < 2 || radix > 64) XSRETURN_UNDEF;
    50          
    50          
526 290           in_data = (unsigned char *) SvPVbyte(in, len);
527 290 50         if (mp_init_multi(&mpi, &tmp, NULL) != MP_OKAY) XSRETURN_UNDEF;
528 290 50         if (len == 0) {
529 0           RETVAL = newSVpvn("", 0);
530             }
531             else {
532 290 50         if (mp_from_ubin(&mpi, in_data, (size_t)len) == MP_OKAY) {
533 290           merr = mp_copy(&mpi, &tmp);
534 5655 50         while (merr == MP_OKAY && mp_iszero(&tmp) == MP_NO) {
    100          
535 5365           merr = mp_div_d(&tmp, (mp_digit)radix, &tmp, &d);
536 5365           digits++;
537             }
538 290 50         if (merr != MP_OKAY) {
539 0           RETVAL = newSVpvn(NULL, 0); /* undef */
540             }
541 290 100         else if (digits == 0) {
542 25           RETVAL = newSVpvn("", 0);
543             }
544             else {
545 265           RETVAL = NEWSV(0, digits + 2); /* +2 for sign and NUL byte */
546 265           SvPOK_only(RETVAL);
547 265           out_data = SvPVX(RETVAL);
548 265 50         if (mp_to_radix(&mpi, out_data, digits + 2, NULL, radix) == MP_OKAY) {
549 265           SvCUR_set(RETVAL, strlen(out_data));
550             }
551             else {
552 0           SvREFCNT_dec(RETVAL);
553 0           RETVAL = newSVpvn(NULL, 0); /* undef */
554             }
555             }
556             }
557             else {
558 0           RETVAL = newSVpvn(NULL, 0); /* undef */
559             }
560             }
561 290           mp_clear_multi(&tmp, &mpi, NULL);
562             }
563             OUTPUT:
564             RETVAL
565              
566             SV *
567             encode_b64(SV * in)
568             ALIAS:
569             encode_b64u = 1
570             CODE:
571             {
572             int rv;
573             STRLEN in_len;
574             unsigned long out_len;
575             unsigned char *in_data;
576             char *out_data;
577              
578 139 50         if (!SvPOK(in)) XSRETURN_UNDEF;
579 139           in_data = (unsigned char *) SvPVbyte(in, in_len);
580 139 50         if (in_len == 0) {
581 0           RETVAL = newSVpvn("", 0);
582             }
583             else {
584 139           out_len = (unsigned long)(4 * ((in_len + 2) / 3) + 1);
585 139           RETVAL = NEWSV(0, out_len); /* avoid zero! */
586 139           SvPOK_only(RETVAL);
587 139           out_data = SvPVX(RETVAL);
588 139 100         if (ix == 1)
589 59           rv = base64url_encode(in_data, (unsigned long)in_len, out_data, &out_len);
590             else
591 80           rv = base64_encode(in_data, (unsigned long)in_len, out_data, &out_len);
592 139 50         if (rv != CRYPT_OK) {
593 0           SvREFCNT_dec(RETVAL);
594 0           XSRETURN_UNDEF;
595             }
596 139           SvCUR_set(RETVAL, out_len);
597             }
598             }
599             OUTPUT:
600             RETVAL
601              
602             SV *
603             decode_b64(SV * in)
604             ALIAS:
605             decode_b64u = 1
606             CODE:
607             {
608             int rv;
609             STRLEN in_len;
610             unsigned long out_len;
611             unsigned char *out_data;
612             char *in_data;
613              
614 386 50         if (!SvPOK(in)) XSRETURN_UNDEF;
615 386           in_data = SvPVbyte(in, in_len);
616 386 50         if (in_len == 0) {
617 0           RETVAL = newSVpvn("", 0);
618             }
619             else {
620 386           out_len = (unsigned long)in_len;
621 386           RETVAL = NEWSV(0, out_len); /* avoid zero! */
622 386           SvPOK_only(RETVAL);
623 386           out_data = (unsigned char *)SvPVX(RETVAL);
624 386 100         if (ix == 1)
625 76           rv = base64url_sane_decode(in_data, (unsigned long)in_len, out_data, &out_len);
626             else
627 310           rv = base64_sane_decode(in_data, (unsigned long)in_len, out_data, &out_len);
628 386 50         if (rv != CRYPT_OK) {
629 0           SvREFCNT_dec(RETVAL);
630 0           XSRETURN_UNDEF;
631             }
632 386           SvCUR_set(RETVAL, out_len);
633             }
634             }
635             OUTPUT:
636             RETVAL
637              
638             SV *
639             encode_b32r(SV *in)
640             ALIAS:
641             encode_b32b = 1
642             encode_b32z = 2
643             encode_b32c = 3
644             CODE:
645             {
646             STRLEN in_len;
647             unsigned long out_len;
648             unsigned char *in_data;
649             char *out_data;
650 232           int id = -1, err;
651              
652 232 50         if (!SvPOK(in)) XSRETURN_UNDEF;
653 232 100         if (ix == 0) id = BASE32_RFC4648;
654 232 100         if (ix == 1) id = BASE32_BASE32HEX;
655 232 100         if (ix == 2) id = BASE32_ZBASE32;
656 232 100         if (ix == 3) id = BASE32_CROCKFORD;
657 232 50         if (id == -1) XSRETURN_UNDEF;
658 232           in_data = (unsigned char *) SvPVbyte(in, in_len);
659 232 50         if (in_len == 0) {
660 0           RETVAL = newSVpvn("", 0);
661             }
662             else {
663 232           out_len = (unsigned long)((8 * in_len + 4) / 5 + 1);
664 232           RETVAL = NEWSV(0, out_len); /* avoid zero! */
665 232           SvPOK_only(RETVAL);
666 232           out_data = SvPVX(RETVAL);
667 232           err = base32_encode(in_data, (unsigned long)in_len, out_data, &out_len, id);
668 232 50         if (err != CRYPT_OK) {
669 0           SvREFCNT_dec(RETVAL);
670 0           XSRETURN_UNDEF;
671             }
672 232           SvCUR_set(RETVAL, out_len);
673             }
674             }
675             OUTPUT:
676             RETVAL
677              
678             SV *
679             decode_b32r(SV *in)
680             ALIAS:
681             decode_b32b = 1
682             decode_b32z = 2
683             decode_b32c = 3
684             CODE:
685             {
686             STRLEN in_len;
687             unsigned long out_len;
688             unsigned char *out_data;
689             char *in_data;
690 232           int id = -1, err;
691              
692 232 50         if (!SvPOK(in)) XSRETURN_UNDEF;
693 232 100         if (ix == 0) id = BASE32_RFC4648;
694 232 100         if (ix == 1) id = BASE32_BASE32HEX;
695 232 100         if (ix == 2) id = BASE32_ZBASE32;
696 232 100         if (ix == 3) id = BASE32_CROCKFORD;
697 232 50         if (id == -1) XSRETURN_UNDEF;
698 232           in_data = SvPVbyte(in, in_len);
699 232 50         if (in_len == 0) {
700 0           RETVAL = newSVpvn("", 0);
701             }
702             else {
703 232           out_len = (unsigned long)in_len;
704 232           RETVAL = NEWSV(0, out_len); /* avoid zero! */
705 232           SvPOK_only(RETVAL);
706 232           out_data = (unsigned char *)SvPVX(RETVAL);
707 232           err = base32_decode(in_data, (unsigned long)in_len, out_data, &out_len, id);
708 232 50         if (err != CRYPT_OK) {
709 0           SvREFCNT_dec(RETVAL);
710 0           XSRETURN_UNDEF;
711             }
712 232           SvCUR_set(RETVAL, out_len);
713             }
714             }
715             OUTPUT:
716             RETVAL
717              
718             SV *
719             increment_octets_le(SV * in)
720             CODE:
721             {
722 0           STRLEN len, i = 0;
723             unsigned char *out_data, *in_data;
724              
725 0 0         if (!SvPOK(in)) XSRETURN_UNDEF;
726 0           in_data = (unsigned char *)SvPVbyte(in, len);
727 0 0         if (len == 0) {
728 0           RETVAL = newSVpvn("", 0);
729             }
730             else {
731 0           RETVAL = NEWSV(0, len); /* avoid zero! */
732 0           SvPOK_only(RETVAL);
733 0           SvCUR_set(RETVAL, len);
734 0           out_data = (unsigned char *)SvPVX(RETVAL);
735 0           Copy(in_data, out_data, len, unsigned char);
736 0 0         while (i < len) {
737 0           out_data[i]++;
738 0 0         if (0 != out_data[i]) break;
739 0           i++;
740             }
741 0 0         if (i == len) {
742 0           SvREFCNT_dec(RETVAL);
743 0           croak("FATAL: increment_octets_le overflow");
744             }
745             }
746             }
747             OUTPUT:
748             RETVAL
749              
750             SV *
751             increment_octets_be(SV * in)
752             CODE:
753             {
754 0           STRLEN len, i = 0;
755             unsigned char *out_data, *in_data;
756              
757 0 0         if (!SvPOK(in)) XSRETURN_UNDEF;
758 0           in_data = (unsigned char *)SvPVbyte(in, len);
759 0 0         if (len == 0) {
760 0           RETVAL = newSVpvn("", 0);
761             }
762             else {
763 0           RETVAL = NEWSV(0, len); /* avoid zero! */
764 0           SvPOK_only(RETVAL);
765 0           SvCUR_set(RETVAL, len);
766 0           out_data = (unsigned char *)SvPVX(RETVAL);
767 0           Copy(in_data, out_data, len, unsigned char);
768 0 0         while (i < len) {
769 0           out_data[len - 1 - i]++;
770 0 0         if (0 != out_data[len - 1 - i]) break;
771 0           i++;
772             }
773 0 0         if (i == len) {
774 0           SvREFCNT_dec(RETVAL);
775 0           croak("FATAL: increment_octets_be overflow");
776             }
777             }
778             }
779             OUTPUT:
780             RETVAL
781              
782             ###############################################################################
783              
784             INCLUDE: inc/CryptX_Digest.xs.inc
785             INCLUDE: inc/CryptX_Digest_SHAKE.xs.inc
786             INCLUDE: inc/CryptX_Cipher.xs.inc
787              
788             INCLUDE: inc/CryptX_Checksum_Adler32.xs.inc
789             INCLUDE: inc/CryptX_Checksum_CRC32.xs.inc
790              
791             INCLUDE: inc/CryptX_AuthEnc_EAX.xs.inc
792             INCLUDE: inc/CryptX_AuthEnc_GCM.xs.inc
793             INCLUDE: inc/CryptX_AuthEnc_OCB.xs.inc
794             INCLUDE: inc/CryptX_AuthEnc_CCM.xs.inc
795             INCLUDE: inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc
796              
797             INCLUDE: inc/CryptX_Stream_ChaCha.xs.inc
798             INCLUDE: inc/CryptX_Stream_Salsa20.xs.inc
799             INCLUDE: inc/CryptX_Stream_RC4.xs.inc
800             INCLUDE: inc/CryptX_Stream_Sober128.xs.inc
801             INCLUDE: inc/CryptX_Stream_Sosemanuk.xs.inc
802             INCLUDE: inc/CryptX_Stream_Rabbit.xs.inc
803              
804             INCLUDE: inc/CryptX_Mac_F9.xs.inc
805             INCLUDE: inc/CryptX_Mac_HMAC.xs.inc
806             INCLUDE: inc/CryptX_Mac_OMAC.xs.inc
807             INCLUDE: inc/CryptX_Mac_Pelican.xs.inc
808             INCLUDE: inc/CryptX_Mac_PMAC.xs.inc
809             INCLUDE: inc/CryptX_Mac_XCBC.xs.inc
810             INCLUDE: inc/CryptX_Mac_Poly1305.xs.inc
811             INCLUDE: inc/CryptX_Mac_BLAKE2s.xs.inc
812             INCLUDE: inc/CryptX_Mac_BLAKE2b.xs.inc
813              
814             INCLUDE: inc/CryptX_Mode_CBC.xs.inc
815             INCLUDE: inc/CryptX_Mode_ECB.xs.inc
816             INCLUDE: inc/CryptX_Mode_CFB.xs.inc
817             INCLUDE: inc/CryptX_Mode_OFB.xs.inc
818             INCLUDE: inc/CryptX_Mode_CTR.xs.inc
819             #INCLUDE: inc/CryptX_Mode_F8.xs.inc
820             #INCLUDE: inc/CryptX_Mode_LRW.xs.inc
821             #INCLUDE: inc/CryptX_Mode_XTS.xs.inc
822              
823             INCLUDE: inc/CryptX_PRNG.xs.inc
824              
825             INCLUDE: inc/CryptX_PK_RSA.xs.inc
826             INCLUDE: inc/CryptX_PK_DSA.xs.inc
827             INCLUDE: inc/CryptX_PK_DH.xs.inc
828             INCLUDE: inc/CryptX_PK_ECC.xs.inc
829             INCLUDE: inc/CryptX_PK_Ed25519.xs.inc
830             INCLUDE: inc/CryptX_PK_X25519.xs.inc
831              
832             INCLUDE: inc/CryptX_KeyDerivation.xs.inc
833              
834             INCLUDE: inc/CryptX_BigInt_LTM.xs.inc