File Coverage

PKCS12.xs
Criterion Covered Total %
statement 504 634 79.5
branch 248 414 59.9
condition n/a
subroutine n/a
pod n/a
total 752 1048 71.7


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 89           SV* extractBioString(pTHX_ BIO* p_stringBio)
155             {
156             SV* sv;
157             char *datap;
158 89           long datasize = 0;
159            
160 89 50         CHECK_OPEN_SSL(BIO_flush(p_stringBio) == 1);
161              
162 89           datasize = BIO_get_mem_data(p_stringBio, &datap);
163 89           sv = newSVpv(datap, datasize);
164              
165 89 50         CHECK_OPEN_SSL(BIO_set_close(p_stringBio, BIO_CLOSE) == 1);
166 89           BIO_free(p_stringBio);
167 89           return sv;
168             }
169              
170 6           static const char *ssl_error(pTHX) {
171             BIO *bio;
172             SV *sv;
173             STRLEN l;
174              
175 6 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
176 6           ERR_print_errors(bio);
177 6           sv = extractBioString(aTHX_ bio);
178 6           ERR_clear_error();
179 6           return SvPV(sv, l);
180             }
181              
182             /* these are trimmed from their openssl/apps/pkcs12.c counterparts */
183 65           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 65           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 65           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 65           EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
196 65           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 65           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 16           case NID_pkcs8ShroudedKeyBag: ;
244              
245 16 100         if (options & NOKEYS) return 1;
246              
247 11 50         if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
248 0           return 0;
249 11 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 11 100         if (options & INFO) {
254             CONST_X509_ALGOR *tp8alg;
255             #if OPENSSL_VERSION_NUMBER > 0x10100000L
256             CONST_X509_SIG *tp8;
257              
258 8           tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
259 8           X509_SIG_get0(tp8, &tp8alg, NULL);
260             #else
261             tp8alg = bag->value.shkeybag->algor;
262             #endif
263 8           key_attrs = PKCS8_pkey_get0_attrs(p8);
264 8 100         if (bag_hv) {
265 4           SV *str_bag = newSVpvn("shrouded_bag", strlen("shrouded_bag"));
266 4           HV * parameters_hv = newHV();;
267 4 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 4           alg_print(aTHX_ bio, tp8alg, parameters_hv);
271             #endif
272 4           print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
273 4 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 4           SV *str_key_bag = newSVpvn("shrouded_keybag", strlen("shrouded_keybag"));
277 4 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 4           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 4 50         CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
285 4           PEM_write_bio_PrivateKey (keybio, pkey, enc, NULL, 0, NULL, pempass);
286 4           SV * key_sv = extractBioString(aTHX_ keybio);
287              
288 4 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 4           BIO_printf(bio, "Shrouded Keybag: ");
292 4           alg_print(aTHX_ bio, tp8alg, NULL);
293 4           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
294              
295 4           print_attribs(aTHX_ bio, key_attrs, "Key Attributes", NULL);
296 4           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 11           PKCS8_PRIV_KEY_INFO_free((PKCS8_PRIV_KEY_INFO *)p8);
303              
304 11           EVP_PKEY_free(pkey);
305              
306 11           break;
307              
308 43           case NID_certBag:
309              
310 43 100         if (options & NOCERTS) return 1;
311              
312 37 100         if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
313              
314 19 100         if (options & CACERTS) return 1;
315              
316 18 100         } else if (options & CLCERTS) {
317              
318 3           return 1;
319             }
320              
321 33 50         if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) return 1;
322              
323 33 50         if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) return 0;
324 33 100         if (options & INFO) {
325 28 100         if (bag_hv) {
326             BIO *keybio;
327 14 50         CHECK_OPEN_SSL(keybio = BIO_new(BIO_s_mem()));
328 14           SV * value = newSVpvn("certificate_bag", strlen("certificate_bag"));
329 14           print_attribs(aTHX_ keybio, bag_attrs, "bag_attributes", bag_hv);
330 14 50         if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
331 0           croak("unable to add type to the bag_hv");
332 14 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 14 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 14           PEM_write_bio_X509 (keybio, x509);
337 14           SV * key_sv = extractBioString(aTHX_ keybio);
338 14 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 14           BIO_printf(bio, "Certificate bag\n");
343 14           print_attribs(aTHX_ bio, bag_attrs, "Bag Attributes", NULL);
344 14           dump_cert_text(bio, x509);
345 14           PEM_write_bio_X509 (bio, x509);
346             }
347             } else {
348 5           PEM_write_bio_X509 (bio, x509);
349             }
350              
351 33           X509_free(x509);
352              
353 33           break;
354              
355             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
356 2           case NID_secretBag:
357             /*FIXME: Not sure how to test this */
358 2 50         if (options & INFO) {
359 2           char * attribute_value = NULL;
360 2 100         if (bag_hv){
361 1           SV * value = newSVpvn("secret_bag", strlen("secret_bag"));
362 1 50         if((hv_store(bag_hv, "type", strlen("type"), value, 0)) == NULL)
363 0           croak("unable to add type to the bag_hv");
364 1           print_attribs(aTHX_ bio, bag_attrs, "bag_attributes", bag_hv);
365 1           Newx(attribute_value, 0, char);
366 1           print_attribute(aTHX_ bio, PKCS12_SAFEBAG_get0_bag_obj(bag), &attribute_value);
367 1 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 2           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 2           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 50           return 1;
413             }
414              
415 46           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 46           AV * bags_av = NULL;
420 46           HV * bag_hv = NULL;
421 46 100         if(hash) {
422 15           bags_av = newAV();
423             }
424 111 100         for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
425 65 100         if(hash)
426 21           bag_hv = newHV();
427 65 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 65 100         if(hash)
431 21           av_push(bags_av, newRV_inc((SV *) bag_hv));
432             }
433              
434 46 100         if (hash) {
435 15           SV **svp = NULL;
436             char *type;
437 15 50         if (hv_exists(bag_hv, "type", strlen("type"))) {
438 15           svp = hv_fetch(bag_hv, "type", strlen("type"), 0);
439 15 50         if (svp != NULL)
440 15           type = SvPVbyte_nolen(*svp);
441             }
442 15 50         if (svp != NULL) {
443 15 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 14 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 46           return 1;
453             }
454              
455 24           int dump_certs_keys_p12(pTHX_ BIO *bio, PKCS12 *p12, 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 24           HV * bag_hv = NULL;
463 24           HV * parameters_hv = NULL;
464 24           AV * pkcs7_bags_av = newAV();
465 24           AV * pkcs7_enc_bags_av = newAV();
466              
467 24 50         if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) {
468 0           croak("Unable to PKCS12_unpack_authsafes");
469             return 0;
470             }
471              
472 68 100         for (i = 0; i < sk_PKCS7_num(asafes); i++) {
473              
474 44 100         if (orig_hash) {
475 14           parameters_hv = newHV();
476 14           bag_hv = newHV();
477             }
478              
479 44           p7 = sk_PKCS7_value(asafes, i);
480              
481 44           bagnid = OBJ_obj2nid(p7->type);
482              
483 44 100         if (bagnid == NID_pkcs7_data) {
484              
485 24 100         if (options & INFO) {
486 16 100         if (orig_hash) {
487 8           bag_hv = newHV();
488 8           av_push(pkcs7_bags_av, newRV_inc((SV *) bag_hv));
489             }
490             else
491 8           BIO_printf(bio, "PKCS7 Data\n");
492             }
493 24           bags = PKCS12_unpack_p7data(p7);
494              
495 20 50         } else if (bagnid == NID_pkcs7_encrypted) {
496 20 100         if (options & INFO) {
497 12 100         if (orig_hash) {
498 6           bag_hv = newHV();
499              
500 6 50         if (p7->d.encrypted != NULL)
501 6           alg_print(aTHX_ bio, p7->d.encrypted->enc_data->algorithm, parameters_hv);
502 6 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 6 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 6           av_push(pkcs7_enc_bags_av, newRV_inc((SV *) bag_hv));
507             } else {
508 6           BIO_printf(bio, "PKCS7 Encrypted data: ");
509 6 50         if (p7->d.encrypted == NULL) {
510 0           BIO_printf(bio, "\n");
511             } else {
512 6           alg_print(aTHX_ bio, p7->d.encrypted->enc_data->algorithm, NULL);
513             }
514             }
515             }
516 20           bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
517              
518             } else {
519 0           continue;
520             }
521              
522 44 50         if (bags == NULL) return 0;
523              
524 44 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 44 100         if (orig_hash) {
530 14 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 14 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 44           sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
536             }
537              
538 24           sk_PKCS7_pop_free(asafes, PKCS7_free);
539              
540 24           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 56           unsigned long get_nameopt(void)
570             {
571             return
572 56 50         nmflag_set ? nmflag : ESC_FLAGS | XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT | XN_FLAG_SPC_EQ;
573             }
574              
575 56           void print_name(BIO *out, const char *title, CONST_X509_NAME *nm)
576             {
577             char *buf;
578 56           char mline = 0;
579 56           int indent = 0;
580 56           unsigned long lflags = get_nameopt();
581              
582 56 50         if (out == NULL)
583 0           return;
584 56 50         if (title != NULL)
585 56           BIO_puts(out, title);
586 56 50         if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
587 0           mline = 1;
588 0           indent = 4;
589             }
590 56 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 56 50         if (mline)
597 0           BIO_puts(out, "\n");
598 56           X509_NAME_print_ex(out, nm, indent, lflags);
599              
600 56           BIO_puts(out, "\n");
601             }
602             }
603              
604 14           void dump_cert_text(BIO *out, X509 *x)
605             {
606 14           print_name(out, "subject=", X509_get_subject_name(x));
607 14           print_name(out, "issuer=", X509_get_issuer_name(x));
608 14           }
609              
610 14           SV * get_cert_subject_name(pTHX_ X509 *x)
611             {
612             BIO *bio;
613 14 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
614              
615 14           print_name(bio, "", X509_get_subject_name(x));
616 14           SV *sv = extractBioString(aTHX_ bio);
617 14           return sv;
618             }
619              
620 14           SV * get_cert_issuer_name(pTHX_ X509 *x)
621             {
622             BIO *bio;
623 14 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
624              
625 14           print_name(bio, "", X509_get_issuer_name(x));
626 14           SV *sv = extractBioString(aTHX_ bio);
627 14           return sv;
628             }
629              
630 15           void get_hex(char *out, unsigned char *buf, int len)
631             {
632             int i;
633 209 100         for (i = 0; i < len; i++) {
634 194 100         if (i == (len-1))
635 15           out += sprintf(out, "%02X", buf[i]);
636             else
637 179           out += sprintf(out, "%02X ", buf[i]);
638             }
639 15           }
640              
641 15           void hex_prin(BIO *out, unsigned char *buf, int len)
642             {
643             int i;
644 209 100         for (i = 0; i < len; i++)
645 194           BIO_printf(out, "%02X ", buf[i]);
646 15           }
647              
648             /* Generalised x509 attribute value print */
649              
650 50           void print_attribute(pTHX_ BIO *out, CONST_ASN1_TYPE *av, char **attribute)
651             {
652             char *value;
653             /*
654             const char *ln;
655             char objbuf[80];
656             */
657 50           switch (av->type) {
658 16           case V_ASN1_BMPSTRING:
659 16           value = OPENSSL_uni2asc(av->value.bmpstring->data,
660 16           av->value.bmpstring->length);
661 16 100         if(*attribute != NULL) {
662 8           Renew(*attribute, av->value.bmpstring->length, char);
663 8           strncpy(*attribute, value, av->value.bmpstring->length);
664             } else {
665 8           BIO_printf(out, "%s\n", value);
666 8           OPENSSL_free(value);
667             }
668 16           break;
669              
670 2           case V_ASN1_UTF8STRING:
671 2 100         if(*attribute != NULL) {
672 1           Renew(*attribute, av->value.utf8string->length, char);
673 1           strncpy(*attribute, (const char * ) av->value.utf8string->data, av->value.utf8string->length);
674             } else {
675 1           BIO_printf(out, "%.*s\n", av->value.utf8string->length,
676 1           av->value.utf8string->data);
677             }
678 2           break;
679              
680 28           case V_ASN1_OCTET_STRING:
681 28 100         if(*attribute != NULL) {
682 14           Renew(*attribute, av->value.octet_string->length * 4, char);
683 14           get_hex(*attribute, av->value.octet_string->data, av->value.octet_string->length);
684             } else {
685 14           hex_prin(out, av->value.octet_string->data,
686 14           av->value.octet_string->length);
687 14           BIO_printf(out, "\n");
688             }
689 28           break;
690              
691 2           case V_ASN1_BIT_STRING:
692 2 100         if(*attribute != NULL) {
693 1           Renew(*attribute, av->value.bit_string->length *4, char);
694 1           get_hex(*attribute, av->value.bit_string->data, av->value.bit_string->length);
695             } else {
696 1           hex_prin(out, av->value.bit_string->data,
697 1           av->value.bit_string->length);
698 1           BIO_printf(out, "\n");
699             }
700 2           break;
701              
702             /* case V_ASN1_OBJECT:
703             ln = OBJ_nid2ln(OBJ_obj2nid(av->value.object));
704             if (!ln)
705             ln = "";
706             OBJ_obj2txt(objbuf, sizeof(objbuf), av->value.object, 1);
707             if(*attribute != NULL) {
708             Renew(*attribute, strlen(ln), char);
709             strncpy(*attribute, ln, strlen(*attribute));
710             } else {
711             BIO_printf(out, "%s (%s)", ln, objbuf);
712             BIO_printf(out, "\n");
713             }
714             break;
715             */
716 2           default:
717 2 100         if(*attribute != NULL) {
718 1           Renew(*attribute, (strlen("") + sizeof(av->type)), char);
719 1           sprintf(*attribute, "\n", av->type);
720             }
721             else {
722 1           BIO_printf(out, "\n", av->type);
723             }
724 2           break;
725             }
726 50           }
727              
728             /* Generalised attribute print: handle PKCS#8 and bag attributes */
729 52           int print_attribs(pTHX_ BIO *out, CONST_STACK_OF(X509_ATTRIBUTE) *attrlst,
730             const char *name, HV * hash)
731             {
732             X509_ATTRIBUTE *attr;
733             ASN1_TYPE *av;
734             int i, j, attr_nid;
735 52           AV * bags_av = newAV();
736 52 100         if (!attrlst) {
737 22 100         if(hash) {
738             /* FIXME: May need to change attribute storage for empty attributes */
739             /*SV * value = newSVpvn("", strlen("")); */
740             /*if((hv_store(hash, "attributes", strlen("attributes"), newRV_inc((SV *) bags_av), 0)) == NULL) */
741             /* croak("unable to add attributes to the hash"); */
742             } else
743 11           BIO_printf(out, "%s: \n", name);
744 22           return 1;
745             }
746 30 50         if (!sk_X509_ATTRIBUTE_num(attrlst)) {
747 0 0         if(hash) {
748             /* FIXME: May need to change attribute storage for empty attributes */
749             /*if((hv_store(hash, "attributes", strlen("attributes"), newRV_inc((SV *) bags_av), 0)) == NULL) */
750             /* croak("unable to add attributes to the hash"); */
751             } else
752 0           BIO_printf(out, "%s: \n", name);
753 0           return 1;
754             }
755 30 100         if(!hash)
756 15           BIO_printf(out, "%s\n", name);
757              
758 30           HV * bag_hv = newHV();
759 78 100         for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
760             ASN1_OBJECT *attr_obj;
761 48           attr = sk_X509_ATTRIBUTE_value(attrlst, i);
762 48           attr_obj = X509_ATTRIBUTE_get0_object(attr);
763 48           attr_nid = OBJ_obj2nid(attr_obj);
764 48 100         if (!hash) {
765 24 100         if (attr_nid == NID_undef) {
766 2           BIO_printf(out, " ");
767 2           i2a_ASN1_OBJECT(out, attr_obj);
768 2           BIO_printf(out, ": ");
769             }
770             else {
771 22 50         if (!hash) {
772             /* Print the name of the attributes */
773 22           BIO_printf(out, " ");
774 22           BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
775             }
776             }
777             }
778              
779 48 50         if (X509_ATTRIBUTE_count(attr)) {
780 96 100         for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
781             {
782 48           av = X509_ATTRIBUTE_get0_type(attr, j);
783 48           char *attribute_value = NULL;
784 48 100         if(hash) {
785 24           const char *attribute_id = NULL;
786 24           Newx(attribute_value, 0, char);
787 24           print_attribute(aTHX_ out, av, &attribute_value);
788 24 100         if (attr_nid != NID_undef) {
789             /* Save the attribute name and value to the hash */
790 22           attribute_id = OBJ_nid2ln(attr_nid);
791 22 50         if (attribute_id) {
792 22 50         if((hv_store(bag_hv, attribute_id, strlen(attribute_id), newSVpvn(attribute_value, strlen(attribute_value)), 0)) == NULL)
793 0           croak("unable to add MAC to the hash");
794             }
795             } else {
796             BIO *attr_bio;
797             BUF_MEM* bptr;
798              
799 2 50         CHECK_OPEN_SSL(attr_bio = BIO_new(BIO_s_mem()));
800 2           i2a_ASN1_OBJECT(attr_bio, attr_obj);
801              
802 2 50         CHECK_OPEN_SSL(BIO_flush(attr_bio) == 1);
803 2           BIO_get_mem_ptr(attr_bio, &bptr);
804              
805 2 50         if (bptr->length > 0) {
806 2 50         if((hv_store(bag_hv, bptr->data, bptr->length, newSVpvn(attribute_value, strlen(attribute_value)), 0)) == NULL)
807 0           croak("unable to add MAC to the hash");
808             }
809              
810 2 50         CHECK_OPEN_SSL(BIO_set_close(attr_bio, BIO_CLOSE) == 1);
811 2           BIO_free(attr_bio);
812             }
813 24           Safefree(attribute_value);
814             } else {
815 24           print_attribute(aTHX_ out, av, &attribute_value);
816             }
817 48           av_push(bags_av, newRV_inc((SV *) bag_hv));
818             }
819             } else {
820 0           BIO_printf(out, "\n");
821             }
822             }
823 30 100         if (hash) {
824 15 50         if((hv_store(hash, name, strlen(name), newRV_inc((SV *) bag_hv), 0)) == NULL)
825 0           croak("unable to add bags to the hash");
826             }
827 30           return 1;
828             }
829              
830 20           static int alg_print(pTHX_ BIO *bio, CONST_X509_ALGOR *alg, HV * parameters_hash)
831             {
832             int pbenid, aparamtype;
833             CONST_ASN1_OBJECT *aoid;
834             CONST_VOID *aparam;
835 20           PBEPARAM *pbe = NULL;
836              
837 20           X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);
838 20           pbenid = OBJ_obj2nid(aoid);
839 20 100         if (parameters_hash) {
840 10           SV * nid_long_name = newSVpvn(OBJ_nid2ln(pbenid), strlen(OBJ_nid2ln(pbenid)));
841 10 50         if((hv_store(parameters_hash, "nid_long_name", strlen("nid_long_name"), nid_long_name, 0)) == NULL)
842 0           croak("unable to add MAC to the parameters_hash");
843 10           SV * nid_short_name = newSVpvn(OBJ_nid2sn(pbenid), strlen(OBJ_nid2sn(pbenid)));
844 10 50         if((hv_store(parameters_hash, "nid_short_name", strlen("nid_short_name"), nid_short_name, 0)) == NULL)
845 0           croak("unable to add MAC to the parameters_hash");
846             } else {
847 10           BIO_printf(bio, "%s", OBJ_nid2ln(pbenid));
848             }
849             /*
850             * If PBE algorithm is PBES2 decode algorithm parameters
851             * for additional details.
852             */
853 20 100         if (pbenid == NID_pbes2) {
854 10           PBE2PARAM *pbe2 = NULL;
855             int encnid;
856 10 50         if (aparamtype == V_ASN1_SEQUENCE)
857 10           pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
858 10 50         if (pbe2 == NULL) {
859 0           BIO_puts(bio, ", ");
860 0           goto done;
861             }
862 10           X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
863 10           pbenid = OBJ_obj2nid(aoid);
864              
865 10           X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
866 10           encnid = OBJ_obj2nid(aoid);
867 10 100         if (parameters_hash) {
868 5           SV * nid_long_name = newSVpvn(OBJ_nid2ln(pbenid), strlen(OBJ_nid2ln(pbenid)));
869 5 50         if((hv_store(parameters_hash, "nid_long_name", strlen("nid_long_name"), nid_long_name, 0)) == NULL)
870 0           croak("unable to add MAC to the parameters_hash");
871 5           SV * nid_short_name = newSVpvn(OBJ_nid2sn(pbenid), strlen(OBJ_nid2sn(pbenid)));
872 5 50         if((hv_store(parameters_hash, "nid_short_name", strlen("nid_short_name"), nid_short_name, 0)) == NULL)
873 0           croak("unable to add MAC to the parameters_hash");
874             } else
875 5           BIO_printf(bio, ", %s, %s", OBJ_nid2ln(pbenid),
876             OBJ_nid2sn(encnid));
877             /* If KDF is PBKDF2 decode parameters */
878 10 50         if (pbenid == NID_id_pbkdf2) {
879 10           PBKDF2PARAM *kdf = NULL;
880             int prfnid;
881 10 50         if (aparamtype == V_ASN1_SEQUENCE)
882 10           kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
883 10 50         if (kdf == NULL) {
884 0           BIO_puts(bio, ", ");
885 0           goto done;
886             }
887              
888 10 50         if (kdf->prf == NULL) {
889 0           prfnid = NID_hmacWithSHA1;
890             } else {
891 10           X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
892 10           prfnid = OBJ_obj2nid(aoid);
893             }
894 10 100         if (parameters_hash) {
895 5           SV * iteration = newSViv(ASN1_INTEGER_get(kdf->iter));
896 5 50         if((hv_store(parameters_hash, "iteration", strlen("iteration"), iteration, 0)) == NULL)
897 0           croak("unable to add iteration to the parameters_hash");
898             } else
899 10           BIO_printf(bio, ", Iteration %ld, PRF %s",
900 5           ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
901 10           PBKDF2PARAM_free(kdf);
902             #if OPENSSL_VERSION_NUMBER > 0x10100000L
903             #ifndef LIBRESSL_VERSION_NUMBER
904             #ifndef OPENSSL_NO_SCRYPT
905 0 0         } else if (pbenid == NID_id_scrypt) {
906 0           SCRYPT_PARAMS *kdf = NULL;
907              
908 0 0         if (aparamtype == V_ASN1_SEQUENCE)
909 0           kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
910 0 0         if (kdf == NULL) {
911 0           BIO_puts(bio, ", ");
912 0           goto done;
913             }
914 0 0         if (parameters_hash) {
915 0 0         if((hv_store(parameters_hash, "salt_length", strlen("salt_length"), newSViv(ASN1_STRING_length(kdf->salt)), 0)) == NULL)
916 0           croak("unable to add salt_length to the parameters_hash");
917 0 0         if((hv_store(parameters_hash, "cost", strlen("cost"), newSViv(ASN1_INTEGER_get(kdf->costParameter)), 0)) == NULL)
918 0           croak("unable to add cost to the parameters_hash");
919 0 0         if((hv_store(parameters_hash, "block_size", strlen("block_size"), newSViv(ASN1_INTEGER_get(kdf->blockSize)), 0)) == NULL)
920 0           croak("unable to add block_size to the parameters_hash");
921 0 0         if((hv_store(parameters_hash, "parallelism", strlen("parallelism"), newSViv(ASN1_INTEGER_get(kdf->parallelizationParameter)), 0)) == NULL)
922 0           croak("unable to add parallelism to the parameters_hash");
923             } else
924 0           BIO_printf(bio, ", Salt length: %d, Cost(N): %ld, "
925             "Block size(r): %ld, Parallelism(p): %ld",
926 0           ASN1_STRING_length(kdf->salt),
927 0           ASN1_INTEGER_get(kdf->costParameter),
928 0           ASN1_INTEGER_get(kdf->blockSize),
929 0           ASN1_INTEGER_get(kdf->parallelizationParameter));
930 0           SCRYPT_PARAMS_free(kdf);
931             #endif
932             #endif
933             #endif
934             }
935 10           PBE2PARAM_free(pbe2);
936             } else {
937 10 50         if (aparamtype == V_ASN1_SEQUENCE)
938 10           pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
939 10 50         if (pbe == NULL) {
940 0           BIO_puts(bio, ", ");
941 0           goto done;
942             }
943 10 100         if (parameters_hash) {
944 5           long int val = ASN1_INTEGER_get(pbe->iter);
945 5           SV * iteration = newSViv(val);
946 5 50         if((hv_store(parameters_hash, "iteration", strlen("iteration"), iteration, 0)) == NULL)
947 0           croak("unable to add MAC to the parameters_hash");
948             } else
949 5           BIO_printf(bio, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
950 10           PBEPARAM_free(pbe);
951             }
952 20           done:
953 20 100         if(!parameters_hash)
954 10           BIO_puts(bio, "\n");
955 20           return 1;
956             }
957              
958             MODULE = Crypt::OpenSSL::PKCS12 PACKAGE = Crypt::OpenSSL::PKCS12
959              
960             PROTOTYPES: DISABLE
961              
962             BOOT:
963             {
964             HV *stash;
965             char *name;
966             int i;
967              
968 13           struct { char *n; I32 v; } Crypt__OpenSSL__PKCS12__const[] = {
969             {"NOKEYS", NOKEYS},
970             {"NOCERTS", NOCERTS},
971             {"INFO", INFO},
972             {"CLCERTS", CLCERTS},
973             {"CACERTS", CACERTS},
974             {Nullch,0}
975             };
976              
977 13           OpenSSL_add_all_algorithms();
978              
979 13           stash = gv_stashpvn("Crypt::OpenSSL::PKCS12", 22, TRUE);
980              
981 78 100         for (i = 0; (name = Crypt__OpenSSL__PKCS12__const[i].n); i++) {
982 65           newCONSTSUB(stash, name, newSViv(Crypt__OpenSSL__PKCS12__const[i].v));
983             }
984             }
985              
986             Crypt::OpenSSL::PKCS12
987             new(class)
988             SV *class
989              
990             CODE:
991              
992 0 0         if ((RETVAL = PKCS12_new()) == NULL) {
993 0           croak("Couldn't create PKCS12_new() for class %" SVf "\n", SVfARG(class));
994             }
995              
996             OUTPUT:
997             RETVAL
998              
999             IV legacy_support(class)
1000             SV *class;
1001              
1002             CODE:
1003 1           RETVAL = 1;
1004             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1005 1 50         if (legacy)
1006 1           RETVAL = 1;
1007             else
1008 0           RETVAL = 0;
1009             #endif
1010             OUTPUT:
1011             RETVAL
1012              
1013             Crypt::OpenSSL::PKCS12
1014             new_from_string(class, string)
1015             SV *class
1016             SV *string
1017              
1018             ALIAS:
1019             new_from_file = 1
1020              
1021             PREINIT:
1022             BIO *bio;
1023             STRLEN str_len;
1024             char *str_ptr;
1025             CODE:
1026              
1027 33 50         SvGETMAGIC(string);
    0          
1028             #if OPENSSL_VERSION_NUMBER >= 0x30000000L
1029             /* FIXME: There should likely be an option for whether to load the legacy provider */
1030 33           legacy = OSSL_PROVIDER_load(NULL, "legacy");
1031 33 50         if (legacy == NULL) {
1032 0           warn("Failed to load Legacy provider\n");
1033             }
1034 33           deflt = OSSL_PROVIDER_load(NULL, "default");
1035 33 50         if (deflt == NULL) {
1036 0           OSSL_PROVIDER_unload(legacy);
1037 0           croak("Failed to load Default provider\n");
1038             }
1039             #endif
1040              
1041 33 100         if (SvPOKp(string) || SvNOKp(string) || SvIOKp(string)) {
    100          
    100          
1042 25 100         if (ix == 1) {
1043             /* We are not looking up the SV's UTF8 bit because BIO_new_file() accepts
1044             * filename like syscall fopen() which mainly may accept octet sequences
1045             * for UTF-8 in C char*. That's what we get from using SvPV(). Also,
1046             * using SvPV() is not a bug if ASCII input is only allowed. */
1047 12           str_ptr = SvPV(string, str_len);
1048             } else {
1049             /* To avoid encoding mess, caller is not allowed to provide octets from
1050             * UTF-8 encoded strings. BIO_new_mem_buf() needs octet input only. */
1051 13 100         if (SvUTF8(string)) {
1052 4           croak("PKCS12_new_from: Source string must not be UTF-8 encoded (please use octets)");
1053             }
1054 9           str_ptr = SvPV(string, str_len);
1055             }
1056             } else {
1057 8           croak("PKCS12_new_from: Invalid Perl type for string or file was passed (0x%x).", (unsigned int)SvFLAGS(string));
1058             }
1059              
1060 21 50         if (!str_ptr || !str_len) croak("PKCS12_new_from: No string or file was passed.");
    50          
1061              
1062 21 100         if (ix == 1) {
1063 12           bio = BIO_new_file(str_ptr, "rb");
1064             } else {
1065 9           bio = BIO_new_mem_buf(str_ptr, str_len);
1066             }
1067              
1068 21 50         if (!bio) croak("Failed to create BIO");
1069              
1070             /* this can come in any number of ways */
1071 21 100         if ((RETVAL = d2i_PKCS12_bio(bio, 0)) == NULL) {
1072 6           BIO_free_all(bio);
1073 6           croak("%" SVf ": Couldn't create PKCS12 from d2i_PKCS12_BIO(): %s", SVfARG(class), ssl_error(aTHX));
1074             }
1075              
1076 15           BIO_free_all(bio);
1077              
1078             OUTPUT:
1079             RETVAL
1080              
1081             # This is called at per-object destruction time.
1082             void
1083             DESTROY(pkcs12)
1084             Crypt::OpenSSL::PKCS12 pkcs12;
1085              
1086             CODE:
1087 15 50         if (pkcs12) {
1088 15           PKCS12_free(pkcs12);
1089             }
1090              
1091             # This is called via an END block in the Perl module to clean up initialization that happened in BOOT.
1092             void
1093             __PKCS12_cleanup(void)
1094             CODE:
1095              
1096 13           CRYPTO_cleanup_all_ex_data();
1097 13           ERR_free_strings();
1098             #if OPENSSL_VERSION_NUMBER < 0x10100000L
1099             ERR_remove_state(0);
1100             #endif
1101 13           EVP_cleanup();
1102              
1103             SV*
1104             as_string(pkcs12)
1105             Crypt::OpenSSL::PKCS12 pkcs12;
1106              
1107             PREINIT:
1108             BIO *bio;
1109              
1110             CODE:
1111              
1112 3 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1113              
1114 3 50         if (!(i2d_PKCS12_bio(bio, pkcs12))) {
1115 0           sv_bio_error(aTHX_ bio);
1116 0           croak("i2d_PKCS12_bio: %s", ssl_error(aTHX));
1117             }
1118              
1119 3           RETVAL = extractBioString(aTHX_ bio);
1120              
1121             OUTPUT:
1122             RETVAL
1123              
1124             SV*
1125             mac_ok(pkcs12, pwd = "")
1126             Crypt::OpenSSL::PKCS12 pkcs12
1127             char *pwd
1128              
1129             CODE:
1130              
1131 7 50         if (!(PKCS12_verify_mac(pkcs12, pwd, strlen(pwd)))) {
1132 0           croak("PKCS12_verify_mac: \n%s", ssl_error(aTHX));
1133             }
1134              
1135 7 50         RETVAL = (PKCS12_verify_mac(pkcs12, pwd, strlen(pwd))) ? &PL_sv_yes : &PL_sv_no;
1136              
1137             OUTPUT:
1138             RETVAL
1139              
1140             SV*
1141             changepass(pkcs12, oldpwd = "", newpwd = "")
1142             Crypt::OpenSSL::PKCS12 pkcs12
1143             char *oldpwd
1144             char *newpwd
1145              
1146             CODE:
1147              
1148 0 0         if (!(PKCS12_newpass(pkcs12, oldpwd, newpwd))) {
1149 0           warn("PKCS12_newpass: %s %s\n%s", oldpwd, newpwd, ssl_error(aTHX));
1150 0           RETVAL = &PL_sv_no;
1151             } else {
1152 0           RETVAL = &PL_sv_yes;
1153             }
1154              
1155             OUTPUT:
1156             RETVAL
1157              
1158             SV*
1159             create(pkcs12, cert_chain_pem = "", pk = "", pass = 0, file = 0, name = "PKCS12 Certificate")
1160             char *cert_chain_pem
1161             char *pk
1162             char *pass
1163             char *file
1164             char *name
1165              
1166             PREINIT:
1167             FILE *fp;
1168             EVP_PKEY* pkey;
1169             PKCS12 *p12;
1170 3 50         STACK_OF(X509) *cert_chain = NULL;
1171              
1172             CODE:
1173              
1174 3           pkey = _load_pkey(pk, PEM_read_bio_PrivateKey);
1175 3           cert_chain = _load_cert_chain(cert_chain_pem, PEM_X509_INFO_read_bio);
1176 3           p12 = PKCS12_create(pass, name, pkey, sk_X509_shift(cert_chain), cert_chain, 0, 0, 0, 0, 0);
1177              
1178 3 50         if (!p12) {
1179 0           ERR_print_errors_fp(stderr);
1180 0           croak("Error creating PKCS#12 structure\n");
1181             }
1182              
1183 3 50         if (!(fp = fopen(file, "wb"))) {
1184 0           ERR_print_errors_fp(stderr);
1185 0           croak("Error opening file %s\n", file);
1186             }
1187              
1188 3           i2d_PKCS12_fp(fp, p12);
1189 3           PKCS12_free(p12);
1190 3           fclose(fp);
1191              
1192 3           RETVAL = &PL_sv_yes;
1193              
1194             OUTPUT:
1195             RETVAL
1196              
1197              
1198             SV*
1199             create_as_string(pkcs12, cert_chain_pem = "", pk = "", pass = 0, name = "PKCS12 Certificate")
1200             char *cert_chain_pem
1201             char *pk
1202             char *pass
1203             char *name
1204              
1205             PREINIT:
1206             BIO *bio;
1207             EVP_PKEY* pkey;
1208             PKCS12 *p12;
1209 1 50         STACK_OF(X509) *cert_chain = NULL;
1210              
1211             CODE:
1212              
1213 1           pkey = _load_pkey(pk, PEM_read_bio_PrivateKey);
1214 1           cert_chain = _load_cert_chain(cert_chain_pem, PEM_X509_INFO_read_bio);
1215 1           p12 = PKCS12_create(pass, name, pkey, sk_X509_shift(cert_chain), cert_chain, 0, 0, 0, 0, 0);
1216              
1217 1 50         if (!p12) {
1218 0           ERR_print_errors_fp(stderr);
1219 0           croak("Error creating PKCS#12 structure\n");
1220             }
1221              
1222 1 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1223 1           i2d_PKCS12_bio(bio, p12);
1224              
1225 1           RETVAL = extractBioString(aTHX_ bio);
1226 1           PKCS12_free(p12);
1227              
1228             OUTPUT:
1229             RETVAL
1230              
1231             SV*
1232             certificate(pkcs12, pwd = "")
1233             Crypt::OpenSSL::PKCS12 pkcs12
1234             char *pwd
1235              
1236             PREINIT:
1237             BIO *bio;
1238 4 50         STACK_OF(PKCS7) *asafes = NULL;
1239              
1240             CODE:
1241              
1242 4 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1243              
1244 4 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1245 0           RETVAL = newSVpvn("",0);
1246              
1247 4           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd, strlen(pwd), CLCERTS|NOKEYS, NULL, NULL);
1248              
1249 4           RETVAL = extractBioString(aTHX_ bio);
1250              
1251             OUTPUT:
1252             RETVAL
1253              
1254             SV*
1255             ca_certificate(pkcs12, pwd = "")
1256             Crypt::OpenSSL::PKCS12 pkcs12
1257             char *pwd
1258              
1259             PREINIT:
1260             BIO *bio;
1261 1 50         STACK_OF(PKCS7) *asafes = NULL;
1262              
1263             CODE:
1264              
1265 1 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1266              
1267 1 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1268 0           RETVAL = newSVpvn("",0);
1269              
1270 1           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd, strlen(pwd), CACERTS|NOKEYS, NULL, NULL);
1271              
1272 1           RETVAL = extractBioString(aTHX_ bio);
1273              
1274             OUTPUT:
1275             RETVAL
1276              
1277             SV*
1278             private_key(pkcs12, pwd = "")
1279             Crypt::OpenSSL::PKCS12 pkcs12
1280             char *pwd
1281              
1282             PREINIT:
1283             BIO *bio;
1284              
1285             CODE:
1286              
1287 3 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1288              
1289 3           PKCS12_unpack_authsafes(pkcs12);
1290              
1291 3           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd, strlen(pwd), NOCERTS, NULL, NULL);
1292              
1293 3           RETVAL = extractBioString(aTHX_ bio);
1294              
1295             OUTPUT:
1296             RETVAL
1297              
1298             HV* info_as_hash(pkcs12, pwd = "")
1299             Crypt::OpenSSL::PKCS12 pkcs12
1300             char *pwd
1301              
1302             PREINIT:
1303             BIO *bio;
1304 8 50         STACK_OF(PKCS7) *asafes = NULL;
1305              
1306             CONST_ASN1_INTEGER *tmaciter;
1307             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1308             SV *value;
1309             CONST_X509_ALGOR *macalgid;
1310             CONST_ASN1_OBJECT *macobj;
1311             CONST_ASN1_OCTET_STRING *tmac;
1312             CONST_ASN1_OCTET_STRING *tsalt;
1313             #endif
1314              
1315             CODE:
1316 8           RETVAL = newHV();
1317              
1318 8 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1319              
1320 8 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1321 0           RETVAL = newHV();
1322 8           HV * mac = newHV();
1323             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1324 8           PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, pkcs12);
1325             /* current hash algorithms do not use parameters so extract just name,
1326             in future alg_print() may be needed */
1327 8           X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
1328 8           i2a_ASN1_OBJECT(bio, macobj);
1329 8           value = extractBioString(aTHX_ bio);
1330 8 50         if((hv_store(mac, "digest", strlen("digest"), value, 0)) == NULL)
1331 0           croak("unable to add digest to the hash");
1332             #else
1333             tmaciter = pkcs12->mac->iter;
1334             #endif
1335 8 50         SV * mac_iteration = newSViv (tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
1336              
1337 8 50         if((hv_store(mac, "iteration", strlen("iteration"), mac_iteration, 0)) == NULL)
1338 0           croak("unable to add iteration to the hash");
1339 8 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1340             /* BIO_printf(bio, "MAC length: %ld, salt length: %ld", */
1341             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1342 8 50         SV * mac_len = newSViv(tmac != NULL ? ASN1_STRING_length(tmac) : 0L);
1343 8 50         SV * salt_len = newSViv(tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
1344              
1345 8 50         if((hv_store(mac, "length", 6, mac_len, 0)) == NULL)
1346 0           croak("unable to add length to the hash");
1347             #else
1348             SV * salt_len = newSViv((pkcs12)->mac ? pkcs12->mac->salt->length : 0L);
1349             #endif
1350              
1351 8 50         if((hv_store(mac, "salt_length", strlen("salt_length"), INT2PTR(SV*, salt_len), 0)) == NULL)
1352 0           croak("unable to add salt_length to the hash");
1353              
1354 8 50         if((hv_store(RETVAL, "mac", strlen("mac"), newRV_inc((SV *) mac), 0)) == NULL)
1355 0           croak("unable to add MAC to the hash");
1356 8           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd, strlen(pwd), INFO, NULL, RETVAL);
1357              
1358 8           SV * end = extractBioString(aTHX_ bio);
1359              
1360 8 50         if (SvPOK(end)) {
1361 0 0         if (SvCUR(end) != 0)
1362 0           printf("BIO %s\n", SvPVbyte_nolen(end));
1363 0           warn("bio from info_as_hash should be zero length - report issue");
1364             }
1365              
1366 8           sv_2mortal((SV*)RETVAL);
1367              
1368             OUTPUT:
1369             RETVAL
1370              
1371             SV*
1372             info(pkcs12, pwd = "")
1373             Crypt::OpenSSL::PKCS12 pkcs12
1374             char *pwd
1375              
1376             PREINIT:
1377             BIO *bio;
1378 8 50         STACK_OF(PKCS7) *asafes = NULL;
1379              
1380             CONST_ASN1_INTEGER *tmaciter;
1381             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1382             CONST_X509_ALGOR *macalgid;
1383             CONST_ASN1_OBJECT *macobj;
1384             CONST_ASN1_OCTET_STRING *tmac;
1385             CONST_ASN1_OCTET_STRING *tsalt;
1386             #endif
1387             CODE:
1388              
1389 8 50         CHECK_OPEN_SSL(bio = BIO_new(BIO_s_mem()));
1390              
1391 8 50         if ((asafes = PKCS12_unpack_authsafes(pkcs12)) == NULL)
1392 0           RETVAL = newSVpvn("",0);
1393             #if OPENSSL_VERSION_NUMBER > 0x10100000L
1394 8           PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, pkcs12);
1395             /* current hash algorithms do not use parameters so extract just name,
1396             in future alg_print() may be needed */
1397 8           X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
1398 8           BIO_puts(bio, "MAC: ");
1399 8           i2a_ASN1_OBJECT(bio, macobj);
1400             /* current hash algorithms do not use parameters so extract just name,
1401             in future alg_print() may be needed */
1402 8           BIO_printf(bio, ", Iteration %ld\n",
1403 8 50         tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
1404 16           BIO_printf(bio, "MAC length: %ld, salt length: %ld\n",
1405 8 50         tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
1406 8 50         tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
1407             #else
1408             tmaciter = pkcs12->mac->iter;
1409             BIO_printf(bio, "MAC Iteration %ld\n",
1410             tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
1411             /* If we enter empty password try no password first */
1412             if (!PKCS12_verify_mac(pkcs12, pwd, -1)) {
1413             BIO_printf(bio, "Mac verify error: invalid password?\n");
1414             ERR_print_errors(bio);
1415             goto end;
1416             }
1417             BIO_printf(bio, "MAC verified OK\n");
1418             end:
1419             #endif
1420 8           dump_certs_keys_p12(aTHX_ bio, pkcs12, pwd, strlen(pwd), INFO, NULL, NULL);
1421              
1422 8           RETVAL = extractBioString(aTHX_ bio);
1423              
1424             OUTPUT:
1425             RETVAL