File Coverage

PKCS12.xs
Criterion Covered Total %
statement 555 705 78.7
branch 277 476 58.1
condition n/a
subroutine n/a
pod n/a
total 832 1181 70.4


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #define NEED_newCONSTSUB
6             #include "ppport.h"
7              
8             #include
9             #include
10             #include
11             #include
12             #include
13             #include
14             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
15             #include
16             OSSL_PROVIDER *legacy = NULL;
17             OSSL_PROVIDER *deflt = NULL;
18             #endif
19             #define NOKEYS 0x1
20             #define NOCERTS 0x2
21             #define INFO 0x4
22             #define CLCERTS 0x8
23             #define CACERTS 0x10
24              
25             #if OPENSSL_VERSION_NUMBER < 0x10100000L
26             #define PKCS12_SAFEBAG_get0_p8inf(o) ((o)->value.keybag)
27             #define PKCS12_SAFEBAG_get0_attr PKCS12_get_attr
28             #define PKCS12_SAFEBAG_get_bag_nid M_PKCS12_cert_bag_type
29             #define PKCS12_SAFEBAG_get_nid M_PKCS12_bag_type
30             #define PKCS12_SAFEBAG_get1_cert PKCS12_certbag2x509
31             #define PKCS12_SAFEBAG_get0_safes(o) ((o)->value.safes)
32             #define PKCS12_SAFEBAG_get0_type(o) (o)->type
33             #define PKCS8_pkey_get0_attrs(o) ((o)->attributes)
34             #define PKCS12_SAFEBAG_get0_attrs(o) ((o)->attrib)
35             #define CONST_PKCS8_PRIV_KEY_INFO PKCS8_PRIV_KEY_INFO
36             #define CONST_X509_ALGOR X509_ALGOR
37             #define CONST_X509_SIG X509_SIG
38             #define CONST_ASN1_TYPE ASN1_TYPE
39             #define CONST_STACK_OF(o) STACK_OF(o)
40             #define CONST_X509_NAME X509_NAME
41             #define CONST_ASN1_INTEGER ASN1_INTEGER
42             #define CONST_ASN1_OBJECT ASN1_OBJECT
43             #define CONST_ASN1_OCTET_STRING ASN1_OCTET_STRING
44             #define CONST_VOID void
45             #else
46             #define CONST_PKCS8_PRIV_KEY_INFO const PKCS8_PRIV_KEY_INFO
47             #define CONST_X509_ALGOR const X509_ALGOR
48             #define CONST_X509_SIG const X509_SIG
49             #define CONST_ASN1_TYPE const ASN1_TYPE
50             #define CONST_STACK_OF(o) const STACK_OF(o)
51             #define CONST_X509_NAME const X509_NAME
52             #define CONST_ASN1_INTEGER const ASN1_INTEGER
53             #define CONST_ASN1_OBJECT const ASN1_OBJECT
54             #define CONST_ASN1_OCTET_STRING const ASN1_OCTET_STRING
55             #define CONST_VOID const void
56             #endif
57              
58             const EVP_CIPHER *enc;
59             int dump_certs_pkeys_bags(pTHX_ BIO *out, CONST_STACK_OF(PKCS12_SAFEBAG) *bags,
60             const char *pass, int passlen, int options,
61             char *pempass, const EVP_CIPHER *enc, HV* hash);
62             static int alg_print(pTHX_ BIO *bio, CONST_X509_ALGOR *alg, HV* hash);
63             void print_attribute(pTHX_ BIO *out, CONST_ASN1_TYPE *av, char **value);
64             int print_attribs(pTHX_ BIO *out, CONST_STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name, HV *hash);
65             void hex_prin(BIO *out, unsigned char *buf, int len);
66             void dump_cert_text(BIO *out, X509 *x);
67             SV * get_cert_subject_name(pTHX_ X509 *x);
68             SV * get_cert_issuer_name(pTHX_ X509 *x);
69              
70             #define CHECK_OPEN_SSL(p_result) if (!(p_result)) croakSSL(__FILE__, __LINE__);
71             #define PACKAGE_CROAK(p_message) croak("%s", (p_message))
72             #define CHECK_NEW(p_var, p_size, p_type) \
73             if (New(0, p_var, p_size, p_type) == NULL) \
74             { PACKAGE_CROAK("unable to alloc buffer"); }
75              
76             /* fake our package name */
77             typedef PKCS12* Crypt__OpenSSL__PKCS12;
78              
79 0           void croakSSL(char* p_file, int p_line) {
80              
81             const char* errorReason;
82              
83             /* Just return the top error on the stack */
84 0           errorReason = ERR_reason_error_string(ERR_get_error());
85              
86 0           ERR_clear_error();
87              
88 0           croak("%s:%d: OpenSSL error: %s", p_file, p_line, errorReason);
89             }
90              
91 4           EVP_PKEY* _load_pkey(char* keyString, EVP_PKEY*(*p_loader)(BIO*, EVP_PKEY**, pem_password_cb*, void*)) {
92              
93             EVP_PKEY* pkey;
94             BIO* stringBIO;
95              
96 4 50         if (!strncmp(keyString, "----", 4)) {
97              
98 0 0         CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, strlen(keyString)));
99              
100             } else {
101              
102 4 50         CHECK_OPEN_SSL(stringBIO = BIO_new_file(keyString, "r"));
103             }
104              
105 4           pkey = p_loader(stringBIO, NULL, NULL, NULL);
106              
107 4           (void)BIO_set_close(stringBIO, BIO_CLOSE);
108 4           BIO_free_all(stringBIO);
109              
110 4 50         CHECK_OPEN_SSL(pkey);
111 4           return pkey;
112             }
113              
114 4           STACK_OF(X509)* _load_cert_chain(char* keyString, STACK_OF(X509_INFO)*(*p_loader)(BIO*, STACK_OF(X509_INFO)*, pem_password_cb*, void*)) {
115             int i;
116 4           STACK_OF(X509_INFO) *xis = NULL;
117 4           X509_INFO *xi = NULL;
118             BIO* stringBIO;
119 4           STACK_OF(X509) *stack = sk_X509_new_null();
120              
121 4 50         if (!strncmp(keyString, "----", 4)) {
122 0 0         CHECK_OPEN_SSL(stringBIO = BIO_new_mem_buf(keyString, strlen(keyString)));
123             } else {
124 4 50         CHECK_OPEN_SSL(stringBIO = BIO_new_file(keyString, "r"));
125             }
126              
127 4           xis = p_loader(stringBIO, NULL, NULL, NULL);
128 8 100         for (i = 0; i < sk_X509_INFO_num(xis); i++) {
129 4           xi = sk_X509_INFO_value(xis, i);
130 4 50         if (xi->x509 != NULL && stack != NULL) {
    50          
131 4 50         CHECK_OPEN_SSL(xi->x509);
132 4 50         if (!sk_X509_push(stack, xi->x509))
133 0           goto end;
134 4           xi->x509 = NULL;
135             }
136             }
137              
138 4           end:
139 4           sk_X509_INFO_pop_free(xis, X509_INFO_free);
140 4           (void)BIO_set_close(stringBIO, BIO_CLOSE);
141 4           BIO_free_all(stringBIO);
142              
143 4           return stack;
144             }
145              
146 0           static void sv_bio_error(pTHX_ BIO *bio) {
147              
148 0           SV* sv = (SV *)BIO_get_callback_arg(bio);
149 0 0         if (sv) sv_free(sv);
150              
151 0           BIO_free_all (bio);
152 0           }
153              
154 202           SV* extractBioString(pTHX_ BIO* p_stringBio)
155             {
156             SV* sv;
157             char *datap;
158 202           long datasize = 0;
159            
160 202 50         CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1);
161              
162 202           datasize = BIO_get_mem_data(p_stringBio, &datap);
163 202           sv = newSVpv(datap, datasize);
164              
165 202 50         CHECK_OPEN_SSL(BIO_set_close(p_stringBio, BIO_CLOSE) == 1);
166 202           BIO_free(p_stringBio);
167 202           return sv;
168             }
169              
170 7           static const char *ssl_error(pTHX) {
171             BIO *bio;
172             SV *sv;
173             STRLEN l;
174              
175 7 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
176 7           ERR_print_errors(bio);
177 7           sv = extractBioString(aTHX_ bio);
178 7           ERR_clear_error();
179 7           return SvPV(sv, l);
180             }
181              
182             /* these are trimmed from their openssl/apps/pkcs12.c counterparts */
183 122           int dump_certs_pkeys_bag (pTHX_ BIO *bio, PKCS12_SAFEBAG *bag, const char *pass, int passlen, int options, char *pempass, const EVP_CIPHER *enc, HV * bag_hv) {
184              
185             EVP_PKEY *pkey;
186             X509 *x509;
187 122           CONST_PKCS8_PRIV_KEY_INFO *p8 = NULL;
188             CONST_STACK_OF(X509_ATTRIBUTE) *bag_attrs;
189             CONST_STACK_OF(X509_ATTRIBUTE) *key_attrs;
190              
191 122           bag_attrs = PKCS12_SAFEBAG_get0_attrs(bag);
192              
193             /* FIXME: Change NULL to default_enc and allow the encryption to ne overridden like no-des */
194             #ifndef OPENSSL_NO_DES
195 122           EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
196 122           enc = NULL; /*default_enc; */
197             #else
198             EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc();
199             enc = default_enc;
200             #endif
201              
202 122           switch (PKCS12_SAFEBAG_get_nid(bag)) {
203              
204 2           case NID_keyBag: ;
205              
206 2 50         if (options & NOKEYS) return 1;
207              
208 2           p8 = PKCS12_SAFEBAG_get0_p8inf(bag);
209              
210 2 50         if (!(pkey = EVP_PKCS82PKEY (p8))) return 0;
211              
212 2 50         if (options & INFO) {
213 2           key_attrs = PKCS8_pkey_get0_attrs(p8);
214 2 100         if (bag_hv) {
215 1           SV * value = newSVpvn("key_bag", strlen("key_bag"));
216 1 50         if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
217 0           croak("unable to add certificate_bag to the bag_hv");
218              
219             /* Assign the output to a temporary BIO and free after it is saved to key_sv */
220             BIO *keybio;
221 1 50         CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
222 1           PEM_write_bio_PrivateKey (keybio, pkey, enc, NULL, 0, NULL, pempass);
223 1           SV * key_sv = extractBioString(aTHX_ keybio);
224              
225 1 50         if((hv_store(bag_hv, "key", strlen("key"), key_sv, 0)) == NULL)
226 0           croak("unable to add certificate_bag to the bag_hv");
227 1           print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
228 1           print_attribs(aTHX_ bio, key_attrs, "key_attributes", bag_hv);
229             } else {
230 1           BIO_printf(bio, "Key bag\n");
231 1           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
232 1           print_attribs(aTHX_ bio, key_attrs, "Key Attributes", NULL);
233 1           PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
234             }
235             } else {
236 0           PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
237             }
238              
239 2           EVP_PKEY_free(pkey);
240              
241 2           break;
242              
243 18           case NID_pkcs8ShroudedKeyBag: ;
244              
245 18 100         if (options & NOKEYS) return 1;
246              
247 13 50         if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
248 0           return 0;
249 13 50         if ((pkey = EVP_PKCS82PKEY (p8)) == NULL) {
250 0           PKCS8_PRIV_KEY_INFO_free((PKCS8_PRIV_KEY_INFO *) p8);
251 0           return 0;
252             }
253 13 100         if (options & INFO) {
254             CONST_X509_ALGOR *tp8alg;
255             #if OPENSSL_VERSION_NUMBER > 0x10100000L
256             CONST_X509_SIG *tp8;
257              
258 10           tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
259 10           X509_SIG_get0(tp8, &tp8alg, NULL);
260             #else
261             tp8alg = bag->value.shkeybag->algor;
262             #endif
263 10           key_attrs = PKCS8_pkey_get0_attrs(p8);
264 10 100         if (bag_hv) {
265 5           SV *str_bag = newSVpvn("shrouded_bag", strlen("shrouded_bag"));
266 5           HV * parameters_hv = newHV();;
267 5 50         if((hv_store(bag_hv, "type", strlen("type"), str_bag, 0)) == NULL)
268 0           croak("unable to add type to the bag_hv");
269             #if OPENSSL_VERSION_NUMBER > 0x10000000L
270 5           alg_print(aTHX_ bio, tp8alg, parameters_hv);
271             #endif
272 5           print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
273 5 50         if((hv_store(bag_hv, "parameters", strlen("parameters"), newRV_inc((SV *) parameters_hv), 0)) == NULL)
274 0           croak("unable to add bag_attributes to the bag_hv");
275              
276 5           SV *str_key_bag = newSVpvn("shrouded_keybag", strlen("shrouded_keybag"));
277 5 50         if((hv_store(bag_hv, "type", strlen("type"), str_key_bag, 0)) == NULL)
278 0           croak("unable to add type to the bag_hv");
279              
280 5           print_attribs(aTHX_ bio, key_attrs, "key_attributes", bag_hv);
281              
282             /* Assign the output to a temporary BIO and free after it is saved to key_sv */
283             BIO *keybio;
284 5 50         CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
285 5           PEM_write_bio_PrivateKey (keybio, pkey, enc, NULL, 0, NULL, pempass);
286 5           SV * key_sv = extractBioString(aTHX_ keybio);
287              
288 5 50         if((hv_store(bag_hv, "key", strlen("key"), key_sv, 0)) == NULL)
289 0           croak("unable to add certificate_bag to the bag_hv");
290             } else {
291 5           BIO_printf(bio, "Shrouded Keybag: ");
292 5           alg_print(aTHX_ bio, tp8alg, NULL);
293 5           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
294              
295 5           print_attribs(aTHX_ bio, key_attrs, "Key Attributes", NULL);
296 5           PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
297             }
298             } else {
299 3           PEM_write_bio_PrivateKey (bio, pkey, enc, NULL, 0, NULL, pempass);
300             }
301              
302 13           PKCS8_PRIV_KEY_INFO_free((PKCS8_PRIV_KEY_INFO *)p8);
303              
304 13           EVP_PKEY_free(pkey);
305              
306 13           break;
307              
308 47           case NID_certBag:
309              
310 47 100         if (options & NOCERTS) return 1;
311              
312 41 100         if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
313              
314 21 100         if (options & CACERTS) return 1;
315              
316 20 100         } else if (options & CLCERTS) {
317              
318 3           return 1;
319             }
320              
321 37 50         if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) return 1;
322              
323 37 50         if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) return 0;
324 37 100         if (options & INFO) {
325 32 100         if (bag_hv) {
326             BIO *keybio;
327 16 50         CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
328 16           SV * value = newSVpvn("certificate_bag", strlen("certificate_bag"));
329 16           print_attribs(aTHX_ keybio, bag_attrs, "bag_attributes", bag_hv);
330 16 50         if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
331 0           croak("unable to add type to the bag_hv");
332 16 50         if((hv_store(bag_hv, "subject", strlen("subject"), get_cert_subject_name(aTHX_ x509), 0)) == NULL)
333 0           croak("unable to add subject to the bag_hv");
334 16 50         if((hv_store(bag_hv, "issuer", strlen("issuer"), get_cert_issuer_name(aTHX_ x509), 0)) == NULL)
335 0           croak("unable to add issuer to the bag_hv");
336 16           PEM_write_bio_X509 (keybio, x509);
337 16           SV * key_sv = extractBioString(aTHX_ keybio);
338 16 50         if((hv_store(bag_hv, "cert", strlen("cert"), key_sv, 0)) == NULL)
339 0           croak("unable to add certificate_bag to the bag_hv");
340             } else
341             {
342 16           BIO_printf(bio, "Certificate bag\n");
343 16           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
344 16           dump_cert_text(bio, x509);
345 16           PEM_write_bio_X509 (bio, x509);
346             }
347             } else {
348 5           PEM_write_bio_X509 (bio, x509);
349             }
350              
351 37           X509_free(x509);
352              
353 37           break;
354              
355             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
356 53           case NID_secretBag:
357             /*FIXME: Not sure how to test this */
358 53 50         if (options & INFO) {
359 53           char * attribute_value = NULL;
360 53 100         if (bag_hv){
361 52           SV * value = newSVpvn("secret_bag", strlen("secret_bag"));
362 52 50         if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
363 0           croak("unable to add type to the bag_hv");
364 52           print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
365 52           Newx(attribute_value, 0, char);
366 52           print_attribute(aTHX_ bio, PKCS12_SAFEBAG_get0_bag_obj(bag), &attribute_value);
367 52 50         if(hv_store(bag_hv, "bag_value", strlen("bag_value"), newSVpvn(attribute_value, strlen(attribute_value)), 0) == NULL)
368 0           croak("unable to add MAC to the bag_hv");
369             }
370             else {
371 1           BIO_printf(bio, "Secret bag\n");
372 1           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
373 1           BIO_printf(bio, "Bag Type: ");
374 1           i2a_ASN1_OBJECT(bio, PKCS12_SAFEBAG_get0_bag_type(bag));
375 1           BIO_printf(bio, "\nBag Value: ");
376 1           print_attribute(aTHX_ bio, PKCS12_SAFEBAG_get0_bag_obj(bag), &attribute_value);
377             }
378 53           Safefree(attribute_value);
379             } else {
380 0 0         if (!bag_hv)
381 0           i2a_ASN1_OBJECT(bio, PKCS12_SAFEBAG_get0_bag_type(bag));
382             }
383 53           break;
384             #endif
385 2           case NID_safeContentsBag:
386 2 50         if (options & INFO) {
387 2 100         if(bag_hv) {
388 1           SV * value = newSVpvn("safe_contents_bag", strlen("safe_contents_bag"));
389 1 50         if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
390 0           croak("unable to add type to the bag_hv");
391              
392 1           print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
393              
394 1           dump_certs_pkeys_bags(aTHX_ bio, PKCS12_SAFEBAG_get0_safes(bag),
395             pass, passlen, options, pempass, enc, bag_hv);
396             } else {
397 1           BIO_printf(bio, "Safe Contents bag\n");
398 1           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
399 1           dump_certs_pkeys_bags(aTHX_ bio, PKCS12_SAFEBAG_get0_safes(bag),
400             pass, passlen, options, pempass, enc, NULL);
401             }
402             }
403 2           break;
404 0           default:
405 0 0         if(bag_hv)
406 0           return 1;
407 0           BIO_printf(bio, "Warning unsupported bag type: ");
408 0           i2a_ASN1_OBJECT(bio, PKCS12_SAFEBAG_get0_type(bag));
409 0           BIO_printf(bio, "\n");
410             }
411              
412 107           return 1;
413             }
414              
415 101           int dump_certs_pkeys_bags(pTHX_ BIO *bio, CONST_STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, int passlen, int options, char *pempass, const EVP_CIPHER *enc, HV * hash) {
416              
417             int i;
418              
419 101           AV * bags_av = NULL;
420 101           HV * bag_hv = NULL;
421 101 100         if(hash) {
422 68           bags_av = newAV();
423             }
424 223 100         for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
425 122 100         if(hash)
426 75           bag_hv = newHV();
427 122 50         if (!dump_certs_pkeys_bag (aTHX_ bio, sk_PKCS12_SAFEBAG_value (bags, i), pass, passlen, options, pempass, enc, bag_hv)) {
428 0           return 0;
429             }
430 122 100         if(hash)
431 75           av_push(bags_av, newRV_inc((SV *) bag_hv));
432             }
433              
434 101 100         if (hash) {
435 68           SV **svp = NULL;
436             char *type;
437 68 50         if (hv_exists(bag_hv, "type", strlen("type"))) {
438 68           svp = hv_fetch(bag_hv, "type", strlen("type"), 0);
439 68 50         if (svp != NULL)
440 68           type = SvPVbyte_nolen(*svp);
441             }
442 68 50         if (svp != NULL) {
443 68 100         if (strcmp(type, "safe_contents_bag") == 0 ) {
444 1 50         if((hv_store(hash, "safe_contents_bag", strlen("safe_contents_bag"), newRV_inc((SV *) bags_av), 0)) == NULL)
445 0           croak("unable to add bags to the hash");
446             } else {
447 67 50         if((hv_store(hash, "bags", strlen("bags"), newRV_inc((SV *) bags_av), 0)) == NULL)
448 0           croak("unable to add bags to the hash");
449             }
450             }
451             }
452 101           return 1;
453             }
454              
455 77           int dump_certs_keys_p12(pTHX_ BIO *bio, PKCS12 *p12, const char *pass, int passlen, int options, char *pempass, HV * orig_hash) {
456              
457             STACK_OF(PKCS7) *asafes;
458             STACK_OF(PKCS12_SAFEBAG) *bags;
459              
460             int i, bagnid;
461             PKCS7 *p7;
462 77           HV * bag_hv = NULL;
463 77           HV * parameters_hv = NULL;
464 77           AV * pkcs7_bags_av = newAV();
465 77           AV * pkcs7_enc_bags_av = newAV();
466              
467 77 50         if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) {
468 0           croak("Unable to PKCS12_unpack_authsafes");
469             return 0;
470             }
471              
472 176 100         for (i = 0; i < sk_PKCS7_num(asafes); i++) {
473              
474 99 100         if (orig_hash) {
475 67           parameters_hv = newHV();
476 67           bag_hv = newHV();
477             }
478              
479 99           p7 = sk_PKCS7_value(asafes, i);
480              
481 99           bagnid = OBJ_obj2nid(p7->type);
482              
483 99 100         if (bagnid == NID_pkcs7_data) {
484              
485 26 100         if (options & INFO) {
486 18 100         if (orig_hash) {
487 9           bag_hv = newHV();
488 9           av_push(pkcs7_bags_av, newRV_inc((SV *) bag_hv));
489             }
490             else
491 9           BIO_printf(bio, "PKCS7 Data\n");
492             }
493 26           bags = PKCS12_unpack_p7data(p7);
494              
495 73 50         } else if (bagnid == NID_pkcs7_encrypted) {
496 73 100         if (options & INFO) {
497 65 100         if (orig_hash) {
498 58           bag_hv = newHV();
499              
500 58 50         if (p7->d.encrypted != NULL)
501 58           alg_print(aTHX_ bio, p7->d.encrypted->enc_data->algorithm, parameters_hv);
502 58 50         if((hv_store(bag_hv, "parameters", strlen("parameters"), newRV_inc((SV *) parameters_hv), 0)) == NULL)
503 0           croak("unable to add parameters to the hash");
504 58 50         if((hv_store(orig_hash, "pkcs7_encrypted_data", strlen("pkcs7_encrypted_data"), newRV_inc((SV *) bag_hv), 0)) == NULL)
505 0           croak("unable to add pkcs7_encrypted_data to the orig_hash");
506 58           av_push(pkcs7_enc_bags_av, newRV_inc((SV *) bag_hv));
507             } else {
508 7           BIO_printf(bio, "PKCS7 Encrypted data: ");
509 7 50         if (p7->d.encrypted == NULL) {
510 0           BIO_printf(bio, "\n");
511             } else {
512 7           alg_print(aTHX_ bio, p7->d.encrypted->enc_data->algorithm, NULL);
513             }
514             }
515             }
516 73           bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
517              
518             } else {
519 0           continue;
520             }
521              
522 99 50         if (bags == NULL) return 0;
523              
524 99 50         if (!dump_certs_pkeys_bags(aTHX_ bio, bags, pass, passlen, options, pempass, enc, bag_hv)) {
525 0           sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
526 0           return 0;
527             }
528              
529 99 100         if (orig_hash) {
530 67 50         if((hv_store(orig_hash, "pkcs7_data", strlen("pkcs7_data"), newRV_inc((SV *) pkcs7_bags_av), 0)) == NULL)
531 0           croak("unable to add bags to the hash");
532 67 50         if((hv_store(orig_hash, "pkcs7_encrypted_data", strlen("pkcs7_encrypted_data"), newRV_inc((SV *) pkcs7_enc_bags_av), 0)) == NULL)
533 0           croak("unable to add bags to the hash");
534             }
535 99           sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
536             }
537              
538 77           sk_PKCS7_pop_free(asafes, PKCS7_free);
539              
540 77           return 1;
541             }
542             #ifdef TIM
543             # define B_FORMAT_TEXT 0x8000
544             # define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
545             int FMT_istext(int format)
546             {
547             return (format & B_FORMAT_TEXT) == B_FORMAT_TEXT;
548             }
549              
550             BIO *dup_bio_err(int format)
551             {
552             BIO *b = BIO_new_fp(stderr,
553             BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
554              
555             return b;
556             }
557             #endif
558             static unsigned long nmflag = 0;
559             static char nmflag_set = 0;
560             # define XN_FLAG_SPC_EQ (1 << 23)/* Put spaces round '=' */
561              
562             #define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
563              
564             #define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
565             ASN1_STRFLGS_ESC_QUOTE | \
566             ASN1_STRFLGS_ESC_CTRL | \
567             ASN1_STRFLGS_ESC_MSB)
568              
569 64           unsigned long get_nameopt(void)
570             {
571             return
572 64 50         nmflag_set ? nmflag : ESC_FLAGS | XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT | XN_FLAG_SPC_EQ;
573             }
574              
575 64           void print_name(BIO *out, const char *title, CONST_X509_NAME *nm)
576             {
577             char *buf;
578 64           char mline = 0;
579 64           int indent = 0;
580 64           unsigned long lflags = get_nameopt();
581              
582 64 50         if (out == NULL)
583 0           return;
584 64 50         if (title != NULL)
585 64           BIO_puts(out, title);
586 64 50         if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
587 0           mline = 1;
588 0           indent = 4;
589             }
590 64 50         if (lflags == XN_FLAG_COMPAT) {
591 0           buf = X509_NAME_oneline(nm, 0, 0);
592 0           BIO_puts(out, buf);
593 0           BIO_puts(out, "\n");
594 0           OPENSSL_free(buf);
595             } else {
596 64 50         if (mline)
597 0           BIO_puts(out, "\n");
598 64           X509_NAME_print_ex(out, nm, indent, lflags);
599              
600 64           BIO_puts(out, "\n");
601             }
602             }
603              
604 16           void dump_cert_text(BIO *out, X509 *x)
605             {
606 16           print_name(out, "subject=", X509_get_subject_name(x));
607 16           print_name(out, "issuer=", X509_get_issuer_name(x));
608 16           }
609              
610 16           SV * get_cert_subject_name(pTHX_ X509 *x)
611             {
612             BIO *bio;
613 16 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
614              
615 16           print_name(bio, "", X509_get_subject_name(x));
616 16           SV *sv = extractBioString(aTHX_ bio);
617 16           return sv;
618             }
619              
620 16           SV * get_cert_issuer_name(pTHX_ X509 *x)
621             {
622             BIO *bio;
623 16 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
624              
625 16           print_name(bio, "", X509_get_issuer_name(x));
626 16           SV *sv = extractBioString(aTHX_ bio);
627 16           return sv;
628             }
629              
630 119           void get_hex(char *out, unsigned char *buf, int len)
631             {
632             int i;
633 1726 100         for (i = 0; i < len; i++) {
634 1607 100         if (i == (len-1))
635 119           out += sprintf(out, "%02X", buf[i]);
636             else
637 1488           out += sprintf(out, "%02X ", buf[i]);
638             }
639 119           }
640              
641 17           void hex_prin(BIO *out, unsigned char *buf, int len)
642             {
643             int i;
644 247 100         for (i = 0; i < len; i++)
645 230           BIO_printf(out, "%02X ", buf[i]);
646 17           }
647              
648             /* Generalised x509 attribute value print */
649              
650 266           void print_attribute(pTHX_ BIO *out, CONST_ASN1_TYPE *av, char **attribute)
651             {
652             char *value;
653 266           int length = 0;
654             /*
655             const char *ln;
656             char objbuf[80];
657             */
658 266           switch (av->type) {
659 73           case V_ASN1_BMPSTRING:
660 73           length = av->value.bmpstring->length;
661 73 50         if (length < 0 || length > (INT_MAX - 1))
    50          
662 0           croak("BMPSTRING attribute length out of range (got %d)", length);
663 73           value = OPENSSL_uni2asc(av->value.bmpstring->data, length);
664 73 100         if(*attribute != NULL) {
665 62           Renew(*attribute, length, char);
666 62           strncpy(*attribute, value, length);
667             } else {
668 11           BIO_printf(out, "%s\n", value);
669             }
670 73           OPENSSL_free(value);
671 73           break;
672              
673 53           case V_ASN1_UTF8STRING:
674 53           length = av->value.utf8string->length;
675 53 100         if(*attribute != NULL) {
676 52 50         if (length < 0 || length > (INT_MAX - 1))
    50          
677 0           croak("UTF8STRING attribute length out of range (got %d)", length);
678 52           Renew(*attribute, (size_t)length + 1, char);
679 52 50         if (length)
680 52           memcpy(*attribute, av->value.utf8string->data, (size_t)length);
681 52           (*attribute)[length] = '\0';
682             } else {
683 1           BIO_printf(out, "%.*s\n", length, av->value.utf8string->data);
684             }
685 53           break;
686              
687 134           case V_ASN1_OCTET_STRING:
688 134           length = av->value.octet_string->length;
689 134 100         if(*attribute != NULL) {
690 118 50         if (length < 0 || length > INT_MAX / 4)
    50          
691 0           croak("OCTET STRING attribute length out of range (got %d)", length);
692 118           Renew(*attribute, (size_t)length * 4, char);
693 118           get_hex(*attribute, av->value.octet_string->data, length);
694             } else {
695 16           hex_prin(out, av->value.octet_string->data, length);
696 16           BIO_printf(out, "\n");
697             }
698 134           break;
699              
700 2           case V_ASN1_BIT_STRING:
701 2           length = av->value.bit_string->length;
702 2 100         if(*attribute != NULL) {
703 1 50         if (length < 0 || length > INT_MAX / 4)
    50          
704 0           croak("BIT STRING attribute length out of range (got %d)", length);
705 1           Renew(*attribute, (size_t)length * 4, char);
706 1           get_hex(*attribute, av->value.bit_string->data, length);
707             } else {
708 1           hex_prin(out, av->value.bit_string->data, length);
709 1           BIO_printf(out, "\n");
710             }
711 2           break;
712              
713             /* case V_ASN1_OBJECT:
714             ln = OBJ_nid2ln(OBJ_obj2nid(av->value.object));
715             if (!ln)
716             ln = "";
717             OBJ_obj2txt(objbuf, sizeof(objbuf), av->value.object, 1);
718             if(*attribute != NULL) {
719             Renew(*attribute, strlen(ln), char);
720             strncpy(*attribute, ln, strlen(*attribute));
721             } else {
722             BIO_printf(out, "%s (%s)", ln, objbuf);
723             BIO_printf(out, "\n");
724             }
725             break;
726             */
727 4           default:
728 4 100         if(*attribute != NULL) {
729 2           Renew(*attribute, strlen("") + 11 + 2, char); /* +2 for \n\0 */
730 2           snprintf(*attribute, strlen("") + 11 + 2,
731 2           "\n", av->type);
732             }
733             else {
734 2           BIO_printf(out, "\n", av->type);
735             }
736 4           break;
737             }
738 266           }
739              
740             /* Generalised attribute print: handle PKCS#8 and bag attributes */
741 111           int print_attribs(pTHX_ BIO *out, CONST_STACK_OF(X509_ATTRIBUTE) *attrlst,
742             const char *name, HV * hash)
743             {
744             X509_ATTRIBUTE *attr;
745             ASN1_TYPE *av;
746             int i, j, attr_nid;
747 111           AV * bags_av = newAV();
748 111 100         if (!attrlst) {
749 24 100         if(hash) {
750             /* FIXME: May need to change attribute storage for empty attributes */
751             /*SV * value = newSVpvn("", strlen("")); */
752             /*if((hv_store(hash, "attributes", strlen("attributes"), newRV_inc((SV *) bags_av), 0)) == NULL) */
753             /* croak("unable to add attributes to the hash"); */
754             } else
755 12           BIO_printf(out, "%s: \n", name);
756 24           return 1;
757             }
758 87 50         if (!sk_X509_ATTRIBUTE_num(attrlst)) {
759 0 0         if(hash) {
760             /* FIXME: May need to change attribute storage for empty attributes */
761             /*if((hv_store(hash, "attributes", strlen("attributes"), newRV_inc((SV *) bags_av), 0)) == NULL) */
762             /* croak("unable to add attributes to the hash"); */
763             } else
764 0           BIO_printf(out, "%s: \n", name);
765 0           return 1;
766             }
767 87 100         if(!hash)
768 18           BIO_printf(out, "%s\n", name);
769              
770 87           HV * bag_hv = newHV();
771 300 100         for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
772             ASN1_OBJECT *attr_obj;
773 213           attr = sk_X509_ATTRIBUTE_value(attrlst, i);
774 213           attr_obj = X509_ATTRIBUTE_get0_object(attr);
775 213           attr_nid = OBJ_obj2nid(attr_obj);
776 213 100         if (!hash) {
777 30 100         if (attr_nid == NID_undef) {
778 3           BIO_printf(out, " ");
779 3           i2a_ASN1_OBJECT(out, attr_obj);
780 3           BIO_printf(out, ": ");
781             }
782             else {
783 27 50         if (!hash) {
784             /* Print the name of the attributes */
785 27           BIO_printf(out, " ");
786 27           BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
787             }
788             }
789             }
790              
791 213 50         if (X509_ATTRIBUTE_count(attr)) {
792 426 100         for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
793             {
794 213           av = X509_ATTRIBUTE_get0_type(attr, j);
795 213           char *attribute_value = NULL;
796 213 100         if(hash) {
797 183           const char *attribute_id = NULL;
798 183           Newx(attribute_value, 0, char);
799 183           print_attribute(aTHX_ out, av, &attribute_value);
800 183 100         if (attr_nid != NID_undef) {
801             /* Save the attribute name and value to the hash */
802 129           attribute_id = OBJ_nid2ln(attr_nid);
803 129 50         if (attribute_id) {
804 129 50         if((hv_store(bag_hv, attribute_id, strlen(attribute_id), newSVpvn(attribute_value, strlen(attribute_value)), 0)) == NULL)
805 0           croak("unable to add MAC to the hash");
806             }
807             } else {
808             BIO *attr_bio;
809             BUF_MEM* bptr;
810              
811 54 50         CHECK_OPEN_SSL(attr_bio = BIO_new(BIO_s_mem()));
812 54           i2a_ASN1_OBJECT(attr_bio, attr_obj);
813              
814 54 50         CHECK_OPEN_SSL(BIO_flush(attr_bio) == 1);
815 54           BIO_get_mem_ptr(attr_bio, &bptr);
816              
817 54 50         if (bptr->length > 0) {
818 54 50         if((hv_store(bag_hv, bptr->data, bptr->length, newSVpvn(attribute_value, strlen(attribute_value)), 0)) == NULL)
819 0           croak("unable to add MAC to the hash");
820             }
821              
822 54 50         CHECK_OPEN_SSL(BIO_set_close(attr_bio, BIO_CLOSE) == 1);
823 54           BIO_free(attr_bio);
824             }
825 183           Safefree(attribute_value);
826             } else {
827 30           print_attribute(aTHX_ out, av, &attribute_value);
828             }
829 213           av_push(bags_av, newRV_inc((SV *) bag_hv));
830             }
831             } else {
832 0           BIO_printf(out, "\n");
833             }
834             }
835 87 100         if (hash) {
836 69 50         if((hv_store(hash, name, strlen(name), newRV_inc((SV *) bag_hv), 0)) == NULL)
837 0           croak("unable to add bags to the hash");
838             }
839 87           return 1;
840             }
841              
842 75           static int alg_print(pTHX_ BIO *bio, CONST_X509_ALGOR *alg, HV * parameters_hash)
843             {
844             int pbenid, aparamtype;
845             CONST_ASN1_OBJECT *aoid;
846             CONST_VOID *aparam;
847 75           PBEPARAM *pbe = NULL;
848              
849 75           X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);
850 75           pbenid = OBJ_obj2nid(aoid);
851 75 100         if (parameters_hash) {
852 63           SV * nid_long_name = newSVpvn(OBJ_nid2ln(pbenid), strlen(OBJ_nid2ln(pbenid)));
853 63 50         if((hv_store(parameters_hash, "nid_long_name", strlen("nid_long_name"), nid_long_name, 0)) == NULL)
854 0           croak("unable to add MAC to the parameters_hash");
855 63           SV * nid_short_name = newSVpvn(OBJ_nid2sn(pbenid), strlen(OBJ_nid2sn(pbenid)));
856 63 50         if((hv_store(parameters_hash, "nid_short_name", strlen("nid_short_name"), nid_short_name, 0)) == NULL)
857 0           croak("unable to add MAC to the parameters_hash");
858             } else {
859 12           BIO_printf(bio, "%s", OBJ_nid2ln(pbenid));
860             }
861             /*
862             * If PBE algorithm is PBES2 decode algorithm parameters
863             * for additional details.
864             */
865 75 100         if (pbenid == NID_pbes2) {
866 14           PBE2PARAM *pbe2 = NULL;
867             int encnid;
868 14 50         if (aparamtype == V_ASN1_SEQUENCE)
869 14           pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
870 14 50         if (pbe2 == NULL) {
871 0           BIO_puts(bio, ", ");
872 0           goto done;
873             }
874 14           X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
875 14           pbenid = OBJ_obj2nid(aoid);
876              
877 14           X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
878 14           encnid = OBJ_obj2nid(aoid);
879 14 100         if (parameters_hash) {
880 7           SV * nid_long_name = newSVpvn(OBJ_nid2ln(pbenid), strlen(OBJ_nid2ln(pbenid)));
881 7 50         if((hv_store(parameters_hash, "nid_long_name", strlen("nid_long_name"), nid_long_name, 0)) == NULL)
882 0           croak("unable to add MAC to the parameters_hash");
883 7           SV * nid_short_name = newSVpvn(OBJ_nid2sn(pbenid), strlen(OBJ_nid2sn(pbenid)));
884 7 50         if((hv_store(parameters_hash, "nid_short_name", strlen("nid_short_name"), nid_short_name, 0)) == NULL)
885 0           croak("unable to add MAC to the parameters_hash");
886             } else
887 7           BIO_printf(bio, ", %s, %s", OBJ_nid2ln(pbenid),
888             OBJ_nid2sn(encnid));
889             /* If KDF is PBKDF2 decode parameters */
890 14 50         if (pbenid == NID_id_pbkdf2) {
891 14           PBKDF2PARAM *kdf = NULL;
892             int prfnid;
893 14 50         if (aparamtype == V_ASN1_SEQUENCE)
894 14           kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
895 14 50         if (kdf == NULL) {
896 0           BIO_puts(bio, ", ");
897 0           goto done;
898             }
899              
900 14 50         if (kdf->prf == NULL) {
901 0           prfnid = NID_hmacWithSHA1;
902             } else {
903 14           X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
904 14           prfnid = OBJ_obj2nid(aoid);
905             }
906 14 100         if (parameters_hash) {
907 7           SV * iteration = newSViv(ASN1_INTEGER_get(kdf->iter));
908 7 50         if((hv_store(parameters_hash, "iteration", strlen("iteration"), iteration, 0)) == NULL)
909 0           croak("unable to add iteration to the parameters_hash");
910             } else
911 14           BIO_printf(bio, ", Iteration %ld, PRF %s",
912 7           ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
913 14           PBKDF2PARAM_free(kdf);
914             #if OPENSSL_VERSION_NUMBER > 0x10100000L
915             #ifndef LIBRESSL_VERSION_NUMBER
916             #ifndef OPENSSL_NO_SCRYPT
917 0 0         } else if (pbenid == NID_id_scrypt) {
918 0           SCRYPT_PARAMS *kdf = NULL;
919              
920 0 0         if (aparamtype == V_ASN1_SEQUENCE)
921 0           kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
922 0 0         if (kdf == NULL) {
923 0           BIO_puts(bio, ", ");
924 0           goto done;
925             }
926 0 0         if (parameters_hash) {
927 0 0         if((hv_store(parameters_hash, "salt_length", strlen("salt_length"), newSViv(ASN1_STRING_length(kdf->salt)), 0)) == NULL)
928 0           croak("unable to add salt_length to the parameters_hash");
929 0 0         if((hv_store(parameters_hash, "cost", strlen("cost"), newSViv(ASN1_INTEGER_get(kdf->costParameter)), 0)) == NULL)
930 0           croak("unable to add cost to the parameters_hash");
931 0 0         if((hv_store(parameters_hash, "block_size", strlen("block_size"), newSViv(ASN1_INTEGER_get(kdf->blockSize)), 0)) == NULL)
932 0           croak("unable to add block_size to the parameters_hash");
933 0 0         if((hv_store(parameters_hash, "parallelism", strlen("parallelism"), newSViv(ASN1_INTEGER_get(kdf->parallelizationParameter)), 0)) == NULL)
934 0           croak("unable to add parallelism to the parameters_hash");
935             } else
936 0           BIO_printf(bio, ", Salt length: %d, Cost(N): %ld, "
937             "Block size(r): %ld, Parallelism(p): %ld",
938 0           ASN1_STRING_length(kdf->salt),
939 0           ASN1_INTEGER_get(kdf->costParameter),
940 0           ASN1_INTEGER_get(kdf->blockSize),
941 0           ASN1_INTEGER_get(kdf->parallelizationParameter));
942 0           SCRYPT_PARAMS_free(kdf);
943             #endif
944             #endif
945             #endif
946             }
947 14           PBE2PARAM_free(pbe2);
948             } else {
949 61 50         if (aparamtype == V_ASN1_SEQUENCE)
950 61           pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
951 61 50         if (pbe == NULL) {
952 0           BIO_puts(bio, ", ");
953 0           goto done;
954             }
955 61 100         if (parameters_hash) {
956 56           long int val = ASN1_INTEGER_get(pbe->iter);
957 56           SV * iteration = newSViv(val);
958 56 50         if((hv_store(parameters_hash, "iteration", strlen("iteration"), iteration, 0)) == NULL)
959 0           croak("unable to add MAC to the parameters_hash");
960             } else
961 5           BIO_printf(bio, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
962 61           PBEPARAM_free(pbe);
963             }
964 75           done:
965 75 100         if(!parameters_hash)
966 12           BIO_puts(bio, "\n");
967 75           return 1;
968             }
969              
970             MODULE = Crypt::OpenSSL::PKCS12 PACKAGE = Crypt::OpenSSL::PKCS12
971              
972             PROTOTYPES: DISABLE
973              
974             BOOT:
975             {
976             HV *stash;
977             char *name;
978             int i;
979              
980 16           struct { char *n; I32 v; } Crypt__OpenSSL__PKCS12__const[] = {
981             {"NOKEYS", NOKEYS},
982             {"NOCERTS", NOCERTS},
983             {"INFO", INFO},
984             {"CLCERTS", CLCERTS},
985             {"CACERTS", CACERTS},
986             {Nullch,0}
987             };
988              
989 16           OpenSSL_add_all_algorithms();
990              
991 16           stash = gv_stashpvn("Crypt::OpenSSL::PKCS12", 22, TRUE);
992              
993 96 100         for (i = 0; (name = Crypt__OpenSSL__PKCS12__const[i].n); i++) {
994 80           newCONSTSUB(stash, name, newSViv(Crypt__OpenSSL__PKCS12__const[i].v));
995             }
996             }
997              
998             Crypt::OpenSSL::PKCS12
999             new(class)
1000             SV *class
1001              
1002             CODE:
1003              
1004 0 0         if ((RETVAL = PKCS12_new()) == NULL) {
1005 0           croak("Couldn't create PKCS12_new() for class %" SVf "\n", SVfARG(class));
1006             }
1007              
1008             OUTPUT:
1009             RETVAL
1010              
1011             IV legacy_support(class)
1012             SV *class;
1013              
1014             CODE:
1015 1           RETVAL = 1;
1016             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1017 1 50         if (legacy)
1018 1           RETVAL = 1;
1019             else
1020 0           RETVAL = 0;
1021             #endif
1022             OUTPUT:
1023             RETVAL
1024              
1025             Crypt::OpenSSL::PKCS12
1026             new_from_string(class, string)
1027             SV *class
1028             SV *string
1029              
1030             ALIAS:
1031             new_from_file = 1
1032              
1033             PREINIT:
1034             BIO *bio;
1035             STRLEN str_len;
1036             char *str_ptr;
1037             CODE:
1038              
1039 36 50         SvGETMAGIC(string);
    0          
1040             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1041             /* FIXME: There should likely be an option for whether to load the legacy provider */
1042 36           legacy = OSSL_PROVIDER_load(NULL, "legacy");
1043 36 50         if (legacy == NULL) {
1044 0           warn("Failed to load Legacy provider\n");
1045             }
1046 36           deflt = OSSL_PROVIDER_load(NULL, "default");
1047 36 50         if (deflt == NULL) {
1048 0           OSSL_PROVIDER_unload(legacy);
1049 0           croak("Failed to load Default provider\n");
1050             }
1051             #endif
1052              
1053 36 100         if (SvPOKp(string) || SvNOKp(string) || SvIOKp(string)) {
    100          
    100          
1054 28 100         if (ix == 1) {
1055             /* We are not looking up the SV's UTF8 bit because BIO_new_file() accepts
1056             * filename like syscall fopen() which mainly may accept octet sequences
1057             * for UTF-8 in C char*. That's what we get from using SvPV(). Also,
1058             * using SvPV() is not a bug if ASCII input is only allowed. */
1059 15           str_ptr = SvPV(string, str_len);
1060             } else {
1061             /* To avoid encoding mess, caller is not allowed to provide octets from
1062             * UTF-8 encoded strings. BIO_new_mem_buf() needs octet input only. */
1063 13 100         if (SvUTF8(string)) {
1064 4           croak("PKCS12_new_from: Source string must not be UTF-8 encoded (please use octets)");
1065             }
1066 9           str_ptr = SvPV(string, str_len);
1067             }
1068             } else {
1069 8           croak("PKCS12_new_from: Invalid Perl type for string or file was passed (0x%x).", (unsigned int)SvFLAGS(string));
1070             }
1071              
1072 24 50         if (!str_ptr || !str_len) croak("PKCS12_new_from: No string or file was passed.");
    50          
1073              
1074 24 100         if (ix == 1) {
1075 15           bio = BIO_new_file(str_ptr, "rb");
1076             } else {
1077 9           bio = BIO_new_mem_buf(str_ptr, str_len);
1078             }
1079              
1080 24 50         if (!bio) croak("Failed to create BIO");
1081              
1082             /* this can come in any number of ways */
1083 24 100         if ((RETVAL = d2i_PKCS12_bio(bio, 0)) == NULL) {
1084 6           BIO_free_all(bio);
1085 6           croak("%" SVf ": Couldn't create PKCS12 from d2i_PKCS12_BIO(): %s", SVfARG(class), ssl_error(aTHX));
1086             }
1087              
1088 18           BIO_free_all(bio);
1089              
1090             OUTPUT:
1091             RETVAL
1092              
1093             # This is called at per-object destruction time.
1094             void
1095             DESTROY(pkcs12)
1096             Crypt::OpenSSL::PKCS12 pkcs12;
1097              
1098             CODE:
1099 18 50         if (pkcs12) {
1100 18           PKCS12_free(pkcs12);
1101             }
1102              
1103             # This is called via an END block in the Perl module to clean up initialization that happened in BOOT.
1104             void
1105             __PKCS12_cleanup(void)
1106             CODE:
1107              
1108 16           CRYPTO_cleanup_all_ex_data();
1109 16           ERR_free_strings();
1110             #if OPENSSL_VERSION_NUMBER < 0x10100000L
1111             ERR_remove_state(0);
1112             #endif
1113 16           EVP_cleanup();
1114              
1115             SV*
1116             as_string(pkcs12)
1117             Crypt::OpenSSL::PKCS12 pkcs12;
1118              
1119             PREINIT:
1120             BIO *bio;
1121              
1122             CODE:
1123              
1124 3 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1125              
1126 3 50         if (!(i2d_PKCS12_bio(bio, pkcs12))) {
1127 0           sv_bio_error(aTHX_ bio);
1128 0           croak("i2d_PKCS12_bio: %s", ssl_error(aTHX));
1129             }
1130              
1131 3           RETVAL = extractBioString(aTHX_ bio);
1132              
1133             OUTPUT:
1134             RETVAL
1135              
1136             SV*
1137             mac_ok(pkcs12, pwd = &PL_sv_undef)
1138             Crypt::OpenSSL::PKCS12 pkcs12
1139             SV *pwd
1140              
1141             PREINIT:
1142 9           STRLEN pwd_len = 0;
1143 9 50         const char *pwd_str = "";
1144              
1145             CODE:
1146              
1147 9 50         if (SvOK(pwd)) {
1148 9           pwd_str = SvPV(pwd, pwd_len);
1149 9 50         if (pwd_len > (STRLEN)INT_MAX)
1150 0           croak("password length exceeds INT_MAX");
1151             }
1152              
1153 9 100         if (!(PKCS12_verify_mac(pkcs12, pwd_str, (int)pwd_len)))
1154 1           croak("PKCS12_verify_mac: \n%s", ssl_error(aTHX));
1155              
1156 8           RETVAL = &PL_sv_yes;
1157              
1158             OUTPUT:
1159             RETVAL
1160              
1161             SV*
1162             changepass(pkcs12, oldpwd = &PL_sv_undef, newpwd = &PL_sv_undef)
1163             Crypt::OpenSSL::PKCS12 pkcs12
1164             SV *oldpwd
1165             SV *newpwd
1166              
1167             PREINIT:
1168 0           STRLEN oldpwd_len = 0, newpwd_len = 0;
1169 0           const char *oldpwd_str = "";
1170 0 0         const char *newpwd_str = "";
1171              
1172             CODE:
1173              
1174 0 0         if (SvOK(oldpwd)) {
1175 0           oldpwd_str = SvPV(oldpwd, oldpwd_len);
1176 0 0         if (memchr(oldpwd_str, '\0', oldpwd_len) != NULL)
1177 0           croak("old PKCS12 password contains embedded NUL byte; "
1178             "PKCS12_newpass() uses strlen() and would silently truncate it");
1179             }
1180 0 0         if (SvOK(newpwd)) {
1181 0           newpwd_str = SvPV(newpwd, newpwd_len);
1182 0 0         if (memchr(newpwd_str, '\0', newpwd_len) != NULL)
1183 0           croak("new PKCS12 password contains embedded NUL byte; "
1184             "PKCS12_newpass() uses strlen() and would silently truncate it");
1185             }
1186              
1187 0 0         if (!(PKCS12_newpass(pkcs12, oldpwd_str, newpwd_str))) {
1188 0           warn("PKCS12_newpass failed: %s", ssl_error(aTHX));
1189 0           RETVAL = &PL_sv_no;
1190             } else {
1191 0           RETVAL = &PL_sv_yes;
1192             }
1193              
1194             OUTPUT:
1195             RETVAL
1196              
1197             SV*
1198             create(pkcs12, cert_chain_pem = "", pk = "", pass = &PL_sv_undef, file = 0, name = "PKCS12 Certificate")
1199             char *cert_chain_pem
1200             char *pk
1201             SV *pass
1202             char *file
1203             char *name
1204              
1205             PREINIT:
1206             FILE *fp;
1207             EVP_PKEY* pkey;
1208             PKCS12 *p12;
1209 4           STACK_OF(X509) *cert_chain = NULL;
1210 4           STRLEN pass_len = 0;
1211 4 50         const char *pass_str = NULL;
1212              
1213             CODE:
1214              
1215 4 50         if (SvOK(pass)) {
1216 4           pass_str = SvPV(pass, pass_len);
1217 4 100         if (memchr(pass_str, '\0', pass_len) != NULL)
1218 1           croak("PKCS12 password contains embedded NUL byte; "
1219             "PKCS12_create() uses strlen() and would silently truncate it");
1220             }
1221              
1222 3           pkey = _load_pkey(pk, PEM_read_bio_PrivateKey);
1223 3           cert_chain = _load_cert_chain(cert_chain_pem, PEM_X509_INFO_read_bio);
1224 3           p12 = PKCS12_create(pass_str, name, pkey, sk_X509_shift(cert_chain), cert_chain, 0, 0, 0, 0, 0);
1225              
1226 3 50         if (!p12) {
1227 0           ERR_print_errors_fp(stderr);
1228 0           croak("Error creating PKCS#12 structure\n");
1229             }
1230              
1231 3 50         if (!(fp = fopen(file, "wb"))) {
1232 0           ERR_print_errors_fp(stderr);
1233 0           croak("Error opening file %s\n", file);
1234             }
1235              
1236 3           i2d_PKCS12_fp(fp, p12);
1237 3           PKCS12_free(p12);
1238 3           fclose(fp);
1239              
1240 3           RETVAL = &PL_sv_yes;
1241              
1242             OUTPUT:
1243             RETVAL
1244              
1245              
1246             SV*
1247             create_as_string(pkcs12, cert_chain_pem = "", pk = "", pass = &PL_sv_undef, name = "PKCS12 Certificate")
1248             char *cert_chain_pem
1249             char *pk
1250             SV *pass
1251             char *name
1252              
1253             PREINIT:
1254             BIO *bio;
1255             EVP_PKEY* pkey;
1256             PKCS12 *p12;
1257 2           STACK_OF(X509) *cert_chain = NULL;
1258 2           STRLEN pass_len = 0;
1259 2 50         const char *pass_str = NULL;
1260              
1261             CODE:
1262              
1263 2 50         if (SvOK(pass)) {
1264 2           pass_str = SvPV(pass, pass_len);
1265 2 100         if (memchr(pass_str, '\0', pass_len) != NULL)
1266 1           croak("PKCS12 password contains embedded NUL byte; "
1267             "PKCS12_create() uses strlen() and would silently truncate it");
1268             }
1269              
1270 1           pkey = _load_pkey(pk, PEM_read_bio_PrivateKey);
1271 1           cert_chain = _load_cert_chain(cert_chain_pem, PEM_X509_INFO_read_bio);
1272 1           p12 = PKCS12_create(pass_str, name, pkey, sk_X509_shift(cert_chain), cert_chain, 0, 0, 0, 0, 0);
1273              
1274 1 50         if (!p12) {
1275 0           ERR_print_errors_fp(stderr);
1276 0           croak("Error creating PKCS#12 structure\n");
1277             }
1278              
1279 1 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1280 1           i2d_PKCS12_bio(bio, p12);
1281              
1282 1           RETVAL = extractBioString(aTHX_ bio);
1283 1           PKCS12_free(p12);
1284              
1285             OUTPUT:
1286             RETVAL
1287              
1288             SV*
1289             certificate(pkcs12, pwd = &PL_sv_undef)
1290             Crypt::OpenSSL::PKCS12 pkcs12
1291             SV *pwd
1292              
1293             PREINIT:
1294             BIO *bio;
1295 4           STACK_OF(PKCS7) *asafes = NULL;
1296 4           STRLEN pwd_len = 0;
1297 4 50         const char *pwd_str = "";
1298              
1299             CODE:
1300              
1301 4 50         if (SvOK(pwd)) {
1302 4           pwd_str = SvPV(pwd, pwd_len);
1303 4 50         if (pwd_len > (STRLEN)INT_MAX)
1304 0           croak("password length exceeds INT_MAX");
1305             }
1306              
1307 4 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1308              
1309 4 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1310 0           RETVAL = newSVpvn("",0);
1311              
1312 4           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd_str, (int)pwd_len, CLCERTS|NOKEYS, NULL, NULL);
1313              
1314 4           RETVAL = extractBioString(aTHX_ bio);
1315              
1316             OUTPUT:
1317             RETVAL
1318              
1319             SV*
1320             ca_certificate(pkcs12, pwd = &PL_sv_undef)
1321             Crypt::OpenSSL::PKCS12 pkcs12
1322             SV *pwd
1323              
1324             PREINIT:
1325             BIO *bio;
1326 1           STACK_OF(PKCS7) *asafes = NULL;
1327 1           STRLEN pwd_len = 0;
1328 1 50         const char *pwd_str = "";
1329              
1330             CODE:
1331              
1332 1 50         if (SvOK(pwd)) {
1333 1           pwd_str = SvPV(pwd, pwd_len);
1334 1 50         if (pwd_len > (STRLEN)INT_MAX)
1335 0           croak("password length exceeds INT_MAX");
1336             }
1337              
1338 1 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1339              
1340 1 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1341 0           RETVAL = newSVpvn("",0);
1342              
1343 1           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd_str, (int)pwd_len, CACERTS|NOKEYS, NULL, NULL);
1344              
1345 1           RETVAL = extractBioString(aTHX_ bio);
1346              
1347             OUTPUT:
1348             RETVAL
1349              
1350             SV*
1351             private_key(pkcs12, pwd = &PL_sv_undef)
1352             Crypt::OpenSSL::PKCS12 pkcs12
1353             SV *pwd
1354              
1355             PREINIT:
1356             BIO *bio;
1357 3           STRLEN pwd_len = 0;
1358 3 50         const char *pwd_str = "";
1359              
1360             CODE:
1361              
1362 3 50         if (SvOK(pwd)) {
1363 3           pwd_str = SvPV(pwd, pwd_len);
1364 3 50         if (pwd_len > (STRLEN)INT_MAX)
1365 0           croak("password length exceeds INT_MAX");
1366             }
1367              
1368 3 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1369              
1370 3           PKCS12_unpack_authsafes(pkcs12);
1371              
1372 3           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd_str, (int)pwd_len, NOCERTS, NULL, NULL);
1373              
1374 3           RETVAL = extractBioString(aTHX_ bio);
1375              
1376             OUTPUT:
1377             RETVAL
1378              
1379             HV* info_as_hash(pkcs12, pwd = &PL_sv_undef)
1380             Crypt::OpenSSL::PKCS12 pkcs12
1381             SV *pwd
1382              
1383             PREINIT:
1384             BIO *bio;
1385 60           STACK_OF(PKCS7) *asafes = NULL;
1386 60           STRLEN pwd_len = 0;
1387 60 50         const char *pwd_str = "";
1388              
1389             CONST_ASN1_INTEGER *tmaciter;
1390             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1391             SV *value;
1392             CONST_X509_ALGOR *macalgid;
1393             CONST_ASN1_OBJECT *macobj;
1394             CONST_ASN1_OCTET_STRING *tmac;
1395             CONST_ASN1_OCTET_STRING *tsalt;
1396             #endif
1397              
1398             CODE:
1399 60 50         if (SvOK(pwd)) {
1400 60           pwd_str = SvPV(pwd, pwd_len);
1401 60 50         if (pwd_len > (STRLEN)INT_MAX)
1402 0           croak("password length exceeds INT_MAX");
1403             }
1404 60           RETVAL = newHV();
1405              
1406 60 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1407              
1408 60 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1409 0           RETVAL = newHV();
1410 60           HV * mac = newHV();
1411             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1412 60           PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, pkcs12);
1413             /* current hash algorithms do not use parameters so extract just name,
1414             in future alg_print() may be needed */
1415 60           X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
1416 60           i2a_ASN1_OBJECT(bio, macobj);
1417 60           value = extractBioString(aTHX_ bio);
1418 60 50         if((hv_store(mac, "digest", strlen("digest"), value, 0)) == NULL)
1419 0           croak("unable to add digest to the hash");
1420             #else
1421             tmaciter = pkcs12->mac->iter;
1422             #endif
1423 60 50         SV * mac_iteration = newSViv (tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
1424              
1425 60 50         if((hv_store(mac, "iteration", strlen("iteration"), mac_iteration, 0)) == NULL)
1426 0           croak("unable to add iteration to the hash");
1427 60 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1428             /* BIO_printf(bio, "MAC length: %ld, salt length: %ld", */
1429             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1430 60 50         SV * mac_len = newSViv(tmac != NULL ? ASN1_STRING_length(tmac) : 0L);
1431 60 50         SV * salt_len = newSViv(tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
1432              
1433 60 50         if((hv_store(mac, "length", 6, mac_len, 0)) == NULL)
1434 0           croak("unable to add length to the hash");
1435             #else
1436             SV * salt_len = newSViv((pkcs12)->mac ? pkcs12->mac->salt->length : 0L);
1437             #endif
1438              
1439 60 50         if((hv_store(mac, "salt_length", strlen("salt_length"), INT2PTR(SV*, salt_len), 0)) == NULL)
1440 0           croak("unable to add salt_length to the hash");
1441              
1442 60 50         if((hv_store(RETVAL, "mac", strlen("mac"), newRV_inc((SV *) mac), 0)) == NULL)
1443 0           croak("unable to add MAC to the hash");
1444 60           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd_str, (int)pwd_len, INFO, NULL, RETVAL);
1445              
1446 60           SV * end = extractBioString(aTHX_ bio);
1447              
1448 60 50         if (SvPOK(end)) {
1449 0 0         if (SvCUR(end) != 0)
1450 0           printf("BIO %s\n", SvPVbyte_nolen(end));
1451 0           warn("bio from info_as_hash should be zero length - report issue");
1452             }
1453              
1454 60           sv_2mortal((SV*)RETVAL);
1455              
1456             OUTPUT:
1457             RETVAL
1458              
1459             SV*
1460             info(pkcs12, pwd = &PL_sv_undef)
1461             Crypt::OpenSSL::PKCS12 pkcs12
1462             SV *pwd
1463              
1464             PREINIT:
1465             BIO *bio;
1466 9           STACK_OF(PKCS7) *asafes = NULL;
1467 9           STRLEN pwd_len = 0;
1468 9 50         const char *pwd_str = "";
1469              
1470             CONST_ASN1_INTEGER *tmaciter;
1471             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1472             CONST_X509_ALGOR *macalgid;
1473             CONST_ASN1_OBJECT *macobj;
1474             CONST_ASN1_OCTET_STRING *tmac;
1475             CONST_ASN1_OCTET_STRING *tsalt;
1476             #endif
1477             CODE:
1478              
1479 9 50         if (SvOK(pwd)) {
1480 9           pwd_str = SvPV(pwd, pwd_len);
1481 9 50         if (pwd_len > (STRLEN)INT_MAX)
1482 0           croak("password length exceeds INT_MAX");
1483             }
1484              
1485 9 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1486              
1487 9 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1488 0           RETVAL = newSVpvn("",0);
1489             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1490 9           PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, pkcs12);
1491             /* current hash algorithms do not use parameters so extract just name,
1492             in future alg_print() may be needed */
1493 9           X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
1494 9           BIO_puts(bio, "MAC: ");
1495 9           i2a_ASN1_OBJECT(bio, macobj);
1496             /* current hash algorithms do not use parameters so extract just name,
1497             in future alg_print() may be needed */
1498 9           BIO_printf(bio, ", Iteration %ld\n",
1499 9 50         tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
1500 18           BIO_printf(bio, "MAC length: %ld, salt length: %ld\n",
1501 9 50         tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
1502 9 50         tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
1503             #else
1504             tmaciter = pkcs12->mac->iter;
1505             BIO_printf(bio, "MAC Iteration %ld\n",
1506             tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
1507             /* If we enter empty password try no password first */
1508             if (!PKCS12_verify_mac(pkcs12, pwd_str, (int)pwd_len)) {
1509             BIO_printf(bio, "Mac verify error: invalid password?\n");
1510             ERR_print_errors(bio);
1511             goto end;
1512             }
1513             BIO_printf(bio, "MAC verified OK\n");
1514             end:
1515             #endif
1516 9           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd_str, (int)pwd_len, INFO, NULL, NULL);
1517              
1518 9           RETVAL = extractBioString(aTHX_ bio);
1519              
1520             OUTPUT:
1521             RETVAL