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_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_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); }