File Coverage

Sodium.xs
Criterion Covered Total %
statement 1397 1775 78.7
branch 597 1018 58.6
condition n/a
subroutine n/a
pod n/a
total 1994 2793 71.3


line stmt bran cond sub pod time code
1              
2             #define PERL_NO_GET_CONTEXT
3             #define NO_XSLOCKS
4              
5             #include "EXTERN.h"
6             #include "perl.h"
7             #include "XSUB.h"
8             #include "patchlevel.h"
9             #include "ppport.h"
10              
11             /* libsodium */
12             #include "sodium.h"
13              
14             #define DUMP(v) do_sv_dump(0, Perl_debug_log, v, 0, 4, 0, 0);
15              
16             typedef struct {
17             unsigned char * bytes;
18             STRLEN length;
19             int locked;
20             } DataBytesLocker;
21              
22             #if defined(AES256GCM_IS_AVAILABLE)
23             typedef struct {
24             int locked;
25             crypto_aead_aes256gcm_state * ctx;
26             } CryptNaClSodiumAeadAes256gcmState;
27             #endif
28              
29             typedef struct {
30             crypto_generichash_state * state;
31             size_t init_bytes;
32             } CryptNaClSodiumGenerichashStream;
33              
34             typedef struct {
35             crypto_hash_sha256_state * state;
36             } CryptNaClSodiumHashSha256Stream;
37              
38             typedef struct {
39             crypto_hash_sha512_state * state;
40             } CryptNaClSodiumHashSha512Stream;
41              
42             typedef struct {
43             crypto_auth_hmacsha256_state * state;
44             } CryptNaClSodiumAuthHmacsha256Stream;
45              
46             typedef struct {
47             crypto_auth_hmacsha512_state * state;
48             } CryptNaClSodiumAuthHmacsha512Stream;
49              
50             typedef struct {
51             crypto_auth_hmacsha512256_state * state;
52             } CryptNaClSodiumAuthHmacsha512256Stream;
53              
54             typedef struct {
55             crypto_onetimeauth_state * state;
56             } CryptNaClSodiumOnetimeauthStream;
57              
58             typedef DataBytesLocker * Data__BytesLocker;
59             #if defined(AES256GCM_IS_AVAILABLE)
60             typedef CryptNaClSodiumAeadAes256gcmState * Crypt__NaCl__Sodium__aead__aes256gcmstate;
61             #endif
62             typedef CryptNaClSodiumGenerichashStream * Crypt__NaCl__Sodium__generichash__stream;
63             typedef CryptNaClSodiumHashSha256Stream * Crypt__NaCl__Sodium__hash__sha256stream;
64             typedef CryptNaClSodiumHashSha512Stream * Crypt__NaCl__Sodium__hash__sha512stream;
65             typedef CryptNaClSodiumAuthHmacsha256Stream * Crypt__NaCl__Sodium__auth__hmacsha256stream;
66             typedef CryptNaClSodiumAuthHmacsha512Stream * Crypt__NaCl__Sodium__auth__hmacsha512stream;
67             typedef CryptNaClSodiumAuthHmacsha512256Stream * Crypt__NaCl__Sodium__auth__hmacsha512256stream;
68             typedef CryptNaClSodiumOnetimeauthStream * Crypt__NaCl__Sodium__onetimeauth__stream;
69              
70             #define CLONESTATE(streamtype, statetype, padding, extra) \
71             Newx(new_stream, 1, streamtype);\
72             if ( new_stream == NULL ) {\
73             croak("Could not allocate enough memory");\
74             }\
75             new_stream->state = sodium_malloc(sizeof(crypto_ ## statetype ## _state) + padding);\
76             if ( new_stream->state == NULL ) {\
77             croak("Could not allocate enough memory");\
78             }\
79             extra;\
80             memcpy(new_stream->state,cur_stream->state,sizeof(crypto_ ## statetype ## _state) + padding);
81              
82             #if defined(USE_ITHREADS) && defined(MGf_DUP)
83             STATIC int dup_byteslocker(pTHX_ MAGIC *mg, CLONE_PARAMS *params)
84             {
85             DataBytesLocker *new_bl;
86             DataBytesLocker *cur_bl;
87             PERL_UNUSED_VAR(params);
88             Newx(new_bl, 1, DataBytesLocker);
89             if ( new_bl == NULL ) {
90             croak("Could not allocate enough memory");
91             }
92             cur_bl = (DataBytesLocker *)mg->mg_ptr;
93             new_bl->length = cur_bl->length;
94             new_bl->locked = cur_bl->locked;
95             new_bl->bytes = sodium_malloc(cur_bl->length + 1 );
96             if ( new_bl->bytes == NULL ) {
97             croak("Could not allocate enough memory");
98             }
99             memcpy(new_bl->bytes,cur_bl->bytes,cur_bl->length);
100             mg->mg_ptr = (char *)new_bl;
101             return 0;
102             }
103              
104             #define DUPSTREAM(streamtype, statetype, padding, extra) \
105             STATIC int dup_ ## statetype ## _stream(pTHX_ MAGIC *mg, CLONE_PARAMS *params)\
106             {\
107             streamtype *new_stream;\
108             streamtype *cur_stream;\
109             PERL_UNUSED_VAR(params);\
110             cur_stream = (streamtype *)mg->mg_ptr;\
111             CLONESTATE(streamtype, statetype, padding, extra)\
112             mg->mg_ptr = (char *)new_stream;\
113             return 0;\
114             }
115              
116             #if defined(AES256GCM_IS_AVAILABLE)
117             STATIC int dup_aead_aes256gcmstate(pTHX_ MAGIC *mg, CLONE_PARAMS *params)
118             {
119             CryptNaClSodiumAeadAes256gcmState *new_state;
120             CryptNaClSodiumAeadAes256gcmState *cur_state;
121             size_t sizeof_state = crypto_aead_aes256gcm_statebytes();
122             PERL_UNUSED_VAR(params);
123             cur_state = (CryptNaClSodiumAeadAes256gcmState *)mg->mg_ptr;
124              
125             Newx(new_state, 1, CryptNaClSodiumAeadAes256gcmState);
126             if ( new_state == NULL ) {
127             croak("Could not allocate enough memory");
128             }
129             new_state->ctx = sodium_malloc(sizeof_state);
130             if ( new_state->ctx == NULL ) {
131             croak("Could not allocate enough memory");
132             }
133             memcpy(new_state->ctx,cur_state->ctx,sizeof_state);
134              
135             mg->mg_ptr = (char *)new_state;
136             return 0;
137             }
138             #endif
139              
140             DUPSTREAM(CryptNaClSodiumGenerichashStream, generichash, (size_t)63U & ~(size_t) 63U, new_stream->init_bytes=cur_stream->init_bytes)
141             DUPSTREAM(CryptNaClSodiumHashSha256Stream, hash_sha256, 0, ((void)0))
142             DUPSTREAM(CryptNaClSodiumHashSha512Stream, hash_sha512, 0, ((void)0))
143             DUPSTREAM(CryptNaClSodiumAuthHmacsha256Stream, auth_hmacsha256, 0, ((void)0))
144             DUPSTREAM(CryptNaClSodiumAuthHmacsha512Stream, auth_hmacsha512, 0, ((void)0))
145             DUPSTREAM(CryptNaClSodiumAuthHmacsha512256Stream, auth_hmacsha512256, 0, ((void)0))
146             DUPSTREAM(CryptNaClSodiumOnetimeauthStream, onetimeauth, 0, ((void)0))
147              
148             #endif
149              
150             STATIC MGVTBL vtbl_byteslocker = {
151             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
152             #ifdef MGf_COPY
153             NULL, /* copy */
154             #endif
155             #ifdef MGf_DUP
156             # ifdef USE_ITHREADS
157             dup_byteslocker,
158             # else
159             NULL, /* dup */
160             # endif
161             #endif
162             #ifdef MGf_LOCAL
163             NULL /* local */
164             #endif
165             };
166             #if defined(AES256GCM_IS_AVAILABLE)
167             STATIC MGVTBL vtbl_aead_aes256gcmstate = {
168             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
169             #ifdef MGf_COPY
170             NULL, /* copy */
171             #endif
172             #ifdef MGf_DUP
173             # ifdef USE_ITHREADS
174             dup_aead_aes256gcmstate,
175             # else
176             NULL, /* dup */
177             # endif
178             #endif
179             #ifdef MGf_LOCAL
180             NULL /* local */
181             #endif
182             };
183             #endif
184             STATIC MGVTBL vtbl_generichash = {
185             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
186             #ifdef MGf_COPY
187             NULL, /* copy */
188             #endif
189             #ifdef MGf_DUP
190             # ifdef USE_ITHREADS
191             dup_generichash_stream,
192             # else
193             NULL, /* dup */
194             # endif
195             #endif
196             #ifdef MGf_LOCAL
197             NULL /* local */
198             #endif
199             };
200             STATIC MGVTBL vtbl_hash_sha256 = {
201             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
202             #ifdef MGf_COPY
203             NULL, /* copy */
204             #endif
205             #ifdef MGf_DUP
206             # ifdef USE_ITHREADS
207             dup_hash_sha256_stream,
208             # else
209             NULL, /* dup */
210             # endif
211             #endif
212             #ifdef MGf_LOCAL
213             NULL /* local */
214             #endif
215             };
216             STATIC MGVTBL vtbl_hash_sha512 = {
217             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
218             #ifdef MGf_COPY
219             NULL, /* copy */
220             #endif
221             #ifdef MGf_DUP
222             # ifdef USE_ITHREADS
223             dup_hash_sha512_stream,
224             # else
225             NULL, /* dup */
226             # endif
227             #endif
228             #ifdef MGf_LOCAL
229             NULL /* local */
230             #endif
231             };
232             STATIC MGVTBL vtbl_auth_hmacsha256 = {
233             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
234             #ifdef MGf_COPY
235             NULL, /* copy */
236             #endif
237             #ifdef MGf_DUP
238             # ifdef USE_ITHREADS
239             dup_auth_hmacsha256_stream,
240             # else
241             NULL, /* dup */
242             # endif
243             #endif
244             #ifdef MGf_LOCAL
245             NULL /* local */
246             #endif
247             };
248             STATIC MGVTBL vtbl_auth_hmacsha512 = {
249             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
250             #ifdef MGf_COPY
251             NULL, /* copy */
252             #endif
253             #ifdef MGf_DUP
254             # ifdef USE_ITHREADS
255             dup_auth_hmacsha512_stream,
256             # else
257             NULL, /* dup */
258             # endif
259             #endif
260             #ifdef MGf_LOCAL
261             NULL /* local */
262             #endif
263             };
264             STATIC MGVTBL vtbl_auth_hmacsha512256 = {
265             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
266             #ifdef MGf_COPY
267             NULL, /* copy */
268             #endif
269             #ifdef MGf_DUP
270             # ifdef USE_ITHREADS
271             dup_auth_hmacsha512256_stream,
272             # else
273             NULL, /* dup */
274             # endif
275             #endif
276             #ifdef MGf_LOCAL
277             NULL /* local */
278             #endif
279             };
280             STATIC MGVTBL vtbl_onetimeauth = {
281             NULL, /* get */ NULL, /* set */ NULL, /* len */ NULL, /* clear */ NULL, /* free */
282             #ifdef MGf_COPY
283             NULL, /* copy */
284             #endif
285             #ifdef MGf_DUP
286             # ifdef USE_ITHREADS
287             dup_onetimeauth_stream,
288             # else
289             NULL, /* dup */
290             # endif
291             #endif
292             #ifdef MGf_LOCAL
293             NULL /* local */
294             #endif
295             };
296              
297 116007           static DataBytesLocker * InitDataBytesLocker(pTHX_ STRLEN size) {
298             DataBytesLocker *bl;
299 116007           Newx(bl, 1, DataBytesLocker);
300              
301 116007 50         if ( bl == NULL ) {
302 0           croak("Could not allocate enough memory");
303             }
304              
305 116007           bl->bytes = sodium_malloc(size + 1 );
306              
307 116007 50         if ( bl->bytes == NULL ) {
308 0           croak("Could not allocate enough memory");
309             }
310              
311 116007           bl->length = size;
312 116007           bl->locked = 0;
313              
314 116007           return bl;
315             }
316              
317 114521           static SV * DataBytesLocker2SV(pTHX_ DataBytesLocker *bl) {
318 114521           SV *sv = newSV(0);
319 114521           SV *obj = newRV_noinc(sv);
320             SV *default_locked;
321             #ifdef USE_ITHREADS
322             MAGIC *mg;
323             #endif
324              
325 114521           sv_bless(obj, gv_stashpv("Data::BytesLocker", 0));
326              
327 114521 50         if ( (default_locked = get_sv("Data::BytesLocker::DEFAULT_LOCKED", 0)) ) {
328 114521 100         if ( SvTRUE(default_locked) ) {
329 13           int rc = sodium_mprotect_noaccess((void *)bl->bytes);
330              
331 13 50         if ( rc != 0 ) {
332 0           croak("Unable to protect BytesLocker object");
333             }
334 13           bl->locked = 1;
335             }
336             } else {
337 0           int rc = sodium_mprotect_readonly((void *)bl->bytes);
338              
339 0 0         if ( rc != 0 ) {
340 0           croak("Unable to protect BytesLocker object");
341             }
342             }
343              
344             #ifdef USE_ITHREADS
345             mg =
346             #endif
347 114521           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_byteslocker, (const char *)bl, 0);
348              
349             #if defined(USE_ITHREADS) && defined(MGf_DUP)
350             mg->mg_flags |= MGf_DUP;
351             #endif
352              
353 114521           return obj;
354             }
355              
356 443511           static DataBytesLocker* GetBytesLocker(pTHX_ SV* sv)
357             {
358             MAGIC *mg;
359              
360 443511 50         if (!sv_derived_from(sv, "Data::BytesLocker"))
361 0           croak("Not a reference to a Data::BytesLocker object");
362              
363 443511 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
364 443511 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_byteslocker) {
    50          
365 443511           return (DataBytesLocker *)mg->mg_ptr;
366             }
367             }
368              
369 0           croak("Failed to get Data::BytesLocker pointer");
370             return (DataBytesLocker*)0; /* some compilers insist on a return value */
371             }
372              
373             #if defined(AES256GCM_IS_AVAILABLE)
374 384           static CryptNaClSodiumAeadAes256gcmState * InitAeadAes256gcmState(pTHX_ unsigned char * key) {
375             CryptNaClSodiumAeadAes256gcmState *pk;
376 384           Newx(pk, 1, CryptNaClSodiumAeadAes256gcmState);
377              
378 384 50         if ( pk == NULL ) {
379 0           croak("Could not allocate enough memory");
380             }
381              
382 384           pk->ctx = sodium_malloc(crypto_aead_aes256gcm_statebytes());
383              
384 384 50         if ( pk->ctx == NULL ) {
385 0           croak("Could not allocate enough memory");
386             }
387              
388              
389 384           crypto_aead_aes256gcm_beforenm(pk->ctx, key);
390 384           pk->locked = 0;
391              
392 384           return pk;
393             }
394              
395 384           static SV * AeadAes256gcmState2SV(pTHX_ CryptNaClSodiumAeadAes256gcmState *state) {
396 384           SV *sv = newSV(0);
397 384           SV *obj = newRV_noinc(sv);
398             SV *default_locked;
399             #ifdef USE_ITHREADS
400             MAGIC *mg;
401             #endif
402              
403 384           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::aead::aes256gcmstate", 0));
404              
405 384 50         if ( (default_locked = get_sv("Data::BytesLocker::DEFAULT_LOCKED", 0)) ) {
406 384 50         if ( SvTRUE(default_locked) ) {
407 0           int rc = sodium_mprotect_noaccess((void *)state->ctx);
408              
409 0 0         if ( rc != 0 ) {
410 0           croak("Unable to protect AES256GCM precalculated key object");
411             }
412 0           state->locked = 1;
413             }
414             }
415              
416             #ifdef USE_ITHREADS
417             mg =
418             #endif
419 384           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_aead_aes256gcmstate, (const char *)state, 0);
420              
421             #if defined(USE_ITHREADS) && defined(MGf_DUP)
422             mg->mg_flags |= MGf_DUP;
423             #endif
424              
425 384           return obj;
426             }
427              
428 1160           static CryptNaClSodiumAeadAes256gcmState* GetAeadAes256gcmState(pTHX_ SV* sv)
429             {
430             MAGIC *mg;
431              
432 1160 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::aead::aes256gcmstate"))
433 0           croak("Not a reference to a Crypt::NaCl::Sodium::aead::aes256gcmstate object");
434              
435 1160 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
436 1160 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_aead_aes256gcmstate) {
    50          
437 1160           return (CryptNaClSodiumAeadAes256gcmState *)mg->mg_ptr;
438             }
439             }
440              
441 0           croak("Failed to get Crypt::NaCl::Sodium::aead::aes256gcmstate pointer");
442             return (CryptNaClSodiumAeadAes256gcmState*)0; /* some compilers insist on a return value */
443             }
444             #endif
445              
446 4783           static SV * GenerichashStream2SV(pTHX_ CryptNaClSodiumGenerichashStream *stream) {
447 4783           SV *sv = newSV(0);
448 4783           SV *obj = newRV_noinc(sv);
449             #ifdef USE_ITHREADS
450             MAGIC *mg;
451             #endif
452              
453 4783           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::generichash::stream", 0));
454              
455             #ifdef USE_ITHREADS
456             mg =
457             #endif
458 4783           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_generichash, (const char *)stream, 0);
459              
460             #if defined(USE_ITHREADS) && defined(MGf_DUP)
461             mg->mg_flags |= MGf_DUP;
462             #endif
463              
464 4783           return obj;
465             }
466              
467 133067           static CryptNaClSodiumGenerichashStream* GetGenerichashStream(pTHX_ SV* sv)
468             {
469             MAGIC *mg;
470              
471 133067 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::generichash::stream"))
472 0           croak("Not a reference to a Crypt::NaCl::Sodium::generichash::stream object");
473              
474 133067 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
475 133067 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_generichash) {
    50          
476 133067           return (CryptNaClSodiumGenerichashStream *)mg->mg_ptr;
477             }
478             }
479              
480 0           croak("Failed to get Crypt::NaCl::Sodium::generichash::stream pointer");
481             return (CryptNaClSodiumGenerichashStream*)0; /* some compilers insist on a return value */
482             }
483              
484              
485 4           static SV * HashSha256Stream2SV(pTHX_ CryptNaClSodiumHashSha256Stream *stream) {
486 4           SV *sv = newSV(0);
487 4           SV *obj = newRV_noinc(sv);
488             #ifdef USE_ITHREADS
489             MAGIC *mg;
490             #endif
491              
492 4           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::hash::sha256stream", 0));
493              
494             #ifdef USE_ITHREADS
495             mg =
496             #endif
497 4           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_hash_sha256, (const char *)stream, 0);
498              
499             #if defined(USE_ITHREADS) && defined(MGf_DUP)
500             mg->mg_flags |= MGf_DUP;
501             #endif
502              
503 4           return obj;
504             }
505              
506 365           static CryptNaClSodiumHashSha256Stream* GetHashSha256Stream(pTHX_ SV* sv)
507             {
508             MAGIC *mg;
509              
510 365 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::hash::sha256stream"))
511 0           croak("Not a reference to a Crypt::NaCl::Sodium::hash::sha256stream object");
512              
513 365 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
514 365 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_hash_sha256) {
    50          
515 365           return (CryptNaClSodiumHashSha256Stream *)mg->mg_ptr;
516             }
517             }
518              
519 0           croak("Failed to get Crypt::NaCl::Sodium::hash::sha256stream pointer");
520             return (CryptNaClSodiumHashSha256Stream*)0; /* some compilers insist on a return value */
521             }
522              
523              
524 4           static SV * HashSha512Stream2SV(pTHX_ CryptNaClSodiumHashSha512Stream *stream) {
525 4           SV *sv = newSV(0);
526 4           SV *obj = newRV_noinc(sv);
527             #ifdef USE_ITHREADS
528             MAGIC *mg;
529             #endif
530              
531 4           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::hash::sha512stream", 0));
532              
533             #ifdef USE_ITHREADS
534             mg =
535             #endif
536 4           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_hash_sha512, (const char *)stream, 0);
537              
538             #if defined(USE_ITHREADS) && defined(MGf_DUP)
539             mg->mg_flags |= MGf_DUP;
540             #endif
541              
542 4           return obj;
543             }
544              
545 365           static CryptNaClSodiumHashSha512Stream* GetHashSha512Stream(pTHX_ SV* sv)
546             {
547             MAGIC *mg;
548              
549 365 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::hash::sha512stream"))
550 0           croak("Not a reference to a Crypt::NaCl::Sodium::hash::sha512stream object");
551              
552 365 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
553 365 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_hash_sha512) {
    50          
554 365           return (CryptNaClSodiumHashSha512Stream *)mg->mg_ptr;
555             }
556             }
557              
558 0           croak("Failed to get Crypt::NaCl::Sodium::hash::sha512stream pointer");
559             return (CryptNaClSodiumHashSha512Stream*)0; /* some compilers insist on a return value */
560             }
561              
562              
563 197           static SV * AuthHmacsha256Stream2SV(pTHX_ CryptNaClSodiumAuthHmacsha256Stream *stream) {
564 197           SV *sv = newSV(0);
565 197           SV *obj = newRV_noinc(sv);
566             #ifdef USE_ITHREADS
567             MAGIC *mg;
568             #endif
569              
570 197           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::auth::hmacsha256stream", 0));
571              
572             #ifdef USE_ITHREADS
573             mg =
574             #endif
575 197           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_auth_hmacsha256, (const char *)stream, 0);
576              
577             #if defined(USE_ITHREADS) && defined(MGf_DUP)
578             mg->mg_flags |= MGf_DUP;
579             #endif
580              
581 197           return obj;
582             }
583              
584 643           static CryptNaClSodiumAuthHmacsha256Stream* GetAuthHmacsha256Stream(pTHX_ SV* sv)
585             {
586             MAGIC *mg;
587              
588 643 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::auth::hmacsha256stream"))
589 0           croak("Not a reference to a Crypt::NaCl::Sodium::auth::hmacsha256stream object");
590              
591 643 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
592 643 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_auth_hmacsha256) {
    50          
593 643           return (CryptNaClSodiumAuthHmacsha256Stream *)mg->mg_ptr;
594             }
595             }
596              
597 0           croak("Failed to get Crypt::NaCl::Sodium::auth::hmacsha256stream pointer");
598             return (CryptNaClSodiumAuthHmacsha256Stream*)0; /* some compilers insist on a return value */
599             }
600              
601              
602 197           static SV * AuthHmacsha512Stream2SV(pTHX_ CryptNaClSodiumAuthHmacsha512Stream *stream) {
603 197           SV *sv = newSV(0);
604 197           SV *obj = newRV_noinc(sv);
605             #ifdef USE_ITHREADS
606             MAGIC *mg;
607             #endif
608              
609 197           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::auth::hmacsha512stream", 0));
610              
611             #ifdef USE_ITHREADS
612             mg =
613             #endif
614 197           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_auth_hmacsha512, (const char *)stream, 0);
615              
616             #if defined(USE_ITHREADS) && defined(MGf_DUP)
617             mg->mg_flags |= MGf_DUP;
618             #endif
619              
620 197           return obj;
621             }
622              
623 643           static CryptNaClSodiumAuthHmacsha512Stream* GetAuthHmacsha512Stream(pTHX_ SV* sv)
624             {
625             MAGIC *mg;
626              
627 643 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::auth::hmacsha512stream"))
628 0           croak("Not a reference to a Crypt::NaCl::Sodium::auth::hmacsha512stream object");
629              
630 643 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
631 643 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_auth_hmacsha512) {
    50          
632 643           return (CryptNaClSodiumAuthHmacsha512Stream *)mg->mg_ptr;
633             }
634             }
635              
636 0           croak("Failed to get Crypt::NaCl::Sodium::auth::hmacsha512stream pointer");
637             return (CryptNaClSodiumAuthHmacsha512Stream*)0; /* some compilers insist on a return value */
638             }
639              
640              
641 199           static SV * AuthHmacsha512256Stream2SV(pTHX_ CryptNaClSodiumAuthHmacsha512256Stream *stream) {
642 199           SV *sv = newSV(0);
643 199           SV *obj = newRV_noinc(sv);
644             #ifdef USE_ITHREADS
645             MAGIC *mg;
646             #endif
647              
648 199           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::auth::hmacsha512256stream", 0));
649              
650             #ifdef USE_ITHREADS
651             mg =
652             #endif
653 199           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_auth_hmacsha512256, (const char *)stream, 0);
654              
655             #if defined(USE_ITHREADS) && defined(MGf_DUP)
656             mg->mg_flags |= MGf_DUP;
657             #endif
658              
659 199           return obj;
660             }
661              
662 675           static CryptNaClSodiumAuthHmacsha512256Stream* GetAuthHmacsha512256Stream(pTHX_ SV* sv)
663             {
664             MAGIC *mg;
665              
666 675 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::auth::hmacsha512256stream"))
667 0           croak("Not a reference to a Crypt::NaCl::Sodium::auth::hmacsha512256stream object");
668              
669 675 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
670 675 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_auth_hmacsha512256) {
    50          
671 675           return (CryptNaClSodiumAuthHmacsha512256Stream *)mg->mg_ptr;
672             }
673             }
674              
675 0           croak("Failed to get Crypt::NaCl::Sodium::auth::hmacsha512256stream pointer");
676             return (CryptNaClSodiumAuthHmacsha512256Stream*)0; /* some compilers insist on a return value */
677             }
678              
679              
680 3           static SV * OnetimeauthStream2SV(pTHX_ CryptNaClSodiumOnetimeauthStream *stream) {
681 3           SV *sv = newSV(0);
682 3           SV *obj = newRV_noinc(sv);
683             #ifdef USE_ITHREADS
684             MAGIC *mg;
685             #endif
686              
687 3           sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::onetimeauth::stream", 0));
688              
689             #ifdef USE_ITHREADS
690             mg =
691             #endif
692 3           sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_onetimeauth, (const char *)stream, 0);
693              
694             #if defined(USE_ITHREADS) && defined(MGf_DUP)
695             mg->mg_flags |= MGf_DUP;
696             #endif
697              
698 3           return obj;
699             }
700              
701 32           static CryptNaClSodiumOnetimeauthStream* GetOnetimeauthStream(pTHX_ SV* sv)
702             {
703             MAGIC *mg;
704              
705 32 50         if (!sv_derived_from(sv, "Crypt::NaCl::Sodium::onetimeauth::stream"))
706 0           croak("Not a reference to a Crypt::NaCl::Sodium::onetimeauth::stream object");
707              
708 32 50         for (mg = SvMAGIC(SvRV(sv)); mg; mg = mg->mg_moremagic) {
709 32 50         if (mg->mg_type == PERL_MAGIC_ext && mg->mg_virtual == &vtbl_onetimeauth) {
    50          
710 32           return (CryptNaClSodiumOnetimeauthStream *)mg->mg_ptr;
711             }
712             }
713              
714 0           croak("Failed to get Crypt::NaCl::Sodium::onetimeauth::stream pointer");
715             return (CryptNaClSodiumOnetimeauthStream*)0; /* some compilers insist on a return value */
716             }
717              
718              
719             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium
720              
721             BOOT:
722             {
723             /* Initialise library */
724 54 50         if ( sodium_init() == -1 )
725             {
726 0           croak("Failed to initialze library");
727             }
728             }
729              
730             PROTOTYPES: ENABLE
731              
732             const char *
733             sodium_version_string()
734              
735             SV *
736             add(left, right)
737             SV * left
738             SV * right
739             PREINIT:
740             unsigned char * copy;
741             INIT:
742             unsigned char * left_buf;
743             unsigned char * right_buf;
744             STRLEN copy_len;
745             STRLEN left_len;
746             STRLEN right_len;
747             CODE:
748             {
749 1024           left_buf = (unsigned char *)SvPV(left, left_len);
750 1024           right_buf = (unsigned char *)SvPV(right, right_len);
751 1024 50         if (right_len > left_len) {
752 0           croak("You must have a RHS less than or equal in length to the LHS");
753             }
754 1024           copy = sodium_malloc(left_len + 1);
755 1024 50         if (copy == NULL) {
756 0           croak("Could not allocate memory");
757             }
758              
759 1024           strcpy(copy, left_buf);
760              
761 1024           sodium_add(copy, right_buf, right_len);
762 1024           RETVAL = newSVpvn((const char * const)copy, left_len);
763             }
764             OUTPUT:
765             RETVAL
766             CLEANUP:
767 1024           sodium_free(copy);
768              
769             void
770             has_aes128ctr()
771             PPCODE:
772             {
773             #ifdef AES128CTR_IS_AVAILABLE
774             XSRETURN_YES;
775             #else
776 1           XSRETURN_NO;
777             #endif
778             }
779              
780             void
781             memcmp(left, right, length = 0)
782             SV * left
783             SV * right
784             unsigned long length
785             INIT:
786             unsigned char * left_buf;
787             unsigned char * right_buf;
788             STRLEN left_len;
789             STRLEN right_len;
790             PPCODE:
791             {
792 1005 50         if ( GIMME_V == G_VOID ) {
793 0           XSRETURN_EMPTY;
794             }
795              
796 1005           left_buf = (unsigned char *)SvPV(left, left_len);
797 1005           right_buf = (unsigned char *)SvPV(right, right_len);
798 1005 100         if ( length == 0 ) {
799 2 100         if ( left_len != right_len ) {
800 1           croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
801             }
802 1           length = left_len;
803             } else {
804 1003 100         if ( length > left_len ) {
805 1           croak("First argument is shorter then requested length");
806             }
807 1002 100         else if ( length > right_len ) {
808 1           croak("Second argument is shorter then requested length");
809             }
810             }
811              
812 1002 100         if ( sodium_memcmp(left_buf, right_buf, length) == 0 ) {
813 1           XSRETURN_YES;
814             } else {
815 1001           XSRETURN_NO;
816             }
817             }
818              
819             void
820             compare(left, right, length = 0)
821             SV * left
822             SV * right
823             unsigned long length
824             INIT:
825             unsigned char * left_buf;
826             unsigned char * right_buf;
827             STRLEN left_len;
828             STRLEN right_len;
829             PPCODE:
830             {
831 2004 50         if ( GIMME_V == G_VOID ) {
832 0           XSRETURN_EMPTY;
833             }
834              
835 2004           left_buf = (unsigned char *)SvPV(left, left_len);
836 2004           right_buf = (unsigned char *)SvPV(right, right_len);
837 2004 100         if ( length == 0 ) {
838 1 50         if ( left_len != right_len ) {
839 1           croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
840             }
841 0           length = left_len;
842             } else {
843 2003 100         if ( length > left_len ) {
844 1           croak("First argument is shorter then requested length");
845             }
846 2002 100         else if ( length > right_len ) {
847 1           croak("Second argument is shorter then requested length");
848             }
849             }
850              
851 2001           XSRETURN_IV( sodium_compare(left_buf, right_buf, length) );
852             }
853              
854             void
855             increment(...)
856             INIT:
857             unsigned char * number_buf;
858             STRLEN len;
859             unsigned int i;
860             PPCODE:
861             {
862 10 100         for ( i = 0; i < items; i++ ) {
863 5 50         if (sv_derived_from(ST(i), "Data::BytesLocker")) {
864 0           croak("This function does not handle BytesLocker objects");
865             }
866 5           number_buf = (unsigned char *)SvPV(ST(i), len);
867              
868 5           sodium_increment(number_buf, len);
869             }
870 5           XSRETURN_EMPTY;
871             }
872              
873             void
874             memzero(...)
875             INIT:
876             unsigned char * buf;
877             STRLEN len;
878             unsigned int i;
879             PPCODE:
880             {
881 3 100         for ( i = 0; i < items; i++ ) {
882 2           buf = (unsigned char *)SvPV_force(ST(i), len);
883 2           sodium_memzero( buf, len);
884             }
885 1           XSRETURN_YES;
886             }
887              
888             SV *
889             random_number(...)
890             INIT:
891             unsigned int num;
892             CODE:
893             {
894 122791 100         if ( items == 1 ) {
895 122711           unsigned int upper_bound = (unsigned int)SvUV(ST(0));
896              
897 122711           num = randombytes_uniform(upper_bound);
898             }
899             else {
900 80           num = randombytes_random();
901             }
902              
903 122791           RETVAL = newSVuv(num);
904             }
905             OUTPUT:
906             RETVAL
907              
908             SV *
909             random_bytes(length)
910             SV * length
911             INIT:
912             size_t len;
913             DataBytesLocker *bl;
914             CODE:
915             {
916 34195           len = (size_t)SvUV(length);
917 34195 100         if ( len < 1 ) {
918 1           croak("Invalid length");
919             };
920              
921 34194           bl = InitDataBytesLocker(aTHX_ len);
922              
923 34194           randombytes_buf( bl->bytes, len );
924              
925 34194           RETVAL = DataBytesLocker2SV(aTHX_ bl);
926             }
927             OUTPUT:
928             RETVAL
929              
930              
931             SV *
932             bin2hex(bin_sv)
933             SV * bin_sv
934             PREINIT:
935             char * hex;
936             unsigned char * bin;
937             size_t hex_len;
938             STRLEN bin_len;
939             CODE:
940 5541           bin = (unsigned char *)SvPV(bin_sv, bin_len);
941              
942 5541 50         if ( bin_len > SIZE_MAX / 2 ) { /* avoid overflow */
943 0           croak("Binary data provided too large (will cause hex_len > SIZE_MAX)");
944             }
945 5541           hex_len = bin_len * 2;
946 5541           hex = sodium_malloc(hex_len + 1);
947 5541 50         if ( hex == NULL ) {
948 0           croak("Could not allocate memory");
949             }
950 5541           sodium_bin2hex(hex, hex_len + 1, bin, bin_len);
951              
952 5541           RETVAL = newSVpvn((const char * const)hex, hex_len);
953             OUTPUT:
954             RETVAL
955             CLEANUP:
956 5541           sodium_free(hex);
957              
958              
959             SV *
960             hex2bin(hex_sv, ...)
961             SV * hex_sv
962             PREINIT:
963 5682           size_t hex_len = 0;
964 5682           size_t bin_len = 0;
965 5682           size_t bin_max_len = 0;
966 5682           int i = 0;
967 5682           STRLEN keylen = 0;
968 5682           char * hex = NULL;
969 5682           char * ignore = NULL;
970 5682           char * key = NULL;
971 5682           const char *hex_end = NULL;
972 5682           unsigned char * bin = NULL;
973              
974             /* idiot check our hex string and turn it into a C string */
975 5682 50         if (SvOK(hex_sv) && SvPOK(hex_sv)) {
    50          
976 5682           hex = SvPV(hex_sv, hex_len);
977 5682 100         if (hex_len == 0) {
978 156           XSRETURN_PV("");
979             }
980             } else {
981 0           croak("A hex string must be provided");
982             }
983             CODE:
984 5526 100         if (items > 1) {
985 7 50         if ((items + 1) % 2 != 0) {
986 0           croak("Invalid number of arguments");
987             }
988 15 100         for (i = 1; i < items; i += 2) {
989 8 50         if (!SvOK(ST(i)) || !SvPOK(ST(i)))
    50          
990 0           continue;
991 8           key = SvPV(ST(i), keylen);
992 8 100         if (keylen == 6 && strnEQ(key, "ignore", 6)) {
    50          
993 4 50         if (SvOK(ST(i + 1)) && SvPOK(ST(i + 1))) {
    50          
994 4           ignore = SvPV(ST(i + 1), keylen);
995 4 50         if (keylen < 1 && ignore != NULL) {
    0          
996 0           ignore = NULL;
997             }
998             }
999 4 50         } else if (keylen == 7 && strnEQ(key, "max_len", 7)) {
    50          
1000 4 50         if (SvOK(ST(i + 1)) && (SvIOK(ST(i + 1)) || SvUOK(ST(i + 1)))) {
    50          
    0          
1001 4           bin_max_len = SvUV(ST(i + 1));
1002             }
1003             else {
1004 0           croak("Invalid max_len. Must be an integer > 0.");
1005             }
1006             }
1007             }
1008             }
1009              
1010 5526 100         size_t max_bin_size = (ignore == NULL) ? (hex_len / 2) : hex_len;
1011              
1012             /* ensure our binary string has enough space */
1013 5526           bin = (unsigned char *) sodium_malloc(max_bin_size + 1);
1014 5526 50         if (bin == NULL) {
1015 0           croak("Could not allocate memory");
1016             }
1017              
1018 5526           memset(bin, '\0', max_bin_size + 1);
1019              
1020 5526           int status = sodium_hex2bin(bin, max_bin_size, hex, hex_len, ignore, &bin_len, &hex_end);
1021              
1022             /* If the call was successful, truncate to max_len if user requested it */
1023 5526 50         if (status == 0) {
1024 5526 100         if (bin_max_len > 0 && bin_max_len < bin_len) {
    100          
1025 2           bin_len = bin_max_len;
1026             }
1027 5526           RETVAL = newSVpvn((const char *)bin, bin_len);
1028             } else {
1029             /* Handle actual errors (invalid hex, etc.) */
1030 0           RETVAL = &PL_sv_undef;
1031             }
1032              
1033             OUTPUT:
1034             RETVAL
1035             CLEANUP:
1036 5526 50         if (bin != NULL) sodium_free(bin);
1037              
1038             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::secretbox
1039              
1040             PROTOTYPES: DISABLE
1041              
1042             unsigned int
1043             NONCEBYTES(...)
1044             CODE:
1045 1 50         RETVAL = crypto_secretbox_NONCEBYTES;
1046             OUTPUT:
1047             RETVAL
1048              
1049             unsigned int
1050             KEYBYTES(...)
1051             CODE:
1052 1 50         RETVAL = crypto_secretbox_KEYBYTES;
1053             OUTPUT:
1054             RETVAL
1055              
1056             unsigned int
1057             MACBYTES(...)
1058             CODE:
1059 6 100         RETVAL = crypto_secretbox_MACBYTES;
1060             OUTPUT:
1061             RETVAL
1062              
1063             PROTOTYPES: ENABLE
1064              
1065             SV *
1066             keygen(self)
1067             SV * self
1068             INIT:
1069             DataBytesLocker *bl;
1070             CODE:
1071             {
1072             PERL_UNUSED_VAR(self);
1073              
1074 6           bl = InitDataBytesLocker(aTHX_ crypto_secretbox_KEYBYTES);
1075              
1076 6           randombytes_buf(bl->bytes, bl->length);
1077              
1078 6           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1079             }
1080             OUTPUT:
1081             RETVAL
1082              
1083             SV *
1084             nonce(self, ...)
1085             SV * self
1086             PROTOTYPE: $;$
1087             INIT:
1088             DataBytesLocker *bl;
1089             CODE:
1090             PERL_UNUSED_VAR(self);
1091              
1092 5 50         if ( items > 2 ) {
1093 0           croak("Invalid number of arguments");
1094             }
1095              
1096 5 50         if (items == 2 ) {
1097 0 0         if ( SvOK(ST(1)) ) {
1098             STRLEN prev_nonce_len;
1099 0           unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
1100              
1101 0 0         if ( prev_nonce_len > crypto_secretbox_NONCEBYTES ) {
1102 0           croak("Base nonce too long");
1103             }
1104              
1105 0           bl = InitDataBytesLocker(aTHX_ crypto_secretbox_NONCEBYTES);
1106 0           memcpy(bl->bytes, prev_nonce, prev_nonce_len);
1107 0           sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
1108             }
1109             else {
1110 0           croak("Base nonce invalid");
1111             }
1112             }
1113             else {
1114 5           bl = InitDataBytesLocker(aTHX_ crypto_secretbox_NONCEBYTES);
1115 5           randombytes_buf(bl->bytes, bl->length);
1116             }
1117 5           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1118             OUTPUT:
1119             RETVAL
1120              
1121              
1122              
1123             void
1124             encrypt(self, msg, nonce, key)
1125             SV * self
1126             SV * msg
1127             SV * nonce
1128             SV * key
1129             PROTOTYPE: $$$$
1130             INIT:
1131             STRLEN msg_len;
1132             STRLEN nonce_len;
1133             STRLEN key_len;
1134             STRLEN enc_len;
1135             unsigned char * msg_buf;
1136             unsigned char * nonce_buf;
1137             unsigned char * key_buf;
1138             DataBytesLocker *bl;
1139             PPCODE:
1140             {
1141             PERL_UNUSED_VAR(self);
1142              
1143 10 50         if ( GIMME_V == G_VOID ) {
1144 0           XSRETURN_EMPTY;
1145             }
1146              
1147 10           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
1148 10 50         if ( nonce_len != crypto_secretbox_NONCEBYTES ) {
1149 0           croak("Invalid nonce");
1150             }
1151              
1152 10           key_buf = (unsigned char *)SvPV(key, key_len);
1153 10 50         if ( key_len != crypto_secretbox_KEYBYTES ) {
1154 0           croak("Invalid key");
1155             }
1156              
1157 10           msg_buf = (unsigned char *)SvPV(msg, msg_len);
1158              
1159             /* detached mode */
1160 10 100         if ( GIMME_V == G_ARRAY ) {
1161             DataBytesLocker *bl_mac;
1162              
1163 5           bl = InitDataBytesLocker(aTHX_ msg_len);
1164 5           bl_mac = InitDataBytesLocker(aTHX_ crypto_secretbox_MACBYTES);
1165              
1166 5           crypto_secretbox_detached( bl->bytes, bl_mac->bytes, (unsigned char *)msg_buf,
1167             (unsigned long long) msg_len, nonce_buf, key_buf);
1168 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl_mac) );
1169 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
1170 5           XSRETURN(2);
1171             }
1172             /* combined mode */
1173             else {
1174 5           enc_len = crypto_secretbox_MACBYTES + msg_len;
1175 5           bl = InitDataBytesLocker(aTHX_ enc_len);
1176 5           crypto_secretbox_easy( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf);
1177              
1178 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
1179 5           XSRETURN(1);
1180             }
1181             }
1182              
1183             void
1184             decrypt(self, ciphertext, nonce, key)
1185             SV * self
1186             SV * ciphertext
1187             SV * nonce
1188             SV * key
1189             PROTOTYPE: $$$$
1190             INIT:
1191             STRLEN msg_len;
1192             STRLEN nonce_len;
1193             STRLEN key_len;
1194             STRLEN enc_len;
1195             unsigned char * msg_buf;
1196             unsigned char * nonce_buf;
1197             unsigned char * key_buf;
1198             DataBytesLocker *bl;
1199             PPCODE:
1200             {
1201             PERL_UNUSED_VAR(self);
1202              
1203 5 50         if ( GIMME_V == G_VOID ) {
1204 0           XSRETURN_EMPTY;
1205             }
1206              
1207 5           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
1208 5 50         if ( nonce_len != crypto_secretbox_NONCEBYTES ) {
1209 0           croak("Invalid nonce");
1210             }
1211              
1212 5           key_buf = (unsigned char *)SvPV(key, key_len);
1213 5 50         if ( key_len != crypto_secretbox_KEYBYTES ) {
1214 0           croak("Invalid key");
1215             }
1216              
1217 5           msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
1218 5 50         if ( msg_len < crypto_secretbox_MACBYTES ) {
1219 0           croak("Invalid ciphertext");
1220             }
1221 5           enc_len = msg_len - crypto_secretbox_MACBYTES;
1222              
1223 5           bl = InitDataBytesLocker(aTHX_ enc_len);
1224 5 50         if ( crypto_secretbox_open_easy( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf) == 0 ) {
1225 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
1226 5           XSRETURN(1);
1227             }
1228             else {
1229 0           sodium_free(bl->bytes);
1230 0           Safefree(bl);
1231 0           croak("Message forged");
1232             }
1233             }
1234              
1235              
1236              
1237             void
1238             decrypt_detached(self, mac, ciphertext, nonce, key)
1239             SV * self
1240             SV * mac
1241             SV * ciphertext
1242             SV * nonce
1243             SV * key
1244             PROTOTYPE: $$$$
1245             INIT:
1246             STRLEN msg_len;
1247             STRLEN nonce_len;
1248             STRLEN key_len;
1249             STRLEN mac_len;
1250             unsigned char * msg_buf;
1251             unsigned char * nonce_buf;
1252             unsigned char * key_buf;
1253             unsigned char * mac_buf;
1254             DataBytesLocker *bl;
1255             PPCODE:
1256             {
1257             PERL_UNUSED_VAR(self);
1258              
1259 3 50         if ( GIMME_V == G_VOID ) {
1260 0           XSRETURN_EMPTY;
1261             }
1262              
1263 3           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
1264 3 50         if ( nonce_len != crypto_secretbox_NONCEBYTES ) {
1265 0           croak("Invalid nonce");
1266             }
1267              
1268 3           key_buf = (unsigned char *)SvPV(key, key_len);
1269 3 50         if ( key_len != crypto_secretbox_KEYBYTES ) {
1270 0           croak("Invalid key");
1271             }
1272              
1273 3           mac_buf = (unsigned char *)SvPV(mac, mac_len);
1274 3 50         if ( mac_len != crypto_secretbox_MACBYTES ) {
1275 0           croak("Invalid mac");
1276             }
1277              
1278 3           msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
1279              
1280 3           bl = InitDataBytesLocker(aTHX_ msg_len);
1281 3 50         if ( crypto_secretbox_open_detached( bl->bytes, msg_buf, mac_buf, msg_len, nonce_buf, key_buf) == 0 ) {
1282 3 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
1283 3           XSRETURN(1);
1284             }
1285             else {
1286 0           sodium_free(bl->bytes);
1287 0           Safefree(bl);
1288 0           croak("Message forged");
1289             }
1290             }
1291              
1292              
1293              
1294             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth
1295              
1296             PROTOTYPES: DISABLE
1297              
1298             unsigned int
1299             KEYBYTES(...)
1300             ALIAS:
1301             HMACSHA256_KEYBYTES = 1
1302             HMACSHA512_KEYBYTES = 2
1303             HMACSHA512256_KEYBYTES = 3
1304             CODE:
1305 5           switch(ix) {
1306 1           case 1:
1307 1           RETVAL = crypto_auth_hmacsha256_KEYBYTES;
1308 1           break;
1309 1           case 2:
1310 1           RETVAL = crypto_auth_hmacsha512_KEYBYTES;
1311 1           break;
1312 1           case 3:
1313 1           RETVAL = crypto_auth_hmacsha512256_KEYBYTES;
1314 1           break;
1315 2           default:
1316 2           RETVAL = crypto_auth_KEYBYTES;
1317             }
1318             OUTPUT:
1319             RETVAL
1320              
1321             unsigned int
1322             BYTES(...)
1323             ALIAS:
1324             HMACSHA256_BYTES = 1
1325             HMACSHA512_BYTES = 2
1326             HMACSHA512256_BYTES = 3
1327             CODE:
1328 20002           switch(ix) {
1329 1           case 1:
1330 1           RETVAL = crypto_auth_hmacsha256_BYTES;
1331 1           break;
1332 10000           case 2:
1333 10000           RETVAL = crypto_auth_hmacsha512_BYTES;
1334 10000           break;
1335 1           case 3:
1336 1           RETVAL = crypto_auth_hmacsha512256_BYTES;
1337 1           break;
1338 10000           default:
1339 10000           RETVAL = crypto_auth_BYTES;
1340             }
1341             OUTPUT:
1342             RETVAL
1343              
1344             PROTOTYPES: ENABLE
1345              
1346             SV *
1347             keygen(self)
1348             SV * self
1349             ALIAS:
1350             hmacsha256_keygen = 1
1351             hmacsha512_keygen = 2
1352             hmacsha512256_keygen = 3
1353             INIT:
1354             DataBytesLocker *bl;
1355             unsigned int key_size;
1356             CODE:
1357             {
1358             PERL_UNUSED_VAR(self);
1359              
1360 20009           switch(ix) {
1361 2           case 1:
1362 2           key_size = crypto_auth_hmacsha256_KEYBYTES;
1363 2           break;
1364 10002           case 2:
1365 10002           key_size = crypto_auth_hmacsha512_KEYBYTES;
1366 10002           break;
1367 2           case 3:
1368 2           key_size = crypto_auth_hmacsha512256_KEYBYTES;
1369 2           break;
1370 10003           default:
1371 10003           key_size = crypto_auth_KEYBYTES;
1372             }
1373 20009           bl = InitDataBytesLocker(aTHX_ key_size);
1374 20009           randombytes_buf(bl->bytes, key_size);
1375 20009           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1376             }
1377             OUTPUT:
1378             RETVAL
1379              
1380             SV *
1381             mac(self, msg, key)
1382             SV * self
1383             SV * msg
1384             SV * key
1385             PROTOTYPE: $$$
1386             ALIAS:
1387             hmacsha256 = 1
1388             hmacsha512 = 2
1389             hmacsha512256 = 3
1390             INIT:
1391             STRLEN msg_len;
1392             STRLEN key_len;
1393             unsigned char * msg_buf;
1394             unsigned char * key_buf;
1395             unsigned int mac_size;
1396             unsigned int key_size;
1397             int (*mac_function)(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *);
1398             DataBytesLocker *bl;
1399             CODE:
1400             {
1401             PERL_UNUSED_VAR(self);
1402              
1403 20013 50         if ( GIMME_V == G_VOID ) {
1404 0           XSRETURN_EMPTY;
1405             }
1406              
1407 20013           switch(ix) {
1408 4           case 1:
1409 4           mac_size = crypto_auth_hmacsha256_BYTES;
1410 4           key_size = crypto_auth_hmacsha256_KEYBYTES;
1411 4           mac_function = &crypto_auth_hmacsha256;
1412 4           break;
1413 10003           case 2:
1414 10003           mac_size = crypto_auth_hmacsha512_BYTES;
1415 10003           key_size = crypto_auth_hmacsha512_KEYBYTES;
1416 10003           mac_function = &crypto_auth_hmacsha512;
1417 10003           break;
1418 2           case 3:
1419 2           mac_size = crypto_auth_hmacsha512256_BYTES;
1420 2           key_size = crypto_auth_hmacsha512256_KEYBYTES;
1421 2           mac_function = &crypto_auth_hmacsha512256;
1422 2           break;
1423 10004           default:
1424 10004           mac_size = crypto_auth_BYTES;
1425 10004           key_size = crypto_auth_KEYBYTES;
1426 10004           mac_function = &crypto_auth;
1427             }
1428              
1429 20013           key_buf = (unsigned char *)SvPV(key, key_len);
1430 20013 50         if ( key_len != key_size ) {
1431 0           croak("Invalid key");
1432             }
1433              
1434 20013           msg_buf = (unsigned char *)SvPV(msg, msg_len);
1435              
1436 20013           bl = InitDataBytesLocker(aTHX_ mac_size);
1437 20013           (*mac_function)( bl->bytes, msg_buf, msg_len, key_buf);
1438              
1439 20013           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1440             }
1441             OUTPUT:
1442             RETVAL
1443              
1444             void
1445             verify(self, mac, msg, key)
1446             SV * self
1447             SV * mac
1448             SV * msg
1449             SV * key
1450             PROTOTYPE: $$$$
1451             INIT:
1452             STRLEN msg_len;
1453             STRLEN key_len;
1454             STRLEN mac_len;
1455             unsigned char * msg_buf;
1456             unsigned char * mac_buf;
1457             unsigned char * key_buf;
1458             PPCODE:
1459             {
1460             PERL_UNUSED_VAR(self);
1461              
1462 30002 50         if ( GIMME_V == G_VOID ) {
1463 0           XSRETURN_EMPTY;
1464             }
1465              
1466 30002           mac_buf = (unsigned char *)SvPV(mac, mac_len);
1467 30002 50         if ( mac_len != crypto_auth_BYTES ) {
1468 0           croak("Invalid mac");
1469             }
1470              
1471 30002           key_buf = (unsigned char *)SvPV(key, key_len);
1472 30002 50         if ( key_len != crypto_auth_KEYBYTES ) {
1473 0           croak("Invalid key");
1474             }
1475              
1476 30002           msg_buf = (unsigned char *)SvPV(msg, msg_len);
1477              
1478 30002 100         if ( crypto_auth_verify( mac_buf, msg_buf, msg_len, key_buf) == 0 ) {
1479 10004           XSRETURN_YES;
1480             }
1481             else {
1482 19998           XSRETURN_NO;
1483             }
1484             }
1485              
1486              
1487             SV *
1488             hmacsha256_verify(self, mac, msg, key)
1489             SV * self
1490             SV * mac
1491             SV * msg
1492             SV * key
1493             PROTOTYPE: $$$$
1494             ALIAS:
1495             hmacsha512_verify = 2
1496             hmacsha512256_verify = 3
1497             INIT:
1498             STRLEN msg_len;
1499             STRLEN key_len;
1500             STRLEN mac_len;
1501             unsigned char * msg_buf;
1502             unsigned char * mac_buf;
1503             unsigned char * key_buf;
1504 30593           unsigned char * expected = NULL;
1505             unsigned int mac_size;
1506             unsigned int key_size;
1507 30593           int free_expected = 0;
1508             int (*verify_function)(const unsigned char *, const unsigned char *, unsigned long long, const unsigned char *);
1509             CODE:
1510             {
1511             PERL_UNUSED_VAR(self);
1512              
1513 30593 50         if ( GIMME_V == G_VOID ) {
1514 0           XSRETURN_EMPTY;
1515             }
1516              
1517 30593           switch(ix) {
1518 30195           case 2:
1519 30195           mac_size = crypto_auth_hmacsha512_BYTES;
1520 30195           key_size = crypto_auth_hmacsha512_KEYBYTES;
1521 30195           verify_function = &crypto_auth_hmacsha512_verify;
1522 30195           break;
1523 199           case 3:
1524 199           mac_size = crypto_auth_hmacsha512256_BYTES;
1525 199           key_size = crypto_auth_hmacsha512256_KEYBYTES;
1526 199           verify_function = &crypto_auth_hmacsha512256_verify;
1527 199           break;
1528 199           default:
1529 199           mac_size = crypto_auth_hmacsha256_BYTES;
1530 199           key_size = crypto_auth_hmacsha256_KEYBYTES;
1531 199           verify_function = &crypto_auth_hmacsha256_verify;
1532             }
1533              
1534 30593           mac_buf = (unsigned char *)SvPV(mac, mac_len);
1535 30593 50         if ( mac_len != mac_size ) {
1536 0           croak("Invalid mac");
1537             }
1538              
1539 30593           msg_buf = (unsigned char *)SvPV(msg, msg_len);
1540              
1541 30593           key_buf = (unsigned char *)SvPV(key, key_len);
1542              
1543 30593 100         if ( key_len != key_size ) {
1544 582           expected = sodium_malloc(mac_size+1);
1545 582 50         if ( expected == NULL ) {
1546 0           croak("Could not allocate memory");
1547             }
1548 582           free_expected = 1;
1549              
1550 582           switch(ix) {
1551 194           case 2:
1552             {
1553             crypto_auth_hmacsha512_state state_exp;
1554 194           crypto_auth_hmacsha512_init(&state_exp, key_buf, key_len);
1555 194           crypto_auth_hmacsha512_update(&state_exp, msg_buf, msg_len);
1556 194           crypto_auth_hmacsha512_final(&state_exp, expected);
1557 194           break;
1558             }
1559 194           case 3:
1560             {
1561             crypto_auth_hmacsha512256_state state_exp;
1562 194           crypto_auth_hmacsha512256_init(&state_exp, key_buf, key_len);
1563 194           crypto_auth_hmacsha512256_update(&state_exp, msg_buf, msg_len);
1564 194           crypto_auth_hmacsha512256_final(&state_exp, expected);
1565 194           break;
1566             }
1567 194           default:
1568             {
1569             crypto_auth_hmacsha256_state state_exp;
1570 194           crypto_auth_hmacsha256_init(&state_exp, key_buf, key_len);
1571 194           crypto_auth_hmacsha256_update(&state_exp, msg_buf, msg_len);
1572 194           crypto_auth_hmacsha256_final(&state_exp, expected);
1573             }
1574             }
1575              
1576 1164           RETVAL = sodium_memcmp( mac_buf, expected, mac_size ) == 0
1577 582 50         ? &PL_sv_yes : &PL_sv_no;
1578             } else {
1579 60022           RETVAL = (*verify_function)( mac_buf, msg_buf, msg_len, key_buf ) == 0
1580 30011 100         ? &PL_sv_yes : &PL_sv_no;
1581             }
1582             }
1583             OUTPUT:
1584             RETVAL
1585             CLEANUP:
1586 30593 100         if ( free_expected ) {
1587 582           sodium_free(expected);
1588             }
1589              
1590             void
1591             hmacsha256_init(self, key)
1592             SV * self
1593             SV * key
1594             PROTOTYPE: $$
1595             INIT:
1596             STRLEN key_len;
1597             unsigned char * key_buf;
1598             CryptNaClSodiumAuthHmacsha256Stream *stream;
1599             PPCODE:
1600             {
1601             PERL_UNUSED_VAR(self);
1602              
1603 197           key_buf = (unsigned char *)SvPV(key, key_len);
1604              
1605 197           Newx(stream, 1, CryptNaClSodiumAuthHmacsha256Stream);
1606 197           stream->state = sodium_malloc(sizeof(crypto_auth_hmacsha256_state));
1607 197 50         if ( stream->state == NULL ) {
1608 0           croak("Could not allocate memory");
1609             }
1610              
1611 197           crypto_auth_hmacsha256_init(stream->state, key_buf, key_len);
1612              
1613 197           ST(0) = sv_2mortal(AuthHmacsha256Stream2SV(aTHX_ stream));
1614              
1615 197           XSRETURN(1);
1616             }
1617              
1618             void
1619             hmacsha512_init(self, key)
1620             SV * self
1621             SV * key
1622             PROTOTYPE: $$
1623             INIT:
1624             STRLEN key_len;
1625             unsigned char * key_buf;
1626             CryptNaClSodiumAuthHmacsha512Stream *stream;
1627             PPCODE:
1628             {
1629             PERL_UNUSED_VAR(self);
1630              
1631 197           key_buf = (unsigned char *)SvPV(key, key_len);
1632              
1633 197           Newx(stream, 1, CryptNaClSodiumAuthHmacsha512Stream);
1634 197           stream->state = sodium_malloc(sizeof(crypto_auth_hmacsha512_state));
1635 197 50         if ( stream->state == NULL ) {
1636 0           croak("Could not allocate memory");
1637             }
1638              
1639 197           crypto_auth_hmacsha512_init(stream->state, key_buf, key_len);
1640              
1641 197           ST(0) = sv_2mortal(AuthHmacsha512Stream2SV(aTHX_ stream));
1642              
1643 197           XSRETURN(1);
1644             }
1645              
1646              
1647             void
1648             hmacsha512256_init(self, key)
1649             SV * self
1650             SV * key
1651             PROTOTYPE: $$
1652             INIT:
1653             STRLEN key_len;
1654             unsigned char * key_buf;
1655             CryptNaClSodiumAuthHmacsha512256Stream *stream;
1656             PPCODE:
1657             {
1658             PERL_UNUSED_VAR(self);
1659              
1660 199           key_buf = (unsigned char *)SvPV(key, key_len);
1661              
1662 199           Newx(stream, 1, CryptNaClSodiumAuthHmacsha512256Stream);
1663 199           stream->state = sodium_malloc(sizeof(crypto_auth_hmacsha512256_state));
1664 199 50         if ( stream->state == NULL ) {
1665 0           croak("Could not allocate memory");
1666             }
1667              
1668 199           crypto_auth_hmacsha512256_init(stream->state, key_buf, key_len);
1669              
1670 199           ST(0) = sv_2mortal(AuthHmacsha512256Stream2SV(aTHX_ stream));
1671              
1672 199           XSRETURN(1);
1673             }
1674              
1675             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth::hmacsha256stream
1676              
1677             void
1678             clone(self)
1679             SV * self
1680             PREINIT:
1681 0           CryptNaClSodiumAuthHmacsha256Stream* cur_stream = GetAuthHmacsha256Stream(aTHX_ self);
1682             INIT:
1683             CryptNaClSodiumAuthHmacsha256Stream* new_stream;
1684             PPCODE:
1685             {
1686 0 0         CLONESTATE(CryptNaClSodiumAuthHmacsha256Stream, auth_hmacsha256, 0, ((void)0))
    0          
1687 0           ST(0) = sv_2mortal(AuthHmacsha256Stream2SV(aTHX_ new_stream));
1688 0           XSRETURN(1);
1689             }
1690              
1691              
1692             void
1693             update(self, ...)
1694             SV * self
1695             PREINIT:
1696 249           CryptNaClSodiumAuthHmacsha256Stream* stream = GetAuthHmacsha256Stream(aTHX_ self);
1697             INIT:
1698             STRLEN msg_len;
1699             unsigned char * msg_buf;
1700             int i;
1701             PPCODE:
1702             {
1703 498 100         for ( i = 1; i < items ; i++ ) {
1704 249           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
1705              
1706 249           crypto_auth_hmacsha256_update(stream->state, msg_buf, msg_len);
1707             }
1708              
1709 249           XSRETURN(1);
1710             }
1711              
1712              
1713             SV *
1714             final(self)
1715             SV * self
1716             PROTOTYPE: $
1717             PREINIT:
1718 197           CryptNaClSodiumAuthHmacsha256Stream* stream = GetAuthHmacsha256Stream(aTHX_ self);
1719             INIT:
1720             DataBytesLocker *bl;
1721             CODE:
1722             {
1723 197           bl = InitDataBytesLocker(aTHX_ crypto_auth_hmacsha256_BYTES);
1724              
1725 197           crypto_auth_hmacsha256_final(stream->state, bl->bytes);
1726              
1727 197           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1728             }
1729             OUTPUT:
1730             RETVAL
1731              
1732             void
1733             DESTROY(self)
1734             SV * self
1735             PREINIT:
1736 197           CryptNaClSodiumAuthHmacsha256Stream* stream = GetAuthHmacsha256Stream(aTHX_ self);
1737             PPCODE:
1738             {
1739 197           sodium_free( stream->state );
1740 197           Safefree(stream);
1741             }
1742              
1743             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth::hmacsha512stream
1744              
1745             void
1746             clone(self)
1747             SV * self
1748             PREINIT:
1749 0           CryptNaClSodiumAuthHmacsha512Stream* cur_stream = GetAuthHmacsha512Stream(aTHX_ self);
1750             INIT:
1751             CryptNaClSodiumAuthHmacsha512Stream* new_stream;
1752             PPCODE:
1753             {
1754 0 0         CLONESTATE(CryptNaClSodiumAuthHmacsha512Stream, auth_hmacsha512, 0, ((void)0))
    0          
1755 0           ST(0) = sv_2mortal(AuthHmacsha512Stream2SV(aTHX_ new_stream));
1756 0           XSRETURN(1);
1757             }
1758              
1759              
1760             void
1761             update(self, ...)
1762             SV * self
1763             PREINIT:
1764 249           CryptNaClSodiumAuthHmacsha512Stream* stream = GetAuthHmacsha512Stream(aTHX_ self);
1765             INIT:
1766             STRLEN msg_len;
1767             unsigned char * msg_buf;
1768             int i;
1769             PPCODE:
1770             {
1771 498 100         for ( i = 1; i < items ; i++ ) {
1772 249           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
1773              
1774 249           crypto_auth_hmacsha512_update(stream->state, msg_buf, msg_len);
1775             }
1776              
1777 249           XSRETURN(1);
1778             }
1779              
1780             SV *
1781             final(self)
1782             SV * self
1783             PROTOTYPE: $
1784             PREINIT:
1785 197           CryptNaClSodiumAuthHmacsha512Stream* stream = GetAuthHmacsha512Stream(aTHX_ self);
1786             INIT:
1787             DataBytesLocker *bl;
1788             CODE:
1789             {
1790 197           bl = InitDataBytesLocker(aTHX_ crypto_auth_hmacsha512_BYTES);
1791              
1792 197           crypto_auth_hmacsha512_final(stream->state, bl->bytes);
1793              
1794 197           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1795             }
1796             OUTPUT:
1797             RETVAL
1798              
1799              
1800             void
1801             DESTROY(self)
1802             SV * self
1803             PREINIT:
1804 197           CryptNaClSodiumAuthHmacsha512Stream* stream = GetAuthHmacsha512Stream(aTHX_ self);
1805             PPCODE:
1806             {
1807 197           sodium_free( stream->state );
1808 197           Safefree(stream);
1809             }
1810              
1811              
1812             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::auth::hmacsha512256stream
1813              
1814             void
1815             clone(self)
1816             SV * self
1817             PREINIT:
1818 0           CryptNaClSodiumAuthHmacsha512256Stream* cur_stream = GetAuthHmacsha512256Stream(aTHX_ self);
1819             INIT:
1820             CryptNaClSodiumAuthHmacsha512256Stream* new_stream;
1821             PPCODE:
1822             {
1823 0 0         CLONESTATE(CryptNaClSodiumAuthHmacsha512256Stream, auth_hmacsha512256, 0, ((void)0))
    0          
1824 0           ST(0) = sv_2mortal(AuthHmacsha512256Stream2SV(aTHX_ new_stream));
1825 0           XSRETURN(1);
1826             }
1827              
1828              
1829             void
1830             update(self, ...)
1831             SV * self
1832             PREINIT:
1833 277           CryptNaClSodiumAuthHmacsha512256Stream* stream = GetAuthHmacsha512256Stream(aTHX_ self);
1834             INIT:
1835             STRLEN msg_len;
1836             unsigned char * msg_buf;
1837             int i;
1838             PPCODE:
1839             {
1840 554 100         for ( i = 1; i < items ; i++ ) {
1841 277           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
1842              
1843 277           crypto_auth_hmacsha512256_update(stream->state, msg_buf, msg_len);
1844             }
1845              
1846 277           XSRETURN(1);
1847             }
1848              
1849             SV *
1850             final(self)
1851             SV * self
1852             PROTOTYPE: $
1853             PREINIT:
1854 199           CryptNaClSodiumAuthHmacsha512256Stream* stream = GetAuthHmacsha512256Stream(aTHX_ self);
1855             INIT:
1856             DataBytesLocker *bl;
1857             CODE:
1858             {
1859 199           bl = InitDataBytesLocker(aTHX_ crypto_auth_hmacsha512256_BYTES);
1860              
1861 199           crypto_auth_hmacsha512256_final(stream->state, bl->bytes);
1862              
1863 199           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1864             }
1865             OUTPUT:
1866             RETVAL
1867              
1868              
1869             void
1870             DESTROY(self)
1871             SV * self
1872             PREINIT:
1873 199           CryptNaClSodiumAuthHmacsha512256Stream* stream = GetAuthHmacsha512256Stream(aTHX_ self);
1874             PPCODE:
1875             {
1876 199           sodium_free( stream->state );
1877 199           Safefree(stream);
1878             }
1879              
1880              
1881             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::aead
1882              
1883             PROTOTYPES: DISABLE
1884              
1885             unsigned int
1886             KEYBYTES(...)
1887             CODE:
1888 3 50         RETVAL = crypto_aead_chacha20poly1305_KEYBYTES;
1889             OUTPUT:
1890             RETVAL
1891              
1892             unsigned int
1893             AES256GCM_KEYBYTES(...)
1894             CODE:
1895             #if defined(AES256GCM_IS_AVAILABLE)
1896 384 100         RETVAL = crypto_aead_aes256gcm_KEYBYTES;
1897             #else
1898             croak("AES256-GCM is not supported by this CPU");
1899             #endif
1900             OUTPUT:
1901             RETVAL
1902              
1903             unsigned int
1904             AES256GCM_NPUBBYTES(...)
1905             CODE:
1906             #if defined(AES256GCM_IS_AVAILABLE)
1907 384 100         RETVAL = crypto_aead_aes256gcm_NPUBBYTES;
1908             #else
1909             croak("AES256-GCM is not supported by this CPU");
1910             #endif
1911             OUTPUT:
1912             RETVAL
1913              
1914             unsigned int
1915             AES256GCM_ABYTES(...)
1916             CODE:
1917             #if defined(AES256GCM_IS_AVAILABLE)
1918 1761 100         RETVAL = crypto_aead_aes256gcm_ABYTES;
1919             #else
1920             croak("AES256-GCM is not supported by this CPU");
1921             #endif
1922             OUTPUT:
1923             RETVAL
1924              
1925             unsigned int
1926             NPUBBYTES(...)
1927             CODE:
1928 2 100         RETVAL = crypto_aead_chacha20poly1305_NPUBBYTES;
1929             OUTPUT:
1930             RETVAL
1931              
1932             unsigned int
1933             IETF_NPUBBYTES(...)
1934             CODE:
1935 1 50         RETVAL = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
1936             OUTPUT:
1937             RETVAL
1938              
1939             unsigned int
1940             ABYTES(...)
1941             CODE:
1942 7 100         RETVAL = crypto_aead_chacha20poly1305_ABYTES;
1943             OUTPUT:
1944             RETVAL
1945              
1946             PROTOTYPES: ENABLE
1947              
1948             void
1949             aes256gcm_is_available(self)
1950             SV * self
1951             PPCODE:
1952             {
1953 1 50         if ( crypto_aead_aes256gcm_is_available() ) {
1954 1           XSRETURN_YES;
1955             }
1956 0           XSRETURN_NO;
1957             }
1958              
1959             SV *
1960             keygen(self)
1961             SV * self
1962             ALIAS:
1963             aes256gcm_keygen = 1
1964             INIT:
1965             unsigned int key_size;
1966             DataBytesLocker *bl;
1967             CODE:
1968             {
1969             PERL_UNUSED_VAR(self);
1970              
1971 3 50         switch(ix) {
1972 0           case 1:
1973             #if defined(AES256GCM_IS_AVAILABLE)
1974 0           key_size = crypto_aead_aes256gcm_KEYBYTES;
1975             #else
1976             croak("AES256-GCM is not supported by this CPU");
1977             #endif
1978 0           break;
1979 3           default:
1980 3           key_size = crypto_aead_chacha20poly1305_KEYBYTES;
1981             }
1982 3           bl = InitDataBytesLocker(aTHX_ key_size);
1983 3           randombytes_buf(bl->bytes, key_size);
1984 3           RETVAL = DataBytesLocker2SV(aTHX_ bl);
1985             }
1986             OUTPUT:
1987             RETVAL
1988              
1989             SV *
1990             nonce(self, ...)
1991             SV * self
1992             PROTOTYPE: $;$
1993             ALIAS:
1994             ietf_nonce = 1
1995             aes256gcm_nonce = 2
1996             INIT:
1997             unsigned int nonce_size;
1998             DataBytesLocker *bl;
1999             CODE:
2000             PERL_UNUSED_VAR(self);
2001              
2002 4           switch(ix) {
2003 0           case 1:
2004 0           nonce_size = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
2005 0           break;
2006 0           case 2:
2007             #if defined(AES256GCM_IS_AVAILABLE)
2008 0           nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
2009             #else
2010             croak("AES256-GCM is not supported by this CPU");
2011             #endif
2012 0           break;
2013 4           default:
2014 4           nonce_size = crypto_aead_chacha20poly1305_NPUBBYTES;
2015             }
2016              
2017 4 50         if ( items > 2 ) {
2018 0           croak("Invalid number of arguments");
2019             }
2020              
2021 4 50         if (items == 2 ) {
2022 0 0         if ( SvOK(ST(1)) ) {
2023             STRLEN prev_nonce_len;
2024 0           unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
2025              
2026 0 0         if ( prev_nonce_len > nonce_size ) {
2027 0           croak("Base nonce too long");
2028             }
2029              
2030 0           bl = InitDataBytesLocker(aTHX_ nonce_size);
2031 0           memcpy(bl->bytes, prev_nonce, prev_nonce_len);
2032 0           sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
2033             }
2034             else {
2035 0           croak("Base nonce invalid");
2036             }
2037             }
2038             else {
2039 4           bl = InitDataBytesLocker(aTHX_ nonce_size);
2040 4           randombytes_buf(bl->bytes, bl->length);
2041             }
2042 4           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2043             OUTPUT:
2044             RETVAL
2045              
2046             void
2047             encrypt(self, msg, adata, nonce, key)
2048             SV * self
2049             SV * msg
2050             SV * adata
2051             SV * nonce
2052             SV * key
2053             PROTOTYPE: $$$$$
2054             ALIAS:
2055             ietf_encrypt = 1
2056             aes256gcm_encrypt = 2
2057             INIT:
2058             STRLEN msg_len;
2059             STRLEN adata_len;
2060             STRLEN nonce_len;
2061             STRLEN key_len;
2062             STRLEN enc_len;
2063             unsigned char * msg_buf;
2064             unsigned char * adata_buf;
2065             unsigned char * nonce_buf;
2066             unsigned char * key_buf;
2067             unsigned int nonce_size;
2068             unsigned int adlen_size;
2069             unsigned int key_size;
2070             int (*encrypt_function)(unsigned char *, unsigned long long *, const unsigned char *, unsigned long long,
2071             const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *, const unsigned char *);
2072             DataBytesLocker *bl;
2073             PPCODE:
2074             {
2075             PERL_UNUSED_VAR(self);
2076              
2077 391 50         if ( GIMME_V == G_VOID ) {
2078 0           XSRETURN_EMPTY;
2079             }
2080              
2081 391           switch(ix) {
2082 2           case 1:
2083 2           nonce_size = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
2084 2           key_size = crypto_aead_chacha20poly1305_KEYBYTES;
2085 2           adlen_size = crypto_aead_chacha20poly1305_ABYTES;
2086 2           encrypt_function = &crypto_aead_chacha20poly1305_ietf_encrypt;
2087 2           break;
2088 383           case 2:
2089             #if defined(AES256GCM_IS_AVAILABLE)
2090 383           nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
2091 383           key_size = crypto_aead_aes256gcm_KEYBYTES;
2092 383           adlen_size = crypto_aead_aes256gcm_ABYTES;
2093 383           encrypt_function = &crypto_aead_aes256gcm_encrypt;
2094             #else
2095             croak("AES256-GCM is not supported by this CPU");
2096             #endif
2097 383           break;
2098 6           default:
2099 6           nonce_size = crypto_aead_chacha20poly1305_NPUBBYTES;
2100 6           key_size = crypto_aead_chacha20poly1305_KEYBYTES;
2101 6           adlen_size = crypto_aead_chacha20poly1305_ABYTES;
2102 6           encrypt_function = &crypto_aead_chacha20poly1305_encrypt;
2103             }
2104              
2105 391           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2106 391 50         if ( nonce_len != nonce_size ) {
2107 0           croak("Invalid nonce");
2108             }
2109              
2110 391           key_buf = (unsigned char *)SvPV(key, key_len);
2111 391 50         if ( key_len != key_size ) {
2112 0           croak("Invalid key");
2113             }
2114              
2115 391           msg_buf = (unsigned char *)SvPV(msg, msg_len);
2116              
2117 391           adata_buf = (unsigned char *)SvPV(adata, adata_len);
2118              
2119 391 50         if (msg_len > SIZE_MAX - adlen_size) {
2120 0           croak("Encrypted length exceeds system memory limit (size_t overflow)");
2121             }
2122 391           enc_len = msg_len + adlen_size;
2123 391           bl = InitDataBytesLocker(aTHX_ enc_len);
2124              
2125 391           (*encrypt_function)( bl->bytes, NULL, msg_buf, msg_len,
2126             adata_buf, adata_len, NULL, nonce_buf, key_buf);
2127              
2128 391           bl->bytes[enc_len] = '\0';
2129              
2130 391 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2131 391           XSRETURN(1);
2132             }
2133              
2134             void
2135             decrypt(self, msg, adata, nonce, key)
2136             SV * self
2137             SV * msg
2138             SV * adata
2139             SV * nonce
2140             SV * key
2141             PROTOTYPE: $$$$
2142             ALIAS:
2143             ietf_decrypt = 1
2144             aes256gcm_decrypt = 2
2145             INIT:
2146             STRLEN msg_len;
2147             STRLEN adata_len;
2148             STRLEN nonce_len;
2149             STRLEN key_len;
2150             STRLEN enc_len;
2151             unsigned char * msg_buf;
2152             unsigned char * adata_buf;
2153             unsigned char * nonce_buf;
2154             unsigned char * key_buf;
2155             unsigned int nonce_size;
2156             unsigned int adlen_size;
2157             unsigned int key_size;
2158             int (*decrypt_function)(unsigned char *, unsigned long long *, unsigned char *, const unsigned char *, unsigned long long,
2159             const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
2160             DataBytesLocker *bl;
2161             PPCODE:
2162             {
2163             PERL_UNUSED_VAR(self);
2164              
2165 1236 50         if ( GIMME_V == G_VOID ) {
2166 0           XSRETURN_EMPTY;
2167             }
2168              
2169 1236           switch(ix) {
2170 132           case 1:
2171 132           nonce_size = crypto_aead_chacha20poly1305_IETF_NPUBBYTES;
2172 132           key_size = crypto_aead_chacha20poly1305_KEYBYTES;
2173 132           adlen_size = crypto_aead_chacha20poly1305_ABYTES;
2174 132           decrypt_function = &crypto_aead_chacha20poly1305_ietf_decrypt;
2175 132           break;
2176 1072           case 2:
2177             #if defined(AES256GCM_IS_AVAILABLE)
2178 1072           nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
2179 1072           key_size = crypto_aead_aes256gcm_KEYBYTES;
2180 1072           adlen_size = crypto_aead_aes256gcm_ABYTES;
2181 1072           decrypt_function = &crypto_aead_aes256gcm_decrypt;
2182             #else
2183             croak("AES256-GCM is not supported by this CPU");
2184             #endif
2185 1072           break;
2186 32           default:
2187 32           nonce_size = crypto_aead_chacha20poly1305_NPUBBYTES;
2188 32           key_size = crypto_aead_chacha20poly1305_KEYBYTES;
2189 32           adlen_size = crypto_aead_chacha20poly1305_ABYTES;
2190 32           decrypt_function = &crypto_aead_chacha20poly1305_decrypt;
2191             }
2192              
2193 1236           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2194 1236 50         if ( nonce_len != nonce_size ) {
2195 0           croak("Invalid nonce");
2196             }
2197              
2198 1236           key_buf = (unsigned char *)SvPV(key, key_len);
2199 1236 50         if ( key_len != key_size ) {
2200 0           croak("Invalid key");
2201             }
2202              
2203 1236           msg_buf = (unsigned char *)SvPV(msg, msg_len);
2204              
2205 1236 100         if ( msg_len < adlen_size ) {
2206 383           croak("Invalid ciphertext");
2207             }
2208              
2209 853           adata_buf = (unsigned char *)SvPV(adata, adata_len);
2210              
2211 853           enc_len = msg_len - adlen_size;
2212 853           bl = InitDataBytesLocker(aTHX_ enc_len);
2213              
2214 853 100         if ( (*decrypt_function)( bl->bytes, NULL, NULL, msg_buf, msg_len, adata_buf, adata_len, nonce_buf, key_buf) == 0 ) {
2215              
2216 391           bl->bytes[enc_len] = '\0';
2217 391 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2218 391           XSRETURN(1);
2219             }
2220             else {
2221 462           sodium_free(bl->bytes);
2222 462           Safefree(bl);
2223 462           croak("Message forged");
2224             }
2225             }
2226              
2227             void
2228             aes256gcm_beforenm(self, key)
2229             SV * self
2230             SV * key
2231             PROTOTYPE: $;%
2232             INIT:
2233 384           STRLEN key_len = 0;
2234 384           unsigned char * key_buf = NULL;
2235             #if defined(AES256GCM_IS_AVAILABLE)
2236             CryptNaClSodiumAeadAes256gcmState *state;
2237             #endif
2238             PPCODE:
2239             {
2240             PERL_UNUSED_VAR(self);
2241             #if defined(AES256GCM_IS_AVAILABLE)
2242 384           key_buf = (unsigned char *)SvPV(key, key_len);
2243 384 50         if ( key_len != crypto_aead_aes256gcm_KEYBYTES ) {
2244 0           croak("Invalid key");
2245             }
2246              
2247 384           state = InitAeadAes256gcmState(aTHX_ key_buf);
2248              
2249 384           ST(0) = sv_2mortal(AeadAes256gcmState2SV(aTHX_ state));
2250              
2251 384           XSRETURN(1);
2252             #else
2253             croak("AES256-GCM is not supported by this CPU");
2254             #endif
2255             }
2256              
2257             void
2258             aes256gcm_encrypt_afternm(self, msg, adata, nonce, precalculated_key)
2259             SV * self
2260             SV * msg
2261             SV * adata
2262             SV * nonce
2263             SV * precalculated_key
2264             PROTOTYPE: $$$$$
2265             INIT:
2266             STRLEN msg_len;
2267             STRLEN adata_len;
2268             STRLEN nonce_len;
2269             STRLEN enc_len;
2270             unsigned char * msg_buf;
2271             unsigned char * adata_buf;
2272             unsigned char * nonce_buf;
2273             #if defined(AES256GCM_IS_AVAILABLE)
2274             CryptNaClSodiumAeadAes256gcmState * precal_key;
2275             #endif
2276             DataBytesLocker *bl;
2277             PPCODE:
2278             {
2279             PERL_UNUSED_VAR(self);
2280             #if defined(AES256GCM_IS_AVAILABLE)
2281              
2282 385 50         if ( GIMME_V == G_VOID ) {
2283 0           XSRETURN_EMPTY;
2284             }
2285              
2286 385           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2287 385 50         if ( nonce_len != crypto_aead_aes256gcm_NPUBBYTES ) {
2288 0           croak("Invalid nonce");
2289             }
2290              
2291 385           precal_key = GetAeadAes256gcmState(aTHX_ precalculated_key);
2292              
2293 385 100         if ( precal_key->locked ) {
2294 1           croak("Unlock AES256GCM precalculated key object before accessing the state");
2295             }
2296              
2297 384           msg_buf = (unsigned char *)SvPV(msg, msg_len);
2298              
2299 384           adata_buf = (unsigned char *)SvPV(adata, adata_len);
2300              
2301 384 50         if (msg_len > SIZE_MAX - crypto_aead_aes256gcm_ABYTES) {
2302 0           croak("Encrypted length exceeds system memory limit (size_t overflow)");
2303             }
2304 384           enc_len = msg_len + crypto_aead_aes256gcm_ABYTES;
2305 384           bl = InitDataBytesLocker(aTHX_ enc_len);
2306              
2307 384           crypto_aead_aes256gcm_encrypt_afternm( bl->bytes, NULL, msg_buf, msg_len,
2308 384           adata_buf, adata_len, NULL, nonce_buf, (const crypto_aead_aes256gcm_state *)precal_key->ctx);
2309              
2310 384           bl->bytes[enc_len] = '\0';
2311              
2312 384 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2313              
2314 384           XSRETURN(1);
2315             #else
2316             croak("AES256-GCM is not supported by this CPU");
2317             #endif
2318             }
2319              
2320             void
2321             aes256gcm_decrypt_afternm(self, msg, adata, nonce, precalculated_key)
2322             SV * self
2323             SV * msg
2324             SV * adata
2325             SV * nonce
2326             SV * precalculated_key
2327             PROTOTYPE: $$$$
2328             INIT:
2329             STRLEN msg_len;
2330             STRLEN adata_len;
2331             STRLEN nonce_len;
2332             STRLEN enc_len;
2333             unsigned char * msg_buf;
2334             unsigned char * adata_buf;
2335             unsigned char * nonce_buf;
2336             #if defined(AES256GCM_IS_AVAILABLE)
2337             CryptNaClSodiumAeadAes256gcmState * precal_key;
2338             #endif
2339             DataBytesLocker *bl;
2340             PPCODE:
2341             {
2342             PERL_UNUSED_VAR(self);
2343             #if defined(AES256GCM_IS_AVAILABLE)
2344              
2345 386 50         if ( GIMME_V == G_VOID ) {
2346 0           XSRETURN_EMPTY;
2347             }
2348              
2349 386           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2350 386 50         if ( nonce_len != crypto_aead_aes256gcm_NPUBBYTES ) {
2351 0           croak("Invalid nonce");
2352             }
2353              
2354 386           msg_buf = (unsigned char *)SvPV(msg, msg_len);
2355              
2356 386 50         if ( msg_len < crypto_aead_aes256gcm_ABYTES ) {
2357 0           croak("Invalid ciphertext");
2358             }
2359              
2360 386           precal_key = GetAeadAes256gcmState(aTHX_ precalculated_key);
2361              
2362 386 100         if ( precal_key->locked ) {
2363 1           croak("Unlock AES256GCM precalculated key object before accessing the state");
2364             }
2365              
2366 385           adata_buf = (unsigned char *)SvPV(adata, adata_len);
2367              
2368 385           enc_len = msg_len - crypto_aead_aes256gcm_ABYTES;
2369 385           bl = InitDataBytesLocker(aTHX_ enc_len);
2370              
2371 385 50         if ( crypto_aead_aes256gcm_decrypt_afternm( bl->bytes, NULL, NULL, msg_buf, msg_len, adata_buf, adata_len, nonce_buf, (const crypto_aead_aes256gcm_state *) precal_key->ctx) == 0 ) {
2372              
2373 385           bl->bytes[enc_len] = '\0';
2374 385 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2375 385           XSRETURN(1);
2376             }
2377             else {
2378 0           sodium_free(bl->bytes);
2379 0           Safefree(bl);
2380 0           croak("Message forged");
2381             }
2382             #else
2383             croak("AES256-GCM is not supported by this CPU");
2384             #endif
2385             }
2386              
2387             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::aead::aes256gcmstate
2388              
2389             void
2390             lock(self)
2391             SV * self
2392             PPCODE:
2393             {
2394             int rc;
2395             #if defined(AES256GCM_IS_AVAILABLE)
2396             CryptNaClSodiumAeadAes256gcmState* state;
2397              
2398 1           state = GetAeadAes256gcmState(aTHX_ self);
2399              
2400 1           rc = sodium_mprotect_noaccess((void *)state->ctx);
2401              
2402 1 50         if (rc == 0 ) {
2403 1           state->locked = 1;
2404 1           XSRETURN_YES;
2405             }
2406              
2407 0           croak("Unable to lock memory: %s", Strerror(errno));
2408             #else
2409             croak("AES256-GCM is not supported by this CPU");
2410             #endif
2411             }
2412              
2413             void
2414             unlock(self)
2415             SV * self
2416             PPCODE:
2417             {
2418             int rc;
2419             #if defined(AES256GCM_IS_AVAILABLE)
2420             CryptNaClSodiumAeadAes256gcmState* state;
2421              
2422 1           state = GetAeadAes256gcmState(aTHX_ self);
2423              
2424 1           rc = sodium_mprotect_readonly((void *)state->ctx);
2425              
2426 1 50         if (rc == 0 ) {
2427 1           state->locked = 0;
2428 1           XSRETURN_YES;
2429             }
2430 0           croak("Unable to unlock memory: %s", Strerror(errno));
2431             #else
2432             croak("AES256-GCM is not supported by this CPU");
2433             #endif
2434             }
2435              
2436             void
2437             is_locked(self, ...)
2438             SV * self
2439             PPCODE:
2440             {
2441             #if defined(AES256GCM_IS_AVAILABLE)
2442             CryptNaClSodiumAeadAes256gcmState* state;
2443              
2444 3           state = GetAeadAes256gcmState(aTHX_ self);
2445 3 100         if ( state->locked ) {
2446 1           XSRETURN_YES;
2447             } else {
2448 2           XSRETURN_NO;
2449             }
2450             #else
2451             croak("AES256-GCM is not supported by this CPU");
2452             #endif
2453             }
2454              
2455             void
2456             DESTROY(self)
2457             SV * self
2458             PPCODE:
2459             {
2460             #if defined(AES256GCM_IS_AVAILABLE)
2461             CryptNaClSodiumAeadAes256gcmState* state;
2462 384           state = GetAeadAes256gcmState(aTHX_ self);
2463 384           sodium_free( state->ctx );
2464 384           Safefree(state);
2465             #else
2466             croak("AES256-GCM is not supported by this CPU");
2467             #endif
2468             }
2469              
2470              
2471             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::box
2472              
2473             PROTOTYPES: DISABLE
2474              
2475             unsigned int
2476             PUBLICKEYBYTES(...)
2477             CODE:
2478 1 50         RETVAL = crypto_box_PUBLICKEYBYTES;
2479             OUTPUT:
2480             RETVAL
2481              
2482             unsigned int
2483             SECRETKEYBYTES(...)
2484             CODE:
2485 1 50         RETVAL = crypto_box_SECRETKEYBYTES;
2486             OUTPUT:
2487             RETVAL
2488              
2489             unsigned int
2490             NONCEBYTES(...)
2491             CODE:
2492 1 50         RETVAL = crypto_box_NONCEBYTES;
2493             OUTPUT:
2494             RETVAL
2495              
2496             unsigned int
2497             MACBYTES(...)
2498             CODE:
2499 6 100         RETVAL = crypto_box_MACBYTES;
2500             OUTPUT:
2501             RETVAL
2502              
2503             unsigned int
2504             SEEDBYTES(...)
2505             CODE:
2506 1 50         RETVAL = crypto_box_SEEDBYTES;
2507             OUTPUT:
2508             RETVAL
2509              
2510             unsigned int
2511             BEFORENMBYTES(...)
2512             CODE:
2513 1 50         RETVAL = crypto_box_BEFORENMBYTES;
2514             OUTPUT:
2515             RETVAL
2516              
2517             PROTOTYPES: ENABLE
2518              
2519             void
2520             keypair(self, ...)
2521             SV * self
2522             PROTOTYPE: $;$
2523             INIT:
2524             DataBytesLocker *blp;
2525             DataBytesLocker *bls;
2526             PPCODE:
2527             {
2528             PERL_UNUSED_VAR(self);
2529              
2530 12 50         if ( items > 2 ) {
2531 0           croak("Invalid number of arguments");
2532             }
2533             /* from seed */
2534 12 100         else if ( items == 2 ) {
2535 8 50         if ( SvPOK(ST(1)) || (SvROK(ST(1)) && sv_derived_from(ST(1), "Data::BytesLocker"))) {
    50          
    50          
2536             STRLEN seed_len;
2537 4           unsigned char * seed_buf = (unsigned char *)SvPV(ST(1), seed_len);
2538              
2539 4 50         if ( seed_len != crypto_box_SEEDBYTES ) {
2540 0           croak("Invalid seed length: %" UVuf, (UV) seed_len);
2541             }
2542              
2543 4           blp = InitDataBytesLocker(aTHX_ crypto_box_PUBLICKEYBYTES);
2544 4           bls = InitDataBytesLocker(aTHX_ crypto_box_SECRETKEYBYTES);
2545              
2546 4           crypto_box_seed_keypair(blp->bytes, bls->bytes, seed_buf);
2547             } else {
2548 0           croak("Invalid seed");
2549             }
2550             }
2551             /* regular */
2552             else {
2553 8           blp = InitDataBytesLocker(aTHX_ crypto_box_PUBLICKEYBYTES);
2554 8           bls = InitDataBytesLocker(aTHX_ crypto_box_SECRETKEYBYTES);
2555 8           crypto_box_keypair(blp->bytes, bls->bytes);
2556             }
2557 12 50         mXPUSHs( DataBytesLocker2SV(aTHX_ blp) );
2558 12 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bls) );
2559 12           XSRETURN(2);
2560             }
2561              
2562             SV *
2563             public_key(self, seckey)
2564             SV * self
2565             SV * seckey
2566             INIT:
2567             DataBytesLocker *bl;
2568             STRLEN skey_len;
2569             unsigned char * skey_buf;
2570             CODE:
2571             {
2572             PERL_UNUSED_VAR(self);
2573              
2574 4           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
2575 4 50         if ( skey_len != crypto_box_SECRETKEYBYTES ) {
2576 0           croak("Invalid secret key");
2577             }
2578 4           bl = InitDataBytesLocker(aTHX_ crypto_box_PUBLICKEYBYTES);
2579              
2580 4           crypto_scalarmult_base(bl->bytes, skey_buf);
2581              
2582 4           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2583             }
2584             OUTPUT:
2585             RETVAL
2586              
2587              
2588              
2589             SV *
2590             seed(self)
2591             SV * self
2592             INIT:
2593             DataBytesLocker *bl;
2594             CODE:
2595             {
2596             PERL_UNUSED_VAR(self);
2597              
2598 2           bl = InitDataBytesLocker(aTHX_ crypto_box_SEEDBYTES);
2599 2           randombytes_buf(bl->bytes, bl->length);
2600              
2601 2           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2602             }
2603             OUTPUT:
2604             RETVAL
2605              
2606              
2607             SV *
2608             beforenm(self, pubkey, seckey)
2609             SV * self
2610             SV * pubkey
2611             SV * seckey
2612             INIT:
2613             STRLEN pkey_len;
2614             STRLEN skey_len;
2615             unsigned char * pkey_buf;
2616             unsigned char * skey_buf;
2617             DataBytesLocker *bl;
2618             CODE:
2619             {
2620             PERL_UNUSED_VAR(self);
2621              
2622 8           pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
2623 8 50         if ( pkey_len != crypto_box_PUBLICKEYBYTES ) {
2624 0           croak("Invalid public key");
2625             }
2626              
2627 8           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
2628 8 50         if ( skey_len != crypto_box_SECRETKEYBYTES ) {
2629 0           croak("Invalid secret key");
2630             }
2631              
2632 8           bl = InitDataBytesLocker(aTHX_ crypto_box_BEFORENMBYTES);
2633              
2634 8 50         if ( crypto_box_beforenm(bl->bytes, pkey_buf, skey_buf) != 0 ) {
2635 0           sodium_free(bl->bytes);
2636 0           Safefree(bl);
2637 0           croak("Failed to pre-calculate key");
2638             }
2639              
2640 8           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2641             }
2642             OUTPUT:
2643             RETVAL
2644              
2645             SV *
2646             nonce(self, ...)
2647             SV * self
2648             PROTOTYPE: $;$
2649             INIT:
2650             DataBytesLocker *bl;
2651             CODE:
2652             PERL_UNUSED_VAR(self);
2653              
2654 5 50         if ( items > 2 ) {
2655 0           croak("Invalid number of arguments");
2656             }
2657              
2658 5 50         if (items == 2 ) {
2659 0 0         if ( SvOK(ST(1)) ) {
2660             STRLEN prev_nonce_len;
2661 0           unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
2662              
2663 0 0         if ( prev_nonce_len > crypto_box_NONCEBYTES ) {
2664 0           croak("Base nonce too long");
2665             }
2666              
2667 0           bl = InitDataBytesLocker(aTHX_ crypto_box_NONCEBYTES);
2668 0           memcpy(bl->bytes, prev_nonce, prev_nonce_len);
2669 0           sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
2670             }
2671             else {
2672 0           croak("Base nonce invalid");
2673             }
2674             }
2675             else {
2676 5           bl = InitDataBytesLocker(aTHX_ crypto_box_NONCEBYTES);
2677 5           randombytes_buf(bl->bytes, bl->length);
2678             }
2679 5           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2680             OUTPUT:
2681             RETVAL
2682              
2683              
2684             void
2685             encrypt(self, msg, nonce, recipient_pubkey, sender_seckey)
2686             SV * self
2687             SV * msg
2688             SV * nonce
2689             SV * recipient_pubkey
2690             SV * sender_seckey
2691             PROTOTYPE: $$$$$
2692             INIT:
2693             STRLEN msg_len;
2694             STRLEN nonce_len;
2695             STRLEN pkey_len;
2696             STRLEN skey_len;
2697             STRLEN enc_len;
2698             unsigned char * msg_buf;
2699             unsigned char * nonce_buf;
2700             unsigned char * pkey_buf;
2701             unsigned char * skey_buf;
2702             DataBytesLocker *bl;
2703             DataBytesLocker *blm;
2704             PPCODE:
2705             {
2706             PERL_UNUSED_VAR(self);
2707              
2708 8 50         if ( GIMME_V == G_VOID ) {
2709 0           XSRETURN_EMPTY;
2710             }
2711              
2712 8           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2713 8 50         if ( nonce_len != crypto_box_NONCEBYTES ) {
2714 0           croak("Invalid nonce");
2715             }
2716              
2717 8           pkey_buf = (unsigned char *)SvPV(recipient_pubkey, pkey_len);
2718 8 50         if ( pkey_len != crypto_box_PUBLICKEYBYTES ) {
2719 0           croak("Invalid public key");
2720             }
2721              
2722 8           skey_buf = (unsigned char *)SvPV(sender_seckey, skey_len);
2723 8 50         if ( skey_len != crypto_box_SECRETKEYBYTES ) {
2724 0           croak("Invalid secret key");
2725             }
2726              
2727 8           msg_buf = (unsigned char *)SvPV(msg, msg_len);
2728              
2729             /* detached mode */
2730 8 100         if ( GIMME_V == G_ARRAY ) {
2731             unsigned char *mac;
2732              
2733 3           bl = InitDataBytesLocker(aTHX_ msg_len);
2734 3           blm = InitDataBytesLocker(aTHX_ crypto_box_MACBYTES);
2735              
2736 3 50         if ( crypto_box_detached( bl->bytes, blm->bytes, (unsigned char *)msg_buf,
2737             (unsigned long long) msg_len, nonce_buf, pkey_buf, skey_buf) != 0 ) {
2738              
2739 0           sodium_free(bl->bytes);
2740 0           Safefree(bl);
2741 0           sodium_free(blm->bytes);
2742 0           Safefree(blm);
2743              
2744 0           croak("Failed to encrypt data");
2745             }
2746 3 50         mXPUSHs( DataBytesLocker2SV(aTHX_ blm) );
2747 3 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2748 3           XSRETURN(2);
2749             }
2750             /* combined mode */
2751             else {
2752 5           enc_len = crypto_box_MACBYTES + msg_len;
2753 5           bl = InitDataBytesLocker(aTHX_ enc_len);
2754              
2755 5 50         if ( crypto_box_easy( bl->bytes, msg_buf, msg_len, nonce_buf, pkey_buf, skey_buf) != 0 ) {
2756 0           sodium_free(bl->bytes);
2757 0           Safefree(bl);
2758 0           croak("Failed to encrypt data");
2759             }
2760              
2761 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2762 5           XSRETURN(1);
2763             }
2764             }
2765              
2766             void
2767             encrypt_afternm(self, msg, nonce, precalculated_key)
2768             SV * self
2769             SV * msg
2770             SV * nonce
2771             SV * precalculated_key
2772             PROTOTYPE: $$$$
2773             INIT:
2774             STRLEN msg_len;
2775             STRLEN nonce_len;
2776             STRLEN key_len;
2777             STRLEN enc_len;
2778             unsigned char * msg_buf;
2779             unsigned char * nonce_buf;
2780             unsigned char * key_buf;
2781             DataBytesLocker *bl;
2782             DataBytesLocker *blm;
2783             PPCODE:
2784             {
2785             PERL_UNUSED_VAR(self);
2786              
2787 7 50         if ( GIMME_V == G_VOID ) {
2788 0           XSRETURN_EMPTY;
2789             }
2790              
2791 7           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2792 7 50         if ( nonce_len != crypto_box_NONCEBYTES ) {
2793 0           croak("Invalid nonce");
2794             }
2795              
2796 7           key_buf = (unsigned char *)SvPV(precalculated_key, key_len);
2797 7 50         if ( key_len != crypto_box_BEFORENMBYTES ) {
2798 0           croak("Invalid precalculated key");
2799             }
2800              
2801 7           msg_buf = (unsigned char *)SvPV(msg, msg_len);
2802              
2803             /* detached mode */
2804 7 100         if ( GIMME_V == G_ARRAY ) {
2805              
2806 4           bl = InitDataBytesLocker(aTHX_ msg_len);
2807 4           blm = InitDataBytesLocker(aTHX_ crypto_box_MACBYTES);
2808              
2809 4           crypto_box_detached_afternm( bl->bytes, blm->bytes, (unsigned char *)msg_buf,
2810             (unsigned long long) msg_len, nonce_buf, key_buf);
2811              
2812 4 50         mXPUSHs( DataBytesLocker2SV(aTHX_ blm) );
2813 4 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2814 4           XSRETURN(2);
2815             }
2816             /* combined mode */
2817             else {
2818 3           enc_len = crypto_box_MACBYTES + msg_len;
2819 3           bl = InitDataBytesLocker(aTHX_ enc_len);
2820              
2821 3           crypto_box_easy_afternm( bl->bytes, msg_buf, msg_len,
2822             nonce_buf, key_buf);
2823              
2824 3 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
2825 3           XSRETURN(1);
2826             }
2827             }
2828              
2829              
2830             SV *
2831             decrypt(self, ciphertext, nonce, sender_pubkey, recipient_seckey)
2832             SV * self
2833             SV * ciphertext
2834             SV * nonce
2835             SV * sender_pubkey
2836             SV * recipient_seckey
2837             PROTOTYPE: $$$$$
2838             INIT:
2839             STRLEN msg_len;
2840             STRLEN nonce_len;
2841             STRLEN pkey_len;
2842             STRLEN skey_len;
2843             STRLEN enc_len;
2844             unsigned char * msg_buf;
2845             unsigned char * nonce_buf;
2846             unsigned char * pkey_buf;
2847             unsigned char * skey_buf;
2848             DataBytesLocker *bl;
2849             CODE:
2850             {
2851             PERL_UNUSED_VAR(self);
2852              
2853 5 50         if ( GIMME_V == G_VOID ) {
2854 0           XSRETURN_EMPTY;
2855             }
2856              
2857 5           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2858 5 50         if ( nonce_len != crypto_box_NONCEBYTES ) {
2859 0           croak("Invalid nonce");
2860             }
2861              
2862 5           pkey_buf = (unsigned char *)SvPV(sender_pubkey, pkey_len);
2863 5 50         if ( pkey_len != crypto_box_PUBLICKEYBYTES ) {
2864 0           croak("Invalid public key");
2865             }
2866              
2867 5           skey_buf = (unsigned char *)SvPV(recipient_seckey, skey_len);
2868 5 50         if ( skey_len != crypto_box_SECRETKEYBYTES ) {
2869 0           croak("Invalid secret key");
2870             }
2871              
2872 5           msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
2873              
2874 5 50         if ( msg_len < crypto_box_MACBYTES ) {
2875 0           croak("Invalid ciphertext");
2876             }
2877              
2878 5           enc_len = msg_len - crypto_box_MACBYTES;
2879              
2880 5           bl = InitDataBytesLocker(aTHX_ enc_len);
2881 5 50         if ( crypto_box_open_easy( bl->bytes, msg_buf, msg_len, nonce_buf, pkey_buf, skey_buf) == 0 ) {
2882 5           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2883             }
2884             else {
2885 0           sodium_free(bl->bytes);
2886 0           Safefree(bl);
2887 0           croak("Message forged");
2888             }
2889             }
2890             OUTPUT:
2891             RETVAL
2892              
2893              
2894             SV *
2895             decrypt_detached(self, mac, ciphertext, nonce, sender_pubkey, recipient_seckey)
2896             SV * self
2897             SV * mac
2898             SV * ciphertext
2899             SV * nonce
2900             SV * sender_pubkey
2901             SV * recipient_seckey
2902             PROTOTYPE: $$$$$$
2903             INIT:
2904             STRLEN msg_len;
2905             STRLEN nonce_len;
2906             STRLEN pkey_len;
2907             STRLEN skey_len;
2908             STRLEN mac_len;
2909             unsigned char * msg_buf;
2910             unsigned char * nonce_buf;
2911             unsigned char * pkey_buf;
2912             unsigned char * skey_buf;
2913             unsigned char * mac_buf;
2914             DataBytesLocker *bl;
2915             CODE:
2916             {
2917             PERL_UNUSED_VAR(self);
2918              
2919 2 50         if ( GIMME_V == G_VOID ) {
2920 0           XSRETURN_EMPTY;
2921             }
2922              
2923 2           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2924 2 50         if ( nonce_len != crypto_box_NONCEBYTES ) {
2925 0           croak("Invalid nonce");
2926             }
2927              
2928 2           pkey_buf = (unsigned char *)SvPV(sender_pubkey, pkey_len);
2929 2 50         if ( pkey_len != crypto_box_PUBLICKEYBYTES ) {
2930 0           croak("Invalid public key");
2931             }
2932              
2933 2           skey_buf = (unsigned char *)SvPV(recipient_seckey, skey_len);
2934 2 50         if ( skey_len != crypto_box_SECRETKEYBYTES ) {
2935 0           croak("Invalid secret key");
2936             }
2937              
2938 2           mac_buf = (unsigned char *)SvPV(mac, mac_len);
2939 2 50         if ( mac_len != crypto_box_MACBYTES ) {
2940 0           croak("Invalid mac");
2941             }
2942              
2943 2           msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
2944              
2945 2           bl = InitDataBytesLocker(aTHX_ msg_len);
2946 2 50         if ( crypto_box_open_detached( bl->bytes, msg_buf, mac_buf, msg_len, nonce_buf, pkey_buf, skey_buf) == 0 ) {
2947 2           RETVAL = DataBytesLocker2SV(aTHX_ bl);
2948             }
2949             else {
2950 0           sodium_free(bl->bytes);
2951 0           Safefree(bl);
2952 0           croak("Message forged");
2953             }
2954             }
2955             OUTPUT:
2956             RETVAL
2957              
2958              
2959             SV *
2960             decrypt_afternm(self, ciphertext, nonce, precalculated_key)
2961             SV * self
2962             SV * ciphertext
2963             SV * nonce
2964             SV * precalculated_key
2965             PROTOTYPE: $$$$
2966             INIT:
2967             STRLEN msg_len;
2968             STRLEN nonce_len;
2969             STRLEN key_len;
2970             STRLEN enc_len;
2971             unsigned char * msg_buf;
2972             unsigned char * nonce_buf;
2973             unsigned char * key_buf;
2974             DataBytesLocker *bl;
2975             CODE:
2976             {
2977             PERL_UNUSED_VAR(self);
2978              
2979 4 50         if ( GIMME_V == G_VOID ) {
2980 0           XSRETURN_EMPTY;
2981             }
2982              
2983 4           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
2984 4 50         if ( nonce_len != crypto_box_NONCEBYTES ) {
2985 0           croak("Invalid nonce");
2986             }
2987              
2988 4           key_buf = (unsigned char *)SvPV(precalculated_key, key_len);
2989 4 50         if ( key_len != crypto_box_BEFORENMBYTES ) {
2990 0           croak("Invalid precalculated key");
2991             }
2992              
2993 4           msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
2994              
2995 4 50         if ( msg_len < crypto_box_MACBYTES ) {
2996 0           croak("Invalid ciphertext");
2997             }
2998              
2999 4           enc_len = msg_len - crypto_box_MACBYTES;
3000              
3001 4           bl = InitDataBytesLocker(aTHX_ enc_len);
3002 4 50         if ( crypto_box_open_easy_afternm( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf) == 0 ) {
3003 4           RETVAL = DataBytesLocker2SV(aTHX_ bl);
3004             }
3005             else {
3006 0           sodium_free(bl->bytes);
3007 0           Safefree(bl);
3008 0           croak("Message forged");
3009             }
3010             }
3011             OUTPUT:
3012             RETVAL
3013              
3014              
3015             SV *
3016             decrypt_detached_afternm(self, mac, ciphertext, nonce, precalculated_key)
3017             SV * self
3018             SV * mac
3019             SV * ciphertext
3020             SV * nonce
3021             SV * precalculated_key
3022             PROTOTYPE: $$$$$
3023             INIT:
3024             STRLEN msg_len;
3025             STRLEN nonce_len;
3026             STRLEN key_len;
3027             STRLEN mac_len;
3028             unsigned char * msg_buf;
3029             unsigned char * nonce_buf;
3030             unsigned char * key_buf;
3031             unsigned char * mac_buf;
3032             DataBytesLocker *bl;
3033             CODE:
3034             {
3035             PERL_UNUSED_VAR(self);
3036              
3037 3 50         if ( GIMME_V == G_VOID ) {
3038 0           XSRETURN_EMPTY;
3039             }
3040              
3041 3           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
3042 3 50         if ( nonce_len != crypto_box_NONCEBYTES ) {
3043 0           croak("Invalid nonce");
3044             }
3045              
3046 3           key_buf = (unsigned char *)SvPV(precalculated_key, key_len);
3047 3 50         if ( key_len != crypto_box_BEFORENMBYTES ) {
3048 0           croak("Invalid precalculated key");
3049             }
3050              
3051 3           mac_buf = (unsigned char *)SvPV(mac, mac_len);
3052 3 50         if ( mac_len != crypto_box_MACBYTES ) {
3053 0           croak("Invalid mac");
3054             }
3055              
3056 3           msg_buf = (unsigned char *)SvPV(ciphertext, msg_len);
3057              
3058 3           bl = InitDataBytesLocker(aTHX_ msg_len);
3059 3 50         if ( crypto_box_open_detached_afternm( bl->bytes, msg_buf, mac_buf, msg_len, nonce_buf, key_buf) == 0 ) {
3060 3           RETVAL = DataBytesLocker2SV(aTHX_ bl);
3061             }
3062             else {
3063 0           sodium_free(bl->bytes);
3064 0           Safefree(bl);
3065 0           croak("Message forged");
3066             }
3067             }
3068             OUTPUT:
3069             RETVAL
3070              
3071              
3072             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::sign
3073              
3074             PROTOTYPES: DISABLE
3075              
3076             unsigned int
3077             PUBLICKEYBYTES(...)
3078             CODE:
3079 1025 100         RETVAL = crypto_sign_PUBLICKEYBYTES;
3080             OUTPUT:
3081             RETVAL
3082              
3083             unsigned int
3084             SECRETKEYBYTES(...)
3085             CODE:
3086 1 50         RETVAL = crypto_sign_SECRETKEYBYTES;
3087             OUTPUT:
3088             RETVAL
3089              
3090             unsigned int
3091             BYTES(...)
3092             CODE:
3093 1025 100         RETVAL = crypto_sign_BYTES;
3094             OUTPUT:
3095             RETVAL
3096              
3097             unsigned int
3098             SEEDBYTES(...)
3099             CODE:
3100 1025 100         RETVAL = crypto_sign_SEEDBYTES;
3101             OUTPUT:
3102             RETVAL
3103              
3104             PROTOTYPES: ENABLE
3105              
3106             void
3107             keypair(self, ...)
3108             SV * self
3109             PROTOTYPE: $;$
3110             INIT:
3111             DataBytesLocker *blp;
3112             DataBytesLocker *bls;
3113             PPCODE:
3114             {
3115             PERL_UNUSED_VAR(self);
3116              
3117 511 50         if ( items > 2 ) {
3118 0           croak("Invalid number of arguments");
3119             }
3120             /* from seed */
3121 511 100         else if ( items == 2 ) {
3122 12 100         if ( SvPOK(ST(1)) || (SvROK(ST(1)) && sv_derived_from(ST(1), "Data::BytesLocker"))) {
    50          
    50          
3123             STRLEN seed_len;
3124 6           unsigned char * seed_buf = (unsigned char *)SvPV(ST(1), seed_len);
3125              
3126 6 50         if ( seed_len != crypto_sign_SEEDBYTES ) {
3127 0           croak("Invalid seed length: %" UVuf, (UV) seed_len);
3128             }
3129              
3130 6           blp = InitDataBytesLocker(aTHX_ crypto_sign_PUBLICKEYBYTES);
3131 6           bls = InitDataBytesLocker(aTHX_ crypto_sign_SECRETKEYBYTES);
3132              
3133 6           crypto_sign_seed_keypair(blp->bytes, bls->bytes, seed_buf);
3134             } else {
3135 0           croak("Invalid seed");
3136             }
3137             }
3138             /* regular */
3139             else {
3140 505           blp = InitDataBytesLocker(aTHX_ crypto_sign_PUBLICKEYBYTES);
3141 505           bls = InitDataBytesLocker(aTHX_ crypto_sign_SECRETKEYBYTES);
3142 505           crypto_sign_keypair(blp->bytes, bls->bytes);
3143             }
3144 511 50         mXPUSHs( DataBytesLocker2SV(aTHX_ blp) );
3145 511 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bls) );
3146 511           XSRETURN(2);
3147             }
3148              
3149              
3150             void
3151             to_curve25519_keypair(self, pubkey, seckey)
3152             SV * self
3153             SV * pubkey
3154             SV * seckey
3155             PROTOTYPE: $$$
3156             INIT:
3157             STRLEN pkey_len;
3158             STRLEN skey_len;
3159             unsigned char * pkey_buf;
3160             unsigned char * skey_buf;
3161             DataBytesLocker *blp;
3162             DataBytesLocker *bls;
3163             PPCODE:
3164             {
3165             PERL_UNUSED_VAR(self);
3166              
3167 501           pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
3168 501 50         if ( pkey_len != crypto_sign_ed25519_PUBLICKEYBYTES ) {
3169 0           croak("Invalid public key");
3170             }
3171              
3172 501           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
3173 501 50         if ( skey_len != crypto_sign_ed25519_SECRETKEYBYTES ) {
3174 0           croak("Invalid secret key");
3175             }
3176              
3177 501           blp = InitDataBytesLocker(aTHX_ crypto_scalarmult_curve25519_BYTES);
3178              
3179 501 50         if ( crypto_sign_ed25519_pk_to_curve25519( blp->bytes, pkey_buf) != 0 ) {
3180 0           sodium_free(blp->bytes);
3181 0           Safefree(blp);
3182 0           croak("Conversion of public key failed");
3183             }
3184              
3185 501           bls = InitDataBytesLocker(aTHX_ crypto_scalarmult_curve25519_BYTES);
3186 501 50         if ( crypto_sign_ed25519_sk_to_curve25519( bls->bytes, skey_buf) != 0 ) {
3187 0           sodium_free(bls->bytes);
3188 0           Safefree(bls);
3189 0           croak("Conversion of secret key failed");
3190             }
3191              
3192 501 50         mXPUSHs( DataBytesLocker2SV(aTHX_ blp) );
3193 501 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bls) );
3194 501           XSRETURN(2);
3195             }
3196              
3197              
3198             void
3199             public_key(self, seckey)
3200             SV * self
3201             SV * seckey
3202             INIT:
3203             STRLEN skey_len;
3204             unsigned char * skey_buf;
3205             DataBytesLocker *bl;
3206             PPCODE:
3207             {
3208             PERL_UNUSED_VAR(self);
3209              
3210 5           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
3211 5 50         if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
3212 0           croak("Invalid secret key");
3213             }
3214 5           bl = InitDataBytesLocker(aTHX_ crypto_sign_PUBLICKEYBYTES);
3215 5           crypto_sign_ed25519_sk_to_pk(bl->bytes, skey_buf);
3216 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3217 5           XSRETURN(1);
3218             }
3219              
3220             void
3221             extract_seed(self, seckey)
3222             SV * self
3223             SV * seckey
3224             INIT:
3225             STRLEN skey_len;
3226             unsigned char * skey_buf;
3227             DataBytesLocker *bl;
3228             PPCODE:
3229             {
3230             PERL_UNUSED_VAR(self);
3231              
3232 5           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
3233 5 50         if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
3234 0           croak("Invalid secret key");
3235             }
3236 5           bl = InitDataBytesLocker(aTHX_ crypto_sign_SEEDBYTES);
3237 5           crypto_sign_ed25519_sk_to_seed(bl->bytes, skey_buf);
3238 5 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3239 5           XSRETURN(1);
3240             }
3241              
3242             void
3243             seed(self)
3244             SV * self
3245             INIT:
3246             DataBytesLocker *bl;
3247             PPCODE:
3248             {
3249             PERL_UNUSED_VAR(self);
3250              
3251 2           bl = InitDataBytesLocker(aTHX_ crypto_sign_SEEDBYTES);
3252 2           randombytes_buf(bl->bytes, bl->length);
3253 2 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3254 2           XSRETURN(1);
3255             }
3256              
3257             void
3258             seal(self, msg, seckey)
3259             SV * self
3260             SV * msg
3261             SV * seckey
3262             PROTOTYPE: $$$
3263             INIT:
3264             STRLEN msg_len;
3265             STRLEN skey_len;
3266             STRLEN enc_len;
3267             unsigned char * msg_buf;
3268             unsigned char * skey_buf;
3269             DataBytesLocker *bl;
3270             PPCODE:
3271             {
3272             PERL_UNUSED_VAR(self);
3273              
3274 1027 50         if ( GIMME_V == G_VOID ) {
3275 0           XSRETURN_EMPTY;
3276             }
3277              
3278 1027           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
3279 1027 50         if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
3280 0           croak("Invalid secret key");
3281             }
3282              
3283 1027           msg_buf = (unsigned char *)SvPV(msg, msg_len);
3284              
3285 1027 50         if (msg_len > SIZE_MAX - crypto_sign_BYTES) {
3286 0           croak("Encrypted length exceeds system memory limit (size_t overflow)");
3287             }
3288 1027           enc_len = crypto_sign_BYTES + msg_len;
3289 1027           bl = InitDataBytesLocker(aTHX_ enc_len);
3290 1027           crypto_sign( bl->bytes, NULL, msg_buf, msg_len, skey_buf);
3291              
3292 1027           bl->bytes[enc_len] = '\0';
3293              
3294 1027 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3295 1027           XSRETURN(1);
3296             }
3297              
3298              
3299             void
3300             mac(self, msg, seckey)
3301             SV * self
3302             SV * msg
3303             SV * seckey
3304             PROTOTYPE: $$$
3305             INIT:
3306             STRLEN msg_len;
3307             STRLEN skey_len;
3308             unsigned char * msg_buf;
3309             unsigned char * skey_buf;
3310             DataBytesLocker *bl;
3311             PPCODE:
3312             {
3313             PERL_UNUSED_VAR(self);
3314              
3315 3 50         if ( GIMME_V == G_VOID ) {
3316 0           XSRETURN_EMPTY;
3317             }
3318              
3319 3           skey_buf = (unsigned char *)SvPV(seckey, skey_len);
3320 3 50         if ( skey_len != crypto_sign_SECRETKEYBYTES ) {
3321 0           croak("Invalid secret key");
3322             }
3323              
3324 3           msg_buf = (unsigned char *)SvPV(msg, msg_len);
3325              
3326 3           bl = InitDataBytesLocker(aTHX_ crypto_sign_BYTES);
3327              
3328 3           crypto_sign_detached( bl->bytes, NULL, (unsigned char *)msg_buf,
3329             (unsigned long long) msg_len, skey_buf);
3330 3 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3331 3           XSRETURN(1);
3332             }
3333              
3334             void
3335             verify(self, sig, msg, pubkey)
3336             SV * self
3337             SV * sig
3338             SV * msg
3339             SV * pubkey
3340             PROTOTYPE: $$$$
3341             INIT:
3342             STRLEN msg_len;
3343             STRLEN sig_len;
3344             STRLEN pkey_len;
3345             unsigned char * msg_buf;
3346             unsigned char * sig_buf;
3347             unsigned char * pkey_buf;
3348             PPCODE:
3349             {
3350             PERL_UNUSED_VAR(self);
3351              
3352 3 50         if ( GIMME_V == G_VOID ) {
3353 0           XSRETURN_EMPTY;
3354             }
3355              
3356 3           sig_buf = (unsigned char *)SvPV(sig, sig_len);
3357 3 50         if ( sig_len != crypto_sign_BYTES ) {
3358 0           croak("Invalid signature");
3359             }
3360              
3361 3           pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
3362 3 50         if ( pkey_len != crypto_sign_PUBLICKEYBYTES ) {
3363 0           croak("Invalid public key");
3364             }
3365              
3366 3           msg_buf = (unsigned char *)SvPV(msg, msg_len);
3367              
3368 3 50         if ( crypto_sign_verify_detached( sig_buf, msg_buf, msg_len, pkey_buf) == 0 ) {
3369 3           XSRETURN_YES;
3370             }
3371             else {
3372 0           XSRETURN_NO;
3373             }
3374             }
3375              
3376              
3377             void
3378             open(self, smsg, pubkey)
3379             SV * self
3380             SV * smsg
3381             SV * pubkey
3382             PROTOTYPE: $$$
3383             INIT:
3384             STRLEN msg_len;
3385             STRLEN pkey_len;
3386             STRLEN enc_len;
3387             unsigned char * msg_buf;
3388             unsigned char * pkey_buf;
3389             DataBytesLocker *bl;
3390             PPCODE:
3391             {
3392             PERL_UNUSED_VAR(self);
3393              
3394 2051 50         if ( GIMME_V == G_VOID ) {
3395 0           XSRETURN_EMPTY;
3396             }
3397              
3398 2051           pkey_buf = (unsigned char *)SvPV(pubkey, pkey_len);
3399 2051 50         if ( pkey_len != crypto_sign_PUBLICKEYBYTES ) {
3400 0           croak("Invalid public key");
3401             }
3402              
3403 2051           msg_buf = (unsigned char *)SvPV(smsg, msg_len);
3404              
3405 2051 50         if ( msg_len < crypto_sign_BYTES ) {
3406 0           croak("Invalid input data");
3407             }
3408              
3409 2051           enc_len = msg_len - crypto_sign_BYTES;
3410              
3411 2051           bl = InitDataBytesLocker(aTHX_ enc_len);
3412 2051 100         if ( crypto_sign_open( bl->bytes, NULL, msg_buf, msg_len, pkey_buf) == 0 ) {
3413              
3414 1027           bl->bytes[enc_len] = '\0';
3415              
3416 1027 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3417              
3418 1027           XSRETURN(1);
3419             }
3420             else {
3421 1024           sodium_free(bl->bytes);
3422 1024           Safefree(bl);
3423 1024           croak("Message forged");
3424             }
3425             }
3426              
3427             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::generichash
3428              
3429             PROTOTYPES: DISABLE
3430              
3431             unsigned int
3432             BYTES(...)
3433             CODE:
3434 2 50         RETVAL = crypto_generichash_BYTES;
3435             OUTPUT:
3436             RETVAL
3437              
3438             unsigned int
3439             BYTES_MIN(...)
3440             CODE:
3441 187 100         RETVAL = crypto_generichash_BYTES_MIN;
3442             OUTPUT:
3443             RETVAL
3444              
3445             unsigned int
3446             BYTES_MAX(...)
3447             CODE:
3448 189 100         RETVAL = crypto_generichash_BYTES_MAX;
3449             OUTPUT:
3450             RETVAL
3451              
3452             unsigned int
3453             KEYBYTES(...)
3454             CODE:
3455 3 100         RETVAL = crypto_generichash_KEYBYTES;
3456             OUTPUT:
3457             RETVAL
3458              
3459             unsigned int
3460             KEYBYTES_MIN(...)
3461             CODE:
3462 15 100         RETVAL = crypto_generichash_KEYBYTES_MIN;
3463             OUTPUT:
3464             RETVAL
3465              
3466             unsigned int
3467             KEYBYTES_MAX(...)
3468             CODE:
3469 18 100         RETVAL = crypto_generichash_KEYBYTES_MAX;
3470             OUTPUT:
3471             RETVAL
3472              
3473             PROTOTYPES: ENABLE
3474              
3475             SV *
3476             keygen(self, keybytes = crypto_generichash_KEYBYTES)
3477             SV * self
3478             size_t keybytes
3479             INIT:
3480             DataBytesLocker *bl;
3481             CODE:
3482             {
3483             PERL_UNUSED_VAR(self);
3484              
3485 169 50         if ( keybytes < crypto_generichash_KEYBYTES_MIN || keybytes > crypto_generichash_KEYBYTES_MAX ) {
    50          
3486 0           croak("Invalid keybytes value: %" UVuf, (UV) keybytes);
3487             }
3488              
3489 169           bl = InitDataBytesLocker(aTHX_ keybytes);
3490              
3491 169           randombytes_buf(bl->bytes, bl->length);
3492              
3493 169           RETVAL = DataBytesLocker2SV(aTHX_ bl);
3494             }
3495             OUTPUT:
3496             RETVAL
3497              
3498             void
3499             mac(self, msg, ...)
3500             SV * self
3501             SV * msg
3502             PROTOTYPE: $$;%
3503             INIT:
3504             unsigned char * msg_buf;
3505             DataBytesLocker *bl;
3506 2419           unsigned char * key_buf = NULL;
3507 2419           STRLEN msg_len = 0;
3508 2419           STRLEN key_len = 0;
3509 2419           size_t bytes = crypto_generichash_BYTES;
3510             PPCODE:
3511             {
3512             PERL_UNUSED_VAR(self);
3513              
3514 2419 50         if ( items > 2 && ( items > 6 || items % 2 != 0 ) ) {
    50          
    50          
3515 0           croak("Invalid number of arguments");
3516 2419 50         } else if ( items > 2 ) {
3517 2419           int i = 0;
3518 2419           STRLEN keylen = 0;
3519             char * key;
3520              
3521 7085 100         for ( i = 2; i < items; i += 2 ) {
3522 4668           key = SvPV(ST(i), keylen);
3523 4668 100         if ( keylen == 3 && strnEQ(key, "key", 3) ) {
    50          
3524 2249           key_buf = (unsigned char *)SvPV(ST(i+1), key_len);
3525 2249 50         if ( key_len < crypto_generichash_KEYBYTES_MIN || key_len > crypto_generichash_KEYBYTES_MAX ) {
    50          
3526 0           croak("Invalid key length: %" UVuf, (UV) key_len);
3527             }
3528             }
3529 2419 50         else if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
    50          
3530 2419           bytes = (size_t)SvUV(ST(i+1));
3531 2419 100         if ( bytes < crypto_generichash_BYTES_MIN || bytes > crypto_generichash_BYTES_MAX ) {
    100          
3532 2           croak("Invalid bytes value: %" UVuf, (UV) bytes);
3533             }
3534             } else {
3535 0           croak("Invalid argument: %s", key);
3536             }
3537             }
3538             }
3539              
3540 2417           msg_buf = (unsigned char *)SvPV(msg, msg_len);
3541              
3542 2417           bl = InitDataBytesLocker(aTHX_ bytes);
3543 2417           crypto_generichash(bl->bytes, bytes, msg_buf, msg_len, key_buf, key_len);
3544              
3545 2417           ST(0) = sv_2mortal(DataBytesLocker2SV(aTHX_ bl));
3546 2417           XSRETURN(1);
3547             }
3548              
3549              
3550             void
3551             init(self, ...)
3552             SV * self
3553             PROTOTYPE: $;%
3554             INIT:
3555 4786           STRLEN key_len = 0;
3556 4786           unsigned char * key_buf = NULL;
3557             CryptNaClSodiumGenerichashStream *stream;
3558              
3559 4786           size_t bytes = crypto_generichash_BYTES;
3560             PPCODE:
3561             {
3562             PERL_UNUSED_VAR(self);
3563              
3564 4786 50         if ( items > 1 && ( items > 5 || (items + 1) % 2 != 0 ) ) {
    50          
    50          
3565 0           croak("Invalid number of arguments");
3566 4786 50         } else if ( items > 1 ) {
3567 4786           int i = 0;
3568 4786           STRLEN keylen = 0;
3569             char * key;
3570              
3571 14013 100         for ( i = 1; i < items; i += 2 ) {
3572 9230           key = (char *)SvPV(ST(i), keylen);
3573 9230 100         if ( keylen == 3 && strnEQ(key, "key", 3) ) {
    50          
3574 4445           key_buf = (unsigned char *)SvPV(ST(i+1), key_len);
3575 4445 50         if ( key_len < crypto_generichash_KEYBYTES_MIN || key_len > crypto_generichash_KEYBYTES_MAX ) {
    100          
3576 1           croak("Invalid key length: %" UVuf, (UV) key_len);
3577             }
3578             }
3579 4785 50         else if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
    50          
3580 4785           bytes = SvUV(ST(i+1));
3581 4785 100         if ( bytes < crypto_generichash_BYTES_MIN || bytes > crypto_generichash_BYTES_MAX ) {
    100          
3582 2           croak("Invalid bytes value: %" UVuf, (UV) bytes);
3583             }
3584             } else {
3585 0           croak("Invalid argument: %s", key);
3586             }
3587             }
3588             }
3589              
3590 4783           Newx(stream, 1, CryptNaClSodiumGenerichashStream);
3591 4783           stream->state = sodium_malloc(sizeof(crypto_generichash_state) + (size_t)63U & ~(size_t) 63U);
3592 4783 50         if ( stream->state == NULL ) {
3593 0           croak("Could not allocate memory");
3594             }
3595 4783           stream->init_bytes = bytes;
3596              
3597 4783           crypto_generichash_init(stream->state, key_buf, key_len, bytes);
3598              
3599 4783           ST(0) = sv_2mortal(GenerichashStream2SV(aTHX_ stream));
3600              
3601 4783           XSRETURN(1);
3602             }
3603              
3604             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::generichash::stream
3605              
3606             void
3607             clone(self)
3608             SV * self
3609             PREINIT:
3610 0           CryptNaClSodiumGenerichashStream* cur_stream = GetGenerichashStream(aTHX_ self);
3611             INIT:
3612             CryptNaClSodiumGenerichashStream* new_stream;
3613             PPCODE:
3614             {
3615 0 0         CLONESTATE(CryptNaClSodiumGenerichashStream, generichash, (size_t)63U & ~(size_t) 63U, new_stream->init_bytes=cur_stream->init_bytes)
    0          
3616 0           ST(0) = sv_2mortal(GenerichashStream2SV(aTHX_ new_stream));
3617 0           XSRETURN(1);
3618             }
3619              
3620              
3621             void
3622             update(self, ...)
3623             SV * self
3624             PREINIT:
3625 123502           CryptNaClSodiumGenerichashStream* stream = GetGenerichashStream(aTHX_ self);
3626             INIT:
3627             STRLEN msg_len;
3628             unsigned char * msg_buf;
3629             int i;
3630             PPCODE:
3631             {
3632 247004 100         for ( i = 1; i < items ; i++ ) {
3633 123502           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
3634              
3635 123502           crypto_generichash_update(stream->state, msg_buf, msg_len);
3636             }
3637              
3638 123502           XSRETURN(1);
3639             }
3640              
3641             void
3642             final(self, ...)
3643             SV * self
3644             PROTOTYPE: $%
3645             PREINIT:
3646 4782           CryptNaClSodiumGenerichashStream* stream = GetGenerichashStream(aTHX_ self);
3647             INIT:
3648             DataBytesLocker *bl;
3649             size_t bytes;
3650             PPCODE:
3651             {
3652 4782           bytes = stream->init_bytes;
3653              
3654 4782 100         if ( items > 1 && items != 3 ) {
    50          
3655 0           croak("Invalid number of arguments");
3656 4782 100         } else if ( items > 1 ) {
3657 4732           int i = 0;
3658 4732           STRLEN keylen = 0;
3659             char * key;
3660              
3661 9464 100         for ( i = 1; i < items; i += 2 ) {
3662 4732           key = (char *)SvPV(ST(i), keylen);
3663 4732 50         if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
    50          
3664 4732           bytes = SvUV(ST(i+1));
3665 4732 50         if ( bytes < crypto_generichash_BYTES_MIN || bytes > crypto_generichash_BYTES_MAX ) {
    50          
3666 0           croak("Invalid bytes value: %" UVuf, (UV) bytes);
3667             }
3668             } else {
3669 0           croak("Invalid argument: %s", key);
3670             }
3671             }
3672             }
3673 4782           bl = InitDataBytesLocker(aTHX_ bytes);
3674              
3675 4782           crypto_generichash_final(stream->state, bl->bytes, bytes);
3676              
3677 4782 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3678              
3679 4782           XSRETURN(1);
3680             }
3681              
3682             void
3683             DESTROY(self)
3684             SV * self
3685             PREINIT:
3686 4783           CryptNaClSodiumGenerichashStream* stream = GetGenerichashStream(aTHX_ self);
3687             PPCODE:
3688             {
3689 4783           sodium_free( stream->state );
3690 4783           Safefree(stream);
3691             }
3692              
3693             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::shorthash
3694              
3695             PROTOTYPES: DISABLE
3696              
3697             unsigned int
3698             BYTES(...)
3699             CODE:
3700 2 50         RETVAL = crypto_shorthash_BYTES;
3701             OUTPUT:
3702             RETVAL
3703              
3704             unsigned int
3705             KEYBYTES(...)
3706             CODE:
3707 4 100         RETVAL = crypto_shorthash_KEYBYTES;
3708             OUTPUT:
3709             RETVAL
3710              
3711             PROTOTYPES: ENABLE
3712              
3713             SV *
3714             keygen(self)
3715             SV * self
3716             INIT:
3717             DataBytesLocker *bl;
3718             CODE:
3719             {
3720             PERL_UNUSED_VAR(self);
3721              
3722 2           bl = InitDataBytesLocker(aTHX_ crypto_shorthash_KEYBYTES);
3723              
3724 2           randombytes_buf(bl->bytes, bl->length);
3725              
3726 2           RETVAL = DataBytesLocker2SV(aTHX_ bl);
3727             }
3728             OUTPUT:
3729             RETVAL
3730              
3731              
3732             SV *
3733             mac(self, msg, key)
3734             SV * self
3735             SV * msg
3736             SV * key
3737             PROTOTYPE: $$$
3738             INIT:
3739 67           STRLEN msg_len = 0;
3740 67           STRLEN key_len = 0;
3741             unsigned char * msg_buf;
3742             unsigned char * key_buf;
3743             DataBytesLocker *bl;
3744             CODE:
3745             {
3746             PERL_UNUSED_VAR(self);
3747              
3748              
3749 67           key_buf = (unsigned char *)SvPV(key, key_len);
3750 67 50         if ( key_len != crypto_shorthash_KEYBYTES ) {
3751 0           croak("Invalid key");
3752             }
3753              
3754 67           msg_buf = (unsigned char *)SvPV(msg, msg_len);
3755              
3756 67           bl = InitDataBytesLocker(aTHX_ crypto_shorthash_BYTES);
3757 67           crypto_shorthash(bl->bytes, msg_buf, msg_len, key_buf);
3758              
3759 67           RETVAL = DataBytesLocker2SV(aTHX_ bl);
3760             }
3761             OUTPUT:
3762             RETVAL
3763              
3764              
3765             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::pwhash
3766              
3767             PROTOTYPES: DISABLE
3768              
3769             unsigned int
3770             SALTBYTES(...)
3771             CODE:
3772 2 50         RETVAL = crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
3773             OUTPUT:
3774             RETVAL
3775              
3776             unsigned int
3777             STRBYTES(...)
3778             CODE:
3779 20 100         RETVAL = crypto_pwhash_scryptsalsa208sha256_STRBYTES;
3780             OUTPUT:
3781             RETVAL
3782              
3783             unsigned long
3784             OPSLIMIT_INTERACTIVE(...)
3785             CODE:
3786 5 100         RETVAL = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
3787             OUTPUT:
3788             RETVAL
3789              
3790             unsigned long
3791             MEMLIMIT_INTERACTIVE(...)
3792             CODE:
3793 13 100         RETVAL = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
3794             OUTPUT:
3795             RETVAL
3796              
3797             unsigned long
3798             OPSLIMIT_SENSITIVE(...)
3799             CODE:
3800 1 50         RETVAL = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
3801             OUTPUT:
3802             RETVAL
3803              
3804             unsigned long
3805             MEMLIMIT_SENSITIVE(...)
3806             CODE:
3807 1 50         RETVAL = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
3808             OUTPUT:
3809             RETVAL
3810              
3811             PROTOTYPES: ENABLE
3812              
3813             SV *
3814             salt(self)
3815             SV * self
3816             INIT:
3817             DataBytesLocker *bl;
3818             CODE:
3819             {
3820             PERL_UNUSED_VAR(self);
3821              
3822 2           bl = InitDataBytesLocker(aTHX_ crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
3823              
3824 2           randombytes_buf(bl->bytes, bl->length);
3825              
3826 2           RETVAL = DataBytesLocker2SV(aTHX_ bl);
3827             }
3828             OUTPUT:
3829             RETVAL
3830              
3831              
3832             void
3833             key(self, passphrase, salt, ... )
3834             SV * self
3835             SV * salt
3836             SV * passphrase
3837             PROTOTYPE: $$$$;%
3838             INIT:
3839             DataBytesLocker *bl;
3840 19           STRLEN pwd_len = 0;
3841 19           STRLEN salt_len = 0;
3842             char * pwd_buf;
3843             unsigned char * salt_buf;
3844 19           unsigned long long outlen = crypto_pwhash_scryptsalsa208sha256_STRBYTES;
3845 19           unsigned long long opslimit = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
3846 19           size_t memlimit = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
3847             PPCODE:
3848             {
3849             PERL_UNUSED_VAR(self);
3850              
3851 19 50         if ( items > 3 && ( ( items + 1 ) % 2 != 0 || items > 9 ) ) {
    50          
    50          
3852 0           croak("Invalid number of arguments");
3853 19 50         } else if ( items > 4 ) {
3854 19           int i = 0;
3855 19           STRLEN keylen = 0;
3856             char * key;
3857              
3858 62 100         for ( i = 3; i < items; i += 2 ) {
3859 43           key = (char *)SvPV(ST(i), keylen);
3860 43 100         if ( keylen == 8 && strnEQ(key, "opslimit", 8) ) {
    100          
3861 12           opslimit = (unsigned long long)SvUV(ST(i+1));
3862 12 50         if ( opslimit < 1 ) {
3863 0           croak("Invalid opslimit: %" UVuf, (UV) opslimit);
3864             }
3865 31 100         } else if ( keylen == 8 && strnEQ(key, "memlimit", 8) ) {
    50          
3866 12           memlimit = (unsigned long long)SvUV(ST(i+1));
3867 12 50         if ( memlimit < 1 ) {
3868 0           croak("Invalid memlimit: %" UVuf, (UV) memlimit);
3869             }
3870 19 50         } else if ( keylen == 5 && strnEQ(key, "bytes", 5) ) {
    50          
3871 19           outlen = (unsigned long long)SvUV(ST(i+1));
3872 19 50         if ( outlen < 1 ) {
3873 0           croak("Invalid bytes: %" UVuf, (UV) outlen);
3874             }
3875             } else {
3876 0           croak("Invalid argument: %s", key);
3877             }
3878             }
3879             }
3880              
3881 19           salt_buf = (unsigned char *)SvPV(salt, salt_len);
3882 19 50         if ( salt_len != crypto_pwhash_scryptsalsa208sha256_SALTBYTES ) {
3883 0           croak("Invalid salt");
3884             }
3885              
3886 19           pwd_buf = (char *)SvPV(passphrase, pwd_len);
3887              
3888 19           bl = InitDataBytesLocker(aTHX_ outlen);
3889 19 50         if ( crypto_pwhash_scryptsalsa208sha256(bl->bytes, outlen, pwd_buf, pwd_len, salt_buf, opslimit, memlimit) != 0 ) {
3890 0           sodium_free( bl->bytes );
3891 0           Safefree(bl);
3892 0           croak("Out of memory");
3893             }
3894              
3895 19 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3896              
3897 19           XSRETURN(1);
3898             }
3899              
3900              
3901             void
3902             str(self, passphrase, ... )
3903             SV * self
3904             SV * passphrase
3905             PROTOTYPE: $$;%
3906             INIT:
3907             DataBytesLocker *bl;
3908 21           STRLEN pwd_len = 0;
3909             char * pwd_buf;
3910 21           unsigned long long opslimit = crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
3911 21           size_t memlimit = crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
3912             PPCODE:
3913             {
3914             PERL_UNUSED_VAR(self);
3915              
3916 21 100         if ( items > 2 && ( items % 2 != 0 || items > 6 ) ) {
    50          
    50          
3917 0           croak("Invalid number of arguments");
3918 21 100         } else if ( items > 2 ) {
3919 20           int i = 0;
3920 20           STRLEN keylen = 0;
3921             char * key;
3922              
3923 60 100         for ( i = 2; i < items; i += 2 ) {
3924 40           key = (char *)SvPV(ST(i), keylen);
3925 40 50         if ( keylen == 8 && strnEQ(key, "opslimit", 8) ) {
    100          
3926 20           opslimit = SvUV(ST(i+1));
3927 20 50         if ( opslimit < 1 ) {
3928 0           croak("Invalid opslimit: %" UVuf, (UV) opslimit);
3929             }
3930 20 50         } else if ( keylen == 8 && strnEQ(key, "memlimit", 8) ) {
    50          
3931 20           memlimit = SvUV(ST(i+1));
3932 20 50         if ( memlimit < 1 ) {
3933 0           croak("Invalid memlimit: %" UVuf, (UV) memlimit);
3934             }
3935             } else {
3936 0           croak("Invalid argument: %s", key);
3937             }
3938             }
3939             }
3940              
3941 21           pwd_buf = (char *)SvPV(passphrase, pwd_len);
3942              
3943 21           bl = InitDataBytesLocker(aTHX_ crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3944 21 50         if ( crypto_pwhash_scryptsalsa208sha256_str((char *)bl->bytes, pwd_buf, pwd_len, opslimit, memlimit) != 0 ) {
3945 0           sodium_free( bl->bytes );
3946 0           Safefree(bl);
3947 0           croak("Out of memory");
3948             }
3949 21           bl->bytes[crypto_pwhash_scryptsalsa208sha256_STRBYTES] = 0;
3950              
3951 21 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
3952 21           XSRETURN(1);
3953             }
3954              
3955              
3956             SV *
3957             verify(self, str, passphrase )
3958             SV * self
3959             SV * str
3960             SV * passphrase
3961             PROTOTYPE: $$$
3962             INIT:
3963             STRLEN str_len;
3964             STRLEN pwd_len;
3965             char * str_buf;
3966             char * pwd_buf;
3967 49           int res = 0;
3968             CODE:
3969             {
3970             PERL_UNUSED_VAR(self);
3971              
3972 49           str_buf = (char *)SvPV(str, str_len);
3973              
3974             /* -1 - need to expand by single null char */
3975 49 100         if ( str_len == crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1 ) {
3976 23           char * str102 = NULL; /* stores the terminating null byte */
3977              
3978 23           pwd_buf = (char *)SvPV(passphrase, pwd_len);
3979              
3980 23           str102 = (char *) sodium_malloc(crypto_pwhash_scryptsalsa208sha256_STRBYTES);
3981 23 50         if ( str102 == NULL ) {
3982 0           croak("Could not allocate memory");
3983             }
3984              
3985 23           memcpy(str102, str_buf, str_len);
3986 23           str102[crypto_pwhash_scryptsalsa208sha256_STRBYTES-1] = 0;
3987              
3988 23           res = crypto_pwhash_scryptsalsa208sha256_str_verify( str102, pwd_buf, pwd_len) == 0;
3989              
3990 23           sodium_free(str102);
3991             }
3992             /* already includes null byte */
3993 26 100         else if ( str_len == crypto_pwhash_scryptsalsa208sha256_STRBYTES
3994 21           &&
3995 21 50         str_buf[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1] == 0
3996             ) {
3997 21           pwd_buf = (char *)SvPV(passphrase, pwd_len);
3998              
3999 21           res = crypto_pwhash_scryptsalsa208sha256_str_verify( str_buf, pwd_buf, pwd_len) == 0;
4000             }
4001             else {
4002 5           croak("Invalid string");
4003             }
4004              
4005 44 100         RETVAL = res ? &PL_sv_yes : &PL_sv_no;
4006             }
4007             OUTPUT:
4008             RETVAL
4009              
4010              
4011             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::hash
4012              
4013             PROTOTYPES: DISABLE
4014              
4015             unsigned int
4016             SHA256_BYTES(...)
4017             CODE:
4018 2 50         RETVAL = crypto_hash_sha256_BYTES;
4019             OUTPUT:
4020             RETVAL
4021              
4022             unsigned int
4023             SHA512_BYTES(...)
4024             CODE:
4025 2 50         RETVAL = crypto_hash_sha512_BYTES;
4026             OUTPUT:
4027             RETVAL
4028              
4029             PROTOTYPES: ENABLE
4030              
4031             void
4032             sha256(self, msg)
4033             SV * self
4034             SV * msg
4035             PROTOTYPE: $$
4036             ALIAS:
4037             sha512 = 1
4038             INIT:
4039 16           STRLEN msg_len = 0;
4040             unsigned char * msg_buf;
4041             DataBytesLocker *bl;
4042             PPCODE:
4043             {
4044             PERL_UNUSED_VAR(self);
4045              
4046 16           msg_buf = (unsigned char *)SvPV(msg, msg_len);
4047              
4048 16 100         switch(ix) {
4049 6           case 1:
4050 6           bl = InitDataBytesLocker(aTHX_ crypto_hash_sha512_BYTES);
4051 6           crypto_hash_sha512(bl->bytes, msg_buf, msg_len);
4052 6           break;
4053 10           default:
4054 10           bl = InitDataBytesLocker(aTHX_ crypto_hash_sha256_BYTES);
4055 10           crypto_hash_sha256(bl->bytes, msg_buf, msg_len);
4056             }
4057              
4058 16 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4059 16           XSRETURN(1);
4060             }
4061              
4062             void
4063             sha256_init(self)
4064             SV * self
4065             PROTOTYPE: $
4066             INIT:
4067             CryptNaClSodiumHashSha256Stream *stream;
4068             PPCODE:
4069             {
4070             PERL_UNUSED_VAR(self);
4071              
4072 4           Newx(stream, 1, CryptNaClSodiumHashSha256Stream);
4073 4           stream->state = sodium_malloc(sizeof(crypto_hash_sha256_state));
4074 4 50         if ( stream->state == NULL ) {
4075 0           croak("Could not allocate memory");
4076             }
4077              
4078 4           crypto_hash_sha256_init(stream->state);
4079              
4080 4           ST(0) = sv_2mortal(HashSha256Stream2SV(aTHX_ stream));
4081              
4082 4           XSRETURN(1);
4083             }
4084              
4085             void
4086             sha512_init(self)
4087             SV * self
4088             PROTOTYPE: $
4089             INIT:
4090             CryptNaClSodiumHashSha512Stream *stream;
4091             PPCODE:
4092             {
4093             PERL_UNUSED_VAR(self);
4094              
4095 4           Newx(stream, 1, CryptNaClSodiumHashSha512Stream);
4096 4           stream->state = sodium_malloc(sizeof(crypto_hash_sha512_state));
4097 4 50         if ( stream->state == NULL ) {
4098 0           croak("Could not allocate memory");
4099             }
4100              
4101 4           crypto_hash_sha512_init(stream->state);
4102              
4103 4           ST(0) = sv_2mortal(HashSha512Stream2SV(aTHX_ stream));
4104              
4105 4           XSRETURN(1);
4106             }
4107              
4108              
4109             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::hash::sha256stream
4110              
4111             void
4112             clone(self)
4113             SV * self
4114             PREINIT:
4115 0           CryptNaClSodiumHashSha256Stream* cur_stream = GetHashSha256Stream(aTHX_ self);
4116             INIT:
4117             CryptNaClSodiumHashSha256Stream* new_stream;
4118             PPCODE:
4119             {
4120 0 0         CLONESTATE(CryptNaClSodiumHashSha256Stream, hash_sha256, 0, ((void)0))
    0          
4121 0           ST(0) = sv_2mortal(HashSha256Stream2SV(aTHX_ new_stream));
4122 0           XSRETURN(1);
4123             }
4124              
4125             void
4126             update(self, ...)
4127             SV * self
4128             PREINIT:
4129 357           CryptNaClSodiumHashSha256Stream* stream = GetHashSha256Stream(aTHX_ self);
4130             INIT:
4131             STRLEN msg_len;
4132             unsigned char * msg_buf;
4133             int i;
4134             PPCODE:
4135             {
4136 714 100         for ( i = 1; i < items ; i++ ) {
4137 357           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
4138              
4139 357           crypto_hash_sha256_update(stream->state, msg_buf, msg_len);
4140             }
4141              
4142 357           XSRETURN(1);
4143             }
4144              
4145             void
4146             final(self)
4147             SV * self
4148             PROTOTYPE: $
4149             PREINIT:
4150 4           CryptNaClSodiumHashSha256Stream* stream = GetHashSha256Stream(aTHX_ self);
4151             INIT:
4152             DataBytesLocker *bl;
4153             PPCODE:
4154             {
4155 4           bl = InitDataBytesLocker(aTHX_ crypto_hash_sha256_BYTES);
4156              
4157 4           crypto_hash_sha256_final(stream->state, bl->bytes);
4158              
4159 4 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4160 4           XSRETURN(1);
4161             }
4162              
4163             void
4164             DESTROY(self)
4165             SV * self
4166             PREINIT:
4167 4           CryptNaClSodiumHashSha256Stream* stream = GetHashSha256Stream(aTHX_ self);
4168             PPCODE:
4169             {
4170 4           sodium_free( stream->state );
4171 4           Safefree(stream);
4172             }
4173              
4174              
4175             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::hash::sha512stream
4176              
4177             void
4178             clone(self)
4179             SV * self
4180             PREINIT:
4181 0           CryptNaClSodiumHashSha512Stream* cur_stream = GetHashSha512Stream(aTHX_ self);
4182             INIT:
4183             CryptNaClSodiumHashSha512Stream* new_stream;
4184             PPCODE:
4185             {
4186 0 0         CLONESTATE(CryptNaClSodiumHashSha512Stream, hash_sha512, 0, ((void)0))
    0          
4187 0           ST(0) = sv_2mortal(HashSha512Stream2SV(aTHX_ new_stream));
4188 0           XSRETURN(1);
4189             }
4190              
4191             void
4192             update(self, ...)
4193             SV * self
4194             PREINIT:
4195 357           CryptNaClSodiumHashSha512Stream* stream = GetHashSha512Stream(aTHX_ self);
4196             INIT:
4197             STRLEN msg_len;
4198             unsigned char * msg_buf;
4199             int i;
4200             PPCODE:
4201             {
4202 714 100         for ( i = 1; i < items ; i++ ) {
4203 357           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
4204              
4205 357           crypto_hash_sha512_update(stream->state, msg_buf, msg_len);
4206             }
4207              
4208 357           XSRETURN(1);
4209             }
4210              
4211             void
4212             final(self)
4213             SV * self
4214             PROTOTYPE: $
4215             PREINIT:
4216 4           CryptNaClSodiumHashSha512Stream* stream = GetHashSha512Stream(aTHX_ self);
4217             INIT:
4218             DataBytesLocker *bl;
4219             PPCODE:
4220             {
4221 4           bl = InitDataBytesLocker(aTHX_ crypto_hash_sha512_BYTES);
4222              
4223 4           crypto_hash_sha512_final(stream->state, bl->bytes);
4224              
4225 4 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4226 4           XSRETURN(1);
4227             }
4228              
4229              
4230             void
4231             DESTROY(self)
4232             SV * self
4233             PREINIT:
4234 4           CryptNaClSodiumHashSha512Stream* stream = GetHashSha512Stream(aTHX_ self);
4235             PPCODE:
4236             {
4237 4           sodium_free( stream->state );
4238 4           Safefree(stream);
4239             }
4240              
4241              
4242             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::onetimeauth
4243              
4244             PROTOTYPES: DISABLE
4245              
4246             unsigned int
4247             BYTES(...)
4248             CODE:
4249 9999 100         RETVAL = crypto_onetimeauth_BYTES;
4250             OUTPUT:
4251             RETVAL
4252              
4253             unsigned int
4254             KEYBYTES(...)
4255             CODE:
4256 1 50         RETVAL = crypto_onetimeauth_KEYBYTES;
4257             OUTPUT:
4258             RETVAL
4259              
4260             PROTOTYPES: ENABLE
4261              
4262             SV *
4263             keygen(self)
4264             SV * self
4265             INIT:
4266             DataBytesLocker *bl;
4267             CODE:
4268             {
4269             PERL_UNUSED_VAR(self);
4270              
4271 10001           bl = InitDataBytesLocker(aTHX_ crypto_onetimeauth_KEYBYTES);
4272              
4273 10001           randombytes_buf(bl->bytes, bl->length);
4274              
4275 10001           RETVAL = DataBytesLocker2SV(aTHX_ bl);
4276             }
4277             OUTPUT:
4278             RETVAL
4279              
4280              
4281             void
4282             mac(self, msg, key)
4283             SV * self
4284             SV * msg
4285             SV * key
4286             PROTOTYPE: $$$
4287             INIT:
4288             STRLEN msg_len;
4289             STRLEN key_len;
4290             unsigned char * msg_buf;
4291             unsigned char * key_buf;
4292             DataBytesLocker *bl;
4293             PPCODE:
4294             {
4295             PERL_UNUSED_VAR(self);
4296              
4297 10003           key_buf = (unsigned char *)SvPV(key, key_len);
4298 10003 50         if ( key_len != crypto_onetimeauth_KEYBYTES ) {
4299 0           croak("Invalid key");
4300             }
4301              
4302 10003           msg_buf = (unsigned char *)SvPV(msg, msg_len);
4303              
4304 10003           bl = InitDataBytesLocker(aTHX_ crypto_onetimeauth_BYTES);
4305 10003           crypto_onetimeauth(bl->bytes, msg_buf, msg_len, key_buf);
4306              
4307 10003 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4308 10003           XSRETURN(1);
4309             }
4310              
4311             void
4312             verify(self, mac, msg, key)
4313             SV * self
4314             SV * mac
4315             SV * msg
4316             SV * key
4317             PROTOTYPE: $$$$
4318             INIT:
4319             STRLEN msg_len;
4320             STRLEN key_len;
4321             STRLEN mac_len;
4322             unsigned char * msg_buf;
4323             unsigned char * mac_buf;
4324             unsigned char * key_buf;
4325             PPCODE:
4326             {
4327             PERL_UNUSED_VAR(self);
4328              
4329 30004 50         if ( GIMME_V == G_VOID ) {
4330 0           XSRETURN_EMPTY;
4331             }
4332              
4333 30004           mac_buf = (unsigned char *)SvPV(mac, mac_len);
4334 30004 50         if ( mac_len != crypto_onetimeauth_BYTES ) {
4335 0           croak("Invalid mac");
4336             }
4337              
4338 30004           key_buf = (unsigned char *)SvPV(key, key_len);
4339 30004 50         if ( key_len != crypto_onetimeauth_KEYBYTES ) {
4340 0           croak("Invalid key");
4341             }
4342              
4343 30004           msg_buf = (unsigned char *)SvPV(msg, msg_len);
4344              
4345 30004 100         if ( crypto_onetimeauth_verify( mac_buf, msg_buf, msg_len, key_buf) == 0 ) {
4346 10006           XSRETURN_YES;
4347             }
4348             else {
4349 19998           XSRETURN_NO;
4350             }
4351             }
4352              
4353              
4354             void
4355             init(self, key)
4356             SV * self
4357             SV * key
4358             PROTOTYPE: $;%
4359             INIT:
4360             STRLEN key_len;
4361             unsigned char * key_buf;
4362             CryptNaClSodiumOnetimeauthStream *stream;
4363             PPCODE:
4364             {
4365             PERL_UNUSED_VAR(self);
4366              
4367 3           key_buf = (unsigned char *)SvPV(key, key_len);
4368 3 50         if ( key_len != crypto_onetimeauth_KEYBYTES ) {
4369 0           croak("Invalid key");
4370             }
4371              
4372 3           Newx(stream, 1, CryptNaClSodiumOnetimeauthStream);
4373 3           stream->state = sodium_malloc(sizeof(crypto_onetimeauth_state));
4374 3 50         if ( stream->state == NULL ) {
4375 0           croak("Could not allocate memory");
4376             }
4377              
4378 3           crypto_onetimeauth_init(stream->state, key_buf);
4379              
4380 3           ST(0) = sv_2mortal(OnetimeauthStream2SV(aTHX_ stream));
4381              
4382 3           XSRETURN(1);
4383             }
4384              
4385              
4386             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::onetimeauth::stream
4387              
4388             void
4389             clone(self)
4390             SV * self
4391             PREINIT:
4392 0           CryptNaClSodiumOnetimeauthStream* cur_stream = GetOnetimeauthStream(aTHX_ self);
4393             INIT:
4394             CryptNaClSodiumOnetimeauthStream* new_stream;
4395             PPCODE:
4396             {
4397 0 0         CLONESTATE(CryptNaClSodiumOnetimeauthStream, onetimeauth, 0, ((void)0))
    0          
4398 0           ST(0) = sv_2mortal(OnetimeauthStream2SV(aTHX_ new_stream));
4399 0           XSRETURN(1);
4400             }
4401              
4402              
4403             void
4404             update(self, ...)
4405             SV * self
4406             PREINIT:
4407 26           CryptNaClSodiumOnetimeauthStream* stream = GetOnetimeauthStream(aTHX_ self);
4408             INIT:
4409             STRLEN msg_len;
4410             unsigned char * msg_buf;
4411             int i;
4412             PPCODE:
4413             {
4414 52 100         for ( i = 1; i < items ; i++ ) {
4415 26           msg_buf = (unsigned char *)SvPV(ST(i), msg_len);
4416              
4417 26           crypto_onetimeauth_update(stream->state, msg_buf, msg_len);
4418             }
4419              
4420 26           XSRETURN(1);
4421             }
4422              
4423             void
4424             final(self)
4425             SV * self
4426             PROTOTYPE: $
4427             PREINIT:
4428 3           CryptNaClSodiumOnetimeauthStream* stream = GetOnetimeauthStream(aTHX_ self);
4429             INIT:
4430             DataBytesLocker *bl;
4431             PPCODE:
4432             {
4433 3           bl = InitDataBytesLocker(aTHX_ crypto_onetimeauth_BYTES);
4434              
4435 3           crypto_onetimeauth_final(stream->state, bl->bytes);
4436              
4437 3 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4438 3           XSRETURN(1);
4439             }
4440              
4441             void
4442             DESTROY(self)
4443             SV * self
4444             PREINIT:
4445 3           CryptNaClSodiumOnetimeauthStream* stream = GetOnetimeauthStream(aTHX_ self);
4446             PPCODE:
4447             {
4448 3           sodium_free( stream->state );
4449 3           Safefree(stream);
4450             }
4451              
4452              
4453             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::scalarmult
4454              
4455             PROTOTYPES: DISABLE
4456              
4457             unsigned int
4458             BYTES(...)
4459             CODE:
4460 1 50         RETVAL = crypto_scalarmult_BYTES;
4461             OUTPUT:
4462             RETVAL
4463              
4464              
4465             unsigned int
4466             SCALARBYTES(...)
4467             CODE:
4468 1 50         RETVAL = crypto_scalarmult_SCALARBYTES;
4469             OUTPUT:
4470             RETVAL
4471              
4472             PROTOTYPES: ENABLE
4473              
4474             SV *
4475             keygen(self)
4476             SV * self
4477             INIT:
4478             DataBytesLocker *bl;
4479             CODE:
4480             {
4481             PERL_UNUSED_VAR(self);
4482              
4483 6           bl = InitDataBytesLocker(aTHX_ crypto_scalarmult_SCALARBYTES);
4484              
4485 6           randombytes_buf(bl->bytes, bl->length);
4486              
4487 6           RETVAL = DataBytesLocker2SV(aTHX_ bl);
4488             }
4489             OUTPUT:
4490             RETVAL
4491              
4492             void
4493             base(self, secret_key)
4494             SV * self
4495             SV * secret_key
4496             PROTOTYPE: $$
4497             INIT:
4498             STRLEN key_len;
4499             unsigned char * key_buf;
4500             DataBytesLocker *bl;
4501             PPCODE:
4502             {
4503             PERL_UNUSED_VAR(self);
4504              
4505 508 50         if ( GIMME_V == G_VOID ) {
4506 0           XSRETURN_EMPTY;
4507             }
4508              
4509 508           key_buf = (unsigned char *)SvPV(secret_key, key_len);
4510 508 50         if ( key_len != crypto_scalarmult_SCALARBYTES ) {
4511 0           croak("Invalid key");
4512             }
4513              
4514 508           bl = InitDataBytesLocker(aTHX_ crypto_scalarmult_BYTES);
4515 508           crypto_scalarmult_base( bl->bytes, key_buf);
4516              
4517 508 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4518 508           XSRETURN(1);
4519             }
4520              
4521              
4522             void
4523             shared_secret(self, secret_key, public_key)
4524             SV * self
4525             SV * secret_key
4526             SV * public_key
4527             PROTOTYPE: $$$$
4528             INIT:
4529             STRLEN skey_len;
4530             STRLEN pkey_len;
4531             unsigned char * skey_buf;
4532             unsigned char * pkey_buf;
4533              
4534             DataBytesLocker *bl;
4535             PPCODE:
4536             {
4537             PERL_UNUSED_VAR(self);
4538              
4539 7 50         if ( GIMME_V == G_VOID ) {
4540 0           XSRETURN_EMPTY;
4541             }
4542              
4543 7           skey_buf = (unsigned char *)SvPV(secret_key, skey_len);
4544 7 50         if ( skey_len != crypto_scalarmult_SCALARBYTES ) {
4545 0           croak("Invalid secret key");
4546             }
4547              
4548 7           pkey_buf = (unsigned char *)SvPV(public_key, pkey_len);
4549 7 50         if ( pkey_len != crypto_scalarmult_SCALARBYTES ) {
4550 0           croak("Invalid public key");
4551             }
4552              
4553 7           bl = InitDataBytesLocker(aTHX_ crypto_scalarmult_BYTES);
4554              
4555 7 50         if ( crypto_scalarmult( bl->bytes, skey_buf, pkey_buf) != 0 ) {
4556 0           sodium_free(bl->bytes);
4557 0           Safefree(bl);
4558 0           croak("Failed to calculate shared secret");
4559             }
4560              
4561 7 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4562 7           XSRETURN(1);
4563             }
4564              
4565              
4566             MODULE = Crypt::NaCl::Sodium PACKAGE = Crypt::NaCl::Sodium::stream
4567              
4568             PROTOTYPES: DISABLE
4569              
4570             unsigned int
4571             NONCEBYTES(...)
4572             CODE:
4573 3 100         RETVAL = crypto_stream_NONCEBYTES;
4574             OUTPUT:
4575             RETVAL
4576              
4577             unsigned int
4578             KEYBYTES(...)
4579             CODE:
4580 3 100         RETVAL = crypto_stream_KEYBYTES;
4581             OUTPUT:
4582             RETVAL
4583              
4584             unsigned int
4585             CHACHA20_NONCEBYTES(...)
4586             CODE:
4587 3 100         RETVAL = crypto_stream_chacha20_NONCEBYTES;
4588             OUTPUT:
4589             RETVAL
4590              
4591             unsigned int
4592             CHACHA20_IETF_NONCEBYTES(...)
4593             CODE:
4594 0 0         RETVAL = crypto_stream_chacha20_IETF_NONCEBYTES;
4595             OUTPUT:
4596             RETVAL
4597              
4598             unsigned int
4599             CHACHA20_KEYBYTES(...)
4600             CODE:
4601 3 100         RETVAL = crypto_stream_chacha20_KEYBYTES;
4602             OUTPUT:
4603             RETVAL
4604              
4605             unsigned int
4606             SALSA20_NONCEBYTES(...)
4607             CODE:
4608 3 100         RETVAL = crypto_stream_salsa20_NONCEBYTES;
4609             OUTPUT:
4610             RETVAL
4611              
4612             unsigned int
4613             SALSA20_KEYBYTES(...)
4614             CODE:
4615 3 100         RETVAL = crypto_stream_salsa20_KEYBYTES;
4616             OUTPUT:
4617             RETVAL
4618              
4619             unsigned int
4620             AES128CTR_NONCEBYTES(...)
4621             CODE:
4622             #ifdef AES128CTR_IS_AVAILABLE
4623             RETVAL = crypto_stream_aes128ctr_NONCEBYTES;
4624             #else
4625 0           croak("AES128CTR is only available in libsodium v1.0.14 and below");
4626             #endif
4627             OUTPUT:
4628             RETVAL
4629              
4630             unsigned int
4631             AES128CTR_KEYBYTES(...)
4632             CODE:
4633             #ifdef AES128CTR_IS_AVAILABLE
4634             RETVAL = crypto_stream_aes128ctr_KEYBYTES;
4635             #else
4636 0           croak("AES128CTR is only available in libsodium v1.0.14 and below");
4637             #endif
4638             OUTPUT:
4639             RETVAL
4640              
4641             PROTOTYPES: ENABLE
4642              
4643             SV *
4644             keygen(self)
4645             SV * self
4646             ALIAS:
4647             chacha20_keygen = 1
4648             salsa20_keygen = 2
4649             aes128ctr_keygen = 3
4650             INIT:
4651             unsigned int key_size;
4652             DataBytesLocker *bl;
4653             CODE:
4654             {
4655             PERL_UNUSED_VAR(self);
4656              
4657 3           switch(ix) {
4658 1           case 1:
4659 1           key_size = crypto_stream_chacha20_KEYBYTES;
4660 1           break;
4661 1           case 2:
4662 1           key_size = crypto_stream_salsa20_KEYBYTES;
4663 1           break;
4664 0           case 3:
4665             #ifdef AES128CTR_IS_AVAILABLE
4666             key_size = crypto_stream_aes128ctr_KEYBYTES;
4667             #else
4668 0           croak("AES128CTR is only available in libsodium v1.0.14 and below");
4669             #endif
4670             break;
4671 1           default:
4672 1           key_size = crypto_stream_KEYBYTES;
4673             }
4674 3           bl = InitDataBytesLocker(aTHX_ key_size);
4675 3           randombytes_buf(bl->bytes, key_size);
4676 3           RETVAL = DataBytesLocker2SV(aTHX_ bl);
4677             }
4678             OUTPUT:
4679             RETVAL
4680              
4681             SV *
4682             nonce(self, ...)
4683             SV * self
4684             PROTOTYPE: $;$
4685             ALIAS:
4686             chacha20_nonce = 1
4687             salsa20_nonce = 2
4688             aes128ctr_nonce = 3
4689             chacha20_ietf_nonce = 4
4690             INIT:
4691             unsigned int nonce_size;
4692             DataBytesLocker *bl;
4693             CODE:
4694             PERL_UNUSED_VAR(self);
4695              
4696 3           switch(ix) {
4697 1           case 1:
4698 1           nonce_size = crypto_stream_chacha20_NONCEBYTES;
4699 1           break;
4700 1           case 2:
4701 1           nonce_size = crypto_stream_salsa20_NONCEBYTES;
4702 1           break;
4703 0           case 3:
4704             #ifdef AES128CTR_IS_AVAILABLE
4705             nonce_size = crypto_stream_aes128ctr_NONCEBYTES;
4706             #else
4707 0           croak("AES128CTR is only available in libsodium v1.0.14 and below");
4708             #endif
4709             break;
4710 0           case 4:
4711 0           nonce_size = crypto_stream_chacha20_IETF_NONCEBYTES;
4712 0           break;
4713 1           default:
4714 1           nonce_size = crypto_stream_NONCEBYTES;
4715             }
4716              
4717 3 50         if ( items > 2 ) {
4718 0           croak("Invalid number of arguments");
4719             }
4720              
4721 3 50         if (items == 2 ) {
4722 0 0         if ( SvOK(ST(1)) ) {
4723             STRLEN prev_nonce_len;
4724 0           unsigned char * prev_nonce = (unsigned char *)SvPV(ST(1), prev_nonce_len);
4725              
4726 0 0         if ( prev_nonce_len > nonce_size ) {
4727 0           croak("Base nonce too long");
4728             }
4729              
4730 0           bl = InitDataBytesLocker(aTHX_ nonce_size);
4731 0           memcpy(bl->bytes, prev_nonce, prev_nonce_len);
4732 0           sodium_memzero(bl->bytes + prev_nonce_len, bl->length - prev_nonce_len);
4733             }
4734             else {
4735 0           croak("Base nonce invalid");
4736             }
4737             }
4738             else {
4739 3           bl = InitDataBytesLocker(aTHX_ nonce_size);
4740 3           randombytes_buf(bl->bytes, bl->length);
4741             }
4742 3           RETVAL = DataBytesLocker2SV(aTHX_ bl);
4743             OUTPUT:
4744             RETVAL
4745              
4746              
4747             void
4748             bytes(self, length, nonce, key)
4749             SV * self
4750             SV * length
4751             SV * nonce
4752             SV * key
4753             ALIAS:
4754             chacha20_bytes = 1
4755             salsa20_bytes = 2
4756             aes128ctr_bytes = 3
4757             salsa2012_bytes = 4
4758             salsa208_bytes = 5
4759             chacha20_ietf_bytes = 6
4760             INIT:
4761             STRLEN nonce_len;
4762             STRLEN key_len;
4763             unsigned char * nonce_buf;
4764             unsigned char * key_buf;
4765             unsigned int nonce_size;
4766             unsigned int key_size;
4767             unsigned int bytes_len;
4768             int (*bytes_function)(unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
4769             DataBytesLocker *bl;
4770             PPCODE:
4771             {
4772             PERL_UNUSED_VAR(self);
4773              
4774 16 50         if ( GIMME_V == G_VOID ) {
4775 0           XSRETURN_EMPTY;
4776             }
4777              
4778 16           switch(ix) {
4779 8           case 1:
4780 8           nonce_size = crypto_stream_chacha20_NONCEBYTES;
4781 8           key_size = crypto_stream_chacha20_KEYBYTES;
4782 8           bytes_function = &crypto_stream_chacha20;
4783 8           break;
4784 3           case 2:
4785 3           nonce_size = crypto_stream_salsa20_NONCEBYTES;
4786 3           key_size = crypto_stream_salsa20_KEYBYTES;
4787 3           bytes_function = &crypto_stream_salsa20;
4788 3           break;
4789 0           case 3:
4790             #ifdef AES128CTR_IS_AVAILABLE
4791             nonce_size = crypto_stream_aes128ctr_NONCEBYTES;
4792             key_size = crypto_stream_aes128ctr_KEYBYTES;
4793             bytes_function = &crypto_stream_aes128ctr;
4794             #else
4795 0           croak("AES128CTR is only available in libsodium v1.0.14 and below");
4796             #endif
4797             break;
4798 0           case 4:
4799 0           nonce_size = crypto_stream_salsa20_NONCEBYTES;
4800 0           key_size = crypto_stream_salsa20_KEYBYTES;
4801 0           bytes_function = &crypto_stream_salsa2012;
4802 0           break;
4803 0           case 5:
4804             #ifdef INCLUDE_DEPRECATED
4805             nonce_size = crypto_stream_salsa20_NONCEBYTES;
4806             key_size = crypto_stream_salsa20_KEYBYTES;
4807             bytes_function = &crypto_stream_salsa208;
4808             #else
4809 0           croak("crypto_stream_salsa208 was deprecated in v1.0.18 define INCLUDE_DEPRECATED to use");
4810             #endif
4811             break;
4812 1           case 6:
4813 1           nonce_size = crypto_stream_chacha20_IETF_NONCEBYTES;
4814 1           key_size = crypto_stream_chacha20_KEYBYTES;
4815 1           bytes_function = &crypto_stream_chacha20_ietf;
4816 1           break;
4817 4           default:
4818 4           nonce_size = crypto_stream_NONCEBYTES;
4819 4           key_size = crypto_stream_KEYBYTES;
4820 4           bytes_function = &crypto_stream;
4821             }
4822              
4823 16           bytes_len = SvUV(length);
4824              
4825 16           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
4826 16 50         if ( nonce_len != nonce_size ) {
4827 0           croak("Invalid nonce");
4828             }
4829              
4830 16           key_buf = (unsigned char *)SvPV(key, key_len);
4831 16 50         if ( key_len != key_size ) {
4832 0           croak("Invalid key");
4833             }
4834              
4835 16           bl = InitDataBytesLocker(aTHX_ bytes_len);
4836              
4837 16           (*bytes_function)( bl->bytes, bytes_len, nonce_buf, key_buf);
4838              
4839 16 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4840 16           XSRETURN(1);
4841             }
4842              
4843              
4844             void
4845             xor(self, msg, nonce, key)
4846             SV * self
4847             SV * msg
4848             SV * nonce
4849             SV * key
4850             ALIAS:
4851             chacha20_xor = 1
4852             salsa20_xor = 2
4853             aes128ctr_xor = 3
4854             salsa2012_xor = 4
4855             salsa208_xor = 5
4856             chacha20_ietf_xor = 6
4857             INIT:
4858             STRLEN msg_len;
4859             STRLEN nonce_len;
4860             STRLEN key_len;
4861             unsigned char * msg_buf;
4862             unsigned char * nonce_buf;
4863             unsigned char * key_buf;
4864             unsigned int nonce_size;
4865             unsigned int key_size;
4866             int (*xor_function)(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *);
4867             DataBytesLocker *bl;
4868             PPCODE:
4869             {
4870             PERL_UNUSED_VAR(self);
4871              
4872 19 50         if ( GIMME_V == G_VOID ) {
4873 0           XSRETURN_EMPTY;
4874             }
4875              
4876 19           switch(ix) {
4877 7           case 1:
4878 7           nonce_size = crypto_stream_chacha20_NONCEBYTES;
4879 7           key_size = crypto_stream_chacha20_KEYBYTES;
4880 7           xor_function = &crypto_stream_chacha20_xor;
4881 7           break;
4882 4           case 2:
4883 4           nonce_size = crypto_stream_salsa20_NONCEBYTES;
4884 4           key_size = crypto_stream_salsa20_KEYBYTES;
4885 4           xor_function = &crypto_stream_salsa20_xor;
4886 4           break;
4887 0           case 3:
4888             #ifdef AES128CTR_IS_AVAILABLE
4889             nonce_size = crypto_stream_aes128ctr_NONCEBYTES;
4890             key_size = crypto_stream_aes128ctr_KEYBYTES;
4891             xor_function = &crypto_stream_aes128ctr_xor;
4892             #else
4893 0           croak("AES128CTR is only available in libsodium v1.0.14 and below");
4894             #endif
4895             break;
4896 0           case 4:
4897 0           nonce_size = crypto_stream_salsa20_NONCEBYTES;
4898 0           key_size = crypto_stream_salsa20_KEYBYTES;
4899 0           xor_function = &crypto_stream_salsa2012_xor;
4900 0           break;
4901 0           case 5:
4902             #ifdef INCLUDE_DEPRECATED
4903             nonce_size = crypto_stream_salsa20_NONCEBYTES;
4904             key_size = crypto_stream_salsa20_KEYBYTES;
4905             xor_function = &crypto_stream_salsa208_xor;
4906             #else
4907 0           croak("crypto_stream_salsa208_xor was deprecated in v1.0.18 define INCLUDE_DEPRECATED to use");
4908             #endif
4909             break;
4910 3           case 6:
4911 3           nonce_size = crypto_stream_chacha20_IETF_NONCEBYTES;
4912 3           key_size = crypto_stream_chacha20_KEYBYTES;
4913 3           xor_function = &crypto_stream_chacha20_ietf_xor;
4914 3           break;
4915 5           default:
4916 5           nonce_size = crypto_stream_NONCEBYTES;
4917 5           key_size = crypto_stream_KEYBYTES;
4918 5           xor_function = &crypto_stream_xor;
4919             }
4920              
4921 19           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
4922 19 50         if ( nonce_len != nonce_size ) {
4923 0           croak("Invalid nonce");
4924             }
4925              
4926 19           key_buf = (unsigned char *)SvPV(key, key_len);
4927 19 50         if ( key_len != key_size ) {
4928 0           croak("Invalid key");
4929             }
4930              
4931 19           msg_buf = (unsigned char *)SvPV(msg, msg_len);
4932              
4933 19           bl = InitDataBytesLocker(aTHX_ msg_len);
4934              
4935 19           (*xor_function)( bl->bytes, msg_buf, msg_len, nonce_buf, key_buf);
4936              
4937 19 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
4938 19           XSRETURN(1);
4939             }
4940              
4941              
4942             void
4943             xor_ic(self, msg, nonce, ic, key)
4944             SV * self
4945             SV * msg
4946             SV * nonce
4947             SV * ic
4948             SV * key
4949             ALIAS:
4950             chacha20_xor_ic = 1
4951             salsa20_xor_ic = 2
4952             INIT:
4953             STRLEN msg_len;
4954             STRLEN nonce_len;
4955             unsigned int bc;
4956             STRLEN key_len;
4957             unsigned char * msg_buf;
4958             unsigned char * nonce_buf;
4959             unsigned char * key_buf;
4960             unsigned int nonce_size;
4961             unsigned int key_size;
4962             int (*xor_ic_function)(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, uint64_t, const unsigned char *);
4963             DataBytesLocker *bl;
4964             PPCODE:
4965             {
4966             PERL_UNUSED_VAR(self);
4967              
4968 13 50         if ( GIMME_V == G_VOID ) {
4969 0           XSRETURN_EMPTY;
4970             }
4971              
4972 13           switch(ix) {
4973 5           case 1:
4974 5           nonce_size = crypto_stream_chacha20_NONCEBYTES;
4975 5           key_size = crypto_stream_chacha20_KEYBYTES;
4976 5           xor_ic_function = &crypto_stream_chacha20_xor_ic;
4977 5           break;
4978 4           case 2:
4979 4           nonce_size = crypto_stream_salsa20_NONCEBYTES;
4980 4           key_size = crypto_stream_salsa20_KEYBYTES;
4981 4           xor_ic_function = &crypto_stream_salsa20_xor_ic;
4982 4           break;
4983 4           default:
4984 4           nonce_size = crypto_stream_NONCEBYTES;
4985 4           key_size = crypto_stream_KEYBYTES;
4986 4           xor_ic_function = &crypto_stream_xsalsa20_xor_ic;
4987             }
4988              
4989 13           bc = SvUV(ic);
4990              
4991 13           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
4992 13 50         if ( nonce_len != nonce_size ) {
4993 0           croak("Invalid nonce");
4994             }
4995              
4996 13           key_buf = (unsigned char *)SvPV(key, key_len);
4997 13 50         if ( key_len != key_size ) {
4998 0           croak("Invalid key");
4999             }
5000              
5001 13           msg_buf = (unsigned char *)SvPV(msg, msg_len);
5002              
5003 13           bl = InitDataBytesLocker(aTHX_ msg_len);
5004              
5005 13           (*xor_ic_function)( bl->bytes, msg_buf, msg_len, nonce_buf, bc, key_buf);
5006              
5007 13 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
5008 13           XSRETURN(1);
5009             }
5010              
5011             void
5012             chacha20_ietf_xor_ic(self, msg, nonce, ic, key)
5013             SV * self
5014             SV * msg
5015             SV * nonce
5016             SV * ic
5017             SV * key
5018             INIT:
5019             STRLEN msg_len;
5020             STRLEN nonce_len;
5021             unsigned int bc;
5022             STRLEN key_len;
5023             unsigned char * msg_buf;
5024             unsigned char * nonce_buf;
5025             unsigned char * key_buf;
5026             DataBytesLocker *bl;
5027             PPCODE:
5028             {
5029             PERL_UNUSED_VAR(self);
5030              
5031 9 50         if ( GIMME_V == G_VOID ) {
5032 0           XSRETURN_EMPTY;
5033             }
5034              
5035 9           bc = SvUV(ic);
5036              
5037 9           nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
5038 9 50         if ( nonce_len != crypto_stream_chacha20_IETF_NONCEBYTES ) {
5039 0           croak("Invalid nonce");
5040             }
5041              
5042 9           key_buf = (unsigned char *)SvPV(key, key_len);
5043 9 50         if ( key_len != crypto_stream_chacha20_KEYBYTES ) {
5044 0           croak("Invalid key");
5045             }
5046              
5047 9           msg_buf = (unsigned char *)SvPV(msg, msg_len);
5048              
5049 9           bl = InitDataBytesLocker(aTHX_ msg_len);
5050              
5051 9           crypto_stream_chacha20_ietf_xor_ic( bl->bytes, msg_buf, msg_len, nonce_buf, bc, key_buf);
5052              
5053 9 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
5054 9           XSRETURN(1);
5055             }
5056              
5057             MODULE = Crypt::NaCl::Sodium PACKAGE = Data::BytesLocker
5058              
5059             FALLBACK: FALSE
5060              
5061             SV *
5062             new(class, bytes, ...)
5063             SV * class
5064             SV * bytes
5065             PROTOTYPE: $$;%
5066             INIT:
5067             DataBytesLocker *bl;
5068             unsigned char *buf;
5069             STRLEN buf_len;
5070 1015           int wipe = 0;
5071 1015           int readonly = 0;
5072             CODE:
5073             {
5074 1015 100         if ( SvREADONLY(bytes) ) {
5075 6           buf = (unsigned char *)SvPV(bytes, buf_len);
5076 6           readonly = 1;
5077             } else {
5078 1009           buf = (unsigned char *)SvPV_force(bytes, buf_len);
5079             }
5080              
5081 1015 100         if ( items > 2 && items != 4 ) {
    50          
5082 0           croak("Invalid number of arguments");
5083 1015 100         } else if ( items > 2 ) {
5084 3           int i = 0;
5085 3           STRLEN keylen = 0;
5086             char * key;
5087              
5088 5 100         for ( i = 2; i < items; i += 2 ) {
5089 3           key = SvPV(ST(i), keylen);
5090 3 50         if ( keylen == 4 && strnEQ(key, "wipe", 4) ) {
    50          
5091 3           wipe = SvTRUE(ST(i+1));
5092 3 50         if ( wipe && readonly ) {
    100          
5093 1           croak("Modification of a read-only value attempted");
5094             }
5095             } else {
5096 0           croak("Invalid argument: %s", key);
5097             }
5098             }
5099             }
5100              
5101 1014           bl = InitDataBytesLocker(aTHX_ buf_len);
5102 1014           memcpy(bl->bytes, buf, buf_len);
5103              
5104 1014 100         if ( wipe ) {
5105 2           sodium_memzero( buf, buf_len);
5106             }
5107              
5108 1014           RETVAL = DataBytesLocker2SV(aTHX_ bl);
5109             }
5110             OUTPUT:
5111             RETVAL
5112              
5113             SV *
5114             _overload_mult(self, other, swapped)
5115             SV * self
5116             SV * other
5117             SV * swapped
5118             PREINIT:
5119 8           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5120             INIT:
5121             DataBytesLocker *bl;
5122 8           unsigned int count = 0;
5123 8           unsigned int cur = 0;
5124             OVERLOAD: x
5125             CODE:
5126             {
5127 8 50         if ( sbl->locked ) {
5128 0           croak("Unlock BytesLocker object before accessing the data");
5129             }
5130              
5131 8           count = SvUV(other);
5132              
5133 8           bl = InitDataBytesLocker(aTHX_ sbl->length * count);
5134              
5135 48 100         while(count--) {
5136 40           memcpy(bl->bytes + sbl->length * cur++, sbl->bytes, sbl->length);
5137             }
5138              
5139 8           RETVAL = DataBytesLocker2SV(aTHX_ bl);
5140             }
5141             OUTPUT:
5142             RETVAL
5143              
5144              
5145             SV *
5146             _overload_concat(self, other, swapped)
5147             SV * self
5148             SV * other
5149             SV * swapped
5150             PREINIT:
5151 7           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5152             INIT:
5153             unsigned char *buf;
5154             STRLEN buf_len;
5155             DataBytesLocker *bl;
5156             OVERLOAD: .
5157             CODE:
5158             {
5159 7 50         if ( sbl->locked ) {
5160 0           croak("Unlock BytesLocker object before accessing the data");
5161             }
5162              
5163 7           buf = (unsigned char *)SvPV(other, buf_len);
5164              
5165 7           bl = InitDataBytesLocker(aTHX_ sbl->length + buf_len);
5166              
5167 7 100         if ( SvTRUE(swapped) ) {
5168 2           memcpy(memcpy(bl->bytes, buf, buf_len) + buf_len, sbl->bytes, sbl->length);
5169             }
5170             else {
5171 5           memcpy(memcpy(bl->bytes, sbl->bytes, sbl->length) + sbl->length, buf, buf_len);
5172             }
5173              
5174 7           RETVAL = DataBytesLocker2SV(aTHX_ bl);
5175             }
5176             OUTPUT:
5177             RETVAL
5178              
5179             void
5180             _overload_bool(self, ...)
5181             SV * self
5182             PREINIT:
5183 6766           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5184             INIT:
5185             int res;
5186             OVERLOAD: bool
5187             PPCODE:
5188             {
5189              
5190 6766 50         if ( sbl->locked ) {
5191 0           croak("Unlock BytesLocker object before accessing the data");
5192             }
5193              
5194 6766 50         if ( sbl->length ) {
5195 6766           res = 1;
5196             } else {
5197 0           res = 0;
5198             }
5199              
5200 6766 50         if ( res ) {
5201 6766           XSRETURN_YES;
5202             } else {
5203 0           XSRETURN_NO;
5204             }
5205             }
5206              
5207             void
5208             _overload_not(self, ...)
5209             SV * self
5210             PREINIT:
5211 0           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5212             INIT:
5213             int res;
5214             OVERLOAD: !
5215             PPCODE:
5216             {
5217              
5218 0 0         if ( sbl->locked ) {
5219 0           croak("Unlock BytesLocker object before accessing the data");
5220             }
5221              
5222 0 0         if ( sbl->length ) {
5223 0           res = 0;
5224             } else {
5225 0           res = 1;
5226             }
5227              
5228 0 0         if ( res ) {
5229 0           XSRETURN_YES;
5230             } else {
5231 0           XSRETURN_NO;
5232             }
5233             }
5234              
5235             void
5236             _overload_eq(self, other, swapped)
5237             SV * self
5238             SV * other
5239             SV * swapped
5240             PREINIT:
5241 1589           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5242             INIT:
5243             unsigned char *buf;
5244             STRLEN buf_len;
5245             int res;
5246             OVERLOAD: eq
5247             PPCODE:
5248             {
5249 1589 50         if ( sbl->locked ) {
5250 0           croak("Unlock BytesLocker object before accessing the data");
5251             }
5252              
5253 1589           buf = (unsigned char *)SvPV(other, buf_len);
5254              
5255 1589 50         if ( sbl->length != buf_len ) {
5256 0           croak("Variables of unequal length cannot be automatically compared. Please use memcmp() with the length argument provided");
5257             }
5258              
5259 1589 50         if ( sodium_memcmp(sbl->bytes, buf, sbl->length) == 0 ) {
5260 1589           res = 1;
5261             } else {
5262 0           res = 0;
5263             }
5264              
5265 1589 50         if ( res ) {
5266 1589           XSRETURN_YES;
5267             } else {
5268 0           XSRETURN_NO;
5269             }
5270             }
5271              
5272              
5273             void
5274             _overload_ne(self, other, swapped)
5275             SV * self
5276             SV * other
5277             SV * swapped
5278             PREINIT:
5279 1026           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5280             INIT:
5281             unsigned char *buf;
5282             STRLEN buf_len;
5283             int res;
5284             OVERLOAD: ne
5285             PPCODE:
5286             {
5287 1026 50         if ( sbl->locked ) {
5288 0           croak("Unlock BytesLocker object before accessing the data");
5289             }
5290              
5291 1026           buf = (unsigned char *)SvPV(other, buf_len);
5292              
5293 1026 50         if ( sbl->length != buf_len ) {
5294 0           croak("Variables of unequal length cannot be automatically compared. Please use memcmp() with the length argument provided");
5295             }
5296              
5297 1026 100         if ( sodium_memcmp(sbl->bytes, buf, sbl->length) == 0 ) {
5298 2           res = 0;
5299             } else {
5300 1024           res = 1;
5301             }
5302              
5303 1026 100         if ( res ) {
5304 1024           XSRETURN_YES;
5305             } else {
5306 2           XSRETURN_NO;
5307             }
5308             }
5309              
5310             void
5311             _overload_str(self, ...)
5312             SV * self
5313             PREINIT:
5314 300267           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5315             INIT:
5316             SV * pv;
5317             OVERLOAD: \"\"
5318             PPCODE:
5319             {
5320 300267 100         if ( sbl->locked ) {
5321 13           croak("Unlock BytesLocker object before accessing the data");
5322             }
5323              
5324 300254           pv = newSVpvn((unsigned char *)sbl->bytes, sbl->length);
5325 300254           SvREADONLY_on(pv);
5326              
5327 300254 50         mXPUSHs(pv);
5328             }
5329              
5330             void
5331             _overload_nomethod(self, ...)
5332             SV * self
5333             OVERLOAD: nomethod
5334             INIT:
5335             char * operator;
5336             PPCODE:
5337             {
5338 10           operator = SvPV_nolen(ST(3));
5339 10           croak("Operation \"%s\" is not supported", operator);
5340             }
5341              
5342             SV *
5343             clone(self)
5344             SV * self
5345             PREINIT:
5346 1           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5347             INIT:
5348             DataBytesLocker *bl;
5349             CODE:
5350             {
5351 1 50         if ( sbl->locked ) {
5352 0           croak("Unlock BytesLocker object before accessing the data");
5353             }
5354              
5355 1           bl = InitDataBytesLocker(aTHX_ sbl->length);
5356              
5357 1           memcpy(bl->bytes, sbl->bytes, sbl->length);
5358              
5359 1           RETVAL = DataBytesLocker2SV(aTHX_ bl);
5360             }
5361             OUTPUT:
5362             RETVAL
5363              
5364             void
5365             lock(self)
5366             SV * self
5367             PREINIT:
5368 4           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5369             INIT:
5370             int rc;
5371             PPCODE:
5372             {
5373 4           rc = sodium_mprotect_noaccess((void *)sbl->bytes);
5374              
5375 4 50         if (rc == 0 ) {
5376 4           sbl->locked = 1;
5377 4           XSRETURN_YES;
5378             }
5379              
5380 0           croak("Unable to lock memory: %s", Strerror(errno));
5381             }
5382              
5383             void
5384             unlock(self)
5385             SV * self
5386             PREINIT:
5387 13           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5388             INIT:
5389             int rc;
5390             PPCODE:
5391             {
5392 13           rc = sodium_mprotect_readonly((void *)sbl->bytes);
5393              
5394 13 50         if (rc == 0 ) {
5395 13           sbl->locked = 0;
5396 13           XSRETURN_YES;
5397             }
5398              
5399 0           croak("Unable to unlock memory: %s", Strerror(errno));
5400             }
5401              
5402             SV *
5403             length(self)
5404             SV * self
5405             PREINIT:
5406 690           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5407             CODE:
5408             {
5409 690 50         if ( sbl->locked ) {
5410 0           croak("Unlock BytesLocker object before accessing the data");
5411             }
5412              
5413 690           RETVAL = newSVuv((UV)sbl->length);
5414             }
5415             OUTPUT:
5416             RETVAL
5417              
5418             void
5419             is_locked(self, ...)
5420             SV * self
5421             PREINIT:
5422 7           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5423             PPCODE:
5424             {
5425 7 100         if ( sbl->locked ) {
5426 4           XSRETURN_YES;
5427             } else {
5428 3           XSRETURN_NO;
5429             }
5430             }
5431              
5432             SV *
5433             to_hex(self)
5434             SV * self
5435             PREINIT:
5436 6304           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5437             INIT:
5438             char * hex;
5439             size_t hex_len;
5440             CODE:
5441             {
5442 6304 50         if ( sbl->locked ) {
5443 0           croak("Unlock BytesLocker object before accessing the data");
5444             }
5445              
5446 6304           hex_len = sbl->length * 2;
5447 6304           hex = sodium_malloc(hex_len + 1);
5448 6304 50         if ( hex == NULL ) {
5449 0           croak("Could not allocate memory");
5450             }
5451 6304           sodium_bin2hex(hex, hex_len + 1, sbl->bytes, sbl->length);
5452              
5453 6304           RETVAL = newSVpvn((const char * const)hex, hex_len);
5454             }
5455             OUTPUT:
5456             RETVAL
5457             CLEANUP:
5458 6304           sodium_free(hex);
5459              
5460             void
5461             bytes(self)
5462             SV * self
5463             PREINIT:
5464 3464           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5465             INIT:
5466             SV * pv;
5467             PPCODE:
5468             {
5469 3464 100         if ( sbl->locked ) {
5470 1           croak("Unlock BytesLocker object before accessing the data");
5471             }
5472              
5473 3463           pv = newSVpvn((unsigned char *)sbl->bytes, sbl->length);
5474              
5475 3463 50         mXPUSHs(pv);
5476             }
5477              
5478             void
5479             memcmp(self, bytes, length = 0)
5480             SV * self
5481             SV * bytes
5482             unsigned long length
5483             PREINIT:
5484 1005           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5485             INIT:
5486             unsigned char * bytes_buf;
5487             STRLEN bytes_len;
5488             PPCODE:
5489             {
5490 1005 50         if ( GIMME_V == G_VOID ) {
5491 0           XSRETURN_EMPTY;
5492             }
5493              
5494 1005 50         if ( sbl->locked ) {
5495 0           croak("Unlock BytesLocker object before accessing the data");
5496             }
5497              
5498 1005 50         if (sv_derived_from(bytes, "Data::BytesLocker")) {
5499 0           DataBytesLocker* rbl = GetBytesLocker(aTHX_ bytes);
5500 0 0         if ( rbl->locked ) {
5501 0           croak("Unlock BytesLocker object before accessing the data");
5502             }
5503 0           bytes_buf = rbl->bytes;
5504 0           bytes_len = rbl->length;
5505             }
5506             else {
5507 1005           bytes_buf = (unsigned char *)SvPV(bytes, bytes_len);
5508             }
5509              
5510 1005 100         if ( length == 0 ) {
5511 2 100         if ( sbl->length != bytes_len ) {
5512 1           croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
5513             }
5514 1           length = bytes_len;
5515             } else {
5516 1003 100         if ( length > sbl->length ) {
5517 1           croak("The data is shorter then requested length");
5518             }
5519 1002 100         else if ( length > bytes_len ) {
5520 1           croak("The argument is shorter then requested length");
5521             }
5522             }
5523              
5524 1002 100         if ( sodium_memcmp(sbl->bytes, bytes_buf, length) == 0 ) {
5525 1           XSRETURN_YES;
5526             } else {
5527 1001           XSRETURN_NO;
5528             }
5529             }
5530              
5531              
5532             void
5533             compare(self, num, length = 0)
5534             SV * self
5535             SV * num
5536             unsigned long length
5537             PREINIT:
5538 2005           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5539             INIT:
5540             unsigned char * num_buf;
5541             STRLEN num_len;
5542             PPCODE:
5543             {
5544 2005 50         if ( GIMME_V == G_VOID ) {
5545 0           XSRETURN_EMPTY;
5546             }
5547              
5548 2005 50         if ( sbl->locked ) {
5549 0           croak("Unlock BytesLocker object before accessing the data");
5550             }
5551              
5552 2005 100         if (sv_derived_from(num, "Data::BytesLocker")) {
5553 1001           DataBytesLocker* rbl = GetBytesLocker(aTHX_ num);
5554 1001 50         if ( rbl->locked ) {
5555 0           croak("Unlock BytesLocker object before accessing the data");
5556             }
5557 1001           num_buf = rbl->bytes;
5558 1001           num_len = rbl->length;
5559             }
5560             else {
5561 1004           num_buf = (unsigned char *)SvPV(num, num_len);
5562             }
5563              
5564 2005 100         if ( length == 0 ) {
5565 2 100         if ( sbl->length != num_len ) {
5566 1           croak("Variables of unequal length cannot be automatically compared. Please provide the length argument");
5567             }
5568 1           length = num_len;
5569             } else {
5570 2003 100         if ( length > sbl->length ) {
5571 1           croak("The data is shorter then requested length");
5572             }
5573 2002 100         else if ( length > num_len ) {
5574 1           croak("The argument is shorter then requested length");
5575             }
5576             }
5577              
5578 2002           XSRETURN_IV( sodium_compare(sbl->bytes, num_buf, length) );
5579             }
5580              
5581             void
5582             increment(self)
5583             SV * self
5584             PREINIT:
5585 4817           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5586             INIT:
5587             SV * pv;
5588             DataBytesLocker *bl;
5589             PPCODE:
5590             {
5591 4817 50         if ( GIMME_V == G_VOID ) {
5592 0           XSRETURN_EMPTY;
5593             }
5594              
5595 4817 50         if ( sbl->locked ) {
5596 0           croak("Unlock BytesLocker object before accessing the data");
5597             }
5598              
5599 4817           bl = InitDataBytesLocker(aTHX_ sbl->length);
5600              
5601 4817           memcpy(bl->bytes, sbl->bytes, sbl->length);
5602              
5603 4817           sodium_increment(bl->bytes, sbl->length);
5604              
5605 4817 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
5606              
5607 4817           XSRETURN(1);
5608             }
5609              
5610             void
5611             add(self, num, ...)
5612             SV * self
5613             SV * num
5614             PREINIT:
5615 7           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5616             INIT:
5617             unsigned char * num_buf;
5618             STRLEN num_len;
5619             STRLEN inc_len;
5620             DataBytesLocker *bl;
5621             PPCODE:
5622             {
5623 7 50         if ( GIMME_V == G_VOID ) {
5624 0           XSRETURN_EMPTY;
5625             }
5626              
5627 7 50         if ( sbl->locked ) {
5628 0           croak("Unlock BytesLocker object before accessing the data");
5629             }
5630              
5631 7 50         if (sv_derived_from(num, "Data::BytesLocker")) {
5632 7           DataBytesLocker* rbl = GetBytesLocker(aTHX_ num);
5633 7 50         if ( rbl->locked ) {
5634 0           croak("Unlock BytesLocker object before accessing the data");
5635             }
5636 7           num_buf = rbl->bytes;
5637 7           num_len = rbl->length;
5638             }
5639             else {
5640 0           num_buf = (unsigned char *)SvPV(num, num_len);
5641             }
5642              
5643 7 100         if ( items == 3 ) {
5644 6           inc_len = (STRLEN)SvUV(ST(2));
5645 6 50         if ( inc_len > sbl->length ) {
5646 0           croak("The data is shorter then requested length");
5647             }
5648 6 50         else if ( inc_len > num_len ) {
5649 0           croak("The argument is shorter then requested length");
5650             }
5651             } else {
5652 1 50         if ( sbl->length != num_len ) {
5653 0           croak("Length of argument has to be equal to the length of data. Please provide the length argument");
5654             }
5655 1           inc_len = num_len;
5656             }
5657              
5658 7           bl = InitDataBytesLocker(aTHX_ sbl->length);
5659              
5660 7           memcpy(bl->bytes, sbl->bytes, sbl->length);
5661              
5662 7           sodium_add( bl->bytes, num_buf, inc_len );
5663              
5664 7 50         mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );
5665              
5666 7           XSRETURN(1);
5667             }
5668              
5669             void
5670             is_zero(self, ...)
5671             SV * self
5672             PREINIT:
5673 2           DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
5674             INIT:
5675             SV * pv;
5676             PPCODE:
5677             {
5678 2 50         if ( sbl->locked ) {
5679 0           croak("Unlock BytesLocker object before accessing the data");
5680             }
5681              
5682 2 100         if ( sodium_is_zero(sbl->bytes, sbl->length) == 1 ) {
5683 1           XSRETURN_YES;
5684             }
5685 1           XSRETURN_NO;
5686             }
5687              
5688              
5689             void
5690             DESTROY(self)
5691             SV * self
5692             PREINIT:
5693 114521           DataBytesLocker* bl = GetBytesLocker(aTHX_ self);
5694             PPCODE:
5695             {
5696 114521           sodium_free( bl->bytes );
5697 114521           Safefree(bl);
5698             }