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