File Coverage

inc/CryptX_PK_Ed25519.xs.inc
Criterion Covered Total %
statement 49 136 36.0
branch 22 84 26.1
condition n/a
subroutine n/a
pod n/a
total 71 220 32.2


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