1676Sizick /*
22940Sizick  * CDDL HEADER START
32940Sizick  *
42940Sizick  * The contents of this file are subject to the terms of the
52940Sizick  * Common Development and Distribution License (the "License").
62940Sizick  * You may not use this file except in compliance with the License.
72940Sizick  *
82940Sizick  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92940Sizick  * or http://www.opensolaris.org/os/licensing.
102940Sizick  * See the License for the specific language governing permissions
112940Sizick  * and limitations under the License.
122940Sizick  *
132940Sizick  * When distributing Covered Code, include this CDDL HEADER in each
142940Sizick  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152940Sizick  * If applicable, add the following below this CDDL HEADER, with the
162940Sizick  * fields enclosed by brackets "[]" replaced with your own identifying
172940Sizick  * information: Portions Copyright [yyyy] [name of copyright owner]
182940Sizick  *
192940Sizick  * CDDL HEADER END
202940Sizick  */
212940Sizick /*
225862Smcpowers  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23676Sizick  * Use is subject to license terms.
24676Sizick  */
25676Sizick 
26676Sizick #include <pthread.h>
27676Sizick #include <stdlib.h>
28676Sizick #include <string.h>
29676Sizick #include <strings.h>
30676Sizick #include <sys/types.h>
31676Sizick #include <security/cryptoki.h>
32676Sizick #include "softSession.h"
33676Sizick #include "softObject.h"
34676Sizick #include "softCrypt.h"
357188Smcpowers #include <blowfish_impl.h>
36676Sizick 
37676Sizick CK_RV
soft_blowfish_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)38676Sizick soft_blowfish_crypt_init_common(soft_session_t *session_p,
39676Sizick     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t encrypt) {
40676Sizick 
41676Sizick 	size_t size;
42676Sizick 	soft_blowfish_ctx_t *soft_blowfish_ctx;
43676Sizick 
44676Sizick 	soft_blowfish_ctx = calloc(1, sizeof (soft_blowfish_ctx_t));
45676Sizick 	if (soft_blowfish_ctx == NULL) {
46676Sizick 		return (CKR_HOST_MEMORY);
47676Sizick 	}
48676Sizick 
49676Sizick 	soft_blowfish_ctx->key_sched = blowfish_alloc_keysched(&size, 0);
50676Sizick 
51676Sizick 	if (soft_blowfish_ctx->key_sched == NULL) {
52676Sizick 		free(soft_blowfish_ctx);
53676Sizick 		return (CKR_HOST_MEMORY);
54676Sizick 	}
55676Sizick 
56676Sizick 	soft_blowfish_ctx->keysched_len = size;
57676Sizick 
58676Sizick 	(void) pthread_mutex_lock(&session_p->session_mutex);
59676Sizick 	if (encrypt) {
60676Sizick 		/* Called by C_EncryptInit */
61676Sizick 		session_p->encrypt.context = soft_blowfish_ctx;
62676Sizick 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
63676Sizick 	} else {
64676Sizick 		/* Called by C_DecryptInit */
65676Sizick 		session_p->decrypt.context = soft_blowfish_ctx;
66676Sizick 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
67676Sizick 	}
68676Sizick 	(void) pthread_mutex_unlock(&session_p->session_mutex);
69676Sizick 
70676Sizick 	/*
71676Sizick 	 * If this is a non-sensitive key and it does NOT have
72676Sizick 	 * a key schedule yet, then allocate one and expand it.
73676Sizick 	 * Otherwise, if it's a non-sensitive key, and it DOES have
74676Sizick 	 * a key schedule already attached to it, just copy the
75676Sizick 	 * pre-expanded schedule to the context and avoid the
76676Sizick 	 * extra key schedule expansion operation.
77676Sizick 	 */
78676Sizick 	if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
795862Smcpowers 		if (OBJ_KEY_SCHED(key_p) == NULL) {
80676Sizick 			void *ks;
815862Smcpowers 
825862Smcpowers 			(void) pthread_mutex_lock(&key_p->object_mutex);
835862Smcpowers 			if (OBJ_KEY_SCHED(key_p) == NULL) {
845862Smcpowers 				ks = blowfish_alloc_keysched(&size, 0);
855862Smcpowers 				if (ks == NULL) {
865862Smcpowers 					(void) pthread_mutex_unlock(
875862Smcpowers 					    &key_p->object_mutex);
885862Smcpowers 					free(soft_blowfish_ctx);
895862Smcpowers 					return (CKR_HOST_MEMORY);
905862Smcpowers 				}
915862Smcpowers 
925862Smcpowers 				blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
935862Smcpowers 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
945862Smcpowers 
955862Smcpowers 				OBJ_KEY_SCHED_LEN(key_p) = size;
965862Smcpowers 				OBJ_KEY_SCHED(key_p) = ks;
97676Sizick 			}
985862Smcpowers 			(void) pthread_mutex_unlock(&key_p->object_mutex);
99676Sizick 		}
100676Sizick 		(void) memcpy(soft_blowfish_ctx->key_sched,
101676Sizick 		    OBJ_KEY_SCHED(key_p), OBJ_KEY_SCHED_LEN(key_p));
102676Sizick 		soft_blowfish_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
103676Sizick 
104676Sizick 	} else {
105676Sizick 		/*
106676Sizick 		 * Initialize key schedule for Blowfish.
107676Sizick 		 * blowfish_init_keysched() requires key length in bits.
108676Sizick 		 */
109676Sizick 		blowfish_init_keysched(OBJ_SEC_VALUE(key_p),
110676Sizick 		    (OBJ_SEC_VALUE_LEN(key_p) * 8),
111676Sizick 		    soft_blowfish_ctx->key_sched);
112676Sizick 	}
113676Sizick 	return (CKR_OK);
114676Sizick }
115676Sizick 
116676Sizick 
117676Sizick /*
118676Sizick  * soft_blowfish_encrypt_common()
119676Sizick  *
120676Sizick  * Arguments:
121676Sizick  *      session_p:	pointer to soft_session_t struct
122676Sizick  *	pData:		pointer to the input data to be encrypted
123676Sizick  *	ulDataLen:	length of the input data
124676Sizick  *	pEncrypted:	pointer to the output data after encryption
125676Sizick  *	pulEncryptedLen: pointer to the length of the output data
126676Sizick  *	update:		boolean flag indicates caller is soft_encrypt
127676Sizick  *			or soft_encrypt_update
128676Sizick  *
129676Sizick  * Description:
130676Sizick  *      This function calls the corresponding encrypt routine based
131676Sizick  *	on the mechanism.
132676Sizick  *
133676Sizick  * Returns:
134676Sizick  *      CKR_OK: success
135676Sizick  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
136676Sizick  *			      is too small
137676Sizick  *	CKR_FUNCTION_FAILED: encrypt function failed
138676Sizick  *	CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
139676Sizick  */
140676Sizick 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)141676Sizick soft_blowfish_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
142676Sizick     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, CK_ULONG_PTR pulEncryptedLen,
143676Sizick     boolean_t update) {
144676Sizick 
145676Sizick 	int rc = 0;
146676Sizick 	CK_RV rv = CKR_OK;
147676Sizick 	soft_blowfish_ctx_t *soft_blowfish_ctx =
148676Sizick 	    (soft_blowfish_ctx_t *)session_p->encrypt.context;
149676Sizick 	blowfish_ctx_t *blowfish_ctx;
150676Sizick 	CK_BYTE *in_buf = NULL;
151676Sizick 	CK_BYTE *out_buf = NULL;
152676Sizick 	CK_ULONG out_len;
153676Sizick 	CK_ULONG total_len;
154676Sizick 	CK_ULONG remain;
155676Sizick 	crypto_data_t out;
156676Sizick 
157676Sizick 	/*
158676Sizick 	 * Blowfish only takes input length that is a multiple of blocksize
159676Sizick 	 * for C_Encrypt function with the mechanism CKM_BLOWFISH_CBC.
160676Sizick 	 *
161676Sizick 	 */
162676Sizick 	if (!update) {
163676Sizick 		if ((ulDataLen % BLOWFISH_BLOCK_LEN) != 0) {
164676Sizick 			rv = CKR_DATA_LEN_RANGE;
165676Sizick 			goto cleanup;
166676Sizick 		}
167676Sizick 
168676Sizick 		out_len = ulDataLen;
169676Sizick 		/*
170676Sizick 		 * If application asks for the length of the output buffer
171676Sizick 		 * to hold the ciphertext?
172676Sizick 		 */
173676Sizick 		if (pEncrypted == NULL) {
174676Sizick 			*pulEncryptedLen = out_len;
175676Sizick 			return (CKR_OK);
176676Sizick 		}
177676Sizick 
178676Sizick 		/* Is the application-supplied buffer large enough? */
179676Sizick 		if (*pulEncryptedLen < out_len) {
180676Sizick 			*pulEncryptedLen = out_len;
181676Sizick 			return (CKR_BUFFER_TOO_SMALL);
182676Sizick 		}
183676Sizick 
184676Sizick 		in_buf = pData;
185676Sizick 		out_buf = pEncrypted;
186676Sizick 	} else {
187676Sizick 		/*
188676Sizick 		 * Called by C_EncryptUpdate
189676Sizick 		 *
190676Sizick 		 * Add the lengths of last remaining data and current
191676Sizick 		 * plaintext together to get the total input length.
192676Sizick 		 */
193676Sizick 		total_len = soft_blowfish_ctx->remain_len + ulDataLen;
194676Sizick 
195676Sizick 		/*
196676Sizick 		 * If the total input length is less than one blocksize,
197676Sizick 		 * we will need to delay encryption until when more data
198676Sizick 		 * comes in next C_EncryptUpdate or when C_EncryptFinal
199676Sizick 		 * is called.
200676Sizick 		 */
201676Sizick 		if (total_len < BLOWFISH_BLOCK_LEN) {
202676Sizick 			if (pEncrypted != NULL) {
203676Sizick 				/*
204676Sizick 				 * Save input data and its length in
205676Sizick 				 * the remaining buffer of BLOWFISH context.
206676Sizick 				 */
207676Sizick 				(void) memcpy(soft_blowfish_ctx->data +
208676Sizick 				    soft_blowfish_ctx->remain_len, pData,
209676Sizick 				    ulDataLen);
210676Sizick 				soft_blowfish_ctx->remain_len += ulDataLen;
211676Sizick 			}
212676Sizick 
213676Sizick 			/* Set encrypted data length to 0. */
214676Sizick 			*pulEncryptedLen = 0;
215676Sizick 			return (CKR_OK);
216676Sizick 		}
217676Sizick 
218676Sizick 		/* Compute the length of remaing data. */
219676Sizick 		remain = total_len % BLOWFISH_BLOCK_LEN;
220676Sizick 
221676Sizick 		/*
222676Sizick 		 * Make sure that the output length is a multiple of
223676Sizick 		 * blocksize.
224676Sizick 		 */
225676Sizick 		out_len = total_len - remain;
226676Sizick 
227676Sizick 		/*
228676Sizick 		 * If application asks for the length of the output buffer
229676Sizick 		 * to hold the ciphertext?
230676Sizick 		 */
231676Sizick 		if (pEncrypted == NULL) {
232676Sizick 			*pulEncryptedLen = out_len;
233676Sizick 			return (CKR_OK);
234676Sizick 		}
235676Sizick 
236676Sizick 		/* Is the application-supplied buffer large enough? */
237676Sizick 		if (*pulEncryptedLen < out_len) {
238676Sizick 			*pulEncryptedLen = out_len;
239676Sizick 			return (CKR_BUFFER_TOO_SMALL);
240676Sizick 		}
241676Sizick 
242676Sizick 		if (soft_blowfish_ctx->remain_len != 0) {
243676Sizick 			/*
244676Sizick 			 * Copy last remaining data and current input data
245676Sizick 			 * to the output buffer.
246676Sizick 			 */
247676Sizick 			(void) memmove(pEncrypted +
248676Sizick 			    soft_blowfish_ctx->remain_len,
249676Sizick 			    pData, out_len - soft_blowfish_ctx->remain_len);
250676Sizick 			(void) memcpy(pEncrypted, soft_blowfish_ctx->data,
251676Sizick 			    soft_blowfish_ctx->remain_len);
252676Sizick 			bzero(soft_blowfish_ctx->data,
253676Sizick 			    soft_blowfish_ctx->remain_len);
254676Sizick 
255676Sizick 			in_buf = pEncrypted;
256676Sizick 		} else {
257676Sizick 			in_buf = pData;
258676Sizick 		}
259676Sizick 		out_buf = pEncrypted;
260676Sizick 	}
261676Sizick 
262676Sizick 	/*
263676Sizick 	 * Begin Encryption now.
264676Sizick 	 */
265676Sizick 
266676Sizick 	out.cd_format = CRYPTO_DATA_RAW;
267676Sizick 	out.cd_offset = 0;
268676Sizick 	out.cd_length = out_len;
269676Sizick 	out.cd_raw.iov_base = (char *)out_buf;
270676Sizick 	out.cd_raw.iov_len = out_len;
271676Sizick 
272676Sizick 	/* Encrypt multiple blocks of data. */
273676Sizick 	rc = blowfish_encrypt_contiguous_blocks(
274676Sizick 		(blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
275676Sizick 		    (char *)in_buf, out_len, &out);
276676Sizick 
277676Sizick 	if (rc == 0) {
278676Sizick 		*pulEncryptedLen = out_len;
279676Sizick 		if (update) {
280676Sizick 			/*
281676Sizick 			 * For encrypt update, if there is remaining data,
282676Sizick 			 * save it and it's length in the context.
283676Sizick 			 */
284676Sizick 			if (remain != 0)
285676Sizick 				(void) memcpy(soft_blowfish_ctx->data, pData +
286676Sizick 				    (ulDataLen - remain), remain);
287676Sizick 
288676Sizick 			soft_blowfish_ctx->remain_len = remain;
2892940Sizick 			return (CKR_OK);
290676Sizick 		}
291676Sizick 
2922940Sizick 	} else {
2932940Sizick 		*pulEncryptedLen = 0;
2942940Sizick 		rv = CKR_FUNCTION_FAILED;
295676Sizick 	}
296676Sizick 
297676Sizick cleanup:
298676Sizick 	(void) pthread_mutex_lock(&session_p->session_mutex);
299676Sizick 	blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
300676Sizick 	if (blowfish_ctx != NULL) {
301676Sizick 		bzero(blowfish_ctx->bc_keysched,
302676Sizick 		    blowfish_ctx->bc_keysched_len);
303676Sizick 		free(soft_blowfish_ctx->blowfish_cbc);
304676Sizick 	}
305676Sizick 
306676Sizick 	bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
307676Sizick 	free(soft_blowfish_ctx->key_sched);
308676Sizick 	free(session_p->encrypt.context);
309676Sizick 	session_p->encrypt.context = NULL;
310676Sizick 	(void) pthread_mutex_unlock(&session_p->session_mutex);
311676Sizick 
312676Sizick 	return (rv);
313676Sizick }
314676Sizick 
315676Sizick 
316676Sizick 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)317676Sizick soft_blowfish_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
318676Sizick     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen,
319676Sizick     boolean_t update) {
320676Sizick 
321676Sizick 	int rc = 0;
322676Sizick 	CK_RV rv = CKR_OK;
323676Sizick 	soft_blowfish_ctx_t *soft_blowfish_ctx =
324676Sizick 	    (soft_blowfish_ctx_t *)session_p->decrypt.context;
325676Sizick 	blowfish_ctx_t *blowfish_ctx;
326676Sizick 	CK_BYTE *in_buf = NULL;
327676Sizick 	CK_BYTE *out_buf = NULL;
328676Sizick 	CK_ULONG out_len;
329676Sizick 	CK_ULONG total_len;
330676Sizick 	CK_ULONG remain;
331676Sizick 	crypto_data_t out;
332676Sizick 
333676Sizick 	/*
334676Sizick 	 * Blowfish only takes input length that is a multiple of 16 bytes
335676Sizick 	 * for C_Decrypt function using CKM_BLOWFISH_CBC.
336676Sizick 	 */
337676Sizick 
338676Sizick 	if (!update) {
339676Sizick 		/* Called by C_Decrypt */
340676Sizick 		if ((ulEncryptedLen % BLOWFISH_BLOCK_LEN) != 0) {
341676Sizick 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
342676Sizick 			goto cleanup;
343676Sizick 		}
344676Sizick 
345676Sizick 		/*
3462940Sizick 		 * If application asks for the length of the output buffer
347676Sizick 		 * to hold the plaintext?
348676Sizick 		 */
349676Sizick 		if (pData == NULL) {
350676Sizick 			*pulDataLen = ulEncryptedLen;
351676Sizick 			return (CKR_OK);
352676Sizick 		}
353676Sizick 
354676Sizick 		/* Is the application-supplied buffer large enough? */
355676Sizick 		if (*pulDataLen < ulEncryptedLen) {
356676Sizick 			*pulDataLen = ulEncryptedLen;
357676Sizick 			return (CKR_BUFFER_TOO_SMALL);
358676Sizick 		}
359676Sizick 		out_len = ulEncryptedLen;
360676Sizick 		in_buf = pEncrypted;
361676Sizick 		out_buf = pData;
362676Sizick 	} else {
363676Sizick 		/*
364676Sizick 		 * Called by C_DecryptUpdate
365676Sizick 		 *
366676Sizick 		 * Add the lengths of last remaining data and current
367676Sizick 		 * input data together to get the total input length.
368676Sizick 		 */
369676Sizick 		total_len = soft_blowfish_ctx->remain_len + ulEncryptedLen;
370676Sizick 
371676Sizick 		if (total_len < BLOWFISH_BLOCK_LEN) {
372676Sizick 			if (pData != NULL) {
373676Sizick 				(void) memcpy(soft_blowfish_ctx->data +
374676Sizick 				    soft_blowfish_ctx->remain_len,
375676Sizick 				    pEncrypted, ulEncryptedLen);
376676Sizick 
377676Sizick 				soft_blowfish_ctx->remain_len += ulEncryptedLen;
378676Sizick 			}
379676Sizick 
380676Sizick 			/* Set output data length to 0. */
381676Sizick 			*pulDataLen = 0;
382676Sizick 			return (CKR_OK);
383676Sizick 		}
384676Sizick 
385676Sizick 		/* Compute the length of remaining data. */
386676Sizick 		remain = total_len % BLOWFISH_BLOCK_LEN;
387676Sizick 
388676Sizick 		/*
389676Sizick 		 * Make sure that the output length is a multiple of
390676Sizick 		 * blocksize.
391676Sizick 		 */
392676Sizick 		out_len = total_len - remain;
393676Sizick 
394676Sizick 		/*
395676Sizick 		 * if application asks for the length of the output buffer
396676Sizick 		 * to hold the plaintext?
397676Sizick 		 */
398676Sizick 		if (pData == NULL) {
399676Sizick 			*pulDataLen = out_len;
400676Sizick 			return (CKR_OK);
401676Sizick 		}
402676Sizick 
403676Sizick 		/*
404676Sizick 		 * Is the application-supplied buffer large enough?
405676Sizick 		 */
406676Sizick 		if (*pulDataLen < out_len) {
407676Sizick 			*pulDataLen = out_len;
408676Sizick 			return (CKR_BUFFER_TOO_SMALL);
409676Sizick 		}
410676Sizick 
411676Sizick 		if (soft_blowfish_ctx->remain_len != 0) {
412676Sizick 			/*
413676Sizick 			 * Copy last remaining data and current input data
414676Sizick 			 * to the output buffer.
415676Sizick 			 */
416676Sizick 			(void) memmove(pData + soft_blowfish_ctx->remain_len,
417676Sizick 			    pEncrypted,
418676Sizick 			    out_len - soft_blowfish_ctx->remain_len);
419676Sizick 			(void) memcpy(pData, soft_blowfish_ctx->data,
420676Sizick 			    soft_blowfish_ctx->remain_len);
421676Sizick 			bzero(soft_blowfish_ctx->data,
422676Sizick 			    soft_blowfish_ctx->remain_len);
423676Sizick 
424676Sizick 
425676Sizick 			in_buf = pData;
426676Sizick 		} else {
427676Sizick 			in_buf = pEncrypted;
428676Sizick 		}
429676Sizick 
430676Sizick 		out_buf = pData;
431676Sizick 	}
432676Sizick 
433676Sizick 	out.cd_format = CRYPTO_DATA_RAW;
434676Sizick 	out.cd_offset = 0;
435676Sizick 	out.cd_length = out_len;
436676Sizick 	out.cd_raw.iov_base = (char *)out_buf;
437676Sizick 	out.cd_raw.iov_len = out_len;
438676Sizick 
439676Sizick 	/* Decrypt multiple blocks of data. */
440676Sizick 	rc = blowfish_decrypt_contiguous_blocks(
441676Sizick 		(blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc,
442676Sizick 		(char *)in_buf, out_len, &out);
443676Sizick 
444676Sizick 	if (rc == 0) {
445676Sizick 		*pulDataLen = out_len;
446676Sizick 		if (update) {
447676Sizick 			/*
448676Sizick 			 * For decrypt update, if there is remaining data,
449676Sizick 			 * save it and its length in the context.
450676Sizick 			 */
451676Sizick 			if (remain != 0)
452676Sizick 				(void) memcpy(soft_blowfish_ctx->data,
453676Sizick 				    pEncrypted + (ulEncryptedLen - remain),
454676Sizick 				    remain);
455676Sizick 			soft_blowfish_ctx->remain_len = remain;
456676Sizick 			return (CKR_OK);
457676Sizick 		}
458676Sizick 
459676Sizick 
460676Sizick 	} else {
461676Sizick 		*pulDataLen = 0;
462676Sizick 		rv = CKR_FUNCTION_FAILED;
463676Sizick 	}
464676Sizick 
465676Sizick cleanup:
466676Sizick 	(void) pthread_mutex_lock(&session_p->session_mutex);
467676Sizick 	blowfish_ctx = (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
468676Sizick 	if (blowfish_ctx != NULL) {
469676Sizick 		bzero(blowfish_ctx->bc_keysched,
470676Sizick 		    blowfish_ctx->bc_keysched_len);
471676Sizick 		free(soft_blowfish_ctx->blowfish_cbc);
472676Sizick 	}
473676Sizick 
474676Sizick 	bzero(soft_blowfish_ctx->key_sched, soft_blowfish_ctx->keysched_len);
475676Sizick 	free(soft_blowfish_ctx->key_sched);
476676Sizick 	free(session_p->decrypt.context);
477676Sizick 	session_p->decrypt.context = NULL;
478676Sizick 	(void) pthread_mutex_unlock(&session_p->session_mutex);
479676Sizick 
480676Sizick 	return (rv);
481676Sizick }
482676Sizick 
483676Sizick /*
484676Sizick  * Allocate and initialize a context for BLOWFISH CBC mode of operation.
485676Sizick  */
486676Sizick 
487676Sizick void *
blowfish_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec)488676Sizick blowfish_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
489676Sizick {
490676Sizick 
4917188Smcpowers 	cbc_ctx_t *cbc_ctx;
492676Sizick 
4937188Smcpowers 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
494676Sizick 		return (NULL);
495676Sizick 
496*7581SMark.Powers@Sun.COM 	cbc_ctx->cbc_keysched = key_sched;
497676Sizick 
498*7581SMark.Powers@Sun.COM 	(void) memcpy(&cbc_ctx->cbc_iv[0], ivec, BLOWFISH_BLOCK_LEN);
499676Sizick 
500*7581SMark.Powers@Sun.COM 	cbc_ctx->cbc_lastp = (uint8_t *)&(cbc_ctx->cbc_iv);
501*7581SMark.Powers@Sun.COM 	cbc_ctx->cbc_keysched_len = size;
502*7581SMark.Powers@Sun.COM 	cbc_ctx->cbc_flags |= CBC_MODE;
503676Sizick 
5047188Smcpowers 	return (cbc_ctx);
505676Sizick }
506