2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include <pthread.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A#include <strings.h>
2N/A#include <sys/types.h>
2N/A#include <security/cryptoki.h>
2N/A#include <modes/modes.h>
2N/A#include <arcfour/arcfour.h>
2N/A#include "softSession.h"
2N/A#include "softObject.h"
2N/A#include "softOps.h"
2N/A#include "softCrypt.h"
2N/A#include "softRSA.h"
2N/A
2N/A/*
2N/A * Remove padding bytes.
2N/A */
2N/ACK_RV
2N/Asoft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
2N/A CK_ULONG *pulDataLen)
2N/A{
2N/A CK_RV rv;
2N/A
2N/A#ifdef __sparcv9
2N/A if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
2N/A#else /* !__sparcv9 */
2N/A if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
2N/A#endif /* __sparcv9 */
2N/A return (rv);
2N/A
2N/A *pulDataLen = padded_len;
2N/A return (CKR_OK);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * soft_decrypt_init()
2N/A *
2N/A * Arguments:
2N/A * session_p: pointer to soft_session_t struct
2N/A * pMechanism: pointer to CK_MECHANISM struct provided by application
2N/A * key_p: pointer to key soft_object_t struct
2N/A *
2N/A * Description:
2N/A * called by C_DecryptInit(). This function calls the corresponding
2N/A * decrypt init routine based on the mechanism.
2N/A *
2N/A * Returns:
2N/A * CKR_OK: success
2N/A * CKR_HOST_MEMORY: ran out of system memory
2N/A * CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
2N/A * CKR_MECHANISM_INVALID: invalid mechanism type
2N/A * CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
2N/A * with the specified mechanism
2N/A */
2N/ACK_RV
2N/Asoft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
2N/A soft_object_t *key_p)
2N/A{
2N/A
2N/A CK_RV rv;
2N/A
2N/A session_p->pk11_functions = NULL;
2N/A session_p->low_level_functions = NULL;
2N/A
2N/A switch (pMechanism->mechanism) {
2N/A
2N/A case CKM_DES_ECB:
2N/A
2N/A if (key_p->key_type != CKK_DES) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A goto ecb_common;
2N/A
2N/A case CKM_DES3_ECB:
2N/A {
2N/A soft_des_ctx_t *soft_des_ctx;
2N/A
2N/A if ((key_p->key_type != CKK_DES2) &&
2N/A (key_p->key_type != CKK_DES3)) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/Aecb_common:
2N/A rv = soft_des_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP);
2N/A
2N/A if (rv != CKR_OK) {
2N/A return (rv);
2N/A }
2N/A
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
2N/A
2N/A /* Allocate a context */
2N/A soft_des_ctx->mode_ctx = (void *)des_ecb_ctx_init(
2N/A soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
2N/A key_p->key_type);
2N/A
2N/A if (soft_des_ctx->mode_ctx == NULL) {
2N/A bzero(soft_des_ctx->key_sched,
2N/A soft_des_ctx->keysched_len);
2N/A free(soft_des_ctx->key_sched);
2N/A free(session_p->decrypt.context);
2N/A session_p->decrypt.context = NULL;
2N/A rv = CKR_HOST_MEMORY;
2N/A }
2N/A
2N/A if (pMechanism->mechanism == CKM_DES_ECB) {
2N/A session_p->pk11_functions = &pk11_des_common_functions;
2N/A } else {
2N/A session_p->pk11_functions = &pk11_des3_common_functions;
2N/A }
2N/A session_p->low_level_functions =
2N/A des_low_level_funcs(soft_des_ctx->mode_ctx,
2N/A B_FALSE /* decrypt */);
2N/A
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A
2N/A return (rv);
2N/A }
2N/A
2N/A case CKM_DES_CBC:
2N/A case CKM_DES_CBC_PAD:
2N/A
2N/A if (key_p->key_type != CKK_DES) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A goto cbc_common;
2N/A
2N/A case CKM_DES3_CBC:
2N/A case CKM_DES3_CBC_PAD:
2N/A {
2N/A soft_des_ctx_t *soft_des_ctx;
2N/A
2N/A if ((key_p->key_type != CKK_DES2) &&
2N/A (key_p->key_type != CKK_DES3)) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/Acbc_common:
2N/A if ((pMechanism->pParameter == NULL) ||
2N/A (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
2N/A return (CKR_MECHANISM_PARAM_INVALID);
2N/A }
2N/A
2N/A rv = soft_des_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP);
2N/A
2N/A if (rv != CKR_OK)
2N/A return (rv);
2N/A
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
2N/A /* Save Initialization Vector (IV) in the context. */
2N/A (void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
2N/A DES_BLOCK_LEN);
2N/A
2N/A /* Allocate a context for DES cipher-block chaining. */
2N/A soft_des_ctx->mode_ctx = (void *)des_cbc_ctx_init(
2N/A soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
2N/A soft_des_ctx->ivec, key_p->key_type);
2N/A
2N/A if (soft_des_ctx->mode_ctx == NULL) {
2N/A bzero(soft_des_ctx->key_sched,
2N/A soft_des_ctx->keysched_len);
2N/A free(soft_des_ctx->key_sched);
2N/A free(session_p->decrypt.context);
2N/A session_p->decrypt.context = NULL;
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A return (CKR_HOST_MEMORY);
2N/A }
2N/A
2N/A if (pMechanism->mechanism == CKM_DES_CBC) {
2N/A session_p->pk11_functions = &pk11_des_common_functions;
2N/A session_p->low_level_functions =
2N/A des_low_level_funcs(soft_des_ctx->mode_ctx,
2N/A B_FALSE /* decrypt */);
2N/A } else if (pMechanism->mechanism == CKM_DES3_CBC) {
2N/A session_p->pk11_functions = &pk11_des3_common_functions;
2N/A session_p->low_level_functions =
2N/A des_low_level_funcs(soft_des_ctx->mode_ctx,
2N/A B_FALSE /* decrypt */);
2N/A }
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A
2N/A return (rv);
2N/A }
2N/A case CKM_AES_ECB:
2N/A if (key_p->key_type != CKK_AES) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A rv = soft_aes_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP);
2N/A
2N/A if (rv != CKR_OK)
2N/A return (rv);
2N/A
2N/A#ifdef __amd64
2N/A if (soft_intel_aes_instructions_present()) {
2N/A#else
2N/A /* LINTED E_CONSTANT_CONDITION */
2N/A if (1) {
2N/A#endif /* __amd64 */
2N/A soft_aes_ctx_t *soft_aes_ctx;
2N/A
2N/A /*
2N/A * Allocate a context for AES Electronic Code Book.
2N/A * This is done to use combined
2N/A * AES/ECB mode optimization. Otherwise, the
2N/A * block-level AES decrypt functions are
2N/A * called directly.
2N/A */
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A soft_aes_ctx =
2N/A (soft_aes_ctx_t *)session_p->decrypt.context;
2N/A
2N/A soft_aes_ctx->mode_ctx = (void *)aes_ecb_ctx_init(
2N/A soft_aes_ctx->key_sched,
2N/A soft_aes_ctx->keysched_len);
2N/A
2N/A if (soft_aes_ctx->mode_ctx == NULL) {
2N/A bzero(soft_aes_ctx->key_sched,
2N/A soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A free(session_p->decrypt.context);
2N/A session_p->decrypt.context = NULL;
2N/A (void) pthread_mutex_unlock(
2N/A &session_p->session_mutex);
2N/A return (CKR_HOST_MEMORY);
2N/A }
2N/A
2N/A session_p->pk11_functions = &pk11_aes_ecb_functions;
2N/A session_p->low_level_functions =
2N/A aes_low_level_funcs(soft_aes_ctx->mode_ctx,
2N/A B_FALSE /* decrypt */);
2N/A
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A }
2N/A
2N/A return (rv);
2N/A
2N/A case CKM_AES_CBC:
2N/A case CKM_AES_CBC_PAD:
2N/A {
2N/A soft_aes_ctx_t *soft_aes_ctx;
2N/A
2N/A if (key_p->key_type != CKK_AES) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A if ((pMechanism->pParameter == NULL) ||
2N/A (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
2N/A return (CKR_MECHANISM_PARAM_INVALID);
2N/A }
2N/A
2N/A rv = soft_aes_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP);
2N/A
2N/A if (rv != CKR_OK)
2N/A return (rv);
2N/A
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
2N/A
2N/A /* Save Initialization Vector (IV) in the context. */
2N/A (void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
2N/A AES_BLOCK_LEN);
2N/A
2N/A /* Allocate a context for AES cipher-block chaining. */
2N/A soft_aes_ctx->mode_ctx = (void *)aes_cbc_ctx_init(
2N/A soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2N/A soft_aes_ctx->ivec);
2N/A
2N/A if (soft_aes_ctx->mode_ctx == NULL) {
2N/A bzero(soft_aes_ctx->key_sched,
2N/A soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A free(session_p->decrypt.context);
2N/A session_p->decrypt.context = NULL;
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A return (CKR_HOST_MEMORY);
2N/A }
2N/A
2N/A if (pMechanism->mechanism != CKM_AES_CBC_PAD) {
2N/A session_p->pk11_functions = &pk11_aes_cbc_functions;
2N/A session_p->low_level_functions =
2N/A aes_low_level_funcs(soft_aes_ctx->mode_ctx,
2N/A B_FALSE /* decrypt */);
2N/A }
2N/A
2N/A
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A
2N/A return (rv);
2N/A }
2N/A case CKM_AES_CTR:
2N/A {
2N/A soft_aes_ctx_t *soft_aes_ctx;
2N/A
2N/A if (key_p->key_type != CKK_AES) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A if (pMechanism->pParameter == NULL ||
2N/A pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
2N/A return (CKR_MECHANISM_PARAM_INVALID);
2N/A }
2N/A
2N/A rv = soft_aes_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP);
2N/A
2N/A if (rv != CKR_OK)
2N/A return (rv);
2N/A
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
2N/A soft_aes_ctx->mode_ctx = aes_ctr_ctx_init(
2N/A soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2N/A pMechanism->pParameter);
2N/A
2N/A if (soft_aes_ctx->mode_ctx == NULL) {
2N/A bzero(soft_aes_ctx->key_sched,
2N/A soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A free(session_p->decrypt.context);
2N/A session_p->decrypt.context = NULL;
2N/A rv = CKR_HOST_MEMORY;
2N/A }
2N/A
2N/A session_p->pk11_functions = &pk11_aes_ctr_functions;
2N/A session_p->low_level_functions =
2N/A aes_low_level_funcs(soft_aes_ctx->mode_ctx,
2N/A B_FALSE /* decrypt */);
2N/A
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A
2N/A return (rv);
2N/A }
2N/A case CKM_BLOWFISH_CBC:
2N/A {
2N/A soft_blowfish_ctx_t *soft_blowfish_ctx;
2N/A
2N/A if (key_p->key_type != CKK_BLOWFISH)
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A
2N/A if ((pMechanism->pParameter == NULL) ||
2N/A (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
2N/A return (CKR_MECHANISM_PARAM_INVALID);
2N/A
2N/A rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP);
2N/A
2N/A if (rv != CKR_OK)
2N/A return (rv);
2N/A
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A soft_blowfish_ctx =
2N/A (soft_blowfish_ctx_t *)session_p->decrypt.context;
2N/A
2N/A /* Save Initialization Vector in the context. */
2N/A (void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
2N/A BLOWFISH_BLOCK_LEN);
2N/A
2N/A /* Allocate a context for CBC */
2N/A soft_blowfish_ctx->mode_ctx =
2N/A (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
2N/A soft_blowfish_ctx->keysched_len,
2N/A soft_blowfish_ctx->ivec);
2N/A
2N/A if (soft_blowfish_ctx->mode_ctx == NULL) {
2N/A bzero(soft_blowfish_ctx->key_sched,
2N/A soft_blowfish_ctx->keysched_len);
2N/A free(soft_blowfish_ctx->key_sched);
2N/A free(session_p->decrypt.context = NULL);
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A return (CKR_HOST_MEMORY);
2N/A }
2N/A
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A return (rv);
2N/A }
2N/A
2N/A case CKM_RC4:
2N/A
2N/A if (key_p->key_type != CKK_RC4) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
2N/A SOFT_DECRYPT_OP));
2N/A
2N/A case CKM_RSA_X_509:
2N/A case CKM_RSA_PKCS:
2N/A
2N/A if (key_p->key_type != CKK_RSA) {
2N/A return (CKR_KEY_TYPE_INCONSISTENT);
2N/A }
2N/A
2N/A return (soft_rsa_crypt_init_common(session_p, pMechanism,
2N/A key_p, SOFT_DECRYPT_OP));
2N/A
2N/A default:
2N/A return (CKR_MECHANISM_INVALID);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * soft_decrypt_common()
2N/A *
2N/A * Arguments:
2N/A * session_p: pointer to soft_session_t struct
2N/A * pEncrypted: pointer to the encrypted data as input
2N/A * ulEncryptedLen: length of the input data
2N/A * pData: pointer to the output data contains plaintext
2N/A * pulDataLen: pointer to the length of the output data
2N/A * Update: boolean flag indicates caller is soft_decrypt
2N/A * or soft_decrypt_update
2N/A *
2N/A * Description:
2N/A * This function calls the corresponding decrypt routine based
2N/A * on the mechanism.
2N/A *
2N/A * Returns:
2N/A * see soft_decrypt_common().
2N/A */
2N/ACK_RV
2N/Asoft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
2N/A CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
2N/A CK_ULONG_PTR pulDataLen, boolean_t Update)
2N/A{
2N/A
2N/A CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
2N/A
2N/A switch (mechanism) {
2N/A
2N/A case CKM_DES_ECB:
2N/A case CKM_DES_CBC:
2N/A case CKM_DES3_ECB:
2N/A case CKM_DES3_CBC:
2N/A
2N/A if (ulEncryptedLen == 0) {
2N/A *pulDataLen = 0;
2N/A return (CKR_OK);
2N/A }
2N/A /* FALLTHROUGH */
2N/A
2N/A case CKM_DES_CBC_PAD:
2N/A case CKM_DES3_CBC_PAD:
2N/A
2N/A return (soft_des_decrypt_common(session_p, pEncrypted,
2N/A ulEncryptedLen, pData, pulDataLen, Update));
2N/A
2N/A case CKM_AES_ECB:
2N/A case CKM_AES_CBC:
2N/A case CKM_AES_CTR:
2N/A
2N/A if (ulEncryptedLen == 0) {
2N/A *pulDataLen = 0;
2N/A return (CKR_OK);
2N/A }
2N/A /* FALLTHROUGH */
2N/A
2N/A case CKM_AES_CBC_PAD:
2N/A
2N/A return (soft_aes_decrypt_common(session_p, pEncrypted,
2N/A ulEncryptedLen, pData, pulDataLen, Update));
2N/A
2N/A case CKM_BLOWFISH_CBC:
2N/A
2N/A if (ulEncryptedLen == 0) {
2N/A *pulDataLen = 0;
2N/A return (CKR_OK);
2N/A }
2N/A
2N/A return (soft_blowfish_decrypt_common(session_p, pEncrypted,
2N/A ulEncryptedLen, pData, pulDataLen, Update));
2N/A
2N/A case CKM_RC4:
2N/A
2N/A if (ulEncryptedLen == 0) {
2N/A *pulDataLen = 0;
2N/A return (CKR_OK);
2N/A }
2N/A
2N/A
2N/A return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
2N/A ulEncryptedLen, pData, pulDataLen));
2N/A
2N/A case CKM_RSA_X_509:
2N/A case CKM_RSA_PKCS:
2N/A
2N/A return (soft_rsa_decrypt_common(session_p, pEncrypted,
2N/A ulEncryptedLen, pData, pulDataLen, mechanism));
2N/A
2N/A default:
2N/A return (CKR_MECHANISM_INVALID);
2N/A
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * soft_decrypt()
2N/A *
2N/A * Arguments:
2N/A * session_p: pointer to soft_session_t struct
2N/A * pEncryptedData: pointer to the encrypted data as input
2N/A * ulEncryptedDataLen: length of the input data
2N/A * pData: pointer to the output data contains plaintext
2N/A * pulDataLen: pointer to the length of the output data
2N/A *
2N/A * Description:
2N/A * called by C_Decrypt(). This function calls the soft_decrypt_common
2N/A * routine.
2N/A *
2N/A * Returns:
2N/A * see soft_decrypt_common().
2N/A */
2N/ACK_RV
2N/Asoft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
2N/A CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
2N/A CK_ULONG_PTR pulDataLen)
2N/A{
2N/A
2N/A return (soft_decrypt_common(session_p, pEncryptedData,
2N/A ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
2N/A}
2N/A
2N/A
2N/A/*
2N/A * soft_decrypt_update()
2N/A *
2N/A * Arguments:
2N/A * session_p: pointer to soft_session_t struct
2N/A * pEncryptedPart: pointer to the encrypted data as input
2N/A * ulEncryptedPartLen: length of the input data
2N/A * pPart: pointer to the output data contains plaintext
2N/A * pulPartLen: pointer to the length of the output data
2N/A *
2N/A * Description:
2N/A * called by C_DecryptUpdate(). This function calls the
2N/A * soft_decrypt_common routine (with update flag on).
2N/A *
2N/A * Returns:
2N/A * see soft_decrypt_common().
2N/A */
2N/ACK_RV
2N/Asoft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
2N/A CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
2N/A CK_ULONG_PTR pulPartLen)
2N/A{
2N/A CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
2N/A
2N/A switch (mechanism) {
2N/A
2N/A case CKM_DES_ECB:
2N/A case CKM_DES_CBC:
2N/A case CKM_DES_CBC_PAD:
2N/A case CKM_DES3_ECB:
2N/A case CKM_DES3_CBC:
2N/A case CKM_DES3_CBC_PAD:
2N/A case CKM_AES_ECB:
2N/A case CKM_AES_CBC:
2N/A case CKM_AES_CBC_PAD:
2N/A case CKM_AES_CTR:
2N/A case CKM_BLOWFISH_CBC:
2N/A case CKM_RC4:
2N/A
2N/A return (soft_decrypt_common(session_p, pEncryptedPart,
2N/A ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
2N/A
2N/A default:
2N/A /* PKCS11: The mechanism only supports single-part operation. */
2N/A return (CKR_MECHANISM_INVALID);
2N/A }
2N/A
2N/A}
2N/A
2N/A
2N/A/*
2N/A * soft_decrypt_final()
2N/A *
2N/A * Arguments:
2N/A * session_p: pointer to soft_session_t struct
2N/A * pLastPart: pointer to the last recovered data part
2N/A * pulLastPartLen: pointer to the length of the last recovered data part
2N/A *
2N/A * Description:
2N/A * called by C_DecryptFinal().
2N/A *
2N/A * Returns:
2N/A * CKR_OK: success
2N/A * CKR_FUNCTION_FAILED: decrypt final function failed
2N/A * CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
2N/A */
2N/ACK_RV
2N/Asoft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
2N/A CK_ULONG_PTR pulLastPartLen)
2N/A{
2N/A
2N/A CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
2N/A CK_ULONG out_len;
2N/A CK_RV rv = CKR_OK;
2N/A int rc;
2N/A
2N/A (void) pthread_mutex_lock(&session_p->session_mutex);
2N/A
2N/A if (session_p->decrypt.context == NULL) {
2N/A rv = CKR_OPERATION_NOT_INITIALIZED;
2N/A *pulLastPartLen = 0;
2N/A goto clean2;
2N/A }
2N/A switch (mechanism) {
2N/A
2N/A case CKM_DES_CBC_PAD:
2N/A case CKM_DES3_CBC_PAD:
2N/A {
2N/A
2N/A soft_des_ctx_t *soft_des_ctx;
2N/A
2N/A soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
2N/A
2N/A /*
2N/A * We should have only one block of data left in the
2N/A * remaining buffer.
2N/A */
2N/A if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
2N/A *pulLastPartLen = 0;
2N/A rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
2N/A /* Cleanup memory space. */
2N/A free(soft_des_ctx->mode_ctx);
2N/A bzero(soft_des_ctx->key_sched,
2N/A soft_des_ctx->keysched_len);
2N/A free(soft_des_ctx->key_sched);
2N/A
2N/A goto clean1;
2N/A }
2N/A
2N/A out_len = DES_BLOCK_LEN;
2N/A
2N/A /*
2N/A * If application asks for the length of the output buffer
2N/A * to hold the plaintext?
2N/A */
2N/A if (pLastPart == NULL) {
2N/A *pulLastPartLen = out_len;
2N/A rv = CKR_OK;
2N/A goto clean2;
2N/A } else {
2N/A crypto_data_t out;
2N/A
2N/A /* Copy remaining data to the output buffer. */
2N/A (void) memcpy(pLastPart, soft_des_ctx->data,
2N/A DES_BLOCK_LEN);
2N/A
2N/A out.cd_format = CRYPTO_DATA_RAW;
2N/A out.cd_offset = 0;
2N/A out.cd_length = DES_BLOCK_LEN;
2N/A out.cd_raw.iov_base = (char *)pLastPart;
2N/A out.cd_raw.iov_len = DES_BLOCK_LEN;
2N/A
2N/A /* Decrypt final block of data. */
2N/A rc = des_decrypt_contiguous_blocks(
2N/A (des_ctx_t *)soft_des_ctx->mode_ctx,
2N/A (char *)pLastPart, DES_BLOCK_LEN, &out);
2N/A
2N/A if (rc == 0) {
2N/A /*
2N/A * Remove padding bytes after decryption of
2N/A * ciphertext block to produce the original
2N/A * plaintext.
2N/A */
2N/A rv = soft_remove_pkcs7_padding(pLastPart,
2N/A DES_BLOCK_LEN, &out_len);
2N/A if (rv != CKR_OK)
2N/A *pulLastPartLen = 0;
2N/A else
2N/A *pulLastPartLen = out_len;
2N/A } else {
2N/A *pulLastPartLen = 0;
2N/A rv = CKR_FUNCTION_FAILED;
2N/A }
2N/A
2N/A /* Cleanup memory space. */
2N/A free(soft_des_ctx->mode_ctx);
2N/A bzero(soft_des_ctx->key_sched,
2N/A soft_des_ctx->keysched_len);
2N/A free(soft_des_ctx->key_sched);
2N/A
2N/A }
2N/A
2N/A break;
2N/A }
2N/A
2N/A case CKM_DES_CBC:
2N/A case CKM_DES_ECB:
2N/A case CKM_DES3_CBC:
2N/A case CKM_DES3_ECB:
2N/A {
2N/A
2N/A soft_des_ctx_t *soft_des_ctx;
2N/A
2N/A soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
2N/A /*
2N/A * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
2N/A * so when the final is called, the remaining buffer
2N/A * should not contain any more data.
2N/A */
2N/A *pulLastPartLen = 0;
2N/A if (soft_des_ctx->remain_len != 0) {
2N/A rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
2N/A } else {
2N/A if (pLastPart == NULL)
2N/A goto clean2;
2N/A }
2N/A
2N/A /* Cleanup memory space. */
2N/A free(soft_des_ctx->mode_ctx);
2N/A bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
2N/A free(soft_des_ctx->key_sched);
2N/A
2N/A break;
2N/A }
2N/A
2N/A case CKM_AES_CBC_PAD:
2N/A {
2N/A
2N/A soft_aes_ctx_t *soft_aes_ctx;
2N/A
2N/A soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
2N/A
2N/A /*
2N/A * We should have only one block of data left in the
2N/A * remaining buffer.
2N/A */
2N/A if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
2N/A *pulLastPartLen = 0;
2N/A rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
2N/A /* Cleanup memory space. */
2N/A free(soft_aes_ctx->mode_ctx);
2N/A bzero(soft_aes_ctx->key_sched,
2N/A soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A
2N/A goto clean1;
2N/A }
2N/A
2N/A out_len = AES_BLOCK_LEN;
2N/A
2N/A /*
2N/A * If application asks for the length of the output buffer
2N/A * to hold the plaintext?
2N/A */
2N/A if (pLastPart == NULL) {
2N/A *pulLastPartLen = out_len;
2N/A rv = CKR_OK;
2N/A goto clean2;
2N/A } else {
2N/A crypto_data_t out;
2N/A
2N/A /* Copy remaining data to the output buffer. */
2N/A (void) memcpy(pLastPart, soft_aes_ctx->data,
2N/A AES_BLOCK_LEN);
2N/A
2N/A out.cd_format = CRYPTO_DATA_RAW;
2N/A out.cd_offset = 0;
2N/A out.cd_length = AES_BLOCK_LEN;
2N/A out.cd_raw.iov_base = (char *)pLastPart;
2N/A out.cd_raw.iov_len = AES_BLOCK_LEN;
2N/A
2N/A /* Decrypt final block of data. */
2N/A rc = aes_decrypt_contiguous_blocks(
2N/A (aes_ctx_t *)soft_aes_ctx->mode_ctx,
2N/A (char *)pLastPart, AES_BLOCK_LEN, &out);
2N/A
2N/A if (rc == 0) {
2N/A /*
2N/A * Remove padding bytes after decryption of
2N/A * ciphertext block to produce the original
2N/A * plaintext.
2N/A */
2N/A rv = soft_remove_pkcs7_padding(pLastPart,
2N/A AES_BLOCK_LEN, &out_len);
2N/A if (rv != CKR_OK)
2N/A *pulLastPartLen = 0;
2N/A else
2N/A *pulLastPartLen = out_len;
2N/A } else {
2N/A *pulLastPartLen = 0;
2N/A rv = CKR_FUNCTION_FAILED;
2N/A }
2N/A
2N/A /* Cleanup memory space. */
2N/A free(soft_aes_ctx->mode_ctx);
2N/A bzero(soft_aes_ctx->key_sched,
2N/A soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A
2N/A }
2N/A
2N/A break;
2N/A }
2N/A
2N/A case CKM_AES_CBC:
2N/A case CKM_AES_ECB:
2N/A {
2N/A soft_aes_ctx_t *soft_aes_ctx;
2N/A
2N/A soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
2N/A /*
2N/A * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
2N/A * so when the final is called, the remaining buffer
2N/A * should not contain any more data.
2N/A */
2N/A *pulLastPartLen = 0;
2N/A if (soft_aes_ctx->remain_len != 0) {
2N/A rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
2N/A } else {
2N/A if (pLastPart == NULL)
2N/A goto clean2;
2N/A }
2N/A
2N/A /* Cleanup memory space. */
2N/A free(soft_aes_ctx->mode_ctx);
2N/A bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A
2N/A break;
2N/A }
2N/A case CKM_AES_CTR:
2N/A {
2N/A soft_aes_ctx_t *soft_aes_ctx;
2N/A ctr_ctx_t *ctr_ctx;
2N/A
2N/A /* CTR is a stream cipher, ...Final() just cleans up */
2N/A soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
2N/A ctr_ctx = soft_aes_ctx->mode_ctx;
2N/A *pulLastPartLen = 0;
2N/A if (pLastPart == NULL) {
2N/A goto clean1;
2N/A }
2N/A
2N/A /* Cleanup memory space. */
2N/A free(ctr_ctx);
2N/A bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
2N/A free(soft_aes_ctx->key_sched);
2N/A
2N/A break;
2N/A }
2N/A case CKM_BLOWFISH_CBC:
2N/A {
2N/A soft_blowfish_ctx_t *soft_blowfish_ctx;
2N/A
2N/A soft_blowfish_ctx =
2N/A (soft_blowfish_ctx_t *)session_p->decrypt.context;
2N/A
2N/A *pulLastPartLen = 0;
2N/A if (soft_blowfish_ctx->remain_len != 0)
2N/A rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
2N/A else {
2N/A if (pLastPart == NULL)
2N/A goto clean2;
2N/A }
2N/A
2N/A free(soft_blowfish_ctx->mode_ctx);
2N/A bzero(soft_blowfish_ctx->key_sched,
2N/A soft_blowfish_ctx->keysched_len);
2N/A free(soft_blowfish_ctx->key_sched);
2N/A
2N/A break;
2N/A }
2N/A
2N/A case CKM_RC4:
2N/A {
2N/A ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
2N/A bzero(key, sizeof (*key));
2N/A *pulLastPartLen = 0;
2N/A break;
2N/A }
2N/A
2N/A default:
2N/A /* PKCS11: The mechanism only supports single-part operation. */
2N/A rv = CKR_MECHANISM_INVALID;
2N/A break;
2N/A }
2N/A
2N/Aclean1:
2N/A free(session_p->decrypt.context);
2N/A session_p->decrypt.context = NULL;
2N/A
2N/Aclean2:
2N/A (void) pthread_mutex_unlock(&session_p->session_mutex);
2N/A
2N/A return (rv);
2N/A
2N/A}