1 /*
2  * Copyright (c) 2011, Collabora Ltd.
3  * Copyright (c) 2019, Red Hat Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *     * Redistributions of source code must retain the above
10  *       copyright notice, this list of conditions and the
11  *       following disclaimer.
12  *     * Redistributions in binary form must reproduce the
13  *       above copyright notice, this list of conditions and
14  *       the following disclaimer in the documentation and/or
15  *       other materials provided with the distribution.
16  *     * The names of contributors to this software may not be
17  *       used to endorse or promote products derived from this
18  *       software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31  * DAMAGE.
32  *
33  * Authors: Stef Walter <stefw@collabora.co.uk>
34  *          Laszlo Ersek <lersek@redhat.com>
35  */
36 
37 #define P11_KIT_DISABLE_DEPRECATED
38 
39 #include "config.h"
40 
41 #include "test-trust.h" /* test_cacert3_ca_der */
42 
43 #include "attrs.h"      /* p11_attrs_build() */
44 #include "extract.h"    /* p11_extract_edk2_cacerts() */
45 #include "mock.h"       /* mock_module_reset() */
46 #include "pkcs11.h"     /* CK_FUNCTION_LIST */
47 #include "pkcs11x.h"    /* CKO_X_CERTIFICATE_EXTENSION */
48 #include "oid.h"        /* P11_OID_EXTENDED_KEY_USAGE */
49 #include "parser.h"
50 #include "test.h"       /* p11_test() */
51 
52 #include <stdarg.h>     /* va_list */
53 #include <stdio.h>      /* asprintf() */
54 #include <stdlib.h>     /* free() */
55 #include <string.h>     /* memcpy() */
56 
57 struct {
58 	CK_FUNCTION_LIST module;
59 	p11_enumerate ex;
60 	char *directory;
61 } test;
62 
63 static void
setup(void * unused)64 setup (void *unused)
65 {
66 	CK_RV rv;
67 
68 	mock_module_reset ();
69 	memcpy (&test.module, &mock_module, sizeof (CK_FUNCTION_LIST));
70 	rv = test.module.C_Initialize (NULL);
71 	assert_num_eq (CKR_OK, rv);
72 
73 	p11_enumerate_init (&test.ex);
74 	test.ex.flags |= P11_ENUMERATE_CORRELATE;
75 
76 	test.directory = p11_test_directory ("test-extract");
77 }
78 
79 static void
teardown(void * unused)80 teardown (void *unused)
81 {
82 	CK_RV rv;
83 
84 	p11_test_directory_delete (test.directory);
85 	free (test.directory);
86 
87 	p11_enumerate_cleanup (&test.ex);
88 	p11_kit_iter_free (test.ex.iter);
89 
90 	rv = test.module.C_Finalize (NULL);
91 	assert_num_eq (CKR_OK, rv);
92 }
93 
94 static CK_OBJECT_CLASS certificate_class = CKO_CERTIFICATE;
95 static CK_OBJECT_CLASS extension_class = CKO_X_CERTIFICATE_EXTENSION;
96 static CK_CERTIFICATE_TYPE x509_type = CKC_X_509;
97 static CK_BBOOL vtrue = CK_TRUE;
98 
99 static CK_ATTRIBUTE cacert3_authority_attrs[] = {
100 	{ CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
101 	{ CKA_CLASS, &certificate_class, sizeof (certificate_class) },
102 	{ CKA_CERTIFICATE_TYPE, &x509_type, sizeof (x509_type) },
103 	{ CKA_LABEL, "Custom Label", 12 },
104 	{ CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
105 	{ CKA_PUBLIC_KEY_INFO, (void *)test_cacert3_ca_public_key, sizeof (test_cacert3_ca_public_key) },
106 	{ CKA_TRUSTED, &vtrue, sizeof (vtrue) },
107 	{ CKA_INVALID },
108 };
109 
110 static CK_ATTRIBUTE verisign_v1_attrs[] = {
111 	{ CKA_VALUE, (void *)verisign_v1_ca, sizeof (verisign_v1_ca) },
112 	{ CKA_CLASS, &certificate_class, sizeof (certificate_class) },
113 	{ CKA_CERTIFICATE_TYPE, &x509_type, sizeof (x509_type) },
114 	{ CKA_LABEL, "Custom Label", 12 },
115 	{ CKA_SUBJECT, (void *)verisign_v1_ca_subject, sizeof (verisign_v1_ca_subject) },
116 	{ CKA_PUBLIC_KEY_INFO, (void *)verisign_v1_ca_public_key, sizeof (verisign_v1_ca_public_key) },
117 	{ CKA_TRUSTED, &vtrue, sizeof (vtrue) },
118 	{ CKA_INVALID },
119 };
120 
121 static CK_ATTRIBUTE extension_eku_server[] = {
122 	{ CKA_CLASS, &extension_class, sizeof (extension_class) },
123 	{ CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE, sizeof (P11_OID_EXTENDED_KEY_USAGE) },
124 	{ CKA_PUBLIC_KEY_INFO, (void *)test_cacert3_ca_public_key, sizeof (test_cacert3_ca_public_key) },
125 	{ CKA_VALUE, "\x30\x13\x06\x03\x55\x1d\x25\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x01", 21 },
126 	{ CKA_INVALID },
127 };
128 
129 static CK_ATTRIBUTE extension_reject_email[] = {
130 	{ CKA_CLASS, &extension_class, sizeof (extension_class) },
131 	{ CKA_OBJECT_ID, (void *)P11_OID_OPENSSL_REJECT, sizeof (P11_OID_OPENSSL_REJECT) },
132 	{ CKA_VALUE, "\x30\x1a\x06\x0a\x2b\x06\x01\x04\x01\x99\x77\x06\x0a\x01\x04\x0c\x30\x0a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x04", 28 },
133 	{ CKA_PUBLIC_KEY_INFO, (void *)test_cacert3_ca_public_key, sizeof (test_cacert3_ca_public_key) },
134 	{ CKA_INVALID },
135 };
136 
137 static CK_ATTRIBUTE certificate_filter[] = {
138 	{ CKA_CLASS, &certificate_class, sizeof (certificate_class) },
139 	{ CKA_INVALID },
140 };
141 
142 static void
setup_objects(const CK_ATTRIBUTE * attrs,...)143 setup_objects (const CK_ATTRIBUTE *attrs,
144                ...)
145 {
146 	static CK_ULONG id_value = 8888;
147 
148 	CK_ATTRIBUTE id = { CKA_ID, &id_value, sizeof (id_value) };
149 	CK_ATTRIBUTE *copy;
150 	va_list va;
151 
152 	va_start (va, attrs);
153 	while (attrs != NULL) {
154 		copy = p11_attrs_build (p11_attrs_dup (attrs), &id, NULL);
155 		assert (copy != NULL);
156 		mock_module_take_object (MOCK_SLOT_ONE_ID, copy);
157 		attrs = va_arg (va, const CK_ATTRIBUTE *);
158 	}
159 	va_end (va);
160 
161 	id_value++;
162 }
163 
164 static void
test_file_multiple(void)165 test_file_multiple (void)
166 {
167 	char *destination;
168 	bool ret;
169 
170 	setup_objects (cacert3_authority_attrs,
171 	               extension_eku_server,
172 	               extension_reject_email,
173 	               NULL);
174 
175 	setup_objects (verisign_v1_attrs,
176 	               NULL);
177 
178 	p11_kit_iter_add_filter (test.ex.iter, certificate_filter, 1);
179 	p11_kit_iter_begin_with (test.ex.iter, &test.module, 0, 0);
180 
181 	if (asprintf (&destination, "%s/%s", test.directory, "extract.jks") < 0)
182 		assert_not_reached ();
183 
184 	ret = p11_extract_jks_cacerts (&test.ex, destination);
185 	assert_num_eq (true, ret);
186 	free (destination);
187 
188 	test_check_file (test.directory, "extract.jks", SRCDIR "/trust/fixtures/multiple.jks");
189 }
190 
191 static void
test_file_duplicated(void)192 test_file_duplicated (void)
193 {
194 	char *destination;
195 	p11_parser *parser;
196 	p11_array *parsed;
197 	CK_ATTRIBUTE *duplicated1;
198 	CK_ATTRIBUTE *duplicated2;
199 	bool ret;
200 
201 	parser = p11_parser_new (NULL);
202 	assert_ptr_not_null (parser);
203 
204 	parsed = p11_parser_parsed (parser);
205 	assert_ptr_not_null (parsed);
206 
207 	p11_parser_formats (parser, p11_parser_format_x509, NULL);
208 
209 	ret = p11_parse_file (parser, SRCDIR "/trust/fixtures/duplicated1.der", NULL,
210 	                      P11_PARSE_FLAG_NONE);
211 
212 	assert_num_eq (1, parsed->num);
213 	duplicated1 = parsed->elem[0];
214 	parsed->elem[0] = NULL;
215 
216 	p11_parser_free (parser);
217 
218 	parser = p11_parser_new (NULL);
219 	assert_ptr_not_null (parser);
220 
221 	parsed = p11_parser_parsed (parser);
222 	assert_ptr_not_null (parsed);
223 
224 	p11_parser_formats (parser, p11_parser_format_x509, NULL);
225 
226 	ret = p11_parse_file (parser, SRCDIR "/trust/fixtures/duplicated2.der", NULL,
227 	                      P11_PARSE_FLAG_NONE);
228 
229 	assert_num_eq (1, parsed->num);
230 	duplicated2 = parsed->elem[0];
231 	parsed->elem[0] = NULL;
232 
233 	p11_parser_free (parser);
234 
235 	setup_objects (duplicated1, NULL);
236 	p11_attrs_free (duplicated1);
237 	setup_objects (duplicated2, NULL);
238 	p11_attrs_free (duplicated2);
239 
240 	p11_kit_iter_add_filter (test.ex.iter, certificate_filter, 1);
241 	p11_kit_iter_begin_with (test.ex.iter, &test.module, 0, 0);
242 
243 	if (asprintf (&destination, "%s/%s", test.directory, "extract.jks") < 0)
244 		assert_not_reached ();
245 
246 	ret = p11_extract_jks_cacerts (&test.ex, destination);
247 	assert_num_eq (true, ret);
248 	free (destination);
249 
250 	test_check_file (test.directory, "extract.jks", SRCDIR "/trust/fixtures/duplicated.jks");
251 }
252 
253 extern time_t _p11_extract_jks_timestamp;
254 
255 int
main(int argc,char * argv[])256 main (int argc,
257       char *argv[])
258 {
259 	mock_module_init ();
260 
261 	_p11_extract_jks_timestamp = 1514761200;
262 
263 	p11_fixture (setup, teardown);
264 	p11_test (test_file_multiple, "/jks/test_file_multiple");
265 	p11_test (test_file_duplicated, "/jks/test_file_duplicated");
266 
267 	return p11_test_run (argc, argv);
268 }
269 
270 #include "enumerate.c"    /* p11_enumerate_init() */
271 #include "extract-jks.c" /* p11_extract_jks_cacerts() */
272