File Coverage

inc/CryptX_PK_DSA.xs.inc
Criterion Covered Total %
statement 200 240 83.3
branch 113 208 54.3
condition n/a
subroutine n/a
pod n/a
total 313 448 69.8


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) {
145 0           pka_key_free(&key_from_pem);
146 0           croak("FATAL: pem_decode_pkcs decoded non-DSA key");
147             }
148 20           self->key = key_from_pem.u.dsa;
149 20 50         XPUSHs(ST(0)); /* return self */
150             }
151              
152             void
153             _import_openssh(Crypt::PK::DSA self, SV * key_data, SV * passwd)
154             PPCODE:
155             {
156             int rv;
157 3           unsigned char *data = NULL;
158 3           STRLEN data_len = 0;
159 3           password_ctx pw_ctx = { cryptx_internal_password_cb_getpw, cryptx_internal_password_cb_free, passwd };
160             ltc_pka_key key_from_pem;
161              
162 3           data = (unsigned char *)SvPVbyte(key_data, data_len);
163 3 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
164 3 100         if (SvOK(passwd)) {
165 1           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, &pw_ctx);
166             }
167             else {
168 2           rv = pem_decode_openssh(data, (unsigned long)data_len, &key_from_pem, NULL);
169             }
170 3 50         if (rv != CRYPT_OK) croak("FATAL: pem_decode_openssh failed: %s", error_to_string(rv));
171 3 50         if (key_from_pem.id != LTC_PKA_DSA) {
172 0           pka_key_free(&key_from_pem);
173 0           croak("FATAL: pem_decode_openssh decoded non-DSA key");
174             }
175 3           self->key = key_from_pem.u.dsa;
176 3 50         XPUSHs(ST(0)); /* return self */
177             }
178              
179             void
180             _import_hex(Crypt::PK::DSA self, char *p, char *q, char *g, char *x, char *y)
181             PPCODE:
182             {
183             int rv;
184             unsigned char pbin[512], qbin[512], gbin[512], xbin[512], ybin[512];
185 3           unsigned long plen=sizeof(pbin), qlen=sizeof(qbin), glen=sizeof(gbin), xlen=sizeof(xbin), ylen=sizeof(ybin);
186              
187 3 100         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
188              
189 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          
190 3           rv = radix_to_bin(p, 16, pbin, &plen);
191 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(p) failed: %s", error_to_string(rv));
192 3           rv = radix_to_bin(q, 16, qbin, &qlen);
193 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(q) failed: %s", error_to_string(rv));
194 3           rv = radix_to_bin(g, 16, gbin, &glen);
195 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(g) failed: %s", error_to_string(rv));
196 3           rv = dsa_set_pqg(pbin, plen, qbin, qlen, gbin, glen, &self->key);
197 3 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_pqg failed: %s", error_to_string(rv));
198              
199 3           rv = radix_to_bin(y, 16, ybin, &ylen);
200 3 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(y) failed: %s", error_to_string(rv));
201 3 100         if (x && strlen(x) > 0) {
    100          
202             /* private */
203 1           rv = radix_to_bin(x, 16, xbin, &xlen);
204 1 50         if (rv != CRYPT_OK) croak("FATAL: radix_to_bin(x) failed: %s", error_to_string(rv));
205 1           rv = dsa_set_key(xbin, xlen, PK_PRIVATE, &self->key);
206 1 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_key failed: %s", error_to_string(rv));
207             }
208             else {
209             /* public */
210 2           rv = dsa_set_key(ybin, ylen, PK_PUBLIC, &self->key);
211 2 50         if (rv != CRYPT_OK) croak("FATAL: dsa_set_key failed: %s", error_to_string(rv));
212             }
213             }
214             else {
215 0           croak("FATAL: import_hex: invalid or incomplete key parameters");
216             }
217              
218 3 50         XPUSHs(ST(0)); /* return self */
219             }
220              
221             int
222             is_private(Crypt::PK::DSA self)
223             CODE:
224 36 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
225 36 100         RETVAL = (self->key.type == PK_PRIVATE) ? 1 : 0;
226             OUTPUT:
227             RETVAL
228              
229             size_t
230             size(Crypt::PK::DSA self)
231             CODE:
232 3 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
233 3           RETVAL = mp_ubin_size(self->key.p);
234             OUTPUT:
235             RETVAL
236              
237             size_t
238             size_q(Crypt::PK::DSA self)
239             CODE:
240 2 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
241 2           RETVAL = mp_ubin_size(self->key.q);
242             OUTPUT:
243             RETVAL
244              
245             SV*
246             key2hash(Crypt::PK::DSA self)
247             PREINIT:
248             HV *rv_hash;
249             size_t siz, qsize, psize;
250             char buf[20001];
251             SV **not_used;
252             CODE:
253 51 50         if (self->key.type == -1 || self->key.qord <= 0) XSRETURN_UNDEF;
    50          
254 51           qsize = mp_ubin_size(self->key.q);
255 51           psize = mp_ubin_size(self->key.p);
256 51           rv_hash = newHV();
257             /* g */
258 51 50         siz = (self->key.g) ? mp_ubin_size(self->key.g) : 0;
259 51 50         if (siz>10000) {
260 0           zeromem(buf, sizeof(buf));
261 0           croak("FATAL: key2hash failed - 'g' too big number");
262             }
263 51 50         if (siz>0) {
264 51           cryptx_internal_mp2hex_with_leading_zero(self->key.g, buf, 20000, 0);
265 51           not_used = hv_store(rv_hash, "g", 1, newSVpv(buf, strlen(buf)), 0);
266             }
267             else{
268 0           not_used = hv_store(rv_hash, "g", 1, newSVpv("", 0), 0);
269             }
270             /* q */
271 51 50         siz = (self->key.q) ? mp_ubin_size(self->key.q) : 0;
272 51 50         if (siz>10000) {
273 0           zeromem(buf, sizeof(buf));
274 0           croak("FATAL: key2hash failed - 'q' too big number");
275             }
276 51 50         if (siz>0) {
277 51           cryptx_internal_mp2hex_with_leading_zero(self->key.q, buf, 20000, 0);
278 51           not_used = hv_store(rv_hash, "q", 1, newSVpv(buf, strlen(buf)), 0);
279             }
280             else{
281 0           not_used = hv_store(rv_hash, "q", 1, newSVpv("", 0), 0);
282             }
283             /* p */
284 51 50         siz = (self->key.p) ? mp_ubin_size(self->key.p) : 0;
285 51 50         if (siz>10000) {
286 0           zeromem(buf, sizeof(buf));
287 0           croak("FATAL: key2hash failed - 'p' too big number");
288             }
289 51 50         if (siz>0) {
290 51           cryptx_internal_mp2hex_with_leading_zero(self->key.p, buf, 20000, 0);
291 51           not_used = hv_store(rv_hash, "p", 1, newSVpv(buf, strlen(buf)), 0);
292             }
293             else{
294 0           not_used = hv_store(rv_hash, "p", 1, newSVpv("", 0), 0);
295             }
296             /* x */
297 51 50         siz = (self->key.x) ? mp_ubin_size(self->key.x) : 0;
298 51 50         if (siz>10000) {
299 0           zeromem(buf, sizeof(buf));
300 0           croak("FATAL: key2hash failed - 'x' too big number");
301             }
302 51 100         if (siz>0) {
303 28           cryptx_internal_mp2hex_with_leading_zero(self->key.x, buf, 20000, qsize*2);
304 28           not_used = hv_store(rv_hash, "x", 1, newSVpv(buf, strlen(buf)), 0);
305             }
306             else{
307 23           not_used = hv_store(rv_hash, "x", 1, newSVpv("", 0), 0);
308             }
309             /* y */
310 51 50         siz = (self->key.y) ? mp_ubin_size(self->key.y) : 0;
311 51 50         if (siz>10000) {
312 0           zeromem(buf, sizeof(buf));
313 0           croak("FATAL: key2hash failed - 'y' too big number");
314             }
315 51 50         if (siz>0) {
316 51           cryptx_internal_mp2hex_with_leading_zero(self->key.y, buf, 20000, psize*2);
317 51           not_used = hv_store(rv_hash, "y", 1, newSVpv(buf, strlen(buf)), 0);
318             }
319             else{
320 0           not_used = hv_store(rv_hash, "y", 1, newSVpv("", 0), 0);
321             }
322             /* size - byte length of p, consistent with size() method */
323 51           not_used = hv_store(rv_hash, "size", 4, newSViv(psize), 0);
324             /* type */
325 51           not_used = hv_store(rv_hash, "type", 4, newSViv(self->key.type), 0);
326             LTC_UNUSED_PARAM(not_used);
327 51           zeromem(buf, sizeof(buf));
328 51           RETVAL = newRV_noinc((SV*)rv_hash);
329             OUTPUT:
330             RETVAL
331              
332             SV *
333             export_key_der(Crypt::PK::DSA self, char * type)
334             CODE:
335             {
336             int rv;
337             unsigned char out[4096];
338 21           unsigned long int out_len = 4096;
339              
340 21           RETVAL = newSVpvn(NULL, 0); /* undef */
341 21 100         if (strEQ(type, "private")) {
342 10           rv = dsa_export(out, &out_len, PK_PRIVATE|PK_STD, &self->key);
343 10 50         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: dsa_export(PK_PRIVATE|PK_STD) failed: %s", error_to_string(rv)); }
344 10           sv_setpvn(RETVAL, (char*)out, out_len);
345             }
346 11 50         else if (strEQ(type, "public")) {
347 11           rv = dsa_export(out, &out_len, PK_PUBLIC|PK_STD, &self->key);
348 11 50         if (rv != CRYPT_OK) { zeromem(out, sizeof(out)); croak("FATAL: dsa_export(PK_PUBLIC|PK_STD) failed: %s", error_to_string(rv)); }
349 11           sv_setpvn(RETVAL, (char*)out, out_len);
350             }
351             else {
352 0           croak("FATAL: export_key_der invalid type '%s'", type);
353             }
354 21           zeromem(out, sizeof(out));
355             }
356             OUTPUT:
357             RETVAL
358              
359             SV *
360             encrypt(Crypt::PK::DSA self, SV * data, const char * hash_name = "SHA1")
361             CODE:
362             {
363             int rv, hash_id;
364 3           unsigned char *data_ptr=NULL;
365 3           STRLEN data_len=0;
366             unsigned char buffer[1024];
367 3           unsigned long buffer_len = 1024;
368              
369 3           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
370 3           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
371              
372 3           hash_id = cryptx_internal_find_hash(hash_name);
373 3 50         if (hash_id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
374 3           rv = dsa_encrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
375             &self->pstate, self->pindex,
376 3           hash_id, &self->key);
377 3 50         if (rv != CRYPT_OK) { zeromem(buffer, sizeof(buffer)); croak("FATAL: dsa_encrypt_key failed: %s", error_to_string(rv)); }
378 3           RETVAL = newSVpvn((char*)buffer, buffer_len);
379 3           zeromem(buffer, sizeof(buffer));
380             }
381             OUTPUT:
382             RETVAL
383              
384             SV *
385             decrypt(Crypt::PK::DSA self, SV * data)
386             CODE:
387             {
388             int rv;
389 2           unsigned char *data_ptr=NULL;
390 2           STRLEN data_len=0;
391             unsigned char buffer[1024];
392 2           unsigned long buffer_len = 1024;
393              
394 2           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
395              
396 2           rv = dsa_decrypt_key(data_ptr, (unsigned long)data_len, buffer, &buffer_len, &self->key);
397 2 50         if (rv != CRYPT_OK) { zeromem(buffer, sizeof(buffer)); croak("FATAL: dsa_decrypt_key failed: %s", error_to_string(rv)); }
398 2           RETVAL = newSVpvn((char*)buffer, buffer_len);
399 2           zeromem(buffer, sizeof(buffer));
400             }
401             OUTPUT:
402             RETVAL
403              
404             SV *
405             sign_hash(Crypt::PK::DSA self, SV * data, const char * hash_name = "SHA1")
406             ALIAS:
407             sign_message = 1
408             CODE:
409             {
410             int rv, id;
411 5           unsigned char buffer[1024], tmp[MAXBLOCKSIZE], *data_ptr = NULL;
412 5           unsigned long tmp_len = MAXBLOCKSIZE, buffer_len = 1024;
413 5           STRLEN data_len = 0;
414              
415 5           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
416 5           cryptx_internal_pk_prng_reseed(&self->pstate, self->pindex, &self->last_pid);
417 5 100         if (ix == 1) {
418 3           id = cryptx_internal_find_hash(hash_name);
419 3 50         if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
420 3           rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
421 3 50         if (rv != CRYPT_OK) { zeromem(tmp, sizeof(tmp)); croak("FATAL: hash_memory failed: %s", error_to_string(rv)); }
422 3           data_ptr = tmp;
423 3           data_len = tmp_len;
424             }
425 5           rv = dsa_sign_hash(data_ptr, (unsigned long)data_len, buffer, &buffer_len,
426             &self->pstate, self->pindex,
427 5           &self->key);
428 5 50         if (rv != CRYPT_OK) {
429 0           zeromem(buffer, sizeof(buffer));
430 0           zeromem(tmp, sizeof(tmp));
431 0           croak("FATAL: dsa_sign_hash failed: %s", error_to_string(rv));
432             }
433 5           RETVAL = newSVpvn((char*)buffer, buffer_len);
434 5           zeromem(buffer, sizeof(buffer));
435 5           zeromem(tmp, sizeof(tmp));
436             }
437             OUTPUT:
438             RETVAL
439              
440             int
441             verify_hash(Crypt::PK::DSA self, SV * sig, SV * data, const char * hash_name = "SHA1")
442             ALIAS:
443             verify_message = 1
444             CODE:
445             {
446             int rv, stat, id;
447 42           unsigned char tmp[MAXBLOCKSIZE], *data_ptr = NULL, *sig_ptr = NULL;
448 42           unsigned long tmp_len = MAXBLOCKSIZE;
449 42           STRLEN data_len = 0, sig_len = 0;
450              
451 42           data_ptr = (unsigned char *)SvPVbyte(data, data_len);
452 42           sig_ptr = (unsigned char *)SvPVbyte(sig, sig_len);
453 42 100         if (ix == 1) {
454 39           id = cryptx_internal_find_hash(hash_name);
455 39 50         if (id == -1) croak("FATAL: find_hash failed for '%s'", hash_name);
456 39           rv = hash_memory(id, data_ptr, (unsigned long)data_len, tmp, &tmp_len);
457 39 50         if (rv != CRYPT_OK) croak("FATAL: hash_memory failed: %s", error_to_string(rv));
458 39           data_ptr = tmp;
459 39           data_len = tmp_len;
460             }
461 42           RETVAL = 1;
462 42           stat = 0;
463 42           rv = dsa_verify_hash(sig_ptr, (unsigned long)sig_len, data_ptr, (unsigned long)data_len, &stat, &self->key);
464 42 100         if (rv != CRYPT_OK || stat != 1) RETVAL = 0;
    50          
465             }
466             OUTPUT:
467             RETVAL
468              
469             void
470             DESTROY(Crypt::PK::DSA self)
471             CODE:
472 82 50         if (self->key.type != -1) { dsa_free(&self->key); self->key.type = -1; }
473 82 50         if (self->pindex >= 0 && prng_is_valid(self->pindex) == CRYPT_OK && prng_descriptor[self->pindex].done) {
    50          
    50          
474 82           prng_descriptor[self->pindex].done(&self->pstate);
475             }
476 82           zeromem(self, sizeof(*self));
477 82           Safefree(self);