File Coverage

Tweet.xs
Criterion Covered Total %
statement 142 269 52.7
branch 51 140 36.4
condition n/a
subroutine n/a
pod n/a
total 193 409 47.1


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #define NO_XSLOCKS
3              
4             #include "EXTERN.h"
5             #include "perl.h"
6             #include "XSUB.h"
7             #include "patchlevel.h"
8             #include "ppport.h"
9              
10             #include "tweetnacl.h"
11              
12             #define xNEWX(x, n, t) Newx(x, n + 1, t); \
13             if (x == NULL) \
14             croak("Out of memory"); \
15             x[n] = '\0';
16              
17             static const unsigned char salsa_sigma[16] = "expand 32-byte k";
18              
19             /* should be impossible to call this. provided for the symbol only */
20 0           void randombytes(unsigned char *out, unsigned long long len) {
21 0           croak("Unreachable");
22             }
23              
24 0           int sign_keypair(unsigned char *pk, unsigned char *sk)
25             {
26             unsigned char d[64];
27             long long p[4][16];
28             int i;
29              
30 0           crypto_hash(d, sk, 32);
31 0           d[0] &= 248;
32 0           d[31] &= 127;
33 0           d[31] |= 64;
34              
35 0           scalarbase(p,d);
36 0           pack(pk,p);
37              
38 0 0         for (i = 0; i < 32; ++i)
39 0           sk[32 + i] = pk[i];
40 0           return 0;
41             }
42              
43             MODULE = Crypt::NaCl::Tweet PACKAGE = Crypt::NaCl::Tweet
44              
45             PROTOTYPES: ENABLE
46              
47             SV * box(SV *msg, SV *nonce, SV *pk, SV *sk)
48              
49             PREINIT:
50             STRLEN full_len, msg_len, nonce_len, pk_len, sk_len;
51             unsigned char *ctext_buf, *full_buf, *msg_buf, *nonce_buf, *pk_buf, *sk_buf;
52              
53             CODE:
54 0           pk_buf = SvPVbyte(pk, pk_len);
55 0 0         if (pk_len != crypto_box_PUBLICKEYBYTES)
56 0           croak("Invalid public key length");
57              
58 0           sk_buf = SvPVbyte(sk, sk_len);
59 0 0         if (sk_len != crypto_box_SECRETKEYBYTES)
60 0           croak("Invalid secret key length");
61              
62 0           nonce_buf = SvPVbyte(nonce, nonce_len);
63 0 0         if (nonce_len != crypto_box_NONCEBYTES)
64 0           croak("Invalid nonce length");
65              
66 0           msg_buf = SvPVbyte(msg, msg_len);
67              
68             /* what a gross API */
69 0           full_len = msg_len + crypto_box_ZEROBYTES;
70 0 0         xNEWX(full_buf, full_len, unsigned char);
71 0           memzero(full_buf, crypto_box_ZEROBYTES);
72 0           Copy(msg_buf, full_buf + crypto_box_ZEROBYTES, msg_len, unsigned char);
73              
74 0 0         xNEWX(ctext_buf, full_len, unsigned char);
75              
76 0           crypto_box(ctext_buf, full_buf, full_len, nonce_buf, pk_buf, sk_buf);
77              
78 0           RETVAL = newSV(0);
79 0           sv_usepvn_flags(RETVAL, (char *)ctext_buf, full_len, SV_HAS_TRAILING_NUL);
80              
81             OUTPUT:
82             RETVAL
83              
84             SV * box_afternm(SV *msg, SV *nonce, SV *key)
85              
86             PREINIT:
87             STRLEN full_len, key_len, msg_len, nonce_len;
88             unsigned char *ctext_buf, *full_buf, *key_buf, *msg_buf, *nonce_buf;
89              
90             CODE:
91 1           key_buf = SvPVbyte(key, key_len);
92 1 50         if (key_len != crypto_box_BEFORENMBYTES)
93 0           croak("Invalid key length");
94              
95 1           nonce_buf = SvPVbyte(nonce, nonce_len);
96 1 50         if (nonce_len != crypto_box_NONCEBYTES)
97 0           croak("Invalid nonce length");
98              
99 1           msg_buf = SvPVbyte(msg, msg_len);
100              
101             /* what a gross API */
102 1           full_len = msg_len + crypto_box_ZEROBYTES;
103 1 50         xNEWX(full_buf, full_len, unsigned char);
104 1           memzero(full_buf, crypto_box_ZEROBYTES);
105 1           Copy(msg_buf, full_buf + crypto_box_ZEROBYTES, msg_len, unsigned char);
106              
107 1 50         xNEWX(ctext_buf, full_len, unsigned char);
108              
109 1           crypto_box_afternm(ctext_buf, full_buf, full_len, nonce_buf, key_buf);
110              
111 1           RETVAL = newSV(0);
112 1           sv_usepvn_flags(RETVAL, (char *)ctext_buf, full_len, SV_HAS_TRAILING_NUL);
113              
114             OUTPUT:
115             RETVAL
116              
117             SV * box_beforenm(SV *pk, SV *sk)
118              
119             PREINIT:
120             STRLEN pk_len, sk_len;
121             unsigned char *key_buf, *pk_buf, *sk_buf;
122              
123             CODE:
124 4           pk_buf = SvPVbyte(pk, pk_len);
125 4 50         if (pk_len != crypto_box_PUBLICKEYBYTES)
126 0           croak("Invalid public key length");
127              
128 4           sk_buf = SvPVbyte(sk, sk_len);
129 4 50         if (sk_len != crypto_box_SECRETKEYBYTES)
130 0           croak("Invalid secret key length");
131              
132 4 50         xNEWX(key_buf, crypto_box_BEFORENMBYTES, unsigned char);
133              
134 4           crypto_box_beforenm(key_buf, pk_buf, sk_buf);
135              
136 4           RETVAL = newSV(0);
137 4           sv_usepvn_flags(RETVAL, (char *)key_buf, crypto_box_BEFORENMBYTES, SV_HAS_TRAILING_NUL);
138              
139             OUTPUT:
140             RETVAL
141              
142             =for doc
143              
144             most of sign_keypair is cribbed from tweetnacl.c to avoid its call to
145             randombytes
146              
147             =cut
148              
149             SV * box_open(SV *ctext, SV *nonce, SV * pk, SV *sk)
150              
151             PREINIT:
152             STRLEN ctext_len, nonce_len, pk_len, sk_len;
153             unsigned char *ctext_buf, *full_buf, *nonce_buf, *pk_buf, *sk_buf;
154              
155             CODE:
156 0           pk_buf = SvPVbyte(pk, pk_len);
157 0 0         if (pk_len != crypto_box_PUBLICKEYBYTES)
158 0           croak("Invalid public key length");
159              
160 0           sk_buf = SvPVbyte(sk, sk_len);
161 0 0         if (sk_len != crypto_box_SECRETKEYBYTES)
162 0           croak("Invalid secret key length");
163              
164 0           nonce_buf = SvPVbyte(nonce, nonce_len);
165 0 0         if (nonce_len != crypto_secretbox_NONCEBYTES)
166 0           croak("Invalid nonce length");
167              
168 0           ctext_buf = SvPVbyte(ctext, ctext_len);
169              
170 0           full_buf = malloc(ctext_len);
171 0 0         if (full_buf == NULL)
172 0           croak("Out of memory");
173              
174 0 0         if (crypto_box_open(full_buf, ctext_buf, ctext_len, nonce_buf, pk_buf, sk_buf) != 0) {
175 0           free(full_buf);
176 0           XSRETURN_UNDEF;
177             }
178              
179 0           RETVAL = newSVpvn(full_buf + crypto_box_ZEROBYTES, ctext_len - crypto_box_ZEROBYTES);
180 0           free(full_buf);
181              
182             OUTPUT:
183             RETVAL
184              
185             SV * box_open_afternm(SV *ctext, SV *nonce, SV *key)
186              
187             PREINIT:
188             STRLEN ctext_len, key_len, nonce_len;
189             unsigned char *ctext_buf, *full_buf, *key_buf, *nonce_buf;
190              
191             CODE:
192 2           key_buf = SvPVbyte(key, key_len);
193 2 50         if (key_len != crypto_box_BEFORENMBYTES)
194 0           croak("Invalid key length");
195              
196 2           nonce_buf = SvPVbyte(nonce, nonce_len);
197 2 50         if (nonce_len != crypto_box_NONCEBYTES)
198 0           croak("Invalid nonce length");
199              
200 2           ctext_buf = SvPVbyte(ctext, ctext_len);
201              
202 2           full_buf = malloc(ctext_len);
203 2 50         if (full_buf == NULL)
204 0           croak("Out of memory");
205              
206 2 100         if (crypto_box_open_afternm(full_buf, ctext_buf, ctext_len, nonce_buf, key_buf) != 0) {
207 1           free(full_buf);
208 1           XSRETURN_UNDEF;
209             }
210              
211 1           RETVAL = newSVpvn(full_buf + crypto_box_ZEROBYTES, ctext_len - crypto_box_ZEROBYTES);
212 1           free(full_buf);
213              
214             OUTPUT:
215             RETVAL
216              
217             =for doc
218              
219             low-level and undocumented. included in case useful.
220              
221             =cut
222              
223             SV * core_salsa20(SV *in, SV *key)
224              
225             ALIAS:
226             core_hsalsa20 = 1
227              
228             PREINIT:
229             STRLEN key_len, key_len_req, in_len, in_len_req, out_len;
230             unsigned char *out_buf, *key_buf, *in_buf;
231             int (*func) (unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *);
232              
233             CODE:
234 0 0         switch(ix) {
235 0           case 1:
236 0           key_len_req = crypto_core_hsalsa20_tweet_KEYBYTES;
237 0           in_len_req = crypto_core_hsalsa20_tweet_INPUTBYTES;
238 0           out_len = crypto_core_hsalsa20_tweet_OUTPUTBYTES;
239 0           func = crypto_core_hsalsa20;
240 0           break;
241 0           default:
242 0           key_len_req = crypto_core_salsa20_tweet_KEYBYTES;
243 0           in_len_req = crypto_core_salsa20_tweet_INPUTBYTES;
244 0           out_len = crypto_core_salsa20_tweet_OUTPUTBYTES;
245 0           func = crypto_core_salsa20;
246 0           break;
247             }
248              
249 0           key_buf = SvPVbyte(key, key_len);
250 0 0         if (key_len != key_len_req)
251 0           croak("Invalid key length");
252              
253 0           in_buf = SvPVbyte(in, in_len);
254 0 0         if (in_len != in_len_req)
255 0           croak("Invalid input length");
256              
257 0 0         xNEWX(out_buf, out_len, unsigned char);
258              
259 0           func(out_buf, in_buf, key_buf, salsa_sigma);
260              
261 0           RETVAL = newSV(0);
262 0           sv_usepvn_flags(RETVAL, (char *)out_buf, out_len, SV_HAS_TRAILING_NUL);
263              
264             OUTPUT:
265             RETVAL
266              
267             =for doc
268              
269             low-level and undocumented. included in case useful.
270              
271             =cut
272              
273             SV * hashblocks(SV *msg)
274              
275             PREINIT:
276             STRLEN msg_len, rem;
277             unsigned char *msg_buf, *out_buf;
278              
279             CODE:
280 0           msg_buf = SvPVbyte(msg, msg_len);
281 0 0         if (msg_len & 127)
282 0           croak("Message length must be a multiple of 128");
283              
284 0 0         xNEWX(out_buf, crypto_hashblocks_STATEBYTES, unsigned char);
285              
286 0           crypto_hashblocks(out_buf, msg_buf, msg_len);
287              
288 0           RETVAL = newSV(0);
289 0           sv_usepvn_flags(RETVAL, (char *)out_buf, crypto_hashblocks_STATEBYTES, SV_HAS_TRAILING_NUL);
290              
291             OUTPUT:
292             RETVAL
293              
294             SV * scalarmult(SV *n, SV *p)
295              
296             PREINIT:
297             STRLEN n_len, p_len;
298             unsigned char *n_buf, *p_buf, *q_buf;
299              
300             CODE:
301 6           n_buf = SvPVbyte(n, n_len);
302 6 50         if (n_len != crypto_scalarmult_SCALARBYTES)
303 0           croak("Invalid scalar length");
304              
305 6           p_buf = SvPVbyte(p, p_len);
306 6 50         if (p_len != crypto_scalarmult_BYTES)
307 0           croak("Invalid group element length");
308              
309 6 50         xNEWX(q_buf, crypto_scalarmult_BYTES, unsigned char);
310              
311 6           crypto_scalarmult(q_buf, n_buf, p_buf);
312              
313 6           RETVAL = newSV(0);
314 6           sv_usepvn_flags(RETVAL, (char *)q_buf, crypto_scalarmult_BYTES, SV_HAS_TRAILING_NUL);
315              
316             OUTPUT:
317             RETVAL
318              
319             SV * scalarmult_base(SV *n)
320              
321             PREINIT:
322             STRLEN n_len;
323             unsigned char *n_buf, *q_buf;
324              
325             CODE:
326 2           n_buf = SvPVbyte(n, n_len);
327 2 50         if (n_len != crypto_scalarmult_SCALARBYTES)
328 0           croak("Invalid scalar length");
329              
330 2 50         xNEWX(q_buf, crypto_scalarmult_BYTES, unsigned char);
331              
332 2           crypto_scalarmult_base(q_buf, n_buf);
333              
334 2           RETVAL = newSV(0);
335 2           sv_usepvn_flags(RETVAL, (char *)q_buf, crypto_scalarmult_BYTES, SV_HAS_TRAILING_NUL);
336              
337             OUTPUT:
338             RETVAL
339              
340              
341             SV * hash(SV *msg)
342              
343             PREINIT:
344             STRLEN hash_len, msg_len;
345             unsigned char *mac_buf, *msg_buf;
346             int (*func) (unsigned char *, const unsigned char *, unsigned long long);
347              
348             CODE:
349 1 50         xNEWX(mac_buf, crypto_hash_BYTES, unsigned char);
350              
351 1           msg_buf = SvPVbyte(msg, msg_len);
352              
353 1           crypto_hash(mac_buf, msg_buf, msg_len);
354              
355 1           RETVAL = newSV(0);
356 1           sv_usepvn_flags(RETVAL, (char *)mac_buf, crypto_hash_BYTES, SV_HAS_TRAILING_NUL);
357              
358             OUTPUT:
359             RETVAL
360              
361             SV * onetimeauth(SV *msg, SV *key)
362              
363             PREINIT:
364             STRLEN key_len, msg_len;
365             unsigned char *auth_buf, *key_buf, *msg_buf;
366              
367             CODE:
368 1           key_buf = SvPVbyte(key, key_len);
369 1 50         if (key_len != crypto_onetimeauth_KEYBYTES)
370 0           croak("Invalid key length");
371              
372 1           msg_buf = SvPVbyte(msg, msg_len);
373              
374 1 50         xNEWX(auth_buf, crypto_onetimeauth_BYTES, unsigned char);
375              
376 1           crypto_onetimeauth(auth_buf, msg_buf, msg_len, key_buf);
377              
378 1           RETVAL = newSV(0);
379 1           sv_usepvn_flags(RETVAL, (char *)auth_buf, crypto_onetimeauth_BYTES, SV_HAS_TRAILING_NUL);
380              
381             OUTPUT:
382             RETVAL
383              
384             void onetimeauth_verify(SV *auth, SV *msg, SV *key)
385              
386             PREINIT:
387             STRLEN auth_len, key_len, msg_len;
388             unsigned char *auth_buf, *key_buf, *msg_buf;
389              
390             PPCODE:
391 2           auth_buf = SvPVbyte(auth, auth_len);
392 2 50         if (auth_len != crypto_onetimeauth_BYTES)
393 0           croak("Invalid authenticator length");
394              
395 2           key_buf = SvPVbyte(key, key_len);
396 2 50         if (key_len != crypto_onetimeauth_KEYBYTES)
397 0           croak("Invalid key length");
398              
399 2           msg_buf = SvPVbyte(msg, msg_len);
400              
401 2 100         if (crypto_onetimeauth_verify(auth_buf, msg_buf, msg_len, key_buf) == 0)
402 1           XSRETURN_YES;
403 1           XSRETURN_NO;
404              
405             SV * secretbox(SV *msg, SV *nonce, SV *key)
406              
407             PREINIT:
408             STRLEN full_len, key_len, msg_len, nonce_len;
409             unsigned char *ctext_buf, *full_buf, *key_buf, *msg_buf, *nonce_buf;
410              
411             CODE:
412 3           key_buf = SvPVbyte(key, key_len);
413 3 50         if (key_len != crypto_secretbox_KEYBYTES)
414 0           croak("Invalid key length");
415              
416 3           nonce_buf = SvPVbyte(nonce, nonce_len);
417 3 50         if (nonce_len != crypto_secretbox_NONCEBYTES)
418 0           croak("Invalid nonce length");
419              
420 3           msg_buf = SvPVbyte(msg, msg_len);
421              
422             /* what a gross API */
423 3           full_len = msg_len + crypto_secretbox_ZEROBYTES;
424 3 50         xNEWX(full_buf, full_len, unsigned char);
425 3           memzero(full_buf, crypto_secretbox_ZEROBYTES);
426 3           Copy(msg_buf, full_buf + crypto_secretbox_ZEROBYTES, msg_len, unsigned char);
427              
428 3 50         xNEWX(ctext_buf, full_len, unsigned char);
429              
430 3           crypto_secretbox(ctext_buf, full_buf, full_len, nonce_buf, key_buf);
431              
432 3           RETVAL = newSV(0);
433 3           sv_usepvn_flags(RETVAL, (char *)ctext_buf, full_len, SV_HAS_TRAILING_NUL);
434              
435             OUTPUT:
436             RETVAL
437              
438             SV * secretbox_open(SV *ctext, SV *nonce, SV *key)
439              
440             PREINIT:
441             STRLEN key_len, ctext_len, nonce_len;
442             unsigned char *ctext_buf, *key_buf, *nonce_buf, *full_buf;
443              
444             CODE:
445 4           key_buf = SvPVbyte(key, key_len);
446 4 50         if (key_len != crypto_secretbox_KEYBYTES)
447 0           croak("Invalid key length");
448              
449 4           nonce_buf = SvPVbyte(nonce, nonce_len);
450 4 50         if (nonce_len != crypto_secretbox_NONCEBYTES)
451 0           croak("Invalid nonce length");
452              
453 4           ctext_buf = SvPVbyte(ctext, ctext_len);
454              
455 4           full_buf = malloc(ctext_len);
456 4 50         if (full_buf == NULL)
457 0           croak("Out of memory");
458              
459 4 100         if (crypto_secretbox_open(full_buf, ctext_buf, ctext_len, nonce_buf, key_buf) != 0) {
460 3           free(full_buf);
461 3           XSRETURN_UNDEF;
462             }
463              
464 1           RETVAL = newSVpvn(full_buf + crypto_secretbox_ZEROBYTES, ctext_len - crypto_secretbox_ZEROBYTES);
465 1           free(full_buf);
466              
467             OUTPUT:
468             RETVAL
469              
470             SV * sign(SV *msg, SV *sk)
471              
472             PREINIT:
473             STRLEN msg_len, sk_len;
474             unsigned char *msg_buf, *sm_buf, *sk_buf;
475             long long unsigned sm_len;
476              
477             CODE:
478 2           sk_buf = SvPVbyte(sk, sk_len);
479 2 50         if (sk_len != crypto_sign_SECRETKEYBYTES)
480 0           croak("Invalid secret key length");
481              
482 2           msg_buf = SvPVbyte(msg, msg_len);
483              
484 2 50         xNEWX(sm_buf, msg_len + crypto_sign_BYTES + 1, unsigned char);
485              
486 2           crypto_sign(sm_buf, &sm_len, msg_buf, msg_len, sk_buf);
487 2           sm_buf[sm_len] = '\0';
488              
489 2           RETVAL = newSV(0);
490 2           sv_usepvn_flags(RETVAL, (char *)sm_buf, (STRLEN)sm_len, SV_HAS_TRAILING_NUL);
491              
492             OUTPUT:
493             RETVAL
494              
495             void sign_keypair()
496              
497             PREINIT:
498             SV *pk, *sk;
499             STRLEN pk_len, sk_len;
500             unsigned char d[64], *pk_buf, *sk_buf;
501             long long p[4];
502             int i, n;
503              
504             PPCODE:
505 0           ENTER;
506 0           SAVETMPS;
507 0 0         PUSHMARK(SP);
508 0 0         XPUSHs(sv_2mortal(newSViv(crypto_sign_SECRETKEYBYTES)));
509 0           PUTBACK;
510 0           n = call_pv("Crypt::NaCl::Tweet::random_bytes", G_SCALAR);
511 0           SPAGAIN;
512 0 0         if (n != 1)
513 0           croak("Failed to get random bytes (%d)", n);
514 0           sk = POPs;
515 0           sk_buf = SvPVbyte(sk, sk_len);
516              
517 0 0         if (sk_len != crypto_sign_SECRETKEYBYTES)
518 0           croak("random_bytes returned wrong number of bytes");
519              
520 0 0         xNEWX(pk_buf, crypto_box_PUBLICKEYBYTES, unsigned char);
521              
522 0           sign_keypair(pk_buf, sk_buf);
523              
524 0           pk = newSV(0);
525 0           sv_usepvn_flags(pk, (char *)pk_buf, crypto_box_PUBLICKEYBYTES, SV_HAS_TRAILING_NUL);
526              
527 0           SvREFCNT_inc(sk);
528 0           PUTBACK;
529 0 0         FREETMPS;
530 0           LEAVE;
531 0 0         mXPUSHs(pk);
532 0 0         mXPUSHs(sk);
533 0           XSRETURN(2);
534              
535             SV * sign_open(SV *sm, SV *pk)
536              
537             PREINIT:
538             STRLEN pk_len, sm_len;
539             unsigned char *msg_buf, *pk_buf, *sm_buf;
540             long long unsigned msg_len;
541              
542             CODE:
543 3           pk_buf = SvPVbyte(pk, pk_len);
544 3 50         if (pk_len != crypto_sign_PUBLICKEYBYTES)
545 0           croak("Invalid public key length");
546              
547 3           sm_buf = SvPVbyte(sm, sm_len);
548              
549 3 50         xNEWX(msg_buf, sm_len + 1, unsigned char);
550              
551 3 100         if (crypto_sign_open(msg_buf, &msg_len, sm_buf, sm_len, pk_buf) != 0) {
552 2           Safefree(msg_buf);
553 2           XSRETURN_UNDEF;
554             }
555 1           msg_buf[msg_len] = '\0';
556              
557 1           RETVAL = newSV(0);
558 1           sv_usepvn_flags(RETVAL, (char *)msg_buf, (STRLEN)msg_len, SV_HAS_TRAILING_NUL);
559              
560             OUTPUT:
561             RETVAL
562              
563             SV * stream(UV stream_len, SV *nonce, SV *key)
564              
565             PREINIT:
566             STRLEN key_len, nonce_len;
567             unsigned char *key_buf, *nonce_buf, *stream_buf;
568              
569             CODE:
570 1           key_buf = SvPVbyte(key, key_len);
571 1 50         if (key_len != crypto_stream_KEYBYTES)
572 0           croak("Invalid key length");
573              
574 1           nonce_buf = SvPVbyte(nonce, nonce_len);
575 1 50         if (nonce_len != crypto_stream_NONCEBYTES)
576 0           croak("Invalid nonce length");
577              
578 1 50         xNEWX(stream_buf, stream_len, unsigned char);
579              
580 1           crypto_stream(stream_buf, stream_len, nonce_buf, key_buf);
581              
582 1           RETVAL = newSV(0);
583 1           sv_usepvn_flags(RETVAL, (char *)stream_buf, stream_len, SV_HAS_TRAILING_NUL);
584              
585             OUTPUT:
586             RETVAL
587              
588             SV * stream_xor(SV *msg, SV *nonce, SV *key)
589              
590             PREINIT:
591             STRLEN key_len, msg_len, nonce_len;
592             unsigned char *ctext_buf, *key_buf, *msg_buf, *nonce_buf;
593              
594             CODE:
595 4           key_buf = SvPVbyte(key, key_len);
596 4 50         if (key_len != crypto_stream_KEYBYTES)
597 0           croak("Invalid key length");
598              
599 4           nonce_buf = SvPVbyte(nonce, nonce_len);
600 4 50         if (nonce_len != crypto_stream_NONCEBYTES)
601 0           croak("Invalid nonce length");
602              
603 4           msg_buf = SvPVbyte(msg, msg_len);
604              
605 4 50         xNEWX(ctext_buf, msg_len, unsigned char);
606              
607 4           crypto_stream_xor(ctext_buf, msg_buf, msg_len, nonce_buf, key_buf);
608              
609 4           RETVAL = newSV(0);
610 4           sv_usepvn_flags(RETVAL, (char *)ctext_buf, msg_len, SV_HAS_TRAILING_NUL);
611              
612             OUTPUT:
613             RETVAL
614              
615             void verify(SV *x, SV *y)
616              
617             ALIAS:
618             verify_16 = 1
619             verify_32 = 2
620              
621             PREINIT:
622             STRLEN x_len, y_len, req_len;
623             unsigned char *x_buf, *y_buf;
624             int (*func) (const unsigned char *, const unsigned char *);
625              
626             PPCODE:
627 4 100         switch(ix) {
628 2           case 2:
629 2           req_len = 32;
630 2           func = crypto_verify_32_tweet;
631 2           break;
632 2           default:
633 2           req_len = 16;
634 2           func = crypto_verify_16_tweet;
635 2           break;
636             }
637              
638 4           x_buf = SvPVbyte(x, x_len);
639 4           y_buf = SvPVbyte(y, y_len);
640 4 50         if (x_len != req_len || y_len != req_len)
    50          
641 0           croak("Invalid argument size(s); must be %d bytes", req_len);
642              
643 4 100         if (func(x_buf, y_buf) == 0)
644 2           XSRETURN_YES;
645 2           XSRETURN_NO;