File Coverage

inc/CryptX_PK_DH.xs.inc
Criterion Covered Total %
statement 126 167 75.4
branch 73 148 49.3
condition n/a
subroutine n/a
pod n/a
total 199 315 63.1


line stmt bran cond sub pod time code
1             MODULE = CryptX PACKAGE = Crypt::PK::DH
2              
3             PROTOTYPES: DISABLE
4              
5             Crypt::PK::DH
6             _new(Class)
7             CODE:
8             {
9             int rv;
10 46           Newz(0, RETVAL, 1, struct dh_struct);
11 46 50         if (!RETVAL) croak("FATAL: Newz failed");
12 46           RETVAL->key.type = -1;
13 46           RETVAL->pindex = find_prng("chacha20");
14 46           RETVAL->last_pid = (IV)PerlProc_getpid();
15 46 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 46           rv = rng_make_prng(320, RETVAL->pindex, &RETVAL->pstate, NULL); /* 320bits = 40bytes */
21 46 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::DH self, int groupsize=256)
32             PPCODE:
33             {
34             int rv;
35 2           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
36 2 50         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
37 2           rv = dh_set_pg_groupsize(groupsize, &self->key);
38 2 50         if (rv != CRYPT_OK) croak("FATAL: dh_set_pg_groupsize failed: %s", error_to_string(rv));
39 2           rv = dh_generate_key(&self->pstate, self->pindex, &self->key);
40 2 50         if (rv != CRYPT_OK) croak("FATAL: dh_generate_key failed: %s", error_to_string(rv));
41 2 50         XPUSHs(ST(0)); /* return self */
42             }
43              
44             void
45             _generate_key_gp(Crypt::PK::DH self, char *g, char *p)
46             PPCODE:
47             {
48             int rv;
49             unsigned char pbin[1536], gbin[512]; /* 1536 = headroom above 8192-bit (1024-byte) groups */
50 8           unsigned long plen=sizeof(pbin), glen=sizeof(gbin);
51 8           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
52 8 100         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
53              
54 8 50         if (p && strlen(p) > 0 && g && strlen(g) > 0) {
    50          
    50          
    50          
55 8           rv = radix_to_bin(p, 16, pbin, &plen);
56 8 100         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv));
57 7           rv = radix_to_bin(g, 16, gbin, &glen);
58 7 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(g) failed: %s", error_to_string(rv));
59              
60 7           rv = dh_set_pg(pbin, plen, gbin, glen, &self->key);
61 7 50         if (rv != CRYPT_OK) croak("FATAL: dh_set_pg failed: %s", error_to_string(rv));
62 7           rv = dh_generate_key(&self->pstate, self->pindex, &self->key);
63 7 50         if (rv != CRYPT_OK) croak("FATAL: dh_generate_key failed: %s", error_to_string(rv));
64             }
65             else {
66 0           croak("FATAL: generate_key: invalid g or p");
67             }
68              
69 7 50         XPUSHs(ST(0)); /* return self */
70             }
71              
72             void
73             _generate_key_dhparam(Crypt::PK::DH self, SV * dhparam)
74             PPCODE:
75             {
76             int rv;
77 2           unsigned char *data=NULL;
78 2           STRLEN data_len=0;
79 2           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
80 2 50         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
81 2           data = (unsigned char *)SvPVbyte(dhparam, data_len);
82             /* load d p q */
83 2           rv = dh_set_pg_dhparam(data, (unsigned long)data_len, &self->key);
84 2 50         if (rv != CRYPT_OK) croak("FATAL: dh_set_pg_dhparam failed: %s", error_to_string(rv));
85             /* gen the key */
86 2           rv = dh_generate_key(&self->pstate, self->pindex, &self->key);
87 2 50         if (rv != CRYPT_OK) croak("FATAL: dh_generate_key failed: %s", error_to_string(rv));
88 2 50         XPUSHs(ST(0)); /* return self */
89             }
90              
91             void
92             _import(Crypt::PK::DH self, SV * key_data)
93             PPCODE:
94             {
95             int rv;
96 27           unsigned char *data=NULL;
97 27           STRLEN data_len=0;
98              
99 27           data = (unsigned char *)SvPVbyte(key_data, data_len);
100 27 50         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
101 27           rv = dh_import(data, (unsigned long)data_len, &self->key);
102 27 50         if (rv != CRYPT_OK) croak("FATAL: dh_import failed: %s", error_to_string(rv));
103 27 50         XPUSHs(ST(0)); /* return self */
104             }
105              
106             void
107             _import_raw(Crypt::PK::DH self, SV * raw_key, int type, char * g, char * p)
108             PPCODE:
109             {
110             int rv;
111 4           unsigned char *data=NULL;
112 4           STRLEN data_len=0;
113             unsigned char pbin[1536], gbin[512]; /* 1536 = headroom above 8192-bit (1024-byte) groups */
114 4           unsigned long plen=sizeof(pbin), glen=sizeof(gbin);
115              
116 4           data = (unsigned char *)SvPVbyte(raw_key, data_len);
117 4 50         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
118              
119 4 50         if (p && strlen(p) > 0 && g && strlen(g) > 0) {
    50          
    50          
    50          
120 4           rv = radix_to_bin(p, 16, pbin, &plen);
121 4 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv));
122 4           rv = radix_to_bin(g, 16, gbin, &glen);
123 4 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(g) failed: %s", error_to_string(rv));
124              
125 4           rv = dh_set_pg(pbin, plen, gbin, glen, &self->key);
126 4 50         if (rv != CRYPT_OK) croak("FATAL: dh_set_pg failed: %s", error_to_string(rv));
127              
128 4 100         if (type == 0) {
129             /* public */
130 2           rv = dh_set_key(data, (unsigned long)data_len, PK_PUBLIC, &self->key);
131 2 50         if (rv != CRYPT_OK) croak("FATAL: dh_set_key failed: %s", error_to_string(rv));
132             }
133 2 50         else if (type == 1) {
134             /* private */
135 2           rv = dh_set_key(data, (unsigned long)data_len, PK_PRIVATE, &self->key);
136 2 50         if (rv != CRYPT_OK) croak("FATAL: dh_set_key failed: %s", error_to_string(rv));
137             }
138             else {
139 0           croak("FATAL: import_raw invalid type '%d'", type);
140             }
141             }
142             else {
143 0           croak("FATAL: import_raw: invalid g or p");
144             }
145              
146 4 50         XPUSHs(ST(0)); /* return self */
147             }
148              
149             int
150             is_private(Crypt::PK::DH self)
151             CODE:
152 23 50         if (self->key.type == -1) XSRETURN_UNDEF;
153 23 100         RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
154             OUTPUT:
155             RETVAL
156              
157             int
158             size(Crypt::PK::DH self)
159             CODE:
160 4 50         if (self->key.type == -1) XSRETURN_UNDEF;
161 4           RETVAL = dh_get_groupsize(&self->key);
162             OUTPUT:
163             RETVAL
164              
165             SV*
166             key2hash(Crypt::PK::DH self)
167             PREINIT:
168             HV *rv_hash;
169             size_t siz;
170             char buf[20001];
171             SV **not_used;
172             CODE:
173 3 50         if (self->key.type == -1) XSRETURN_UNDEF;
174 3           rv_hash = newHV();
175             /* x */
176 3 50         siz = (self->key.x) ? mp_ubin_size(self->key.x) : 0;
177 3 50         if (siz>10000) {
178 0           zeromem(buf, sizeof(buf));
179 0           croak("FATAL: key2hash failed - 'x' too big number");
180             }
181 3 50         if (siz>0) {
182 3           cryptx_internal_mp2hex_with_leading_zero(self->key.x, buf, 20000, 0);
183 3           not_used = hv_store(rv_hash, "x", 1, newSVpv(buf, strlen(buf)), 0);
184             }
185             else{
186 0           not_used = hv_store(rv_hash, "x", 1, newSVpv("", 0), 0);
187             }
188             /* y */
189 3 50         siz = (self->key.y) ? mp_ubin_size(self->key.y) : 0;
190 3 50         if (siz>10000) {
191 0           zeromem(buf, sizeof(buf));
192 0           croak("FATAL: key2hash failed - 'y' too big number");
193             }
194 3 50         if (siz>0) {
195 3           cryptx_internal_mp2hex_with_leading_zero(self->key.y, buf, 20000, 0);
196 3           not_used = hv_store(rv_hash, "y", 1, newSVpv(buf, strlen(buf)), 0);
197             }
198             else{
199 0           not_used = hv_store(rv_hash, "y", 1, newSVpv("", 0), 0);
200             }
201             /* p */
202 3 50         siz = (self->key.prime) ? mp_ubin_size(self->key.prime) : 0;
203 3 50         if (siz>10000) {
204 0           zeromem(buf, sizeof(buf));
205 0           croak("FATAL: key2hash failed - 'p' too big number");
206             }
207 3 50         if (siz>0) {
208 3           cryptx_internal_mp2hex_with_leading_zero(self->key.prime, buf, 20000, 0);
209 3           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
210             }
211             else {
212 0           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
213             }
214              
215             /* g */
216 3 50         siz = (self->key.base) ? mp_ubin_size(self->key.base) : 0;
217 3 50         if (siz>10000) {
218 0           zeromem(buf, sizeof(buf));
219 0           croak("FATAL: key2hash failed - 'g' too big number");
220             }
221 3 50         if (siz>0) {
222 3           cryptx_internal_mp2hex_with_leading_zero(self->key.base, buf, 20000, 0);
223 3           not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0);
224             }
225             else {
226 0           not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0);
227             }
228             /* size */
229 3           not_used = hv_store(rv_hash, "size", 4, newSViv(dh_get_groupsize(&self->key)), 0);
230             /* type */
231 3           not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
232             LTC_UNUSED_PARAM(not_used);
233 3           zeromem(buf, sizeof(buf));
234 3           RETVAL = newRV_noinc((SV*)rv_hash);
235             OUTPUT:
236             RETVAL
237              
238             SV*
239             params2hash(Crypt::PK::DH self)
240             PREINIT:
241             HV *rv_hash;
242             size_t siz;
243             char buf[20001];
244             SV **not_used;
245             CODE:
246 0 0         if (self->key.type == -1) XSRETURN_UNDEF;
247 0           rv_hash = newHV();
248             /* p */
249 0 0         siz = (self->key.prime) ? mp_ubin_size(self->key.prime) : 0;
250 0 0         if (siz>10000) {
251 0           croak("FATAL: params2hash failed - 'p' too big number");
252             }
253 0 0         if (siz>0) {
254 0           cryptx_internal_mp2hex_with_leading_zero(self->key.prime, buf, 20000, 0);
255 0           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
256             }
257             else {
258 0           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
259             }
260              
261             /* g */
262 0 0         siz = (self->key.base) ? mp_ubin_size(self->key.base) : 0;
263 0 0         if (siz>10000) {
264 0           croak("FATAL: params2hash failed - 'g' too big number");
265             }
266 0 0         if (siz>0) {
267 0           cryptx_internal_mp2hex_with_leading_zero(self->key.base, buf, 20000, 0);
268 0           not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0);
269             }
270             else {
271 0           not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0);
272             }
273 0 0         if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */
274 0           RETVAL = newRV_noinc((SV*)rv_hash);
275             OUTPUT:
276             RETVAL
277              
278             SV *
279             export_key(Crypt::PK::DH self, char * type)
280             CODE:
281             {
282             int rv;
283 14           unsigned long int out_len = 4096;
284             unsigned char out[4096];
285              
286 14           RETVAL = newSVpvn(NULL, 0); /* undef */
287 14 100         if (strEQ(type, "private")) {
288 7           rv = dh_export(out, &out_len, PK_PRIVATE, &self->key);
289 7 50         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: dh_export(PK_PRIVATE) failed: %s", error_to_string(rv)); }
290 7           sv_setpvn(RETVAL, (char*)out, out_len);
291             }
292 7 50         else if (strEQ(type, "public")) {
293 7           rv = dh_export(out, &out_len, PK_PUBLIC, &self->key);
294 7 50         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: dh_export(PK_PUBLIC) failed: %s", error_to_string(rv)); }
295 7           sv_setpvn(RETVAL, (char*)out, out_len);
296             }
297             else {
298 0           croak("FATAL: export_key invalid type '%s'", type);
299             }
300 14           zeromem(out, sizeof(out));
301             }
302             OUTPUT:
303             RETVAL
304              
305             SV *
306             shared_secret(Crypt::PK::DH self, Crypt::PK::DH pubkey)
307             CODE:
308             {
309             int rv;
310             unsigned char buffer[1536]; /* headroom above 8192-bit (1024-byte) groups */
311 10           unsigned long buffer_len = sizeof(buffer);
312              
313 10           rv = dh_shared_secret(&self->key, &pubkey->key, buffer, &buffer_len);
314 10 50         if (rv != CRYPT_OK) { zeromem(buffer, sizeof(buffer)); croak("FATAL: dh_shared_secret failed: %s", error_to_string(rv)); }
315 10           RETVAL = newSVpvn((char*)buffer, buffer_len);
316 10           zeromem(buffer, sizeof(buffer));
317             }
318             OUTPUT:
319             RETVAL
320              
321             SV *
322             export_key_raw(Crypt::PK::DH self, char * type)
323             CODE:
324             {
325             int rv;
326             unsigned char out[1536]; /* headroom above 8192-bit (1024-byte) groups */
327 5           unsigned long out_len = sizeof(out);
328              
329 5           RETVAL = newSVpvn(NULL, 0); /* undef */
330 5 100         if (strEQ(type, "private")) {
331 1           rv = dh_export_key(out, &out_len, PK_PRIVATE, &self->key);
332 1 50         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: dh_export_key(PK_PRIVATE) failed: %s", error_to_string(rv)); }
333 1           sv_setpvn(RETVAL, (char*)out, out_len);
334             }
335 4 50         else if (strEQ(type, "public")) {
336 4           rv = dh_export_key(out, &out_len, PK_PUBLIC, &self->key);
337 4 50         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: dh_export_key(PK_PUBLIC) failed: %s", error_to_string(rv)); }
338 4           sv_setpvn(RETVAL, (char*)out, out_len);
339             }
340             else {
341 0           croak("FATAL: export_key_raw: invalid type '%s'", type);
342             }
343 5           zeromem(out, sizeof(out));
344             }
345             OUTPUT:
346             RETVAL
347              
348             void
349             DESTROY(Crypt::PK::DH self)
350             CODE:
351 46 100         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
352 46 50         if (self->pindex >= 0 && prng_is_valid(self->pindex) == CRYPT_OK && prng_descriptor[self->pindex].done) {
    50          
    50          
353 46           prng_descriptor[self->pindex].done(&self->pstate);
354             }
355 46           zeromem(self, sizeof(*self));
356 46           Safefree(self);