/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <security/cryptoki.h>
#include "softSession.h"
#include "softObject.h"
#include "softOps.h"
#include "softCrypt.h"
#include "softRSA.h"
/*
* Remove padding bytes.
*/
{
#ifdef __sparcv9
#else /* !__sparcv9 */
#endif /* __sparcv9 */
return (rv);
*pulDataLen = padded_len;
return (CKR_OK);
}
/*
* soft_decrypt_init()
*
* Arguments:
* session_p: pointer to soft_session_t struct
* pMechanism: pointer to CK_MECHANISM struct provided by application
* key_p: pointer to key soft_object_t struct
*
* Description:
* called by C_DecryptInit(). This function calls the corresponding
* decrypt init routine based on the mechanism.
*
* Returns:
* CKR_OK: success
* CKR_HOST_MEMORY: ran out of system memory
* CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
* CKR_MECHANISM_INVALID: invalid mechanism type
* CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
* with the specified mechanism
*/
{
switch (pMechanism->mechanism) {
case CKM_DES_ECB:
return (CKR_KEY_TYPE_INCONSISTENT);
}
goto ecb_common;
case CKM_DES3_ECB:
{
return (CKR_KEY_TYPE_INCONSISTENT);
}
return (rv);
}
/* Allocate a context */
}
} else {
}
B_FALSE /* decrypt */);
return (rv);
}
case CKM_DES_CBC:
case CKM_DES_CBC_PAD:
return (CKR_KEY_TYPE_INCONSISTENT);
}
goto cbc_common;
case CKM_DES3_CBC:
case CKM_DES3_CBC_PAD:
{
return (CKR_KEY_TYPE_INCONSISTENT);
}
return (CKR_MECHANISM_PARAM_INVALID);
}
return (rv);
/* Save Initialization Vector (IV) in the context. */
/* Allocate a context for DES cipher-block chaining. */
return (CKR_HOST_MEMORY);
}
B_FALSE /* decrypt */);
B_FALSE /* decrypt */);
}
return (rv);
}
case CKM_AES_ECB:
return (CKR_KEY_TYPE_INCONSISTENT);
}
return (rv);
#ifdef __amd64
if (soft_intel_aes_instructions_present()) {
#else
/* LINTED E_CONSTANT_CONDITION */
if (1) {
#endif /* __amd64 */
/*
* Allocate a context for AES Electronic Code Book.
* This is done to use combined
* block-level AES decrypt functions are
* called directly.
*/
(void) pthread_mutex_unlock(
return (CKR_HOST_MEMORY);
}
B_FALSE /* decrypt */);
}
return (rv);
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
{
return (CKR_KEY_TYPE_INCONSISTENT);
}
return (CKR_MECHANISM_PARAM_INVALID);
}
return (rv);
/* Save Initialization Vector (IV) in the context. */
/* Allocate a context for AES cipher-block chaining. */
soft_aes_ctx->ivec);
return (CKR_HOST_MEMORY);
}
B_FALSE /* decrypt */);
}
return (rv);
}
case CKM_AES_CTR:
{
return (CKR_KEY_TYPE_INCONSISTENT);
}
return (CKR_MECHANISM_PARAM_INVALID);
}
return (rv);
}
B_FALSE /* decrypt */);
return (rv);
}
case CKM_BLOWFISH_CBC:
{
return (CKR_KEY_TYPE_INCONSISTENT);
return (CKR_MECHANISM_PARAM_INVALID);
return (rv);
/* Save Initialization Vector in the context. */
/* Allocate a context for CBC */
return (CKR_HOST_MEMORY);
}
return (rv);
}
case CKM_RC4:
return (CKR_KEY_TYPE_INCONSISTENT);
}
case CKM_RSA_X_509:
case CKM_RSA_PKCS:
return (CKR_KEY_TYPE_INCONSISTENT);
}
key_p, SOFT_DECRYPT_OP));
default:
return (CKR_MECHANISM_INVALID);
}
}
/*
* soft_decrypt_common()
*
* Arguments:
* session_p: pointer to soft_session_t struct
* pEncrypted: pointer to the encrypted data as input
* ulEncryptedLen: length of the input data
* pData: pointer to the output data contains plaintext
* pulDataLen: pointer to the length of the output data
* Update: boolean flag indicates caller is soft_decrypt
* or soft_decrypt_update
*
* Description:
* This function calls the corresponding decrypt routine based
* on the mechanism.
*
* Returns:
* see soft_decrypt_common().
*/
{
switch (mechanism) {
case CKM_DES_ECB:
case CKM_DES_CBC:
case CKM_DES3_ECB:
case CKM_DES3_CBC:
if (ulEncryptedLen == 0) {
*pulDataLen = 0;
return (CKR_OK);
}
/* FALLTHROUGH */
case CKM_DES_CBC_PAD:
case CKM_DES3_CBC_PAD:
case CKM_AES_ECB:
case CKM_AES_CBC:
case CKM_AES_CTR:
if (ulEncryptedLen == 0) {
*pulDataLen = 0;
return (CKR_OK);
}
/* FALLTHROUGH */
case CKM_AES_CBC_PAD:
case CKM_BLOWFISH_CBC:
if (ulEncryptedLen == 0) {
*pulDataLen = 0;
return (CKR_OK);
}
case CKM_RC4:
if (ulEncryptedLen == 0) {
*pulDataLen = 0;
return (CKR_OK);
}
case CKM_RSA_X_509:
case CKM_RSA_PKCS:
default:
return (CKR_MECHANISM_INVALID);
}
}
/*
* soft_decrypt()
*
* Arguments:
* session_p: pointer to soft_session_t struct
* pEncryptedData: pointer to the encrypted data as input
* ulEncryptedDataLen: length of the input data
* pData: pointer to the output data contains plaintext
* pulDataLen: pointer to the length of the output data
*
* Description:
* called by C_Decrypt(). This function calls the soft_decrypt_common
* routine.
*
* Returns:
* see soft_decrypt_common().
*/
{
}
/*
* soft_decrypt_update()
*
* Arguments:
* session_p: pointer to soft_session_t struct
* pEncryptedPart: pointer to the encrypted data as input
* ulEncryptedPartLen: length of the input data
* pPart: pointer to the output data contains plaintext
* pulPartLen: pointer to the length of the output data
*
* Description:
* called by C_DecryptUpdate(). This function calls the
* soft_decrypt_common routine (with update flag on).
*
* Returns:
* see soft_decrypt_common().
*/
{
switch (mechanism) {
case CKM_DES_ECB:
case CKM_DES_CBC:
case CKM_DES_CBC_PAD:
case CKM_DES3_ECB:
case CKM_DES3_CBC:
case CKM_DES3_CBC_PAD:
case CKM_AES_ECB:
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
case CKM_AES_CTR:
case CKM_BLOWFISH_CBC:
case CKM_RC4:
default:
/* PKCS11: The mechanism only supports single-part operation. */
return (CKR_MECHANISM_INVALID);
}
}
/*
* soft_decrypt_final()
*
* Arguments:
* session_p: pointer to soft_session_t struct
* pLastPart: pointer to the last recovered data part
* pulLastPartLen: pointer to the length of the last recovered data part
*
* Description:
* called by C_DecryptFinal().
*
* Returns:
* CKR_OK: success
* CKR_FUNCTION_FAILED: decrypt final function failed
* CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
*/
{
int rc;
*pulLastPartLen = 0;
goto clean2;
}
switch (mechanism) {
case CKM_DES_CBC_PAD:
case CKM_DES3_CBC_PAD:
{
/*
* We should have only one block of data left in the
* remaining buffer.
*/
*pulLastPartLen = 0;
/* Cleanup memory space. */
goto clean1;
}
/*
* If application asks for the length of the output buffer
* to hold the plaintext?
*/
goto clean2;
} else {
/* Copy remaining data to the output buffer. */
/* Decrypt final block of data. */
if (rc == 0) {
/*
* Remove padding bytes after decryption of
* ciphertext block to produce the original
* plaintext.
*/
DES_BLOCK_LEN, &out_len);
*pulLastPartLen = 0;
else
} else {
*pulLastPartLen = 0;
}
/* Cleanup memory space. */
}
break;
}
case CKM_DES_CBC:
case CKM_DES_ECB:
case CKM_DES3_CBC:
case CKM_DES3_ECB:
{
/*
* CKM_DES_CBC and CKM_DES_ECB does not do any padding,
* so when the final is called, the remaining buffer
* should not contain any more data.
*/
*pulLastPartLen = 0;
if (soft_des_ctx->remain_len != 0) {
} else {
goto clean2;
}
/* Cleanup memory space. */
break;
}
case CKM_AES_CBC_PAD:
{
/*
* We should have only one block of data left in the
* remaining buffer.
*/
*pulLastPartLen = 0;
/* Cleanup memory space. */
goto clean1;
}
/*
* If application asks for the length of the output buffer
* to hold the plaintext?
*/
goto clean2;
} else {
/* Copy remaining data to the output buffer. */
/* Decrypt final block of data. */
if (rc == 0) {
/*
* Remove padding bytes after decryption of
* ciphertext block to produce the original
* plaintext.
*/
AES_BLOCK_LEN, &out_len);
*pulLastPartLen = 0;
else
} else {
*pulLastPartLen = 0;
}
/* Cleanup memory space. */
}
break;
}
case CKM_AES_CBC:
case CKM_AES_ECB:
{
/*
* CKM_AES_CBC and CKM_AES_ECB does not do any padding,
* so when the final is called, the remaining buffer
* should not contain any more data.
*/
*pulLastPartLen = 0;
if (soft_aes_ctx->remain_len != 0) {
} else {
goto clean2;
}
/* Cleanup memory space. */
break;
}
case CKM_AES_CTR:
{
/* CTR is a stream cipher, ...Final() just cleans up */
*pulLastPartLen = 0;
goto clean1;
}
/* Cleanup memory space. */
break;
}
case CKM_BLOWFISH_CBC:
{
*pulLastPartLen = 0;
if (soft_blowfish_ctx->remain_len != 0)
else {
goto clean2;
}
break;
}
case CKM_RC4:
{
*pulLastPartLen = 0;
break;
}
default:
/* PKCS11: The mechanism only supports single-part operation. */
break;
}
return (rv);
}