xref: /freebsd/crypto/openssl/test/pkcs12_api_test.c (revision 10a428653ee7216475f1ddce3fb4cbf1200319f8)
1 /*
2  * Copyright 2022-2026 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 
test_PKCS12_set_pbmac1_pbkdf2_invalid_saltlen(void)256 static int test_PKCS12_set_pbmac1_pbkdf2_invalid_saltlen(void)
257 {
258     int ret = 0;
259     unsigned char salt[8] = { 0 };
260     EVP_PKEY *key = NULL;
261     X509 *cert = NULL;
262     STACK_OF(X509) *ca = NULL;
263     PKCS12 *p12 = NULL;
264 
265     if (!TEST_ptr(p12 = PKCS12_load(in_file)))
266         return 0;
267     if (!TEST_true(PKCS12_parse(p12, in_pass, &key, &cert, &ca)))
268         goto err;
269     PKCS12_free(p12);
270 
271     if (!TEST_ptr(p12 = PKCS12_create_ex2("pass", NULL, key, cert, ca,
272                       NID_undef, NID_undef, 0, -1, 0,
273                       testctx, NULL, NULL, NULL)))
274         goto err;
275     ret = TEST_false(PKCS12_set_pbmac1_pbkdf2(p12, "pass", -1,
276         salt, -1, 0, NULL, NULL));
277 err:
278     PKCS12_free(p12);
279     EVP_PKEY_free(key);
280     X509_free(cert);
281     OSSL_STACK_OF_X509_free(ca);
282     return ret;
283 }
284 
setup_tests(void)285 int setup_tests(void)
286 {
287     OPTION_CHOICE o;
288 
289     while ((o = opt_next()) != OPT_EOF) {
290         switch (o) {
291         case OPT_IN_FILE:
292             in_file = opt_arg();
293             break;
294         case OPT_IN_PASS:
295             in_pass = opt_arg();
296             break;
297         case OPT_LEGACY:
298             break;
299         case OPT_IN_HAS_KEY:
300             has_key = opt_int_arg();
301             break;
302         case OPT_IN_HAS_CERT:
303             has_cert = opt_int_arg();
304             break;
305         case OPT_IN_HAS_CA:
306             has_ca = opt_int_arg();
307             break;
308         case OPT_TEST_CASES:
309             break;
310         default:
311             return 0;
312         }
313     }
314 
315     if (!test_get_libctx(&testctx, &nullprov, NULL, NULL, NULL)) {
316         OSSL_LIB_CTX_free(testctx);
317         testctx = NULL;
318         return 0;
319     }
320 
321     ADD_TEST(test_null_args);
322     ADD_TEST(pkcs12_parse_test);
323     ADD_ALL_TESTS(pkcs12_create_ex2_test, 3);
324     ADD_TEST(test_PKCS12_set_pbmac1_pbkdf2_invalid_saltlen);
325     return 1;
326 }
327 
cleanup_tests(void)328 void cleanup_tests(void)
329 {
330     OSSL_LIB_CTX_free(testctx);
331     OSSL_PROVIDER_unload(nullprov);
332 }
333