1f66d273dSizick /*
24c21f043Sizick * CDDL HEADER START
34c21f043Sizick *
44c21f043Sizick * The contents of this file are subject to the terms of the
54c21f043Sizick * Common Development and Distribution License (the "License").
64c21f043Sizick * You may not use this file except in compliance with the License.
74c21f043Sizick *
84c21f043Sizick * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94c21f043Sizick * or http://www.opensolaris.org/os/licensing.
104c21f043Sizick * See the License for the specific language governing permissions
114c21f043Sizick * and limitations under the License.
124c21f043Sizick *
134c21f043Sizick * When distributing Covered Code, include this CDDL HEADER in each
144c21f043Sizick * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154c21f043Sizick * If applicable, add the following below this CDDL HEADER, with the
164c21f043Sizick * fields enclosed by brackets "[]" replaced with your own identifying
174c21f043Sizick * information: Portions Copyright [yyyy] [name of copyright owner]
184c21f043Sizick *
194c21f043Sizick * CDDL HEADER END
204c21f043Sizick */
214c21f043Sizick /*
229627968bSmcpowers * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23f66d273dSizick * Use is subject to license terms.
24f66d273dSizick */
25f66d273dSizick
26f66d273dSizick #include <pthread.h>
27f66d273dSizick #include <stdlib.h>
28f66d273dSizick #include <string.h>
29f66d273dSizick #include <strings.h>
30f66d273dSizick #include <sys/types.h>
31f66d273dSizick #include <security/cryptoki.h>
32f66d273dSizick #include "softSession.h"
33f66d273dSizick #include "softObject.h"
34f66d273dSizick #include "softCrypt.h"
3523c57df7Smcpowers #include <blowfish_impl.h>
36f66d273dSizick
37f66d273dSizick CK_RV
soft_blowfish_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)38f66d273dSizick soft_blowfish_crypt_init_common(soft_session_t *session_p,
39f66d273dSizick CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t encrypt) {
40f66d273dSizick
41f66d273dSizick size_t size;
42f66d273dSizick soft_blowfish_ctx_t *soft_blowfish_ctx;
43f66d273dSizick
44f66d273dSizick soft_blowfish_ctx = calloc(1, sizeof (soft_blowfish_ctx_t));
45f66d273dSizick if (soft_blowfish_ctx == NULL) {
46f66d273dSizick return (CKR_HOST_MEMORY);
47f66d273dSizick }
48f66d273dSizick
49f66d273dSizick soft_blowfish_ctx->key_sched = blowfish_alloc_keysched(&size, 0);
50f66d273dSizick
51f66d273dSizick if (soft_blowfish_ctx->key_sched == NULL) {
52f66d273dSizick free(soft_blowfish_ctx);
53f66d273dSizick return (CKR_HOST_MEMORY);
54f66d273dSizick }
55f66d273dSizick
56f66d273dSizick soft_blowfish_ctx->keysched_len = size;
57f66d273dSizick
58f66d273dSizick (void) pthread_mutex_lock(&session_p->session_mutex);
59f66d273dSizick if (encrypt) {
60f66d273dSizick /* Called by C_EncryptInit */
61f66d273dSizick session_p->encrypt.context = soft_blowfish_ctx;
62f66d273dSizick session_p->encrypt.mech.mechanism = pMechanism->mechanism;
63f66d273dSizick } else {
64f66d273dSizick /* Called by C_DecryptInit */
65f66d273dSizick session_p->decrypt.context = soft_blowfish_ctx;
66f66d273dSizick session_p->decrypt.mech.mechanism = pMechanism->mechanism;
67f66d273dSizick }
68f66d273dSizick (void) pthread_mutex_unlock(&session_p->session_mutex);
69f66d273dSizick
70f66d273dSizick /*
71f66d273dSizick * If this is a non-sensitive key and it does NOT have
72f66d273dSizick * a key schedule yet, then allocate one and expand it.
73f66d273dSizick * Otherwise, if it's a non-sensitive key, and it DOES have
74f66d273dSizick * a key schedule already attached to it, just copy the
75f66d273dSizick * pre-expanded schedule to the context and avoid the
76f66d273dSizick * extra key schedule expansion operation.
77f66d273dSizick */
78f66d273dSizick if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
799627968bSmcpowers if (OBJ_KEY_SCHED(key_p) == NULL) {
80f66d273dSizick void *ks;
819627968bSmcpowers
829627968bSmcpowers (void) pthread_mutex_lock(&key_p->object_mutex);
839627968bSmcpowers if (OBJ_KEY_SCHED(key_p) == NULL) {
84f66d273dSizick ks = blowfish_alloc_keysched(&size, 0);
85f66d273dSizick if (ks == NULL) {
869627968bSmcpowers (void) pthread_mutex_unlock(
879627968bSmcpowers &key_p->object_mutex);
88f66d273dSizick free(soft_blowfish_ctx);
89f66d273dSizick return (CKR_HOST_MEMORY);
90f66d273dSizick }
91f66d273dSizick
92f66d273dSizick blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
939627968bSmcpowers (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
949627968bSmcpowers
959627968bSmcpowers OBJ_KEY_SCHED_LEN(key_p) = size;
969627968bSmcpowers OBJ_KEY_SCHED(key_p) = ks;
979627968bSmcpowers }
989627968bSmcpowers (void) pthread_mutex_unlock(&key_p->object_mutex);
99f66d273dSizick }
100f66d273dSizick (void) memcpy(soft_blowfish_ctx->key_sched,
101f66d273dSizick OBJ_KEY_SCHED(key_p), OBJ_KEY_SCHED_LEN(key_p));
102f66d273dSizick soft_blowfish_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
103f66d273dSizick
104f66d273dSizick } else {
105f66d273dSizick /*
106f66d273dSizick * Initialize key schedule for Blowfish.
107f66d273dSizick * blowfish_init_keysched() requires key length in bits.
108f66d273dSizick */
109f66d273dSizick blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
110f66d273dSizick (OBJ_SEC_VALUE_LEN(key_p) * 8),
111f66d273dSizick soft_blowfish_ctx->key_sched);
112f66d273dSizick }
113f66d273dSizick return (CKR_OK);
114f66d273dSizick }
115f66d273dSizick
116f66d273dSizick
117f66d273dSizick /*
118f66d273dSizick * soft_blowfish_encrypt_common()
119f66d273dSizick *
120f66d273dSizick * Arguments:
121f66d273dSizick * session_p: pointer to soft_session_t struct
122f66d273dSizick * pData: pointer to the input data to be encrypted
123f66d273dSizick * ulDataLen: length of the input data
124f66d273dSizick * pEncrypted: pointer to the output data after encryption
125f66d273dSizick * pulEncryptedLen: pointer to the length of the output data
126f66d273dSizick * update: boolean flag indicates caller is soft_encrypt
127f66d273dSizick * or soft_encrypt_update
128f66d273dSizick *
129f66d273dSizick * Description:
130f66d273dSizick * This function calls the corresponding encrypt routine based
131f66d273dSizick * on the mechanism.
132f66d273dSizick *
133f66d273dSizick * Returns:
134f66d273dSizick * CKR_OK: success
135f66d273dSizick * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
136f66d273dSizick * is too small
137f66d273dSizick * CKR_FUNCTION_FAILED: encrypt function failed
138f66d273dSizick * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
139f66d273dSizick */
140f66d273dSizick CK_RV
soft_blowfish_encrypt_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncrypted,CK_ULONG_PTR pulEncryptedLen,boolean_t update)141f66d273dSizick soft_blowfish_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
142f66d273dSizick CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, CK_ULONG_PTR pulEncryptedLen,
143f66d273dSizick boolean_t update) {
144f66d273dSizick
145f66d273dSizick int rc = 0;
146f66d273dSizick CK_RV rv = CKR_OK;
147f66d273dSizick soft_blowfish_ctx_t *soft_blowfish_ctx =
148f66d273dSizick (soft_blowfish_ctx_t *)session_p->encrypt.context;
149f66d273dSizick blowfish_ctx_t *blowfish_ctx;
150f66d273dSizick CK_BYTE *in_buf = NULL;
151f66d273dSizick CK_BYTE *out_buf = NULL;
152f66d273dSizick CK_ULONG out_len;
153f66d273dSizick CK_ULONG total_len;
154f66d273dSizick CK_ULONG remain;
155f66d273dSizick crypto_data_t out;
156f66d273dSizick
157f66d273dSizick /*
158f66d273dSizick * Blowfish only takes input length that is a multiple of blocksize
159f66d273dSizick * for C_Encrypt function with the mechanism CKM_BLOWFISH_CBC.
160f66d273dSizick *
161f66d273dSizick */
162f66d273dSizick if (!update) {
163f66d273dSizick if ((ulDataLen % BLOWFISH_BLOCK_LEN) != 0) {
164f66d273dSizick rv = CKR_DATA_LEN_RANGE;
165f66d273dSizick goto cleanup;
166f66d273dSizick }
167f66d273dSizick
168f66d273dSizick out_len = ulDataLen;
169f66d273dSizick /*
170f66d273dSizick * If application asks for the length of the output buffer
171f66d273dSizick * to hold the ciphertext?
172f66d273dSizick */
173f66d273dSizick if (pEncrypted == NULL) {
174f66d273dSizick *pulEncryptedLen = out_len;
175f66d273dSizick return (CKR_OK);
176f66d273dSizick }
177f66d273dSizick
178f66d273dSizick /* Is the application-supplied buffer large enough? */
179f66d273dSizick if (*pulEncryptedLen < out_len) {
180f66d273dSizick *pulEncryptedLen = out_len;
181f66d273dSizick return (CKR_BUFFER_TOO_SMALL);
182f66d273dSizick }
183f66d273dSizick
184f66d273dSizick in_buf = pData;
185f66d273dSizick out_buf = pEncrypted;
186f66d273dSizick } else {
187f66d273dSizick /*
188f66d273dSizick * Called by C_EncryptUpdate
189f66d273dSizick *
190f66d273dSizick * Add the lengths of last remaining data and current
191f66d273dSizick * plaintext together to get the total input length.
192f66d273dSizick */
193f66d273dSizick total_len = soft_blowfish_ctx->remain_len + ulDataLen;
194f66d273dSizick
195f66d273dSizick /*
196f66d273dSizick * If the total input length is less than one blocksize,
197f66d273dSizick * we will need to delay encryption until when more data
198f66d273dSizick * comes in next C_EncryptUpdate or when C_EncryptFinal
199f66d273dSizick * is called.
200f66d273dSizick */
201f66d273dSizick if (total_len < BLOWFISH_BLOCK_LEN) {
202f66d273dSizick if (pEncrypted != NULL) {
203f66d273dSizick /*
204f66d273dSizick * Save input data and its length in
205f66d273dSizick * the remaining buffer of BLOWFISH context.
206f66d273dSizick */
207f66d273dSizick (void) memcpy(soft_blowfish_ctx->data +
208f66d273dSizick soft_blowfish_ctx->remain_len, pData,
209f66d273dSizick ulDataLen);
210f66d273dSizick soft_blowfish_ctx->remain_len += ulDataLen;
211f66d273dSizick }
212f66d273dSizick
213f66d273dSizick /* Set encrypted data length to 0. */
214f66d273dSizick *pulEncryptedLen = 0;
215f66d273dSizick return (CKR_OK);
216f66d273dSizick }
217f66d273dSizick
218f66d273dSizick /* Compute the length of remaing data. */
219f66d273dSizick remain = total_len % BLOWFISH_BLOCK_LEN;
220f66d273dSizick
221f66d273dSizick /*
222f66d273dSizick * Make sure that the output length is a multiple of
223f66d273dSizick * blocksize.
224f66d273dSizick */
225f66d273dSizick out_len = total_len - remain;
226f66d273dSizick
227f66d273dSizick /*
228f66d273dSizick * If application asks for the length of the output buffer
229f66d273dSizick * to hold the ciphertext?
230f66d273dSizick */
231f66d273dSizick if (pEncrypted == NULL) {
232f66d273dSizick *pulEncryptedLen = out_len;
233f66d273dSizick return (CKR_OK);
234f66d273dSizick }
235f66d273dSizick
236f66d273dSizick /* Is the application-supplied buffer large enough? */
237f66d273dSizick if (*pulEncryptedLen < out_len) {
238f66d273dSizick *pulEncryptedLen = out_len;
239f66d273dSizick return (CKR_BUFFER_TOO_SMALL);
240f66d273dSizick }
241f66d273dSizick
242f66d273dSizick if (soft_blowfish_ctx->remain_len != 0) {
243f66d273dSizick /*
244f66d273dSizick * Copy last remaining data and current input data
245f66d273dSizick * to the output buffer.
246f66d273dSizick */
247f66d273dSizick (void) memmove(pEncrypted +
248f66d273dSizick soft_blowfish_ctx->remain_len,
249f66d273dSizick pData, out_len - soft_blowfish_ctx->remain_len);
250f66d273dSizick (void) memcpy(pEncrypted, soft_blowfish_ctx->data,
251f66d273dSizick soft_blowfish_ctx->remain_len);
252f66d273dSizick bzero(soft_blowfish_ctx->data,
253f66d273dSizick soft_blowfish_ctx->remain_len);
254f66d273dSizick
255f66d273dSizick in_buf = pEncrypted;
256f66d273dSizick } else {
257f66d273dSizick in_buf = pData;
258f66d273dSizick }
259f66d273dSizick out_buf = pEncrypted;
260f66d273dSizick }
261f66d273dSizick
262f66d273dSizick /*
263f66d273dSizick * Begin Encryption now.
264f66d273dSizick */
265f66d273dSizick
266f66d273dSizick out.cd_format = CRYPTO_DATA_RAW;
267f66d273dSizick out.cd_offset = 0;
268f66d273dSizick out.cd_length = out_len;
269f66d273dSizick out.cd_raw.iov_base = (char *)out_buf;
270f66d273dSizick out.cd_raw.iov_len = out_len;
271f66d273dSizick
272f66d273dSizick /* Encrypt multiple blocks of data. */
273f66d273dSizick rc = blowfish_encrypt_contiguous_blocks(
274f66d273dSizick (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
275f66d273dSizick (char *)in_buf, out_len, &out);
276f66d273dSizick
277f66d273dSizick if (rc == 0) {
278f66d273dSizick *pulEncryptedLen = out_len;
279f66d273dSizick if (update) {
280f66d273dSizick /*
281f66d273dSizick * For encrypt update, if there is remaining data,
282f66d273dSizick * save it and it's length in the context.
283f66d273dSizick */
284f66d273dSizick if (remain != 0)
285f66d273dSizick (void) memcpy(soft_blowfish_ctx->data, pData +
286f66d273dSizick (ulDataLen - remain), remain);
287f66d273dSizick
288f66d273dSizick soft_blowfish_ctx->remain_len = remain;
289f66d273dSizick return (CKR_OK);
290f66d273dSizick }
291f66d273dSizick
2924c21f043Sizick } else {
293f66d273dSizick *pulEncryptedLen = 0;
294f66d273dSizick rv = CKR_FUNCTION_FAILED;
2954c21f043Sizick }
296f66d273dSizick
297f66d273dSizick cleanup:
298f66d273dSizick (void) pthread_mutex_lock(&session_p->session_mutex);
299f66d273dSizick blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
300f66d273dSizick if (blowfish_ctx != NULL) {
301f66d273dSizick bzero(blowfish_ctx->bc_keysched,
302f66d273dSizick blowfish_ctx->bc_keysched_len);
303f66d273dSizick free(soft_blowfish_ctx->blowfish_cbc);
304f66d273dSizick }
305f66d273dSizick
306f66d273dSizick bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
307f66d273dSizick free(soft_blowfish_ctx->key_sched);
308f66d273dSizick free(session_p->encrypt.context);
309f66d273dSizick session_p->encrypt.context = NULL;
310f66d273dSizick (void) pthread_mutex_unlock(&session_p->session_mutex);
311f66d273dSizick
312f66d273dSizick return (rv);
313f66d273dSizick }
314f66d273dSizick
315f66d273dSizick
316f66d273dSizick CK_RV
soft_blowfish_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)317f66d273dSizick soft_blowfish_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
318f66d273dSizick CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen,
319f66d273dSizick boolean_t update) {
320f66d273dSizick
321f66d273dSizick int rc = 0;
322f66d273dSizick CK_RV rv = CKR_OK;
323f66d273dSizick soft_blowfish_ctx_t *soft_blowfish_ctx =
324f66d273dSizick (soft_blowfish_ctx_t *)session_p->decrypt.context;
325f66d273dSizick blowfish_ctx_t *blowfish_ctx;
326f66d273dSizick CK_BYTE *in_buf = NULL;
327f66d273dSizick CK_BYTE *out_buf = NULL;
328f66d273dSizick CK_ULONG out_len;
329f66d273dSizick CK_ULONG total_len;
330f66d273dSizick CK_ULONG remain;
331f66d273dSizick crypto_data_t out;
332f66d273dSizick
333f66d273dSizick /*
334f66d273dSizick * Blowfish only takes input length that is a multiple of 16 bytes
335f66d273dSizick * for C_Decrypt function using CKM_BLOWFISH_CBC.
336f66d273dSizick */
337f66d273dSizick
338f66d273dSizick if (!update) {
339f66d273dSizick /* Called by C_Decrypt */
340f66d273dSizick if ((ulEncryptedLen % BLOWFISH_BLOCK_LEN) != 0) {
341f66d273dSizick rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
342f66d273dSizick goto cleanup;
343f66d273dSizick }
344f66d273dSizick
345f66d273dSizick /*
3464c21f043Sizick * If application asks for the length of the output buffer
347f66d273dSizick * to hold the plaintext?
348f66d273dSizick */
349f66d273dSizick if (pData == NULL) {
350f66d273dSizick *pulDataLen = ulEncryptedLen;
351f66d273dSizick return (CKR_OK);
352f66d273dSizick }
353f66d273dSizick
354f66d273dSizick /* Is the application-supplied buffer large enough? */
355f66d273dSizick if (*pulDataLen < ulEncryptedLen) {
356f66d273dSizick *pulDataLen = ulEncryptedLen;
357f66d273dSizick return (CKR_BUFFER_TOO_SMALL);
358f66d273dSizick }
359f66d273dSizick out_len = ulEncryptedLen;
360f66d273dSizick in_buf = pEncrypted;
361f66d273dSizick out_buf = pData;
362f66d273dSizick } else {
363f66d273dSizick /*
364f66d273dSizick * Called by C_DecryptUpdate
365f66d273dSizick *
366f66d273dSizick * Add the lengths of last remaining data and current
367f66d273dSizick * input data together to get the total input length.
368f66d273dSizick */
369f66d273dSizick total_len = soft_blowfish_ctx->remain_len + ulEncryptedLen;
370f66d273dSizick
371f66d273dSizick if (total_len < BLOWFISH_BLOCK_LEN) {
372f66d273dSizick if (pData != NULL) {
373f66d273dSizick (void) memcpy(soft_blowfish_ctx->data +
374f66d273dSizick soft_blowfish_ctx->remain_len,
375f66d273dSizick pEncrypted, ulEncryptedLen);
376f66d273dSizick
377f66d273dSizick soft_blowfish_ctx->remain_len += ulEncryptedLen;
378f66d273dSizick }
379f66d273dSizick
380f66d273dSizick /* Set output data length to 0. */
381f66d273dSizick *pulDataLen = 0;
382f66d273dSizick return (CKR_OK);
383f66d273dSizick }
384f66d273dSizick
385f66d273dSizick /* Compute the length of remaining data. */
386f66d273dSizick remain = total_len % BLOWFISH_BLOCK_LEN;
387f66d273dSizick
388f66d273dSizick /*
389f66d273dSizick * Make sure that the output length is a multiple of
390f66d273dSizick * blocksize.
391f66d273dSizick */
392f66d273dSizick out_len = total_len - remain;
393f66d273dSizick
394f66d273dSizick /*
395f66d273dSizick * if application asks for the length of the output buffer
396f66d273dSizick * to hold the plaintext?
397f66d273dSizick */
398f66d273dSizick if (pData == NULL) {
399f66d273dSizick *pulDataLen = out_len;
400f66d273dSizick return (CKR_OK);
401f66d273dSizick }
402f66d273dSizick
403f66d273dSizick /*
404f66d273dSizick * Is the application-supplied buffer large enough?
405f66d273dSizick */
406f66d273dSizick if (*pulDataLen < out_len) {
407f66d273dSizick *pulDataLen = out_len;
408f66d273dSizick return (CKR_BUFFER_TOO_SMALL);
409f66d273dSizick }
410f66d273dSizick
411f66d273dSizick if (soft_blowfish_ctx->remain_len != 0) {
412f66d273dSizick /*
413f66d273dSizick * Copy last remaining data and current input data
414f66d273dSizick * to the output buffer.
415f66d273dSizick */
416f66d273dSizick (void) memmove(pData + soft_blowfish_ctx->remain_len,
417f66d273dSizick pEncrypted,
418f66d273dSizick out_len - soft_blowfish_ctx->remain_len);
419f66d273dSizick (void) memcpy(pData, soft_blowfish_ctx->data,
420f66d273dSizick soft_blowfish_ctx->remain_len);
421f66d273dSizick bzero(soft_blowfish_ctx->data,
422f66d273dSizick soft_blowfish_ctx->remain_len);
423f66d273dSizick
424f66d273dSizick
425f66d273dSizick in_buf = pData;
426f66d273dSizick } else {
427f66d273dSizick in_buf = pEncrypted;
428f66d273dSizick }
429f66d273dSizick
430f66d273dSizick out_buf = pData;
431f66d273dSizick }
432f66d273dSizick
433f66d273dSizick out.cd_format = CRYPTO_DATA_RAW;
434f66d273dSizick out.cd_offset = 0;
435f66d273dSizick out.cd_length = out_len;
436f66d273dSizick out.cd_raw.iov_base = (char *)out_buf;
437f66d273dSizick out.cd_raw.iov_len = out_len;
438f66d273dSizick
439f66d273dSizick /* Decrypt multiple blocks of data. */
440f66d273dSizick rc = blowfish_decrypt_contiguous_blocks(
441f66d273dSizick (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
442f66d273dSizick (char *)in_buf, out_len, &out);
443f66d273dSizick
444f66d273dSizick if (rc == 0) {
445f66d273dSizick *pulDataLen = out_len;
446f66d273dSizick if (update) {
447f66d273dSizick /*
448f66d273dSizick * For decrypt update, if there is remaining data,
449f66d273dSizick * save it and its length in the context.
450f66d273dSizick */
451f66d273dSizick if (remain != 0)
452f66d273dSizick (void) memcpy(soft_blowfish_ctx->data,
453f66d273dSizick pEncrypted + (ulEncryptedLen - remain),
454f66d273dSizick remain);
455f66d273dSizick soft_blowfish_ctx->remain_len = remain;
456f66d273dSizick return (CKR_OK);
457f66d273dSizick }
458f66d273dSizick
459f66d273dSizick
460f66d273dSizick } else {
461f66d273dSizick *pulDataLen = 0;
462f66d273dSizick rv = CKR_FUNCTION_FAILED;
463f66d273dSizick }
464f66d273dSizick
465f66d273dSizick cleanup:
466f66d273dSizick (void) pthread_mutex_lock(&session_p->session_mutex);
467f66d273dSizick blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
468f66d273dSizick if (blowfish_ctx != NULL) {
469f66d273dSizick bzero(blowfish_ctx->bc_keysched,
470f66d273dSizick blowfish_ctx->bc_keysched_len);
471f66d273dSizick free(soft_blowfish_ctx->blowfish_cbc);
472f66d273dSizick }
473f66d273dSizick
474f66d273dSizick bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
475f66d273dSizick free(soft_blowfish_ctx->key_sched);
476f66d273dSizick free(session_p->decrypt.context);
477f66d273dSizick session_p->decrypt.context = NULL;
478f66d273dSizick (void) pthread_mutex_unlock(&session_p->session_mutex);
479f66d273dSizick
480f66d273dSizick return (rv);
481f66d273dSizick }
482f66d273dSizick
483f66d273dSizick /*
484f66d273dSizick * Allocate and initialize a context for BLOWFISH CBC mode of operation.
485f66d273dSizick */
486f66d273dSizick
487f66d273dSizick void *
blowfish_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec)488f66d273dSizick blowfish_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
489f66d273dSizick {
490f66d273dSizick
49123c57df7Smcpowers cbc_ctx_t *cbc_ctx;
492f66d273dSizick
49323c57df7Smcpowers if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
494f66d273dSizick return (NULL);
495f66d273dSizick
496*16239bc8SMark Powers cbc_ctx->cbc_keysched = key_sched;
497f66d273dSizick
498*16239bc8SMark Powers (void) memcpy(&cbc_ctx->cbc_iv[0], ivec, BLOWFISH_BLOCK_LEN);
499f66d273dSizick
500*16239bc8SMark Powers cbc_ctx->cbc_lastp = (uint8_t *)&(cbc_ctx->cbc_iv);
501*16239bc8SMark Powers cbc_ctx->cbc_keysched_len = size;
502*16239bc8SMark Powers cbc_ctx->cbc_flags |= CBC_MODE;
503f66d273dSizick
50423c57df7Smcpowers return (cbc_ctx);
505f66d273dSizick }
506