1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <pthread.h>
28 #include <security/cryptoki.h>
29 #include "pkcs11Global.h"
30 #include "pkcs11Session.h"
31 #include "pkcs11Slot.h"
32 #include "metaGlobal.h"
33
34 /*
35 * C_OpenSession will need to create a pseudo session associated
36 * with the session created by the plugged in provider. Only
37 * minimal argument checking is done here, as we rely on the
38 * underlying provider to catch most errors.
39 */
40 CK_RV
C_OpenSession(CK_SLOT_ID slotID,CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession)41 C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
42 CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
43 {
44
45 CK_RV rv;
46 CK_SLOT_ID true_id;
47 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
48 CK_SESSION_HANDLE prov_sess;
49
50 if (!pkcs11_initialized) {
51 return (CKR_CRYPTOKI_NOT_INITIALIZED);
52 }
53
54 /* Check for a fastpath */
55 if (purefastpath || policyfastpath) {
56 if (metaslot_enabled) {
57 /*
58 * if metaslot is enabled and we are in fastpath
59 * mode, only one other slot is in the framework
60 * so, need to go to that slot's entry
61 * to look up the true slot ID for the slot
62 */
63 return (fast_funcs->C_OpenSession(TRUEID(slotID+1),
64 flags, pApplication, Notify, phSession));
65 } else {
66 return (fast_funcs->C_OpenSession(slotID, flags,
67 pApplication, Notify, phSession));
68 }
69 }
70
71
72 if (slotID == METASLOT_FRAMEWORK_ID) {
73 rv = meta_OpenSession(METASLOT_SLOTID, flags,
74 pApplication, Notify, &prov_sess);
75 } else {
76 /* Check that slotID is valid */
77 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id)
78 != CKR_OK) {
79 return (CKR_SLOT_ID_INVALID);
80 }
81 true_id = TRUEID(fw_st_id);
82 rv = FUNCLIST(fw_st_id)->C_OpenSession(true_id, flags,
83 pApplication, Notify, &prov_sess);
84 }
85
86 /* Present consistent interface for framework */
87 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
88 return (CKR_FUNCTION_FAILED);
89 } else if (rv != CKR_OK) {
90 /* could not create session with provider, return now */
91 return (rv);
92 }
93
94 /* Provider was successful, now create session in framework */
95 if (slotID == METASLOT_FRAMEWORK_ID) {
96 rv = pkcs11_session_add(
97 slottable->st_slots[METASLOT_FRAMEWORK_ID],
98 METASLOT_FRAMEWORK_ID, phSession, prov_sess);
99 } else {
100 rv = pkcs11_session_add(slottable->st_slots[fw_st_id],
101 fw_st_id, phSession, prov_sess);
102 }
103
104 if (rv != CKR_OK) {
105 /* Trouble in the framework, clean up provider session */
106 FUNCLIST(slotID)->C_CloseSession(prov_sess);
107 }
108 return (rv);
109 }
110
111 /*
112 * C_CloseSession will close a session with the underlying provider,
113 * and if that's successful will close it in the framework.
114 */
115 CK_RV
C_CloseSession(CK_SESSION_HANDLE hSession)116 C_CloseSession(CK_SESSION_HANDLE hSession)
117 {
118 CK_RV rv;
119 pkcs11_session_t *sessp;
120
121 /* Check for a fastpath */
122 if (purefastpath || policyfastpath) {
123 return (fast_funcs->C_CloseSession(hSession));
124 }
125
126 if (!pkcs11_initialized) {
127 return (CKR_CRYPTOKI_NOT_INITIALIZED);
128 }
129
130 /* Obtain the session pointer */
131 HANDLE2SESSION(hSession, sessp, rv);
132
133 if (rv != CKR_OK) {
134 return (rv);
135 }
136
137 /* Delete the session with the provider */
138 rv = FUNCLIST(sessp->se_slotid)->C_CloseSession(sessp->se_handle);
139
140 /* Present consistent interface for framework */
141 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
142 return (CKR_FUNCTION_FAILED);
143 } else if (rv != CKR_OK) {
144 /* could not delete session with provider, return now */
145 return (rv);
146 }
147
148 /* Delete session from the framework */
149 pkcs11_session_delete(slottable->st_slots[sessp->se_slotid], sessp);
150
151 return (rv);
152 }
153
154 /*
155 * C_CloseAllSessions will close all sessions associated with this
156 * slot with the underlying provider. If that is successful, will
157 * close the associated sessions in the framework. If the provider
158 * has not implemented C_CloseAllSessions, then we will loop through
159 * the list of sessions and individually call C_CloseSession.
160 */
161 CK_RV
C_CloseAllSessions(CK_SLOT_ID slotID)162 C_CloseAllSessions(CK_SLOT_ID slotID)
163 {
164
165 CK_RV rv, rv1;
166
167 CK_SLOT_ID true_id;
168 CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
169 pkcs11_session_t *sessp, *sess_nextp;
170 pkcs11_slot_t *slotp;
171
172 if (!pkcs11_initialized) {
173 return (CKR_CRYPTOKI_NOT_INITIALIZED);
174 }
175
176 /* Check for a fastpath */
177 if (purefastpath || policyfastpath) {
178 if (metaslot_enabled) {
179 /*
180 * if metaslot is enabled and we are in fastpath
181 * mode, only one other slot is in the framework
182 * so, need to go to that slot's entry
183 * to look up the true slot ID for the slot
184 */
185 return (fast_funcs->C_CloseAllSessions(
186 TRUEID(slotID+1)));
187 } else {
188 return (fast_funcs->C_CloseAllSessions(slotID));
189 }
190 }
191
192 /* Check that slotID is valid */
193 if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) {
194 return (CKR_SLOT_ID_INVALID);
195 }
196
197 slotp = slottable->st_slots[fw_st_id];
198 true_id = TRUEID(fw_st_id);
199
200 rv = FUNCLIST(fw_st_id)->C_CloseAllSessions(true_id);
201
202 /* Present consistent interface for framework */
203 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
204 /* Need to attempt to individually delete sessions */
205
206 /* reset rv */
207 rv = CKR_OK;
208
209 (void) pthread_mutex_lock(&slotp->sl_mutex);
210 sessp = slotp->sl_sess_list;
211
212 while (sessp) {
213 sess_nextp = sessp->se_next;
214
215 rv1 = FUNCLIST(fw_st_id)->
216 C_CloseSession(sessp->se_handle);
217
218 /* Record the first error encountered */
219 if ((rv == CKR_OK) && (rv1 != CKR_OK)) {
220 rv = rv1;
221 }
222
223 sessp = sess_nextp;
224 }
225
226 (void) pthread_mutex_unlock(&slotp->sl_mutex);
227 }
228
229 if (rv != CKR_OK) {
230 /* could not delete sessionlist with provider, return now */
231 return (rv);
232 }
233
234 /* Delete sessions from the framework */
235 pkcs11_sessionlist_delete(slotp);
236
237 return (rv);
238 }
239
240 /*
241 * C_GetSessionInfo is a pure wrapper to the underlying provider.
242 * The only argument checked is whether or not hSession is valid.
243 */
244 CK_RV
C_GetSessionInfo(CK_SESSION_HANDLE hSession,CK_SESSION_INFO_PTR pInfo)245 C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
246 {
247
248 CK_RV rv;
249 CK_SLOT_ID slot_id;
250 pkcs11_session_t *sessp;
251
252 /* Check for a fastpath */
253 if (purefastpath || policyfastpath) {
254 rv = fast_funcs->C_GetSessionInfo(hSession, pInfo);
255
256 /*
257 * If metaslot is enabled, and we are here, that
258 * that means there's only 1 other slot in the
259 * framework, and that slot should be hidden.
260 * so, override value of slot id to be metaslot's
261 * slot id.
262 */
263 if (metaslot_enabled) {
264 pInfo->slotID = METASLOT_FRAMEWORK_ID;
265 }
266 return (rv);
267 }
268
269 if (!pkcs11_initialized) {
270 return (CKR_CRYPTOKI_NOT_INITIALIZED);
271 }
272
273 /* Obtain the session pointer */
274 HANDLE2SESSION(hSession, sessp, rv);
275
276 if (rv != CKR_OK) {
277 return (rv);
278 }
279
280 /* Find the slot id for the framework */
281 slot_id = sessp->se_slotid;
282
283 /* Get session info from the provider */
284 rv = FUNCLIST(slot_id)->
285 C_GetSessionInfo(sessp->se_handle, pInfo);
286
287 /* Present consistent interface to the application */
288 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
289 return (CKR_FUNCTION_FAILED);
290 }
291
292 /* Override value of slot id to framework's */
293 pInfo->slotID = slot_id;
294
295 return (rv);
296 }
297
298 /*
299 * C_GetOperationState is a pure wrapper to the underlying provider.
300 * The only argument checked is whether or not hSession is valid.
301 */
302 CK_RV
C_GetOperationState(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pOperationState,CK_ULONG_PTR pulOperationStateLen)303 C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
304 CK_ULONG_PTR pulOperationStateLen)
305 {
306
307 CK_RV rv;
308 pkcs11_session_t *sessp;
309
310 /* Check for a fastpath */
311 if (purefastpath || policyfastpath) {
312 return (fast_funcs->C_GetOperationState(hSession,
313 pOperationState, pulOperationStateLen));
314 }
315
316 if (!pkcs11_initialized) {
317 return (CKR_CRYPTOKI_NOT_INITIALIZED);
318 }
319
320 /* Obtain the session pointer */
321 HANDLE2SESSION(hSession, sessp, rv);
322
323 if (rv != CKR_OK) {
324 return (rv);
325 }
326
327 /* Get the operation state with the provider */
328 rv = FUNCLIST(sessp->se_slotid)->C_GetOperationState(sessp->se_handle,
329 pOperationState, pulOperationStateLen);
330
331 /* Present consistent interface to the application */
332 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
333 return (CKR_FUNCTION_FAILED);
334 }
335
336 return (rv);
337 }
338
339
340 /*
341 * C_SetOperationState is a pure wrapper to the underlying provider.
342 * The only argument checked is whether or not hSession is valid.
343 */
344 CK_RV
C_SetOperationState(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pOperationState,CK_ULONG ulOperationStateLen,CK_OBJECT_HANDLE hEncryptionKey,CK_OBJECT_HANDLE hAuthenticationKey)345 C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
346 CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
347 CK_OBJECT_HANDLE hAuthenticationKey)
348 {
349 CK_RV rv;
350 pkcs11_session_t *sessp;
351
352 /* Check for a fastpath */
353 if (purefastpath || policyfastpath) {
354 return (fast_funcs->C_SetOperationState(hSession,
355 pOperationState, ulOperationStateLen,
356 hEncryptionKey, hAuthenticationKey));
357 }
358
359 if (!pkcs11_initialized) {
360 return (CKR_CRYPTOKI_NOT_INITIALIZED);
361 }
362
363 /* Obtain the session pointer */
364 HANDLE2SESSION(hSession, sessp, rv);
365
366 if (rv != CKR_OK) {
367 return (rv);
368 }
369
370 /* Set the operation state with the provider */
371 rv = FUNCLIST(sessp->se_slotid)->C_SetOperationState(sessp->se_handle,
372 pOperationState, ulOperationStateLen, hEncryptionKey,
373 hAuthenticationKey);
374
375 /* Present consistent interface to the application */
376 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
377 return (CKR_FUNCTION_FAILED);
378 }
379
380 return (rv);
381 }
382
383
384 /*
385 * C_Login is a pure wrapper to the underlying provider.
386 * The only argument checked is whether or not hSession is valid.
387 */
388 CK_RV
C_Login(CK_SESSION_HANDLE hSession,CK_USER_TYPE userType,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)389 C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
390 CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
391 {
392 CK_RV rv;
393 pkcs11_session_t *sessp;
394
395 /* Check for a fastpath */
396 if (purefastpath || policyfastpath) {
397 return (fast_funcs->C_Login(hSession, userType, pPin,
398 ulPinLen));
399 }
400
401 if (!pkcs11_initialized) {
402 return (CKR_CRYPTOKI_NOT_INITIALIZED);
403 }
404
405 /* Obtain the session pointer */
406 HANDLE2SESSION(hSession, sessp, rv);
407
408 if (rv != CKR_OK) {
409 return (rv);
410 }
411
412 /* Login with the provider */
413 rv = FUNCLIST(sessp->se_slotid)->C_Login(sessp->se_handle,
414 userType, pPin, ulPinLen);
415
416 /* Present consistent interface to the application */
417 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
418 return (CKR_FUNCTION_FAILED);
419 }
420
421 return (rv);
422 }
423
424 /*
425 * C_Logout is a pure wrapper to the underlying provider.
426 * The only argument checked is whether or not hSession is valid.
427 */
428 CK_RV
C_Logout(CK_SESSION_HANDLE hSession)429 C_Logout(CK_SESSION_HANDLE hSession)
430 {
431 CK_RV rv;
432 pkcs11_session_t *sessp;
433
434 /* Check for a fastpath */
435 if (purefastpath || policyfastpath) {
436 return (fast_funcs->C_Logout(hSession));
437 }
438
439 if (!pkcs11_initialized) {
440 return (CKR_CRYPTOKI_NOT_INITIALIZED);
441 }
442
443 /* Obtain the session pointer */
444 HANDLE2SESSION(hSession, sessp, rv);
445
446 if (rv != CKR_OK) {
447 return (rv);
448 }
449
450 rv = FUNCLIST(sessp->se_slotid)->C_Logout(sessp->se_handle);
451
452 /* Present consistent interface to the application */
453 if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
454 return (CKR_FUNCTION_FAILED);
455 }
456
457 return (rv);
458 }
459