File Coverage

inc/CryptX_PK_Ed25519.xs.inc
Criterion Covered Total %
statement 56 138 40.5
branch 24 84 28.5
condition n/a
subroutine n/a
pod n/a
total 80 222 36.0


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           Safefree(RETVAL);
17 0           croak("FATAL: find_prng('chacha20') failed");
18             }
19 2           rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */
20 2 50         if (rv != CRYPT_OK) {
21 0           Safefree(RETVAL);
22 0           croak("FATAL: rng_make_prng failed: %s", error_to_string(rv));
23             }
24             }
25             OUTPUT:
26             RETVAL
27              
28             void
29             generate_key(Crypt::PK::Ed25519 self)
30             PPCODE:
31             {
32             int rv;
33 1           self->initialized = 0;
34 1           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
35 1           rv = ed25519_make_key(&self->pstate, self->pindex, &self->key);
36 1 50         if (rv != CRYPT_OK) croak("FATAL: ed25519_make_key failed: %s", error_to_string(rv));
37 1           self->initialized = 1;
38 1 50         XPUSHs(ST(0)); /* return self */
39             }
40              
41             void
42             _import(Crypt::PK::Ed25519 self, SV * key_data)
43             PPCODE:
44             {
45             int rv;
46 0           unsigned char *data=NULL;
47 0           STRLEN data_len=0;
48              
49 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
50 0           self->initialized = 0;
51 0           rv = ed25519_import(data, (unsigned long)data_len, &self->key);
52 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import failed: %s", error_to_string(rv));
53 0           self->initialized = 1;
54 0 0         XPUSHs(ST(0)); /* return self */
55             }
56              
57             void
58             _import_pkcs8(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
59             PPCODE:
60             {
61             int rv;
62 0           unsigned char *data = NULL;
63 0           STRLEN data_len = 0;
64 0           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
65              
66 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
67 0           self->initialized = 0;
68 0 0         if (SvOK(passwd)) {
69 0           rv = ed25519_import_pkcs8(data, (unsigned long)data_len, &pw_ctx, &self->key);
70             }
71             else {
72 0           rv = ed25519_import_pkcs8(data, (unsigned long)data_len, NULL, &self->key);
73             }
74 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_pkcs8 failed: %s", error_to_string(rv));
75 0           self->initialized = 1;
76 0 0         XPUSHs(ST(0)); /* return self */
77             }
78              
79             void
80             _import_pem(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
81             PPCODE:
82             {
83             int rv;
84 0           unsigned char *data = NULL;
85 0           STRLEN data_len = 0;
86 0           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
87             ltc_pka_key key_from_pem;
88              
89 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
90 0           self->initialized = 0;
91 0 0         if (SvOK(passwd)) {
92 0           rv = pem_decode_pkcs(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
93             }
94             else {
95 0           rv = pem_decode_pkcs(data, (unsigned long)data_len, &key_from_pem, NULL);
96             }
97 0 0         if (rv != CRYPT_OK) croak("FATAL: pem_decode_pkcs failed: %s", error_to_string(rv));
98 0 0         if (key_from_pem.id != LTC_PKA_ED25519) croak("FATAL: pem_decode_pkcs decoded non-Ed25519 key");
99 0           self->key = key_from_pem.u.ed25519;
100 0           self->initialized = 1;
101 0 0         XPUSHs(ST(0)); /* return self */
102             }
103              
104             void
105             _import_openssh(Crypt::PK::Ed25519 self, SV * key_data, SV * passwd)
106             PPCODE:
107             {
108             int rv;
109 3           unsigned char *data = NULL;
110 3           STRLEN data_len = 0;
111 3           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
112             ltc_pka_key key_from_pem;
113              
114 3           data = (unsigned char *)SvPVbyte(key_data, data_len);
115 3           self->initialized = 0;
116 3 100         if (SvOK(passwd)) {
117 1           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
118             }
119             else {
120 2           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, NULL);
121             }
122 3 50         if (rv != CRYPT_OK) croak("FATAL: pem_decode_openssh failed: %s", error_to_string(rv));
123 3 50         if (key_from_pem.id != LTC_PKA_ED25519) croak("FATAL: pem_decode_openssh decoded non-Ed25519 key");
124 3           self->key = key_from_pem.u.ed25519;
125 3           self->initialized = 1;
126 3 50         XPUSHs(ST(0)); /* return self */
127             }
128              
129             void
130             _import_x509(Crypt::PK::Ed25519 self, SV * key_data)
131             PPCODE:
132             {
133             int rv;
134 0           unsigned char *data=NULL;
135 0           STRLEN data_len=0;
136              
137 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
138 0           self->initialized = 0;
139 0           rv = ed25519_import_x509(data, (unsigned long)data_len, &self->key);
140 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_x509 failed: %s", error_to_string(rv));
141 0           self->initialized = 1;
142 0 0         XPUSHs(ST(0)); /* return self */
143             }
144              
145             void
146             _import_raw(Crypt::PK::Ed25519 self, SV * key, int which)
147             PPCODE:
148             {
149             int rv;
150 3           unsigned char *key_data=NULL;
151 3           STRLEN key_len=0;
152              
153 3 50         if (SvOK(key)) {
154 3           key_data = (unsigned char *)SvPVbyte(key, key_len);
155             }
156 3           self->initialized = 0;
157 3 100         if (which == 0) {
158 2           rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PUBLIC, &self->key);
159             }
160 1 50         else if (which == 1) {
161 1           rv = ed25519_import_raw(key_data, (unsigned long)key_len, PK_PRIVATE, &self->key);
162             }
163             else {
164 0           croak("FATAL: import_raw invalid type '%d'", which);
165             }
166 3 50         if (rv != CRYPT_OK) croak("FATAL: ed25519_import_raw failed: %s", error_to_string(rv));
167 3           self->initialized = 1;
168 3 50         XPUSHs(ST(0)); /* return self */
169             }
170              
171             int
172             is_private(Crypt::PK::Ed25519 self)
173             CODE:
174 6 50         if (self->initialized == 0) XSRETURN_UNDEF;
175 6 100         RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
176             OUTPUT:
177             RETVAL
178              
179             SV*
180             key2hash(Crypt::PK::Ed25519 self)
181             PREINIT:
182             HV *rv_hash;
183             char buf[32 * 2 + 1];
184             unsigned long blen;
185             SV **not_used;
186             int rv;
187             CODE:
188 9 50         if (self->initialized == 0) XSRETURN_UNDEF;
189 9           rv_hash = newHV();
190             /* priv */
191 9 100         if (self->key.type == PK_PRIVATE) {
192 5           blen = sizeof(buf);
193 5           rv = base16_encode(self->key.priv, sizeof(self->key.priv), buf, &blen, 0);
194 5 50         if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
195 5           not_used = hv_store(rv_hash, "priv", 4, newSVpv(buf, blen), 0);
196             }
197             else {
198 4           not_used = hv_store(rv_hash, "priv", 4, newSVpvn(NULL, 0), 0); /* undef */
199             }
200             /* pub */
201 9           blen = sizeof(buf);
202 9           rv = base16_encode(self->key.pub, sizeof(self->key.pub), buf, &blen, 0);
203 9 50         if (rv != CRYPT_OK) croak("FATAL: base16_encode failed: %s", error_to_string(rv));
204 9           not_used = hv_store(rv_hash, "pub", 3, newSVpv(buf, blen), 0);
205             /* curve */
206 9           not_used = hv_store(rv_hash, "curve", 5, newSVpv("ed25519", 0), 0);
207             LTC_UNUSED_PARAM(not_used);
208 9           RETVAL = newRV_noinc((SV*)rv_hash);
209             OUTPUT:
210             RETVAL
211              
212             SV*
213             export_key_der(Crypt::PK::Ed25519 self, char * type)
214             CODE:
215             {
216             int rv;
217             unsigned char out[4096];
218 0           unsigned long int out_len = sizeof(out);
219              
220 0           RETVAL = newSVpvn(NULL, 0); /* undef */
221 0 0         if (strnEQ(type, "private", 7)) {
222 0           rv = ed25519_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key);
223 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv));
224 0           RETVAL = newSVpvn((char*)out, out_len);
225             }
226 0 0         else if (strnEQ(type, "public", 6)) {
227 0           rv = ed25519_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key);
228 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv));
229 0           RETVAL = newSVpvn((char*)out, out_len);
230             }
231             else {
232 0           croak("FATAL: export_key_der invalid type '%s'", type);
233             }
234             }
235             OUTPUT:
236             RETVAL
237              
238             SV*
239             export_key_raw(Crypt::PK::Ed25519 self, char * type)
240             CODE:
241             {
242             int rv;
243             unsigned char out[32];
244 0           unsigned long int out_len = sizeof(out);
245              
246 0           RETVAL = newSVpvn(NULL, 0); /* undef */
247 0 0         if (strnEQ(type, "private", 7)) {
248 0           rv = ed25519_export(out, &out_len, PK_PRIVATE, &self->key);
249 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PRIVATE) failed: %s", error_to_string(rv));
250 0           RETVAL = newSVpvn((char*)out, out_len);
251             }
252 0 0         else if (strnEQ(type, "public", 6)) {
253 0           rv = ed25519_export(out, &out_len, PK_PUBLIC, &self->key);
254 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_export(PK_PUBLIC) failed: %s", error_to_string(rv));
255 0           RETVAL = newSVpvn((char*)out, out_len);
256             }
257             else {
258 0           croak("FATAL: export_key_raw invalid type '%s'", type);
259             }
260             }
261             OUTPUT:
262             RETVAL
263              
264             SV *
265             sign_message(Crypt::PK::Ed25519 self, SV * data)
266             CODE:
267             {
268             int rv;
269 0           unsigned char buffer[64], *data_ptr = NULL;
270 0           unsigned long buffer_len = 64;
271 0           STRLEN data_len = 0;
272              
273 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
274 0           rv = ed25519_sign(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key);
275 0 0         if (rv != CRYPT_OK) croak("FATAL: ed25519_sign failed: %s", error_to_string(rv));
276 0           RETVAL = newSVpvn((char*)buffer, buffer_len);
277             }
278             OUTPUT:
279             RETVAL
280              
281             int
282             verify_message(Crypt::PK::Ed25519 self, SV * sig, SV * data)
283             CODE:
284             {
285             int rv, stat;
286 0           unsigned char *data_ptr = NULL, *sig_ptr = NULL;
287 0           STRLEN data_len = 0, sig_len = 0;
288              
289 0           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
290 0           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
291 0           RETVAL = 0;
292 0           stat = 0;
293 0           rv = ed25519_verify(data_ptr, (unsigned long)data_len, sig_ptr, (unsigned long)sig_len, &stat, &self->key);
294 0 0         if (rv == CRYPT_OK && stat == 1) RETVAL = 1;
    0          
295             }
296             OUTPUT:
297             RETVAL
298              
299             void
300             DESTROY(Crypt::PK::Ed25519 self)
301             CODE:
302 2           Safefree(self);