1 /*
2 * Copyright (c) 2012 Red Hat Inc
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
11 * * Redistributions in binary form must reproduce the
12 * above copyright notice, this list of conditions and
13 * the following disclaimer in the documentation and/or
14 * other materials provided with the distribution.
15 * * The names of contributors to this software may not be
16 * used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
29 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30 * DAMAGE.
31 *
32 * Author: Stef Walter <stefw@redhat.com>
33 */
34
35 #include "config.h"
36 #include "test.h"
37
38 #include "dict.h"
39 #include "library.h"
40 #include "mock.h"
41 #include "modules.h"
42 #include "p11-kit.h"
43 #include "virtual.h"
44 #include "virtual-fixed.h"
45
46 #include <sys/types.h>
47 #ifdef OS_UNIX
48 #include <sys/wait.h>
49 #include <unistd.h>
50 #endif
51 #include <errno.h>
52 #include <stdlib.h>
53 #include <stdio.h>
54 #include <string.h>
55
56 static CK_FUNCTION_LIST_PTR
setup_mock_module(CK_SESSION_HANDLE * session)57 setup_mock_module (CK_SESSION_HANDLE *session)
58 {
59 CK_FUNCTION_LIST_PTR module = NULL;
60 CK_RV rv;
61
62 p11_lock ();
63
64 rv = p11_module_load_inlock_reentrant (&mock_module, 0, &module);
65
66 p11_unlock ();
67
68 if (rv == CKR_OK) {
69 assert_ptr_not_null (module);
70 assert (p11_virtual_is_wrapper (module));
71 } else {
72 assert_ptr_eq (NULL, module);
73 return NULL;
74 }
75
76 rv = p11_kit_module_initialize (module);
77 assert (rv == CKR_OK);
78
79 if (session) {
80 rv = (module->C_OpenSession) (MOCK_SLOT_ONE_ID,
81 CKF_RW_SESSION | CKF_SERIAL_SESSION,
82 NULL, NULL, session);
83 assert (rv == CKR_OK);
84 }
85
86 return module;
87 }
88
89 static void
teardown_mock_module(CK_FUNCTION_LIST_PTR module)90 teardown_mock_module (CK_FUNCTION_LIST_PTR module)
91 {
92 CK_RV rv;
93
94 rv = p11_kit_module_finalize (module);
95 assert (rv == CKR_OK);
96
97 p11_lock ();
98
99 rv = p11_module_release_inlock_reentrant (module);
100 assert (rv == CKR_OK);
101
102 p11_unlock ();
103 }
104
105 static CK_RV
fail_C_Initialize(void * init_reserved)106 fail_C_Initialize (void *init_reserved)
107 {
108 return CKR_FUNCTION_FAILED;
109 }
110
111 static void
test_initialize_finalize(void)112 test_initialize_finalize (void)
113 {
114 CK_FUNCTION_LIST_PTR module;
115 CK_RV rv;
116
117 p11_lock ();
118
119 rv = p11_module_load_inlock_reentrant (&mock_module, 0, &module);
120 assert (rv == CKR_OK);
121 assert_ptr_not_null (module);
122 assert (p11_virtual_is_wrapper (module));
123
124 p11_unlock ();
125
126 rv = module->C_Initialize (NULL);
127 assert (rv == CKR_OK);
128
129 rv = module->C_Initialize (NULL);
130 assert (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED);
131
132 rv = module->C_Finalize (NULL);
133 assert (rv == CKR_OK);
134
135 rv = module->C_Finalize (NULL);
136 assert (rv == CKR_CRYPTOKI_NOT_INITIALIZED);
137
138 p11_lock ();
139
140 rv = p11_module_release_inlock_reentrant (module);
141 assert (rv == CKR_OK);
142
143 p11_unlock ();
144 }
145
146 static void
test_initialize_fail(void)147 test_initialize_fail (void)
148 {
149 CK_FUNCTION_LIST_PTR module;
150 CK_FUNCTION_LIST base;
151 CK_RV rv;
152
153 memcpy (&base, &mock_module, sizeof (CK_FUNCTION_LIST));
154 base.C_Initialize = fail_C_Initialize;
155
156 p11_lock ();
157
158 rv = p11_module_load_inlock_reentrant (&base, 0, &module);
159 assert (rv == CKR_OK);
160
161 p11_unlock ();
162
163 rv = p11_kit_module_initialize (module);
164 assert (rv == CKR_FUNCTION_FAILED);
165 }
166
167 static void
test_separate_close_all_sessions(void)168 test_separate_close_all_sessions (void)
169 {
170 CK_FUNCTION_LIST *first;
171 CK_FUNCTION_LIST *second;
172 CK_SESSION_HANDLE s1;
173 CK_SESSION_HANDLE s2;
174 CK_SESSION_INFO info;
175 CK_RV rv;
176
177 first = setup_mock_module (&s1);
178 assert_ptr_not_null (first);
179 second = setup_mock_module (&s2);
180 assert_ptr_not_null (second);
181
182 rv = first->C_GetSessionInfo (s1, &info);
183 assert (rv == CKR_OK);
184
185 rv = second->C_GetSessionInfo (s2, &info);
186 assert (rv == CKR_OK);
187
188 first->C_CloseAllSessions (MOCK_SLOT_ONE_ID);
189 assert (rv == CKR_OK);
190
191 rv = first->C_GetSessionInfo (s1, &info);
192 assert (rv == CKR_SESSION_HANDLE_INVALID);
193
194 rv = second->C_GetSessionInfo (s2, &info);
195 assert (rv == CKR_OK);
196
197 second->C_CloseAllSessions (MOCK_SLOT_ONE_ID);
198 assert (rv == CKR_OK);
199
200 rv = first->C_GetSessionInfo (s1, &info);
201 assert (rv == CKR_SESSION_HANDLE_INVALID);
202
203 rv = second->C_GetSessionInfo (s2, &info);
204 assert (rv == CKR_SESSION_HANDLE_INVALID);
205
206 teardown_mock_module (first);
207 teardown_mock_module (second);
208 }
209
210 #define MAX_MODS (P11_VIRTUAL_MAX_FIXED+10)
211 static void
test_max_session_load(void)212 test_max_session_load (void)
213 {
214 CK_FUNCTION_LIST *list[MAX_MODS];
215 CK_SESSION_HANDLE s1;
216 CK_SESSION_INFO info;
217 CK_RV rv;
218 unsigned i;
219 unsigned registered = 0;
220
221 for (i = 0; i < MAX_MODS; i++) {
222 list[i] = setup_mock_module (&s1);
223 if (list[i] != NULL)
224 registered++;
225 }
226
227 assert_num_cmp (registered + 1, >=, P11_VIRTUAL_MAX_FIXED);
228
229 for (i = 0; i < registered; i++) {
230 rv = list[i]->C_GetSessionInfo (s1, &info);
231 assert (rv == CKR_OK);
232
233 list[i]->C_CloseAllSessions (MOCK_SLOT_ONE_ID);
234 assert (rv == CKR_OK);
235 }
236
237 for (i = 0; i < registered; i++) {
238 teardown_mock_module (list[i]);
239 }
240 }
241
242 #ifdef OS_UNIX
243
244 static void
test_fork_and_reinitialize(void)245 test_fork_and_reinitialize (void)
246 {
247 CK_FUNCTION_LIST *module;
248 CK_INFO info;
249 int status;
250 CK_RV rv;
251 pid_t pid;
252 int i;
253
254 module = setup_mock_module (NULL);
255 assert_ptr_not_null (module);
256
257 pid = fork ();
258 assert_num_cmp (pid, >=, 0);
259
260 /* The child */
261 if (pid == 0) {
262 rv = (module->C_Initialize) (NULL);
263 assert_num_eq (CKR_OK, rv);
264
265 for (i = 0; i < 32; i++) {
266 rv = (module->C_GetInfo) (&info);
267 assert_num_eq (CKR_OK, rv);
268 }
269
270 rv = (module->C_Finalize) (NULL);
271 assert_num_eq (CKR_OK, rv);
272
273 _exit (66);
274 }
275
276 for (i = 0; i < 128; i++) {
277 rv = (module->C_GetInfo) (&info);
278 assert_num_eq (CKR_OK, rv);
279 }
280
281 assert_num_eq (waitpid (pid, &status, 0), pid);
282 assert_num_eq (WEXITSTATUS (status), 66);
283
284 teardown_mock_module (module);
285 }
286
287 #endif /* OS_UNIX */
288
289 /* Bring in all the mock module tests */
290 #include "test-mock.c"
291
292 int
main(int argc,char * argv[])293 main (int argc,
294 char *argv[])
295 {
296 mock_module_init ();
297 p11_library_init ();
298
299 p11_test (test_initialize_finalize, "/managed/test_initialize_finalize");
300 p11_test (test_initialize_fail, "/managed/test_initialize_fail");
301 p11_test (test_separate_close_all_sessions, "/managed/test_separate_close_all_sessions");
302 p11_test (test_max_session_load, "/managed/test_max_session_load");
303
304 #ifdef OS_UNIX
305 p11_test (test_fork_and_reinitialize, "/managed/fork-and-reinitialize");
306 #endif
307
308 test_mock_add_tests ("/managed");
309
310 p11_kit_be_quiet ();
311
312 return p11_test_run (argc, argv);
313 }
314