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