File Coverage

inc/CryptX_PK_DH.xs.inc
Criterion Covered Total %
statement 125 162 77.1
branch 73 148 49.3
condition n/a
subroutine n/a
pod n/a
total 198 310 63.8


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           croak("FATAL: key2hash failed - 'x' too big number");
179             }
180 3 50         if (siz>0) {
181 3           cryptx_internal_mp2hex_with_leading_zero(self->key.x, buf, 20000, 0);
182 3           not_used = hv_store(rv_hash, "x", 1, newSVpv(buf, strlen(buf)), 0);
183             }
184             else{
185 0           not_used = hv_store(rv_hash, "x", 1, newSVpv("", 0), 0);
186             }
187             /* y */
188 3 50         siz = (self->key.y) ? mp_ubin_size(self->key.y) : 0;
189 3 50         if (siz>10000) {
190 0           croak("FATAL: key2hash failed - 'y' too big number");
191             }
192 3 50         if (siz>0) {
193 3           cryptx_internal_mp2hex_with_leading_zero(self->key.y, buf, 20000, 0);
194 3           not_used = hv_store(rv_hash, "y", 1, newSVpv(buf, strlen(buf)), 0);
195             }
196             else{
197 0           not_used = hv_store(rv_hash, "y", 1, newSVpv("", 0), 0);
198             }
199             /* p */
200 3 50         siz = (self->key.prime) ? mp_ubin_size(self->key.prime) : 0;
201 3 50         if (siz>10000) {
202 0           croak("FATAL: key2hash failed - 'p' too big number");
203             }
204 3 50         if (siz>0) {
205 3           cryptx_internal_mp2hex_with_leading_zero(self->key.prime, buf, 20000, 0);
206 3           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
207             }
208             else {
209 0           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
210             }
211              
212             /* g */
213 3 50         siz = (self->key.base) ? mp_ubin_size(self->key.base) : 0;
214 3 50         if (siz>10000) {
215 0           croak("FATAL: key2hash failed - 'g' too big number");
216             }
217 3 50         if (siz>0) {
218 3           cryptx_internal_mp2hex_with_leading_zero(self->key.base, buf, 20000, 0);
219 3           not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0);
220             }
221             else {
222 0           not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0);
223             }
224             /* size */
225 3           not_used = hv_store(rv_hash, "size", 4, newSViv(dh_get_groupsize(&self->key)), 0);
226             /* type */
227 3           not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
228             LTC_UNUSED_PARAM(not_used);
229 3           RETVAL = newRV_noinc((SV*)rv_hash);
230             OUTPUT:
231             RETVAL
232              
233             SV*
234             params2hash(Crypt::PK::DH self)
235             PREINIT:
236             HV *rv_hash;
237             size_t siz;
238             char buf[20001];
239             SV **not_used;
240             CODE:
241 0 0         if (self->key.type == -1) XSRETURN_UNDEF;
242 0           rv_hash = newHV();
243             /* p */
244 0 0         siz = (self->key.prime) ? mp_ubin_size(self->key.prime) : 0;
245 0 0         if (siz>10000) {
246 0           croak("FATAL: params2hash failed - 'p' too big number");
247             }
248 0 0         if (siz>0) {
249 0           cryptx_internal_mp2hex_with_leading_zero(self->key.prime, buf, 20000, 0);
250 0           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
251             }
252             else {
253 0           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
254             }
255              
256             /* g */
257 0 0         siz = (self->key.base) ? mp_ubin_size(self->key.base) : 0;
258 0 0         if (siz>10000) {
259 0           croak("FATAL: params2hash failed - 'g' too big number");
260             }
261 0 0         if (siz>0) {
262 0           cryptx_internal_mp2hex_with_leading_zero(self->key.base, buf, 20000, 0);
263 0           not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0);
264             }
265             else {
266 0           not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0);
267             }
268 0 0         if (not_used) not_used = NULL; /* just silence the warning: variable 'not_used' set but not used */
269 0           RETVAL = newRV_noinc((SV*)rv_hash);
270             OUTPUT:
271             RETVAL
272              
273             SV *
274             export_key(Crypt::PK::DH self, char * type)
275             CODE:
276             {
277             int rv;
278 14           unsigned long int out_len = 4096;
279             unsigned char out[4096];
280              
281 14           RETVAL = newSVpvn(NULL, 0); /* undef */
282 14 100         if (strEQ(type, "private")) {
283 7           rv = dh_export(out, &out_len, PK_PRIVATE, &self->key);
284 7 50         if (rv != CRYPT_OK) croak("FATAL: dh_export(PK_PRIVATE) failed: %s", error_to_string(rv));
285 7           sv_setpvn(RETVAL, (char*)out, out_len);
286             }
287 7 50         else if (strEQ(type, "public")) {
288 7           rv = dh_export(out, &out_len, PK_PUBLIC, &self->key);
289 7 50         if (rv != CRYPT_OK) croak("FATAL: dh_export(PK_PUBLIC) failed: %s", error_to_string(rv));
290 7           sv_setpvn(RETVAL, (char*)out, out_len);
291             }
292             else {
293 0           croak("FATAL: export_key invalid type '%s'", type);
294             }
295 14           zeromem(out, sizeof(out));
296             }
297             OUTPUT:
298             RETVAL
299              
300             SV *
301             shared_secret(Crypt::PK::DH self, Crypt::PK::DH pubkey)
302             CODE:
303             {
304             int rv;
305             unsigned char buffer[1536]; /* headroom above 8192-bit (1024-byte) groups */
306 10           unsigned long buffer_len = sizeof(buffer);
307              
308 10           rv = dh_shared_secret(&self->key, &pubkey->key, buffer, &buffer_len);
309 10 50         if (rv != CRYPT_OK) croak("FATAL: dh_shared_secret failed: %s", error_to_string(rv));
310 10           RETVAL = newSVpvn((char*)buffer, buffer_len);
311 10           zeromem(buffer, sizeof(buffer));
312             }
313             OUTPUT:
314             RETVAL
315              
316             SV *
317             export_key_raw(Crypt::PK::DH self, char * type)
318             CODE:
319             {
320             int rv;
321             unsigned char out[1536]; /* headroom above 8192-bit (1024-byte) groups */
322 5           unsigned long out_len = sizeof(out);
323              
324 5           RETVAL = newSVpvn(NULL, 0); /* undef */
325 5 100         if (strEQ(type, "private")) {
326 1           rv = dh_export_key(out, &out_len, PK_PRIVATE, &self->key);
327 1 50         if (rv != CRYPT_OK) croak("FATAL: dh_export_key(PK_PRIVATE) failed: %s", error_to_string(rv));
328 1           sv_setpvn(RETVAL, (char*)out, out_len);
329             }
330 4 50         else if (strEQ(type, "public")) {
331 4           rv = dh_export_key(out, &out_len, PK_PUBLIC, &self->key);
332 4 50         if (rv != CRYPT_OK) croak("FATAL: dh_export_key(PK_PUBLIC) failed: %s", error_to_string(rv));
333 4           sv_setpvn(RETVAL, (char*)out, out_len);
334             }
335             else {
336 0           croak("FATAL: export_key_raw: invalid type '%s'", type);
337             }
338 5           zeromem(out, sizeof(out));
339             }
340             OUTPUT:
341             RETVAL
342              
343             void
344             DESTROY(Crypt::PK::DH self)
345             CODE:
346 46 100         if (self->key.type != -1) { dh_free(&self->key); self->key.type = -1; }
347 46 50         if (self->pindex >= 0 && prng_is_valid(self->pindex) == CRYPT_OK && prng_descriptor[self->pindex].done) {
    50          
    50          
348 46           prng_descriptor[self->pindex].done(&self->pstate);
349             }
350 46           zeromem(self, sizeof(*self));
351 46           Safefree(self);