File Coverage

inc/CryptX_PK_Ed25519.xs.inc
Criterion Covered Total %
statement 59 192 30.7
branch 27 118 22.8
condition n/a
subroutine n/a
pod n/a
total 86 310 27.7


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::PK::Ed25519
2              
3             PROTOTYPES: DISABLE
4              
5             Crypt::PK::Ed25519
6             _new(Class)
7             CODE:
8             {
9             int rv;
10 2           Newz(0, RETVAL, 1, struct ed25519_struct);
11 2 50         if (!RETVAL) croak("FATAL: Newz failed");
12 2           RETVAL->initialized = 0;
13 2           RETVAL->pindex = find_prng("chacha20");
14 2           RETVAL->last_pid = (IV)PerlProc_getpid();
15 2 50         if (RETVAL->pindex == -1) {
16 0           zeromem(RETVAL, sizeof(*RETVAL));
17 0           Safefree(RETVAL);
18 0           croak("FATAL: find_prng('chacha20') failed");
19             }
20 2           rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */
21 2 50         if (rv != CRYPT_OK) {
22 0           zeromem(RETVAL, sizeof(*RETVAL));
23 0           Safefree(RETVAL);
24 0           croak("FATAL: rng_make_prng failed: %s", error_to_string(rv));
25             }
26             }
27             OUTPUT:
28             RETVAL
29              
30             void
31             generate_key(Crypt::PK::Ed25519 self)
32             PPCODE:
33             {
34             int rv;
35 1           self->initialized = 0;
36 1           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
37 1           rv = ed25519_make_key(&self->pstate, self->pindex, &self->key);
38 1 50         if (rv != CRYPT_OK) croak("FATAL: ed25519_make_key failed: %s", error_to_string(rv));
39 1           self->initialized = 1;
40 1 50         XPUSHs(ST(0)); /* return self */
41             }
42              
43             void
44             _import(Crypt::PK::Ed25519 self, SV * key_data)
45             PPCODE:
46             {
47             int rv;
48 0           unsigned char *data=NULL;
49 0           STRLEN data_len=0;
50              
51 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
52 0           self->initialized = 0;
53 0           rv = ed25519_import(data, (unsigned long)data_len, &self->key);
54 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import failed: %s", error_to_string(rv));
55 0           self->initialized = 1;
56 0 0         XPUSHs(ST(0)); /* return self */
57             }
58              
59             void
60             _import_pkcs8(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
61             PPCODE:
62             {
63             int rv;
64 0           unsigned char *data = NULL;
65 0           STRLEN data_len = 0;
66 0           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
67              
68 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
69 0           self->initialized = 0;
70 0 0         if (SvOK(passwd)) {
71 0           rv = ed25519_import_pkcs8(data, (unsigned long)data_len, &pw_ctx, &self->key);
72             }
73             else {
74 0           rv = ed25519_import_pkcs8(data, (unsigned long)data_len, NULL, &self->key);
75             }
76 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_pkcs8 failed: %s", error_to_string(rv));
77 0           self->initialized = 1;
78 0 0         XPUSHs(ST(0)); /* return self */
79             }
80              
81             void
82             _import_pem(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
83             PPCODE:
84             {
85             int rv;
86 0           unsigned char *data = NULL;
87 0           STRLEN data_len = 0;
88 0           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
89             ltc_pka_key key_from_pem;
90              
91 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
92 0           self->initialized = 0;
93 0 0         if (SvOK(passwd)) {
94 0           rv = pem_decode_pkcs(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
95             }
96             else {
97 0           rv = pem_decode_pkcs(data, (unsigned long)data_len, &key_from_pem, NULL);
98             }
99 0 0         if (rv != CRYPT_OK) croak("FATAL: pem_decode_pkcs failed: %s", error_to_string(rv));
100 0 0         if (key_from_pem.id != LTC_PKA_ED25519) croak("FATAL: pem_decode_pkcs decoded non-Ed25519 key");
101 0           self->key = key_from_pem.u.ed25519;
102 0           self->initialized = 1;
103 0 0         XPUSHs(ST(0)); /* return self */
104             }
105              
106             void
107             _import_openssh(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
108             PPCODE:
109             {
110             int rv;
111 3           unsigned char *data = NULL;
112 3           STRLEN data_len = 0;
113 3           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
114             ltc_pka_key key_from_pem;
115              
116 3           data = (unsigned char *)SvPVbyte(key_data, data_len);
117 3           self->initialized = 0;
118 3 100         if (SvOK(passwd)) {
119 1           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
120             }
121             else {
122 2           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, NULL);
123             }
124 3 50         if (rv != CRYPT_OK) croak("FATAL: pem_decode_openssh failed: %s", error_to_string(rv));
125 3 50         if (key_from_pem.id != LTC_PKA_ED25519) croak("FATAL: pem_decode_openssh decoded non-Ed25519 key");
126 3           self->key = key_from_pem.u.ed25519;
127 3           self->initialized = 1;
128 3 50         XPUSHs(ST(0)); /* return self */
129             }
130              
131             void
132             _import_x509(Crypt::PK::Ed25519 self, SV * key_data)
133             PPCODE:
134             {
135             int rv;
136 0           unsigned char *data=NULL;
137 0           STRLEN data_len=0;
138              
139 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
140 0           self->initialized = 0;
141 0           rv = ed25519_import_x509(data, (unsigned long)data_len, &self->key);
142 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_x509 failed: %s", error_to_string(rv));
143 0           self->initialized = 1;
144 0 0         XPUSHs(ST(0)); /* return self */
145             }
146              
147             void
148             _import_raw(Crypt::PK::Ed25519 self, SV * key, int which)
149             PPCODE:
150             {
151             int rv;
152 3           unsigned char *key_data=NULL;
153 3           STRLEN key_len=0;
154              
155 3 50         if (SvOK(key)) {
156 3           key_data = (unsigned char *)SvPVbyte(key, key_len);
157             }
158 3           self->initialized = 0;
159 3 100         if (which == 0) {
160 2           rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key);
161             }
162 1 50         else if (which == 1) {
163 1           rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key);
164             }
165             else {
166 0           croak("FATAL: import_raw invalid type '%d'", which);
167             }
168 3 50         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_raw failed: %s", error_to_string(rv));
169 3           self->initialized = 1;
170 3 50         XPUSHs(ST(0)); /* return self */
171             }
172              
173             int
174             is_private(Crypt::PK::Ed25519 self)
175             CODE:
176 6 50         if (self->initialized == 0) XSRETURN_UNDEF;
177 6 100         RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
178             OUTPUT:
179             RETVAL
180              
181             SV*
182             key2hash(Crypt::PK::Ed25519 self)
183             PREINIT:
184             HV *rv_hash;
185             char buf[32 * 2 + 1];
186             unsigned long blen;
187             SV **not_used;
188             int rv;
189             CODE:
190 9 50         if (self->initialized == 0) XSRETURN_UNDEF;
191 9           rv_hash = newHV();
192             /* priv */
193 9 100         if (self->key.type == PK_PRIVATE) {
194 5           blen = sizeof(buf);
195 5           rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0);
196 5 50         if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
197 5           not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0);
198             }
199             else {
200 4           not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */
201             }
202             /* pub */
203 9           blen = sizeof(buf);
204 9           rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0);
205 9 50         if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
206 9           not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0);
207             /* curve */
208 9           not_used = hv_store(rv_hash, "curve", 5, newSVpv("ed25519", 0), 0);
209             LTC_UNUSED_PARAM(not_used);
210 9           RETVAL = newRV_noinc((SV*)rv_hash);
211             OUTPUT:
212             RETVAL
213              
214             SV*
215             export_key_der(Crypt::PK::Ed25519 self, char * type)
216             CODE:
217             {
218             int rv;
219             unsigned char out[4096];
220 0           unsigned long int out_len = sizeof(out);
221              
222 0           RETVAL = newSVpvn(NULL, 0); /* undef */
223 0 0         if (strEQ(type, "private")) {
224 0           rv = ed25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key);
225 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv));
226 0           sv_setpvn(RETVAL, (char*)out, out_len);
227             }
228 0 0         else if (strEQ(type, "public")) {
229 0           rv = ed25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key);
230 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv));
231 0           sv_setpvn(RETVAL, (char*)out, out_len);
232             }
233             else {
234 0           croak("FATAL: export_key_der invalid type '%s'", type);
235             }
236 0           zeromem(out, sizeof(out));
237             }
238             OUTPUT:
239             RETVAL
240              
241             SV*
242             export_key_raw(Crypt::PK::Ed25519 self, char * type)
243             CODE:
244             {
245             int rv;
246             unsigned char out[32];
247 0           unsigned long int out_len = sizeof(out);
248              
249 0           RETVAL = newSVpvn(NULL, 0); /* undef */
250 0 0         if (strEQ(type, "private")) {
251 0           rv = ed25519_export(out, &out_len, PK_PRIVATE, &self->key);
252 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE) failed: %s", error_to_string(rv));
253 0           sv_setpvn(RETVAL, (char*)out, out_len);
254             }
255 0 0         else if (strEQ(type, "public")) {
256 0           rv = ed25519_export(out, &out_len, PK_PUBLIC, &self->key);
257 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC) failed: %s", error_to_string(rv));
258 0           sv_setpvn(RETVAL, (char*)out, out_len);
259             }
260             else {
261 0           croak("FATAL: export_key_raw invalid type '%s'", type);
262             }
263 0           zeromem(out, sizeof(out));
264             }
265             OUTPUT:
266             RETVAL
267              
268             SV *
269             sign_message(Crypt::PK::Ed25519 self, SV * data)
270             CODE:
271             {
272             int rv;
273 0           unsigned char buffer[64], *data_ptr = NULL;
274 0           unsigned long buffer_len = 64;
275 0           STRLEN data_len = 0;
276              
277 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
278 0           rv = ed25519_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key);
279 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_sign failed: %s", error_to_string(rv));
280 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
281 0           zeromem(buffer, sizeof(buffer));
282             }
283             OUTPUT:
284             RETVAL
285              
286             int
287             verify_message(Crypt::PK::Ed25519 self, SV * sig, SV * data)
288             CODE:
289             {
290             int rv, stat;
291 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL;
292 0           STRLEN data_len = 0, sig_len = 0;
293              
294 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
295 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
296 0           RETVAL = 0;
297 0           stat = 0;
298 0           rv = ed25519_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len, &stat, &self->key);
299 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
300             }
301             OUTPUT:
302             RETVAL
303              
304             SV *
305             sign_message_ctx(Crypt::PK::Ed25519 self, SV * data, SV * ctx)
306             CODE:
307             {
308             int rv;
309 0           unsigned char buffer[64], *data_ptr = NULL, *ctx_ptr = NULL;
310 0           unsigned long buffer_len = 64;
311 0           STRLEN data_len = 0, ctx_len = 0;
312              
313 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
314 0           ctx_ptr = (unsigned char *)SvPVbyte(ctx, ctx_len);
315 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
316 0           rv = ed25519ctx_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
317 0           ctx_ptr, (unsigned long)ctx_len, &self->key);
318 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519ctx_sign failed: %s", error_to_string(rv));
319 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
320 0           zeromem(buffer, sizeof(buffer));
321             }
322             OUTPUT:
323             RETVAL
324              
325             int
326             verify_message_ctx(Crypt::PK::Ed25519 self, SV * sig, SV * data, SV * ctx)
327             CODE:
328             {
329             int rv, stat;
330 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL, *ctx_ptr = NULL;
331 0           STRLEN data_len = 0, sig_len = 0, ctx_len = 0;
332              
333 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
334 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
335 0           ctx_ptr = (unsigned char *)SvPVbyte(ctx, ctx_len);
336 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
337 0           RETVAL = 0;
338 0           stat = 0;
339 0           rv = ed25519ctx_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len,
340 0           ctx_ptr, (unsigned long)ctx_len, &stat, &self->key);
341 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
342             }
343             OUTPUT:
344             RETVAL
345              
346             SV *
347             sign_message_ph(Crypt::PK::Ed25519 self, SV * data, ...)
348             CODE:
349             {
350             int rv;
351 0           unsigned char buffer[64], *data_ptr = NULL, *ctx_ptr = NULL;
352 0           unsigned long buffer_len = 64;
353 0           STRLEN data_len = 0, ctx_len = 0;
354              
355 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
356 0 0         if (items > 2 && SvOK(ST(2))) {
    0          
357 0           ctx_ptr = (unsigned char *)SvPVbyte(ST(2), ctx_len);
358 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
359             }
360 0           rv = ed25519ph_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
361 0           ctx_ptr, (unsigned long)ctx_len, &self->key);
362 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519ph_sign failed: %s", error_to_string(rv));
363 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
364 0           zeromem(buffer, sizeof(buffer));
365             }
366             OUTPUT:
367             RETVAL
368              
369             int
370             verify_message_ph(Crypt::PK::Ed25519 self, SV * sig, SV * data, ...)
371             CODE:
372             {
373             int rv, stat;
374 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL, *ctx_ptr = NULL;
375 0           STRLEN data_len = 0, sig_len = 0, ctx_len = 0;
376              
377 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
378 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
379 0 0         if (items > 3 && SvOK(ST(3))) {
    0          
380 0           ctx_ptr = (unsigned char *)SvPVbyte(ST(3), ctx_len);
381 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
382             }
383 0           RETVAL = 0;
384 0           stat = 0;
385 0           rv = ed25519ph_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len,
386 0           ctx_ptr, (unsigned long)ctx_len, &stat, &self->key);
387 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
388             }
389             OUTPUT:
390             RETVAL
391              
392             void
393             DESTROY(Crypt::PK::Ed25519 self)
394             CODE:
395 2 50         if (self->pindex >= 0 && prng_is_valid(self->pindex) == CRYPT_OK && prng_descriptor[self->pindex].done) {
    50          
    50          
396 2           prng_descriptor[self->pindex].done(&self->pstate);
397             }
398 2           zeromem(self, sizeof(*self));
399 2           Safefree(self);