File Coverage

Secp256k1.xs
Criterion Covered Total %
statement 355 402 88.3
branch 130 178 73.0
condition n/a
subroutine n/a
pod n/a
total 485 580 83.6


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #define SECP256K1_STATIC
6             #include
7             #include
8             #include
9             #include
10              
11             #define CURVE_SIZE 32
12             #define SCHNORR_SIGNATURE_SIZE 64
13             #define RECOVERABLE_SIGNATURE_SIZE 64
14              
15             typedef struct {
16             secp256k1_context *ctx;
17             secp256k1_pubkey *pubkey;
18             secp256k1_xonly_pubkey *xonly_pubkey;
19             secp256k1_pubkey **pubkeys;
20             unsigned int pubkeys_count;
21             secp256k1_ecdsa_signature *signature;
22             unsigned char *schnorr_signature;
23             secp256k1_ecdsa_recoverable_signature *recoverable_signature;
24             } secp256k1_perl;
25              
26             void secp256k1_perl_replace_pubkey(secp256k1_perl *perl_ctx, secp256k1_pubkey *new_pubkey);
27             void secp256k1_perl_replace_xonly_pubkey(secp256k1_perl *perl_ctx, secp256k1_xonly_pubkey *new_pubkey);
28             void secp256k1_perl_replace_signature(secp256k1_perl *perl_ctx, secp256k1_ecdsa_signature *new_signature);
29             void secp256k1_perl_replace_schnorr_signature(secp256k1_perl *perl_ctx, unsigned char *new_signature);
30             void secp256k1_perl_replace_recoverable_signature(secp256k1_perl *perl_ctx, secp256k1_ecdsa_recoverable_signature *new_signature);
31              
32 3           secp256k1_perl* secp256k1_perl_create()
33             {
34 3           secp256k1_context *secp_ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
35 3           secp256k1_perl *perl_ctx = malloc(sizeof *perl_ctx);
36 3           perl_ctx->ctx = secp_ctx;
37 3           perl_ctx->pubkey = NULL;
38 3           perl_ctx->xonly_pubkey = NULL;
39 3           perl_ctx->signature = NULL;
40 3           perl_ctx->schnorr_signature = NULL;
41 3           perl_ctx->recoverable_signature = NULL;
42 3           perl_ctx->pubkeys = NULL;
43 3           perl_ctx->pubkeys_count = 0;
44 3           return perl_ctx;
45             }
46              
47 8           void secp256k1_perl_clear(secp256k1_perl *perl_ctx)
48             {
49 8           secp256k1_perl_replace_pubkey(perl_ctx, NULL);
50 8           secp256k1_perl_replace_xonly_pubkey(perl_ctx, NULL);
51 8           secp256k1_perl_replace_signature(perl_ctx, NULL);
52 8           secp256k1_perl_replace_schnorr_signature(perl_ctx, NULL);
53 8           secp256k1_perl_replace_recoverable_signature(perl_ctx, NULL);
54              
55 8 100         if (perl_ctx->pubkeys_count > 0) {
56             int i;
57 10 100         for (i = 0; i < perl_ctx->pubkeys_count; ++i) {
58 6           free(perl_ctx->pubkeys[i]);
59             }
60              
61 4           free(perl_ctx->pubkeys);
62 4           perl_ctx->pubkeys_count = 0;
63 4           perl_ctx->pubkeys = NULL;
64             }
65 8           }
66              
67 3           void secp256k1_perl_destroy(secp256k1_perl *perl_ctx)
68             {
69 3           secp256k1_perl_clear(perl_ctx);
70 3           secp256k1_context_destroy(perl_ctx->ctx);
71 3           free(perl_ctx);
72 3           }
73              
74 54           void secp256k1_perl_replace_pubkey(secp256k1_perl *perl_ctx, secp256k1_pubkey *new_pubkey)
75             {
76 54 100         if (perl_ctx->pubkey != NULL) {
77 39           free(perl_ctx->pubkey);
78             }
79              
80 54           perl_ctx->pubkey = new_pubkey;
81 54           }
82              
83 18           void secp256k1_perl_replace_xonly_pubkey(secp256k1_perl *perl_ctx, secp256k1_xonly_pubkey *new_pubkey)
84             {
85 18 100         if (perl_ctx->xonly_pubkey != NULL) {
86 9           free(perl_ctx->xonly_pubkey);
87             }
88              
89 18           perl_ctx->xonly_pubkey = new_pubkey;
90 18           }
91              
92 36           void secp256k1_perl_replace_signature(secp256k1_perl *perl_ctx, secp256k1_ecdsa_signature *new_signature)
93             {
94 36 100         if (perl_ctx->signature != NULL) {
95 27           free(perl_ctx->signature);
96             }
97              
98 36           perl_ctx->signature = new_signature;
99 36           }
100              
101 21           void secp256k1_perl_replace_schnorr_signature(secp256k1_perl *perl_ctx, unsigned char *new_signature)
102             {
103 21 100         if (perl_ctx->schnorr_signature != NULL) {
104 12           free(perl_ctx->schnorr_signature);
105             }
106              
107 21           perl_ctx->schnorr_signature = new_signature;
108 21           }
109              
110 24           void secp256k1_perl_replace_recoverable_signature(secp256k1_perl *perl_ctx, secp256k1_ecdsa_recoverable_signature *new_signature)
111             {
112 24 100         if (perl_ctx->recoverable_signature != NULL) {
113 16           free(perl_ctx->recoverable_signature);
114             }
115              
116 24           perl_ctx->recoverable_signature = new_signature;
117 24           }
118              
119             /* HELPERS */
120              
121 210           secp256k1_perl* ctx_from_sv(SV *self)
122             {
123 210 100         if (!(sv_isobject(self) && sv_derived_from(self, "Bitcoin::Secp256k1"))) {
    50          
124 2           croak("calling Bitcoin::Secp256k1 methods is only valid in object context");
125             }
126              
127 208           return (secp256k1_perl*) SvIV(SvRV(self));
128             }
129              
130 146           unsigned char* bytestr_from_sv(SV *perlval, STRLEN *size)
131             {
132 146           return (unsigned char*) SvPVbyte(perlval, *size);
133             }
134              
135 95           unsigned char* size_bytestr_from_sv(SV *perlval, size_t wanted_size, char *argname)
136             {
137             STRLEN size;
138 95           unsigned char *bytestr = bytestr_from_sv(perlval, &size);
139              
140 95 100         if (size != wanted_size) {
141 5           croak("%s must be a bytestring of length %lu", argname, (unsigned long) wanted_size);
142             }
143              
144 90           return bytestr;
145             }
146              
147 34           secp256k1_pubkey* pubkey_from_sv(secp256k1_perl *ctx, SV *data)
148             {
149 34 50         if (!SvOK(data) || SvROK(data)) {
    50          
150 0           croak("public key must be defined and not a reference");
151             }
152              
153             size_t key_size;
154 34           unsigned char *key = bytestr_from_sv(data, &key_size);
155              
156 34           secp256k1_pubkey *result_pubkey = malloc(sizeof *result_pubkey);
157 34           int result = secp256k1_ec_pubkey_parse(
158 34           ctx->ctx,
159             result_pubkey,
160             key,
161             key_size
162             );
163              
164 34 100         if (!result) {
165 4           free(result_pubkey);
166 4           croak("the input does not appear to be a valid public key");
167             }
168              
169 30           return result_pubkey;
170             }
171              
172 9           secp256k1_xonly_pubkey* xonly_pubkey_from_sv(secp256k1_perl *ctx, SV *data)
173             {
174 9 50         if (!SvOK(data) || SvROK(data)) {
    50          
175 0           croak("xonly public key must be defined and not a reference");
176             }
177              
178 9           unsigned char *key = size_bytestr_from_sv(data, CURVE_SIZE, "xonly pubkey");
179              
180 8           secp256k1_xonly_pubkey *result_pubkey = malloc(sizeof *result_pubkey);
181 8           int result = secp256k1_xonly_pubkey_parse(
182 8           ctx->ctx,
183             result_pubkey,
184             key
185             );
186              
187 8 50         if (!result) {
188 0           free(result_pubkey);
189 0           croak("the input does not appear to be a valid xonly public key");
190             }
191              
192 8           return result_pubkey;
193             }
194              
195 5           void copy_bytestr(unsigned char *to, unsigned char *from, size_t size)
196             {
197             int i;
198 165 100         for (i = 0; i < size; ++i) {
199 160           to[i] = from[i];
200             }
201 5           }
202              
203 5           void clean_secret(unsigned char *secret)
204             {
205             int i;
206 165 100         for (i = 0; i < CURVE_SIZE; ++i) {
207 160           secret[i] = 0;
208             }
209 5           }
210              
211             /* XS code below */
212              
213             MODULE = Bitcoin::Secp256k1 PACKAGE = Bitcoin::Secp256k1
214              
215             PROTOTYPES: DISABLED
216              
217             SV*
218             new(classname)
219             SV *classname
220             CODE:
221             /* Calling perl function to randomize context */
222 3           dSP;
223 3 50         PUSHMARK(SP);
224              
225 3           SV *tmp = newSViv(CURVE_SIZE);
226              
227 3 50         EXTEND(SP, 1);
228 3           PUSHs(tmp);
229 3           PUTBACK;
230              
231 3           size_t count = call_pv("Bitcoin::Secp256k1::_random_bytes", G_SCALAR);
232 3           SvREFCNT_dec(tmp);
233              
234 3           SPAGAIN;
235              
236 3 50         if (count != 1) {
237 0           croak("fetching randomness went wrong in Bitcoin::Secp256k1::new");
238             }
239              
240 3           tmp = POPs;
241 3           PUTBACK;
242              
243             /* Randomness dump */
244             /* for (int i = 0; i < len; ++i) { warn("%d: %d", i, randomize[i]); } */
245              
246 3           secp256k1_perl* ctx = secp256k1_perl_create();
247              
248 3 50         if (SvOK(tmp)) {
249 0           unsigned char *randomize = size_bytestr_from_sv(tmp, CURVE_SIZE, "random data");
250              
251 0 0         if (!secp256k1_context_randomize(ctx->ctx, randomize)) {
252 0           secp256k1_perl_destroy(ctx);
253 0           croak("Failed to randomize secp256k1 context");
254             }
255             }
256              
257             /* Blessing the object */
258 3           SV *secp_sv = newSViv(0);
259 3           RETVAL = sv_setref_iv(secp_sv, SvPVbyte_nolen(classname), (uintptr_t) ctx);
260 3           SvREADONLY_on(secp_sv);
261             OUTPUT:
262             RETVAL
263              
264             # Clears public key and signature from the object
265             void
266             _clear(self)
267             SV *self
268             CODE:
269 5           secp256k1_perl *ctx = ctx_from_sv(self);
270 5           secp256k1_perl_clear(ctx);
271              
272              
273             # Getter / setter for the public key
274             SV*
275             _pubkey(self, ...)
276             SV *self
277             CODE:
278 57           secp256k1_perl *ctx = ctx_from_sv(self);
279 86 100         if (items > 1 && SvOK(ST(1))) {
    100          
280 34           SV *pubkey_data = ST(1);
281 34           secp256k1_pubkey *new_pubkey = pubkey_from_sv(ctx, pubkey_data);
282 30           secp256k1_perl_replace_pubkey(ctx, new_pubkey);
283             }
284 22 100         else if (items > 1) {
285 1           secp256k1_perl_replace_pubkey(ctx, NULL);
286             }
287              
288 52           unsigned int compression = SECP256K1_EC_COMPRESSED;
289              
290 52 100         if (items > 2 && !SvTRUE(ST(2))) {
    100          
291 3           compression = SECP256K1_EC_UNCOMPRESSED;
292             }
293              
294 52 100         if (ctx->pubkey != NULL) {
295             unsigned char key_output[65];
296 49           size_t key_size = 65;
297 49           secp256k1_ec_pubkey_serialize(
298 49           ctx->ctx,
299             key_output,
300             &key_size,
301 49           ctx->pubkey,
302             compression
303             );
304              
305 49           RETVAL = newSVpv((char*) key_output, key_size);
306             }
307             else {
308 3           RETVAL = &PL_sv_undef;
309             }
310             OUTPUT:
311             RETVAL
312              
313             # Getter / setter for the xonly public key
314             SV*
315             _xonly_pubkey(self, ...)
316             SV *self
317             CODE:
318 14           secp256k1_perl *ctx = ctx_from_sv(self);
319 22 100         if (items > 1 && SvOK(ST(1))) {
    100          
320 9           SV *pubkey_data = ST(1);
321 9           secp256k1_xonly_pubkey *new_pubkey = xonly_pubkey_from_sv(ctx, pubkey_data);
322 8           secp256k1_perl_replace_xonly_pubkey(ctx, new_pubkey);
323             }
324 5 100         else if (items > 1) {
325 1           secp256k1_perl_replace_xonly_pubkey(ctx, NULL);
326             }
327              
328 13 100         if (ctx->xonly_pubkey != NULL) {
329             unsigned char key_output[CURVE_SIZE];
330 10           secp256k1_xonly_pubkey_serialize(
331 10           ctx->ctx,
332             key_output,
333 10           ctx->xonly_pubkey
334             );
335              
336 10           RETVAL = newSVpv((char*) key_output, CURVE_SIZE);
337             }
338             else {
339 3           RETVAL = &PL_sv_undef;
340             }
341             OUTPUT:
342             RETVAL
343              
344             # Getter / setter for the signature
345             SV*
346             _signature(self, ...)
347             SV *self
348             CODE:
349 23           secp256k1_perl *ctx = ctx_from_sv(self);
350 36 100         if (items > 1 && SvOK(ST(1))) {
    100          
351 14           SV *new_signature = ST(1);
352 14 50         if (SvROK(new_signature)) {
353 0           croak("signature must not be a reference");
354             }
355              
356             size_t signature_size;
357 14           unsigned char *signature = bytestr_from_sv(new_signature, &signature_size);
358              
359 14           secp256k1_ecdsa_signature *result_signature = malloc(sizeof *result_signature);
360 14           int result = secp256k1_ecdsa_signature_parse_der(
361 14           ctx->ctx,
362             result_signature,
363             signature,
364             signature_size
365             );
366              
367 14 100         if (!result) {
368 1           free(result_signature);
369 1           croak("the input does not appear to be a valid signature");
370             }
371              
372 13           secp256k1_perl_replace_signature(ctx, result_signature);
373             }
374 9 100         else if (items > 1) {
375 1           secp256k1_perl_replace_signature(ctx, NULL);
376             }
377              
378 22 100         if (ctx->signature != NULL) {
379             unsigned char signature_output[72];
380 19           size_t signature_size = 72;
381 19           secp256k1_ecdsa_signature_serialize_der(
382 19           ctx->ctx,
383             signature_output,
384             &signature_size,
385 19           ctx->signature
386             );
387              
388 19           RETVAL = newSVpv((char*) signature_output, signature_size);
389             }
390             else {
391 3           RETVAL = &PL_sv_undef;
392             }
393             OUTPUT:
394             RETVAL
395              
396             # Getter / setter for the schnorr signature
397             SV*
398             _signature_schnorr(self, ...)
399             SV *self
400             CODE:
401 16           secp256k1_perl *ctx = ctx_from_sv(self);
402 24 100         if (items > 1 && SvOK(ST(1))) {
    100          
403 8           SV *new_signature = ST(1);
404 8 50         if (SvROK(new_signature)) {
405 0           croak("signature must not be a reference");
406             }
407              
408 8           unsigned char *signature = size_bytestr_from_sv(new_signature, SCHNORR_SIGNATURE_SIZE, "Schnorr signature");
409              
410 8           unsigned char *result_signature = malloc(sizeof *result_signature * SCHNORR_SIGNATURE_SIZE);
411 8           memcpy(result_signature, signature, sizeof *result_signature * SCHNORR_SIGNATURE_SIZE);
412              
413 8           secp256k1_perl_replace_schnorr_signature(ctx, result_signature);
414             }
415 8 100         else if (items > 1) {
416 1           secp256k1_perl_replace_schnorr_signature(ctx, NULL);
417             }
418              
419 16 100         if (ctx->schnorr_signature != NULL) {
420 13           RETVAL = newSVpv((char*) ctx->schnorr_signature, SCHNORR_SIGNATURE_SIZE);
421             }
422             else {
423 3           RETVAL = &PL_sv_undef;
424             }
425             OUTPUT:
426             RETVAL
427              
428             # Getter / setter for the recoverable signature
429             SV*
430             _signature_recoverable(self, ...)
431             SV *self
432             CODE:
433 16           secp256k1_perl *ctx = ctx_from_sv(self);
434 26 100         if (items > 1 && SvOK(ST(1))) {
    50          
435 10           SV *new_signature = ST(1);
436              
437 10 50         if (!SvOK(new_signature)) {
438 0           croak("recoverable signature must be defined");
439             }
440              
441             /* Expect hash ref with signature and recovery_id */
442 10 50         if (!SvROK(new_signature) || SvTYPE(SvRV(new_signature)) != SVt_PVHV) {
    50          
443 0           croak("recoverable signature must be a hash reference with 'signature' and 'recovery_id' keys");
444             }
445              
446 10           HV *sig_hash = (HV*) SvRV(new_signature);
447              
448 10           SV **sig_sv = hv_fetchs(sig_hash, "signature", 0);
449 10           SV **recovery_id_sv = hv_fetchs(sig_hash, "recovery_id", 0);
450              
451 10 50         if (!sig_sv || !recovery_id_sv) {
    50          
452 0           croak("recoverable signature must contain 'signature' and 'recovery_id' keys");
453             }
454              
455 10           unsigned char *sig_data = size_bytestr_from_sv(*sig_sv, RECOVERABLE_SIGNATURE_SIZE, "signature data");
456 10           int recovery_id = SvIV(*recovery_id_sv);
457              
458 10 50         if (recovery_id < 0 || recovery_id > 3) {
    50          
459 0           croak("recovery_id must be 0, 1, 2, or 3");
460             }
461              
462 10           secp256k1_ecdsa_recoverable_signature *parsed_signature = malloc(sizeof *parsed_signature);
463 10           int result = secp256k1_ecdsa_recoverable_signature_parse_compact(
464 10           ctx->ctx,
465             parsed_signature,
466             sig_data,
467             recovery_id
468             );
469              
470 10 50         if (!result) {
471 0           free(parsed_signature);
472 0           croak("failed to parse compact recoverable signature");
473             }
474              
475 10           secp256k1_perl_replace_recoverable_signature(ctx, parsed_signature);
476             }
477 6 50         else if (items > 1) {
478 0           secp256k1_perl_replace_recoverable_signature(ctx, NULL);
479             }
480              
481 16 50         if (ctx->recoverable_signature != NULL) {
482             unsigned char signature_data[RECOVERABLE_SIGNATURE_SIZE];
483             int recovery_id;
484              
485 16           int result = secp256k1_ecdsa_recoverable_signature_serialize_compact(
486 16           ctx->ctx,
487             signature_data,
488             &recovery_id,
489 16           ctx->recoverable_signature
490             );
491              
492 16 50         if (!result) {
493 0           croak("failed to serialize recoverable signature");
494             }
495              
496 16           HV *return_hash = newHV();
497 16           hv_stores(return_hash, "signature", newSVpvn((char*) signature_data, RECOVERABLE_SIGNATURE_SIZE));
498 16           hv_stores(return_hash, "recovery_id", newSViv(recovery_id));
499 16           RETVAL = newRV_noinc((SV*) return_hash);
500             }
501             else {
502 0           RETVAL = &PL_sv_undef;
503             }
504             OUTPUT:
505             RETVAL
506              
507             void
508             _push_pubkey(self)
509             SV *self
510             CODE:
511 6           secp256k1_perl *ctx = ctx_from_sv(self);
512              
513 6 100         if (ctx->pubkeys_count > 0) {
514 2           ctx->pubkeys = realloc(ctx->pubkeys, sizeof *ctx->pubkeys * (ctx->pubkeys_count + 1));
515             }
516             else {
517 4           ctx->pubkeys = malloc(sizeof *ctx->pubkeys);
518             }
519              
520 6           ctx->pubkeys[ctx->pubkeys_count++] = ctx->pubkey;
521 6           ctx->pubkey = NULL;
522              
523             # Creates a public key from a private key
524             void
525             _create_pubkey(self, privkey)
526             SV *self
527             SV *privkey
528             CODE:
529 7           secp256k1_perl *ctx = ctx_from_sv(self);
530 6           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private key");
531              
532 3           secp256k1_pubkey *result_pubkey = malloc(sizeof *result_pubkey);
533 3           int result = secp256k1_ec_pubkey_create(
534 3           ctx->ctx,
535             result_pubkey,
536             seckey_str
537             );
538              
539 3 50         if (!result) {
540 0           free(result_pubkey);
541 0           croak("creating pubkey failed (invalid private key?)");
542             }
543              
544 3           secp256k1_perl_replace_pubkey(ctx, result_pubkey);
545              
546             # Convert pubkey to xonly pubkey
547             void
548             _convert_pubkey_xonly(self)
549             SV *self
550             CODE:
551 1           secp256k1_perl *ctx = ctx_from_sv(self);
552 1 50         if (ctx->pubkey == NULL) {
553 0           croak("converting pubkey to xonly requires a pubkey");
554             }
555              
556 1           secp256k1_xonly_pubkey *xonly_pubkey = malloc(sizeof *xonly_pubkey);
557 1           int result = secp256k1_xonly_pubkey_from_pubkey(
558 1           ctx->ctx,
559             xonly_pubkey,
560             NULL,
561 1           ctx->pubkey
562             );
563              
564 1 50         if (!result) {
565 0           free(xonly_pubkey);
566 0           croak("converting pubkey failed");
567             }
568              
569 1           secp256k1_perl_replace_xonly_pubkey(ctx, xonly_pubkey);
570              
571             # Normalizes a signature. Returns false value if signature was already normalized
572             SV*
573             _normalize(self)
574             SV *self
575             CODE:
576 12           secp256k1_perl *ctx = ctx_from_sv(self);
577 12 50         if (ctx->signature == NULL) {
578 0           croak("normalization requires a signature");
579             }
580              
581 12           secp256k1_ecdsa_signature *result_signature = malloc(sizeof *result_signature);
582 12           int result = secp256k1_ecdsa_signature_normalize(
583 12           ctx->ctx,
584             result_signature,
585 12           ctx->signature
586             );
587              
588 12           secp256k1_perl_replace_signature(ctx, result_signature);
589 12 100         RETVAL = result ? &PL_sv_yes : &PL_sv_no;
590             OUTPUT:
591             RETVAL
592              
593             # Verifies a signature
594             SV*
595             _verify(self, message)
596             SV *self
597             SV *message
598             CODE:
599 8           secp256k1_perl *ctx = ctx_from_sv(self);
600 8 50         if (ctx->pubkey == NULL || ctx->signature == NULL) {
    50          
601 0           croak("verification requires both pubkey and signature");
602             }
603              
604 8           unsigned char *message_str = size_bytestr_from_sv(message, CURVE_SIZE, "digest");
605              
606 7           int result = secp256k1_ecdsa_verify(
607 7           ctx->ctx,
608 7           ctx->signature,
609             message_str,
610 7           ctx->pubkey
611             );
612              
613 7 100         RETVAL = result ? &PL_sv_yes : &PL_sv_no;
614             OUTPUT:
615             RETVAL
616              
617             # Verifies a Schnorr signature
618             SV*
619             _verify_schnorr(self, message)
620             SV *self
621             SV *message
622             CODE:
623 6           secp256k1_perl *ctx = ctx_from_sv(self);
624 6 50         if (ctx->xonly_pubkey == NULL || ctx->schnorr_signature == NULL) {
    50          
625 0           croak("verification requires both xonly pubkey and schnorr signature");
626             }
627              
628 6           unsigned char *message_str = size_bytestr_from_sv(message, CURVE_SIZE, "digest");
629              
630 6           int result = secp256k1_schnorrsig_verify(
631 6           ctx->ctx,
632 6           ctx->schnorr_signature,
633             message_str,
634             CURVE_SIZE,
635 6           ctx->xonly_pubkey
636             );
637              
638 6 100         RETVAL = result ? &PL_sv_yes : &PL_sv_no;
639             OUTPUT:
640             RETVAL
641              
642             # Signs a digest
643             void
644             _sign(self, privkey, message)
645             SV* self
646             SV* privkey
647             SV* message
648             CODE:
649 2           secp256k1_perl *ctx = ctx_from_sv(self);
650              
651 2           unsigned char *message_str = size_bytestr_from_sv(message, CURVE_SIZE, "digest");
652 2           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private key");
653              
654 2           secp256k1_ecdsa_signature *result_signature = malloc(sizeof *result_signature);
655 2           int result = secp256k1_ecdsa_sign(
656 2           ctx->ctx,
657             result_signature,
658             message_str,
659             seckey_str,
660             NULL,
661             NULL
662             );
663              
664 2 50         if (!result) {
665 0           free(result_signature);
666 0           croak("signing failed (nonce generation problem?)");
667             }
668              
669 2           secp256k1_perl_replace_signature(ctx, result_signature);
670              
671             # Signs a digest with Schnorr
672             void
673             _sign_schnorr(self, privkey, message)
674             SV* self
675             SV* privkey
676             SV* message
677             CODE:
678 4           secp256k1_perl *ctx = ctx_from_sv(self);
679              
680 4           unsigned char *message_str = size_bytestr_from_sv(message, CURVE_SIZE, "digest");
681 4           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private key");
682              
683             secp256k1_keypair keypair;
684 4           int result = secp256k1_keypair_create(
685 4           ctx->ctx,
686             &keypair,
687             seckey_str
688             );
689              
690 4 50         if (!result) {
691 0           croak("creating a keypair failed");
692             }
693              
694             /* Calling perl function to get auxiliary randomness */
695 4           dSP;
696 4 50         PUSHMARK(SP);
697              
698 4           SV *tmp = newSViv(CURVE_SIZE);
699              
700 4 50         EXTEND(SP, 1);
701 4           PUSHs(tmp);
702 4           PUTBACK;
703              
704 4           size_t count = call_pv("Bitcoin::Secp256k1::_schnorr_aux_random", G_SCALAR);
705 4           SvREFCNT_dec(tmp);
706              
707 4           SPAGAIN;
708              
709 4 50         if (count != 1) {
710 0           croak("fetching randomness went wrong in Bitcoin::Secp256k1::_sign_schnorr");
711             }
712              
713 4           tmp = POPs;
714 4           PUTBACK;
715              
716             /* Randomness dump */
717             /* for (int i = 0; i < len; ++i) { warn("%d: %d", i, randomize[i]); } */
718              
719 4           unsigned char *result_signature = malloc(sizeof *result_signature * SCHNORR_SIGNATURE_SIZE);
720 1           result = secp256k1_schnorrsig_sign32(
721 4           ctx->ctx,
722             result_signature,
723             message_str,
724             &keypair,
725 4 100         SvOK(tmp) ? size_bytestr_from_sv(tmp, CURVE_SIZE, "auxiliary randomness") : NULL
726             );
727              
728 4 50         if (!result) {
729 0           free(result_signature);
730 0           croak("Schnorr signing failed");
731             }
732              
733 4           secp256k1_perl_replace_schnorr_signature(ctx, result_signature);
734              
735             # Signs a recoverable digest
736             void
737             _sign_recoverable(self, privkey, message)
738             SV* self
739             SV* privkey
740             SV* message
741             CODE:
742 6           secp256k1_perl *ctx = ctx_from_sv(self);
743              
744 6           unsigned char *message_str = size_bytestr_from_sv(message, CURVE_SIZE, "digest");
745 6           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private key");
746              
747 6           secp256k1_ecdsa_recoverable_signature *signature = malloc(sizeof *signature);
748 6           int result = secp256k1_ecdsa_sign_recoverable(
749 6           ctx->ctx,
750             signature,
751             message_str,
752             seckey_str,
753             NULL,
754             NULL
755             );
756              
757 6 50         if (!result) {
758 0           free(signature);
759 0           croak("signing failed (nonce generation problem?)");
760             }
761              
762 6           secp256k1_perl_replace_recoverable_signature(ctx, signature);
763              
764             # Recover an ECDSA public key from a recoverable signature and message hash
765             void
766             _recover_pubkey_recoverable(self, message_hash)
767             SV* self
768             SV* message_hash
769             CODE:
770 10           secp256k1_perl *ctx = ctx_from_sv(self);
771              
772 10 50         if (ctx->recoverable_signature == NULL) {
773 0           croak("no recoverable signature available - sign first or set via _signature_recoverable");
774             }
775              
776 10           unsigned char *message_str = size_bytestr_from_sv(message_hash, CURVE_SIZE, "message hash");
777              
778 10           secp256k1_pubkey *result_pubkey = malloc(sizeof *result_pubkey);
779              
780 10           int result = secp256k1_ecdsa_recover(
781 10           ctx->ctx,
782             result_pubkey,
783 10           ctx->recoverable_signature,
784             message_str
785             );
786              
787 10 50         if (!result) {
788 0           free(result_pubkey);
789 0           croak("failed to recover public key from signature");
790             }
791              
792 10           secp256k1_perl_replace_pubkey(ctx, result_pubkey);
793              
794             # Checks whether a private key is valid
795             SV*
796             _verify_privkey(self, privkey)
797             SV* self
798             SV* privkey
799             CODE:
800 3           secp256k1_perl *ctx = ctx_from_sv(self);
801             STRLEN seckey_size;
802 3           unsigned char *seckey_str = bytestr_from_sv(privkey, &seckey_size);
803              
804 3           int result = (
805 3           seckey_size == CURVE_SIZE
806 3 100         && secp256k1_ec_seckey_verify(ctx->ctx, seckey_str)
    100          
807             );
808              
809 3 100         RETVAL = result ? &PL_sv_yes : &PL_sv_no;
810             OUTPUT:
811             RETVAL
812              
813             # Negates a private key
814             SV*
815             _privkey_negate(self, privkey)
816             SV *self
817             SV *privkey
818             CODE:
819 2           secp256k1_perl *ctx = ctx_from_sv(self);
820 2           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private key");
821              
822             unsigned char new_seckey[CURVE_SIZE];
823 2           copy_bytestr(new_seckey, seckey_str, CURVE_SIZE);
824              
825 2           int result = secp256k1_ec_seckey_negate(
826 2           ctx->ctx,
827             new_seckey
828             );
829              
830 2 50         if (!result) {
831 0           clean_secret(new_seckey);
832 0           croak("resulting negated privkey is not valid");
833             }
834              
835 2           RETVAL = newSVpv((char*) new_seckey, CURVE_SIZE);
836 2           clean_secret(new_seckey);
837             OUTPUT:
838             RETVAL
839              
840             # Negates a public key
841             void
842             _pubkey_negate(self)
843             SV *self
844             CODE:
845 1           secp256k1_perl *ctx = ctx_from_sv(self);
846              
847 1           int result = secp256k1_ec_pubkey_negate(
848 1           ctx->ctx,
849             ctx->pubkey
850             );
851              
852             /* NOTE: result is always 1 */
853 1 50         if (!result) {
854 0           croak("something went wrong while negating a pubkey");
855             }
856              
857             # Adds a tweak to private key
858             SV*
859             _privkey_add(self, privkey, tweak)
860             SV *self
861             SV *privkey
862             SV *tweak
863             CODE:
864 2           secp256k1_perl *ctx = ctx_from_sv(self);
865 2           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private key");
866 2           unsigned char *tweak_str = size_bytestr_from_sv(tweak, CURVE_SIZE, "tweak");
867              
868             unsigned char new_seckey[CURVE_SIZE];
869 2           copy_bytestr(new_seckey, seckey_str, CURVE_SIZE);
870              
871 2           int result = secp256k1_ec_seckey_tweak_add(
872 2           ctx->ctx,
873             new_seckey,
874             tweak_str
875             );
876              
877 2 100         if (!result) {
878 1           clean_secret(new_seckey);
879 1           croak("resulting added privkey is not valid");
880             }
881              
882 1           RETVAL = newSVpv((char*) new_seckey, CURVE_SIZE);
883 1           clean_secret(new_seckey);
884             OUTPUT:
885             RETVAL
886              
887             # Adds a tweak to public key
888             void
889             _pubkey_add(self, tweak)
890             SV *self
891             SV *tweak
892             CODE:
893 1           secp256k1_perl *ctx = ctx_from_sv(self);
894 1           unsigned char *tweak_str = size_bytestr_from_sv(tweak, CURVE_SIZE, "tweak");
895              
896 1           int result = secp256k1_ec_pubkey_tweak_add(
897 1           ctx->ctx,
898             ctx->pubkey,
899             tweak_str
900             );
901              
902 1 50         if (!result) {
903 0           croak("resulting added pubkey is not valid");
904             }
905              
906             # Multiplies private key by a tweak
907             SV*
908             _privkey_mul(self, privkey, tweak)
909             SV *self
910             SV *privkey
911             SV *tweak
912             CODE:
913 1           secp256k1_perl *ctx = ctx_from_sv(self);
914 1           unsigned char *seckey_str = size_bytestr_from_sv(privkey, CURVE_SIZE, "private_key");
915 1           unsigned char *tweak_str = size_bytestr_from_sv(tweak, CURVE_SIZE, "tweak");
916              
917             unsigned char new_seckey[CURVE_SIZE];
918 1           copy_bytestr(new_seckey, seckey_str, CURVE_SIZE);
919              
920 1           int result = secp256k1_ec_seckey_tweak_mul(
921 1           ctx->ctx,
922             new_seckey,
923             tweak_str
924             );
925              
926 1 50         if (!result) {
927 0           clean_secret(new_seckey);
928 0           croak("multiplication arguments are not valid");
929             }
930              
931 1           RETVAL = newSVpv((char*) new_seckey, CURVE_SIZE);
932 1           clean_secret(new_seckey);
933             OUTPUT:
934             RETVAL
935              
936             # Multiplies public key by a tweak
937             void
938             _pubkey_mul(self, tweak)
939             SV *self
940             SV *tweak
941             CODE:
942 2           secp256k1_perl *ctx = ctx_from_sv(self);
943 2           unsigned char *tweak_str = size_bytestr_from_sv(tweak, CURVE_SIZE, "tweak");
944              
945 2           int result = secp256k1_ec_pubkey_tweak_mul(
946 2           ctx->ctx,
947             ctx->pubkey,
948             tweak_str
949             );
950              
951 2 100         if (!result) {
952 1           croak("multiplication arguments are not valid");
953             }
954              
955             # Combines public keys together
956             void
957             _pubkey_combine(self)
958             SV *self
959             CODE:
960 2           secp256k1_perl *ctx = ctx_from_sv(self);
961              
962 2           secp256k1_pubkey *result_pubkey = malloc(sizeof *result_pubkey);
963 2           int result = secp256k1_ec_pubkey_combine(
964 2           ctx->ctx,
965             result_pubkey,
966 2           (const secp256k1_pubkey * const *) ctx->pubkeys,
967 2           ctx->pubkeys_count
968             );
969              
970 2 50         if (!result) {
971 0           free(result_pubkey);
972 0           croak("resulting sum of pubkeys is not valid");
973             }
974              
975 2           secp256k1_perl_replace_pubkey(ctx, result_pubkey);
976              
977              
978             # Destructor
979             void
980             DESTROY(self)
981             SV *self
982             CODE:
983 3           secp256k1_perl_destroy(ctx_from_sv(self));
984              
985             # Do a selftest on module load
986             BOOT:
987 3           secp256k1_selftest();
988