File Coverage

CryptX.xs
Criterion Covered Total %
statement 616 733 84.0
branch 460 778 59.1
condition n/a
subroutine n/a
pod n/a
total 1076 1511 71.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 655           STATIC int cryptx_internal_input_has_no_payload(const char *in, STRLEN len) {
29             STRLEN i;
30 655           int saw_formatting = 0;
31              
32 655 50         if (in == NULL || len == 0) return 0;
    50          
33              
34 684 100         for (i = 0; i < len; i++) {
35 675 100         if (in[i] == '=') {
36 10           saw_formatting = 1;
37 10           continue;
38             }
39 665 100         if (in[i] == ' ' || in[i] == '\t' || in[i] == '\n' || in[i] == '\r') {
    100          
    100          
    50          
40 19           saw_formatting = 1;
41 19           continue;
42             }
43 646           return 0;
44             }
45 9           return saw_formatting;
46             }
47              
48             typedef adler32_state *Crypt__Checksum__Adler32;
49             typedef crc32_state *Crypt__Checksum__CRC32;
50              
51             typedef struct cryptx_authenc_ccm_struct {
52             ccm_state state;
53             int finalized;
54             } *Crypt__AuthEnc__CCM;
55             typedef struct cryptx_authenc_eax_struct {
56             eax_state state;
57             int finalized;
58             } *Crypt__AuthEnc__EAX;
59             typedef struct cryptx_authenc_gcm_struct {
60             gcm_state state;
61             int finalized;
62             } *Crypt__AuthEnc__GCM;
63             typedef struct cryptx_authenc_chacha20poly1305_struct {
64             chacha20poly1305_state state;
65             int finalized;
66             } *Crypt__AuthEnc__ChaCha20Poly1305;
67             typedef struct cryptx_authenc_ocb_struct {
68             ocb3_state state;
69             int finalized;
70             } *Crypt__AuthEnc__OCB;
71              
72             typedef chacha_state *Crypt__Stream__ChaCha;
73             typedef chacha_state *Crypt__Stream__XChaCha;
74             typedef salsa20_state *Crypt__Stream__Salsa20;
75             typedef salsa20_state *Crypt__Stream__XSalsa20;
76             typedef sosemanuk_state *Crypt__Stream__Sosemanuk;
77             typedef rabbit_state *Crypt__Stream__Rabbit;
78             typedef rc4_state *Crypt__Stream__RC4;
79             typedef sober128_state *Crypt__Stream__Sober128;
80              
81             typedef struct cryptx_mac_f9_struct {
82             f9_state state;
83             int finalized;
84             } *Crypt__Mac__F9;
85             typedef struct cryptx_mac_hmac_struct {
86             hmac_state state;
87             int finalized;
88             } *Crypt__Mac__HMAC;
89             typedef struct cryptx_mac_omac_struct {
90             omac_state state;
91             int finalized;
92             } *Crypt__Mac__OMAC;
93             typedef struct cryptx_mac_pelican_struct {
94             pelican_state state;
95             int finalized;
96             } *Crypt__Mac__Pelican;
97             typedef struct cryptx_mac_pmac_struct {
98             pmac_state state;
99             int finalized;
100             } *Crypt__Mac__PMAC;
101             typedef struct cryptx_mac_xcbc_struct {
102             xcbc_state state;
103             int finalized;
104             } *Crypt__Mac__XCBC;
105             typedef struct cryptx_mac_poly1305_struct {
106             poly1305_state state;
107             int finalized;
108             } *Crypt__Mac__Poly1305;
109             typedef struct cryptx_mac_blake2s_struct {
110             blake2smac_state state;
111             int finalized;
112             } *Crypt__Mac__BLAKE2s;
113             typedef struct cryptx_mac_blake2b_struct {
114             blake2bmac_state state;
115             int finalized;
116             } *Crypt__Mac__BLAKE2b;
117              
118             typedef struct cipher_struct { /* used by Crypt::Cipher */
119             symmetric_key skey;
120             struct ltc_cipher_descriptor *desc;
121             } *Crypt__Cipher;
122              
123             typedef struct digest_struct { /* used by Crypt::Digest */
124             hash_state state;
125             struct ltc_hash_descriptor *desc;
126             int finalized;
127             } *Crypt__Digest;
128              
129 90           STATIC int cryptx_internal_noclone_hash(const char *name) {
130 90 50         if (name == NULL) return 0;
131 90           return strcmp(name, "sha1") == 0
132 90 50         || strcmp(name, "sha224") == 0
133 180 50         || strcmp(name, "sha256") == 0;
    50          
134             }
135              
136             typedef struct digest_shake_struct { /* used by Crypt::Digest::SHAKE, TurboSHAKE, KangarooTwelve */
137             hash_state state;
138             int num;
139             int squeezing;
140             } *Crypt__Digest__SHAKE;
141             typedef struct digest_shake_struct *Crypt__Digest__TurboSHAKE;
142             typedef struct digest_shake_struct *Crypt__Digest__KangarooTwelve;
143              
144             /* --- Crypt::ASN1 helper -------------------------------------------------- */
145             static const char * const s_asn1_class_names[] = {
146             "UNIVERSAL", "APPLICATION", "CONTEXT_SPECIFIC", "PRIVATE"
147             };
148              
149             typedef struct { int int_fmt; int bin_fmt; int dt_fmt; HV *oidmap; } asn1_opts_t;
150             /* int_fmt: 0=decimal(default) 1=hex 2=bytes */
151             /* bin_fmt: 0=raw(default) 1=hex 2=base64 */
152             /* dt_fmt: 0=rfc3339(default) 1=epoch */
153              
154 56           static SV * s_asn1_oid_name_sv(pTHX_ HV *oidmap, SV *oid_sv)
155             {
156 56           STRLEN len = 0;
157 56           const char *oid = NULL;
158 56           SV **name_sv = NULL;
159              
160 56 100         if (!oidmap || !oid_sv || !SvOK(oid_sv)) return NULL;
    50          
    50          
161              
162 1           oid = SvPV(oid_sv, len);
163 1           name_sv = hv_fetch(oidmap, oid, (I32)len, 0);
164 1 50         if (!name_sv || !SvOK(*name_sv)) return NULL;
    50          
165              
166 1           return newSVsv(*name_sv);
167             }
168              
169             /* Encode binary data according to bin_fmt */
170 56           static SV * s_asn1_bin_sv(pTHX_ const void *data, unsigned long size, int bin_fmt)
171             {
172 56 50         if (!data || size == 0) return newSVpvn("", 0);
    50          
173 56 100         if (bin_fmt == 1) { /* hex */
174             SV *s;
175 6           unsigned long outlen = size * 2 + 1;
176 6           char *buf; Newz(0, buf, outlen, char);
177 6           { unsigned long ol = outlen; base16_encode((const unsigned char*)data, size, buf, &ol, 0); }
178 6           s = newSVpvn(buf, size * 2); Safefree(buf);
179 6           return s;
180 50 100         } else if (bin_fmt == 2) { /* base64 */
181             SV *s;
182 11           unsigned long outlen = ((size + 2) / 3) * 4 + 4;
183 11           char *buf; Newz(0, buf, outlen, char);
184 11           base64_encode((const unsigned char*)data, size, buf, &outlen);
185 11           s = newSVpvn(buf, outlen); Safefree(buf);
186 11           return s;
187             }
188 39           return newSVpvn((const char *)data, size); /* raw */
189             }
190              
191             /* Convert Gregorian date+time to Unix epoch (portable, no timegm needed) */
192 7           static IV s_asn1_to_epoch(unsigned YYYY, unsigned MM, unsigned DD,
193             unsigned hh, unsigned mm, unsigned ss,
194             unsigned off_dir, unsigned off_hh, unsigned off_mm)
195             {
196 7           long y = YYYY, m = MM, d = DD;
197             long days;
198             IV epoch, offset;
199 7 100         if (m <= 2) { y--; m += 12; }
200 7           days = 365*y + y/4 - y/100 + y/400 + (153*m - 457)/5 + d - 719469;
201 7           epoch = (IV)days * 86400 + (IV)hh * 3600 + (IV)mm * 60 + (IV)ss;
202 7           offset = (IV)(off_hh * 3600 + off_mm * 60);
203             /* off_dir: 0 = '+' (local ahead of UTC, subtract to get UTC)
204             * 1 = '-' (local behind UTC, add to get UTC) */
205 7 50         epoch += (off_dir ? offset : -offset);
206 7           return epoch;
207             }
208              
209 190           static SV * s_ltc_asn1_to_perl(pTHX_ ltc_asn1_list *node, asn1_opts_t opts)
210             {
211 190           AV *av = newAV();
212 556 100         while (node != NULL && node->type != LTC_ASN1_EOL) {
    100          
213 367           HV *hv = newHV();
214 367           SV *value_sv = NULL;
215 367           const char *type_str = "UNKNOWN";
216 367           const char *format_str = "unknown";
217 367           switch (node->type) {
218 3           case LTC_ASN1_BOOLEAN:
219 3           type_str = "BOOLEAN"; format_str = "bool";
220 3 50         if (node->data) value_sv = newSViv(*(int *)node->data ? 1 : 0);
221 3           break;
222 44           case LTC_ASN1_INTEGER: {
223 44           mp_int *mpi = (mp_int *)node->data;
224 44           type_str = "INTEGER";
225 44 50         if (mpi) {
226 44 100         if (opts.int_fmt == 2) { /* bytes */
227 5 100         if (mp_isneg(mpi)) {
228 1           SvREFCNT_dec(hv);
229 1           croak("FATAL: asn1_decode_der: negative INTEGER cannot be represented with int=>'bytes'");
230             }
231 4           format_str = "bytes";
232 4 100         if (mp_iszero(mpi)) {
233 1           value_sv = newSVpvn("\0", 1);
234             } else {
235 3           unsigned long usize = mp_ubin_size(mpi);
236 3           unsigned char *ubuf; Newz(0, ubuf, usize, unsigned char);
237 3           { mp_err me = mp_to_ubin(mpi, ubuf, usize, NULL); PERL_UNUSED_VAR(me); }
238 3           value_sv = newSVpvn((char *)ubuf, usize); Safefree(ubuf);
239             }
240             } else {
241 39 100         int radix = (opts.int_fmt == 1) ? 16 : 10;
242             int len;
243             char *buf;
244 39 100         format_str = (opts.int_fmt == 1) ? "hex" : "decimal";
245 39 100         len = mp_count_bits(mpi) / (opts.int_fmt == 1 ? 4 : 3) + 4;
246 39           Newz(0, buf, len, char);
247 39           { mp_err me = mp_to_radix(mpi, buf, len, NULL, radix); PERL_UNUSED_VAR(me); }
248 39 100         if (opts.int_fmt == 1) { /* lowercase hex */
249 41 100         char *p; for (p = buf; *p; p++) if (*p >= 'A' && *p <= 'F') *p += 32;
    50          
    100          
250             }
251 39           value_sv = newSVpv(buf, 0); Safefree(buf);
252             }
253             }
254 43           break;
255             }
256 0           case LTC_ASN1_SHORT_INTEGER: {
257 0           type_str = "INTEGER";
258 0 0         if (node->data) {
259 0           unsigned long v = *(unsigned long *)node->data;
260 0 0         if (opts.int_fmt == 1) { /* hex */
261             char buf[32];
262 0           format_str = "hex";
263 0           snprintf(buf, sizeof(buf), "%lx", v);
264 0           value_sv = newSVpv(buf, 0);
265 0 0         } else if (opts.int_fmt == 2) { /* bytes */
266             unsigned char b[8], be[8];
267 0           int n = 0, k;
268 0           unsigned long tmp = v;
269 0           format_str = "bytes";
270 0 0         while (tmp) { b[n++] = (unsigned char)(tmp & 0xff); tmp >>= 8; }
271 0 0         if (!n) { b[0] = 0; n = 1; }
272 0 0         for (k = 0; k < n; k++) be[k] = b[n - 1 - k];
273 0           value_sv = newSVpvn((char *)be, n);
274             } else {
275 0           format_str = "decimal";
276 0           value_sv = newSVuv((UV)v);
277             }
278             }
279 0           break;
280             }
281 18           case LTC_ASN1_BIT_STRING: {
282 18           unsigned char *bits = (unsigned char *)node->data;
283 18           unsigned long nbits = node->size, nbytes = (nbits + 7) / 8;
284 18           type_str = "BIT_STRING";
285 18 100         format_str = (opts.bin_fmt == 1) ? "hex" : (opts.bin_fmt == 2) ? "base64" : "bytes";
    100          
286 18 50         if (bits && nbytes > 0) {
    50          
287             unsigned long i;
288             unsigned char *packed;
289 18           Newz(0, packed, nbytes, unsigned char);
290 28074 100         for (i = 0; i < nbits; i++)
291 28056 100         if (bits[i]) packed[i/8] |= (unsigned char)(0x80u >> (i%8));
292 18           value_sv = s_asn1_bin_sv(aTHX_ packed, nbytes, opts.bin_fmt);
293 18           Safefree(packed);
294             }
295 18           hv_stores(hv, "bits", newSVuv((UV)nbits));
296 18           break;
297             }
298 0           case LTC_ASN1_RAW_BIT_STRING: {
299 0           unsigned long nbits_raw = node->size;
300 0           unsigned long nbytes_raw = (nbits_raw + 7) / 8;
301 0           type_str = "BIT_STRING";
302 0 0         format_str = (opts.bin_fmt == 1) ? "hex" : (opts.bin_fmt == 2) ? "base64" : "bytes";
    0          
303 0           value_sv = s_asn1_bin_sv(aTHX_ node->data, nbytes_raw, opts.bin_fmt);
304 0           hv_stores(hv, "bits", newSVuv((UV)nbits_raw));
305 0           break;
306             }
307 37           case LTC_ASN1_OCTET_STRING:
308 37           type_str = "OCTET_STRING";
309 37 100         format_str = (opts.bin_fmt == 1) ? "hex" : (opts.bin_fmt == 2) ? "base64" : "bytes";
    100          
310 37           value_sv = s_asn1_bin_sv(aTHX_ node->data, node->size, opts.bin_fmt);
311 37           break;
312 20           case LTC_ASN1_NULL:
313 20           type_str = "NULL"; format_str = "null";
314 20           break;
315 56           case LTC_ASN1_OBJECT_IDENTIFIER: {
316 56           unsigned long *oid = (unsigned long *)node->data;
317 56           type_str = "OID"; format_str = "oid";
318 56 50         if (oid && node->size > 0) {
    50          
319 56           unsigned long i; SV *s = newSVpvn("", 0);
320 337 100         for (i = 0; i < node->size; i++) {
321 281 100         if (i > 0) sv_catpv(s, "."); sv_catpvf(s, "%lu", oid[i]);
322             }
323 56           value_sv = s;
324             {
325 56           SV *name_sv = s_asn1_oid_name_sv(aTHX_ opts.oidmap, value_sv);
326 56 100         if (name_sv) hv_stores(hv, "name", name_sv);
327             }
328             }
329 56           break;
330             }
331 2           case LTC_ASN1_IA5_STRING:
332 2           type_str = "IA5_STRING"; format_str = "string";
333 2 50         if (node->data && node->size > 0) value_sv = newSVpvn((char *)node->data, node->size);
    50          
334 2           break;
335 2           case LTC_ASN1_PRINTABLE_STRING:
336 2           type_str = "PRINTABLE_STRING"; format_str = "string";
337 2 50         if (node->data && node->size > 0) value_sv = newSVpvn((char *)node->data, node->size);
    50          
338 2           break;
339 0           case LTC_ASN1_TELETEX_STRING:
340 0           type_str = "TELETEX_STRING"; format_str = "string";
341 0 0         if (node->data && node->size > 0) value_sv = newSVpvn((char *)node->data, node->size);
    0          
342 0           break;
343 14           case LTC_ASN1_UTF8_STRING: {
344 14           wchar_t *wstr = (wchar_t *)node->data;
345 14           type_str = "UTF8_STRING"; format_str = "utf8";
346 14 50         if (wstr && node->size > 0) {
    50          
347             unsigned long i;
348 14           SV *s = newSVpvn("", 0); SvUTF8_on(s);
349 78 100         for (i = 0; i < node->size; i++) {
350             U8 ubuf[UTF8_MAXBYTES + 1];
351 64           U8 *end = uvchr_to_utf8(ubuf, (UV)wstr[i]);
352 64           sv_catpvn(s, (char *)ubuf, end - ubuf);
353             }
354 14           value_sv = s;
355             }
356 14           break;
357             }
358 16           case LTC_ASN1_UTCTIME: {
359 16           ltc_utctime *t = (ltc_utctime *)node->data;
360 16           type_str = "UTCTIME";
361 16 50         if (t) {
362 16 50         unsigned YYYY = (t->YY >= 50) ? 1900 + t->YY : 2000 + t->YY;
363 16 100         if (opts.dt_fmt == 1) { /* epoch */
364 6           format_str = "epoch";
365 6           value_sv = newSViv(s_asn1_to_epoch(YYYY, t->MM, t->DD, t->hh, t->mm, t->ss,
366             t->off_dir, t->off_hh, t->off_mm));
367             } else { /* rfc3339 */
368             char buf[32];
369 10           format_str = "rfc3339";
370 10 50         if (t->off_dir == 0 && t->off_hh == 0 && t->off_mm == 0)
    50          
    50          
371 10           snprintf(buf, sizeof(buf), "%04u-%02u-%02uT%02u:%02u:%02uZ",
372             YYYY, t->MM, t->DD, t->hh, t->mm, t->ss);
373             else
374 0           snprintf(buf, sizeof(buf), "%04u-%02u-%02uT%02u:%02u:%02u%c%02u:%02u",
375             YYYY, t->MM, t->DD, t->hh, t->mm, t->ss,
376 0 0         t->off_dir ? '-' : '+', t->off_hh, t->off_mm);
377 10           value_sv = newSVpv(buf, 0);
378             }
379             }
380 16           break;
381             }
382 5           case LTC_ASN1_GENERALIZEDTIME: {
383 5           ltc_generalizedtime *t = (ltc_generalizedtime *)node->data;
384 5           type_str = "GENERALIZEDTIME";
385 5 50         if (t) {
386 5 100         if (opts.dt_fmt == 1) { /* epoch */
387 1           format_str = "epoch";
388 1           value_sv = newSViv(s_asn1_to_epoch(t->YYYY, t->MM, t->DD, t->hh, t->mm, t->ss,
389             t->off_dir, t->off_hh, t->off_mm));
390             } else { /* rfc3339 */
391             char buf[48];
392             int pos;
393 4           format_str = "rfc3339";
394 4           pos = snprintf(buf, sizeof(buf), "%04u-%02u-%02uT%02u:%02u:%02u",
395             t->YYYY, t->MM, t->DD, t->hh, t->mm, t->ss);
396 4 100         if (t->fs > 0)
397 3           pos += snprintf(buf + pos, sizeof(buf) - pos, ".%u", t->fs);
398 4 50         if (t->off_dir == 0 && t->off_hh == 0 && t->off_mm == 0)
    100          
    50          
399 3           snprintf(buf + pos, sizeof(buf) - pos, "Z");
400             else
401 1           snprintf(buf + pos, sizeof(buf) - pos, "%c%02u:%02u",
402 1 50         t->off_dir ? '-' : '+', t->off_hh, t->off_mm);
403 4           value_sv = newSVpv(buf, 0);
404             }
405             }
406 5           break;
407             }
408 115           case LTC_ASN1_SEQUENCE:
409 115           type_str = "SEQUENCE"; format_str = "array";
410 115 50         value_sv = node->child ? newRV_noinc(s_ltc_asn1_to_perl(aTHX_ node->child, opts)) : newRV_noinc((SV *)newAV());
411 115           break;
412 14           case LTC_ASN1_SET:
413             case LTC_ASN1_SETOF:
414 14           type_str = "SET"; format_str = "array";
415 14 50         value_sv = node->child ? newRV_noinc(s_ltc_asn1_to_perl(aTHX_ node->child, opts)) : newRV_noinc((SV *)newAV());
416 14           break;
417 21           case LTC_ASN1_CUSTOM_TYPE: {
418 21           unsigned int cls = (unsigned int)node->klass;
419 21           type_str = "CUSTOM";
420 21 50         hv_stores(hv, "class", newSVpv((cls < 4) ? s_asn1_class_names[cls] : "UNKNOWN", 0));
421 21           hv_stores(hv, "constructed", newSViv(node->pc == LTC_ASN1_PC_CONSTRUCTED ? 1 : 0));
422 21           hv_stores(hv, "tag", newSVuv((UV)node->tag));
423 21 100         if (node->pc == LTC_ASN1_PC_CONSTRUCTED && node->child) {
    50          
424 20           format_str = "array";
425 20           value_sv = newRV_noinc(s_ltc_asn1_to_perl(aTHX_ node->child, opts));
426 1 50         } else if (node->data && node->size > 0) {
    50          
427 1 50         format_str = (opts.bin_fmt == 1) ? "hex" : (opts.bin_fmt == 2) ? "base64" : "bytes";
    50          
428 1           value_sv = s_asn1_bin_sv(aTHX_ node->data, node->size, opts.bin_fmt);
429             }
430 21           break;
431             }
432 0           default:
433             /* Unknown ltc_asn1_type — skip rather than emit unroundtrippable node */
434 0           SvREFCNT_dec(hv);
435 0           node = node->next;
436 0           continue;
437             }
438 366           hv_stores(hv, "type", newSVpv(type_str, 0));
439 366           hv_stores(hv, "format", newSVpv(format_str, 0));
440 366 100         hv_stores(hv, "value", value_sv ? value_sv : newSV(0));
441 366           av_push(av, newRV_noinc((SV *)hv));
442 366           node = node->next;
443             }
444 189           return (SV *)av;
445             }
446             /* --- end Crypt::ASN1 decoder helper -------------------------------------- */
447              
448             /* --- Crypt::ASN1 encoder helpers ----------------------------------------- */
449              
450             /* Write DER length to buf, return bytes written (buf must be >= 5 bytes) */
451 141           static unsigned long s_asn1_put_der_length(pTHX_ unsigned char *buf, unsigned long len)
452             {
453 141 50         if (len > 0xffffffffUL) {
454 0           croak("FATAL: asn1_encode: DER length exceeds 0xffffffff bytes");
455             }
456 141 100         if (len < 128) {
457 123           buf[0] = (unsigned char)len;
458 123           return 1;
459 18 50         } else if (len <= 0xffUL) {
460 0           buf[0] = 0x81; buf[1] = (unsigned char)len;
461 0           return 2;
462 18 50         } else if (len <= 0xffffUL) {
463 18           buf[0] = 0x82;
464 18           buf[1] = (unsigned char)(len >> 8);
465 18           buf[2] = (unsigned char)(len & 0xff);
466 18           return 3;
467 0 0         } else if (len <= 0xffffffUL) {
468 0           buf[0] = 0x83;
469 0           buf[1] = (unsigned char)(len >> 16);
470 0           buf[2] = (unsigned char)((len >> 8) & 0xff);
471 0           buf[3] = (unsigned char)(len & 0xff);
472 0           return 4;
473             }
474 0           buf[0] = 0x84;
475 0           buf[1] = (unsigned char)(len >> 24);
476 0           buf[2] = (unsigned char)((len >> 16) & 0xff);
477 0           buf[3] = (unsigned char)((len >> 8) & 0xff);
478 0           buf[4] = (unsigned char)(len & 0xff);
479 0           return 5;
480             }
481              
482             /* Append single-byte tag + DER length + content to SV */
483 130           static void s_asn1_append_tlv(pTHX_ SV *out, unsigned char tag,
484             const void *content, unsigned long clen)
485             {
486             unsigned char lbuf[5];
487 130           unsigned long llen = s_asn1_put_der_length(aTHX_ lbuf, clen);
488 130           sv_catpvn(out, (char *)&tag, 1);
489 130           sv_catpvn(out, (char *)lbuf, llen);
490 130 100         if (clen > 0 && content) sv_catpvn(out, (const char *)content, clen);
    50          
491 130           }
492              
493             /* Append multi-byte tag (for CUSTOM) + DER length + content to SV */
494 11           static void s_asn1_append_custom_tlv(pTHX_ SV *out,
495             unsigned int klass, unsigned int pc,
496             unsigned long tag,
497             const void *content, unsigned long clen)
498             {
499             unsigned char tbuf[12], lbuf[5];
500             unsigned long tlen, llen;
501 11           unsigned char first = (unsigned char)(((klass & 0x3) << 6) | ((pc & 0x1) << 5));
502              
503 11 50         if (tag < 31) {
504 11           tbuf[0] = first | (unsigned char)tag;
505 11           tlen = 1;
506             } else {
507             unsigned char tmp[10];
508 0           int n = 0, i;
509 0           unsigned long t = tag;
510 0           tbuf[0] = first | 0x1f;
511             /* base-128 big-endian */
512 0 0         do { tmp[n++] = (unsigned char)(t & 0x7f); t >>= 7; } while (t > 0);
513 0           tlen = 1;
514 0 0         for (i = n - 1; i >= 0; i--) tbuf[tlen++] = tmp[i] | (i > 0 ? 0x80 : 0x00);
    0          
515             }
516 11           llen = s_asn1_put_der_length(aTHX_ lbuf, clen);
517 11           sv_catpvn(out, (char *)tbuf, tlen);
518 11           sv_catpvn(out, (char *)lbuf, llen);
519 11 100         if (clen > 0 && content) sv_catpvn(out, (const char *)content, clen);
    50          
520 11           }
521              
522             /* Forward declarations */
523             static void s_asn1_encode_node(pTHX_ SV *out, HV *node);
524              
525 115           static void s_asn1_encode_nodes(pTHX_ SV *out, AV *nodes)
526             {
527 115 50         I32 i, len = av_top_index(nodes);
528 309 100         for (i = 0; i <= len; i++) {
529 194           SV **elem = av_fetch(nodes, i, 0);
530 194 50         if (!elem || !SvROK(*elem) || SvTYPE(SvRV(*elem)) != SVt_PVHV) continue;
    50          
    50          
531 194           s_asn1_encode_node(aTHX_ out, (HV *)SvRV(*elem));
532             }
533 115           }
534              
535 194           static void s_asn1_encode_node(pTHX_ SV *out, HV *node)
536             {
537 194           SV **sv_type = hv_fetchs(node, "type", 0);
538 194           SV **sv_value = hv_fetchs(node, "value", 0);
539             const char *type;
540              
541 194 50         if (!sv_type || !SvOK(*sv_type)) croak("FATAL: asn1_encode: node missing 'type'");
    50          
542 194           type = SvPV_nolen(*sv_type);
543              
544 194 100         if (strEQ(type, "BOOLEAN")) {
545 4 50         int val = (sv_value && SvOK(*sv_value)) ? SvIV(*sv_value) : 0;
    50          
546 4 100         unsigned char c = val ? 0xFF : 0x00;
547 4           s_asn1_append_tlv(aTHX_ out, 0x01, &c, 1);
548             }
549 190 100         else if (strEQ(type, "NULL")) {
550 11           s_asn1_append_tlv(aTHX_ out, 0x05, NULL, 0);
551             }
552 179 100         else if (strEQ(type, "INTEGER")) {
553             STRLEN slen; const char *str;
554             mp_int mpi; int rv;
555             unsigned long outlen; unsigned char *buf;
556              
557 25 50         if (!sv_value || !SvOK(*sv_value)) croak("FATAL: asn1_encode: INTEGER missing value");
    50          
558 25           str = SvPV(*sv_value, slen);
559              
560 25 50         if (mp_init(&mpi) != MP_OKAY) croak("FATAL: asn1_encode: mp_init failed");
561 25 50         if (mp_read_radix(&mpi, str, 10) != MP_OKAY) { mp_clear(&mpi); croak("FATAL: asn1_encode: invalid INTEGER value '%s'", str); }
562              
563 25           rv = der_length_integer(&mpi, &outlen);
564 25 50         if (rv != CRYPT_OK) { mp_clear(&mpi); croak("FATAL: asn1_encode: der_length_integer failed"); }
565              
566 25           Newx(buf, outlen, unsigned char);
567 25           rv = der_encode_integer(&mpi, buf, &outlen);
568 25           mp_clear(&mpi);
569 25 50         if (rv != CRYPT_OK) { Safefree(buf); croak("FATAL: asn1_encode: der_encode_integer failed"); }
570              
571 25           sv_catpvn(out, (char *)buf, outlen);
572 25           Safefree(buf);
573             }
574 154 100         else if (strEQ(type, "OID")) {
575             STRLEN slen; const char *str; const char *p;
576 28           unsigned long words[64], nwords = 0, outlen;
577             unsigned char *buf; int rv;
578              
579 28 50         if (!sv_value || !SvOK(*sv_value)) croak("FATAL: asn1_encode: OID missing value");
    50          
580 28           str = SvPV(*sv_value, slen);
581              
582 28           p = str;
583 166 100         while (*p && nwords < 64) {
    50          
584 138           words[nwords++] = strtoul(p, (char **)&p, 10);
585 138 100         if (*p == '.') p++;
586             }
587 28 50         if (nwords < 2) croak("FATAL: asn1_encode: OID must have at least 2 arcs");
588              
589 28           rv = der_length_object_identifier(words, nwords, &outlen);
590 28 50         if (rv != CRYPT_OK) croak("FATAL: asn1_encode: der_length_object_identifier failed");
591              
592 28           Newx(buf, outlen, unsigned char);
593 28           rv = der_encode_object_identifier(words, nwords, buf, &outlen);
594 28 50         if (rv != CRYPT_OK) { Safefree(buf); croak("FATAL: asn1_encode: der_encode_object_identifier failed"); }
595              
596 28           sv_catpvn(out, (char *)buf, outlen);
597 28           Safefree(buf);
598             }
599 126 100         else if (strEQ(type, "OCTET_STRING")) {
600 17           STRLEN vlen = 0;
601 17 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVbyte(*sv_value, vlen) : "";
    50          
602 17           s_asn1_append_tlv(aTHX_ out, 0x04, data, (unsigned long)vlen);
603             }
604 109 100         else if (strEQ(type, "BIT_STRING")) {
605 11           STRLEN vlen = 0;
606 11 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVbyte(*sv_value, vlen) : "";
    50          
607 11           SV **sv_bits = hv_fetchs(node, "bits", 0);
608 11 50         unsigned long nbits = (sv_bits && SvOK(*sv_bits)) ? (unsigned long)SvUV(*sv_bits) : (unsigned long)(vlen * 8);
    50          
609 11           unsigned long nbytes = (nbits + 7) / 8;
610 11 50         unsigned char unused = (nbytes > 0) ? (unsigned char)(8 * nbytes - nbits) : 0;
611 11           unsigned long content_len = 1 + nbytes;
612             unsigned char *content;
613              
614 11           Newxz(content, content_len, unsigned char);
615 11           content[0] = unused;
616 11 50         if (nbytes > 0 && vlen > 0) {
    50          
617 11           Copy(data, content + 1, nbytes < (unsigned long)vlen ? nbytes : (unsigned long)vlen, unsigned char);
618 11 100         if (unused > 0) content[nbytes] &= (unsigned char)(0xFF << unused);
619             }
620 11           s_asn1_append_tlv(aTHX_ out, 0x03, content, content_len);
621 11           Safefree(content);
622             }
623 98 100         else if (strEQ(type, "UTF8_STRING")) {
624 8           STRLEN vlen = 0;
625 8 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVutf8(*sv_value, vlen) : "";
    50          
626 8           s_asn1_append_tlv(aTHX_ out, 0x0C, data, (unsigned long)vlen);
627             }
628 90 100         else if (strEQ(type, "IA5_STRING")) {
629 2           STRLEN vlen = 0;
630 2 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVbyte(*sv_value, vlen) : "";
    50          
631 2           s_asn1_append_tlv(aTHX_ out, 0x16, data, (unsigned long)vlen);
632             }
633 88 100         else if (strEQ(type, "PRINTABLE_STRING")) {
634 2           STRLEN vlen = 0;
635 2 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVbyte(*sv_value, vlen) : "";
    50          
636 2           s_asn1_append_tlv(aTHX_ out, 0x13, data, (unsigned long)vlen);
637             }
638 86 100         else if (strEQ(type, "TELETEX_STRING")) {
639 1           STRLEN vlen = 0;
640 1 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVbyte(*sv_value, vlen) : "";
    50          
641 1           s_asn1_append_tlv(aTHX_ out, 0x14, data, (unsigned long)vlen);
642             }
643 85 100         else if (strEQ(type, "UTCTIME")) {
644 10           STRLEN vlen = 0;
645 10 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPV(*sv_value, vlen) : "";
    50          
646 10           s_asn1_append_tlv(aTHX_ out, 0x17, data, (unsigned long)vlen);
647             }
648 75 100         else if (strEQ(type, "GENERALIZEDTIME")) {
649 1           STRLEN vlen = 0;
650 1 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPV(*sv_value, vlen) : "";
    50          
651 1           s_asn1_append_tlv(aTHX_ out, 0x18, data, (unsigned long)vlen);
652             }
653 137 100         else if (strEQ(type, "SEQUENCE") || strEQ(type, "SET")) {
    100          
654 63 100         unsigned char tag = strEQ(type, "SEQUENCE") ? 0x30 : 0x31;
655 126 50         if (sv_value && SvROK(*sv_value) && SvTYPE(SvRV(*sv_value)) == SVt_PVAV) {
    50          
    50          
656 63           SV *content = newSVpvn("", 0);
657 63           s_asn1_encode_nodes(aTHX_ content, (AV *)SvRV(*sv_value));
658 63           { STRLEN clen; const char *cdata = SvPV(content, clen);
659 63           s_asn1_append_tlv(aTHX_ out, tag, cdata, (unsigned long)clen); }
660 63           SvREFCNT_dec(content);
661             } else {
662 0           s_asn1_append_tlv(aTHX_ out, tag, NULL, 0);
663             }
664             }
665 11 50         else if (strEQ(type, "CUSTOM")) {
666 11           SV **sv_class = hv_fetchs(node, "class", 0);
667 11           SV **sv_constr = hv_fetchs(node, "constructed", 0);
668 11           SV **sv_tag = hv_fetchs(node, "tag", 0);
669 11 50         unsigned int klass = (sv_class && SvOK(*sv_class)) ? (unsigned int)SvIV(*sv_class) : 2;
    50          
670 11 50         unsigned int pc = (sv_constr && SvOK(*sv_constr) && SvIV(*sv_constr)) ? 1 : 0;
    50          
    100          
671 11 50         unsigned long tag = (sv_tag && SvOK(*sv_tag)) ? (unsigned long)SvUV(*sv_tag) : 0;
    50          
672              
673 21 100         if (pc && sv_value && SvROK(*sv_value) && SvTYPE(SvRV(*sv_value)) == SVt_PVAV) {
    50          
    50          
    50          
674 10           SV *content = newSVpvn("", 0);
675 10           s_asn1_encode_nodes(aTHX_ content, (AV *)SvRV(*sv_value));
676 10           { STRLEN clen; const char *cdata = SvPV(content, clen);
677 10           s_asn1_append_custom_tlv(aTHX_ out, klass, pc, tag, cdata, (unsigned long)clen); }
678 10           SvREFCNT_dec(content);
679             } else {
680 1           STRLEN vlen = 0;
681 1 50         const char *data = (sv_value && SvOK(*sv_value)) ? SvPVbyte(*sv_value, vlen) : "";
    50          
682 1           s_asn1_append_custom_tlv(aTHX_ out, klass, pc, tag, data, (unsigned long)vlen);
683             }
684             }
685             else {
686 0           croak("FATAL: asn1_encode: unsupported type '%s'", type);
687             }
688 194           }
689             /* --- end Crypt::ASN1 encoder helpers ------------------------------------- */
690              
691             typedef struct cbc_struct { /* used by Crypt::Mode::CBC */
692             int cipher_id, cipher_rounds;
693             symmetric_CBC state;
694             unsigned char pad[MAXBLOCKSIZE];
695             int padlen;
696             int padding_mode;
697             int direction;
698             } *Crypt__Mode__CBC;
699              
700             typedef struct ecb_struct { /* used by Crypt::Mode::ECB */
701             int cipher_id, cipher_rounds;
702             symmetric_ECB state;
703             unsigned char pad[MAXBLOCKSIZE];
704             int padlen;
705             int padding_mode;
706             int direction;
707             } *Crypt__Mode__ECB;
708              
709             typedef struct cfb_struct { /* used by Crypt::Mode::CFB */
710             int cipher_id, cipher_rounds;
711             symmetric_CFB state;
712             int direction;
713             } *Crypt__Mode__CFB;
714              
715             typedef struct ctr_struct { /* used by Crypt::Mode::CTR */
716             int cipher_id, cipher_rounds;
717             int ctr_mode_param;
718             symmetric_CTR state;
719             int direction;
720             } *Crypt__Mode__CTR;
721              
722             typedef struct f8_struct { /* used by Crypt::Mode::F8 */
723             int cipher_id, cipher_rounds;
724             symmetric_F8 state;
725             int direction;
726             } *Crypt__Mode__F8;
727              
728             typedef struct lrw_struct { /* used by Crypt::Mode::LRW */
729             int cipher_id, cipher_rounds;
730             symmetric_LRW state;
731             int direction;
732             } *Crypt__Mode__LRW;
733              
734             typedef struct ofb_struct { /* used by Crypt::Mode::OFB */
735             int cipher_id, cipher_rounds;
736             symmetric_OFB state;
737             int direction;
738             } *Crypt__Mode__OFB;
739              
740             typedef struct xts_struct { /* used by Crypt::Mode::XTS */
741             int cipher_id, cipher_rounds;
742             symmetric_xts state;
743             int direction;
744             } *Crypt__Mode__XTS;
745              
746             typedef struct prng_struct { /* used by Crypt::PRNG */
747             prng_state state;
748             struct ltc_prng_descriptor *desc;
749             IV last_pid;
750             } *Crypt__PRNG;
751              
752             typedef struct rsa_struct { /* used by Crypt::PK::RSA */
753             prng_state pstate;
754             int pindex;
755             IV last_pid;
756             rsa_key key;
757             } *Crypt__PK__RSA;
758              
759             typedef struct dsa_struct { /* used by Crypt::PK::DSA */
760             prng_state pstate;
761             int pindex;
762             IV last_pid;
763             dsa_key key;
764             } *Crypt__PK__DSA;
765              
766             typedef struct dh_struct { /* used by Crypt::PK::DH */
767             prng_state pstate;
768             int pindex;
769             IV last_pid;
770             dh_key key;
771             } *Crypt__PK__DH;
772              
773             typedef struct ecc_struct { /* used by Crypt::PK::ECC */
774             prng_state pstate;
775             int pindex;
776             IV last_pid;
777             ecc_key key;
778             } *Crypt__PK__ECC;
779              
780             typedef struct ed25519_struct { /* used by Crypt::PK::Ed25519 */
781             prng_state pstate;
782             int pindex;
783             IV last_pid;
784             curve25519_key key;
785             int initialized;
786             } *Crypt__PK__Ed25519;
787              
788             typedef struct x25519_struct { /* used by Crypt::PK::X25519 */
789             prng_state pstate;
790             int pindex;
791             IV last_pid;
792             curve25519_key key;
793             int initialized;
794             } *Crypt__PK__X25519;
795              
796             typedef struct ed448_struct { /* used by Crypt::PK::Ed448 */
797             prng_state pstate;
798             int pindex;
799             IV last_pid;
800             curve448_key key;
801             int initialized;
802             } *Crypt__PK__Ed448;
803              
804             typedef struct x448_struct { /* used by Crypt::PK::X448 */
805             prng_state pstate;
806             int pindex;
807             IV last_pid;
808             curve448_key key;
809             int initialized;
810             } *Crypt__PK__X448;
811              
812 64           STATIC int cryptx_internal_password_cb_getpw(void **p, unsigned long *l, void *u) {
813             dTHX; /* fetch context */
814 64           SV *passwd = u;
815 64           void *pwd = NULL;
816 64           STRLEN pwd_len = 0;
817              
818 64 50         if (p == NULL) {
819 0           *l = 0;
820 0           return 1;
821             }
822 64 50         if (passwd == NULL || !SvOK(passwd)) {
    50          
823 0           *p = NULL;
824 0           *l = 0;
825 0           return 1;
826             }
827 64           pwd = SvPVbyte(passwd, pwd_len);
828 64 50         if (pwd == NULL || pwd_len == 0) {
    50          
829 0           *p = NULL;
830 0           *l = 0;
831 0           return 1;
832             }
833 64           Newz(0, *p, pwd_len, unsigned char);
834 64 50         if (*p == NULL) {
835 0           *l = 0;
836 0           return 1;
837             }
838 64           Copy(pwd, *p, pwd_len, unsigned char);
839 64           *l = (unsigned long)pwd_len;
840              
841 64           return 0;
842             }
843              
844 401           STATIC void cryptx_internal_pk_prng_reseed(prng_state *state, int pindex, IV *last_pid) {
845             dTHX; /* fetch context */
846 401           IV curpid = (IV)PerlProc_getpid();
847             unsigned char entropy_buf[40];
848             int rv;
849              
850 401 50         if (*last_pid == curpid) return;
851              
852 0 0         if (rng_get_bytes(entropy_buf, sizeof(entropy_buf), NULL) != sizeof(entropy_buf)) {
853 0           croak("FATAL: rng_get_bytes failed");
854             }
855 0           rv = prng_descriptor[pindex].add_entropy(entropy_buf, sizeof(entropy_buf), state);
856 0 0         if (rv != CRYPT_OK) croak("FATAL: PRNG_add_entropy failed: %s", error_to_string(rv));
857 0           rv = prng_descriptor[pindex].ready(state);
858 0 0         if (rv != CRYPT_OK) croak("FATAL: PRNG_ready failed: %s", error_to_string(rv));
859 0           zeromem(entropy_buf, sizeof(entropy_buf));
860 0           *last_pid = curpid;
861             }
862              
863 53           STATIC void cryptx_internal_prng_done(struct prng_struct *prng) {
864 53 50         if (prng != NULL && prng->desc != NULL && prng->desc->done != NULL) {
    50          
    50          
865 53           (void)prng->desc->done(&prng->state);
866             }
867 53           }
868              
869 36124           STATIC void cryptx_internal_prng_reseed(struct prng_struct *prng) {
870             dTHX; /* fetch context */
871 36124           IV curpid = (IV)PerlProc_getpid();
872             unsigned char entropy_buf[40];
873             int rv;
874              
875 36124 50         if (prng == NULL || prng->desc == NULL || prng->last_pid == curpid) return;
    50          
    50          
876              
877 0 0         if (rng_get_bytes(entropy_buf, sizeof(entropy_buf), NULL) != sizeof(entropy_buf)) {
878 0           croak("FATAL: rng_get_bytes failed");
879             }
880 0           rv = prng->desc->add_entropy(entropy_buf, sizeof(entropy_buf), &prng->state);
881 0           zeromem(entropy_buf, sizeof(entropy_buf));
882 0 0         if (rv != CRYPT_OK) croak("FATAL: PRNG_add_entropy failed: %s", error_to_string(rv));
883 0           rv = prng->desc->ready(&prng->state);
884 0 0         if (rv != CRYPT_OK) croak("FATAL: PRNG_ready failed: %s", error_to_string(rv));
885 0           prng->last_pid = curpid;
886             }
887              
888 64           STATIC void cryptx_internal_password_cb_free(void *p) {
889             dTHX; /* fetch context */
890 64           Safefree(p);
891 64           return;
892             }
893              
894 1404           STATIC int cryptx_internal_mp2hex_with_leading_zero(mp_int * a, char *str, int maxlen, int minlen) {
895             int len, rv;
896              
897 1404 50         if (mp_isneg(a) == MP_YES) {
898 0           *str = '\0';
899 0           return MP_VAL;
900             }
901              
902 1404           rv = mp_to_radix(a, str, maxlen, NULL, 16);
903 1404 50         if (rv != MP_OKAY) {
904 0           *str = '\0';
905 0           return rv;
906             }
907              
908 1404           len = (int)strlen(str);
909 1404 50         if (len > 0 && len % 2 && len < maxlen-2) {
    100          
    50          
910 279           memmove(str+1, str, len+1); /* incl. NUL byte */
911 279           *str = '0'; /* add leading zero */
912             }
913              
914 1404           len = (int)strlen(str);
915 1404 100         if (len < minlen && minlen < maxlen-1) {
    50          
916 6           memmove(str+(minlen-len), str, len+1); /* incl. NUL byte */
917 6           memset(str, '0', minlen-len); /* add leading zero */
918             }
919              
920 1404           return MP_OKAY;
921             }
922              
923 15088           STATIC size_t cryptx_internal_find_start(const char *name, char *ltcname, size_t ltclen)
924             {
925 15088           size_t i, start = 0;
926 15088 50         if (name == NULL || strlen(name) + 1 > ltclen) croak("FATAL: invalid name") ;
    50          
927             /* normalize */
928 110206 50         for (i = 0; i < ltclen && name[i] > 0; i++) {
    100          
929 95118 100         if (name[i] >= 'A' && name[i] <= 'Z') {
    100          
930 49245           ltcname[i] = name[i] + 32; /* lowecase */
931             }
932 45873 100         else if (name[i] == '_') {
933 1859           ltcname[i] = '-';
934             }
935             else {
936 44014           ltcname[i] = name[i];
937             }
938 95118 50         if (name[i] == ':') start = i + 1;
939             }
940 15088           return start;
941             }
942              
943 8695           STATIC int cryptx_internal_find_hash(const char *name)
944             {
945 8695           char ltcname[100] = { 0 };
946 8695           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
947             /* special cases */
948 8695 100         if (strcmp(ltcname + start, "ripemd128") == 0) return find_hash("rmd128");
949 8223 100         if (strcmp(ltcname + start, "ripemd160") == 0) return find_hash("rmd160");
950 7751 100         if (strcmp(ltcname + start, "ripemd256") == 0) return find_hash("rmd256");
951 7667 100         if (strcmp(ltcname + start, "ripemd320") == 0) return find_hash("rmd320");
952 7583 100         if (strcmp(ltcname + start, "tiger192") == 0) return find_hash("tiger");
953 7093 100         if (strcmp(ltcname + start, "chaes") == 0) return find_hash("chc_hash");
954 6909 50         if (strcmp(ltcname + start, "chc-hash") == 0) return find_hash("chc_hash");
955 6909           return find_hash(ltcname + start);
956             }
957              
958 6339           STATIC int cryptx_internal_find_cipher(const char *name)
959             {
960 6339           char ltcname[100] = { 0 };
961 6339           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
962             /* special cases */
963 6339 100         if (strcmp(ltcname + start, "des-ede") == 0) return find_cipher("3des");
964 6204 100         if (strcmp(ltcname + start, "saferp") == 0) return find_cipher("safer+");
965 5941           return find_cipher(ltcname + start);
966             }
967              
968 54           STATIC int cryptx_internal_find_prng(const char *name)
969             {
970 54           char ltcname[100] = { 0 };
971 54           size_t start = cryptx_internal_find_start(name, ltcname, sizeof(ltcname) - 1);
972 54           return find_prng(ltcname + start);
973             }
974              
975             /* Math::BigInt::LTM related */
976             typedef mp_int * Math__BigInt__LTM;
977 181           STATIC SV * sv_from_mpi(mp_int *mpi) {
978             dTHX; /* fetch context */
979 181           SV *obj = newSV(0);
980 181           sv_setref_pv(obj, "Math::BigInt::LTM", (void*)mpi);
981 181           return obj;
982             }
983              
984 2           STATIC void cryptx_internal_ecc_oid_lookup(ecc_key *key)
985             {
986             int err;
987             unsigned i, j;
988             void *tmp;
989             const ltc_ecc_curve *cu;
990              
991 2           key->dp.oidlen = 0;
992 2 50         if ((err = ltc_mp.init(&tmp)) != CRYPT_OK) return;
993 52 100         for (cu = ltc_ecc_curves; cu->prime != NULL; cu++) {
994 51 50         if ((err = mp_read_radix(tmp, cu->prime, 16)) != CRYPT_OK) continue;
995 51 100         if ((mp_cmp(tmp, key->dp.prime) != LTC_MP_EQ)) continue;
996 2 50         if ((err = mp_read_radix(tmp, cu->order, 16)) != CRYPT_OK) continue;
997 2 50         if ((mp_cmp(tmp, key->dp.order) != LTC_MP_EQ)) continue;
998 2 50         if ((err = mp_read_radix(tmp, cu->A, 16)) != CRYPT_OK) continue;
999 2 50         if ((mp_cmp(tmp, key->dp.A) != LTC_MP_EQ)) continue;
1000 2 50         if ((err = mp_read_radix(tmp, cu->B, 16)) != CRYPT_OK) continue;
1001 2 50         if ((mp_cmp(tmp, key->dp.B) != LTC_MP_EQ)) continue;
1002 2 50         if ((err = mp_read_radix(tmp, cu->Gx, 16)) != CRYPT_OK) continue;
1003 2 50         if ((mp_cmp(tmp, key->dp.base.x) != LTC_MP_EQ)) continue;
1004 2 50         if ((err = mp_read_radix(tmp, cu->Gy, 16)) != CRYPT_OK) continue;
1005 2 50         if ((mp_cmp(tmp, key->dp.base.y) != LTC_MP_EQ)) continue;
1006 2 100         if (key->dp.cofactor != cu->cofactor) continue;
1007 1           break; /* found */
1008             }
1009 2           ltc_mp.deinit(tmp);
1010 2 100         if (cu->prime && cu->OID) {
    50          
1011 17 100         for (i = 0; i < 16; i++) key->dp.oid[i] = 0;
1012 13 100         for (i = 0, j = 0; i < strlen(cu->OID); i++) {
1013 12 100         if (cu->OID[i] == '.') {
1014 4 50         if (++j >= 16) return;
1015             }
1016 8 50         else if(cu->OID[i] >= '0' && cu->OID[i] <= '9') {
    50          
1017 8           key->dp.oid[j] = key->dp.oid[j] * 10 + (cu->OID[i] - '0');
1018             }
1019             else {
1020 0           return;
1021             }
1022             }
1023 1           key->dp.oidlen = j + 1;
1024             }
1025             }
1026              
1027 199           STATIC int cryptx_internal_ecc_set_curve_from_SV(ecc_key *key, SV *curve)
1028             {
1029             dTHX; /* fetch context */
1030             HV *hc, *h;
1031             SV *sv_crv, **pref;
1032             SV **sv_cofactor, **sv_prime, **sv_A, **sv_B, **sv_order, **sv_Gx, **sv_Gy, **sv_oid;
1033             char *ptr_crv;
1034             STRLEN len_crv;
1035             int err;
1036              
1037 199 50         if (!SvOK(curve)) croak("FATAL: undefined curve");
1038              
1039 199 50         if (SvPOK_spec(curve)) {
    100          
    50          
    50          
    0          
1040             /* string */
1041 197           ptr_crv = SvPV(curve, len_crv);
1042 197 50         if ((hc = get_hv("Crypt::PK::ECC::curve", 0)) == NULL) croak("FATAL: no curve register");
1043 197           pref = hv_fetch(hc, ptr_crv, (U32)len_crv, 0);
1044 197 50         if (pref && SvOK(*pref)) {
    0          
1045 0           sv_crv = *pref; /* found in %curve */
1046             }
1047             else {
1048 197           sv_crv = curve;
1049             }
1050             }
1051 2 50         else if (SvROK(curve) && SvTYPE(SvRV(curve)) == SVt_PVHV) {
    50          
1052             /* hashref */
1053 2           sv_crv = curve;
1054             }
1055             else {
1056 0           croak("FATAL: curve has to be a string or a hashref");
1057             }
1058              
1059 199 50         if (SvPOK_spec(sv_crv)) {
    100          
    50          
    50          
    0          
1060             /* string - curve name */
1061             const ltc_ecc_curve *cu;
1062 197           ptr_crv = SvPV(sv_crv, len_crv);
1063 197 50         if (ecc_find_curve(ptr_crv, &cu) != CRYPT_OK) croak("FATAL: ecparams: unknown curve '%s'", ptr_crv);
1064 197           return ecc_set_curve(cu, key);
1065             }
1066             else {
1067             /* hashref */
1068 2           ltc_ecc_curve cu = { 0 };
1069              
1070 2 50         if ((h = (HV*)(SvRV(sv_crv))) == NULL) croak("FATAL: ecparams: param is not valid hashref");
1071              
1072 2 50         if ((sv_prime = hv_fetchs(h, "prime", 0)) == NULL) croak("FATAL: ecparams: missing param prime");
1073 2 50         if ((sv_A = hv_fetchs(h, "A", 0)) == NULL) croak("FATAL: ecparams: missing param A");
1074 2 50         if ((sv_B = hv_fetchs(h, "B", 0)) == NULL) croak("FATAL: ecparams: missing param B");
1075 2 50         if ((sv_order = hv_fetchs(h, "order", 0)) == NULL) croak("FATAL: ecparams: missing param order");
1076 2 50         if ((sv_Gx = hv_fetchs(h, "Gx", 0)) == NULL) croak("FATAL: ecparams: missing param Gx");
1077 2 50         if ((sv_Gy = hv_fetchs(h, "Gy", 0)) == NULL) croak("FATAL: ecparams: missing param Gy");
1078 2 50         if ((sv_cofactor = hv_fetchs(h, "cofactor", 0)) == NULL) croak("FATAL: ecparams: missing param cofactor");
1079              
1080 2 50         if (!SvOK(*sv_prime )) croak("FATAL: ecparams: undefined param prime");
1081 2 50         if (!SvOK(*sv_A )) croak("FATAL: ecparams: undefined param A");
1082 2 50         if (!SvOK(*sv_B )) croak("FATAL: ecparams: undefined param B");
1083 2 50         if (!SvOK(*sv_order )) croak("FATAL: ecparams: undefined param order");
1084 2 50         if (!SvOK(*sv_Gx )) croak("FATAL: ecparams: undefined param Gx");
1085 2 50         if (!SvOK(*sv_Gy )) croak("FATAL: ecparams: undefined param Gy");
1086 2 50         if (!SvOK(*sv_cofactor)) croak("FATAL: ecparams: undefined param cofactor");
1087              
1088 2           sv_oid = hv_fetchs(h, "oid", 0); /* 'oid' is optional */
1089 2 50         cu.OID = (sv_oid && SvOK(*sv_oid)) ? SvPV_nolen(*sv_oid) : NULL;
    0          
1090              
1091 2           cu.prime = SvPV_nolen(*sv_prime);
1092 2           cu.A = SvPV_nolen(*sv_A);
1093 2           cu.B = SvPV_nolen(*sv_B);
1094 2           cu.order = SvPV_nolen(*sv_order);
1095 2           cu.Gx = SvPV_nolen(*sv_Gx);
1096 2           cu.Gy = SvPV_nolen(*sv_Gy);
1097 2           cu.cofactor = (unsigned long)SvUV(*sv_cofactor);
1098              
1099 2 50         if ((err = ecc_set_curve(&cu, key)) != CRYPT_OK) return err;
1100 2 50         if (key->dp.oidlen == 0) cryptx_internal_ecc_oid_lookup(key);
1101 2           return CRYPT_OK;
1102             }
1103             }
1104              
1105             MODULE = CryptX PACKAGE = CryptX PREFIX = CryptX_
1106              
1107             PROTOTYPES: DISABLE
1108              
1109             BOOT:
1110 152 50         if(register_all_ciphers() != CRYPT_OK) { croak("FATAL: register_all_ciphers failed"); }
1111 152 50         if(register_all_hashes() != CRYPT_OK) { croak("FATAL: register_all_hashes failed"); }
1112 152 50         if(register_all_prngs() != CRYPT_OK) { croak("FATAL: register_all_prngs failed"); }
1113 152 50         if(crypt_mp_init("ltm") != CRYPT_OK) { croak("FATAL: crypt_mp_init failed"); }
1114              
1115             SV *
1116             CryptX__ltc_build_settings()
1117             CODE:
1118 1           RETVAL = newSVpv(crypt_build_settings, 0);
1119             OUTPUT:
1120             RETVAL
1121              
1122             SV *
1123             CryptX__ltc_mp_name()
1124             CODE:
1125 1           RETVAL = newSVpv(ltc_mp.name, 0);
1126             OUTPUT:
1127             RETVAL
1128              
1129             int
1130             CryptX__ltc_mp_bits_per_digit()
1131             CODE:
1132 1 50         RETVAL = ltc_mp.bits_per_digit;
1133             OUTPUT:
1134             RETVAL
1135              
1136             MODULE = CryptX PACKAGE = Crypt::Misc
1137              
1138             PROTOTYPES: DISABLE
1139              
1140             SV *
1141             _radix_to_bin(SV *in, int radix)
1142             CODE:
1143             {
1144             STRLEN in_len, len;
1145             unsigned char *out_data;
1146             char *in_data;
1147             mp_int mpi;
1148              
1149 265 50         if (!SvPOK_spec(in) || radix < 2 || radix > 64) XSRETURN_UNDEF;
    50          
    0          
    0          
    0          
    50          
    50          
1150 265           in_data = SvPVbyte(in, in_len);
1151 265 50         if (in_len > 0 && memchr(in_data, '\0', in_len) != NULL) XSRETURN_UNDEF;
    50          
1152 265 50         if (mp_init(&mpi) != MP_OKAY) XSRETURN_UNDEF;
1153 265 50         if (in_len == 0) {
1154 0           RETVAL = newSVpvn("", 0);
1155             }
1156 265 50         else if (mp_read_radix(&mpi, in_data, radix) == MP_OKAY) {
1157 265           len = mp_ubin_size(&mpi);
1158 265 50         if (len == 0) {
1159 0           RETVAL = newSVpvn("", 0);
1160             }
1161             else {
1162 265           RETVAL = NEWSV(0, len); /* avoid zero! */
1163 265           SvPOK_only(RETVAL);
1164 265           SvCUR_set(RETVAL, len);
1165 265           out_data = (unsigned char *)SvPVX(RETVAL);
1166 265 50         if (mp_to_ubin(&mpi, out_data, len, NULL) != MP_OKAY) {
1167 0           SvREFCNT_dec(RETVAL);
1168 0           RETVAL = newSVpvn(NULL, 0); /* undef */
1169             }
1170             }
1171             }
1172             else {
1173 0           RETVAL = newSVpvn(NULL, 0); /* undef */
1174             }
1175 265           mp_clear(&mpi);
1176             }
1177             OUTPUT:
1178             RETVAL
1179              
1180             SV *
1181             _bin_to_radix(SV *in, int radix)
1182             CODE:
1183             {
1184             STRLEN len;
1185             unsigned char *in_data;
1186             char *out_data;
1187             mp_int mpi, tmp;
1188             mp_digit d;
1189             mp_err merr;
1190 290           int digits = 0;
1191              
1192 290 50         if (!SvPOK_spec(in) || radix < 2 || radix > 64) XSRETURN_UNDEF;
    50          
    0          
    0          
    0          
    50          
    50          
1193 290           in_data = (unsigned char *) SvPVbyte(in, len);
1194 290 50         if (mp_init_multi(&mpi, &tmp, NULL) != MP_OKAY) XSRETURN_UNDEF;
1195 290 50         if (len == 0) {
1196 0           RETVAL = newSVpvn("", 0);
1197             }
1198             else {
1199 290 50         if (mp_from_ubin(&mpi, in_data, (size_t)len) == MP_OKAY) {
1200 290           merr = mp_copy(&mpi, &tmp);
1201 5655 50         while (merr == MP_OKAY && mp_iszero(&tmp) == MP_NO) {
    100          
1202 5365           merr = mp_div_d(&tmp, (mp_digit)radix, &tmp, &d);
1203 5365           digits++;
1204             }
1205 290 50         if (merr != MP_OKAY) {
1206 0           RETVAL = newSVpvn(NULL, 0); /* undef */
1207             }
1208 290 100         else if (digits == 0) {
1209 25           RETVAL = newSVpvn("", 0);
1210             }
1211             else {
1212 265           RETVAL = NEWSV(0, digits + 2); /* +2 for sign and NUL byte */
1213 265           SvPOK_only(RETVAL);
1214 265           out_data = SvPVX(RETVAL);
1215 265 50         if (mp_to_radix(&mpi, out_data, digits + 2, NULL, radix) == MP_OKAY) {
1216 265           SvCUR_set(RETVAL, strlen(out_data));
1217             }
1218             else {
1219 0           SvREFCNT_dec(RETVAL);
1220 0           RETVAL = newSVpvn(NULL, 0); /* undef */
1221             }
1222             }
1223             }
1224             else {
1225 0           RETVAL = newSVpvn(NULL, 0); /* undef */
1226             }
1227             }
1228 290           mp_clear_multi(&tmp, &mpi, NULL);
1229             }
1230             OUTPUT:
1231             RETVAL
1232              
1233             SV *
1234             encode_b64(SV * in)
1235             ALIAS:
1236             encode_b64u = 1
1237             CODE:
1238             {
1239             int rv;
1240             STRLEN in_len;
1241             unsigned long out_len;
1242             unsigned char *in_data;
1243             char *out_data;
1244              
1245 154 100         if (!SvPOK_spec(in)) XSRETURN_UNDEF;
    100          
    50          
    50          
    50          
1246 153           in_data = (unsigned char *) SvPVbyte(in, in_len);
1247 153 50         if (in_len == 0) {
1248 0           RETVAL = newSVpvn("", 0);
1249             }
1250             else {
1251 153           out_len = (unsigned long)(4 * ((in_len + 2) / 3) + 1);
1252 153           RETVAL = NEWSV(0, out_len); /* avoid zero! */
1253 153           SvPOK_only(RETVAL);
1254 153           out_data = SvPVX(RETVAL);
1255 153 100         if (ix == 1)
1256 59           rv = base64url_encode(in_data, (unsigned long)in_len, out_data, &out_len);
1257             else
1258 94           rv = base64_encode(in_data, (unsigned long)in_len, out_data, &out_len);
1259 153 50         if (rv != CRYPT_OK) {
1260 0           SvREFCNT_dec(RETVAL);
1261 0           XSRETURN_UNDEF;
1262             }
1263 153           SvCUR_set(RETVAL, out_len);
1264             }
1265             }
1266             OUTPUT:
1267             RETVAL
1268              
1269             SV *
1270             decode_b64(SV * in)
1271             ALIAS:
1272             decode_b64u = 1
1273             CODE:
1274             {
1275             int rv;
1276             STRLEN in_len;
1277             unsigned long out_len;
1278             unsigned char *out_data;
1279             char *in_data;
1280              
1281 425 100         if (!SvPOK_spec(in)) XSRETURN_UNDEF;
    100          
    50          
    50          
    50          
1282 419           in_data = SvPVbyte(in, in_len);
1283 419 50         if (in_len == 0) {
1284 0           RETVAL = newSVpvn("", 0);
1285             }
1286             else {
1287 419 100         if (cryptx_internal_input_has_no_payload(in_data, in_len)) XSRETURN_UNDEF;
1288 414           out_len = (unsigned long)in_len;
1289 414           RETVAL = NEWSV(0, out_len); /* avoid zero! */
1290 414           SvPOK_only(RETVAL);
1291 414           out_data = (unsigned char *)SvPVX(RETVAL);
1292 414 100         if (ix == 1)
1293 76           rv = base64url_sane_decode(in_data, (unsigned long)in_len, out_data, &out_len);
1294             else
1295 338           rv = base64_sane_decode(in_data, (unsigned long)in_len, out_data, &out_len);
1296 414 50         if (rv != CRYPT_OK) {
1297 0           SvREFCNT_dec(RETVAL);
1298 0           XSRETURN_UNDEF;
1299             }
1300 414           SvCUR_set(RETVAL, out_len);
1301             }
1302             }
1303             OUTPUT:
1304             RETVAL
1305              
1306             SV *
1307             encode_b32r(SV *in)
1308             ALIAS:
1309             encode_b32b = 1
1310             encode_b32z = 2
1311             encode_b32c = 3
1312             CODE:
1313             {
1314             STRLEN in_len;
1315             unsigned long out_len;
1316             unsigned char *in_data;
1317             char *out_data;
1318 235           int id = -1, err;
1319              
1320 235 100         if (!SvPOK_spec(in)) XSRETURN_UNDEF;
    100          
    50          
    50          
    50          
1321 234 100         if (ix == 0) id = BASE32_RFC4648;
1322 234 100         if (ix == 1) id = BASE32_BASE32HEX;
1323 234 100         if (ix == 2) id = BASE32_ZBASE32;
1324 234 100         if (ix == 3) id = BASE32_CROCKFORD;
1325 234 50         if (id == -1) XSRETURN_UNDEF;
1326 234           in_data = (unsigned char *) SvPVbyte(in, in_len);
1327 234 50         if (in_len == 0) {
1328 0           RETVAL = newSVpvn("", 0);
1329             }
1330             else {
1331 234           out_len = (unsigned long)((8 * in_len + 4) / 5 + 1);
1332 234           RETVAL = NEWSV(0, out_len); /* avoid zero! */
1333 234           SvPOK_only(RETVAL);
1334 234           out_data = SvPVX(RETVAL);
1335 234           err = base32_encode(in_data, (unsigned long)in_len, out_data, &out_len, id);
1336 234 50         if (err != CRYPT_OK) {
1337 0           SvREFCNT_dec(RETVAL);
1338 0           XSRETURN_UNDEF;
1339             }
1340 234           SvCUR_set(RETVAL, out_len);
1341             }
1342             }
1343             OUTPUT:
1344             RETVAL
1345              
1346             SV *
1347             decode_b32r(SV *in)
1348             ALIAS:
1349             decode_b32b = 1
1350             decode_b32z = 2
1351             decode_b32c = 3
1352             CODE:
1353             {
1354             STRLEN in_len;
1355             unsigned long out_len;
1356             unsigned char *out_data;
1357             char *in_data;
1358 237           int id = -1, err;
1359              
1360 241 100         if (!SvPOK_spec(in)) XSRETURN_UNDEF;
    50          
    0          
    0          
    0          
1361 236 100         if (ix == 0) id = BASE32_RFC4648;
1362 236 100         if (ix == 1) id = BASE32_BASE32HEX;
1363 236 100         if (ix == 2) id = BASE32_ZBASE32;
1364 236 100         if (ix == 3) id = BASE32_CROCKFORD;
1365 236 50         if (id == -1) XSRETURN_UNDEF;
1366 236           in_data = SvPVbyte(in, in_len);
1367 236 50         if (in_len == 0) {
1368 0           RETVAL = newSVpvn("", 0);
1369             }
1370             else {
1371 236 100         if (cryptx_internal_input_has_no_payload(in_data, in_len)) XSRETURN_UNDEF;
1372 232           out_len = (unsigned long)in_len;
1373 232           RETVAL = NEWSV(0, out_len); /* avoid zero! */
1374 232           SvPOK_only(RETVAL);
1375 232           out_data = (unsigned char *)SvPVX(RETVAL);
1376 232           err = base32_decode(in_data, (unsigned long)in_len, out_data, &out_len, id);
1377 232 50         if (err != CRYPT_OK) {
1378 0           SvREFCNT_dec(RETVAL);
1379 0           XSRETURN_UNDEF;
1380             }
1381 232           SvCUR_set(RETVAL, out_len);
1382             }
1383             }
1384             OUTPUT:
1385             RETVAL
1386              
1387             SV *
1388             increment_octets_le(SV * in)
1389             CODE:
1390             {
1391 6           STRLEN len, i = 0;
1392             unsigned char *out_data, *in_data;
1393              
1394 6 50         if (!SvPOK_spec(in)) XSRETURN_UNDEF;
    50          
    0          
    0          
    0          
1395 6           in_data = (unsigned char *)SvPVbyte(in, len);
1396 6 50         if (len == 0) {
1397 0           RETVAL = newSVpvn("", 0);
1398             }
1399             else {
1400 6           RETVAL = NEWSV(0, len); /* avoid zero! */
1401 6           SvPOK_only(RETVAL);
1402 6           SvCUR_set(RETVAL, len);
1403 6           out_data = (unsigned char *)SvPVX(RETVAL);
1404 6           Copy(in_data, out_data, len, unsigned char);
1405 13 100         while (i < len) {
1406 11           out_data[i]++;
1407 11 100         if (0 != out_data[i]) break;
1408 7           i++;
1409             }
1410 6 100         if (i == len) {
1411 2           SvREFCNT_dec(RETVAL);
1412 2           croak("FATAL: increment_octets_le overflow");
1413             }
1414             }
1415             }
1416             OUTPUT:
1417             RETVAL
1418              
1419             SV *
1420             increment_octets_be(SV * in)
1421             CODE:
1422             {
1423 8           STRLEN len, i = 0;
1424             unsigned char *out_data, *in_data;
1425              
1426 8 50         if (!SvPOK_spec(in)) XSRETURN_UNDEF;
    100          
    50          
    50          
    50          
1427 8           in_data = (unsigned char *)SvPVbyte(in, len);
1428 8 50         if (len == 0) {
1429 0           RETVAL = newSVpvn("", 0);
1430             }
1431             else {
1432 8           RETVAL = NEWSV(0, len); /* avoid zero! */
1433 8           SvPOK_only(RETVAL);
1434 8           SvCUR_set(RETVAL, len);
1435 8           out_data = (unsigned char *)SvPVX(RETVAL);
1436 8           Copy(in_data, out_data, len, unsigned char);
1437 15 100         while (i < len) {
1438 13           out_data[len - 1 - i]++;
1439 13 100         if (0 != out_data[len - 1 - i]) break;
1440 7           i++;
1441             }
1442 8 100         if (i == len) {
1443 2           SvREFCNT_dec(RETVAL);
1444 2           croak("FATAL: increment_octets_be overflow");
1445             }
1446             }
1447             }
1448             OUTPUT:
1449             RETVAL
1450              
1451             SV *
1452             slow_eq(SV *a, SV *b)
1453             CODE:
1454             {
1455             STRLEN a_len, b_len;
1456             unsigned char *a_data, *b_data;
1457             const void *first;
1458 9           int result = 0;
1459              
1460 9 100         if (!SvPOK_spec(a) || !SvPOK_spec(b)) XSRETURN_UNDEF;
    50          
    0          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
1461 8           a_data = (unsigned char *)SvPVbyte(a, a_len);
1462 8           b_data = (unsigned char *)SvPVbyte(b, b_len);
1463 8           first = a_data;
1464 8 100         if (a_len != b_len) { first = b_data; result = 1; }
1465 8           result |= mem_neq(first, b_data, b_len);
1466 8           RETVAL = newSViv(result == 0 ? 1 : 0);
1467             }
1468             OUTPUT:
1469             RETVAL
1470              
1471             ###############################################################################
1472              
1473             INCLUDE: inc/CryptX_ASN1.xs.inc
1474             INCLUDE: inc/CryptX_Digest.xs.inc
1475             INCLUDE: inc/CryptX_Digest_SHAKE.xs.inc
1476             INCLUDE: inc/CryptX_Digest_TurboSHAKE.xs.inc
1477             INCLUDE: inc/CryptX_Digest_KangarooTwelve.xs.inc
1478             INCLUDE: inc/CryptX_Cipher.xs.inc
1479              
1480             INCLUDE: inc/CryptX_Checksum_Adler32.xs.inc
1481             INCLUDE: inc/CryptX_Checksum_CRC32.xs.inc
1482              
1483             INCLUDE: inc/CryptX_AuthEnc_EAX.xs.inc
1484             INCLUDE: inc/CryptX_AuthEnc_GCM.xs.inc
1485             INCLUDE: inc/CryptX_AuthEnc_OCB.xs.inc
1486             INCLUDE: inc/CryptX_AuthEnc_CCM.xs.inc
1487             INCLUDE: inc/CryptX_AuthEnc_ChaCha20Poly1305.xs.inc
1488             INCLUDE: inc/CryptX_AuthEnc_SIV.xs.inc
1489              
1490             INCLUDE: inc/CryptX_Stream_ChaCha.xs.inc
1491             INCLUDE: inc/CryptX_Stream_XChaCha.xs.inc
1492             INCLUDE: inc/CryptX_Stream_Salsa20.xs.inc
1493             INCLUDE: inc/CryptX_Stream_XSalsa20.xs.inc
1494             INCLUDE: inc/CryptX_Stream_RC4.xs.inc
1495             INCLUDE: inc/CryptX_Stream_Sober128.xs.inc
1496             INCLUDE: inc/CryptX_Stream_Sosemanuk.xs.inc
1497             INCLUDE: inc/CryptX_Stream_Rabbit.xs.inc
1498              
1499             INCLUDE: inc/CryptX_Mac_F9.xs.inc
1500             INCLUDE: inc/CryptX_Mac_HMAC.xs.inc
1501             INCLUDE: inc/CryptX_Mac_OMAC.xs.inc
1502             INCLUDE: inc/CryptX_Mac_Pelican.xs.inc
1503             INCLUDE: inc/CryptX_Mac_PMAC.xs.inc
1504             INCLUDE: inc/CryptX_Mac_XCBC.xs.inc
1505             INCLUDE: inc/CryptX_Mac_Poly1305.xs.inc
1506             INCLUDE: inc/CryptX_Mac_BLAKE2s.xs.inc
1507             INCLUDE: inc/CryptX_Mac_BLAKE2b.xs.inc
1508              
1509             INCLUDE: inc/CryptX_Mode_CBC.xs.inc
1510             INCLUDE: inc/CryptX_Mode_ECB.xs.inc
1511             INCLUDE: inc/CryptX_Mode_CFB.xs.inc
1512             INCLUDE: inc/CryptX_Mode_OFB.xs.inc
1513             INCLUDE: inc/CryptX_Mode_CTR.xs.inc
1514             #INCLUDE: inc/CryptX_Mode_F8.xs.inc
1515             #INCLUDE: inc/CryptX_Mode_LRW.xs.inc
1516             #INCLUDE: inc/CryptX_Mode_XTS.xs.inc
1517              
1518             INCLUDE: inc/CryptX_PRNG.xs.inc
1519              
1520             INCLUDE: inc/CryptX_PK_RSA.xs.inc
1521             INCLUDE: inc/CryptX_PK_DSA.xs.inc
1522             INCLUDE: inc/CryptX_PK_DH.xs.inc
1523             INCLUDE: inc/CryptX_PK_ECC.xs.inc
1524             INCLUDE: inc/CryptX_PK_Ed25519.xs.inc
1525             INCLUDE: inc/CryptX_PK_X25519.xs.inc
1526             INCLUDE: inc/CryptX_PK_Ed448.xs.inc
1527             INCLUDE: inc/CryptX_PK_X448.xs.inc
1528              
1529             INCLUDE: inc/CryptX_KeyDerivation.xs.inc
1530              
1531             INCLUDE: inc/CryptX_BigInt_LTM.xs.inc