]>
git.ipfire.org Git - thirdparty/openssl.git/blob - test/helpers/pkcs12.c
2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
14 #include "internal/nelem.h"
16 #include <openssl/pkcs12.h>
17 #include <openssl/x509.h>
18 #include <openssl/x509v3.h>
19 #include <openssl/pem.h>
21 #include "../testutil.h"
22 #include "pkcs12.h" /* from the same directory */
24 /* Set this to > 0 write test data to file */
25 static int write_files
= 0;
27 static int legacy
= 0;
29 static OSSL_LIB_CTX
*test_ctx
= NULL
;
30 static const char *test_propq
= NULL
;
32 /* -------------------------------------------------------------------------
33 * Local function declarations
36 static int add_attributes(PKCS12_SAFEBAG
*bag
, const PKCS12_ATTR
*attrs
);
38 static void generate_p12(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
);
39 static int write_p12(PKCS12
*p12
, const char *outfile
);
41 static PKCS12
*from_bio_p12(BIO
*bio
, const PKCS12_ENC
*mac
);
42 static PKCS12
*read_p12(const char *infile
, const PKCS12_ENC
*mac
);
43 static int check_p12_mac(PKCS12
*p12
, const PKCS12_ENC
*mac
);
44 static int check_asn1_string(const ASN1_TYPE
*av
, const char *txt
);
45 static int check_attrs(const STACK_OF(X509_ATTRIBUTE
) *bag_attrs
, const PKCS12_ATTR
*attrs
);
48 /* --------------------------------------------------------------------------
52 void PKCS12_helper_set_write_files(int enable
)
57 void PKCS12_helper_set_legacy(int enable
)
62 void PKCS12_helper_set_libctx(OSSL_LIB_CTX
*libctx
)
67 void PKCS12_helper_set_propq(const char *propq
)
73 /* --------------------------------------------------------------------------
74 * Test data load functions
77 static X509
*load_cert_asn1(const unsigned char *bytes
, int len
)
81 cert
= d2i_X509(NULL
, &bytes
, len
);
88 static EVP_PKEY
*load_pkey_asn1(const unsigned char *bytes
, int len
)
90 EVP_PKEY
*pkey
= NULL
;
92 pkey
= d2i_AutoPrivateKey(NULL
, &bytes
, len
);
99 /* -------------------------------------------------------------------------
103 PKCS12_BUILDER
*new_pkcs12_builder(const char *filename
)
105 PKCS12_BUILDER
*pb
= OPENSSL_malloc(sizeof(PKCS12_BUILDER
));
109 pb
->filename
= filename
;
114 int end_pkcs12_builder(PKCS12_BUILDER
*pb
)
116 int result
= pb
->success
;
123 void start_pkcs12(PKCS12_BUILDER
*pb
)
129 void end_pkcs12(PKCS12_BUILDER
*pb
)
133 generate_p12(pb
, NULL
);
137 void end_pkcs12_with_mac(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
141 generate_p12(pb
, mac
);
145 /* Generate the PKCS12 encoding and write to memory bio */
146 static void generate_p12(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
154 pb
->p12bio
= BIO_new(BIO_s_mem());
155 if (!TEST_ptr(pb
->p12bio
)) {
160 p12
= PKCS12_add_safes(pb
->safes
, 0);
162 p12
= PKCS12_add_safes_ex(pb
->safes
, 0, test_ctx
, test_propq
);
163 if (!TEST_ptr(p12
)) {
167 sk_PKCS7_pop_free(pb
->safes
, PKCS7_free
);
171 md
= (EVP_MD
*)EVP_get_digestbynid(mac
->nid
);
173 md
= EVP_MD_fetch(test_ctx
, OBJ_nid2sn(mac
->nid
), test_propq
);
175 if (!TEST_true(PKCS12_set_mac(p12
, mac
->pass
, strlen(mac
->pass
),
176 NULL
, 0, mac
->iter
, md
))) {
181 i2d_PKCS12_bio(pb
->p12bio
, p12
);
183 /* Can write to file here for debug */
185 write_p12(p12
, pb
->filename
);
187 if (!legacy
&& md
!= NULL
)
193 static int write_p12(PKCS12
*p12
, const char *outfile
)
196 BIO
*out
= BIO_new_file(outfile
, "w");
201 if (!TEST_int_eq(i2d_PKCS12_bio(out
, p12
), 1))
209 static PKCS12
*from_bio_p12(BIO
*bio
, const PKCS12_ENC
*mac
)
213 /* Supply a p12 with library context/propq to the d2i decoder*/
215 p12
= PKCS12_init_ex(NID_pkcs7_data
, test_ctx
, test_propq
);
219 p12
= d2i_PKCS12_bio(bio
, &p12
);
224 if (!TEST_false(PKCS12_mac_present(p12
)))
227 if (!check_p12_mac(p12
, mac
))
237 /* For use with existing files */
238 static PKCS12
*read_p12(const char *infile
, const PKCS12_ENC
*mac
)
241 BIO
*in
= BIO_new_file(infile
, "r");
245 p12
= d2i_PKCS12_bio(in
, NULL
);
250 if (!TEST_false(PKCS12_mac_present(p12
)))
253 if (!check_p12_mac(p12
, mac
))
262 static int check_p12_mac(PKCS12
*p12
, const PKCS12_ENC
*mac
)
264 return TEST_true(PKCS12_mac_present(p12
))
265 && TEST_true(PKCS12_verify_mac(p12
, mac
->pass
, strlen(mac
->pass
)));
269 /* -------------------------------------------------------------------------
270 * PKCS7 content info builder
273 void start_contentinfo(PKCS12_BUILDER
*pb
)
279 void end_contentinfo(PKCS12_BUILDER
*pb
)
281 if (pb
->success
&& pb
->bags
!= NULL
) {
282 if (!TEST_true(PKCS12_add_safe(&pb
->safes
, pb
->bags
, -1, 0, NULL
)))
285 sk_PKCS12_SAFEBAG_pop_free(pb
->bags
, PKCS12_SAFEBAG_free
);
290 void end_contentinfo_encrypted(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*enc
)
292 if (pb
->success
&& pb
->bags
!= NULL
) {
294 if (!TEST_true(PKCS12_add_safe(&pb
->safes
, pb
->bags
, enc
->nid
,
295 enc
->iter
, enc
->pass
)))
298 if (!TEST_true(PKCS12_add_safe_ex(&pb
->safes
, pb
->bags
, enc
->nid
,
299 enc
->iter
, enc
->pass
, test_ctx
,
304 sk_PKCS12_SAFEBAG_pop_free(pb
->bags
, PKCS12_SAFEBAG_free
);
309 static STACK_OF(PKCS12_SAFEBAG
) *decode_contentinfo(STACK_OF(PKCS7
) *safes
, int idx
, const PKCS12_ENC
*enc
)
311 STACK_OF(PKCS12_SAFEBAG
) *bags
= NULL
;
313 PKCS7
*p7
= sk_PKCS7_value(safes
, idx
);
318 bagnid
= OBJ_obj2nid(p7
->type
);
320 if (!TEST_int_eq(bagnid
, NID_pkcs7_encrypted
))
322 /* TODO: Check algorithm (iterations?) against what we originally set */
323 bags
= PKCS12_unpack_p7encdata(p7
, enc
->pass
, strlen(enc
->pass
));
325 if (!TEST_int_eq(bagnid
, NID_pkcs7_data
))
327 bags
= PKCS12_unpack_p7data(p7
);
338 /* -------------------------------------------------------------------------
339 * PKCS12 safeBag/attribute builder
342 static int add_attributes(PKCS12_SAFEBAG
*bag
, const PKCS12_ATTR
*attrs
)
346 const PKCS12_ATTR
*p_attr
= attrs
;
351 while (p_attr
->oid
!= NULL
) {
352 TEST_info("Adding attribute %s = %s", p_attr
->oid
, p_attr
->value
);
353 attr_nid
= OBJ_txt2nid(p_attr
->oid
);
355 if (attr_nid
== NID_friendlyName
) {
356 if (!TEST_true(PKCS12_add_friendlyname(bag
, p_attr
->value
, -1)))
358 } else if (attr_nid
== NID_localKeyID
) {
359 if (!TEST_true(PKCS12_add_localkeyid(bag
, (unsigned char *)p_attr
->value
,
360 strlen(p_attr
->value
))))
363 /* Custom attribute values limited to ASCII in these tests */
364 if (!TEST_true(PKCS12_add1_attr_by_txt(bag
, p_attr
->oid
, MBSTRING_ASC
,
365 (unsigned char *)p_attr
->value
,
366 strlen(p_attr
->value
))))
376 void add_certbag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
377 const PKCS12_ATTR
*attrs
)
379 PKCS12_SAFEBAG
*bag
= NULL
;
386 cert
= load_cert_asn1(bytes
, len
);
387 if (!TEST_ptr(cert
)) {
392 name
= X509_NAME_oneline(X509_get_subject_name(cert
), NULL
, 0);
393 TEST_info("Adding certificate <%s>", name
);
396 bag
= PKCS12_add_cert(&pb
->bags
, cert
);
397 if (!TEST_ptr(bag
)) {
402 if (!TEST_true(add_attributes(bag
, attrs
))) {
410 void add_keybag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
411 const PKCS12_ATTR
*attrs
, const PKCS12_ENC
*enc
)
413 PKCS12_SAFEBAG
*bag
= NULL
;
414 EVP_PKEY
*pkey
= NULL
;
419 TEST_info("Adding key");
421 pkey
= load_pkey_asn1(bytes
, len
);
422 if (!TEST_ptr(pkey
)) {
428 bag
= PKCS12_add_key(&pb
->bags
, pkey
, 0 /*keytype*/, enc
->iter
, enc
->nid
, enc
->pass
);
430 bag
= PKCS12_add_key_ex(&pb
->bags
, pkey
, 0 /*keytype*/, enc
->iter
, enc
->nid
, enc
->pass
,
431 test_ctx
, test_propq
);
432 if (!TEST_ptr(bag
)) {
436 if (!add_attributes(bag
, attrs
))
442 void add_secretbag(PKCS12_BUILDER
*pb
, int secret_nid
, const char *secret
,
443 const PKCS12_ATTR
*attrs
)
445 PKCS12_SAFEBAG
*bag
= NULL
;
450 TEST_info("Adding secret <%s>", secret
);
452 bag
= PKCS12_add_secret(&pb
->bags
, secret_nid
, (const unsigned char *)secret
, strlen(secret
));
453 if (!TEST_ptr(bag
)) {
457 if (!add_attributes(bag
, attrs
))
462 /* -------------------------------------------------------------------------
463 * PKCS12 structure checking
466 static int check_asn1_string(const ASN1_TYPE
*av
, const char *txt
)
475 case V_ASN1_BMPSTRING
:
476 value
= OPENSSL_uni2asc(av
->value
.bmpstring
->data
,
477 av
->value
.bmpstring
->length
);
478 if (!TEST_str_eq(txt
, (char *)value
))
482 case V_ASN1_UTF8STRING
:
483 if (!TEST_str_eq(txt
, (char *)av
->value
.utf8string
->data
))
487 case V_ASN1_OCTET_STRING
:
488 if (!TEST_str_eq(txt
, (char *)av
->value
.octet_string
->data
))
493 /* Tests do not support other attribute types currently */
502 static int check_attrs(const STACK_OF(X509_ATTRIBUTE
) *bag_attrs
, const PKCS12_ATTR
*attrs
)
505 X509_ATTRIBUTE
*attr
;
510 for (i
= 0; i
< sk_X509_ATTRIBUTE_num(bag_attrs
); i
++) {
511 const PKCS12_ATTR
*p_attr
= attrs
;
512 ASN1_OBJECT
*attr_obj
;
514 attr
= sk_X509_ATTRIBUTE_value(bag_attrs
, i
);
515 attr_obj
= X509_ATTRIBUTE_get0_object(attr
);
516 OBJ_obj2txt(attr_txt
, 100, attr_obj
, 0);
518 while(p_attr
->oid
!= NULL
) {
519 /* Find a matching attribute type */
520 if (strcmp(p_attr
->oid
, attr_txt
) == 0) {
522 /* TODO: Handle multi-value attributes */
523 if (!TEST_int_eq(X509_ATTRIBUTE_count(attr
), 1))
526 for (j
= 0; j
< X509_ATTRIBUTE_count(attr
); j
++)
528 av
= X509_ATTRIBUTE_get0_type(attr
, j
);
529 if (!TEST_true(check_asn1_string(av
, p_attr
->value
)))
542 void check_certbag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
543 const PKCS12_ATTR
*attrs
)
546 X509
*ref_x509
= NULL
;
547 const PKCS12_SAFEBAG
*bag
;
552 bag
= sk_PKCS12_SAFEBAG_value(pb
->bags
, pb
->bag_idx
++);
553 if (!TEST_ptr(bag
)) {
557 if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag
), attrs
)
558 || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag
), NID_certBag
)
559 || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag
), NID_x509Certificate
)) {
563 x509
= PKCS12_SAFEBAG_get1_cert(bag
);
564 if (!TEST_ptr(x509
)) {
568 ref_x509
= load_cert_asn1(bytes
, len
);
569 if (!TEST_false(X509_cmp(x509
, ref_x509
)))
576 void check_keybag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
577 const PKCS12_ATTR
*attrs
, const PKCS12_ENC
*enc
)
579 EVP_PKEY
*pkey
= NULL
;
580 EVP_PKEY
*ref_pkey
= NULL
;
581 PKCS8_PRIV_KEY_INFO
*p8
;
582 const PKCS8_PRIV_KEY_INFO
*p8c
;
583 const PKCS12_SAFEBAG
*bag
;
588 bag
= sk_PKCS12_SAFEBAG_value(pb
->bags
, pb
->bag_idx
++);
589 if (!TEST_ptr(bag
)) {
594 if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag
), attrs
)) {
599 switch (PKCS12_SAFEBAG_get_nid(bag
)) {
601 p8c
= PKCS12_SAFEBAG_get0_p8inf(bag
);
602 if (!TEST_ptr(pkey
= EVP_PKCS82PKEY(p8c
))) {
606 /* TODO: handle key attributes */
607 /* PKCS8_pkey_get0_attrs(p8c); */
610 case NID_pkcs8ShroudedKeyBag
:
612 p8
= PKCS12_decrypt_skey(bag
, enc
->pass
, strlen(enc
->pass
));
614 p8
= PKCS12_decrypt_skey_ex(bag
, enc
->pass
, strlen(enc
->pass
), test_ctx
, test_propq
);
619 if (!TEST_ptr(pkey
= EVP_PKCS82PKEY(p8
))) {
620 PKCS8_PRIV_KEY_INFO_free(p8
);
624 /* TODO: handle key attributes */
625 /* PKCS8_pkey_get0_attrs(p8); */
626 PKCS8_PRIV_KEY_INFO_free(p8
);
634 /* PKEY compare returns 1 for match */
635 ref_pkey
= load_pkey_asn1(bytes
, len
);
636 if (!TEST_true(EVP_PKEY_eq(pkey
, ref_pkey
)))
640 EVP_PKEY_free(ref_pkey
);
643 void check_secretbag(PKCS12_BUILDER
*pb
, int secret_nid
, const char *secret
, const PKCS12_ATTR
*attrs
)
645 const PKCS12_SAFEBAG
*bag
;
650 bag
= sk_PKCS12_SAFEBAG_value(pb
->bags
, pb
->bag_idx
++);
651 if (!TEST_ptr(bag
)) {
656 if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag
), attrs
)
657 || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag
), NID_secretBag
)
658 || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag
), secret_nid
)
659 || !TEST_true(check_asn1_string(PKCS12_SAFEBAG_get0_bag_obj(bag
), secret
)))
664 void start_check_pkcs12(PKCS12_BUILDER
*pb
)
671 p12
= from_bio_p12(pb
->p12bio
, NULL
);
672 if (!TEST_ptr(p12
)) {
676 pb
->safes
= PKCS12_unpack_authsafes(p12
);
677 if (!TEST_ptr(pb
->safes
))
684 void start_check_pkcs12_with_mac(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
691 p12
= from_bio_p12(pb
->p12bio
, mac
);
692 if (!TEST_ptr(p12
)) {
696 pb
->safes
= PKCS12_unpack_authsafes(p12
);
697 if (!TEST_ptr(pb
->safes
))
704 void start_check_pkcs12_file(PKCS12_BUILDER
*pb
)
711 p12
= read_p12(pb
->filename
, NULL
);
712 if (!TEST_ptr(p12
)) {
716 pb
->safes
= PKCS12_unpack_authsafes(p12
);
717 if (!TEST_ptr(pb
->safes
))
724 void start_check_pkcs12_file_with_mac(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
731 p12
= read_p12(pb
->filename
, mac
);
732 if (!TEST_ptr(p12
)) {
736 pb
->safes
= PKCS12_unpack_authsafes(p12
);
737 if (!TEST_ptr(pb
->safes
))
744 void end_check_pkcs12(PKCS12_BUILDER
*pb
)
749 sk_PKCS7_pop_free(pb
->safes
, PKCS7_free
);
753 void start_check_contentinfo(PKCS12_BUILDER
*pb
)
759 pb
->bags
= decode_contentinfo(pb
->safes
, pb
->safe_idx
++, NULL
);
760 if (!TEST_ptr(pb
->bags
)) {
764 TEST_info("Decoding %d bags", sk_PKCS12_SAFEBAG_num(pb
->bags
));
767 void start_check_contentinfo_encrypted(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*enc
)
773 pb
->bags
= decode_contentinfo(pb
->safes
, pb
->safe_idx
++, enc
);
774 if (!TEST_ptr(pb
->bags
)) {
778 TEST_info("Decoding %d bags", sk_PKCS12_SAFEBAG_num(pb
->bags
));
782 void end_check_contentinfo(PKCS12_BUILDER
*pb
)
787 if (!TEST_int_eq(sk_PKCS12_SAFEBAG_num(pb
->bags
), pb
->bag_idx
))
789 sk_PKCS12_SAFEBAG_pop_free(pb
->bags
, PKCS12_SAFEBAG_free
);