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