File Coverage

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