xref: /openssl/test/pkcs12_api_test.c (revision da1c088f)
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