CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { kms_session_t *session_p; CK_RV rv; boolean_t ses_lock_held = B_FALSE; if (!kms_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (pInfo == NULL) return (CKR_ARGUMENTS_BAD); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* Provide information for the specified session */ pInfo->slotID = session_p->ses_slotid; pInfo->flags = session_p->flags; pInfo->ulDeviceError = 0; pInfo->state = get_ses_state(session_p); /* * Decrement the session reference count. */ REFRELE(session_p, ses_lock_held); return (rv); }
CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { soft_session_t *session_p; CK_RV rv; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if ((pOperationState == NULL_PTR) || (ulOperationStateLen == 0)) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } rv = soft_set_operationstate(session_p, pOperationState, ulOperationStateLen, hEncryptionKey, hAuthenticationKey); clean_exit: SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv; cpk_session_t *session_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obatin the session pointer */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pData == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* Application must call C_VerifyInit before calling C_Verify. */ if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } /* * C_Verify must be called without intervening C_VerifyUpdate * calls. */ if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) { /* * C_Verify can not be used to terminate a multi-part * operation, so we'll leave the active verify operation * flag on and let the application continue with the * verify update operation. */ SES_REFRELE(session_p, lock_held); return (CKR_FUNCTION_FAILED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_verify(session_p, pData, ulDataLen, pSignature, ulSignatureLen); clean_exit: /* Clear context, free key, and release session counter */ cpk_sign_verify_cleanup(session_p, B_FALSE, B_FALSE); return (rv); }
CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { CK_RV rv; cpk_session_t *session_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (ulPartLen == 0) { SES_REFRELE(session_p, lock_held); return (CKR_OK); } if (pPart == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* * Application must call C_SignInit before calling * C_SignUpdate. */ if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } session_p->sign.flags |= CRYPTO_OPERATION_UPDATE; (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_sign_update(session_p, pPart, ulPartLen); if (rv == CKR_OK) { SES_REFRELE(session_p, lock_held); return (rv); } clean_exit: /* After error, clear context, free key, & release session counter */ cpk_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); return (rv); }
CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; cpk_session_t *session_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pulSignatureLen == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* * Application must call C_SignInit before calling * C_SignFinal. */ if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_sign_final(session_p, pSignature, pulSignatureLen); if ((rv == CKR_BUFFER_TOO_SMALL) || (pSignature == NULL && rv == CKR_OK)) { /* * We will not terminate the active sign operation flag, * when the application-supplied buffer is too small, or * the application asks for the length of buffer to hold * the signature. */ SES_REFRELE(session_p, lock_held); return (rv); } clean_exit: /* Clear contexts, free key, and release session counter */ cpk_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); return (rv); }
CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv; cpk_session_t *session_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pData == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } if (pulEncryptedDataLen == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } if (session_p->encrypt.flags & CRYPTO_OPERATION_UPDATE) { SES_REFRELE(session_p, lock_held); return (CKR_FUNCTION_FAILED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_encrypt(session_p, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); if ((rv == CKR_BUFFER_TOO_SMALL) || (pEncryptedData == NULL && rv == CKR_OK)) { SES_REFRELE(session_p, lock_held); return (rv); } clean_exit: cpk_crypt_cleanup(session_p, B_TRUE, B_FALSE); return (rv); }
CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; cpk_session_t *session_p; cpk_object_t *key_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pMechanism == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } HANDLE2OBJECT(hKey, key_p, rv); if (rv != CKR_OK) goto clean_exit; (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) { cpk_crypt_cleanup(session_p, B_TRUE, lock_held); } session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE; (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_encrypt_init(session_p, pMechanism, key_p); if (rv != CKR_OK) { (void) pthread_mutex_lock(&session_p->session_mutex); session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE; lock_held = B_TRUE; } OBJ_REFRELE(key_p); clean_exit: SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { CK_RV rv; kms_session_t *session_p; boolean_t ses_lock_held = B_FALSE; if (!kms_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); (void) pthread_mutex_lock(&session_p->session_mutex); ses_lock_held = B_TRUE; /* * Set SESSION_IS_CLOSING flag so any access to this * session will be rejected. */ if (session_p->ses_close_sync & SESSION_IS_CLOSING) { REFRELE(session_p, ses_lock_held); return (CKR_SESSION_CLOSED); } session_p->ses_close_sync |= SESSION_IS_CLOSING; /* * Decrement the session reference count. * We hold the session lock, and REFRELE() * will release the session lock for us. */ REFRELE(session_p, ses_lock_held); /* * Delete a session by calling kms_delete_session() with * a session pointer and two boolean arguments. The 3rd argument * boolean value FALSE indicates that the caller does not * hold the slot lock. The 4th argument boolean value B_FALSE * indicates that we want to delete all the objects completely. * * kms_delete_session() will reset SESSION_IS_CLOSING * flag after it is done. */ kms_delete_session(session_p, B_FALSE, B_FALSE); return (rv); }
CK_RV C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) { soft_session_t *session_p; CK_RV rv; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (!soft_keystore_status(KEYSTORE_LOAD)) { SES_REFRELE(session_p, lock_held); return (CKR_DEVICE_REMOVED); } if ((ulOldPinLen < MIN_PIN_LEN) || (ulOldPinLen > MAX_PIN_LEN) || (ulNewPinLen < MIN_PIN_LEN) ||(ulNewPinLen > MAX_PIN_LEN)) { SES_REFRELE(session_p, lock_held); return (CKR_PIN_LEN_RANGE); } if ((pOldPin == NULL_PTR) || (pNewPin == NULL_PTR)) { /* * We don't support CKF_PROTECTED_AUTHENTICATION_PATH */ SES_REFRELE(session_p, lock_held); return (CKR_ARGUMENTS_BAD); } /* check the state of the session */ if ((session_p->state != CKS_RW_PUBLIC_SESSION) && (session_p->state != CKS_RW_USER_FUNCTIONS)) { SES_REFRELE(session_p, lock_held); return (CKR_SESSION_READ_ONLY); } rv = soft_setpin(pOldPin, ulOldPinLen, pNewPin, ulNewPinLen); SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_Logout(CK_SESSION_HANDLE hSession) { CK_RV rv = CKR_OK; kms_session_t *session_p; kms_slot_t *pslot; boolean_t ses_lock_held = B_FALSE; if (!kms_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* Acquire the slot lock. */ pslot = get_slotinfo(); (void) pthread_mutex_lock(&pslot->sl_mutex); /* Check if the user or SO was logged in */ if (pslot->sl_state == CKU_PUBLIC) { rv = CKR_USER_NOT_LOGGED_IN; goto clean_exit; } KMS_UnloadProfile(&session_p->kmsProfile); /* * If this slot was logged in as USER previously, we need to clean up * all private object wrappers in library for this slot. */ kms_cleanup_pri_objects_in_slot(pslot, session_p); if (rv == CKR_OK) { /* Reset the slot's session state. */ pslot->sl_state = CKU_PUBLIC; } clean_exit: REFRELE(session_p, ses_lock_held); (void) pthread_mutex_unlock(&pslot->sl_mutex); return (rv); }
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { soft_session_t *session_p; CK_RV rv; boolean_t lock_held = B_TRUE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pInfo == NULL) { lock_held = B_FALSE; rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); /* Provide information for the specified session */ pInfo->slotID = SOFTTOKEN_SLOTID; pInfo->state = session_p->state; pInfo->flags = session_p->flags; pInfo->ulDeviceError = 0; clean_exit: /* * Decrement the session reference count. * We hold the session lock, and SES_REFRELE() * will release the session lock for us. */ SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_RV rv; cpk_session_t *session_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* * Application must call C_VerifyInit before calling * C_VerifyFinal. */ if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_verify_final(session_p, pSignature, ulSignatureLen); /* Clear contexts, free key, and release session counter */ cpk_sign_verify_cleanup(session_p, B_FALSE, B_FALSE); return (rv); }
CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { soft_session_t *session_p; CK_RV rv; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* * Only check if pulOperationStateLen is NULL_PTR. * No need to check if pOperationState is NULL_PTR because * application might just ask for the length of buffer to hold * the OperationState. */ if (pulOperationStateLen == NULL_PTR) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } rv = soft_get_operationstate(session_p, pOperationState, pulOperationStateLen); clean_exit: SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; soft_session_t *session_p; soft_object_t *key_p; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pMechanism == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } /* Obtain the object pointer. */ HANDLE2OBJECT(hKey, key_p, rv); if (rv != CKR_OK) goto clean_exit; /* Check to see if key object allows for encryption. */ if (!(key_p->bool_attr_mask & ENCRYPT_BOOL_ON)) { rv = CKR_KEY_FUNCTION_NOT_PERMITTED; goto clean_exit1; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* Check to see if encrypt operation is already active. */ if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) { /* free the memory to avoid memory leak */ soft_crypt_cleanup(session_p, B_TRUE, lock_held); } /* * This active flag will remain ON until application calls either * C_Encrypt or C_EncryptFinal to actually obtain the final piece * of ciphertext. */ session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE; (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = soft_encrypt_init(session_p, pMechanism, key_p); if (rv != CKR_OK) { (void) pthread_mutex_lock(&session_p->session_mutex); session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE; lock_held = B_TRUE; } clean_exit1: OBJ_REFRELE(key_p); clean_exit: SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { CK_RV rv; soft_session_t *session_p; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pulLastEncryptedPartLen == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* * Application must call C_EncryptInit before calling * C_EncryptFinal. */ if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = soft_encrypt_final(session_p, pLastEncryptedPart, pulLastEncryptedPartLen); if ((rv == CKR_BUFFER_TOO_SMALL) || (pLastEncryptedPart == NULL && rv == CKR_OK)) { /* * We will not terminate the active encrypt operation flag, * when the application-supplied buffer is too small, or * the application asks for the length of buffer to hold * the ciphertext. */ SES_REFRELE(session_p, lock_held); return (rv); } /* Terminates the active encrypt operation. */ (void) pthread_mutex_lock(&session_p->session_mutex); session_p->encrypt.flags = 0; lock_held = B_TRUE; SES_REFRELE(session_p, lock_held); return (rv); clean_exit: /* Terminates the active encrypt operation. */ soft_crypt_cleanup(session_p, B_TRUE, lock_held); return (rv); }
CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_RV rv; soft_session_t *session_p; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* * Only check if input buffer is null. How to handle zero input * length depends on the mechanism in use. For secret key mechanisms, * unpadded ones yeild zero length output, but padded ones always * result in greater than zero length output. */ if (pPart == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } /* * Only check if pulEncryptedPartLen is NULL. * No need to check if pEncryptedPart is NULL because * application might just ask for the length of buffer to hold * the ciphertext. */ if (pulEncryptedPartLen == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* * Application must call C_EncryptInit before calling * C_EncryptUpdate. */ if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } session_p->encrypt.flags |= CRYPTO_OPERATION_UPDATE; (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = soft_encrypt_update(session_p, pPart, ulPartLen, pEncryptedPart, pulEncryptedPartLen); /* * If CKR_OK or CKR_BUFFER_TOO_SMALL, don't terminate the * current encryption operation. */ if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL)) { SES_REFRELE(session_p, lock_held); return (rv); } clean_exit: /* * After an error occurred, terminate the current encrypt * operation by resetting the active and update flags. */ soft_crypt_cleanup(session_p, B_TRUE, lock_held); return (rv); }
CK_RV C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_RV rv; soft_session_t *session_p; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* * Only check if input buffer is null. How to handle zero input * length depends on the mechanism in use. For secret key mechanisms, * unpadded ones yield zero length output, but padded ones always * result in greater than zero length output. */ if (pData == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } /* * Only check if pulEncryptedDataLen is NULL. * No need to check if pEncryptedData is NULL because * application might just ask for the length of buffer to hold * the ciphertext. */ if (pulEncryptedDataLen == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* Application must call C_EncryptInit before calling C_Encrypt. */ if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } /* * C_Encrypt must be called without intervening C_EncryptUpdate * calls. */ if (session_p->encrypt.flags & CRYPTO_OPERATION_UPDATE) { /* * C_Encrypt can not be used to terminate a multi-part * operation, so we'll leave the active encrypt operation * flag on and let the application continue with the * encrypt update operation. */ SES_REFRELE(session_p, lock_held); return (CKR_FUNCTION_FAILED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = soft_encrypt(session_p, pData, ulDataLen, pEncryptedData, pulEncryptedDataLen); if ((rv == CKR_BUFFER_TOO_SMALL) || (pEncryptedData == NULL && rv == CKR_OK)) { /* * We will not terminate the active encrypt operation flag, * when the application-supplied buffer is too small, or * the application asks for the length of buffer to hold * the ciphertext. */ SES_REFRELE(session_p, lock_held); return (rv); } clean_exit: /* Clear context, free key, and release session counter */ soft_crypt_cleanup(session_p, B_TRUE, B_FALSE); return (rv); }
CK_RV C_Logout(CK_SESSION_HANDLE hSession) { soft_session_t *session_p, *sp; CK_RV rv; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); (void) pthread_mutex_lock(&soft_giant_mutex); if (!soft_slot.authenticated) { if (!soft_slot.userpin_change_needed) { /* * Only if the PIN has been initialized in the keystore. */ (void) pthread_mutex_unlock(&soft_giant_mutex); SES_REFRELE(session_p, lock_held); return (CKR_USER_NOT_LOGGED_IN); } else { soft_slot.userpin_change_needed = 0; (void) pthread_mutex_unlock(&soft_giant_mutex); SES_REFRELE(session_p, lock_held); return (CKR_OK); } } soft_logout(); soft_slot.authenticated = 0; (void) pthread_mutex_unlock(&soft_giant_mutex); /* Acquire the global session list lock */ (void) pthread_mutex_lock(&soft_sessionlist_mutex); sp = soft_session_list; while (sp) { (void) pthread_mutex_lock(&sp->session_mutex); if (sp->flags & CKF_RW_SESSION) { sp->state = CKS_RW_PUBLIC_SESSION; } else { sp->state = CKS_RO_PUBLIC_SESSION; } (void) pthread_mutex_unlock(&sp->session_mutex); sp = sp->next; } (void) pthread_mutex_unlock(&soft_sessionlist_mutex); SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv = CKR_OK; kernel_session_t *session_p; kernel_object_t *basekey_p; kernel_object_t *new_objp; kernel_slot_t *pslot; boolean_t ses_lock_held = B_FALSE; CK_BBOOL is_pri_obj; CK_BBOOL is_token_obj = FALSE; crypto_mech_type_t k_mech_type; crypto_derive_key_t obj_dk; int r; if (!kernel_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pMechanism == NULL) { REFRELE(session_p, ses_lock_held); return (CKR_ARGUMENTS_BAD); } if ((pTemplate == NULL && ulAttributeCount != 0) || (pTemplate != NULL && ulAttributeCount == 0)) { REFRELE(session_p, ses_lock_held); return (CKR_ARGUMENTS_BAD); } /* Obtain the base key object pointer. */ HANDLE2OBJECT(hBaseKey, basekey_p, rv); if (rv != CKR_OK) { REFRELE(session_p, ses_lock_held); return (rv); } /* Get the kernel's internal mechanism number. */ rv = kernel_mech(pMechanism->mechanism, &k_mech_type); if (rv != CKR_OK) { goto failed_exit; } /* Create an object wrapper in the library for the generated key. */ new_objp = calloc(1, sizeof (kernel_object_t)); if (new_objp == NULL) { rv = CKR_HOST_MEMORY; goto failed_exit; } /* Process the attributes */ rv = process_object_attributes(pTemplate, ulAttributeCount, &obj_dk.dk_attributes, &is_token_obj); if (rv != CKR_OK) { goto failed_exit; } /* Cannot create a token object with a READ-ONLY session. */ if (is_token_obj && session_p->ses_RO) { free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); rv = CKR_SESSION_READ_ONLY; goto failed_exit; } /* Call the CRYPTO_DERIVE_KEY ioctl */ obj_dk.dk_session = session_p->k_session; obj_dk.dk_mechanism.cm_type = k_mech_type; obj_dk.dk_mechanism.cm_param = pMechanism->pParameter; obj_dk.dk_mechanism.cm_param_len = pMechanism->ulParameterLen; obj_dk.dk_base_key.ck_format = CRYPTO_KEY_REFERENCE; obj_dk.dk_base_key.ck_obj_id = basekey_p->k_handle; obj_dk.dk_count = ulAttributeCount; while ((r = ioctl(kernel_fd, CRYPTO_DERIVE_KEY, &obj_dk)) < 0) { if (errno != EINTR) break; } if (r < 0) { rv = CKR_FUNCTION_FAILED; } else { rv = crypto2pkcs11_error_number(obj_dk.dk_return_value); } free_object_attributes(obj_dk.dk_attributes, ulAttributeCount); if (rv != CKR_OK) { goto failed_exit; } /* Get the CKA_PRIVATE value for the derived key. */ rv = get_cka_private_value(session_p, obj_dk.dk_object_handle, &is_pri_obj); if (rv != CKR_OK) { goto failed_exit; } /* * Store the kernel object handle into the new derived key object * and finish the object initialization. */ new_objp->is_lib_obj = B_FALSE; new_objp->k_handle = obj_dk.dk_object_handle; new_objp->session_handle = (CK_SESSION_HANDLE)session_p; new_objp->extra_attrlistp = NULL; if (is_pri_obj) new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; else new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; if (is_token_obj) new_objp->bool_attr_mask |= TOKEN_BOOL_ON; else new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; (void) pthread_mutex_init(&new_objp->object_mutex, NULL); new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; /* * Add the new derived object to the slot's token list if it is a * token object. Otherwise, add it to the session's object list. */ if (is_token_obj) { pslot = slot_table[session_p->ses_slotid]; kernel_add_token_object_to_slot(new_objp, pslot); } else { kernel_add_object_to_session(new_objp, session_p); } *phKey = (CK_OBJECT_HANDLE)new_objp; OBJ_REFRELE(basekey_p); REFRELE(session_p, ses_lock_held); return (rv); failed_exit: OBJ_REFRELE(basekey_p); if (new_objp != NULL) { (void) free(new_objp); } REFRELE(session_p, ses_lock_held); return (rv); }
CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_RV rv = CKR_OK; kernel_session_t *session_p; kernel_object_t *unwrappingkey_p; kernel_object_t *new_objp = NULL; kernel_slot_t *pslot; boolean_t ses_lock_held = B_FALSE; CK_BBOOL is_pri_obj; CK_BBOOL is_token_obj = FALSE; CK_MECHANISM_INFO info; uint32_t k_mi_flags; CK_BYTE *clear_key_val = NULL; CK_ULONG ulDataLen; CK_ATTRIBUTE_PTR newTemplate = NULL; CK_ULONG templ_size; crypto_mech_type_t k_mech_type; crypto_object_unwrap_key_t obj_unwrapkey; int r; if (!kernel_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (pMechanism == NULL || pWrappedKey == NULL || phKey == NULL) { return (CKR_ARGUMENTS_BAD); } if ((pTemplate == NULL) && (ulAttributeCount != 0)) { return (CKR_ARGUMENTS_BAD); } /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* Obtain the wrapping key object pointer. */ HANDLE2OBJECT(hUnwrappingKey, unwrappingkey_p, rv); if (rv != CKR_OK) { REFRELE(session_p, ses_lock_held); return (rv); } /* * If the HW provider doesn't support C_UnwrapKey, we will try * to emulate it in the library. */ pslot = slot_table[session_p->ses_slotid]; if ((pslot->sl_func_list.fl_object_create == B_FALSE) && (pslot->sl_func_list.fl_key_unwrap == B_FALSE)) { rv = get_mechanism_info(pslot, pMechanism->mechanism, &info, &k_mi_flags); if (rv != CKR_OK) { goto failed_exit; } /* * If the mechanism flag doesn't have CKF_UNWRAP, and it's * an unwrapping of a secret key object, then help this * out with a decryption followed by an object creation. */ if (!(k_mi_flags & CRYPTO_FG_UNWRAP) && (k_mi_flags & CRYPTO_FG_DECRYPT) && (is_secret_key_template(pTemplate, ulAttributeCount))) { /* First allocate space for the recovered key value */ clear_key_val = malloc(ulWrappedKeyLen); if (clear_key_val == NULL) { rv = CKR_HOST_MEMORY; goto failed_exit; } rv = kernel_decrypt_init(session_p, unwrappingkey_p, pMechanism); if (rv != CKR_OK) { goto failed_exit; } ulDataLen = ulWrappedKeyLen; rv = kernel_decrypt(session_p, pWrappedKey, ulWrappedKeyLen, clear_key_val, &ulDataLen); if (rv != CKR_OK) { goto failed_exit; } /* Now add the CKA_VALUE attribute to template */ templ_size = ulAttributeCount * sizeof (CK_ATTRIBUTE); newTemplate = malloc(templ_size + sizeof (CK_ATTRIBUTE)); if (newTemplate == NULL) { rv = CKR_HOST_MEMORY; goto failed_exit; } bcopy(pTemplate, newTemplate, templ_size); newTemplate[ulAttributeCount].type = CKA_VALUE; newTemplate[ulAttributeCount].pValue = clear_key_val; newTemplate[ulAttributeCount].ulValueLen = ulDataLen; /* Finally create the key, based on the new template */ rv = kernel_add_object(newTemplate, ulAttributeCount + 1, phKey, session_p); (void) free(clear_key_val); (void) free(newTemplate); OBJ_REFRELE(unwrappingkey_p); REFRELE(session_p, ses_lock_held); return (rv); } else { rv = CKR_FUNCTION_FAILED; goto failed_exit; } } /* * If we come here, the HW provider must have registered the unwrapkey * entry. Therefore, the unwrap key will be performed in the HW * provider. */ rv = kernel_mech(pMechanism->mechanism, &k_mech_type); if (rv != CKR_OK) { goto failed_exit; } /* Create an object wrapper for the new key in the library first */ new_objp = calloc(1, sizeof (kernel_object_t)); if (new_objp == NULL) { rv = CKR_HOST_MEMORY; goto failed_exit; } /* Process the attributes */ rv = process_object_attributes(pTemplate, ulAttributeCount, &obj_unwrapkey.uk_attributes, &is_token_obj); if (rv != CKR_OK) { goto failed_exit; } /* Cannot create a token object with a READ-ONLY session. */ if (is_token_obj && session_p->ses_RO) { free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount); rv = CKR_SESSION_READ_ONLY; goto failed_exit; } /* Make the CRYPTO_UNWRAP_KEY ioctl call. */ obj_unwrapkey.uk_session = session_p->k_session; obj_unwrapkey.uk_mechanism.cm_type = k_mech_type; obj_unwrapkey.uk_mechanism.cm_param = pMechanism->pParameter; obj_unwrapkey.uk_mechanism.cm_param_len = pMechanism->ulParameterLen; obj_unwrapkey.uk_unwrapping_key.ck_format = CRYPTO_KEY_REFERENCE; obj_unwrapkey.uk_unwrapping_key.ck_obj_id = unwrappingkey_p->k_handle; obj_unwrapkey.uk_wrapped_key = (char *)pWrappedKey; obj_unwrapkey.uk_wrapped_key_len = ulWrappedKeyLen; obj_unwrapkey.uk_count = ulAttributeCount; while ((r = ioctl(kernel_fd, CRYPTO_UNWRAP_KEY, &obj_unwrapkey)) < 0) { if (errno != EINTR) break; } if (r < 0) { rv = CKR_FUNCTION_FAILED; } else { rv = crypto2pkcs11_error_number(obj_unwrapkey.uk_return_value); } free_object_attributes(obj_unwrapkey.uk_attributes, ulAttributeCount); if (rv != CKR_OK) { goto failed_exit; } /* Get the CKA_PRIVATE value for the unwrapped key. */ rv = get_cka_private_value(session_p, obj_unwrapkey.uk_object_handle, &is_pri_obj); if (rv != CKR_OK) { goto failed_exit; } /* * Store the kernel object handle in the new key object wrapper and * initialize it. */ new_objp->k_handle = obj_unwrapkey.uk_object_handle; new_objp->is_lib_obj = B_FALSE; new_objp->session_handle = (CK_SESSION_HANDLE)session_p; new_objp->extra_attrlistp = NULL; if (is_pri_obj) new_objp->bool_attr_mask |= PRIVATE_BOOL_ON; else new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; if (is_token_obj) new_objp->bool_attr_mask |= TOKEN_BOOL_ON; else new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; (void) pthread_mutex_init(&new_objp->object_mutex, NULL); new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; /* * Add the new object to the slot's token object list if it is a * a token object. Otherwise, add it to the session's object list. */ if (is_token_obj) { pslot = slot_table[session_p->ses_slotid]; kernel_add_token_object_to_slot(new_objp, pslot); } else { kernel_add_object_to_session(new_objp, session_p); } *phKey = (CK_OBJECT_HANDLE)new_objp; OBJ_REFRELE(unwrappingkey_p); REFRELE(session_p, ses_lock_held); return (rv); failed_exit: OBJ_REFRELE(unwrappingkey_p); if (new_objp != NULL) (void) free(new_objp); if (clear_key_val != NULL) (void) free(clear_key_val); if (newTemplate != NULL) (void) free(newTemplate); REFRELE(session_p, ses_lock_held); return (rv); }
CK_RV C_WrapKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { CK_RV rv = CKR_OK; kernel_session_t *session_p; boolean_t ses_lock_held = B_FALSE; kernel_object_t *wrappingkey_p; kernel_object_t *key_p; crypto_mech_type_t k_mech_type; crypto_object_wrap_key_t obj_wrapkey; int r; if (!kernel_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); if (pulWrappedKeyLen == NULL || pMechanism == NULL) { return (CKR_ARGUMENTS_BAD); } /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* Get the kernel's internal mechanism number. */ rv = kernel_mech(pMechanism->mechanism, &k_mech_type); if (rv != CKR_OK) { REFRELE(session_p, ses_lock_held); return (rv); } /* Obtain the wrapping key object pointer. */ HANDLE2OBJECT(hWrappingKey, wrappingkey_p, rv); if (rv != CKR_OK) { REFRELE(session_p, ses_lock_held); return (rv); } /* Obtain the to_be_wrapped key object pointer. */ HANDLE2OBJECT(hKey, key_p, rv); if (rv != CKR_OK) { OBJ_REFRELE(wrappingkey_p); REFRELE(session_p, ses_lock_held); return (rv); } /* Make the CRYPTO_OBJECT_WRAP_KEY ioctl call. */ obj_wrapkey.wk_session = session_p->k_session; obj_wrapkey.wk_mechanism.cm_type = k_mech_type; obj_wrapkey.wk_mechanism.cm_param = pMechanism->pParameter; obj_wrapkey.wk_mechanism.cm_param_len = pMechanism->ulParameterLen; obj_wrapkey.wk_wrapping_key.ck_format = CRYPTO_KEY_REFERENCE; obj_wrapkey.wk_wrapping_key.ck_obj_id = wrappingkey_p->k_handle; obj_wrapkey.wk_object_handle = key_p->k_handle; obj_wrapkey.wk_wrapped_key_len = *pulWrappedKeyLen; obj_wrapkey.wk_wrapped_key = (char *)pWrappedKey; while ((r = ioctl(kernel_fd, CRYPTO_WRAP_KEY, &obj_wrapkey)) < 0) { if (errno != EINTR) break; } if (r < 0) { rv = CKR_FUNCTION_FAILED; } else { rv = crypto2pkcs11_error_number(obj_wrapkey.wk_return_value); } /* * Besides rv == CKR_OK, we will set the value of pulWrappedKeyLen * when the applciation-supplied wrapped key buffer is too small. * The situation that the application only asks for the length of * the wrapped key is covered in rv == CKR_OK. */ if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { *pulWrappedKeyLen = obj_wrapkey.wk_wrapped_key_len; } OBJ_REFRELE(key_p); OBJ_REFRELE(wrappingkey_p); REFRELE(session_p, ses_lock_held); return (rv); }
CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { CK_RV rv = CKR_OK; kms_session_t *session_p; kms_slot_t *pslot; boolean_t ses_lock_held = B_FALSE; if (!kms_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); if ((userType != CKU_SO) && (userType != CKU_USER)) { return (CKR_USER_TYPE_INVALID); } /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* Acquire the slot lock */ pslot = get_slotinfo(); (void) pthread_mutex_lock(&pslot->sl_mutex); /* Check if the slot is logged in already */ if ((pslot->sl_state == CKU_USER) || (pslot->sl_state == CKU_SO)) { rv = CKR_USER_ALREADY_LOGGED_IN; goto clean_exit; } /* To login as SO, every session in this slot needs to be R/W */ if (userType == CKU_SO) { kms_session_t *sp; boolean_t found; found = B_FALSE; sp = pslot->sl_sess_list; while (sp) { /* * Need not to lock individual sessions before * accessing their "ses_RO" and "next" fields, * because they are always accessed under the * slot's mutex protection. */ if (sp->ses_RO) { found = B_TRUE; break; } sp = sp->next; } if (found) { rv = CKR_SESSION_READ_ONLY_EXISTS; goto clean_exit; } } /* * Login to KMS by attempting to load the profile using * the given password. */ rv = KMS_LoadProfile( &session_p->kmsProfile, &session_p->configInfo, (const char *)pPin, (size_t)ulPinLen); if (rv == CKR_OK) { /* Set the slot's session state. */ pslot->sl_state = userType; } clean_exit: REFRELE(session_p, ses_lock_held); (void) pthread_mutex_unlock(&pslot->sl_mutex); return (rv); }
CK_RV C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_RV rv; cpk_session_t *session_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obatin the session pointer */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if ((pData == NULL) || (pulSignatureLen == NULL)) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* Application must call C_SignInit before calling C_Sign. */ if (!(session_p->sign.flags & CRYPTO_OPERATION_ACTIVE)) { SES_REFRELE(session_p, lock_held); return (CKR_OPERATION_NOT_INITIALIZED); } /* * C_Sign must be called without intervening C_SignUpdate * calls. */ if (session_p->sign.flags & CRYPTO_OPERATION_UPDATE) { /* * C_Sign can not be used to terminate a multi-part * operation, so we'll leave the active sign operation * flag on and let the application continue with the * sign update operation. */ SES_REFRELE(session_p, lock_held); return (CKR_FUNCTION_FAILED); } (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_sign(session_p, pData, ulDataLen, pSignature, pulSignatureLen); if ((rv == CKR_BUFFER_TOO_SMALL) || (pSignature == NULL && rv == CKR_OK)) { /* * We will not terminate the active sign operation flag, * when the application-supplied buffer is too small, or * the application asks for the length of buffer to hold * the signature. */ SES_REFRELE(session_p, lock_held); return (rv); } clean_exit: /* Clear contexts, free key, and release session counter */ cpk_sign_verify_cleanup(session_p, B_TRUE, B_FALSE); return (rv); }
CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { soft_session_t *session_p, *sp; CK_RV rv; boolean_t lock_held = B_FALSE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); /* Check the load status of keystore */ if (!soft_keystore_status(KEYSTORE_LOAD)) { SES_REFRELE(session_p, lock_held); return (CKR_DEVICE_REMOVED); } if (userType != CKU_USER) { SES_REFRELE(session_p, lock_held); return (CKR_USER_TYPE_INVALID); } if ((ulPinLen < MIN_PIN_LEN) || (ulPinLen > MAX_PIN_LEN)) { SES_REFRELE(session_p, lock_held); return (CKR_PIN_LEN_RANGE); } if (pPin == NULL_PTR) { /* * We don't support CKF_PROTECTED_AUTHENTICATION_PATH */ SES_REFRELE(session_p, lock_held); return (CKR_ARGUMENTS_BAD); } (void) pthread_mutex_lock(&soft_giant_mutex); if (soft_slot.authenticated) { (void) pthread_mutex_unlock(&soft_giant_mutex); SES_REFRELE(session_p, lock_held); return (CKR_USER_ALREADY_LOGGED_IN); } rv = soft_login(pPin, ulPinLen); if (rv == CKR_OK) { if (soft_slot.userpin_change_needed) { /* * This is the special case when the PIN is never * initialized in the keystore, which will always * return CKR_OK with "userpin_change_needed" set. */ (void) pthread_mutex_unlock(&soft_giant_mutex); SES_REFRELE(session_p, lock_held); return (rv); } soft_slot.authenticated = 1; (void) pthread_mutex_unlock(&soft_giant_mutex); } else { (void) pthread_mutex_unlock(&soft_giant_mutex); SES_REFRELE(session_p, lock_held); return (rv); } /* * Load all the private token objects from keystore. */ rv = soft_get_token_objects_from_keystore(PRI_TOKENOBJS); if (rv != CKR_OK) { SES_REFRELE(session_p, lock_held); return (rv); } /* Acquire the global session list lock */ (void) pthread_mutex_lock(&soft_sessionlist_mutex); sp = soft_session_list; while (sp) { (void) pthread_mutex_lock(&sp->session_mutex); if (sp->flags & CKF_RW_SESSION) { sp->state = CKS_RW_USER_FUNCTIONS; } else { sp->state = CKS_RO_USER_FUNCTIONS; } (void) pthread_mutex_unlock(&sp->session_mutex); sp = sp->next; } (void) pthread_mutex_unlock(&soft_sessionlist_mutex); SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { CK_RV rv; cpk_session_t *session_p; cpk_object_t *key_p; boolean_t lock_held = B_FALSE; if (!cpktoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if (pMechanism == NULL) { rv = CKR_ARGUMENTS_BAD; goto clean_exit; } /* Obtain the object pointer. */ HANDLE2OBJECT(hKey, key_p, rv); if (rv != CKR_OK) { goto clean_exit; } (void) pthread_mutex_lock(&session_p->session_mutex); lock_held = B_TRUE; /* Check to see if verify operation is already active. */ if (session_p->verify.flags & CRYPTO_OPERATION_ACTIVE) { /* free the memory to avoid memory leak */ cpk_sign_verify_cleanup(session_p, B_FALSE, B_TRUE); } /* * This active flag will remain ON until application calls either * C_Verify or C_VerifyFinal to verify a signature on data. */ session_p->verify.flags = CRYPTO_OPERATION_ACTIVE; (void) pthread_mutex_unlock(&session_p->session_mutex); lock_held = B_FALSE; rv = cpk_verify_init(session_p, pMechanism, key_p); if (rv != CKR_OK) { (void) pthread_mutex_lock(&session_p->session_mutex); session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE; lock_held = B_TRUE; } OBJ_REFRELE(key_p); clean_exit: SES_REFRELE(session_p, lock_held); return (rv); }
CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { CK_RV rv = CKR_OK; kernel_session_t *session_p; kernel_object_t *new_pub_objp = NULL; kernel_object_t *new_pri_objp = NULL; kernel_slot_t *pslot; boolean_t ses_lock_held = B_FALSE; CK_BBOOL is_pri_obj1; CK_BBOOL is_pri_obj2; CK_BBOOL is_token_obj1 = FALSE; CK_BBOOL is_token_obj2 = FALSE; crypto_mech_type_t k_mech_type; crypto_object_generate_key_pair_t obj_kp; int r; if (!kernel_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* Obtain the session pointer. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); if ((pMechanism == NULL) || (phPublicKey == NULL) || (phPrivateKey == NULL)) { rv = CKR_ARGUMENTS_BAD; goto failed_exit; } if ((pPublicKeyTemplate == NULL) && (ulPublicKeyAttributeCount != 0)) { rv = CKR_ARGUMENTS_BAD; goto failed_exit; } if ((pPrivateKeyTemplate == NULL) && (ulPrivateKeyAttributeCount != 0)) { rv = CKR_ARGUMENTS_BAD; goto failed_exit; } /* Get the kernel's internal mechanism number. */ rv = kernel_mech(pMechanism->mechanism, &k_mech_type); if (rv != CKR_OK) { goto failed_exit; } /* Create an object wrapper for the public key */ new_pub_objp = calloc(1, sizeof (kernel_object_t)); if (new_pub_objp == NULL) { rv = CKR_HOST_MEMORY; goto failed_exit; } /* Create an object wrapper for the private key. */ new_pri_objp = calloc(1, sizeof (kernel_object_t)); if (new_pri_objp == NULL) { rv = CKR_HOST_MEMORY; goto failed_exit; } /* Process the public key attributes. */ rv = process_object_attributes(pPublicKeyTemplate, ulPublicKeyAttributeCount, &obj_kp.kp_public_attributes, &is_token_obj1); if (rv != CKR_OK) { goto failed_exit; } /* Cannot create a token object with a READ-ONLY session. */ if (is_token_obj1 && session_p->ses_RO) { free_object_attributes(obj_kp.kp_public_attributes, ulPublicKeyAttributeCount); rv = CKR_SESSION_READ_ONLY; goto failed_exit; } /* Process the private key attributes. */ rv = process_object_attributes(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, &obj_kp.kp_private_attributes, &is_token_obj2); if (rv != CKR_OK) { free_object_attributes(obj_kp.kp_public_attributes, ulPublicKeyAttributeCount); goto failed_exit; } /* * The public key and the private key need to contain the same * attribute values for CKA_TOKEN. */ if (is_token_obj1 != is_token_obj2) { free_object_attributes(obj_kp.kp_public_attributes, ulPublicKeyAttributeCount); free_object_attributes(obj_kp.kp_private_attributes, ulPrivateKeyAttributeCount); rv = CKR_ATTRIBUTE_VALUE_INVALID; goto failed_exit; } /* Call the CRYPTO_GENERATE_KEY_PAIR ioctl. */ obj_kp.kp_session = session_p-> k_session; obj_kp.kp_mechanism.cm_type = k_mech_type; obj_kp.kp_mechanism.cm_param = pMechanism->pParameter; obj_kp.kp_mechanism.cm_param_len = pMechanism->ulParameterLen; obj_kp.kp_public_count = ulPublicKeyAttributeCount; obj_kp.kp_private_count = ulPrivateKeyAttributeCount; while ((r = ioctl(kernel_fd, CRYPTO_GENERATE_KEY_PAIR, &obj_kp)) < 0) { if (errno != EINTR) break; } if (r < 0) { rv = CKR_FUNCTION_FAILED; } else { rv = crypto2pkcs11_error_number(obj_kp.kp_return_value); } free_object_attributes(obj_kp.kp_public_attributes, ulPublicKeyAttributeCount); free_object_attributes(obj_kp.kp_private_attributes, ulPrivateKeyAttributeCount); if (rv != CKR_OK) { goto failed_exit; } /* Get the CKA_PRIVATE value for the key pair. */ rv = get_cka_private_value(session_p, obj_kp.kp_public_handle, &is_pri_obj1); if (rv != CKR_OK) { goto failed_exit; } rv = get_cka_private_value(session_p, obj_kp.kp_private_handle, &is_pri_obj2); if (rv != CKR_OK) { goto failed_exit; } /* * Store the kernel public key handle into the public key object and * finish the public key object initialization. */ new_pub_objp->is_lib_obj = B_FALSE; new_pub_objp->k_handle = obj_kp.kp_public_handle; new_pub_objp->session_handle = (CK_SESSION_HANDLE)session_p; new_pub_objp->extra_attrlistp = NULL; if (is_pri_obj1) new_pub_objp->bool_attr_mask |= PRIVATE_BOOL_ON; else new_pub_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; if (is_token_obj1) new_pub_objp->bool_attr_mask |= TOKEN_BOOL_ON; else new_pub_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; (void) pthread_mutex_init(&new_pub_objp->object_mutex, NULL); new_pub_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; /* * Store the kernel private key handle into the private key object * and finish the private key object initialization. */ new_pri_objp->is_lib_obj = B_FALSE; new_pri_objp->k_handle = obj_kp.kp_private_handle; new_pri_objp->session_handle = (CK_SESSION_HANDLE)session_p; new_pri_objp->extra_attrlistp = NULL; if (is_pri_obj2) new_pri_objp->bool_attr_mask |= PRIVATE_BOOL_ON; else new_pri_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON; if (is_token_obj2) new_pri_objp->bool_attr_mask |= TOKEN_BOOL_ON; else new_pri_objp->bool_attr_mask &= ~TOKEN_BOOL_ON; (void) pthread_mutex_init(&new_pri_objp->object_mutex, NULL); new_pri_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC; /* * Add the new pub/pri objects to the slot's token list if they are * token objects. Otherwise, add them to the session's object list. */ if (is_token_obj1) { /* is_token_obj1 == is_token_obj2 */ pslot = slot_table[session_p->ses_slotid]; kernel_add_token_object_to_slot(new_pub_objp, pslot); kernel_add_token_object_to_slot(new_pri_objp, pslot); } else { kernel_add_object_to_session(new_pub_objp, session_p); kernel_add_object_to_session(new_pri_objp, session_p); } *phPublicKey = (CK_OBJECT_HANDLE)new_pub_objp; *phPrivateKey = (CK_OBJECT_HANDLE)new_pri_objp; REFRELE(session_p, ses_lock_held); return (rv); failed_exit: if (new_pub_objp != NULL) { (void) free(new_pub_objp); } if (new_pri_objp != NULL) { (void) free(new_pri_objp); } REFRELE(session_p, ses_lock_held); return (rv); }
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { CK_RV rv; soft_session_t *session_p; boolean_t lock_held = B_TRUE; if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); /* * Obtain the session pointer. Also, increment the session * reference count. */ rv = handle2session(hSession, &session_p); if (rv != CKR_OK) return (rv); (void) pthread_mutex_lock(&session_p->session_mutex); /* * Set SESSION_IS_CLOSING flag so any access to this * session will be rejected. */ if (session_p->ses_close_sync & SESSION_IS_CLOSING) { SES_REFRELE(session_p, lock_held); return (CKR_SESSION_CLOSED); } session_p->ses_close_sync |= SESSION_IS_CLOSING; /* * Decrement the session reference count. * We hold the session lock, and SES_REFRELE() * will release the session lock for us. */ SES_REFRELE(session_p, lock_held); /* * Delete a session by calling soft_delete_session() with * a session pointer and a boolean arguments. Boolean * value FALSE is used to indicate that the caller does not * hold the lock on the global session list and also that * this is not a forced session close but an explicit request. * * soft_delete_session() will reset SESSION_IS_CLOSING * flag after it is done. */ rv = soft_delete_session(session_p, B_FALSE, B_FALSE); if (soft_session_cnt == 0) { /* Clean up private token objects from the token object list */ soft_delete_all_in_core_token_objects(PRIVATE_TOKEN); /* * Invalidate public token object handles instead of * deleting them. */ soft_validate_token_objects(B_FALSE); (void) pthread_mutex_lock(&soft_giant_mutex); soft_slot.authenticated = 0; soft_slot.userpin_change_needed = 0; (void) pthread_mutex_unlock(&soft_giant_mutex); } return (rv); }