softDecryptUtil.c revision 2786:2d1d57651e47
1213379Shselasky/*
2213379Shselasky * CDDL HEADER START
3213379Shselasky *
4213379Shselasky * The contents of this file are subject to the terms of the
5213379Shselasky * Common Development and Distribution License (the "License").
6213379Shselasky * You may not use this file except in compliance with the License.
7213379Shselasky *
8213379Shselasky * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9213379Shselasky * or http://www.opensolaris.org/os/licensing.
10213379Shselasky * See the License for the specific language governing permissions
11213379Shselasky * and limitations under the License.
12213379Shselasky *
13213379Shselasky * When distributing Covered Code, include this CDDL HEADER in each
14213379Shselasky * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15213379Shselasky * If applicable, add the following below this CDDL HEADER, with the
16213379Shselasky * fields enclosed by brackets "[]" replaced with your own identifying
17213379Shselasky * information: Portions Copyright [yyyy] [name of copyright owner]
18213379Shselasky *
19213379Shselasky * CDDL HEADER END
20213379Shselasky */
21213379Shselasky/*
22213379Shselasky * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23213379Shselasky * Use is subject to license terms.
24213379Shselasky */
25213379Shselasky
26213379Shselasky#pragma ident	"%Z%%M%	%I%	%E% SMI"
27213379Shselasky
28213379Shselasky#include <pthread.h>
29213379Shselasky#include <stdlib.h>
30213379Shselasky#include <string.h>
31213379Shselasky#include <strings.h>
32213379Shselasky#include <sys/types.h>
33213379Shselasky#include <security/cryptoki.h>
34213379Shselasky#include <des_cbc_crypt.h>
35213379Shselasky#include <aes_cbc_crypt.h>
36213379Shselasky#include <blowfish_cbc_crypt.h>
37213379Shselasky#include <arcfour.h>
38213379Shselasky#include "softSession.h"
39213379Shselasky#include "softObject.h"
40213379Shselasky#include "softOps.h"
41213379Shselasky#include "softCrypt.h"
42213379Shselasky#include "softRSA.h"
43213379Shselasky
44213379Shselasky
45213379Shselasky/*
46213379Shselasky * Remove padding bytes.
47213379Shselasky */
48213379ShselaskyCK_RV
49213379Shselaskysoft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
50213379Shselasky    CK_ULONG *pulDataLen, int block_size)
51213379Shselasky{
52213379Shselasky
53213379Shselasky	CK_BYTE  pad_value;
54213379Shselasky
55213379Shselasky	pad_value = pData[padded_len - 1];
56213379Shselasky
57213379Shselasky
58213379Shselasky	/* Make sure there is a valid padding value. */
59213379Shselasky	if ((pad_value == 0) || (pad_value > block_size))
60213379Shselasky	    return (CKR_ENCRYPTED_DATA_INVALID);
61228483Shselasky
62213379Shselasky	*pulDataLen = padded_len - pad_value;
63213379Shselasky	return (CKR_OK);
64213379Shselasky}
65213379Shselasky
66228483Shselasky
67213379Shselasky/*
68213379Shselasky * soft_decrypt_init()
69213379Shselasky *
70213379Shselasky * Arguments:
71213379Shselasky *	session_p:	pointer to soft_session_t struct
72213379Shselasky *	pMechanism:	pointer to CK_MECHANISM struct provided by application
73228483Shselasky *	key_p:		pointer to key soft_object_t struct
74228483Shselasky *
75228483Shselasky * Description:
76228483Shselasky *	called by C_DecryptInit(). This function calls the corresponding
77213379Shselasky *	decrypt init routine based on the mechanism.
78227843Smarius *
79213379Shselasky * Returns:
80213379Shselasky *	CKR_OK: success
81213379Shselasky *	CKR_HOST_MEMORY: run out of system memory
82213379Shselasky *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
83213379Shselasky *	CKR_MECHANISM_INVALID: invalid mechanism type
84213379Shselasky *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
85213379Shselasky *				   with the specified mechanism
86213379Shselasky */
87213379ShselaskyCK_RV
88213379Shselaskysoft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
89290331Shselasky    soft_object_t *key_p)
90213379Shselasky{
91213379Shselasky
92213379Shselasky	CK_RV rv;
93213379Shselasky
94213379Shselasky	switch (pMechanism->mechanism) {
95238015Smav
96238015Smav	case CKM_DES_ECB:
97238015Smav
98297852Smav		if (key_p->key_type != CKK_DES) {
99297852Smav			return (CKR_KEY_TYPE_INCONSISTENT);
100297852Smav		}
101238015Smav
102238015Smav		goto ecb_common;
103238015Smav
104289161Skevlo	case CKM_DES3_ECB:
105289161Skevlo
106289161Skevlo		if ((key_p->key_type != CKK_DES2) &&
107249336Smav		    (key_p->key_type != CKK_DES3)) {
108249336Smav			return (CKR_KEY_TYPE_INCONSISTENT);
109290331Shselasky		}
110290331Shselasky
111249336Smavecb_common:
112276968Shselasky
113289161Skevlo		return (soft_des_crypt_init_common(session_p, pMechanism,
114262364Shselasky		    key_p, B_FALSE));
115238015Smav
116238015Smav	case CKM_DES_CBC:
117238551Smav	case CKM_DES_CBC_PAD:
118238551Smav
119275439Smav		if (key_p->key_type != CKK_DES) {
120275439Smav			return (CKR_KEY_TYPE_INCONSISTENT);
121297341Smav		}
122297341Smav
123290331Shselasky		goto cbc_common;
124290331Shselasky
125238015Smav	case CKM_DES3_CBC:
126289013Shselasky	case CKM_DES3_CBC_PAD:
127289013Shselasky	{
128289013Shselasky		soft_des_ctx_t *soft_des_ctx;
129238015Smav
130238015Smav		if ((key_p->key_type != CKK_DES2) &&
131238015Smav		    (key_p->key_type != CKK_DES3)) {
132238015Smav			return (CKR_KEY_TYPE_INCONSISTENT);
133213379Shselasky		}
134213379Shselasky
135222018Srucbc_common:
136213379Shselasky		if ((pMechanism->pParameter == NULL) ||
137213379Shselasky		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
138213379Shselasky			return (CKR_MECHANISM_PARAM_INVALID);
139213379Shselasky		}
140213379Shselasky
141213379Shselasky		rv = soft_des_crypt_init_common(session_p, pMechanism,
142213379Shselasky		    key_p, B_FALSE);
143213379Shselasky
144213379Shselasky		if (rv != CKR_OK)
145213379Shselasky			return (rv);
146213379Shselasky
147213379Shselasky		(void) pthread_mutex_lock(&session_p->session_mutex);
148213379Shselasky
149213379Shselasky		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
150213379Shselasky		/* Save Initialization Vector (IV) in the context. */
151213379Shselasky		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
152213379Shselasky		    DES_BLOCK_LEN);
153213379Shselasky
154253398Skib		/* Allocate a context for DES cipher-block chaining. */
155253398Skib		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
156253398Skib		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
157251499Shselasky		    soft_des_ctx->ivec, key_p->key_type);
158251499Shselasky
159251499Shselasky		if (soft_des_ctx->des_cbc == NULL) {
160251499Shselasky			bzero(soft_des_ctx->key_sched,
161251499Shselasky			    soft_des_ctx->keysched_len);
162251499Shselasky			free(soft_des_ctx->key_sched);
163251499Shselasky			free(session_p->decrypt.context);
164251499Shselasky			session_p->decrypt.context = NULL;
165251499Shselasky			(void) pthread_mutex_unlock(&session_p->session_mutex);
166251499Shselasky			return (CKR_HOST_MEMORY);
167213379Shselasky		}
168255768Shselasky
169255768Shselasky		(void) pthread_mutex_unlock(&session_p->session_mutex);
170255768Shselasky
171268884Shselasky		return (rv);
172268884Shselasky	}
173255768Shselasky	case CKM_AES_ECB:
174255768Shselasky
175255768Shselasky		if (key_p->key_type != CKK_AES) {
176255768Shselasky			return (CKR_KEY_TYPE_INCONSISTENT);
177255768Shselasky		}
178255768Shselasky
179255768Shselasky		return (soft_aes_crypt_init_common(session_p, pMechanism,
180268604Shselasky		    key_p, B_FALSE));
181268884Shselasky
182268884Shselasky	case CKM_AES_CBC:
183268604Shselasky	case CKM_AES_CBC_PAD:
184268884Shselasky	{
185268884Shselasky		soft_aes_ctx_t *soft_aes_ctx;
186255768Shselasky
187255768Shselasky		if (key_p->key_type != CKK_AES) {
188255768Shselasky			return (CKR_KEY_TYPE_INCONSISTENT);
189255768Shselasky		}
190255768Shselasky
191255768Shselasky		if ((pMechanism->pParameter == NULL) ||
192255768Shselasky		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
193213379Shselasky			return (CKR_MECHANISM_PARAM_INVALID);
194213379Shselasky		}
195213379Shselasky
196253094Skib		rv = soft_aes_crypt_init_common(session_p, pMechanism,
197289161Skevlo		    key_p, B_FALSE);
198289161Skevlo
199213379Shselasky		if (rv != CKR_OK)
200213379Shselasky			return (rv);
201213379Shselasky
202213379Shselasky		(void) pthread_mutex_lock(&session_p->session_mutex);
203213379Shselasky
204213379Shselasky		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
205278278Shselasky
206213379Shselasky		/* Save Initialization Vector (IV) in the context. */
207213379Shselasky		(void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
208213379Shselasky		    AES_BLOCK_LEN);
209213379Shselasky
210213379Shselasky		/* Allocate a context for AES cipher-block chaining. */
211279693Shselasky		soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
212279693Shselasky		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
213290331Shselasky		    soft_aes_ctx->ivec);
214290331Shselasky
215279693Shselasky		if (soft_aes_ctx->aes_cbc == NULL) {
216279693Shselasky			bzero(soft_aes_ctx->key_sched,
217289161Skevlo			    soft_aes_ctx->keysched_len);
218289161Skevlo			free(soft_aes_ctx->key_sched);
219289161Skevlo			free(session_p->decrypt.context);
220279693Shselasky			session_p->decrypt.context = NULL;
221290331Shselasky			(void) pthread_mutex_unlock(&session_p->session_mutex);
222290331Shselasky			return (CKR_HOST_MEMORY);
223290331Shselasky		}
224290331Shselasky
225290331Shselasky		(void) pthread_mutex_unlock(&session_p->session_mutex);
226290331Shselasky
227290331Shselasky		return (rv);
228290331Shselasky	}
229290331Shselasky
230290331Shselasky	case CKM_BLOWFISH_CBC:
231290331Shselasky	{
232290331Shselasky		soft_blowfish_ctx_t *soft_blowfish_ctx;
233290331Shselasky
234279693Shselasky		if (key_p->key_type != CKK_BLOWFISH)
235290331Shselasky			return (CKR_KEY_TYPE_INCONSISTENT);
236279693Shselasky
237278278Shselasky		if ((pMechanism->pParameter == NULL) ||
238278278Shselasky		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
239278278Shselasky			return (CKR_MECHANISM_PARAM_INVALID);
240278278Shselasky
241278278Shselasky		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
242278278Shselasky		    key_p, B_FALSE);
243278278Shselasky
244278278Shselasky		if (rv != CKR_OK)
245251499Shselasky			return (rv);
246251499Shselasky
247276965Shselasky		(void) pthread_mutex_lock(&session_p->session_mutex);
248289161Skevlo
249276965Shselasky		soft_blowfish_ctx =
250276965Shselasky		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
251276965Shselasky
252276965Shselasky		/* Save Initialization Vector in the context. */
253276965Shselasky		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
254253094Skib		    BLOWFISH_BLOCK_LEN);
255253094Skib
256276965Shselasky		/* Allocate a context for CBC */
257276965Shselasky		soft_blowfish_ctx->blowfish_cbc =
258213379Shselasky		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
259276965Shselasky			soft_blowfish_ctx->keysched_len,
260213379Shselasky			soft_blowfish_ctx->ivec);
261255768Shselasky
262213379Shselasky		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
263213379Shselasky			bzero(soft_blowfish_ctx->key_sched,
264213379Shselasky			    soft_blowfish_ctx->keysched_len);
265213379Shselasky			free(soft_blowfish_ctx->key_sched);
266213379Shselasky			free(session_p->decrypt.context = NULL);
267213379Shselasky			(void) pthread_mutex_unlock(&session_p->session_mutex);
268213379Shselasky			return (CKR_HOST_MEMORY);
269213379Shselasky		}
270213379Shselasky
271213379Shselasky		(void) pthread_mutex_unlock(&session_p->session_mutex);
272251499Shselasky		return (rv);
273251499Shselasky	}
274251499Shselasky
275251499Shselasky	case CKM_RC4:
276276965Shselasky
277276965Shselasky		if (key_p->key_type != CKK_RC4) {
278276965Shselasky			return (CKR_KEY_TYPE_INCONSISTENT);
279276965Shselasky		}
280251499Shselasky
281251499Shselasky		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
282251499Shselasky		    B_FALSE));
283213379Shselasky
284276965Shselasky	case CKM_RSA_X_509:
285276965Shselasky	case CKM_RSA_PKCS:
286276965Shselasky
287276965Shselasky		if (key_p->key_type != CKK_RSA) {
288276965Shselasky			return (CKR_KEY_TYPE_INCONSISTENT);
289276965Shselasky		}
290276965Shselasky
291276965Shselasky		return (soft_rsa_crypt_init_common(session_p, pMechanism,
292251499Shselasky		    key_p, B_FALSE));
293251499Shselasky
294228483Shselasky	default:
295213379Shselasky		return (CKR_MECHANISM_INVALID);
296213379Shselasky	}
297213379Shselasky}
298213379Shselasky
299213379Shselasky
300213379Shselasky/*
301213379Shselasky * soft_decrypt_common()
302213379Shselasky *
303213379Shselasky * Arguments:
304213379Shselasky *      session_p:	pointer to soft_session_t struct
305213379Shselasky *	pEncrypted:	pointer to the encrypted data as input
306213379Shselasky *	ulEncryptedLen:	length of the input data
307213379Shselasky *	pData:		pointer to the output data contains plaintext
308213379Shselasky *	pulDataLen:	pointer to the length of the output data
309213379Shselasky *	Update:		boolean flag indicates caller is soft_decrypt
310213379Shselasky *			or soft_decrypt_update
311213379Shselasky *
312213379Shselasky * Description:
313213379Shselasky *      This function calls the corresponding decrypt routine based
314213379Shselasky *	on the mechanism.
315213379Shselasky *
316213379Shselasky * Returns:
317213379Shselasky *	see soft_decrypt_common().
318213379Shselasky */
319213379ShselaskyCK_RV
320213379Shselaskysoft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
321213379Shselasky    CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
322213379Shselasky    CK_ULONG_PTR pulDataLen, boolean_t Update)
323213379Shselasky{
324213379Shselasky
325213379Shselasky	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
326213379Shselasky
327227849Shselasky	switch (mechanism) {
328213379Shselasky
329278278Shselasky	case CKM_DES_ECB:
330278278Shselasky	case CKM_DES_CBC:
331251499Shselasky	case CKM_DES3_ECB:
332213379Shselasky	case CKM_DES3_CBC:
333213379Shselasky
334213379Shselasky		if (ulEncryptedLen == 0) {
335213379Shselasky			*pulDataLen = 0;
336213379Shselasky			return (CKR_OK);
337213379Shselasky		}
338213379Shselasky		/* FALLTHROUGH */
339276965Shselasky
340276965Shselasky	case CKM_DES_CBC_PAD:
341213379Shselasky	case CKM_DES3_CBC_PAD:
342276965Shselasky
343213379Shselasky		return (soft_des_decrypt_common(session_p, pEncrypted,
344213379Shselasky		    ulEncryptedLen, pData, pulDataLen, Update));
345213379Shselasky
346213379Shselasky	case CKM_AES_ECB:
347213379Shselasky	case CKM_AES_CBC:
348213379Shselasky
349213379Shselasky		if (ulEncryptedLen == 0) {
350213379Shselasky			*pulDataLen = 0;
351213379Shselasky			return (CKR_OK);
352213379Shselasky		}
353213379Shselasky		/* FALLTHROUGH */
354213379Shselasky
355228483Shselasky	case CKM_AES_CBC_PAD:
356228483Shselasky
357213379Shselasky		return (soft_aes_decrypt_common(session_p, pEncrypted,
358213379Shselasky		    ulEncryptedLen, pData, pulDataLen, Update));
359213379Shselasky
360213379Shselasky	case CKM_BLOWFISH_CBC:
361213379Shselasky
362213379Shselasky		if (ulEncryptedLen == 0) {
363213379Shselasky			*pulDataLen = 0;
364213379Shselasky			return (CKR_OK);
365213379Shselasky		}
366213379Shselasky
367213379Shselasky		return (soft_blowfish_decrypt_common(session_p, pEncrypted,
368213379Shselasky		    ulEncryptedLen, pData, pulDataLen, Update));
369213379Shselasky
370213379Shselasky	case CKM_RC4:
371213379Shselasky
372213379Shselasky		if (ulEncryptedLen == 0) {
373213379Shselasky			*pulDataLen = 0;
374213379Shselasky			return (CKR_OK);
375213379Shselasky		}
376213379Shselasky
377213379Shselasky
378213379Shselasky		return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
379213379Shselasky		    ulEncryptedLen, pData, pulDataLen));
380213379Shselasky
381213379Shselasky	case CKM_RSA_X_509:
382213379Shselasky	case CKM_RSA_PKCS:
383213379Shselasky
384213379Shselasky		return (soft_rsa_decrypt_common(session_p, pEncrypted,
385213379Shselasky		    ulEncryptedLen, pData, pulDataLen, mechanism));
386213379Shselasky
387213379Shselasky	default:
388213379Shselasky		return (CKR_MECHANISM_INVALID);
389213379Shselasky
390213379Shselasky	}
391213379Shselasky}
392213379Shselasky
393213379Shselasky
394213379Shselasky/*
395213379Shselasky * soft_decrypt()
396213379Shselasky *
397213379Shselasky * Arguments:
398213379Shselasky *      session_p:	pointer to soft_session_t struct
399228483Shselasky *	pEncryptedData: pointer to the encrypted data as input
400213379Shselasky *	ulEncryptedDataLen: length of the input data
401 *	pData:		pointer to the output data contains plaintext
402 *	pulDataLen:	pointer to the length of the output data
403 *
404 * Description:
405 *      called by C_Decrypt(). This function calls the soft_decrypt_common
406 *	routine.
407 *
408 * Returns:
409 *	see soft_decrypt_common().
410 */
411CK_RV
412soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
413    CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
414    CK_ULONG_PTR pulDataLen)
415{
416
417	return (soft_decrypt_common(session_p, pEncryptedData,
418	    ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
419}
420
421
422/*
423 * soft_decrypt_update()
424 *
425 * Arguments:
426 *      session_p:	pointer to soft_session_t struct
427 *	pEncryptedPart: pointer to the encrypted data as input
428 *	ulEncryptedPartLen: length of the input data
429 *	pPart:          pointer to the output data contains plaintext
430 *	pulPartLen:     pointer to the length of the output data
431 *
432 * Description:
433 *      called by C_DecryptUpdate(). This function calls the
434 *	soft_decrypt_common routine (with update flag on).
435 *
436 * Returns:
437 *	see soft_decrypt_common().
438 */
439CK_RV
440soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
441	CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
442	CK_ULONG_PTR pulPartLen)
443{
444
445	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
446
447	switch (mechanism) {
448
449	case CKM_DES_ECB:
450	case CKM_DES_CBC:
451	case CKM_DES_CBC_PAD:
452	case CKM_DES3_ECB:
453	case CKM_DES3_CBC:
454	case CKM_DES3_CBC_PAD:
455	case CKM_AES_ECB:
456	case CKM_AES_CBC:
457	case CKM_AES_CBC_PAD:
458	case CKM_BLOWFISH_CBC:
459	case CKM_RC4:
460
461		return (soft_decrypt_common(session_p, pEncryptedPart,
462		    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
463
464	default:
465		/* PKCS11: The mechanism only supports single-part operation. */
466		return (CKR_MECHANISM_INVALID);
467	}
468
469}
470
471
472/*
473 * soft_decrypt_final()
474 *
475 * Arguments:
476 *      session_p:	pointer to soft_session_t struct
477 *      pLastPart:	pointer to the last recovered data part
478 *      pulLastPartLen:	pointer to the length of the last recovered data part
479 *
480 * Description:
481 *      called by C_DecryptFinal().
482 *
483 * Returns:
484 *	CKR_OK: success
485 *	CKR_FUNCTION_FAILED: decrypt final function failed
486 *	CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
487 */
488CK_RV
489soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
490	CK_ULONG_PTR pulLastPartLen)
491{
492
493	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
494	CK_ULONG out_len;
495	CK_RV rv = CKR_OK;
496	int rc;
497
498	(void) pthread_mutex_lock(&session_p->session_mutex);
499
500	if (session_p->decrypt.context == NULL) {
501		rv = CKR_OPERATION_NOT_INITIALIZED;
502		*pulLastPartLen = 0;
503		goto clean2;
504	}
505	switch (mechanism) {
506
507	case CKM_DES_CBC_PAD:
508	case CKM_DES3_CBC_PAD:
509	{
510
511		soft_des_ctx_t *soft_des_ctx;
512
513		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
514
515		/*
516		 * We should have only one block of data left in the
517		 * remaining buffer.
518		 */
519		if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
520			*pulLastPartLen = 0;
521			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
522			/* Cleanup memory space. */
523			free(soft_des_ctx->des_cbc);
524			bzero(soft_des_ctx->key_sched,
525			    soft_des_ctx->keysched_len);
526			free(soft_des_ctx->key_sched);
527
528			goto clean1;
529		}
530
531		out_len = DES_BLOCK_LEN;
532
533		/*
534		 * If application asks for the length of the output buffer
535		 * to hold the plaintext?
536		 */
537		if (pLastPart == NULL) {
538			*pulLastPartLen = out_len;
539			rv = CKR_OK;
540			goto clean2;
541		} else {
542			crypto_data_t out;
543
544			/* Copy remaining data to the output buffer. */
545			(void) memcpy(pLastPart, soft_des_ctx->data,
546			    DES_BLOCK_LEN);
547
548			out.cd_format = CRYPTO_DATA_RAW;
549			out.cd_offset = 0;
550			out.cd_length = DES_BLOCK_LEN;
551			out.cd_raw.iov_base = (char *)pLastPart;
552			out.cd_raw.iov_len = DES_BLOCK_LEN;
553
554			/* Decrypt final block of data. */
555			rc = des_decrypt_contiguous_blocks(
556			    (des_ctx_t *)soft_des_ctx->des_cbc,
557			    (char *)pLastPart, DES_BLOCK_LEN, &out);
558
559			if (rc == 0) {
560				/*
561				 * Remove padding bytes after decryption of
562				 * ciphertext block to produce the original
563				 * plaintext.
564				 */
565				rv = soft_remove_pkcs7_padding(pLastPart,
566				    DES_BLOCK_LEN, &out_len, DES_BLOCK_LEN);
567				if (rv != CKR_OK)
568					*pulLastPartLen = 0;
569				else
570					*pulLastPartLen = out_len;
571			} else {
572				*pulLastPartLen = 0;
573				rv = CKR_FUNCTION_FAILED;
574			}
575
576			/* Cleanup memory space. */
577			free(soft_des_ctx->des_cbc);
578			bzero(soft_des_ctx->key_sched,
579			    soft_des_ctx->keysched_len);
580			free(soft_des_ctx->key_sched);
581
582		}
583
584		break;
585	}
586
587	case CKM_DES_CBC:
588	case CKM_DES_ECB:
589	case CKM_DES3_CBC:
590	case CKM_DES3_ECB:
591	{
592
593		soft_des_ctx_t *soft_des_ctx;
594
595		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
596		/*
597		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
598		 * so when the final is called, the remaining buffer
599		 * should not contain any more data.
600		 */
601		*pulLastPartLen = 0;
602		if (soft_des_ctx->remain_len != 0) {
603			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
604		} else {
605			if (pLastPart == NULL)
606				goto clean2;
607		}
608
609		/* Cleanup memory space. */
610		free(soft_des_ctx->des_cbc);
611		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
612		free(soft_des_ctx->key_sched);
613
614		break;
615	}
616
617	case CKM_AES_CBC_PAD:
618	{
619
620		soft_aes_ctx_t *soft_aes_ctx;
621
622		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
623
624		/*
625		 * We should have only one block of data left in the
626		 * remaining buffer.
627		 */
628		if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
629			*pulLastPartLen = 0;
630			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
631			/* Cleanup memory space. */
632			free(soft_aes_ctx->aes_cbc);
633			bzero(soft_aes_ctx->key_sched,
634			    soft_aes_ctx->keysched_len);
635			free(soft_aes_ctx->key_sched);
636
637			goto clean1;
638		}
639
640		out_len = AES_BLOCK_LEN;
641
642		/*
643		 * If application asks for the length of the output buffer
644		 * to hold the plaintext?
645		 */
646		if (pLastPart == NULL) {
647			*pulLastPartLen = out_len;
648			rv = CKR_OK;
649			goto clean2;
650		} else {
651			crypto_data_t out;
652
653			/* Copy remaining data to the output buffer. */
654			(void) memcpy(pLastPart, soft_aes_ctx->data,
655			    AES_BLOCK_LEN);
656
657			out.cd_format = CRYPTO_DATA_RAW;
658			out.cd_offset = 0;
659			out.cd_length = AES_BLOCK_LEN;
660			out.cd_raw.iov_base = (char *)pLastPart;
661			out.cd_raw.iov_len = AES_BLOCK_LEN;
662
663			/* Decrypt final block of data. */
664			rc = aes_decrypt_contiguous_blocks(
665			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
666			    (char *)pLastPart, AES_BLOCK_LEN, &out);
667
668			if (rc == 0) {
669				/*
670				 * Remove padding bytes after decryption of
671				 * ciphertext block to produce the original
672				 * plaintext.
673				 */
674				rv = soft_remove_pkcs7_padding(pLastPart,
675				    AES_BLOCK_LEN, &out_len, AES_BLOCK_LEN);
676				if (rv != CKR_OK)
677					*pulLastPartLen = 0;
678				else
679					*pulLastPartLen = out_len;
680			} else {
681				*pulLastPartLen = 0;
682				rv = CKR_FUNCTION_FAILED;
683			}
684
685			/* Cleanup memory space. */
686			free(soft_aes_ctx->aes_cbc);
687			bzero(soft_aes_ctx->key_sched,
688			    soft_aes_ctx->keysched_len);
689			free(soft_aes_ctx->key_sched);
690
691		}
692
693		break;
694	}
695
696	case CKM_AES_CBC:
697	case CKM_AES_ECB:
698	{
699		soft_aes_ctx_t *soft_aes_ctx;
700
701		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
702		/*
703		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
704		 * so when the final is called, the remaining buffer
705		 * should not contain any more data.
706		 */
707		*pulLastPartLen = 0;
708		if (soft_aes_ctx->remain_len != 0) {
709			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
710		} else {
711			if (pLastPart == NULL)
712				goto clean2;
713		}
714
715		/* Cleanup memory space. */
716		free(soft_aes_ctx->aes_cbc);
717		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
718		free(soft_aes_ctx->key_sched);
719
720		break;
721	}
722
723	case CKM_BLOWFISH_CBC:
724	{
725		soft_blowfish_ctx_t *soft_blowfish_ctx;
726
727		soft_blowfish_ctx =
728		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
729
730		*pulLastPartLen = 0;
731		if (soft_blowfish_ctx->remain_len != 0)
732			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
733		else {
734			if (pLastPart == NULL)
735				goto clean2;
736		}
737
738		free(soft_blowfish_ctx->blowfish_cbc);
739		bzero(soft_blowfish_ctx->key_sched,
740		    soft_blowfish_ctx->keysched_len);
741		free(soft_blowfish_ctx->key_sched);
742
743		break;
744	}
745
746	case CKM_RC4:
747	{
748		ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
749		bzero(key, sizeof (*key));
750		*pulLastPartLen = 0;
751		break;
752	}
753
754	default:
755		/* PKCS11: The mechanism only supports single-part operation. */
756		rv = CKR_MECHANISM_INVALID;
757		break;
758	}
759
760clean1:
761	free(session_p->decrypt.context);
762	session_p->decrypt.context = NULL;
763
764clean2:
765	(void) pthread_mutex_unlock(&session_p->session_mutex);
766
767	return (rv);
768
769}
770