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