17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 587fa5c53Smcpowers * Common Development and Distribution License (the "License"). 687fa5c53Smcpowers * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*6d2259e1SDan OpenSolaris Anderson * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <pthread.h> 277c478bd9Sstevel@tonic-gate #include <stdlib.h> 287c478bd9Sstevel@tonic-gate #include <errno.h> 297c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h> 307c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 317c478bd9Sstevel@tonic-gate #include "kernelGlobal.h" 327c478bd9Sstevel@tonic-gate #include "kernelSession.h" 337c478bd9Sstevel@tonic-gate #include "kernelObject.h" 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate CK_RV 377c478bd9Sstevel@tonic-gate C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 387c478bd9Sstevel@tonic-gate CK_OBJECT_HANDLE hKey) 397c478bd9Sstevel@tonic-gate { 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate CK_RV rv; 427c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 437c478bd9Sstevel@tonic-gate kernel_object_t *key_p; 447c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 457c478bd9Sstevel@tonic-gate crypto_encrypt_init_t encrypt_init; 467c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type; 477c478bd9Sstevel@tonic-gate int r; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate if (!kernel_initialized) 507c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate if (pMechanism == NULL) { 537c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD); 547c478bd9Sstevel@tonic-gate } 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* Get the kernel's internal mechanism number. */ 577c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type); 587c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 597c478bd9Sstevel@tonic-gate return (rv); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 627c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 637c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 647c478bd9Sstevel@tonic-gate return (rv); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */ 677c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv); 6801223cbaSmcpowers if (rv != CKR_OK) { 6901223cbaSmcpowers REFRELE(session_p, ses_lock_held); 7001223cbaSmcpowers return (rv); 7101223cbaSmcpowers } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* Check to see if key object allows for encryption. */ 747c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj && !(key_p->bool_attr_mask & ENCRYPT_BOOL_ON)) { 757c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 767c478bd9Sstevel@tonic-gate goto clean_exit; 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 807c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * This active flag will remain ON until application calls either 847c478bd9Sstevel@tonic-gate * C_Encrypt or C_EncryptFinal to actually obtain the final piece 857c478bd9Sstevel@tonic-gate * of ciphertext. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* set up key data */ 907c478bd9Sstevel@tonic-gate if (!key_p->is_lib_obj) { 917c478bd9Sstevel@tonic-gate encrypt_init.ei_key.ck_format = CRYPTO_KEY_REFERENCE; 927c478bd9Sstevel@tonic-gate encrypt_init.ei_key.ck_obj_id = key_p->k_handle; 937c478bd9Sstevel@tonic-gate } else { 947c478bd9Sstevel@tonic-gate if (key_p->class == CKO_SECRET_KEY) { 957c478bd9Sstevel@tonic-gate encrypt_init.ei_key.ck_format = CRYPTO_KEY_RAW; 967c478bd9Sstevel@tonic-gate encrypt_init.ei_key.ck_data = 977c478bd9Sstevel@tonic-gate get_symmetric_key_value(key_p); 987c478bd9Sstevel@tonic-gate if (encrypt_init.ei_key.ck_data == NULL) { 997c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 1007c478bd9Sstevel@tonic-gate goto clean_exit; 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate encrypt_init.ei_key.ck_length = 1037c478bd9Sstevel@tonic-gate OBJ_SEC(key_p)->sk_value_len << 3; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate } else if (key_p->key_type == CKK_RSA) { 1067c478bd9Sstevel@tonic-gate if (get_rsa_public_key(key_p, &encrypt_init.ei_key) != 1077c478bd9Sstevel@tonic-gate CKR_OK) { 1087c478bd9Sstevel@tonic-gate rv = CKR_HOST_MEMORY; 1097c478bd9Sstevel@tonic-gate goto clean_exit; 1107c478bd9Sstevel@tonic-gate } 1117c478bd9Sstevel@tonic-gate } else { 1127c478bd9Sstevel@tonic-gate rv = CKR_KEY_TYPE_INCONSISTENT; 1137c478bd9Sstevel@tonic-gate goto clean_exit; 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate encrypt_init.ei_session = session_p->k_session; 11887fa5c53Smcpowers session_p->encrypt.mech = *pMechanism; 119*6d2259e1SDan OpenSolaris Anderson 120*6d2259e1SDan OpenSolaris Anderson /* Cache this capability value for efficiency */ 121*6d2259e1SDan OpenSolaris Anderson if (INPLACE_MECHANISM(session_p->encrypt.mech.mechanism)) { 122*6d2259e1SDan OpenSolaris Anderson session_p->encrypt.flags |= CRYPTO_OPERATION_INPLACE_OK; 123*6d2259e1SDan OpenSolaris Anderson } 1247c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 125*6d2259e1SDan OpenSolaris Anderson 1267c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 1277c478bd9Sstevel@tonic-gate encrypt_init.ei_mech.cm_type = k_mech_type; 1287c478bd9Sstevel@tonic-gate encrypt_init.ei_mech.cm_param = pMechanism->pParameter; 1297c478bd9Sstevel@tonic-gate encrypt_init.ei_mech.cm_param_len = pMechanism->ulParameterLen; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT_INIT, &encrypt_init)) < 0) { 1327c478bd9Sstevel@tonic-gate if (errno != EINTR) 1337c478bd9Sstevel@tonic-gate break; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate if (r < 0) { 1367c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 1377c478bd9Sstevel@tonic-gate } else { 1387c478bd9Sstevel@tonic-gate if (encrypt_init.ei_return_value != CRYPTO_SUCCESS) { 1397c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 1407c478bd9Sstevel@tonic-gate encrypt_init.ei_return_value); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* Free memory allocated for decrypt_init.di_key */ 1457c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj) { 1467c478bd9Sstevel@tonic-gate if (key_p->class == CKO_SECRET_KEY) { 1477c478bd9Sstevel@tonic-gate free(encrypt_init.ei_key.ck_data); 1487c478bd9Sstevel@tonic-gate } else if (key_p->key_type == CKK_RSA) { 1497c478bd9Sstevel@tonic-gate free_key_attributes(&encrypt_init.ei_key); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate if (rv != CKR_OK) { 1547c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 1557c478bd9Sstevel@tonic-gate session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE; 1567c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate clean_exit: 16001223cbaSmcpowers OBJ_REFRELE(key_p); 1617c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 1627c478bd9Sstevel@tonic-gate return (rv); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate CK_RV 1677c478bd9Sstevel@tonic-gate C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 1687c478bd9Sstevel@tonic-gate CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate CK_RV rv; 1727c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 1737c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 17487fa5c53Smcpowers boolean_t inplace; 1757c478bd9Sstevel@tonic-gate crypto_encrypt_t encrypt; 1767c478bd9Sstevel@tonic-gate int r; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (!kernel_initialized) 1797c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 1827c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 1837c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 1847c478bd9Sstevel@tonic-gate return (rv); 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate if (pData == NULL) { 1877c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 1887c478bd9Sstevel@tonic-gate goto clean_exit; 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * Only check if pulEncryptedDataLen is NULL. 1937c478bd9Sstevel@tonic-gate * No need to check if pEncryptedData is NULL because 1947c478bd9Sstevel@tonic-gate * application might just ask for the length of buffer to hold 1957c478bd9Sstevel@tonic-gate * the ciphertext. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate if (pulEncryptedDataLen == NULL) { 1987c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 1997c478bd9Sstevel@tonic-gate goto clean_exit; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2037c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* Application must call C_EncryptInit before calling C_Encrypt. */ 2067c478bd9Sstevel@tonic-gate if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 2077c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2087c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate /* 2127c478bd9Sstevel@tonic-gate * C_Encrypt must be called without intervening C_EncryptUpdate 2137c478bd9Sstevel@tonic-gate * calls. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate if (session_p->encrypt.flags & CRYPTO_OPERATION_UPDATE) { 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * C_Encrypt can not be used to terminate a multi-part 2187c478bd9Sstevel@tonic-gate * operation, so we'll leave the active encrypt operation 2197c478bd9Sstevel@tonic-gate * flag on and let the application continue with the 2207c478bd9Sstevel@tonic-gate * encrypt update operation. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2237c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED); 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate encrypt.ce_session = session_p->k_session; 22787fa5c53Smcpowers 22887fa5c53Smcpowers /* 22987fa5c53Smcpowers * Certain mechanisms, where the length of the ciphertext is 23087fa5c53Smcpowers * same as the transformed plaintext, can be optimized 23187fa5c53Smcpowers * by the kernel into an in-place operation. Unfortunately, 23287fa5c53Smcpowers * some applications use a ciphertext buffer that is larger 23387fa5c53Smcpowers * than it needs to be. We fix that here. 23487fa5c53Smcpowers */ 235*6d2259e1SDan OpenSolaris Anderson inplace = (session_p->encrypt.flags & CRYPTO_OPERATION_INPLACE_OK) != 0; 23687fa5c53Smcpowers if (ulDataLen < *pulEncryptedDataLen && inplace) { 23787fa5c53Smcpowers encrypt.ce_encrlen = ulDataLen; 23887fa5c53Smcpowers } else { 23987fa5c53Smcpowers encrypt.ce_encrlen = *pulEncryptedDataLen; 24087fa5c53Smcpowers } 2417c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 2427c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate encrypt.ce_datalen = ulDataLen; 2457c478bd9Sstevel@tonic-gate encrypt.ce_databuf = (char *)pData; 2467c478bd9Sstevel@tonic-gate encrypt.ce_encrbuf = (char *)pEncryptedData; 247*6d2259e1SDan OpenSolaris Anderson encrypt.ce_flags = 248*6d2259e1SDan OpenSolaris Anderson ((inplace && (pEncryptedData != NULL)) || 249*6d2259e1SDan OpenSolaris Anderson (pData == pEncryptedData)) && 250*6d2259e1SDan OpenSolaris Anderson (encrypt.ce_encrlen == encrypt.ce_datalen) ? 25187fa5c53Smcpowers CRYPTO_INPLACE_OPERATION : 0; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT, &encrypt)) < 0) { 2547c478bd9Sstevel@tonic-gate if (errno != EINTR) 2557c478bd9Sstevel@tonic-gate break; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate if (r < 0) { 2587c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 2597c478bd9Sstevel@tonic-gate } else { 2607c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(encrypt.ce_return_value); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 2647c478bd9Sstevel@tonic-gate *pulEncryptedDataLen = encrypt.ce_encrlen; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) || 2677c478bd9Sstevel@tonic-gate (rv == CKR_OK && pEncryptedData == NULL)) { 2687c478bd9Sstevel@tonic-gate /* 2697c478bd9Sstevel@tonic-gate * We will not terminate the active encrypt operation flag, 2707c478bd9Sstevel@tonic-gate * when the application-supplied buffer is too small, or 2717c478bd9Sstevel@tonic-gate * the application asks for the length of buffer to hold 2727c478bd9Sstevel@tonic-gate * the ciphertext. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2757c478bd9Sstevel@tonic-gate return (rv); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate clean_exit: 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Terminates the active encrypt operation. 2817c478bd9Sstevel@tonic-gate * Application needs to call C_EncryptInit again for next 2827c478bd9Sstevel@tonic-gate * encrypt operation. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 2857c478bd9Sstevel@tonic-gate session_p->encrypt.flags = 0; 2867c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 2877c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate return (rv); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate CK_RV 2947c478bd9Sstevel@tonic-gate C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, 2957c478bd9Sstevel@tonic-gate CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, 2967c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulEncryptedPartLen) 2977c478bd9Sstevel@tonic-gate { 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate CK_RV rv; 3007c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 3017c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 302*6d2259e1SDan OpenSolaris Anderson boolean_t inplace; 3037c478bd9Sstevel@tonic-gate crypto_encrypt_update_t encrypt_update; 3047c478bd9Sstevel@tonic-gate int r; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate if (!kernel_initialized) 3077c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 3107c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 3117c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 3127c478bd9Sstevel@tonic-gate return (rv); 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if (pPart == NULL) { 3157c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 3167c478bd9Sstevel@tonic-gate goto clean_exit; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * Only check if pulEncryptedPartLen is NULL. 3217c478bd9Sstevel@tonic-gate * No need to check if pEncryptedPart is NULL because 3227c478bd9Sstevel@tonic-gate * application might just ask for the length of buffer to hold 3237c478bd9Sstevel@tonic-gate * the ciphertext. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate if (pulEncryptedPartLen == NULL) { 3267c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 3277c478bd9Sstevel@tonic-gate goto clean_exit; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3317c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * Application must call C_EncryptInit before calling 3357c478bd9Sstevel@tonic-gate * C_EncryptUpdate. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 3387c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3397c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate session_p->encrypt.flags |= CRYPTO_OPERATION_UPDATE; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate encrypt_update.eu_session = session_p->k_session; 3457c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 3467c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate encrypt_update.eu_datalen = ulPartLen; 3497c478bd9Sstevel@tonic-gate encrypt_update.eu_databuf = (char *)pPart; 3507c478bd9Sstevel@tonic-gate encrypt_update.eu_encrlen = *pulEncryptedPartLen; 3517c478bd9Sstevel@tonic-gate encrypt_update.eu_encrbuf = (char *)pEncryptedPart; 3527c478bd9Sstevel@tonic-gate 353*6d2259e1SDan OpenSolaris Anderson inplace = (session_p->encrypt.flags & CRYPTO_OPERATION_INPLACE_OK) != 0; 354*6d2259e1SDan OpenSolaris Anderson encrypt_update.eu_flags = 355*6d2259e1SDan OpenSolaris Anderson ((inplace && (pEncryptedPart != NULL)) || 356*6d2259e1SDan OpenSolaris Anderson (pPart == pEncryptedPart)) && 357*6d2259e1SDan OpenSolaris Anderson (encrypt_update.eu_encrlen == encrypt_update.eu_datalen) ? 358*6d2259e1SDan OpenSolaris Anderson CRYPTO_INPLACE_OPERATION : 0; 359*6d2259e1SDan OpenSolaris Anderson 3607c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT_UPDATE, 3617c478bd9Sstevel@tonic-gate &encrypt_update)) < 0) { 3627c478bd9Sstevel@tonic-gate if (errno != EINTR) 3637c478bd9Sstevel@tonic-gate break; 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate if (r < 0) { 3667c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 3677c478bd9Sstevel@tonic-gate } else { 3687c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number( 3697c478bd9Sstevel@tonic-gate encrypt_update.eu_return_value); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* 3737c478bd9Sstevel@tonic-gate * If CKR_OK or CKR_BUFFER_TOO_SMALL, set the output length. 3747c478bd9Sstevel@tonic-gate * We don't terminate the current encryption operation. 3757c478bd9Sstevel@tonic-gate */ 3767c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) { 3777c478bd9Sstevel@tonic-gate *pulEncryptedPartLen = encrypt_update.eu_encrlen; 3787c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3797c478bd9Sstevel@tonic-gate return (rv); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate clean_exit: 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * After an error occurred, terminate the current encrypt 3857c478bd9Sstevel@tonic-gate * operation by resetting the active and update flags. 3867c478bd9Sstevel@tonic-gate */ 3877c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 3887c478bd9Sstevel@tonic-gate session_p->encrypt.flags = 0; 3897c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 3907c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate return (rv); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate CK_RV 3977c478bd9Sstevel@tonic-gate C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, 3987c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulLastEncryptedPartLen) 3997c478bd9Sstevel@tonic-gate { 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate CK_RV rv; 4027c478bd9Sstevel@tonic-gate kernel_session_t *session_p; 4037c478bd9Sstevel@tonic-gate boolean_t ses_lock_held = B_FALSE; 4047c478bd9Sstevel@tonic-gate crypto_encrypt_final_t encrypt_final; 4057c478bd9Sstevel@tonic-gate int r; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (!kernel_initialized) 4087c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* Obtain the session pointer. */ 4117c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p); 4127c478bd9Sstevel@tonic-gate if (rv != CKR_OK) 4137c478bd9Sstevel@tonic-gate return (rv); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (pulLastEncryptedPartLen == NULL) { 4167c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD; 4177c478bd9Sstevel@tonic-gate goto clean_exit; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 4217c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * Application must call C_EncryptInit before calling 4257c478bd9Sstevel@tonic-gate * C_EncryptFinal. 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 4287c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4297c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate encrypt_final.ef_session = session_p->k_session; 4337c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex); 4347c478bd9Sstevel@tonic-gate ses_lock_held = B_FALSE; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate encrypt_final.ef_encrlen = *pulLastEncryptedPartLen; 4377c478bd9Sstevel@tonic-gate encrypt_final.ef_encrbuf = (char *)pLastEncryptedPart; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_ENCRYPT_FINAL, 4407c478bd9Sstevel@tonic-gate &encrypt_final)) < 0) { 4417c478bd9Sstevel@tonic-gate if (errno != EINTR) 4427c478bd9Sstevel@tonic-gate break; 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate if (r < 0) { 4457c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED; 4467c478bd9Sstevel@tonic-gate } else { 4477c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(encrypt_final.ef_return_value); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL) 4517c478bd9Sstevel@tonic-gate *pulLastEncryptedPartLen = encrypt_final.ef_encrlen; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) || 4547c478bd9Sstevel@tonic-gate (rv == CKR_OK && pLastEncryptedPart == NULL)) { 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * We will not terminate the active encrypt operation flag, 4577c478bd9Sstevel@tonic-gate * when the application-supplied buffer is too small, or 4587c478bd9Sstevel@tonic-gate * the application asks for the length of buffer to hold 4597c478bd9Sstevel@tonic-gate * the ciphertext. 4607c478bd9Sstevel@tonic-gate */ 4617c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4627c478bd9Sstevel@tonic-gate return (rv); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate clean_exit: 4667c478bd9Sstevel@tonic-gate /* Terminates the active encrypt operation. */ 4677c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex); 4687c478bd9Sstevel@tonic-gate session_p->encrypt.flags = 0; 4697c478bd9Sstevel@tonic-gate ses_lock_held = B_TRUE; 4707c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate return (rv); 4737c478bd9Sstevel@tonic-gate } 474