xref: /freebsd/crypto/openssl/test/pkcs12_api_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery 
10*e7be843bSPierre Pronchery #include <stdio.h>
11*e7be843bSPierre Pronchery #include <string.h>
12*e7be843bSPierre Pronchery #include <stdlib.h>
13*e7be843bSPierre Pronchery 
14*e7be843bSPierre Pronchery #include "internal/nelem.h"
15*e7be843bSPierre Pronchery 
16*e7be843bSPierre Pronchery #include <openssl/pkcs12.h>
17*e7be843bSPierre Pronchery #include <openssl/x509.h>
18*e7be843bSPierre Pronchery #include <openssl/x509v3.h>
19*e7be843bSPierre Pronchery #include <openssl/pem.h>
20*e7be843bSPierre Pronchery 
21*e7be843bSPierre Pronchery #include "testutil.h"
22*e7be843bSPierre Pronchery #include "helpers/pkcs12.h"
23*e7be843bSPierre Pronchery 
24*e7be843bSPierre Pronchery static OSSL_LIB_CTX *testctx = NULL;
25*e7be843bSPierre Pronchery static OSSL_PROVIDER *nullprov = NULL;
26*e7be843bSPierre Pronchery 
test_null_args(void)27*e7be843bSPierre Pronchery static int test_null_args(void)
28*e7be843bSPierre Pronchery {
29*e7be843bSPierre Pronchery     return TEST_false(PKCS12_parse(NULL, NULL, NULL, NULL, NULL));
30*e7be843bSPierre Pronchery }
31*e7be843bSPierre Pronchery 
PKCS12_load(const char * fpath)32*e7be843bSPierre Pronchery static PKCS12 *PKCS12_load(const char *fpath)
33*e7be843bSPierre Pronchery {
34*e7be843bSPierre Pronchery     BIO *bio = NULL;
35*e7be843bSPierre Pronchery     PKCS12 *p12 = NULL;
36*e7be843bSPierre Pronchery 
37*e7be843bSPierre Pronchery     bio = BIO_new_file(fpath, "rb");
38*e7be843bSPierre Pronchery     if (!TEST_ptr(bio))
39*e7be843bSPierre Pronchery         goto err;
40*e7be843bSPierre Pronchery 
41*e7be843bSPierre Pronchery     p12 = PKCS12_init_ex(NID_pkcs7_data, testctx, "provider=default");
42*e7be843bSPierre Pronchery     if (!TEST_ptr(p12))
43*e7be843bSPierre Pronchery         goto err;
44*e7be843bSPierre Pronchery 
45*e7be843bSPierre Pronchery     if (!TEST_true(p12 == d2i_PKCS12_bio(bio, &p12)))
46*e7be843bSPierre Pronchery         goto err;
47*e7be843bSPierre Pronchery 
48*e7be843bSPierre Pronchery     BIO_free(bio);
49*e7be843bSPierre Pronchery 
50*e7be843bSPierre Pronchery     return p12;
51*e7be843bSPierre Pronchery 
52*e7be843bSPierre Pronchery err:
53*e7be843bSPierre Pronchery     BIO_free(bio);
54*e7be843bSPierre Pronchery     PKCS12_free(p12);
55*e7be843bSPierre Pronchery     return NULL;
56*e7be843bSPierre Pronchery }
57*e7be843bSPierre Pronchery 
58*e7be843bSPierre Pronchery static const char *in_file = NULL;
59*e7be843bSPierre Pronchery static const char *in_pass = "";
60*e7be843bSPierre Pronchery static int has_key = 0;
61*e7be843bSPierre Pronchery static int has_cert = 0;
62*e7be843bSPierre Pronchery static int has_ca = 0;
63*e7be843bSPierre Pronchery 
changepass(PKCS12 * p12,EVP_PKEY * key,X509 * cert,STACK_OF (X509)* ca)64*e7be843bSPierre Pronchery static int changepass(PKCS12 *p12, EVP_PKEY *key, X509 *cert, STACK_OF(X509) *ca)
65*e7be843bSPierre Pronchery {
66*e7be843bSPierre Pronchery     int ret = 0;
67*e7be843bSPierre Pronchery     PKCS12 *p12new = NULL;
68*e7be843bSPierre Pronchery     EVP_PKEY *key2 = NULL;
69*e7be843bSPierre Pronchery     X509 *cert2 = NULL;
70*e7be843bSPierre Pronchery     STACK_OF(X509) *ca2 = NULL;
71*e7be843bSPierre Pronchery     BIO *bio = NULL;
72*e7be843bSPierre Pronchery 
73*e7be843bSPierre Pronchery     if (!TEST_true(PKCS12_newpass(p12, in_pass, "NEWPASS")))
74*e7be843bSPierre Pronchery         goto err;
75*e7be843bSPierre Pronchery     if (!TEST_ptr(bio = BIO_new(BIO_s_mem())))
76*e7be843bSPierre Pronchery         goto err;
77*e7be843bSPierre Pronchery     if (!TEST_true(i2d_PKCS12_bio(bio, p12)))
78*e7be843bSPierre Pronchery         goto err;
79*e7be843bSPierre Pronchery     if (!TEST_ptr(p12new = PKCS12_init_ex(NID_pkcs7_data, testctx, "provider=default")))
80*e7be843bSPierre Pronchery         goto err;
81*e7be843bSPierre Pronchery     if (!TEST_ptr(d2i_PKCS12_bio(bio, &p12new)))
82*e7be843bSPierre Pronchery         goto err;
83*e7be843bSPierre Pronchery     if (!TEST_true(PKCS12_parse(p12new, "NEWPASS", &key2, &cert2, &ca2)))
84*e7be843bSPierre Pronchery         goto err;
85*e7be843bSPierre Pronchery     if (has_key) {
86*e7be843bSPierre Pronchery         if (!TEST_ptr(key2) || !TEST_int_eq(EVP_PKEY_eq(key, key2), 1))
87*e7be843bSPierre Pronchery             goto err;
88*e7be843bSPierre Pronchery     }
89*e7be843bSPierre Pronchery     if (has_cert) {
90*e7be843bSPierre Pronchery         if (!TEST_ptr(cert2) || !TEST_int_eq(X509_cmp(cert, cert2), 0))
91*e7be843bSPierre Pronchery             goto err;
92*e7be843bSPierre Pronchery     }
93*e7be843bSPierre Pronchery     ret = 1;
94*e7be843bSPierre Pronchery err:
95*e7be843bSPierre Pronchery     BIO_free(bio);
96*e7be843bSPierre Pronchery     PKCS12_free(p12new);
97*e7be843bSPierre Pronchery     EVP_PKEY_free(key2);
98*e7be843bSPierre Pronchery     X509_free(cert2);
99*e7be843bSPierre Pronchery     OSSL_STACK_OF_X509_free(ca2);
100*e7be843bSPierre Pronchery     return ret;
101*e7be843bSPierre Pronchery }
102*e7be843bSPierre Pronchery 
pkcs12_parse_test(void)103*e7be843bSPierre Pronchery static int pkcs12_parse_test(void)
104*e7be843bSPierre Pronchery {
105*e7be843bSPierre Pronchery     int ret = 0;
106*e7be843bSPierre Pronchery     PKCS12 *p12 = NULL;
107*e7be843bSPierre Pronchery     EVP_PKEY *key = NULL;
108*e7be843bSPierre Pronchery     X509 *cert = NULL;
109*e7be843bSPierre Pronchery     STACK_OF(X509) *ca = NULL;
110*e7be843bSPierre Pronchery 
111*e7be843bSPierre Pronchery     if (in_file != NULL) {
112*e7be843bSPierre Pronchery         p12 = PKCS12_load(in_file);
113*e7be843bSPierre Pronchery         if (!TEST_ptr(p12))
114*e7be843bSPierre Pronchery             goto err;
115*e7be843bSPierre Pronchery 
116*e7be843bSPierre Pronchery         if (!TEST_true(PKCS12_parse(p12, in_pass, &key, &cert, &ca)))
117*e7be843bSPierre Pronchery             goto err;
118*e7be843bSPierre Pronchery 
119*e7be843bSPierre Pronchery         if ((has_key && !TEST_ptr(key)) || (!has_key && !TEST_ptr_null(key)))
120*e7be843bSPierre Pronchery             goto err;
121*e7be843bSPierre Pronchery         if ((has_cert && !TEST_ptr(cert)) || (!has_cert && !TEST_ptr_null(cert)))
122*e7be843bSPierre Pronchery             goto err;
123*e7be843bSPierre Pronchery         if ((has_ca && !TEST_ptr(ca)) || (!has_ca && !TEST_ptr_null(ca)))
124*e7be843bSPierre Pronchery             goto err;
125*e7be843bSPierre Pronchery         if (has_key && !changepass(p12, key, cert, ca))
126*e7be843bSPierre Pronchery             goto err;
127*e7be843bSPierre Pronchery     }
128*e7be843bSPierre Pronchery     ret = 1;
129*e7be843bSPierre Pronchery err:
130*e7be843bSPierre Pronchery     PKCS12_free(p12);
131*e7be843bSPierre Pronchery     EVP_PKEY_free(key);
132*e7be843bSPierre Pronchery     X509_free(cert);
133*e7be843bSPierre Pronchery     OSSL_STACK_OF_X509_free(ca);
134*e7be843bSPierre Pronchery     return TEST_true(ret);
135*e7be843bSPierre Pronchery }
136*e7be843bSPierre Pronchery 
pkcs12_create_cb(PKCS12_SAFEBAG * bag,void * cbarg)137*e7be843bSPierre Pronchery static int pkcs12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg)
138*e7be843bSPierre Pronchery {
139*e7be843bSPierre Pronchery     int cb_ret = *((int*)cbarg);
140*e7be843bSPierre Pronchery     return cb_ret;
141*e7be843bSPierre Pronchery }
142*e7be843bSPierre Pronchery 
pkcs12_create_ex2_setup(EVP_PKEY ** key,X509 ** cert,STACK_OF (X509)** ca)143*e7be843bSPierre Pronchery static PKCS12 *pkcs12_create_ex2_setup(EVP_PKEY **key, X509 **cert, STACK_OF(X509) **ca)
144*e7be843bSPierre Pronchery {
145*e7be843bSPierre Pronchery     PKCS12 *p12 = NULL;
146*e7be843bSPierre Pronchery     p12 = PKCS12_load("out6.p12");
147*e7be843bSPierre Pronchery     if (!TEST_ptr(p12))
148*e7be843bSPierre Pronchery         goto err;
149*e7be843bSPierre Pronchery 
150*e7be843bSPierre Pronchery     if (!TEST_true(PKCS12_parse(p12, "", key, cert, ca)))
151*e7be843bSPierre Pronchery         goto err;
152*e7be843bSPierre Pronchery 
153*e7be843bSPierre Pronchery     return p12;
154*e7be843bSPierre Pronchery err:
155*e7be843bSPierre Pronchery     PKCS12_free(p12);
156*e7be843bSPierre Pronchery     return NULL;
157*e7be843bSPierre Pronchery }
158*e7be843bSPierre Pronchery 
pkcs12_create_ex2_test(int test)159*e7be843bSPierre Pronchery static int pkcs12_create_ex2_test(int test)
160*e7be843bSPierre Pronchery {
161*e7be843bSPierre Pronchery     int ret = 0, cb_ret = 0;
162*e7be843bSPierre Pronchery     PKCS12 *ptr = NULL, *p12 = NULL;
163*e7be843bSPierre Pronchery     EVP_PKEY *key = NULL;
164*e7be843bSPierre Pronchery     X509 *cert = NULL;
165*e7be843bSPierre Pronchery     STACK_OF(X509) *ca = NULL;
166*e7be843bSPierre Pronchery 
167*e7be843bSPierre Pronchery     p12 = pkcs12_create_ex2_setup(&key, &cert, &ca);
168*e7be843bSPierre Pronchery     if (!TEST_ptr(p12))
169*e7be843bSPierre Pronchery         goto err;
170*e7be843bSPierre Pronchery 
171*e7be843bSPierre Pronchery     if (test == 0) {
172*e7be843bSPierre Pronchery         /* Confirm PKCS12_create_ex2 returns NULL */
173*e7be843bSPierre Pronchery         ptr = PKCS12_create_ex2(NULL, NULL, NULL,
174*e7be843bSPierre Pronchery                                 NULL, NULL, NID_undef, NID_undef,
175*e7be843bSPierre Pronchery                                 0, 0, 0,
176*e7be843bSPierre Pronchery                                 testctx, NULL,
177*e7be843bSPierre Pronchery                                 NULL, NULL);
178*e7be843bSPierre Pronchery         if (TEST_ptr(ptr))
179*e7be843bSPierre Pronchery             goto err;
180*e7be843bSPierre Pronchery 
181*e7be843bSPierre Pronchery         /* Can't proceed without a valid cert at least */
182*e7be843bSPierre Pronchery         if (!TEST_ptr(cert))
183*e7be843bSPierre Pronchery             goto err;
184*e7be843bSPierre Pronchery 
185*e7be843bSPierre Pronchery         /* Specified call back called - return success */
186*e7be843bSPierre Pronchery         cb_ret = 1;
187*e7be843bSPierre Pronchery         ptr = PKCS12_create_ex2(NULL, NULL, NULL,
188*e7be843bSPierre Pronchery                                 cert, NULL, NID_undef, NID_undef,
189*e7be843bSPierre Pronchery                                 0, 0, 0,
190*e7be843bSPierre Pronchery                                 testctx, NULL,
191*e7be843bSPierre Pronchery                                 pkcs12_create_cb, (void*)&cb_ret);
192*e7be843bSPierre Pronchery         /* PKCS12 successfully created */
193*e7be843bSPierre Pronchery         if (!TEST_ptr(ptr))
194*e7be843bSPierre Pronchery             goto err;
195*e7be843bSPierre Pronchery     } else if (test == 1) {
196*e7be843bSPierre Pronchery         /* Specified call back called - return error*/
197*e7be843bSPierre Pronchery         cb_ret = -1;
198*e7be843bSPierre Pronchery         ptr = PKCS12_create_ex2(NULL, NULL, NULL,
199*e7be843bSPierre Pronchery                                 cert, NULL, NID_undef, NID_undef,
200*e7be843bSPierre Pronchery                                 0, 0, 0,
201*e7be843bSPierre Pronchery                                 testctx, NULL,
202*e7be843bSPierre Pronchery                                 pkcs12_create_cb, (void*)&cb_ret);
203*e7be843bSPierre Pronchery         /* PKCS12 not created */
204*e7be843bSPierre Pronchery        if (TEST_ptr(ptr))
205*e7be843bSPierre Pronchery             goto err;
206*e7be843bSPierre Pronchery     } else if (test == 2) {
207*e7be843bSPierre Pronchery         /* Specified call back called - return failure */
208*e7be843bSPierre Pronchery         cb_ret = 0;
209*e7be843bSPierre Pronchery         ptr = PKCS12_create_ex2(NULL, NULL, NULL,
210*e7be843bSPierre Pronchery                                 cert, NULL, NID_undef, NID_undef,
211*e7be843bSPierre Pronchery                                 0, 0, 0,
212*e7be843bSPierre Pronchery                                 testctx, NULL,
213*e7be843bSPierre Pronchery                                 pkcs12_create_cb, (void*)&cb_ret);
214*e7be843bSPierre Pronchery         /* PKCS12 successfully created */
215*e7be843bSPierre Pronchery         if (!TEST_ptr(ptr))
216*e7be843bSPierre Pronchery             goto err;
217*e7be843bSPierre Pronchery     }
218*e7be843bSPierre Pronchery 
219*e7be843bSPierre Pronchery     ret = 1;
220*e7be843bSPierre Pronchery err:
221*e7be843bSPierre Pronchery     PKCS12_free(p12);
222*e7be843bSPierre Pronchery     PKCS12_free(ptr);
223*e7be843bSPierre Pronchery     EVP_PKEY_free(key);
224*e7be843bSPierre Pronchery     X509_free(cert);
225*e7be843bSPierre Pronchery     OSSL_STACK_OF_X509_free(ca);
226*e7be843bSPierre Pronchery     return TEST_true(ret);
227*e7be843bSPierre Pronchery }
228*e7be843bSPierre Pronchery 
229*e7be843bSPierre Pronchery typedef enum OPTION_choice {
230*e7be843bSPierre Pronchery     OPT_ERR = -1,
231*e7be843bSPierre Pronchery     OPT_EOF = 0,
232*e7be843bSPierre Pronchery     OPT_IN_FILE,
233*e7be843bSPierre Pronchery     OPT_IN_PASS,
234*e7be843bSPierre Pronchery     OPT_IN_HAS_KEY,
235*e7be843bSPierre Pronchery     OPT_IN_HAS_CERT,
236*e7be843bSPierre Pronchery     OPT_IN_HAS_CA,
237*e7be843bSPierre Pronchery     OPT_LEGACY,
238*e7be843bSPierre Pronchery     OPT_TEST_ENUM
239*e7be843bSPierre Pronchery } OPTION_CHOICE;
240*e7be843bSPierre Pronchery 
test_get_options(void)241*e7be843bSPierre Pronchery const OPTIONS *test_get_options(void)
242*e7be843bSPierre Pronchery {
243*e7be843bSPierre Pronchery     static const OPTIONS options[] = {
244*e7be843bSPierre Pronchery         OPT_TEST_OPTIONS_DEFAULT_USAGE,
245*e7be843bSPierre Pronchery         { "in",   OPT_IN_FILE,   '<', "PKCS12 input file" },
246*e7be843bSPierre Pronchery         { "pass",   OPT_IN_PASS,   's', "PKCS12 input file password" },
247*e7be843bSPierre Pronchery         { "has-key",   OPT_IN_HAS_KEY,  'n', "Whether the input file does contain an user key" },
248*e7be843bSPierre Pronchery         { "has-cert",   OPT_IN_HAS_CERT, 'n', "Whether the input file does contain an user certificate" },
249*e7be843bSPierre Pronchery         { "has-ca",   OPT_IN_HAS_CA,   'n', "Whether the input file does contain other certificate" },
250*e7be843bSPierre Pronchery         { "legacy",  OPT_LEGACY,  '-', "Test the legacy APIs" },
251*e7be843bSPierre Pronchery         { NULL }
252*e7be843bSPierre Pronchery     };
253*e7be843bSPierre Pronchery     return options;
254*e7be843bSPierre Pronchery }
255*e7be843bSPierre Pronchery 
setup_tests(void)256*e7be843bSPierre Pronchery int setup_tests(void)
257*e7be843bSPierre Pronchery {
258*e7be843bSPierre Pronchery     OPTION_CHOICE o;
259*e7be843bSPierre Pronchery 
260*e7be843bSPierre Pronchery     while ((o = opt_next()) != OPT_EOF) {
261*e7be843bSPierre Pronchery         switch (o) {
262*e7be843bSPierre Pronchery         case OPT_IN_FILE:
263*e7be843bSPierre Pronchery             in_file = opt_arg();
264*e7be843bSPierre Pronchery             break;
265*e7be843bSPierre Pronchery         case OPT_IN_PASS:
266*e7be843bSPierre Pronchery             in_pass = opt_arg();
267*e7be843bSPierre Pronchery             break;
268*e7be843bSPierre Pronchery         case OPT_LEGACY:
269*e7be843bSPierre Pronchery             break;
270*e7be843bSPierre Pronchery         case OPT_IN_HAS_KEY:
271*e7be843bSPierre Pronchery             has_key = opt_int_arg();
272*e7be843bSPierre Pronchery             break;
273*e7be843bSPierre Pronchery         case OPT_IN_HAS_CERT:
274*e7be843bSPierre Pronchery             has_cert = opt_int_arg();
275*e7be843bSPierre Pronchery             break;
276*e7be843bSPierre Pronchery         case OPT_IN_HAS_CA:
277*e7be843bSPierre Pronchery             has_ca = opt_int_arg();
278*e7be843bSPierre Pronchery             break;
279*e7be843bSPierre Pronchery         case OPT_TEST_CASES:
280*e7be843bSPierre Pronchery             break;
281*e7be843bSPierre Pronchery         default:
282*e7be843bSPierre Pronchery             return 0;
283*e7be843bSPierre Pronchery         }
284*e7be843bSPierre Pronchery     }
285*e7be843bSPierre Pronchery 
286*e7be843bSPierre Pronchery     if (!test_get_libctx(&testctx, &nullprov, NULL, NULL, NULL)) {
287*e7be843bSPierre Pronchery         OSSL_LIB_CTX_free(testctx);
288*e7be843bSPierre Pronchery         testctx = NULL;
289*e7be843bSPierre Pronchery         return 0;
290*e7be843bSPierre Pronchery     }
291*e7be843bSPierre Pronchery 
292*e7be843bSPierre Pronchery     ADD_TEST(test_null_args);
293*e7be843bSPierre Pronchery     ADD_TEST(pkcs12_parse_test);
294*e7be843bSPierre Pronchery     ADD_ALL_TESTS(pkcs12_create_ex2_test, 3);
295*e7be843bSPierre Pronchery     return 1;
296*e7be843bSPierre Pronchery }
297*e7be843bSPierre Pronchery 
cleanup_tests(void)298*e7be843bSPierre Pronchery void cleanup_tests(void)
299*e7be843bSPierre Pronchery {
300*e7be843bSPierre Pronchery     OSSL_LIB_CTX_free(testctx);
301*e7be843bSPierre Pronchery     OSSL_PROVIDER_unload(nullprov);
302*e7be843bSPierre Pronchery }
303