]>
git.ipfire.org Git - thirdparty/openssl.git/blob - test/pkcs12_helper.c
2 * Copyright 2020 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>
22 #include "pkcs12_helper.h"
24 /* Set this to > 0 write test data to file */
27 /* -------------------------------------------------------------------------
28 * Local function declarations
31 static X509
*load_cert(const unsigned char *bytes
, int len
);
32 static EVP_PKEY
*load_pkey(const unsigned char *bytes
, int len
);
34 static int add_attributes(PKCS12_SAFEBAG
*bag
, const PKCS12_ATTR
*attrs
);
36 static void generate_p12(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
);
37 static int write_p12(PKCS12
*p12
, const char *outfile
);
39 static PKCS12
*from_bio_p12(BIO
*bio
, const PKCS12_ENC
*mac
);
40 static PKCS12
*read_p12(const char *infile
, const PKCS12_ENC
*mac
);
41 static int check_p12_mac(PKCS12
*p12
, const PKCS12_ENC
*mac
);
42 static int check_asn1_string(const ASN1_TYPE
*av
, const char *txt
);
43 static int check_attrs(const STACK_OF(X509_ATTRIBUTE
) *bag_attrs
, const PKCS12_ATTR
*attrs
);
46 /* --------------------------------------------------------------------------
47 * Test data load functions
50 static X509
*load_cert(const unsigned char *bytes
, int len
)
54 cert
= d2i_X509(NULL
, &bytes
, len
);
61 static EVP_PKEY
*load_pkey(const unsigned char *bytes
, int len
)
63 EVP_PKEY
*pkey
= NULL
;
65 pkey
= d2i_AutoPrivateKey(NULL
, &bytes
, len
);
73 /* -------------------------------------------------------------------------
77 PKCS12_BUILDER
*new_pkcs12_builder(const char *filename
)
79 PKCS12_BUILDER
*pb
= OPENSSL_malloc(sizeof(PKCS12_BUILDER
));
83 pb
->filename
= filename
;
88 int end_pkcs12_builder(PKCS12_BUILDER
*pb
)
90 int result
= pb
->success
;
97 void start_pkcs12(PKCS12_BUILDER
*pb
)
103 void end_pkcs12(PKCS12_BUILDER
*pb
)
107 generate_p12(pb
, NULL
);
111 void end_pkcs12_with_mac(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
115 generate_p12(pb
, mac
);
119 /* Generate the PKCS12 encoding and write to memory bio */
120 static void generate_p12(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
127 pb
->p12bio
= BIO_new(BIO_s_mem());
128 if (!TEST_ptr(pb
->p12bio
)) {
132 p12
= PKCS12_add_safes(pb
->safes
, 0);
133 if (!TEST_ptr(p12
)) {
137 sk_PKCS7_pop_free(pb
->safes
, PKCS7_free
);
140 if (!TEST_true(PKCS12_set_mac(p12
, mac
->pass
, strlen(mac
->pass
),
141 NULL
, 0, mac
->iter
, EVP_get_digestbynid(mac
->nid
)))) {
146 i2d_PKCS12_bio(pb
->p12bio
, p12
);
148 /* Can write to file here for debug */
150 write_p12(p12
, pb
->filename
);
156 static int write_p12(PKCS12
*p12
, const char *outfile
)
159 BIO
*out
= BIO_new_file(outfile
, "w");
164 if (!TEST_int_eq(i2d_PKCS12_bio(out
, p12
), 1))
172 static PKCS12
*from_bio_p12(BIO
*bio
, const PKCS12_ENC
*mac
)
176 p12
= d2i_PKCS12_bio(bio
, NULL
);
181 if (!TEST_false(PKCS12_mac_present(p12
)))
184 if (!check_p12_mac(p12
, mac
))
194 /* For use with existing files */
195 static PKCS12
*read_p12(const char *infile
, const PKCS12_ENC
*mac
)
198 BIO
*in
= BIO_new_file(infile
, "r");
202 p12
= d2i_PKCS12_bio(in
, NULL
);
207 if (!TEST_false(PKCS12_mac_present(p12
)))
210 if (!check_p12_mac(p12
, mac
))
219 static int check_p12_mac(PKCS12
*p12
, const PKCS12_ENC
*mac
)
221 return TEST_true(PKCS12_mac_present(p12
))
222 && TEST_true(PKCS12_verify_mac(p12
, mac
->pass
, strlen(mac
->pass
)));
226 /* -------------------------------------------------------------------------
227 * PKCS7 content info builder
230 void start_contentinfo(PKCS12_BUILDER
*pb
)
236 void end_contentinfo(PKCS12_BUILDER
*pb
)
239 if (pb
->bags
&& !TEST_true(PKCS12_add_safe(&pb
->safes
, pb
->bags
, -1, 0, NULL
))) {
244 sk_PKCS12_SAFEBAG_pop_free(pb
->bags
, PKCS12_SAFEBAG_free
);
249 void end_contentinfo_encrypted(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*enc
)
253 && !TEST_true(PKCS12_add_safe(&pb
->safes
, pb
->bags
, enc
->nid
, enc
->iter
, enc
->pass
))) {
258 sk_PKCS12_SAFEBAG_pop_free(pb
->bags
, PKCS12_SAFEBAG_free
);
263 static STACK_OF(PKCS12_SAFEBAG
) *decode_contentinfo(STACK_OF(PKCS7
) *safes
, int idx
, const PKCS12_ENC
*enc
)
265 STACK_OF(PKCS12_SAFEBAG
) *bags
= NULL
;
266 PKCS7
*p7
= sk_PKCS7_value(safes
, idx
);
267 int bagnid
= OBJ_obj2nid(p7
->type
);
270 if (!TEST_int_eq(bagnid
, NID_pkcs7_encrypted
))
272 /* TODO: Check algorithm (iterations?) against what we originally set */
273 bags
= PKCS12_unpack_p7encdata(p7
, enc
->pass
, strlen(enc
->pass
));
275 if (!TEST_int_eq(bagnid
, NID_pkcs7_data
))
277 bags
= PKCS12_unpack_p7data(p7
);
288 /* -------------------------------------------------------------------------
289 * PKCS12 safeBag/attribute builder
292 static int add_attributes(PKCS12_SAFEBAG
*bag
, const PKCS12_ATTR
*attrs
)
296 const PKCS12_ATTR
*p_attr
= attrs
;
301 while (p_attr
->oid
!= NULL
) {
302 TEST_info("Adding attribute %s = %s", p_attr
->oid
, p_attr
->value
);
303 attr_nid
= OBJ_txt2nid(p_attr
->oid
);
305 if (attr_nid
== NID_friendlyName
) {
306 if (!TEST_true(PKCS12_add_friendlyname(bag
, p_attr
->value
, -1)))
308 } else if (attr_nid
== NID_localKeyID
) {
309 if (!TEST_true(PKCS12_add_localkeyid(bag
, (unsigned char *)p_attr
->value
,
310 strlen(p_attr
->value
))))
313 /* Custom attribute values limited to ASCII in these tests */
314 if (!TEST_true(PKCS12_add1_attr_by_txt(bag
, p_attr
->oid
, MBSTRING_ASC
,
315 (unsigned char *)p_attr
->value
,
316 strlen(p_attr
->value
))))
326 void add_certbag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
327 const PKCS12_ATTR
*attrs
)
329 PKCS12_SAFEBAG
*bag
= NULL
;
336 cert
= load_cert(bytes
, len
);
337 if (!TEST_ptr(cert
)) {
342 name
= X509_NAME_oneline(X509_get_subject_name(cert
), NULL
, 0);
343 TEST_info("Adding certificate <%s>", name
);
346 bag
= PKCS12_add_cert(&pb
->bags
, cert
);
347 if (!TEST_ptr(bag
)) {
352 if (!TEST_true(add_attributes(bag
, attrs
))) {
360 void add_keybag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
361 const PKCS12_ATTR
*attrs
, const PKCS12_ENC
*enc
)
363 PKCS12_SAFEBAG
*bag
= NULL
;
364 EVP_PKEY
*pkey
= NULL
;
369 TEST_info("Adding key");
371 pkey
= load_pkey(bytes
, len
);
372 if (!TEST_ptr(pkey
)) {
377 bag
= PKCS12_add_key(&pb
->bags
, pkey
, 0 /*keytype*/, enc
->iter
, enc
->nid
, enc
->pass
);
378 if (!TEST_ptr(bag
)) {
382 if (!add_attributes(bag
, attrs
))
388 void add_secretbag(PKCS12_BUILDER
*pb
, int secret_nid
, const char *secret
,
389 const PKCS12_ATTR
*attrs
)
391 PKCS12_SAFEBAG
*bag
= NULL
;
396 TEST_info("Adding secret <%s>", secret
);
398 bag
= PKCS12_add_secret(&pb
->bags
, secret_nid
, (const unsigned char *)secret
, strlen(secret
));
399 if (!TEST_ptr(bag
)) {
403 if (!add_attributes(bag
, attrs
))
408 /* -------------------------------------------------------------------------
409 * PKCS12 structure checking
412 static int check_asn1_string(const ASN1_TYPE
*av
, const char *txt
)
421 case V_ASN1_BMPSTRING
:
422 value
= OPENSSL_uni2asc(av
->value
.bmpstring
->data
,
423 av
->value
.bmpstring
->length
);
424 if (!TEST_str_eq(txt
, (char *)value
))
428 case V_ASN1_UTF8STRING
:
429 if (!TEST_str_eq(txt
, (char *)av
->value
.utf8string
->data
))
433 case V_ASN1_OCTET_STRING
:
434 if (!TEST_str_eq(txt
, (char *)av
->value
.octet_string
->data
))
439 /* Tests do not support other attribute types currently */
448 static int check_attrs(const STACK_OF(X509_ATTRIBUTE
) *bag_attrs
, const PKCS12_ATTR
*attrs
)
451 X509_ATTRIBUTE
*attr
;
456 for (i
= 0; i
< sk_X509_ATTRIBUTE_num(bag_attrs
); i
++) {
457 const PKCS12_ATTR
*p_attr
= attrs
;
458 ASN1_OBJECT
*attr_obj
;
460 attr
= sk_X509_ATTRIBUTE_value(bag_attrs
, i
);
461 attr_obj
= X509_ATTRIBUTE_get0_object(attr
);
462 OBJ_obj2txt(attr_txt
, 100, attr_obj
, 0);
464 while(p_attr
->oid
!= NULL
) {
465 /* Find a matching attribute type */
466 if (strcmp(p_attr
->oid
, attr_txt
) == 0) {
468 /* TODO: Handle multi-value attributes */
469 if (!TEST_int_eq(X509_ATTRIBUTE_count(attr
), 1))
472 for (j
= 0; j
< X509_ATTRIBUTE_count(attr
); j
++)
474 av
= X509_ATTRIBUTE_get0_type(attr
, j
);
475 if (!TEST_true(check_asn1_string(av
, p_attr
->value
)))
488 void check_certbag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
489 const PKCS12_ATTR
*attrs
)
492 X509
*ref_x509
= NULL
;
493 const PKCS12_SAFEBAG
*bag
;
498 bag
= sk_PKCS12_SAFEBAG_value(pb
->bags
, pb
->bag_idx
++);
499 if (!TEST_ptr(bag
)) {
503 if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag
), attrs
)
504 || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag
), NID_certBag
)
505 || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag
), NID_x509Certificate
)) {
509 x509
= PKCS12_SAFEBAG_get1_cert(bag
);
510 if (!TEST_ptr(x509
)) {
514 ref_x509
= load_cert(bytes
, len
);
515 if (!TEST_false(X509_cmp(x509
, ref_x509
)))
522 void check_keybag(PKCS12_BUILDER
*pb
, const unsigned char *bytes
, int len
,
523 const PKCS12_ATTR
*attrs
, const PKCS12_ENC
*enc
)
525 EVP_PKEY
*pkey
= NULL
;
526 EVP_PKEY
*ref_pkey
= NULL
;
527 PKCS8_PRIV_KEY_INFO
*p8
;
528 const PKCS8_PRIV_KEY_INFO
*p8c
;
529 const PKCS12_SAFEBAG
*bag
;
534 bag
= sk_PKCS12_SAFEBAG_value(pb
->bags
, pb
->bag_idx
++);
535 if (!TEST_ptr(bag
)) {
540 if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag
), attrs
)) {
545 switch (PKCS12_SAFEBAG_get_nid(bag
)) {
547 p8c
= PKCS12_SAFEBAG_get0_p8inf(bag
);
548 if (!TEST_ptr(pkey
= EVP_PKCS82PKEY(p8c
))) {
552 /* TODO: handle key attributes */
553 /* PKCS8_pkey_get0_attrs(p8c); */
556 case NID_pkcs8ShroudedKeyBag
:
557 if (!TEST_ptr(p8
= PKCS12_decrypt_skey(bag
, enc
->pass
, strlen(enc
->pass
)))) {
561 if (!TEST_ptr(pkey
= EVP_PKCS82PKEY(p8
))) {
562 PKCS8_PRIV_KEY_INFO_free(p8
);
566 /* TODO: handle key attributes */
567 /* PKCS8_pkey_get0_attrs(p8); */
568 PKCS8_PRIV_KEY_INFO_free(p8
);
576 /* PKEY compare returns 1 for match */
577 ref_pkey
= load_pkey(bytes
, len
);
578 if (!TEST_true(EVP_PKEY_eq(pkey
, ref_pkey
)))
582 EVP_PKEY_free(ref_pkey
);
585 void check_secretbag(PKCS12_BUILDER
*pb
, int secret_nid
, const char *secret
, const PKCS12_ATTR
*attrs
)
587 const PKCS12_SAFEBAG
*bag
;
592 bag
= sk_PKCS12_SAFEBAG_value(pb
->bags
, pb
->bag_idx
++);
593 if (!TEST_ptr(bag
)) {
598 if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag
), attrs
)
599 || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag
), NID_secretBag
)
600 || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag
), secret_nid
)
601 || !TEST_true(check_asn1_string(PKCS12_SAFEBAG_get0_bag_obj(bag
), secret
)))
606 void start_check_pkcs12(PKCS12_BUILDER
*pb
)
608 PKCS12
*p12
= from_bio_p12(pb
->p12bio
, NULL
);
609 if (!TEST_ptr(p12
)) {
613 pb
->safes
= PKCS12_unpack_authsafes(p12
);
614 if (!TEST_ptr(pb
->safes
))
621 void start_check_pkcs12_with_mac(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
623 PKCS12
*p12
= from_bio_p12(pb
->p12bio
, mac
);
624 if (!TEST_ptr(p12
)) {
628 pb
->safes
= PKCS12_unpack_authsafes(p12
);
629 if (!TEST_ptr(pb
->safes
))
636 void start_check_pkcs12_file(PKCS12_BUILDER
*pb
)
638 PKCS12
*p12
= read_p12(pb
->filename
, NULL
);
639 if (!TEST_ptr(p12
)) {
643 pb
->safes
= PKCS12_unpack_authsafes(p12
);
644 if (!TEST_ptr(pb
->safes
))
651 void start_check_pkcs12_file_with_mac(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*mac
)
653 PKCS12
*p12
= read_p12(pb
->filename
, mac
);
654 if (!TEST_ptr(p12
)) {
658 pb
->safes
= PKCS12_unpack_authsafes(p12
);
659 if (!TEST_ptr(pb
->safes
))
666 void end_check_pkcs12(PKCS12_BUILDER
*pb
)
668 sk_PKCS7_pop_free(pb
->safes
, PKCS7_free
);
672 void start_check_contentinfo(PKCS12_BUILDER
*pb
)
675 pb
->bags
= decode_contentinfo(pb
->safes
, pb
->safe_idx
++, NULL
);
676 if (!TEST_ptr(pb
->bags
)) {
680 TEST_info("Decoding %d bags", sk_PKCS12_SAFEBAG_num(pb
->bags
));
683 void start_check_contentinfo_encrypted(PKCS12_BUILDER
*pb
, const PKCS12_ENC
*enc
)
686 pb
->bags
= decode_contentinfo(pb
->safes
, pb
->safe_idx
++, enc
);
687 if (!TEST_ptr(pb
->bags
)) {
691 TEST_info("Decoding %d bags", sk_PKCS12_SAFEBAG_num(pb
->bags
));
695 void end_check_contentinfo(PKCS12_BUILDER
*pb
)
697 if (!TEST_int_eq(sk_PKCS12_SAFEBAG_num(pb
->bags
), pb
->bag_idx
))
699 sk_PKCS12_SAFEBAG_pop_free(pb
->bags
, PKCS12_SAFEBAG_free
);