f66d273d14eede3a1bb803a39414588d8f143a98izick/*
4c21f043137d037cfab505df3956f56ba521b170izick * CDDL HEADER START
4c21f043137d037cfab505df3956f56ba521b170izick *
4c21f043137d037cfab505df3956f56ba521b170izick * The contents of this file are subject to the terms of the
4c21f043137d037cfab505df3956f56ba521b170izick * Common Development and Distribution License (the "License").
4c21f043137d037cfab505df3956f56ba521b170izick * You may not use this file except in compliance with the License.
4c21f043137d037cfab505df3956f56ba521b170izick *
4c21f043137d037cfab505df3956f56ba521b170izick * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4c21f043137d037cfab505df3956f56ba521b170izick * or http://www.opensolaris.org/os/licensing.
4c21f043137d037cfab505df3956f56ba521b170izick * See the License for the specific language governing permissions
4c21f043137d037cfab505df3956f56ba521b170izick * and limitations under the License.
4c21f043137d037cfab505df3956f56ba521b170izick *
4c21f043137d037cfab505df3956f56ba521b170izick * When distributing Covered Code, include this CDDL HEADER in each
4c21f043137d037cfab505df3956f56ba521b170izick * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4c21f043137d037cfab505df3956f56ba521b170izick * If applicable, add the following below this CDDL HEADER, with the
4c21f043137d037cfab505df3956f56ba521b170izick * fields enclosed by brackets "[]" replaced with your own identifying
4c21f043137d037cfab505df3956f56ba521b170izick * information: Portions Copyright [yyyy] [name of copyright owner]
4c21f043137d037cfab505df3956f56ba521b170izick *
4c21f043137d037cfab505df3956f56ba521b170izick * CDDL HEADER END
4c21f043137d037cfab505df3956f56ba521b170izick */
4c21f043137d037cfab505df3956f56ba521b170izick/*
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
f66d273d14eede3a1bb803a39414588d8f143a98izick * Use is subject to license terms.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick#include <pthread.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick#include <stdlib.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick#include <string.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick#include <strings.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick#include <sys/types.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick#include <security/cryptoki.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick#include "softSession.h"
f66d273d14eede3a1bb803a39414588d8f143a98izick#include "softObject.h"
f66d273d14eede3a1bb803a39414588d8f143a98izick#include "softCrypt.h"
23c57df72989c916b3e98084eb88d48777999691mcpowers#include <blowfish_impl.h>
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izickCK_RV
f66d273d14eede3a1bb803a39414588d8f143a98izicksoft_blowfish_crypt_init_common(soft_session_t *session_p,
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t encrypt) {
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick size_t size;
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx_t *soft_blowfish_ctx;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx = calloc(1, sizeof (soft_blowfish_ctx_t));
f66d273d14eede3a1bb803a39414588d8f143a98izick if (soft_blowfish_ctx == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_HOST_MEMORY);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->key_sched = blowfish_alloc_keysched(&size, 0);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (soft_blowfish_ctx->key_sched == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick free(soft_blowfish_ctx);
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_HOST_MEMORY);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->keysched_len = size;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) pthread_mutex_lock(&session_p->session_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick if (encrypt) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Called by C_EncryptInit */
f66d273d14eede3a1bb803a39414588d8f143a98izick session_p->encrypt.context = soft_blowfish_ctx;
f66d273d14eede3a1bb803a39414588d8f143a98izick session_p->encrypt.mech.mechanism = pMechanism->mechanism;
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Called by C_DecryptInit */
f66d273d14eede3a1bb803a39414588d8f143a98izick session_p->decrypt.context = soft_blowfish_ctx;
f66d273d14eede3a1bb803a39414588d8f143a98izick session_p->decrypt.mech.mechanism = pMechanism->mechanism;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) pthread_mutex_unlock(&session_p->session_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * If this is a non-sensitive key and it does NOT have
f66d273d14eede3a1bb803a39414588d8f143a98izick * a key schedule yet, then allocate one and expand it.
f66d273d14eede3a1bb803a39414588d8f143a98izick * Otherwise, if it's a non-sensitive key, and it DOES have
f66d273d14eede3a1bb803a39414588d8f143a98izick * a key schedule already attached to it, just copy the
f66d273d14eede3a1bb803a39414588d8f143a98izick * pre-expanded schedule to the context and avoid the
f66d273d14eede3a1bb803a39414588d8f143a98izick * extra key schedule expansion operation.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers if (OBJ_KEY_SCHED(key_p) == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick void *ks;
f66d273d14eede3a1bb803a39414588d8f143a98izick
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers (void) pthread_mutex_lock(&key_p->object_mutex);
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers if (OBJ_KEY_SCHED(key_p) == NULL) {
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers ks = blowfish_alloc_keysched(&size, 0);
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers if (ks == NULL) {
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers (void) pthread_mutex_unlock(
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers &key_p->object_mutex);
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers free(soft_blowfish_ctx);
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers return (CKR_HOST_MEMORY);
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers }
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers OBJ_KEY_SCHED_LEN(key_p) = size;
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers OBJ_KEY_SCHED(key_p) = ks;
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers }
9627968bca31e10e2055342c2f1ccf7b2a165c71mcpowers (void) pthread_mutex_unlock(&key_p->object_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(soft_blowfish_ctx->key_sched,
f66d273d14eede3a1bb803a39414588d8f143a98izick OBJ_KEY_SCHED(key_p), OBJ_KEY_SCHED_LEN(key_p));
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Initialize key schedule for Blowfish.
f66d273d14eede3a1bb803a39414588d8f143a98izick * blowfish_init_keysched() requires key length in bits.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
f66d273d14eede3a1bb803a39414588d8f143a98izick (OBJ_SEC_VALUE_LEN(key_p) * 8),
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->key_sched);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick}
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick/*
f66d273d14eede3a1bb803a39414588d8f143a98izick * soft_blowfish_encrypt_common()
f66d273d14eede3a1bb803a39414588d8f143a98izick *
f66d273d14eede3a1bb803a39414588d8f143a98izick * Arguments:
f66d273d14eede3a1bb803a39414588d8f143a98izick * session_p: pointer to soft_session_t struct
f66d273d14eede3a1bb803a39414588d8f143a98izick * pData: pointer to the input data to be encrypted
f66d273d14eede3a1bb803a39414588d8f143a98izick * ulDataLen: length of the input data
f66d273d14eede3a1bb803a39414588d8f143a98izick * pEncrypted: pointer to the output data after encryption
f66d273d14eede3a1bb803a39414588d8f143a98izick * pulEncryptedLen: pointer to the length of the output data
f66d273d14eede3a1bb803a39414588d8f143a98izick * update: boolean flag indicates caller is soft_encrypt
f66d273d14eede3a1bb803a39414588d8f143a98izick * or soft_encrypt_update
f66d273d14eede3a1bb803a39414588d8f143a98izick *
f66d273d14eede3a1bb803a39414588d8f143a98izick * Description:
f66d273d14eede3a1bb803a39414588d8f143a98izick * This function calls the corresponding encrypt routine based
f66d273d14eede3a1bb803a39414588d8f143a98izick * on the mechanism.
f66d273d14eede3a1bb803a39414588d8f143a98izick *
f66d273d14eede3a1bb803a39414588d8f143a98izick * Returns:
f66d273d14eede3a1bb803a39414588d8f143a98izick * CKR_OK: success
f66d273d14eede3a1bb803a39414588d8f143a98izick * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
f66d273d14eede3a1bb803a39414588d8f143a98izick * is too small
f66d273d14eede3a1bb803a39414588d8f143a98izick * CKR_FUNCTION_FAILED: encrypt function failed
f66d273d14eede3a1bb803a39414588d8f143a98izick * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izickCK_RV
f66d273d14eede3a1bb803a39414588d8f143a98izicksoft_blowfish_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, CK_ULONG_PTR pulEncryptedLen,
f66d273d14eede3a1bb803a39414588d8f143a98izick boolean_t update) {
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick int rc = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_RV rv = CKR_OK;
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx_t *soft_blowfish_ctx =
f66d273d14eede3a1bb803a39414588d8f143a98izick (soft_blowfish_ctx_t *)session_p->encrypt.context;
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_ctx_t *blowfish_ctx;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_BYTE *in_buf = NULL;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_BYTE *out_buf = NULL;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG total_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG remain;
f66d273d14eede3a1bb803a39414588d8f143a98izick crypto_data_t out;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Blowfish only takes input length that is a multiple of blocksize
f66d273d14eede3a1bb803a39414588d8f143a98izick * for C_Encrypt function with the mechanism CKM_BLOWFISH_CBC.
f66d273d14eede3a1bb803a39414588d8f143a98izick *
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (!update) {
f66d273d14eede3a1bb803a39414588d8f143a98izick if ((ulDataLen % BLOWFISH_BLOCK_LEN) != 0) {
f66d273d14eede3a1bb803a39414588d8f143a98izick rv = CKR_DATA_LEN_RANGE;
f66d273d14eede3a1bb803a39414588d8f143a98izick goto cleanup;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick out_len = ulDataLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * If application asks for the length of the output buffer
f66d273d14eede3a1bb803a39414588d8f143a98izick * to hold the ciphertext?
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (pEncrypted == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulEncryptedLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Is the application-supplied buffer large enough? */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (*pulEncryptedLen < out_len) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulEncryptedLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_BUFFER_TOO_SMALL);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick in_buf = pData;
f66d273d14eede3a1bb803a39414588d8f143a98izick out_buf = pEncrypted;
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Called by C_EncryptUpdate
f66d273d14eede3a1bb803a39414588d8f143a98izick *
f66d273d14eede3a1bb803a39414588d8f143a98izick * Add the lengths of last remaining data and current
f66d273d14eede3a1bb803a39414588d8f143a98izick * plaintext together to get the total input length.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick total_len = soft_blowfish_ctx->remain_len + ulDataLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * If the total input length is less than one blocksize,
f66d273d14eede3a1bb803a39414588d8f143a98izick * we will need to delay encryption until when more data
f66d273d14eede3a1bb803a39414588d8f143a98izick * comes in next C_EncryptUpdate or when C_EncryptFinal
f66d273d14eede3a1bb803a39414588d8f143a98izick * is called.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (total_len < BLOWFISH_BLOCK_LEN) {
f66d273d14eede3a1bb803a39414588d8f143a98izick if (pEncrypted != NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Save input data and its length in
f66d273d14eede3a1bb803a39414588d8f143a98izick * the remaining buffer of BLOWFISH context.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(soft_blowfish_ctx->data +
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len, pData,
f66d273d14eede3a1bb803a39414588d8f143a98izick ulDataLen);
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len += ulDataLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Set encrypted data length to 0. */
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulEncryptedLen = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Compute the length of remaing data. */
f66d273d14eede3a1bb803a39414588d8f143a98izick remain = total_len % BLOWFISH_BLOCK_LEN;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Make sure that the output length is a multiple of
f66d273d14eede3a1bb803a39414588d8f143a98izick * blocksize.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick out_len = total_len - remain;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * If application asks for the length of the output buffer
f66d273d14eede3a1bb803a39414588d8f143a98izick * to hold the ciphertext?
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (pEncrypted == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulEncryptedLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Is the application-supplied buffer large enough? */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (*pulEncryptedLen < out_len) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulEncryptedLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_BUFFER_TOO_SMALL);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (soft_blowfish_ctx->remain_len != 0) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Copy last remaining data and current input data
f66d273d14eede3a1bb803a39414588d8f143a98izick * to the output buffer.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memmove(pEncrypted +
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len,
f66d273d14eede3a1bb803a39414588d8f143a98izick pData, out_len - soft_blowfish_ctx->remain_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(pEncrypted, soft_blowfish_ctx->data,
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick bzero(soft_blowfish_ctx->data,
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick in_buf = pEncrypted;
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick in_buf = pData;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick out_buf = pEncrypted;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Begin Encryption now.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_format = CRYPTO_DATA_RAW;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_offset = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_length = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_raw.iov_base = (char *)out_buf;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_raw.iov_len = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Encrypt multiple blocks of data. */
f66d273d14eede3a1bb803a39414588d8f143a98izick rc = blowfish_encrypt_contiguous_blocks(
f66d273d14eede3a1bb803a39414588d8f143a98izick (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
f66d273d14eede3a1bb803a39414588d8f143a98izick (char *)in_buf, out_len, &out);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (rc == 0) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulEncryptedLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick if (update) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * For encrypt update, if there is remaining data,
f66d273d14eede3a1bb803a39414588d8f143a98izick * save it and it's length in the context.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (remain != 0)
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(soft_blowfish_ctx->data, pData +
f66d273d14eede3a1bb803a39414588d8f143a98izick (ulDataLen - remain), remain);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len = remain;
4c21f043137d037cfab505df3956f56ba521b170izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
4c21f043137d037cfab505df3956f56ba521b170izick } else {
4c21f043137d037cfab505df3956f56ba521b170izick *pulEncryptedLen = 0;
4c21f043137d037cfab505df3956f56ba521b170izick rv = CKR_FUNCTION_FAILED;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izickcleanup:
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) pthread_mutex_lock(&session_p->session_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
f66d273d14eede3a1bb803a39414588d8f143a98izick if (blowfish_ctx != NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick bzero(blowfish_ctx->bc_keysched,
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_ctx->bc_keysched_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick free(soft_blowfish_ctx->blowfish_cbc);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick free(soft_blowfish_ctx->key_sched);
f66d273d14eede3a1bb803a39414588d8f143a98izick free(session_p->encrypt.context);
f66d273d14eede3a1bb803a39414588d8f143a98izick session_p->encrypt.context = NULL;
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) pthread_mutex_unlock(&session_p->session_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick return (rv);
f66d273d14eede3a1bb803a39414588d8f143a98izick}
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izickCK_RV
f66d273d14eede3a1bb803a39414588d8f143a98izicksoft_blowfish_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen,
f66d273d14eede3a1bb803a39414588d8f143a98izick boolean_t update) {
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick int rc = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_RV rv = CKR_OK;
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx_t *soft_blowfish_ctx =
f66d273d14eede3a1bb803a39414588d8f143a98izick (soft_blowfish_ctx_t *)session_p->decrypt.context;
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_ctx_t *blowfish_ctx;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_BYTE *in_buf = NULL;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_BYTE *out_buf = NULL;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG total_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick CK_ULONG remain;
f66d273d14eede3a1bb803a39414588d8f143a98izick crypto_data_t out;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Blowfish only takes input length that is a multiple of 16 bytes
f66d273d14eede3a1bb803a39414588d8f143a98izick * for C_Decrypt function using CKM_BLOWFISH_CBC.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (!update) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Called by C_Decrypt */
f66d273d14eede3a1bb803a39414588d8f143a98izick if ((ulEncryptedLen % BLOWFISH_BLOCK_LEN) != 0) {
f66d273d14eede3a1bb803a39414588d8f143a98izick rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
f66d273d14eede3a1bb803a39414588d8f143a98izick goto cleanup;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
4c21f043137d037cfab505df3956f56ba521b170izick * If application asks for the length of the output buffer
f66d273d14eede3a1bb803a39414588d8f143a98izick * to hold the plaintext?
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (pData == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = ulEncryptedLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Is the application-supplied buffer large enough? */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (*pulDataLen < ulEncryptedLen) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = ulEncryptedLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_BUFFER_TOO_SMALL);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick out_len = ulEncryptedLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick in_buf = pEncrypted;
f66d273d14eede3a1bb803a39414588d8f143a98izick out_buf = pData;
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Called by C_DecryptUpdate
f66d273d14eede3a1bb803a39414588d8f143a98izick *
f66d273d14eede3a1bb803a39414588d8f143a98izick * Add the lengths of last remaining data and current
f66d273d14eede3a1bb803a39414588d8f143a98izick * input data together to get the total input length.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick total_len = soft_blowfish_ctx->remain_len + ulEncryptedLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (total_len < BLOWFISH_BLOCK_LEN) {
f66d273d14eede3a1bb803a39414588d8f143a98izick if (pData != NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(soft_blowfish_ctx->data +
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len,
f66d273d14eede3a1bb803a39414588d8f143a98izick pEncrypted, ulEncryptedLen);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len += ulEncryptedLen;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Set output data length to 0. */
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Compute the length of remaining data. */
f66d273d14eede3a1bb803a39414588d8f143a98izick remain = total_len % BLOWFISH_BLOCK_LEN;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Make sure that the output length is a multiple of
f66d273d14eede3a1bb803a39414588d8f143a98izick * blocksize.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick out_len = total_len - remain;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * if application asks for the length of the output buffer
f66d273d14eede3a1bb803a39414588d8f143a98izick * to hold the plaintext?
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (pData == NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Is the application-supplied buffer large enough?
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (*pulDataLen < out_len) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_BUFFER_TOO_SMALL);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (soft_blowfish_ctx->remain_len != 0) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Copy last remaining data and current input data
f66d273d14eede3a1bb803a39414588d8f143a98izick * to the output buffer.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memmove(pData + soft_blowfish_ctx->remain_len,
f66d273d14eede3a1bb803a39414588d8f143a98izick pEncrypted,
f66d273d14eede3a1bb803a39414588d8f143a98izick out_len - soft_blowfish_ctx->remain_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(pData, soft_blowfish_ctx->data,
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick bzero(soft_blowfish_ctx->data,
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick in_buf = pData;
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick in_buf = pEncrypted;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick out_buf = pData;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_format = CRYPTO_DATA_RAW;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_offset = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_length = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_raw.iov_base = (char *)out_buf;
f66d273d14eede3a1bb803a39414588d8f143a98izick out.cd_raw.iov_len = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick /* Decrypt multiple blocks of data. */
f66d273d14eede3a1bb803a39414588d8f143a98izick rc = blowfish_decrypt_contiguous_blocks(
f66d273d14eede3a1bb803a39414588d8f143a98izick (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
f66d273d14eede3a1bb803a39414588d8f143a98izick (char *)in_buf, out_len, &out);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick if (rc == 0) {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = out_len;
f66d273d14eede3a1bb803a39414588d8f143a98izick if (update) {
f66d273d14eede3a1bb803a39414588d8f143a98izick /*
f66d273d14eede3a1bb803a39414588d8f143a98izick * For decrypt update, if there is remaining data,
f66d273d14eede3a1bb803a39414588d8f143a98izick * save it and its length in the context.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick if (remain != 0)
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) memcpy(soft_blowfish_ctx->data,
f66d273d14eede3a1bb803a39414588d8f143a98izick pEncrypted + (ulEncryptedLen - remain),
f66d273d14eede3a1bb803a39414588d8f143a98izick remain);
f66d273d14eede3a1bb803a39414588d8f143a98izick soft_blowfish_ctx->remain_len = remain;
f66d273d14eede3a1bb803a39414588d8f143a98izick return (CKR_OK);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick } else {
f66d273d14eede3a1bb803a39414588d8f143a98izick *pulDataLen = 0;
f66d273d14eede3a1bb803a39414588d8f143a98izick rv = CKR_FUNCTION_FAILED;
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izickcleanup:
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) pthread_mutex_lock(&session_p->session_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
f66d273d14eede3a1bb803a39414588d8f143a98izick if (blowfish_ctx != NULL) {
f66d273d14eede3a1bb803a39414588d8f143a98izick bzero(blowfish_ctx->bc_keysched,
f66d273d14eede3a1bb803a39414588d8f143a98izick blowfish_ctx->bc_keysched_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick free(soft_blowfish_ctx->blowfish_cbc);
f66d273d14eede3a1bb803a39414588d8f143a98izick }
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
f66d273d14eede3a1bb803a39414588d8f143a98izick free(soft_blowfish_ctx->key_sched);
f66d273d14eede3a1bb803a39414588d8f143a98izick free(session_p->decrypt.context);
f66d273d14eede3a1bb803a39414588d8f143a98izick session_p->decrypt.context = NULL;
f66d273d14eede3a1bb803a39414588d8f143a98izick (void) pthread_mutex_unlock(&session_p->session_mutex);
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick return (rv);
f66d273d14eede3a1bb803a39414588d8f143a98izick}
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izick/*
f66d273d14eede3a1bb803a39414588d8f143a98izick * Allocate and initialize a context for BLOWFISH CBC mode of operation.
f66d273d14eede3a1bb803a39414588d8f143a98izick */
f66d273d14eede3a1bb803a39414588d8f143a98izick
f66d273d14eede3a1bb803a39414588d8f143a98izickvoid *
f66d273d14eede3a1bb803a39414588d8f143a98izickblowfish_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
f66d273d14eede3a1bb803a39414588d8f143a98izick{
f66d273d14eede3a1bb803a39414588d8f143a98izick
23c57df72989c916b3e98084eb88d48777999691mcpowers cbc_ctx_t *cbc_ctx;
f66d273d14eede3a1bb803a39414588d8f143a98izick
23c57df72989c916b3e98084eb88d48777999691mcpowers if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
f66d273d14eede3a1bb803a39414588d8f143a98izick return (NULL);
f66d273d14eede3a1bb803a39414588d8f143a98izick
16239bc82c111618343e0a5b1a70e0fc702d00e0Mark Powers cbc_ctx->cbc_keysched = key_sched;
f66d273d14eede3a1bb803a39414588d8f143a98izick
16239bc82c111618343e0a5b1a70e0fc702d00e0Mark Powers (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, BLOWFISH_BLOCK_LEN);
f66d273d14eede3a1bb803a39414588d8f143a98izick
16239bc82c111618343e0a5b1a70e0fc702d00e0Mark Powers cbc_ctx->cbc_lastp = (uint8_t *)&(cbc_ctx->cbc_iv);
16239bc82c111618343e0a5b1a70e0fc702d00e0Mark Powers cbc_ctx->cbc_keysched_len = size;
16239bc82c111618343e0a5b1a70e0fc702d00e0Mark Powers cbc_ctx->cbc_flags |= CBC_MODE;
f66d273d14eede3a1bb803a39414588d8f143a98izick
23c57df72989c916b3e98084eb88d48777999691mcpowers return (cbc_ctx);
f66d273d14eede3a1bb803a39414588d8f143a98izick}