File Coverage

inc/CryptX_PK_Ed25519.xs.inc
Criterion Covered Total %
statement 60 197 30.4
branch 27 118 22.8
condition n/a
subroutine n/a
pod n/a
total 87 315 27.6


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) {
101 0           pka_key_free(&key_from_pem);
102 0           croak("FATAL: pem_decode_pkcs decoded non-Ed25519 key");
103             }
104 0           self->key = key_from_pem.u.ed25519;
105 0           self->initialized = 1;
106 0 0         XPUSHs(ST(0)); /* return self */
107             }
108              
109             void
110             _import_openssh(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
111             PPCODE:
112             {
113             int rv;
114 3           unsigned char *data = NULL;
115 3           STRLEN data_len = 0;
116 3           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
117             ltc_pka_key key_from_pem;
118              
119 3           data = (unsigned char *)SvPVbyte(key_data, data_len);
120 3           self->initialized = 0;
121 3 100         if (SvOK(passwd)) {
122 1           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
123             }
124             else {
125 2           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, NULL);
126             }
127 3 50         if (rv != CRYPT_OK) croak("FATAL: pem_decode_openssh failed: %s", error_to_string(rv));
128 3 50         if (key_from_pem.id != LTC_PKA_ED25519) {
129 0           pka_key_free(&key_from_pem);
130 0           croak("FATAL: pem_decode_openssh decoded non-Ed25519 key");
131             }
132 3           self->key = key_from_pem.u.ed25519;
133 3           self->initialized = 1;
134 3 50         XPUSHs(ST(0)); /* return self */
135             }
136              
137             void
138             _import_x509(Crypt::PK::Ed25519 self, SV * key_data)
139             PPCODE:
140             {
141             int rv;
142 0           unsigned char *data=NULL;
143 0           STRLEN data_len=0;
144              
145 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
146 0           self->initialized = 0;
147 0           rv = ed25519_import_x509(data, (unsigned long)data_len, &self->key);
148 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_x509 failed: %s", error_to_string(rv));
149 0           self->initialized = 1;
150 0 0         XPUSHs(ST(0)); /* return self */
151             }
152              
153             void
154             _import_raw(Crypt::PK::Ed25519 self, SV * key, int which)
155             PPCODE:
156             {
157             int rv;
158 3           unsigned char *key_data=NULL;
159 3           STRLEN key_len=0;
160              
161 3 50         if (SvOK(key)) {
162 3           key_data = (unsigned char *)SvPVbyte(key, key_len);
163             }
164 3           self->initialized = 0;
165 3 100         if (which == 0) {
166 2           rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key);
167             }
168 1 50         else if (which == 1) {
169 1           rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key);
170             }
171             else {
172 0           croak("FATAL: import_raw invalid type '%d'", which);
173             }
174 3 50         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_raw failed: %s", error_to_string(rv));
175 3           self->initialized = 1;
176 3 50         XPUSHs(ST(0)); /* return self */
177             }
178              
179             int
180             is_private(Crypt::PK::Ed25519 self)
181             CODE:
182 6 50         if (self->initialized == 0) XSRETURN_UNDEF;
183 6 100         RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
184             OUTPUT:
185             RETVAL
186              
187             SV*
188             key2hash(Crypt::PK::Ed25519 self)
189             PREINIT:
190             HV *rv_hash;
191             char buf[32 * 2 + 1];
192             unsigned long blen;
193             SV **not_used;
194             int rv;
195             CODE:
196 9 50         if (self->initialized == 0) XSRETURN_UNDEF;
197 9           rv_hash = newHV();
198             /* priv */
199 9 100         if (self->key.type == PK_PRIVATE) {
200 5           blen = sizeof(buf);
201 5           rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0);
202 5 50         if (rv != CRYPT_OK) { zeromem(buf, sizeof(buf)); croak("FATAL: base16_encode failed: %s", error_to_string(rv)); }
203 5           not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0);
204             }
205             else {
206 4           not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */
207             }
208             /* pub */
209 9           blen = sizeof(buf);
210 9           rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0);
211 9 50         if (rv != CRYPT_OK) { zeromem(buf, sizeof(buf)); croak("FATAL: base16_encode failed: %s", error_to_string(rv)); }
212 9           not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0);
213             /* curve */
214 9           not_used = hv_store(rv_hash, "curve", 5, newSVpv("ed25519", 0), 0);
215             LTC_UNUSED_PARAM(not_used);
216 9           zeromem(buf, sizeof(buf));
217 9           RETVAL = newRV_noinc((SV*)rv_hash);
218             OUTPUT:
219             RETVAL
220              
221             SV*
222             export_key_der(Crypt::PK::Ed25519 self, char * type)
223             CODE:
224             {
225             int rv;
226             unsigned char out[4096];
227 0           unsigned long int out_len = sizeof(out);
228              
229 0           RETVAL = newSVpvn(NULL, 0); /* undef */
230 0 0         if (strEQ(type, "private")) {
231 0           rv = ed25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key);
232 0 0         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: ed25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); }
233 0           sv_setpvn(RETVAL, (char*)out, out_len);
234             }
235 0 0         else if (strEQ(type, "public")) {
236 0           rv = ed25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key);
237 0 0         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: ed25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); }
238 0           sv_setpvn(RETVAL, (char*)out, out_len);
239             }
240             else {
241 0           croak("FATAL: export_key_der invalid type '%s'", type);
242             }
243 0           zeromem(out, sizeof(out));
244             }
245             OUTPUT:
246             RETVAL
247              
248             SV*
249             export_key_raw(Crypt::PK::Ed25519 self, char * type)
250             CODE:
251             {
252             int rv;
253             unsigned char out[32];
254 0           unsigned long int out_len = sizeof(out);
255              
256 0           RETVAL = newSVpvn(NULL, 0); /* undef */
257 0 0         if (strEQ(type, "private")) {
258 0           rv = ed25519_export(out, &out_len, PK_PRIVATE, &self->key);
259 0 0         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: ed25519_export(PK_PRIVATE) failed: %s", error_to_string(rv)); }
260 0           sv_setpvn(RETVAL, (char*)out, out_len);
261             }
262 0 0         else if (strEQ(type, "public")) {
263 0           rv = ed25519_export(out, &out_len, PK_PUBLIC, &self->key);
264 0 0         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: ed25519_export(PK_PUBLIC) failed: %s", error_to_string(rv)); }
265 0           sv_setpvn(RETVAL, (char*)out, out_len);
266             }
267             else {
268 0           croak("FATAL: export_key_raw invalid type '%s'", type);
269             }
270 0           zeromem(out, sizeof(out));
271             }
272             OUTPUT:
273             RETVAL
274              
275             SV *
276             sign_message(Crypt::PK::Ed25519 self, SV * data)
277             CODE:
278             {
279             int rv;
280 0           unsigned char buffer[64], *data_ptr = NULL;
281 0           unsigned long buffer_len = 64;
282 0           STRLEN data_len = 0;
283              
284 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
285 0           rv = ed25519_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key);
286 0 0         if (rv != CRYPT_OK) { zeromem(buffer, sizeof(buffer)); croak("FATAL: ed25519_sign failed: %s", error_to_string(rv)); }
287 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
288 0           zeromem(buffer, sizeof(buffer));
289             }
290             OUTPUT:
291             RETVAL
292              
293             int
294             verify_message(Crypt::PK::Ed25519 self, SV * sig, SV * data)
295             CODE:
296             {
297             int rv, stat;
298 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL;
299 0           STRLEN data_len = 0, sig_len = 0;
300              
301 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
302 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
303 0           RETVAL = 0;
304 0           stat = 0;
305 0           rv = ed25519_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len, &stat, &self->key);
306 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
307             }
308             OUTPUT:
309             RETVAL
310              
311             SV *
312             sign_message_ctx(Crypt::PK::Ed25519 self, SV * data, SV * ctx)
313             CODE:
314             {
315             int rv;
316 0           unsigned char buffer[64], *data_ptr = NULL, *ctx_ptr = NULL;
317 0           unsigned long buffer_len = 64;
318 0           STRLEN data_len = 0, ctx_len = 0;
319              
320 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
321 0           ctx_ptr = (unsigned char *)SvPVbyte(ctx, ctx_len);
322 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
323 0           rv = ed25519ctx_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
324 0           ctx_ptr, (unsigned long)ctx_len, &self->key);
325 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519ctx_sign failed: %s", error_to_string(rv));
326 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
327 0           zeromem(buffer, sizeof(buffer));
328             }
329             OUTPUT:
330             RETVAL
331              
332             int
333             verify_message_ctx(Crypt::PK::Ed25519 self, SV * sig, SV * data, SV * ctx)
334             CODE:
335             {
336             int rv, stat;
337 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL, *ctx_ptr = NULL;
338 0           STRLEN data_len = 0, sig_len = 0, ctx_len = 0;
339              
340 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
341 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
342 0           ctx_ptr = (unsigned char *)SvPVbyte(ctx, ctx_len);
343 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
344 0           RETVAL = 0;
345 0           stat = 0;
346 0           rv = ed25519ctx_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len,
347 0           ctx_ptr, (unsigned long)ctx_len, &stat, &self->key);
348 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
349             }
350             OUTPUT:
351             RETVAL
352              
353             SV *
354             sign_message_ph(Crypt::PK::Ed25519 self, SV * data, ...)
355             CODE:
356             {
357             int rv;
358 0           unsigned char buffer[64], *data_ptr = NULL, *ctx_ptr = NULL;
359 0           unsigned long buffer_len = 64;
360 0           STRLEN data_len = 0, ctx_len = 0;
361              
362 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
363 0 0         if (items > 2 && SvOK(ST(2))) {
    0          
364 0           ctx_ptr = (unsigned char *)SvPVbyte(ST(2), ctx_len);
365 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
366             }
367 0           rv = ed25519ph_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
368 0           ctx_ptr, (unsigned long)ctx_len, &self->key);
369 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519ph_sign failed: %s", error_to_string(rv));
370 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
371 0           zeromem(buffer, sizeof(buffer));
372             }
373             OUTPUT:
374             RETVAL
375              
376             int
377             verify_message_ph(Crypt::PK::Ed25519 self, SV * sig, SV * data, ...)
378             CODE:
379             {
380             int rv, stat;
381 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL, *ctx_ptr = NULL;
382 0           STRLEN data_len = 0, sig_len = 0, ctx_len = 0;
383              
384 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
385 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
386 0 0         if (items > 3 && SvOK(ST(3))) {
    0          
387 0           ctx_ptr = (unsigned char *)SvPVbyte(ST(3), ctx_len);
388 0 0         if (ctx_len > 255) croak("FATAL: context must be at most 255 bytes");
389             }
390 0           RETVAL = 0;
391 0           stat = 0;
392 0           rv = ed25519ph_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len,
393 0           ctx_ptr, (unsigned long)ctx_len, &stat, &self->key);
394 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
395             }
396             OUTPUT:
397             RETVAL
398              
399             void
400             DESTROY(Crypt::PK::Ed25519 self)
401             CODE:
402 2 50         if (self->pindex >= 0 && prng_is_valid(self->pindex) == CRYPT_OK && prng_descriptor[self->pindex].done) {
    50          
    50          
403 2           prng_descriptor[self->pindex].done(&self->pstate);
404             }
405 2           zeromem(self, sizeof(*self));
406 2           Safefree(self);