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
547c883c7Sdinak * Common Development and Distribution License (the "License").
647c883c7Sdinak * 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*726fad2aSDina K Nimeh /*
23*726fad2aSDina K Nimeh * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*726fad2aSDina K Nimeh */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <pthread.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
3223c57df7Smcpowers #include <modes/modes.h>
337c478bd9Sstevel@tonic-gate #include <arcfour.h>
347c478bd9Sstevel@tonic-gate #include "softSession.h"
357c478bd9Sstevel@tonic-gate #include "softObject.h"
367c478bd9Sstevel@tonic-gate #include "softOps.h"
377c478bd9Sstevel@tonic-gate #include "softCrypt.h"
387c478bd9Sstevel@tonic-gate #include "softRSA.h"
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate * Remove padding bytes.
427c478bd9Sstevel@tonic-gate */
437c478bd9Sstevel@tonic-gate CK_RV
soft_remove_pkcs7_padding(CK_BYTE * pData,CK_ULONG padded_len,CK_ULONG * pulDataLen)447c478bd9Sstevel@tonic-gate soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
45*726fad2aSDina K Nimeh CK_ULONG *pulDataLen)
467c478bd9Sstevel@tonic-gate {
47*726fad2aSDina K Nimeh CK_RV rv;
487c478bd9Sstevel@tonic-gate
49*726fad2aSDina K Nimeh #ifdef __sparcv9
50*726fad2aSDina K Nimeh if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
51*726fad2aSDina K Nimeh #else /* !__sparcv9 */
52*726fad2aSDina K Nimeh if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
53*726fad2aSDina K Nimeh #endif /* __sparcv9 */
54*726fad2aSDina K Nimeh return (rv);
557c478bd9Sstevel@tonic-gate
56*726fad2aSDina K Nimeh *pulDataLen = padded_len;
577c478bd9Sstevel@tonic-gate return (CKR_OK);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate * soft_decrypt_init()
637c478bd9Sstevel@tonic-gate *
647c478bd9Sstevel@tonic-gate * Arguments:
657c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
667c478bd9Sstevel@tonic-gate * pMechanism: pointer to CK_MECHANISM struct provided by application
677c478bd9Sstevel@tonic-gate * key_p: pointer to key soft_object_t struct
687c478bd9Sstevel@tonic-gate *
697c478bd9Sstevel@tonic-gate * Description:
707c478bd9Sstevel@tonic-gate * called by C_DecryptInit(). This function calls the corresponding
717c478bd9Sstevel@tonic-gate * decrypt init routine based on the mechanism.
727c478bd9Sstevel@tonic-gate *
737c478bd9Sstevel@tonic-gate * Returns:
747c478bd9Sstevel@tonic-gate * CKR_OK: success
757c478bd9Sstevel@tonic-gate * CKR_HOST_MEMORY: run out of system memory
767c478bd9Sstevel@tonic-gate * CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
777c478bd9Sstevel@tonic-gate * CKR_MECHANISM_INVALID: invalid mechanism type
787c478bd9Sstevel@tonic-gate * CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
797c478bd9Sstevel@tonic-gate * with the specified mechanism
807c478bd9Sstevel@tonic-gate */
817c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt_init(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p)827c478bd9Sstevel@tonic-gate soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
837c478bd9Sstevel@tonic-gate soft_object_t *key_p)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate CK_RV rv;
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate switch (pMechanism->mechanism) {
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate case CKM_DES_ECB:
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate if (key_p->key_type != CKK_DES) {
937c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate goto ecb_common;
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate case CKM_DES3_ECB:
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate if ((key_p->key_type != CKK_DES2) &&
1017c478bd9Sstevel@tonic-gate (key_p->key_type != CKK_DES3)) {
1027c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate ecb_common:
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate return (soft_des_crypt_init_common(session_p, pMechanism,
1087c478bd9Sstevel@tonic-gate key_p, B_FALSE));
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate case CKM_DES_CBC:
1117c478bd9Sstevel@tonic-gate case CKM_DES_CBC_PAD:
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate if (key_p->key_type != CKK_DES) {
1147c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate goto cbc_common;
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate case CKM_DES3_CBC:
1207c478bd9Sstevel@tonic-gate case CKM_DES3_CBC_PAD:
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate if ((key_p->key_type != CKK_DES2) &&
1257c478bd9Sstevel@tonic-gate (key_p->key_type != CKK_DES3)) {
1267c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate cbc_common:
1307c478bd9Sstevel@tonic-gate if ((pMechanism->pParameter == NULL) ||
1317c478bd9Sstevel@tonic-gate (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
1327c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate rv = soft_des_crypt_init_common(session_p, pMechanism,
1367c478bd9Sstevel@tonic-gate key_p, B_FALSE);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
1397c478bd9Sstevel@tonic-gate return (rv);
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
1447c478bd9Sstevel@tonic-gate /* Save Initialization Vector (IV) in the context. */
1457c478bd9Sstevel@tonic-gate (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
1467c478bd9Sstevel@tonic-gate DES_BLOCK_LEN);
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate /* Allocate a context for DES cipher-block chaining. */
1497c478bd9Sstevel@tonic-gate soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
1507c478bd9Sstevel@tonic-gate soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
1517c478bd9Sstevel@tonic-gate soft_des_ctx->ivec, key_p->key_type);
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate if (soft_des_ctx->des_cbc == NULL) {
1547c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->key_sched,
1557c478bd9Sstevel@tonic-gate soft_des_ctx->keysched_len);
1567c478bd9Sstevel@tonic-gate free(soft_des_ctx->key_sched);
1577c478bd9Sstevel@tonic-gate free(session_p->decrypt.context);
1587c478bd9Sstevel@tonic-gate session_p->decrypt.context = NULL;
1597c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
1607c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate return (rv);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate case CKM_AES_ECB:
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate if (key_p->key_type != CKK_AES) {
1707c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate return (soft_aes_crypt_init_common(session_p, pMechanism,
1747c478bd9Sstevel@tonic-gate key_p, B_FALSE));
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate case CKM_AES_CBC:
1777c478bd9Sstevel@tonic-gate case CKM_AES_CBC_PAD:
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate soft_aes_ctx_t *soft_aes_ctx;
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate if (key_p->key_type != CKK_AES) {
1827c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate if ((pMechanism->pParameter == NULL) ||
1867c478bd9Sstevel@tonic-gate (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
1877c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_PARAM_INVALID);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate rv = soft_aes_crypt_init_common(session_p, pMechanism,
1917c478bd9Sstevel@tonic-gate key_p, B_FALSE);
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
1947c478bd9Sstevel@tonic-gate return (rv);
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate /* Save Initialization Vector (IV) in the context. */
2017c478bd9Sstevel@tonic-gate (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
2027c478bd9Sstevel@tonic-gate AES_BLOCK_LEN);
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate /* Allocate a context for AES cipher-block chaining. */
2057c478bd9Sstevel@tonic-gate soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
2067c478bd9Sstevel@tonic-gate soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2077c478bd9Sstevel@tonic-gate soft_aes_ctx->ivec);
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate if (soft_aes_ctx->aes_cbc == NULL) {
2107c478bd9Sstevel@tonic-gate bzero(soft_aes_ctx->key_sched,
2117c478bd9Sstevel@tonic-gate soft_aes_ctx->keysched_len);
2127c478bd9Sstevel@tonic-gate free(soft_aes_ctx->key_sched);
2137c478bd9Sstevel@tonic-gate free(session_p->decrypt.context);
2147c478bd9Sstevel@tonic-gate session_p->decrypt.context = NULL;
2157c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
2167c478bd9Sstevel@tonic-gate return (CKR_HOST_MEMORY);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate return (rv);
2227c478bd9Sstevel@tonic-gate }
22323c57df7Smcpowers case CKM_AES_CTR:
22423c57df7Smcpowers {
22523c57df7Smcpowers soft_aes_ctx_t *soft_aes_ctx;
2267c478bd9Sstevel@tonic-gate
22723c57df7Smcpowers if (key_p->key_type != CKK_AES) {
22823c57df7Smcpowers return (CKR_KEY_TYPE_INCONSISTENT);
22923c57df7Smcpowers }
23023c57df7Smcpowers
23123c57df7Smcpowers if (pMechanism->pParameter == NULL ||
23223c57df7Smcpowers pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
23323c57df7Smcpowers return (CKR_MECHANISM_PARAM_INVALID);
23423c57df7Smcpowers }
23523c57df7Smcpowers
23623c57df7Smcpowers rv = soft_aes_crypt_init_common(session_p, pMechanism,
23723c57df7Smcpowers key_p, B_FALSE);
23823c57df7Smcpowers
23923c57df7Smcpowers if (rv != CKR_OK)
24023c57df7Smcpowers return (rv);
24123c57df7Smcpowers
24223c57df7Smcpowers (void) pthread_mutex_lock(&session_p->session_mutex);
24323c57df7Smcpowers
24423c57df7Smcpowers soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
24523c57df7Smcpowers soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
24623c57df7Smcpowers soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
24723c57df7Smcpowers pMechanism->pParameter);
24823c57df7Smcpowers
24923c57df7Smcpowers if (soft_aes_ctx->aes_cbc == NULL) {
25023c57df7Smcpowers bzero(soft_aes_ctx->key_sched,
25123c57df7Smcpowers soft_aes_ctx->keysched_len);
25223c57df7Smcpowers free(soft_aes_ctx->key_sched);
25323c57df7Smcpowers free(session_p->decrypt.context);
25423c57df7Smcpowers session_p->decrypt.context = NULL;
25523c57df7Smcpowers rv = CKR_HOST_MEMORY;
25623c57df7Smcpowers }
25723c57df7Smcpowers
25823c57df7Smcpowers (void) pthread_mutex_unlock(&session_p->session_mutex);
25923c57df7Smcpowers
26023c57df7Smcpowers return (rv);
26123c57df7Smcpowers }
262f66d273dSizick case CKM_BLOWFISH_CBC:
263f66d273dSizick {
264f66d273dSizick soft_blowfish_ctx_t *soft_blowfish_ctx;
265f66d273dSizick
266f66d273dSizick if (key_p->key_type != CKK_BLOWFISH)
267f66d273dSizick return (CKR_KEY_TYPE_INCONSISTENT);
268f66d273dSizick
269f66d273dSizick if ((pMechanism->pParameter == NULL) ||
270f66d273dSizick (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
271f66d273dSizick return (CKR_MECHANISM_PARAM_INVALID);
272f66d273dSizick
273f66d273dSizick rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
274f66d273dSizick key_p, B_FALSE);
275f66d273dSizick
276f66d273dSizick if (rv != CKR_OK)
277f66d273dSizick return (rv);
278f66d273dSizick
279f66d273dSizick (void) pthread_mutex_lock(&session_p->session_mutex);
280f66d273dSizick
281f66d273dSizick soft_blowfish_ctx =
282f66d273dSizick (soft_blowfish_ctx_t *)session_p->decrypt.context;
283f66d273dSizick
284f66d273dSizick /* Save Initialization Vector in the context. */
285f66d273dSizick (void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
286f66d273dSizick BLOWFISH_BLOCK_LEN);
287f66d273dSizick
288f66d273dSizick /* Allocate a context for CBC */
289f66d273dSizick soft_blowfish_ctx->blowfish_cbc =
290f66d273dSizick (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
291f66d273dSizick soft_blowfish_ctx->keysched_len,
292f66d273dSizick soft_blowfish_ctx->ivec);
293f66d273dSizick
294f66d273dSizick if (soft_blowfish_ctx->blowfish_cbc == NULL) {
295f66d273dSizick bzero(soft_blowfish_ctx->key_sched,
296f66d273dSizick soft_blowfish_ctx->keysched_len);
297f66d273dSizick free(soft_blowfish_ctx->key_sched);
298f66d273dSizick free(session_p->decrypt.context = NULL);
299f66d273dSizick (void) pthread_mutex_unlock(&session_p->session_mutex);
300f66d273dSizick return (CKR_HOST_MEMORY);
301f66d273dSizick }
302f66d273dSizick
303f66d273dSizick (void) pthread_mutex_unlock(&session_p->session_mutex);
304f66d273dSizick return (rv);
305f66d273dSizick }
306f66d273dSizick
3077c478bd9Sstevel@tonic-gate case CKM_RC4:
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate if (key_p->key_type != CKK_RC4) {
3107c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
3147c478bd9Sstevel@tonic-gate B_FALSE));
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate case CKM_RSA_X_509:
3177c478bd9Sstevel@tonic-gate case CKM_RSA_PKCS:
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate if (key_p->key_type != CKK_RSA) {
3207c478bd9Sstevel@tonic-gate return (CKR_KEY_TYPE_INCONSISTENT);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate return (soft_rsa_crypt_init_common(session_p, pMechanism,
3247c478bd9Sstevel@tonic-gate key_p, B_FALSE));
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate default:
3277c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate /*
3337c478bd9Sstevel@tonic-gate * soft_decrypt_common()
3347c478bd9Sstevel@tonic-gate *
3357c478bd9Sstevel@tonic-gate * Arguments:
3367c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
3377c478bd9Sstevel@tonic-gate * pEncrypted: pointer to the encrypted data as input
3387c478bd9Sstevel@tonic-gate * ulEncryptedLen: length of the input data
3397c478bd9Sstevel@tonic-gate * pData: pointer to the output data contains plaintext
3407c478bd9Sstevel@tonic-gate * pulDataLen: pointer to the length of the output data
3417c478bd9Sstevel@tonic-gate * Update: boolean flag indicates caller is soft_decrypt
3427c478bd9Sstevel@tonic-gate * or soft_decrypt_update
3437c478bd9Sstevel@tonic-gate *
3447c478bd9Sstevel@tonic-gate * Description:
3457c478bd9Sstevel@tonic-gate * This function calls the corresponding decrypt routine based
3467c478bd9Sstevel@tonic-gate * on the mechanism.
3477c478bd9Sstevel@tonic-gate *
3487c478bd9Sstevel@tonic-gate * Returns:
3497c478bd9Sstevel@tonic-gate * see soft_decrypt_common().
3507c478bd9Sstevel@tonic-gate */
3517c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt_common(soft_session_t * session_p,CK_BYTE_PTR pEncrypted,CK_ULONG ulEncryptedLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen,boolean_t Update)3527c478bd9Sstevel@tonic-gate soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
3537c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
3547c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulDataLen, boolean_t Update)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate switch (mechanism) {
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate case CKM_DES_ECB:
3627c478bd9Sstevel@tonic-gate case CKM_DES_CBC:
3637c478bd9Sstevel@tonic-gate case CKM_DES3_ECB:
3647c478bd9Sstevel@tonic-gate case CKM_DES3_CBC:
36547c883c7Sdinak
36647c883c7Sdinak if (ulEncryptedLen == 0) {
36747c883c7Sdinak *pulDataLen = 0;
36847c883c7Sdinak return (CKR_OK);
36947c883c7Sdinak }
37047c883c7Sdinak /* FALLTHROUGH */
37147c883c7Sdinak
37247c883c7Sdinak case CKM_DES_CBC_PAD:
3737c478bd9Sstevel@tonic-gate case CKM_DES3_CBC_PAD:
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate return (soft_des_decrypt_common(session_p, pEncrypted,
3767c478bd9Sstevel@tonic-gate ulEncryptedLen, pData, pulDataLen, Update));
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate case CKM_AES_ECB:
3797c478bd9Sstevel@tonic-gate case CKM_AES_CBC:
38023c57df7Smcpowers case CKM_AES_CTR:
38147c883c7Sdinak
38247c883c7Sdinak if (ulEncryptedLen == 0) {
38347c883c7Sdinak *pulDataLen = 0;
38447c883c7Sdinak return (CKR_OK);
38547c883c7Sdinak }
38647c883c7Sdinak /* FALLTHROUGH */
38747c883c7Sdinak
3887c478bd9Sstevel@tonic-gate case CKM_AES_CBC_PAD:
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate return (soft_aes_decrypt_common(session_p, pEncrypted,
3917c478bd9Sstevel@tonic-gate ulEncryptedLen, pData, pulDataLen, Update));
3927c478bd9Sstevel@tonic-gate
393f66d273dSizick case CKM_BLOWFISH_CBC:
394f66d273dSizick
39547c883c7Sdinak if (ulEncryptedLen == 0) {
39647c883c7Sdinak *pulDataLen = 0;
39747c883c7Sdinak return (CKR_OK);
39847c883c7Sdinak }
39947c883c7Sdinak
400f66d273dSizick return (soft_blowfish_decrypt_common(session_p, pEncrypted,
401f66d273dSizick ulEncryptedLen, pData, pulDataLen, Update));
402f66d273dSizick
4037c478bd9Sstevel@tonic-gate case CKM_RC4:
4047c478bd9Sstevel@tonic-gate
40547c883c7Sdinak if (ulEncryptedLen == 0) {
40647c883c7Sdinak *pulDataLen = 0;
40747c883c7Sdinak return (CKR_OK);
40847c883c7Sdinak }
4097c478bd9Sstevel@tonic-gate
41047c883c7Sdinak
41147c883c7Sdinak return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
41247c883c7Sdinak ulEncryptedLen, pData, pulDataLen));
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate case CKM_RSA_X_509:
4157c478bd9Sstevel@tonic-gate case CKM_RSA_PKCS:
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate return (soft_rsa_decrypt_common(session_p, pEncrypted,
4187c478bd9Sstevel@tonic-gate ulEncryptedLen, pData, pulDataLen, mechanism));
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate default:
4217c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate
4277c478bd9Sstevel@tonic-gate /*
4287c478bd9Sstevel@tonic-gate * soft_decrypt()
4297c478bd9Sstevel@tonic-gate *
4307c478bd9Sstevel@tonic-gate * Arguments:
4317c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
4327c478bd9Sstevel@tonic-gate * pEncryptedData: pointer to the encrypted data as input
4337c478bd9Sstevel@tonic-gate * ulEncryptedDataLen: length of the input data
4347c478bd9Sstevel@tonic-gate * pData: pointer to the output data contains plaintext
4357c478bd9Sstevel@tonic-gate * pulDataLen: pointer to the length of the output data
4367c478bd9Sstevel@tonic-gate *
4377c478bd9Sstevel@tonic-gate * Description:
4387c478bd9Sstevel@tonic-gate * called by C_Decrypt(). This function calls the soft_decrypt_common
4397c478bd9Sstevel@tonic-gate * routine.
4407c478bd9Sstevel@tonic-gate *
4417c478bd9Sstevel@tonic-gate * Returns:
4427c478bd9Sstevel@tonic-gate * see soft_decrypt_common().
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt(soft_session_t * session_p,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)4457c478bd9Sstevel@tonic-gate soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
4467c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
4477c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulDataLen)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate return (soft_decrypt_common(session_p, pEncryptedData,
4517c478bd9Sstevel@tonic-gate ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate * soft_decrypt_update()
4577c478bd9Sstevel@tonic-gate *
4587c478bd9Sstevel@tonic-gate * Arguments:
4597c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
4607c478bd9Sstevel@tonic-gate * pEncryptedPart: pointer to the encrypted data as input
4617c478bd9Sstevel@tonic-gate * ulEncryptedPartLen: length of the input data
4627c478bd9Sstevel@tonic-gate * pPart: pointer to the output data contains plaintext
4637c478bd9Sstevel@tonic-gate * pulPartLen: pointer to the length of the output data
4647c478bd9Sstevel@tonic-gate *
4657c478bd9Sstevel@tonic-gate * Description:
4667c478bd9Sstevel@tonic-gate * called by C_DecryptUpdate(). This function calls the
4677c478bd9Sstevel@tonic-gate * soft_decrypt_common routine (with update flag on).
4687c478bd9Sstevel@tonic-gate *
4697c478bd9Sstevel@tonic-gate * Returns:
4707c478bd9Sstevel@tonic-gate * see soft_decrypt_common().
4717c478bd9Sstevel@tonic-gate */
4727c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt_update(soft_session_t * session_p,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)4737c478bd9Sstevel@tonic-gate soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
4747c478bd9Sstevel@tonic-gate CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
4757c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulPartLen)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate switch (mechanism) {
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate case CKM_DES_ECB:
4827c478bd9Sstevel@tonic-gate case CKM_DES_CBC:
4837c478bd9Sstevel@tonic-gate case CKM_DES_CBC_PAD:
4847c478bd9Sstevel@tonic-gate case CKM_DES3_ECB:
4857c478bd9Sstevel@tonic-gate case CKM_DES3_CBC:
4867c478bd9Sstevel@tonic-gate case CKM_DES3_CBC_PAD:
4877c478bd9Sstevel@tonic-gate case CKM_AES_ECB:
4887c478bd9Sstevel@tonic-gate case CKM_AES_CBC:
4897c478bd9Sstevel@tonic-gate case CKM_AES_CBC_PAD:
49023c57df7Smcpowers case CKM_AES_CTR:
491f66d273dSizick case CKM_BLOWFISH_CBC:
49247c883c7Sdinak case CKM_RC4:
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate return (soft_decrypt_common(session_p, pEncryptedPart,
4957c478bd9Sstevel@tonic-gate ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate default:
4987c478bd9Sstevel@tonic-gate /* PKCS11: The mechanism only supports single-part operation. */
4997c478bd9Sstevel@tonic-gate return (CKR_MECHANISM_INVALID);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate * soft_decrypt_final()
5077c478bd9Sstevel@tonic-gate *
5087c478bd9Sstevel@tonic-gate * Arguments:
5097c478bd9Sstevel@tonic-gate * session_p: pointer to soft_session_t struct
5107c478bd9Sstevel@tonic-gate * pLastPart: pointer to the last recovered data part
5117c478bd9Sstevel@tonic-gate * pulLastPartLen: pointer to the length of the last recovered data part
5127c478bd9Sstevel@tonic-gate *
5137c478bd9Sstevel@tonic-gate * Description:
5147c478bd9Sstevel@tonic-gate * called by C_DecryptFinal().
5157c478bd9Sstevel@tonic-gate *
5167c478bd9Sstevel@tonic-gate * Returns:
5177c478bd9Sstevel@tonic-gate * CKR_OK: success
5187c478bd9Sstevel@tonic-gate * CKR_FUNCTION_FAILED: decrypt final function failed
5197c478bd9Sstevel@tonic-gate * CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
5207c478bd9Sstevel@tonic-gate */
5217c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt_final(soft_session_t * session_p,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)5227c478bd9Sstevel@tonic-gate soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
5237c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulLastPartLen)
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
5277c478bd9Sstevel@tonic-gate CK_ULONG out_len;
5287c478bd9Sstevel@tonic-gate CK_RV rv = CKR_OK;
5297c478bd9Sstevel@tonic-gate int rc;
5307c478bd9Sstevel@tonic-gate
5317c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate if (session_p->decrypt.context == NULL) {
5347c478bd9Sstevel@tonic-gate rv = CKR_OPERATION_NOT_INITIALIZED;
5357c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
5367c478bd9Sstevel@tonic-gate goto clean2;
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate switch (mechanism) {
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate case CKM_DES_CBC_PAD:
5417c478bd9Sstevel@tonic-gate case CKM_DES3_CBC_PAD:
5427c478bd9Sstevel@tonic-gate {
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx;
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate /*
5497c478bd9Sstevel@tonic-gate * We should have only one block of data left in the
5507c478bd9Sstevel@tonic-gate * remaining buffer.
5517c478bd9Sstevel@tonic-gate */
5527c478bd9Sstevel@tonic-gate if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
5537c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
5547c478bd9Sstevel@tonic-gate rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
5557c478bd9Sstevel@tonic-gate /* Cleanup memory space. */
5567c478bd9Sstevel@tonic-gate free(soft_des_ctx->des_cbc);
5577c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->key_sched,
5587c478bd9Sstevel@tonic-gate soft_des_ctx->keysched_len);
5597c478bd9Sstevel@tonic-gate free(soft_des_ctx->key_sched);
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate goto clean1;
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate out_len = DES_BLOCK_LEN;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate /*
5677c478bd9Sstevel@tonic-gate * If application asks for the length of the output buffer
5687c478bd9Sstevel@tonic-gate * to hold the plaintext?
5697c478bd9Sstevel@tonic-gate */
5707c478bd9Sstevel@tonic-gate if (pLastPart == NULL) {
5717c478bd9Sstevel@tonic-gate *pulLastPartLen = out_len;
5727c478bd9Sstevel@tonic-gate rv = CKR_OK;
5737c478bd9Sstevel@tonic-gate goto clean2;
5747c478bd9Sstevel@tonic-gate } else {
5757c478bd9Sstevel@tonic-gate crypto_data_t out;
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /* Copy remaining data to the output buffer. */
5787c478bd9Sstevel@tonic-gate (void) memcpy(pLastPart, soft_des_ctx->data,
5797c478bd9Sstevel@tonic-gate DES_BLOCK_LEN);
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate out.cd_format = CRYPTO_DATA_RAW;
5827c478bd9Sstevel@tonic-gate out.cd_offset = 0;
5837c478bd9Sstevel@tonic-gate out.cd_length = DES_BLOCK_LEN;
5847c478bd9Sstevel@tonic-gate out.cd_raw.iov_base = (char *)pLastPart;
5857c478bd9Sstevel@tonic-gate out.cd_raw.iov_len = DES_BLOCK_LEN;
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate /* Decrypt final block of data. */
5887c478bd9Sstevel@tonic-gate rc = des_decrypt_contiguous_blocks(
5897c478bd9Sstevel@tonic-gate (des_ctx_t *)soft_des_ctx->des_cbc,
5907c478bd9Sstevel@tonic-gate (char *)pLastPart, DES_BLOCK_LEN, &out);
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate if (rc == 0) {
5937c478bd9Sstevel@tonic-gate /*
5947c478bd9Sstevel@tonic-gate * Remove padding bytes after decryption of
5957c478bd9Sstevel@tonic-gate * ciphertext block to produce the original
5967c478bd9Sstevel@tonic-gate * plaintext.
5977c478bd9Sstevel@tonic-gate */
5987c478bd9Sstevel@tonic-gate rv = soft_remove_pkcs7_padding(pLastPart,
599*726fad2aSDina K Nimeh DES_BLOCK_LEN, &out_len);
6007c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
6017c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
6027c478bd9Sstevel@tonic-gate else
6037c478bd9Sstevel@tonic-gate *pulLastPartLen = out_len;
6047c478bd9Sstevel@tonic-gate } else {
6057c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
6067c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate /* Cleanup memory space. */
6107c478bd9Sstevel@tonic-gate free(soft_des_ctx->des_cbc);
6117c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->key_sched,
6127c478bd9Sstevel@tonic-gate soft_des_ctx->keysched_len);
6137c478bd9Sstevel@tonic-gate free(soft_des_ctx->key_sched);
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate break;
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate case CKM_DES_CBC:
6217c478bd9Sstevel@tonic-gate case CKM_DES_ECB:
6227c478bd9Sstevel@tonic-gate case CKM_DES3_CBC:
6237c478bd9Sstevel@tonic-gate case CKM_DES3_ECB:
6247c478bd9Sstevel@tonic-gate {
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate soft_des_ctx_t *soft_des_ctx;
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
6317c478bd9Sstevel@tonic-gate * so when the final is called, the remaining buffer
6327c478bd9Sstevel@tonic-gate * should not contain any more data.
6337c478bd9Sstevel@tonic-gate */
6347c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
6357c478bd9Sstevel@tonic-gate if (soft_des_ctx->remain_len != 0) {
6367c478bd9Sstevel@tonic-gate rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
6377c478bd9Sstevel@tonic-gate } else {
6387c478bd9Sstevel@tonic-gate if (pLastPart == NULL)
6397c478bd9Sstevel@tonic-gate goto clean2;
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate /* Cleanup memory space. */
6437c478bd9Sstevel@tonic-gate free(soft_des_ctx->des_cbc);
6447c478bd9Sstevel@tonic-gate bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
6457c478bd9Sstevel@tonic-gate free(soft_des_ctx->key_sched);
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate break;
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate case CKM_AES_CBC_PAD:
6517c478bd9Sstevel@tonic-gate {
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate soft_aes_ctx_t *soft_aes_ctx;
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate /*
6587c478bd9Sstevel@tonic-gate * We should have only one block of data left in the
6597c478bd9Sstevel@tonic-gate * remaining buffer.
6607c478bd9Sstevel@tonic-gate */
6617c478bd9Sstevel@tonic-gate if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
6627c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
6637c478bd9Sstevel@tonic-gate rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
6647c478bd9Sstevel@tonic-gate /* Cleanup memory space. */
6657c478bd9Sstevel@tonic-gate free(soft_aes_ctx->aes_cbc);
6667c478bd9Sstevel@tonic-gate bzero(soft_aes_ctx->key_sched,
6677c478bd9Sstevel@tonic-gate soft_aes_ctx->keysched_len);
6687c478bd9Sstevel@tonic-gate free(soft_aes_ctx->key_sched);
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate goto clean1;
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate out_len = AES_BLOCK_LEN;
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate /*
6767c478bd9Sstevel@tonic-gate * If application asks for the length of the output buffer
6777c478bd9Sstevel@tonic-gate * to hold the plaintext?
6787c478bd9Sstevel@tonic-gate */
6797c478bd9Sstevel@tonic-gate if (pLastPart == NULL) {
6807c478bd9Sstevel@tonic-gate *pulLastPartLen = out_len;
6817c478bd9Sstevel@tonic-gate rv = CKR_OK;
6827c478bd9Sstevel@tonic-gate goto clean2;
6837c478bd9Sstevel@tonic-gate } else {
6847c478bd9Sstevel@tonic-gate crypto_data_t out;
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate /* Copy remaining data to the output buffer. */
6877c478bd9Sstevel@tonic-gate (void) memcpy(pLastPart, soft_aes_ctx->data,
6887c478bd9Sstevel@tonic-gate AES_BLOCK_LEN);
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate out.cd_format = CRYPTO_DATA_RAW;
6917c478bd9Sstevel@tonic-gate out.cd_offset = 0;
6927c478bd9Sstevel@tonic-gate out.cd_length = AES_BLOCK_LEN;
6937c478bd9Sstevel@tonic-gate out.cd_raw.iov_base = (char *)pLastPart;
6947c478bd9Sstevel@tonic-gate out.cd_raw.iov_len = AES_BLOCK_LEN;
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate /* Decrypt final block of data. */
6977c478bd9Sstevel@tonic-gate rc = aes_decrypt_contiguous_blocks(
6987c478bd9Sstevel@tonic-gate (aes_ctx_t *)soft_aes_ctx->aes_cbc,
6997c478bd9Sstevel@tonic-gate (char *)pLastPart, AES_BLOCK_LEN, &out);
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate if (rc == 0) {
7027c478bd9Sstevel@tonic-gate /*
7037c478bd9Sstevel@tonic-gate * Remove padding bytes after decryption of
7047c478bd9Sstevel@tonic-gate * ciphertext block to produce the original
7057c478bd9Sstevel@tonic-gate * plaintext.
7067c478bd9Sstevel@tonic-gate */
7077c478bd9Sstevel@tonic-gate rv = soft_remove_pkcs7_padding(pLastPart,
708*726fad2aSDina K Nimeh AES_BLOCK_LEN, &out_len);
7097c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
7107c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
7117c478bd9Sstevel@tonic-gate else
7127c478bd9Sstevel@tonic-gate *pulLastPartLen = out_len;
7137c478bd9Sstevel@tonic-gate } else {
7147c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
7157c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate /* Cleanup memory space. */
7197c478bd9Sstevel@tonic-gate free(soft_aes_ctx->aes_cbc);
7207c478bd9Sstevel@tonic-gate bzero(soft_aes_ctx->key_sched,
7217c478bd9Sstevel@tonic-gate soft_aes_ctx->keysched_len);
7227c478bd9Sstevel@tonic-gate free(soft_aes_ctx->key_sched);
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate break;
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate case CKM_AES_CBC:
7307c478bd9Sstevel@tonic-gate case CKM_AES_ECB:
7317c478bd9Sstevel@tonic-gate {
7327c478bd9Sstevel@tonic-gate soft_aes_ctx_t *soft_aes_ctx;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
7357c478bd9Sstevel@tonic-gate /*
7367c478bd9Sstevel@tonic-gate * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
7377c478bd9Sstevel@tonic-gate * so when the final is called, the remaining buffer
7387c478bd9Sstevel@tonic-gate * should not contain any more data.
7397c478bd9Sstevel@tonic-gate */
7407c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
7417c478bd9Sstevel@tonic-gate if (soft_aes_ctx->remain_len != 0) {
7427c478bd9Sstevel@tonic-gate rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
7437c478bd9Sstevel@tonic-gate } else {
7447c478bd9Sstevel@tonic-gate if (pLastPart == NULL)
7457c478bd9Sstevel@tonic-gate goto clean2;
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate /* Cleanup memory space. */
7497c478bd9Sstevel@tonic-gate free(soft_aes_ctx->aes_cbc);
7507c478bd9Sstevel@tonic-gate bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
7517c478bd9Sstevel@tonic-gate free(soft_aes_ctx->key_sched);
7527c478bd9Sstevel@tonic-gate
7537c478bd9Sstevel@tonic-gate break;
7547c478bd9Sstevel@tonic-gate }
75523c57df7Smcpowers case CKM_AES_CTR:
75623c57df7Smcpowers {
75723c57df7Smcpowers crypto_data_t out;
75823c57df7Smcpowers soft_aes_ctx_t *soft_aes_ctx;
75923c57df7Smcpowers ctr_ctx_t *ctr_ctx;
76023c57df7Smcpowers size_t len;
7617c478bd9Sstevel@tonic-gate
76223c57df7Smcpowers soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
76323c57df7Smcpowers ctr_ctx = soft_aes_ctx->aes_cbc;
76423c57df7Smcpowers len = ctr_ctx->ctr_remainder_len;
76523c57df7Smcpowers if (pLastPart == NULL) {
76623c57df7Smcpowers *pulLastPartLen = len;
76723c57df7Smcpowers goto clean1;
76823c57df7Smcpowers }
76923c57df7Smcpowers if (len > 0) {
77023c57df7Smcpowers out.cd_format = CRYPTO_DATA_RAW;
77123c57df7Smcpowers out.cd_offset = 0;
77223c57df7Smcpowers out.cd_length = len;
77323c57df7Smcpowers out.cd_raw.iov_base = (char *)pLastPart;
77423c57df7Smcpowers out.cd_raw.iov_len = len;
77523c57df7Smcpowers
77623c57df7Smcpowers rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
77723c57df7Smcpowers if (rv == CRYPTO_DATA_LEN_RANGE)
77823c57df7Smcpowers rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
77923c57df7Smcpowers }
78023c57df7Smcpowers if (rv == CRYPTO_BUFFER_TOO_SMALL) {
78123c57df7Smcpowers *pulLastPartLen = len;
78223c57df7Smcpowers goto clean1;
78323c57df7Smcpowers }
78423c57df7Smcpowers
78523c57df7Smcpowers /* Cleanup memory space. */
78623c57df7Smcpowers free(ctr_ctx);
78723c57df7Smcpowers bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
78823c57df7Smcpowers free(soft_aes_ctx->key_sched);
78923c57df7Smcpowers
79023c57df7Smcpowers break;
79123c57df7Smcpowers }
792f66d273dSizick case CKM_BLOWFISH_CBC:
793f66d273dSizick {
794f66d273dSizick soft_blowfish_ctx_t *soft_blowfish_ctx;
795f66d273dSizick
796f66d273dSizick soft_blowfish_ctx =
797f66d273dSizick (soft_blowfish_ctx_t *)session_p->decrypt.context;
798f66d273dSizick
799f66d273dSizick *pulLastPartLen = 0;
800f66d273dSizick if (soft_blowfish_ctx->remain_len != 0)
801f66d273dSizick rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
802f66d273dSizick else {
803f66d273dSizick if (pLastPart == NULL)
804f66d273dSizick goto clean2;
805f66d273dSizick }
806f66d273dSizick
807f66d273dSizick free(soft_blowfish_ctx->blowfish_cbc);
808f66d273dSizick bzero(soft_blowfish_ctx->key_sched,
809f66d273dSizick soft_blowfish_ctx->keysched_len);
810f66d273dSizick free(soft_blowfish_ctx->key_sched);
811f66d273dSizick
812f66d273dSizick break;
813f66d273dSizick }
814f66d273dSizick
8157c478bd9Sstevel@tonic-gate case CKM_RC4:
8167c478bd9Sstevel@tonic-gate {
8177c478bd9Sstevel@tonic-gate ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
8187c478bd9Sstevel@tonic-gate bzero(key, sizeof (*key));
8197c478bd9Sstevel@tonic-gate *pulLastPartLen = 0;
8207c478bd9Sstevel@tonic-gate break;
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate default:
8247c478bd9Sstevel@tonic-gate /* PKCS11: The mechanism only supports single-part operation. */
8257c478bd9Sstevel@tonic-gate rv = CKR_MECHANISM_INVALID;
8267c478bd9Sstevel@tonic-gate break;
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate clean1:
8307c478bd9Sstevel@tonic-gate free(session_p->decrypt.context);
8317c478bd9Sstevel@tonic-gate session_p->decrypt.context = NULL;
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate clean2:
8347c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate return (rv);
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate }
839