xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kms/common/kmsDecrypt.c (revision 12720:3db6e0082404)
1*12720SWyllys.Ingersoll@Sun.COM /*
2*12720SWyllys.Ingersoll@Sun.COM  * CDDL HEADER START
3*12720SWyllys.Ingersoll@Sun.COM  *
4*12720SWyllys.Ingersoll@Sun.COM  * The contents of this file are subject to the terms of the
5*12720SWyllys.Ingersoll@Sun.COM  * Common Development and Distribution License (the "License").
6*12720SWyllys.Ingersoll@Sun.COM  * You may not use this file except in compliance with the License.
7*12720SWyllys.Ingersoll@Sun.COM  *
8*12720SWyllys.Ingersoll@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*12720SWyllys.Ingersoll@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*12720SWyllys.Ingersoll@Sun.COM  * See the License for the specific language governing permissions
11*12720SWyllys.Ingersoll@Sun.COM  * and limitations under the License.
12*12720SWyllys.Ingersoll@Sun.COM  *
13*12720SWyllys.Ingersoll@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*12720SWyllys.Ingersoll@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*12720SWyllys.Ingersoll@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*12720SWyllys.Ingersoll@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*12720SWyllys.Ingersoll@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*12720SWyllys.Ingersoll@Sun.COM  *
19*12720SWyllys.Ingersoll@Sun.COM  * CDDL HEADER END
20*12720SWyllys.Ingersoll@Sun.COM  *
21*12720SWyllys.Ingersoll@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
22*12720SWyllys.Ingersoll@Sun.COM  */
23*12720SWyllys.Ingersoll@Sun.COM 
24*12720SWyllys.Ingersoll@Sun.COM #include <string.h>
25*12720SWyllys.Ingersoll@Sun.COM #include <strings.h>
26*12720SWyllys.Ingersoll@Sun.COM #include <security/cryptoki.h>
27*12720SWyllys.Ingersoll@Sun.COM #include "kmsGlobal.h"
28*12720SWyllys.Ingersoll@Sun.COM #include "kmsCrypt.h"
29*12720SWyllys.Ingersoll@Sun.COM 
30*12720SWyllys.Ingersoll@Sun.COM 
31*12720SWyllys.Ingersoll@Sun.COM /*
32*12720SWyllys.Ingersoll@Sun.COM  * kms_decrypt_init()
33*12720SWyllys.Ingersoll@Sun.COM  *
34*12720SWyllys.Ingersoll@Sun.COM  * Arguments:
35*12720SWyllys.Ingersoll@Sun.COM  *	session_p:	pointer to kms_session_t struct
36*12720SWyllys.Ingersoll@Sun.COM  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
37*12720SWyllys.Ingersoll@Sun.COM  *	key_p:		pointer to key kms_object_t struct
38*12720SWyllys.Ingersoll@Sun.COM  *
39*12720SWyllys.Ingersoll@Sun.COM  * Description:
40*12720SWyllys.Ingersoll@Sun.COM  *	called by C_DecryptInit(). This function calls the corresponding
41*12720SWyllys.Ingersoll@Sun.COM  *	decrypt init routine based on the mechanism.
42*12720SWyllys.Ingersoll@Sun.COM  *
43*12720SWyllys.Ingersoll@Sun.COM  * Returns:
44*12720SWyllys.Ingersoll@Sun.COM  *	CKR_OK: success
45*12720SWyllys.Ingersoll@Sun.COM  *	CKR_HOST_MEMORY: run out of system memory
46*12720SWyllys.Ingersoll@Sun.COM  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
47*12720SWyllys.Ingersoll@Sun.COM  *	CKR_MECHANISM_INVALID: invalid mechanism type
48*12720SWyllys.Ingersoll@Sun.COM  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
49*12720SWyllys.Ingersoll@Sun.COM  *				   with the specified mechanism
50*12720SWyllys.Ingersoll@Sun.COM  */
51*12720SWyllys.Ingersoll@Sun.COM CK_RV
kms_decrypt_init(kms_session_t * session_p,CK_MECHANISM_PTR pMechanism,kms_object_t * key_p)52*12720SWyllys.Ingersoll@Sun.COM kms_decrypt_init(kms_session_t *session_p, CK_MECHANISM_PTR pMechanism,
53*12720SWyllys.Ingersoll@Sun.COM     kms_object_t *key_p)
54*12720SWyllys.Ingersoll@Sun.COM {
55*12720SWyllys.Ingersoll@Sun.COM 
56*12720SWyllys.Ingersoll@Sun.COM 	CK_RV rv;
57*12720SWyllys.Ingersoll@Sun.COM 
58*12720SWyllys.Ingersoll@Sun.COM 	switch (pMechanism->mechanism) {
59*12720SWyllys.Ingersoll@Sun.COM 	case CKM_AES_CBC:
60*12720SWyllys.Ingersoll@Sun.COM 	case CKM_AES_CBC_PAD:
61*12720SWyllys.Ingersoll@Sun.COM 	{
62*12720SWyllys.Ingersoll@Sun.COM 		kms_aes_ctx_t *kms_aes_ctx;
63*12720SWyllys.Ingersoll@Sun.COM 
64*12720SWyllys.Ingersoll@Sun.COM 		if (key_p->key_type != CKK_AES) {
65*12720SWyllys.Ingersoll@Sun.COM 			return (CKR_KEY_TYPE_INCONSISTENT);
66*12720SWyllys.Ingersoll@Sun.COM 		}
67*12720SWyllys.Ingersoll@Sun.COM 
68*12720SWyllys.Ingersoll@Sun.COM 		if ((pMechanism->pParameter == NULL) ||
69*12720SWyllys.Ingersoll@Sun.COM 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
70*12720SWyllys.Ingersoll@Sun.COM 			return (CKR_MECHANISM_PARAM_INVALID);
71*12720SWyllys.Ingersoll@Sun.COM 		}
72*12720SWyllys.Ingersoll@Sun.COM 
73*12720SWyllys.Ingersoll@Sun.COM 		rv = kms_aes_crypt_init_common(session_p, pMechanism,
74*12720SWyllys.Ingersoll@Sun.COM 		    key_p, B_FALSE);
75*12720SWyllys.Ingersoll@Sun.COM 
76*12720SWyllys.Ingersoll@Sun.COM 		if (rv != CKR_OK)
77*12720SWyllys.Ingersoll@Sun.COM 			return (rv);
78*12720SWyllys.Ingersoll@Sun.COM 
79*12720SWyllys.Ingersoll@Sun.COM 		(void) pthread_mutex_lock(&session_p->session_mutex);
80*12720SWyllys.Ingersoll@Sun.COM 
81*12720SWyllys.Ingersoll@Sun.COM 		kms_aes_ctx = (kms_aes_ctx_t *)session_p->decrypt.context;
82*12720SWyllys.Ingersoll@Sun.COM 
83*12720SWyllys.Ingersoll@Sun.COM 		/* Save Initialization Vector (IV) in the context. */
84*12720SWyllys.Ingersoll@Sun.COM 		(void) memcpy(kms_aes_ctx->ivec, pMechanism->pParameter,
85*12720SWyllys.Ingersoll@Sun.COM 		    AES_BLOCK_LEN);
86*12720SWyllys.Ingersoll@Sun.COM 
87*12720SWyllys.Ingersoll@Sun.COM 		/* Allocate a context for AES cipher-block chaining. */
88*12720SWyllys.Ingersoll@Sun.COM 		kms_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
89*12720SWyllys.Ingersoll@Sun.COM 		    kms_aes_ctx->key_sched, kms_aes_ctx->keysched_len,
90*12720SWyllys.Ingersoll@Sun.COM 		    kms_aes_ctx->ivec);
91*12720SWyllys.Ingersoll@Sun.COM 
92*12720SWyllys.Ingersoll@Sun.COM 		if (kms_aes_ctx->aes_cbc == NULL) {
93*12720SWyllys.Ingersoll@Sun.COM 			bzero(kms_aes_ctx->key_sched,
94*12720SWyllys.Ingersoll@Sun.COM 			    kms_aes_ctx->keysched_len);
95*12720SWyllys.Ingersoll@Sun.COM 			free(kms_aes_ctx->key_sched);
96*12720SWyllys.Ingersoll@Sun.COM 			free(session_p->decrypt.context);
97*12720SWyllys.Ingersoll@Sun.COM 			session_p->decrypt.context = NULL;
98*12720SWyllys.Ingersoll@Sun.COM 			(void) pthread_mutex_unlock(&session_p->session_mutex);
99*12720SWyllys.Ingersoll@Sun.COM 			return (CKR_HOST_MEMORY);
100*12720SWyllys.Ingersoll@Sun.COM 		}
101*12720SWyllys.Ingersoll@Sun.COM 
102*12720SWyllys.Ingersoll@Sun.COM 		(void) pthread_mutex_unlock(&session_p->session_mutex);
103*12720SWyllys.Ingersoll@Sun.COM 
104*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
105*12720SWyllys.Ingersoll@Sun.COM 	}
106*12720SWyllys.Ingersoll@Sun.COM 	default:
107*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_MECHANISM_INVALID);
108*12720SWyllys.Ingersoll@Sun.COM 	}
109*12720SWyllys.Ingersoll@Sun.COM }
110*12720SWyllys.Ingersoll@Sun.COM 
111*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_DecryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)112*12720SWyllys.Ingersoll@Sun.COM C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
113*12720SWyllys.Ingersoll@Sun.COM     CK_OBJECT_HANDLE hKey)
114*12720SWyllys.Ingersoll@Sun.COM {
115*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
116*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
117*12720SWyllys.Ingersoll@Sun.COM 	kms_object_t	*key_p;
118*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
119*12720SWyllys.Ingersoll@Sun.COM 
120*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
121*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
122*12720SWyllys.Ingersoll@Sun.COM 
123*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
124*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
125*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
126*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
127*12720SWyllys.Ingersoll@Sun.COM 
128*12720SWyllys.Ingersoll@Sun.COM 	if (pMechanism == NULL) {
129*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
130*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
131*12720SWyllys.Ingersoll@Sun.COM 	}
132*12720SWyllys.Ingersoll@Sun.COM 
133*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the object pointer. */
134*12720SWyllys.Ingersoll@Sun.COM 	HANDLE2OBJECT(hKey, key_p, rv);
135*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
136*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
137*12720SWyllys.Ingersoll@Sun.COM 
138*12720SWyllys.Ingersoll@Sun.COM 	/* Check to see if key object allows for decryption. */
139*12720SWyllys.Ingersoll@Sun.COM 	if (!(key_p->bool_attr_mask & DECRYPT_BOOL_ON)) {
140*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_KEY_FUNCTION_NOT_PERMITTED;
141*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit1;
142*12720SWyllys.Ingersoll@Sun.COM 	}
143*12720SWyllys.Ingersoll@Sun.COM 
144*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
145*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
146*12720SWyllys.Ingersoll@Sun.COM 
147*12720SWyllys.Ingersoll@Sun.COM 	/* Check to see if decrypt operation is already active. */
148*12720SWyllys.Ingersoll@Sun.COM 	if (session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE) {
149*12720SWyllys.Ingersoll@Sun.COM 		/* free the memory to avoid memory leak */
150*12720SWyllys.Ingersoll@Sun.COM 		kms_crypt_cleanup(session_p, B_FALSE, lock_held);
151*12720SWyllys.Ingersoll@Sun.COM 	}
152*12720SWyllys.Ingersoll@Sun.COM 
153*12720SWyllys.Ingersoll@Sun.COM 	/*
154*12720SWyllys.Ingersoll@Sun.COM 	 * This active flag will remain ON until application calls either
155*12720SWyllys.Ingersoll@Sun.COM 	 * C_Decrypt or C_DecryptFinal to actually obtain the final piece
156*12720SWyllys.Ingersoll@Sun.COM 	 * of plaintext.
157*12720SWyllys.Ingersoll@Sun.COM 	 */
158*12720SWyllys.Ingersoll@Sun.COM 	session_p->decrypt.flags = CRYPTO_OPERATION_ACTIVE;
159*12720SWyllys.Ingersoll@Sun.COM 
160*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
161*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
162*12720SWyllys.Ingersoll@Sun.COM 
163*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_decrypt_init(session_p, pMechanism, key_p);
164*12720SWyllys.Ingersoll@Sun.COM 
165*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK) {
166*12720SWyllys.Ingersoll@Sun.COM 		(void) pthread_mutex_lock(&session_p->session_mutex);
167*12720SWyllys.Ingersoll@Sun.COM 		session_p->decrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
168*12720SWyllys.Ingersoll@Sun.COM 		lock_held = B_TRUE;
169*12720SWyllys.Ingersoll@Sun.COM 	}
170*12720SWyllys.Ingersoll@Sun.COM 
171*12720SWyllys.Ingersoll@Sun.COM clean_exit1:
172*12720SWyllys.Ingersoll@Sun.COM 	OBJ_REFRELE(key_p);
173*12720SWyllys.Ingersoll@Sun.COM clean_exit:
174*12720SWyllys.Ingersoll@Sun.COM 	REFRELE(session_p, lock_held);
175*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
176*12720SWyllys.Ingersoll@Sun.COM }
177*12720SWyllys.Ingersoll@Sun.COM 
178*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_Decrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedData,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)179*12720SWyllys.Ingersoll@Sun.COM C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData,
180*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG ulEncryptedData, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
181*12720SWyllys.Ingersoll@Sun.COM {
182*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
183*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
184*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
185*12720SWyllys.Ingersoll@Sun.COM 
186*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
187*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
188*12720SWyllys.Ingersoll@Sun.COM 
189*12720SWyllys.Ingersoll@Sun.COM 	/* Obatin the session pointer. */
190*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
191*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
192*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
193*12720SWyllys.Ingersoll@Sun.COM 
194*12720SWyllys.Ingersoll@Sun.COM 	/*
195*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if input buffer is null.  How to handle zero input
196*12720SWyllys.Ingersoll@Sun.COM 	 * length depents on the mechanism in use.  For secret key mechanisms,
197*12720SWyllys.Ingersoll@Sun.COM 	 * unpadded ones yield zero length output, but padded ones always
198*12720SWyllys.Ingersoll@Sun.COM 	 * result in smaller than original, possibly zero, length output.
199*12720SWyllys.Ingersoll@Sun.COM 	 */
200*12720SWyllys.Ingersoll@Sun.COM 	if (pEncryptedData == NULL) {
201*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
202*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
203*12720SWyllys.Ingersoll@Sun.COM 	}
204*12720SWyllys.Ingersoll@Sun.COM 
205*12720SWyllys.Ingersoll@Sun.COM 	/*
206*12720SWyllys.Ingersoll@Sun.COM 	 * No need to check pData because application might
207*12720SWyllys.Ingersoll@Sun.COM 	 * just want to know the length of decrypted data.
208*12720SWyllys.Ingersoll@Sun.COM 	 */
209*12720SWyllys.Ingersoll@Sun.COM 	if (pulDataLen == NULL) {
210*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
211*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
212*12720SWyllys.Ingersoll@Sun.COM 	}
213*12720SWyllys.Ingersoll@Sun.COM 
214*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
215*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
216*12720SWyllys.Ingersoll@Sun.COM 
217*12720SWyllys.Ingersoll@Sun.COM 	/* Application must call C_DecryptInit before calling C_Decrypt. */
218*12720SWyllys.Ingersoll@Sun.COM 	if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
219*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
220*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_OPERATION_NOT_INITIALIZED);
221*12720SWyllys.Ingersoll@Sun.COM 	}
222*12720SWyllys.Ingersoll@Sun.COM 
223*12720SWyllys.Ingersoll@Sun.COM 	/*
224*12720SWyllys.Ingersoll@Sun.COM 	 * C_Decrypt must be called without intervening C_DecryptUpdate
225*12720SWyllys.Ingersoll@Sun.COM 	 * calls.
226*12720SWyllys.Ingersoll@Sun.COM 	 */
227*12720SWyllys.Ingersoll@Sun.COM 	if (session_p->decrypt.flags & CRYPTO_OPERATION_UPDATE) {
228*12720SWyllys.Ingersoll@Sun.COM 		/*
229*12720SWyllys.Ingersoll@Sun.COM 		 * C_Decrypt can not be used to terminate a multi-part
230*12720SWyllys.Ingersoll@Sun.COM 		 * operation, so we'll leave the active decrypt operation
231*12720SWyllys.Ingersoll@Sun.COM 		 * flag on and let the application continue with the
232*12720SWyllys.Ingersoll@Sun.COM 		 * decrypt update operation.
233*12720SWyllys.Ingersoll@Sun.COM 		 */
234*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
235*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_FUNCTION_FAILED);
236*12720SWyllys.Ingersoll@Sun.COM 	}
237*12720SWyllys.Ingersoll@Sun.COM 
238*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
239*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
240*12720SWyllys.Ingersoll@Sun.COM 
241*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_decrypt_common(session_p, pEncryptedData,
242*12720SWyllys.Ingersoll@Sun.COM 	    ulEncryptedData, pData, pulDataLen, FALSE);
243*12720SWyllys.Ingersoll@Sun.COM 
244*12720SWyllys.Ingersoll@Sun.COM 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
245*12720SWyllys.Ingersoll@Sun.COM 	    (pData == NULL && rv == CKR_OK)) {
246*12720SWyllys.Ingersoll@Sun.COM 		/*
247*12720SWyllys.Ingersoll@Sun.COM 		 * We will not terminate the active decrypt operation flag,
248*12720SWyllys.Ingersoll@Sun.COM 		 * when the application-supplied buffer is too small, or
249*12720SWyllys.Ingersoll@Sun.COM 		 * the application asks for the length of buffer to hold
250*12720SWyllys.Ingersoll@Sun.COM 		 * the plaintext.
251*12720SWyllys.Ingersoll@Sun.COM 		 */
252*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
253*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
254*12720SWyllys.Ingersoll@Sun.COM 	}
255*12720SWyllys.Ingersoll@Sun.COM 
256*12720SWyllys.Ingersoll@Sun.COM clean_exit:
257*12720SWyllys.Ingersoll@Sun.COM 	/* Clear context, free key, and release session counter */
258*12720SWyllys.Ingersoll@Sun.COM 	kms_crypt_cleanup(session_p, B_FALSE, B_FALSE);
259*12720SWyllys.Ingersoll@Sun.COM 
260*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
261*12720SWyllys.Ingersoll@Sun.COM }
262*12720SWyllys.Ingersoll@Sun.COM 
263*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_DecryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)264*12720SWyllys.Ingersoll@Sun.COM C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart,
265*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
266*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG_PTR pulPartLen)
267*12720SWyllys.Ingersoll@Sun.COM {
268*12720SWyllys.Ingersoll@Sun.COM 
269*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
270*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
271*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
272*12720SWyllys.Ingersoll@Sun.COM 
273*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
274*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
275*12720SWyllys.Ingersoll@Sun.COM 
276*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
277*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
278*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
279*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
280*12720SWyllys.Ingersoll@Sun.COM 
281*12720SWyllys.Ingersoll@Sun.COM 	/*
282*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if input buffer is null.  How to handle zero input
283*12720SWyllys.Ingersoll@Sun.COM 	 * length depents on the mechanism in use.  For secret key mechanisms,
284*12720SWyllys.Ingersoll@Sun.COM 	 * unpadded ones yeild zero length output, but padded ones always
285*12720SWyllys.Ingersoll@Sun.COM 	 * result in smaller than original, possibly zero, length output.
286*12720SWyllys.Ingersoll@Sun.COM 	 */
287*12720SWyllys.Ingersoll@Sun.COM 	if (pEncryptedPart == NULL) {
288*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
289*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
290*12720SWyllys.Ingersoll@Sun.COM 	}
291*12720SWyllys.Ingersoll@Sun.COM 
292*12720SWyllys.Ingersoll@Sun.COM 	/*
293*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if pulPartLen is NULL.
294*12720SWyllys.Ingersoll@Sun.COM 	 * No need to check if pPart is NULL because application
295*12720SWyllys.Ingersoll@Sun.COM 	 * might just ask for the length of buffer to hold the
296*12720SWyllys.Ingersoll@Sun.COM 	 * recovered data.
297*12720SWyllys.Ingersoll@Sun.COM 	 */
298*12720SWyllys.Ingersoll@Sun.COM 	if (pulPartLen == NULL) {
299*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
300*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
301*12720SWyllys.Ingersoll@Sun.COM 	}
302*12720SWyllys.Ingersoll@Sun.COM 
303*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
304*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
305*12720SWyllys.Ingersoll@Sun.COM 
306*12720SWyllys.Ingersoll@Sun.COM 	/*
307*12720SWyllys.Ingersoll@Sun.COM 	 * Application must call C_DecryptInit before calling
308*12720SWyllys.Ingersoll@Sun.COM 	 * C_DecryptUpdate.
309*12720SWyllys.Ingersoll@Sun.COM 	 */
310*12720SWyllys.Ingersoll@Sun.COM 	if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
311*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
312*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_OPERATION_NOT_INITIALIZED);
313*12720SWyllys.Ingersoll@Sun.COM 	}
314*12720SWyllys.Ingersoll@Sun.COM 
315*12720SWyllys.Ingersoll@Sun.COM 	session_p->decrypt.flags |= CRYPTO_OPERATION_UPDATE;
316*12720SWyllys.Ingersoll@Sun.COM 
317*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
318*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
319*12720SWyllys.Ingersoll@Sun.COM 
320*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_decrypt_common(session_p, pEncryptedPart,
321*12720SWyllys.Ingersoll@Sun.COM 	    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE);
322*12720SWyllys.Ingersoll@Sun.COM 
323*12720SWyllys.Ingersoll@Sun.COM 	/*
324*12720SWyllys.Ingersoll@Sun.COM 	 * If CKR_OK or CKR_BUFFER_TOO_SMALL, don't terminate the
325*12720SWyllys.Ingersoll@Sun.COM 	 * current decryption operation.
326*12720SWyllys.Ingersoll@Sun.COM 	 */
327*12720SWyllys.Ingersoll@Sun.COM 	if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL)) {
328*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
329*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
330*12720SWyllys.Ingersoll@Sun.COM 	}
331*12720SWyllys.Ingersoll@Sun.COM 
332*12720SWyllys.Ingersoll@Sun.COM clean_exit:
333*12720SWyllys.Ingersoll@Sun.COM 	/*
334*12720SWyllys.Ingersoll@Sun.COM 	 * After an error occurred, terminate the current decrypt
335*12720SWyllys.Ingersoll@Sun.COM 	 * operation by resetting the active and update flags.
336*12720SWyllys.Ingersoll@Sun.COM 	 */
337*12720SWyllys.Ingersoll@Sun.COM 	kms_crypt_cleanup(session_p, B_FALSE, lock_held);
338*12720SWyllys.Ingersoll@Sun.COM 
339*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
340*12720SWyllys.Ingersoll@Sun.COM }
341*12720SWyllys.Ingersoll@Sun.COM 
342*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_DecryptFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)343*12720SWyllys.Ingersoll@Sun.COM C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart,
344*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG_PTR pulLastPartLen)
345*12720SWyllys.Ingersoll@Sun.COM {
346*12720SWyllys.Ingersoll@Sun.COM 
347*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
348*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
349*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
350*12720SWyllys.Ingersoll@Sun.COM 
351*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
352*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
353*12720SWyllys.Ingersoll@Sun.COM 
354*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
355*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
356*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
357*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
358*12720SWyllys.Ingersoll@Sun.COM 
359*12720SWyllys.Ingersoll@Sun.COM 	if (pulLastPartLen == NULL) {
360*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
361*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
362*12720SWyllys.Ingersoll@Sun.COM 	}
363*12720SWyllys.Ingersoll@Sun.COM 
364*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
365*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
366*12720SWyllys.Ingersoll@Sun.COM 
367*12720SWyllys.Ingersoll@Sun.COM 	/*
368*12720SWyllys.Ingersoll@Sun.COM 	 * Application must call C_DecryptInit before calling
369*12720SWyllys.Ingersoll@Sun.COM 	 * C_DecryptFinal.
370*12720SWyllys.Ingersoll@Sun.COM 	 */
371*12720SWyllys.Ingersoll@Sun.COM 	if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
372*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
373*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_OPERATION_NOT_INITIALIZED);
374*12720SWyllys.Ingersoll@Sun.COM 	}
375*12720SWyllys.Ingersoll@Sun.COM 
376*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
377*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
378*12720SWyllys.Ingersoll@Sun.COM 
379*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_decrypt_final(session_p, pLastPart, pulLastPartLen);
380*12720SWyllys.Ingersoll@Sun.COM 
381*12720SWyllys.Ingersoll@Sun.COM 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
382*12720SWyllys.Ingersoll@Sun.COM 	    (pLastPart == NULL && rv == CKR_OK)) {
383*12720SWyllys.Ingersoll@Sun.COM 		/*
384*12720SWyllys.Ingersoll@Sun.COM 		 * We will not terminate the active decrypt operation flag,
385*12720SWyllys.Ingersoll@Sun.COM 		 * when the application-supplied buffer is too small, or
386*12720SWyllys.Ingersoll@Sun.COM 		 * the application asks for the length of buffer to hold
387*12720SWyllys.Ingersoll@Sun.COM 		 * the plaintext.
388*12720SWyllys.Ingersoll@Sun.COM 		 */
389*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
390*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
391*12720SWyllys.Ingersoll@Sun.COM 	}
392*12720SWyllys.Ingersoll@Sun.COM 
393*12720SWyllys.Ingersoll@Sun.COM 	/* Terminates the active encrypt operation. */
394*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
395*12720SWyllys.Ingersoll@Sun.COM 	session_p->decrypt.flags = 0;
396*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
397*12720SWyllys.Ingersoll@Sun.COM 	REFRELE(session_p, lock_held);
398*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
399*12720SWyllys.Ingersoll@Sun.COM 
400*12720SWyllys.Ingersoll@Sun.COM clean_exit:
401*12720SWyllys.Ingersoll@Sun.COM 	/* Terminates the active decrypt operation */
402*12720SWyllys.Ingersoll@Sun.COM 	kms_crypt_cleanup(session_p, B_FALSE, lock_held);
403*12720SWyllys.Ingersoll@Sun.COM 
404*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
405*12720SWyllys.Ingersoll@Sun.COM }
406