File Coverage

inc/CryptX_PK_DSA.xs.inc
Criterion Covered Total %
statement 199 227 87.6
branch 113 208 54.3
condition n/a
subroutine n/a
pod n/a
total 312 435 71.7


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::PK::DSA
2              
3             PROTOTYPES: DISABLE
4              
5             Crypt::PK::DSA
6             _new(Class)
7             CODE:
8             {
9             int rv;
10 82           Newz(0, RETVAL, 1, struct dsa_struct);
11 82 50         if (!RETVAL) croak("FATAL: Newz failed");
12 82           RETVAL->key.type = -1;
13 82           RETVAL->pindex = find_prng("chacha20");
14 82           RETVAL->last_pid = (IV)PerlProc_getpid();
15 82 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 82           rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */
21 82 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_size(Crypt::PK::DSA self, int group_size=30, int modulus_size=256)
32             PPCODE:
33             {
34             int rv;
35 5           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
36 5 100         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
37             /* gen the key */
38 5           rv = dsa_make_key(&self->pstate, self->pindex, group_size, modulus_size, &self->key);
39 5 50         if (rv != CRYPT_OK) croak("FATAL: dsa_make_key failed: %s", error_to_string(rv));
40 5 50         XPUSHs(ST(0)); /* return self */
41             }
42              
43             void
44             _generate_key_dsaparam(Crypt::PK::DSA self, SV * dsaparam)
45             PPCODE:
46             {
47             int rv;
48 2           unsigned char *data=NULL;
49 2           STRLEN data_len=0;
50 2           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
51 2 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
52 2           data = (unsigned char *)SvPVbyte(dsaparam, data_len);
53             /* load d p q */
54 2           rv = dsa_set_pqg_dsaparam(data, (unsigned long)data_len, &self->key);
55 2 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_pqg_dsaparam failed: %s", error_to_string(rv));
56             /* gen the key */
57 2           rv = dsa_generate_key(&self->pstate, self->pindex, &self->key);
58 2 50         if (rv != CRYPT_OK) croak("FATAL: dsa_generate_key failed: %s", error_to_string(rv));
59 2 50         XPUSHs(ST(0)); /* return self */
60             }
61              
62             void
63             _generate_key_pqg_hex(Crypt::PK::DSA self, char *p, char *q, char *g)
64             PPCODE:
65             {
66             int rv;
67             unsigned char pbin[512], qbin[512], gbin[512];
68 1           unsigned long plen=sizeof(pbin), qlen=sizeof(qbin), glen=sizeof(gbin);
69 1           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
70 1 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
71 1 50         if (!p || !strlen(p) || !q || !strlen(q) || !g || !strlen(g)) {
    50          
    50          
    50          
    50          
    50          
72 0           croak("FATAL: generate_key_pqg_hex incomplete args");
73             }
74             /* set p q g */
75 1           rv = radix_to_bin(p, 16, pbin, &plen);
76 1 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv));
77 1           rv = radix_to_bin(q, 16, qbin, &qlen);
78 1 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(q) failed: %s", error_to_string(rv));
79 1           rv = radix_to_bin(g, 16, gbin, &glen);
80 1 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(g) failed: %s", error_to_string(rv));
81 1           rv = dsa_set_pqg(pbin, plen, qbin, qlen, gbin, glen, &self->key);
82 1 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_pqg failed: %s", error_to_string(rv));
83             /* gen the key */
84 1           rv = dsa_generate_key(&self->pstate, self->pindex, &self->key);
85 1 50         if (rv != CRYPT_OK) croak("FATAL: dsa_generate_key failed: %s", error_to_string(rv));
86 1 50         XPUSHs(ST(0)); /* return self */
87             }
88              
89             void
90             _import(Crypt::PK::DSA self, SV * key_data)
91             PPCODE:
92             {
93             int rv;
94 57           unsigned char *data=NULL;
95 57           STRLEN data_len=0;
96              
97 57           data = (unsigned char *)SvPVbyte(key_data, data_len);
98 57 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
99 57           rv = dsa_import(data, (unsigned long)data_len, &self->key);
100 57 50         if (rv != CRYPT_OK) croak("FATAL: dsa_import failed: %s", error_to_string(rv));
101 57 50         XPUSHs(ST(0)); /* return self */
102             }
103              
104             void
105             _import_pkcs8(Crypt::PK::DSA self, SV * key_data, SV * passwd)
106             PPCODE:
107             {
108             int rv;
109 0           unsigned char *data = NULL;
110 0           STRLEN data_len = 0;
111 0           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
112              
113 0           data = (unsigned char *)SvPVbyte(key_data, data_len);
114 0 0         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
115 0 0         if (SvOK(passwd)) {
116 0           rv = dsa_import_pkcs8(data, (unsigned long)data_len, &pw_ctx, &self->key);
117             }
118             else {
119 0           rv = dsa_import_pkcs8(data, (unsigned long)data_len, NULL, &self->key);
120             }
121 0 0         if (rv != CRYPT_OK) croak("FATAL: dsa_import_pkcs8 failed: %s", error_to_string(rv));
122 0 0         XPUSHs(ST(0)); /* return self */
123             }
124              
125             void
126             _import_pem(Crypt::PK::DSA self, SV * key_data, SV * passwd)
127             PPCODE:
128             {
129             int rv;
130 20           unsigned char *data = NULL;
131 20           STRLEN data_len = 0;
132 20           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
133             ltc_pka_key key_from_pem;
134              
135 20           data = (unsigned char *)SvPVbyte(key_data, data_len);
136 20 100         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
137 20 100         if (SvOK(passwd)) {
138 11           rv = pem_decode_pkcs(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
139             }
140             else {
141 9           rv = pem_decode_pkcs(data, (unsigned long)data_len, &key_from_pem, NULL);
142             }
143 20 50         if (rv != CRYPT_OK) croak("FATAL: pem_decode_pkcs failed: %s", error_to_string(rv));
144 20 50         if (key_from_pem.id != LTC_PKA_DSA) croak("FATAL: pem_decode_pkcs decoded non-DSA key");
145 20           self->key = key_from_pem.u.dsa;
146 20 50         XPUSHs(ST(0)); /* return self */
147             }
148              
149             void
150             _import_openssh(Crypt::PK::DSA self, SV * key_data, SV * passwd)
151             PPCODE:
152             {
153             int rv;
154 3           unsigned char *data = NULL;
155 3           STRLEN data_len = 0;
156 3           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
157             ltc_pka_key key_from_pem;
158              
159 3           data = (unsigned char *)SvPVbyte(key_data, data_len);
160 3 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
161 3 100         if (SvOK(passwd)) {
162 1           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
163             }
164             else {
165 2           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, NULL);
166             }
167 3 50         if (rv != CRYPT_OK) croak("FATAL: pem_decode_openssh failed: %s", error_to_string(rv));
168 3 50         if (key_from_pem.id != LTC_PKA_DSA) croak("FATAL: pem_decode_openssh decoded non-DSA key");
169 3           self->key = key_from_pem.u.dsa;
170 3 50         XPUSHs(ST(0)); /* return self */
171             }
172              
173             void
174             _import_hex(Crypt::PK::DSA self, char *p, char *q, char *g, char *x, char *y)
175             PPCODE:
176             {
177             int rv;
178             unsigned char pbin[512], qbin[512], gbin[512], xbin[512], ybin[512];
179 3           unsigned long plen=sizeof(pbin), qlen=sizeof(qbin), glen=sizeof(gbin), xlen=sizeof(xbin), ylen=sizeof(ybin);
180              
181 3 100         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
182              
183 3 50         if (p && strlen(p) > 0 && q && strlen(q) > 0 && g && strlen(g) > 0 && y && strlen(y) > 0) {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
184 3           rv = radix_to_bin(p, 16, pbin, &plen);
185 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv));
186 3           rv = radix_to_bin(q, 16, qbin, &qlen);
187 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(q) failed: %s", error_to_string(rv));
188 3           rv = radix_to_bin(g, 16, gbin, &glen);
189 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(g) failed: %s", error_to_string(rv));
190 3           rv = dsa_set_pqg(pbin, plen, qbin, qlen, gbin, glen, &self->key);
191 3 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_pqg failed: %s", error_to_string(rv));
192              
193 3           rv = radix_to_bin(y, 16, ybin, &ylen);
194 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(y) failed: %s", error_to_string(rv));
195 3 100         if (x && strlen(x) > 0) {
    100          
196             /* private */
197 1           rv = radix_to_bin(x, 16, xbin, &xlen);
198 1 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(x) failed: %s", error_to_string(rv));
199 1           rv = dsa_set_key(xbin, xlen, PK_PRIVATE, &self->key);
200 1 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_key failed: %s", error_to_string(rv));
201             }
202             else {
203             /* public */
204 2           rv = dsa_set_key(ybin, ylen, PK_PUBLIC, &self->key);
205 2 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_key failed: %s", error_to_string(rv));
206             }
207             }
208             else {
209 0           croak("FATAL: import_hex: invalid or incomplete key parameters");
210             }
211              
212 3 50         XPUSHs(ST(0)); /* return self */
213             }
214              
215             int
216             is_private(Crypt::PK::DSA self)
217             CODE:
218 36 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
219 36 100         RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
220             OUTPUT:
221             RETVAL
222              
223             size_t
224             size(Crypt::PK::DSA self)
225             CODE:
226 3 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
227 3           RETVAL = mp_ubin_size(self->key.p);
228             OUTPUT:
229             RETVAL
230              
231             size_t
232             size_q(Crypt::PK::DSA self)
233             CODE:
234 2 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
235 2           RETVAL = mp_ubin_size(self->key.q);
236             OUTPUT:
237             RETVAL
238              
239             SV*
240             key2hash(Crypt::PK::DSA self)
241             PREINIT:
242             HV *rv_hash;
243             size_t siz, qsize, psize;
244             char buf[20001];
245             SV **not_used;
246             CODE:
247 51 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
248 51           qsize = mp_ubin_size(self->key.q);
249 51           psize = mp_ubin_size(self->key.p);
250 51           rv_hash = newHV();
251             /* g */
252 51 50         siz = (self->key.g) ? mp_ubin_size(self->key.g) : 0;
253 51 50         if (siz>10000) {
254 0           croak("FATAL: key2hash failed - 'g' too big number");
255             }
256 51 50         if (siz>0) {
257 51           cryptx_internal_mp2hex_with_leading_zero(self->key.g, buf, 20000, 0);
258 51           not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0);
259             }
260             else{
261 0           not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0);
262             }
263             /* q */
264 51 50         siz = (self->key.q) ? mp_ubin_size(self->key.q) : 0;
265 51 50         if (siz>10000) {
266 0           croak("FATAL: key2hash failed - 'q' too big number");
267             }
268 51 50         if (siz>0) {
269 51           cryptx_internal_mp2hex_with_leading_zero(self->key.q, buf, 20000, 0);
270 51           not_used = hv_store(rv_hash, "q", 1, newSVpv(buf, strlen(buf)), 0);
271             }
272             else{
273 0           not_used = hv_store(rv_hash, "q", 1, newSVpv("", 0), 0);
274             }
275             /* p */
276 51 50         siz = (self->key.p) ? mp_ubin_size(self->key.p) : 0;
277 51 50         if (siz>10000) {
278 0           croak("FATAL: key2hash failed - 'p' too big number");
279             }
280 51 50         if (siz>0) {
281 51           cryptx_internal_mp2hex_with_leading_zero(self->key.p, buf, 20000, 0);
282 51           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
283             }
284             else{
285 0           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
286             }
287             /* x */
288 51 50         siz = (self->key.x) ? mp_ubin_size(self->key.x) : 0;
289 51 50         if (siz>10000) {
290 0           croak("FATAL: key2hash failed - 'x' too big number");
291             }
292 51 100         if (siz>0) {
293 28           cryptx_internal_mp2hex_with_leading_zero(self->key.x, buf, 20000, qsize*2);
294 28           not_used = hv_store(rv_hash, "x", 1, newSVpv(buf, strlen(buf)), 0);
295             }
296             else{
297 23           not_used = hv_store(rv_hash, "x", 1, newSVpv("", 0), 0);
298             }
299             /* y */
300 51 50         siz = (self->key.y) ? mp_ubin_size(self->key.y) : 0;
301 51 50         if (siz>10000) {
302 0           croak("FATAL: key2hash failed - 'y' too big number");
303             }
304 51 50         if (siz>0) {
305 51           cryptx_internal_mp2hex_with_leading_zero(self->key.y, buf, 20000, psize*2);
306 51           not_used = hv_store(rv_hash, "y", 1, newSVpv(buf, strlen(buf)), 0);
307             }
308             else{
309 0           not_used = hv_store(rv_hash, "y", 1, newSVpv("", 0), 0);
310             }
311             /* size - byte length of p, consistent with size() method */
312 51           not_used = hv_store(rv_hash, "size", 4, newSViv(psize), 0);
313             /* type */
314 51           not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
315             LTC_UNUSED_PARAM(not_used);
316 51           RETVAL = newRV_noinc((SV*)rv_hash);
317             OUTPUT:
318             RETVAL
319              
320             SV *
321             export_key_der(Crypt::PK::DSA self, char * type)
322             CODE:
323             {
324             int rv;
325             unsigned char out[4096];
326 21           unsigned long int out_len = 4096;
327              
328 21           RETVAL = newSVpvn(NULL, 0); /* undef */
329 21 100         if (strEQ(type, "private")) {
330 10           rv = dsa_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key);
331 10 50         if (rv != CRYPT_OK) croak("FATAL: dsa_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv));
332 10           sv_setpvn(RETVAL, (char*)out, out_len);
333             }
334 11 50         else if (strEQ(type, "public")) {
335 11           rv = dsa_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key);
336 11 50         if (rv != CRYPT_OK) croak("FATAL: dsa_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv));
337 11           sv_setpvn(RETVAL, (char*)out, out_len);
338             }
339             else {
340 0           croak("FATAL: export_key_der invalid type '%s'", type);
341             }
342 21           zeromem(out, sizeof(out));
343             }
344             OUTPUT:
345             RETVAL
346              
347             SV *
348             encrypt(Crypt::PK::DSA self, SV * data, const char * hash_name = "SHA1")
349             CODE:
350             {
351             int rv, hash_id;
352 3           unsigned char *data_ptr=NULL;
353 3           STRLEN data_len=0;
354             unsigned char buffer[1024];
355 3           unsigned long buffer_len = 1024;
356              
357 3           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
358 3           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
359              
360 3           hash_id = cryptx_internal_find_hash(hash_name);
361 3 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
362 3           rv = dsa_encrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
363             &self->pstate, self->pindex,
364 3           hash_id, &self->key);
365 3 50         if (rv != CRYPT_OK) croak("FATAL: dsa_encrypt_key failed: %s", error_to_string(rv));
366 3           RETVAL = newSVpvn((char*)buffer, buffer_len);
367 3           zeromem(buffer, sizeof(buffer));
368             }
369             OUTPUT:
370             RETVAL
371              
372             SV *
373             decrypt(Crypt::PK::DSA self, SV * data)
374             CODE:
375             {
376             int rv;
377 2           unsigned char *data_ptr=NULL;
378 2           STRLEN data_len=0;
379             unsigned char buffer[1024];
380 2           unsigned long buffer_len = 1024;
381              
382 2           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
383              
384 2           rv = dsa_decrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key);
385 2 50         if (rv != CRYPT_OK) croak("FATAL: dsa_decrypt_key failed: %s", error_to_string(rv));
386 2           RETVAL = newSVpvn((char*)buffer, buffer_len);
387 2           zeromem(buffer, sizeof(buffer));
388             }
389             OUTPUT:
390             RETVAL
391              
392             SV *
393             sign_hash(Crypt::PK::DSA self, SV * data, const char * hash_name = "SHA1")
394             ALIAS:
395             sign_message = 1
396             CODE:
397             {
398             int rv, id;
399 5           unsigned char buffer[1024], tmp[MAXBLOCKSIZE], *data_ptr = NULL;
400 5           unsigned long tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
401 5           STRLEN data_len = 0;
402              
403 5           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
404 5           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
405 5 100         if (ix == 1) {
406 3           id = cryptx_internal_find_hash(hash_name);
407 3 50         if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
408 3           rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
409 3 50         if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
410 3           data_ptr = tmp;
411 3           data_len = tmp_len;
412             }
413 5           rv = dsa_sign_hash(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
414             &self->pstate, self->pindex,
415 5           &self->key);
416 5 50         if (rv != CRYPT_OK) croak("FATAL: dsa_sign_hash failed: %s", error_to_string(rv));
417 5           RETVAL = newSVpvn((char*)buffer, buffer_len);
418 5           zeromem(buffer, sizeof(buffer));
419 5           zeromem(tmp, sizeof(tmp));
420             }
421             OUTPUT:
422             RETVAL
423              
424             int
425             verify_hash(Crypt::PK::DSA self, SV * sig, SV * data, const char * hash_name = "SHA1")
426             ALIAS:
427             verify_message = 1
428             CODE:
429             {
430             int rv, stat, id;
431 42           unsigned char tmp[MAXBLOCKSIZE], *data_ptr = NULL, *sig_ptr = NULL;
432 42           unsigned long tmp_len = MAXBLOCKSIZE;
433 42           STRLEN data_len = 0, sig_len = 0;
434              
435 42           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
436 42           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
437 42 100         if (ix == 1) {
438 39           id = cryptx_internal_find_hash(hash_name);
439 39 50         if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
440 39           rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
441 39 50         if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
442 39           data_ptr = tmp;
443 39           data_len = tmp_len;
444             }
445 42           RETVAL = 1;
446 42           stat = 0;
447 42           rv = dsa_verify_hash(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
448 42 100         if (rv != CRYPT_OK || stat != 1) RETVAL = 0;
    50          
449             }
450             OUTPUT:
451             RETVAL
452              
453             void
454             DESTROY(Crypt::PK::DSA self)
455             CODE:
456 82 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
457 82 50         if (self->pindex >= 0 && prng_is_valid(self->pindex) == CRYPT_OK && prng_descriptor[self->pindex].done) {
    50          
    50          
458 82           prng_descriptor[self->pindex].done(&self->pstate);
459             }
460 82           zeromem(self, sizeof(*self));
461 82           Safefree(self);