Home | History | Annotate | Download | only in common
      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
     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
    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
    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
    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
    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
    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
    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
    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