File Coverage

inc/CryptX_PK_DSA.xs.inc
Criterion Covered Total %
statement 182 213 85.4
branch 97 196 49.4
condition n/a
subroutine n/a
pod n/a
total 279 409 68.2


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