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_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_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_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_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_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_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); }
/* * This function frees the allocated active crypto context. * It is only called by the first tier of sign/verify routines * and the caller of this function may or may not hold the session mutex. */ void soft_sign_verify_cleanup(soft_session_t *session_p, boolean_t sign, boolean_t lock_held) { crypto_active_op_t *active_op; boolean_t lock_true = B_TRUE; if (!lock_held) (void) pthread_mutex_lock(&session_p->session_mutex); active_op = (sign) ? &(session_p->sign) : &(session_p->verify); switch (active_op->mech.mechanism) { case CKM_MD5_RSA_PKCS: case CKM_SHA1_RSA_PKCS: case CKM_SHA256_RSA_PKCS: case CKM_SHA384_RSA_PKCS: case CKM_SHA512_RSA_PKCS: if (session_p->digest.context != NULL) { free(session_p->digest.context); session_p->digest.context = NULL; session_p->digest.flags = 0; } /* FALLTHRU */ case CKM_RSA_PKCS: case CKM_RSA_X_509: { soft_rsa_ctx_t *rsa_ctx = (soft_rsa_ctx_t *)active_op->context; if (rsa_ctx != NULL && rsa_ctx->key != NULL) { soft_cleanup_object(rsa_ctx->key); free(rsa_ctx->key); } break; } case CKM_DSA_SHA1: if (session_p->digest.context != NULL) { free(session_p->digest.context); session_p->digest.context = NULL; session_p->digest.flags = 0; } /* FALLTHRU */ case CKM_DSA: { soft_dsa_ctx_t *dsa_ctx = (soft_dsa_ctx_t *)active_op->context; if (dsa_ctx != NULL && dsa_ctx->key != NULL) { soft_cleanup_object(dsa_ctx->key); free(dsa_ctx->key); } break; } case CKM_SSL3_MD5_MAC: case CKM_SSL3_SHA1_MAC: case CKM_MD5_HMAC_GENERAL: case CKM_MD5_HMAC: case CKM_SHA_1_HMAC_GENERAL: case CKM_SHA_1_HMAC: case CKM_SHA256_HMAC_GENERAL: case CKM_SHA256_HMAC: case CKM_SHA384_HMAC_GENERAL: case CKM_SHA384_HMAC: case CKM_SHA512_HMAC_GENERAL: case CKM_SHA512_HMAC: if (active_op->context != NULL) bzero(active_op->context, sizeof (soft_hmac_ctx_t)); break; case CKM_DES_MAC_GENERAL: case CKM_DES_MAC: if (session_p->encrypt.context != NULL) { free(session_p->encrypt.context); session_p->encrypt.context = NULL; session_p->encrypt.flags = 0; } if (active_op->context != NULL) bzero(active_op->context, sizeof (soft_des_ctx_t)); break; } if (active_op->context != NULL) { free(active_op->context); active_op->context = NULL; } active_op->flags = 0; if (!lock_held) SES_REFRELE(session_p, lock_true); }
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_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_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_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); }
/* * This function frees the allocated active crypto context and the * lower level of allocated struct as needed. * This function is called by the 1st tier of encrypt/decrypt routines * or by the 2nd tier of session close routine. Since the 1st tier * caller will always call this function without locking the session * mutex and the 2nd tier caller will call with the lock, we add the * third parameter "lock_held" to distiguish this case. */ void soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt, boolean_t lock_held) { crypto_active_op_t *active_op; boolean_t lock_true = B_TRUE; if (!lock_held) (void) pthread_mutex_lock(&session_p->session_mutex); active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt); switch (active_op->mech.mechanism) { case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_DES_CBC: case CKM_DES_ECB: case CKM_DES3_CBC: case CKM_DES3_ECB: { soft_des_ctx_t *soft_des_ctx = (soft_des_ctx_t *)active_op->context; des_ctx_t *des_ctx; if (soft_des_ctx != NULL) { des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc; if (des_ctx != NULL) { bzero(des_ctx->dc_keysched, des_ctx->dc_keysched_len); free(soft_des_ctx->des_cbc); } bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len); free(soft_des_ctx->key_sched); } break; } case CKM_AES_CBC_PAD: case CKM_AES_CBC: case CKM_AES_ECB: { soft_aes_ctx_t *soft_aes_ctx = (soft_aes_ctx_t *)active_op->context; aes_ctx_t *aes_ctx; if (soft_aes_ctx != NULL) { aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc; if (aes_ctx != NULL) { bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len); free(soft_aes_ctx->aes_cbc); } bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); free(soft_aes_ctx->key_sched); } break; } case CKM_BLOWFISH_CBC: { soft_blowfish_ctx_t *soft_blowfish_ctx = (soft_blowfish_ctx_t *)active_op->context; blowfish_ctx_t *blowfish_ctx; if (soft_blowfish_ctx != NULL) { blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc; if (blowfish_ctx != NULL) { bzero(blowfish_ctx->bc_keysched, blowfish_ctx->bc_keysched_len); free(soft_blowfish_ctx->blowfish_cbc); } bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len); free(soft_blowfish_ctx->key_sched); } break; } case CKM_RC4: { ARCFour_key *key = (ARCFour_key *)active_op->context; if (key != NULL) bzero(key, sizeof (*key)); break; } case CKM_RSA_X_509: case CKM_RSA_PKCS: break; } /* switch */ if (active_op->context != NULL) { free(active_op->context); active_op->context = NULL; } active_op->flags = 0; if (!lock_held) SES_REFRELE(session_p, lock_true); }
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); }