xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kms/common/kmsEncrypt.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 static CK_RV
kms_encrypt_init(kms_session_t * session_p,CK_MECHANISM_PTR pMechanism,kms_object_t * key_p)31*12720SWyllys.Ingersoll@Sun.COM kms_encrypt_init(kms_session_t *session_p, CK_MECHANISM_PTR pMechanism,
32*12720SWyllys.Ingersoll@Sun.COM     kms_object_t *key_p)
33*12720SWyllys.Ingersoll@Sun.COM {
34*12720SWyllys.Ingersoll@Sun.COM 	CK_RV rv = CKR_OK;
35*12720SWyllys.Ingersoll@Sun.COM 	kms_aes_ctx_t *kms_aes_ctx;
36*12720SWyllys.Ingersoll@Sun.COM 
37*12720SWyllys.Ingersoll@Sun.COM 	if (pMechanism->mechanism != CKM_AES_CBC &&
38*12720SWyllys.Ingersoll@Sun.COM 	    pMechanism->mechanism != CKM_AES_CBC_PAD)
39*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_MECHANISM_INVALID);
40*12720SWyllys.Ingersoll@Sun.COM 
41*12720SWyllys.Ingersoll@Sun.COM 	if (key_p->key_type != CKK_AES) {
42*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_KEY_TYPE_INCONSISTENT);
43*12720SWyllys.Ingersoll@Sun.COM 	}
44*12720SWyllys.Ingersoll@Sun.COM 
45*12720SWyllys.Ingersoll@Sun.COM 	if ((pMechanism->pParameter == NULL) ||
46*12720SWyllys.Ingersoll@Sun.COM 	    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
47*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_MECHANISM_PARAM_INVALID);
48*12720SWyllys.Ingersoll@Sun.COM 	}
49*12720SWyllys.Ingersoll@Sun.COM 
50*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_crypt_init_common(session_p, pMechanism,
51*12720SWyllys.Ingersoll@Sun.COM 	    key_p, B_TRUE);
52*12720SWyllys.Ingersoll@Sun.COM 
53*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
54*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
55*12720SWyllys.Ingersoll@Sun.COM 
56*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
57*12720SWyllys.Ingersoll@Sun.COM 
58*12720SWyllys.Ingersoll@Sun.COM 	kms_aes_ctx = (kms_aes_ctx_t *)session_p->encrypt.context;
59*12720SWyllys.Ingersoll@Sun.COM 	/* Copy Initialization Vector (IV) into the context. */
60*12720SWyllys.Ingersoll@Sun.COM 
61*12720SWyllys.Ingersoll@Sun.COM 	(void) memcpy(kms_aes_ctx->ivec, pMechanism->pParameter,
62*12720SWyllys.Ingersoll@Sun.COM 	    AES_BLOCK_LEN);
63*12720SWyllys.Ingersoll@Sun.COM 
64*12720SWyllys.Ingersoll@Sun.COM 	/* Allocate a context for AES cipher-block chaining. */
65*12720SWyllys.Ingersoll@Sun.COM 	kms_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
66*12720SWyllys.Ingersoll@Sun.COM 	    kms_aes_ctx->key_sched, kms_aes_ctx->keysched_len,
67*12720SWyllys.Ingersoll@Sun.COM 	    kms_aes_ctx->ivec);
68*12720SWyllys.Ingersoll@Sun.COM 
69*12720SWyllys.Ingersoll@Sun.COM 	if (kms_aes_ctx->aes_cbc == NULL) {
70*12720SWyllys.Ingersoll@Sun.COM 		bzero(kms_aes_ctx->key_sched,
71*12720SWyllys.Ingersoll@Sun.COM 		    kms_aes_ctx->keysched_len);
72*12720SWyllys.Ingersoll@Sun.COM 		free(kms_aes_ctx->key_sched);
73*12720SWyllys.Ingersoll@Sun.COM 		free(session_p->encrypt.context);
74*12720SWyllys.Ingersoll@Sun.COM 		session_p->encrypt.context = NULL;
75*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_HOST_MEMORY;
76*12720SWyllys.Ingersoll@Sun.COM 	}
77*12720SWyllys.Ingersoll@Sun.COM 
78*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
79*12720SWyllys.Ingersoll@Sun.COM 
80*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
81*12720SWyllys.Ingersoll@Sun.COM }
82*12720SWyllys.Ingersoll@Sun.COM 
83*12720SWyllys.Ingersoll@Sun.COM void
kms_crypt_cleanup(kms_session_t * session_p,boolean_t encrypt,boolean_t lock_held)84*12720SWyllys.Ingersoll@Sun.COM kms_crypt_cleanup(kms_session_t *session_p, boolean_t encrypt,
85*12720SWyllys.Ingersoll@Sun.COM 	boolean_t lock_held)
86*12720SWyllys.Ingersoll@Sun.COM {
87*12720SWyllys.Ingersoll@Sun.COM 	kms_active_op_t *active_op;
88*12720SWyllys.Ingersoll@Sun.COM 	boolean_t lock_true = B_TRUE;
89*12720SWyllys.Ingersoll@Sun.COM 	kms_aes_ctx_t *kms_aes_ctx;
90*12720SWyllys.Ingersoll@Sun.COM 	aes_ctx_t *aes_ctx;
91*12720SWyllys.Ingersoll@Sun.COM 
92*12720SWyllys.Ingersoll@Sun.COM 	if (!lock_held)
93*12720SWyllys.Ingersoll@Sun.COM 		(void) pthread_mutex_lock(&session_p->session_mutex);
94*12720SWyllys.Ingersoll@Sun.COM 
95*12720SWyllys.Ingersoll@Sun.COM 	active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
96*12720SWyllys.Ingersoll@Sun.COM 	if (active_op->mech.mechanism != CKM_AES_CBC &&
97*12720SWyllys.Ingersoll@Sun.COM 	    active_op->mech.mechanism != CKM_AES_CBC_PAD)
98*12720SWyllys.Ingersoll@Sun.COM 		return;
99*12720SWyllys.Ingersoll@Sun.COM 
100*12720SWyllys.Ingersoll@Sun.COM 	kms_aes_ctx = (kms_aes_ctx_t *)active_op->context;
101*12720SWyllys.Ingersoll@Sun.COM 
102*12720SWyllys.Ingersoll@Sun.COM 	if (kms_aes_ctx != NULL) {
103*12720SWyllys.Ingersoll@Sun.COM 		aes_ctx = (aes_ctx_t *)kms_aes_ctx->aes_cbc;
104*12720SWyllys.Ingersoll@Sun.COM 		if (aes_ctx != NULL) {
105*12720SWyllys.Ingersoll@Sun.COM 			bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
106*12720SWyllys.Ingersoll@Sun.COM 			free(kms_aes_ctx->aes_cbc);
107*12720SWyllys.Ingersoll@Sun.COM 			bzero(kms_aes_ctx->key_sched,
108*12720SWyllys.Ingersoll@Sun.COM 			    kms_aes_ctx->keysched_len);
109*12720SWyllys.Ingersoll@Sun.COM 			free(kms_aes_ctx->key_sched);
110*12720SWyllys.Ingersoll@Sun.COM 		}
111*12720SWyllys.Ingersoll@Sun.COM 	}
112*12720SWyllys.Ingersoll@Sun.COM 	if (active_op->context != NULL) {
113*12720SWyllys.Ingersoll@Sun.COM 		free(active_op->context);
114*12720SWyllys.Ingersoll@Sun.COM 		active_op->context = NULL;
115*12720SWyllys.Ingersoll@Sun.COM 	}
116*12720SWyllys.Ingersoll@Sun.COM 	active_op->flags = 0;
117*12720SWyllys.Ingersoll@Sun.COM 	if (!lock_held)
118*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_true);
119*12720SWyllys.Ingersoll@Sun.COM }
120*12720SWyllys.Ingersoll@Sun.COM 
121*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)122*12720SWyllys.Ingersoll@Sun.COM C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
123*12720SWyllys.Ingersoll@Sun.COM     CK_OBJECT_HANDLE hKey)
124*12720SWyllys.Ingersoll@Sun.COM {
125*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
126*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
127*12720SWyllys.Ingersoll@Sun.COM 	kms_object_t	*key_p;
128*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
129*12720SWyllys.Ingersoll@Sun.COM 
130*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
131*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
132*12720SWyllys.Ingersoll@Sun.COM 
133*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
134*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
135*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
136*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
137*12720SWyllys.Ingersoll@Sun.COM 
138*12720SWyllys.Ingersoll@Sun.COM 	if (pMechanism == NULL) {
139*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
140*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
141*12720SWyllys.Ingersoll@Sun.COM 	}
142*12720SWyllys.Ingersoll@Sun.COM 
143*12720SWyllys.Ingersoll@Sun.COM 	if (pMechanism->mechanism != CKM_AES_CBC &&
144*12720SWyllys.Ingersoll@Sun.COM 	    pMechanism->mechanism != CKM_AES_CBC_PAD)
145*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_MECHANISM_INVALID);
146*12720SWyllys.Ingersoll@Sun.COM 
147*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the object pointer. */
148*12720SWyllys.Ingersoll@Sun.COM 	HANDLE2OBJECT(hKey, key_p, rv);
149*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
150*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
151*12720SWyllys.Ingersoll@Sun.COM 
152*12720SWyllys.Ingersoll@Sun.COM 	/* Check to see if key object allows for encryption. */
153*12720SWyllys.Ingersoll@Sun.COM 	if (!(key_p->bool_attr_mask & ENCRYPT_BOOL_ON)) {
154*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_KEY_FUNCTION_NOT_PERMITTED;
155*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit1;
156*12720SWyllys.Ingersoll@Sun.COM 	}
157*12720SWyllys.Ingersoll@Sun.COM 
158*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
159*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
160*12720SWyllys.Ingersoll@Sun.COM 
161*12720SWyllys.Ingersoll@Sun.COM 	/* Check to see if encrypt operation is already active. */
162*12720SWyllys.Ingersoll@Sun.COM 	if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
163*12720SWyllys.Ingersoll@Sun.COM 		/* free the memory to avoid memory leak */
164*12720SWyllys.Ingersoll@Sun.COM 		kms_crypt_cleanup(session_p, B_TRUE, lock_held);
165*12720SWyllys.Ingersoll@Sun.COM 	}
166*12720SWyllys.Ingersoll@Sun.COM 
167*12720SWyllys.Ingersoll@Sun.COM 	/*
168*12720SWyllys.Ingersoll@Sun.COM 	 * This active flag will remain ON until application calls either
169*12720SWyllys.Ingersoll@Sun.COM 	 * C_Encrypt or C_EncryptFinal to actually obtain the final piece
170*12720SWyllys.Ingersoll@Sun.COM 	 * of ciphertext.
171*12720SWyllys.Ingersoll@Sun.COM 	 */
172*12720SWyllys.Ingersoll@Sun.COM 	session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
173*12720SWyllys.Ingersoll@Sun.COM 
174*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
175*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
176*12720SWyllys.Ingersoll@Sun.COM 
177*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_encrypt_init(session_p, pMechanism, key_p);
178*12720SWyllys.Ingersoll@Sun.COM 
179*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK) {
180*12720SWyllys.Ingersoll@Sun.COM 		(void) pthread_mutex_lock(&session_p->session_mutex);
181*12720SWyllys.Ingersoll@Sun.COM 		session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
182*12720SWyllys.Ingersoll@Sun.COM 		lock_held = B_TRUE;
183*12720SWyllys.Ingersoll@Sun.COM 	}
184*12720SWyllys.Ingersoll@Sun.COM 
185*12720SWyllys.Ingersoll@Sun.COM clean_exit1:
186*12720SWyllys.Ingersoll@Sun.COM 	OBJ_REFRELE(key_p);
187*12720SWyllys.Ingersoll@Sun.COM clean_exit:
188*12720SWyllys.Ingersoll@Sun.COM 	REFRELE(session_p, lock_held);
189*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
190*12720SWyllys.Ingersoll@Sun.COM }
191*12720SWyllys.Ingersoll@Sun.COM 
192*12720SWyllys.Ingersoll@Sun.COM 
193*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)194*12720SWyllys.Ingersoll@Sun.COM C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
195*12720SWyllys.Ingersoll@Sun.COM     CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
196*12720SWyllys.Ingersoll@Sun.COM {
197*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
198*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
199*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
200*12720SWyllys.Ingersoll@Sun.COM 
201*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
202*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
203*12720SWyllys.Ingersoll@Sun.COM 
204*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
205*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
206*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
207*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
208*12720SWyllys.Ingersoll@Sun.COM 
209*12720SWyllys.Ingersoll@Sun.COM 	/*
210*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if input buffer is null.  How to handle zero input
211*12720SWyllys.Ingersoll@Sun.COM 	 * length depends on the mechanism in use.  For secret key mechanisms,
212*12720SWyllys.Ingersoll@Sun.COM 	 * unpadded ones yield zero length output, but padded ones always
213*12720SWyllys.Ingersoll@Sun.COM 	 * result in greater than zero length output.
214*12720SWyllys.Ingersoll@Sun.COM 	 */
215*12720SWyllys.Ingersoll@Sun.COM 	if (pData == NULL) {
216*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
217*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
218*12720SWyllys.Ingersoll@Sun.COM 	}
219*12720SWyllys.Ingersoll@Sun.COM 
220*12720SWyllys.Ingersoll@Sun.COM 	/*
221*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if pulEncryptedDataLen is NULL.
222*12720SWyllys.Ingersoll@Sun.COM 	 * No need to check if pEncryptedData is NULL because
223*12720SWyllys.Ingersoll@Sun.COM 	 * application might just ask for the length of buffer to hold
224*12720SWyllys.Ingersoll@Sun.COM 	 * the ciphertext.
225*12720SWyllys.Ingersoll@Sun.COM 	 */
226*12720SWyllys.Ingersoll@Sun.COM 	if (pulEncryptedDataLen == NULL) {
227*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
228*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
229*12720SWyllys.Ingersoll@Sun.COM 	}
230*12720SWyllys.Ingersoll@Sun.COM 
231*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
232*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
233*12720SWyllys.Ingersoll@Sun.COM 
234*12720SWyllys.Ingersoll@Sun.COM 	/* Application must call C_EncryptInit before calling C_Encrypt. */
235*12720SWyllys.Ingersoll@Sun.COM 	if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
236*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
237*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_OPERATION_NOT_INITIALIZED);
238*12720SWyllys.Ingersoll@Sun.COM 	}
239*12720SWyllys.Ingersoll@Sun.COM 
240*12720SWyllys.Ingersoll@Sun.COM 	/*
241*12720SWyllys.Ingersoll@Sun.COM 	 * C_Encrypt must be called without intervening C_EncryptUpdate
242*12720SWyllys.Ingersoll@Sun.COM 	 * calls.
243*12720SWyllys.Ingersoll@Sun.COM 	 */
244*12720SWyllys.Ingersoll@Sun.COM 	if (session_p->encrypt.flags & CRYPTO_OPERATION_UPDATE) {
245*12720SWyllys.Ingersoll@Sun.COM 		/*
246*12720SWyllys.Ingersoll@Sun.COM 		 * C_Encrypt can not be used to terminate a multi-part
247*12720SWyllys.Ingersoll@Sun.COM 		 * operation, so we'll leave the active encrypt operation
248*12720SWyllys.Ingersoll@Sun.COM 		 * flag on and let the application continue with the
249*12720SWyllys.Ingersoll@Sun.COM 		 * encrypt update operation.
250*12720SWyllys.Ingersoll@Sun.COM 		 */
251*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
252*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_FUNCTION_FAILED);
253*12720SWyllys.Ingersoll@Sun.COM 	}
254*12720SWyllys.Ingersoll@Sun.COM 
255*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
256*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
257*12720SWyllys.Ingersoll@Sun.COM 
258*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_encrypt_common(session_p, pData, ulDataLen, pEncryptedData,
259*12720SWyllys.Ingersoll@Sun.COM 	    pulEncryptedDataLen, 0);
260*12720SWyllys.Ingersoll@Sun.COM 
261*12720SWyllys.Ingersoll@Sun.COM 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
262*12720SWyllys.Ingersoll@Sun.COM 	    (pEncryptedData == NULL && rv == CKR_OK)) {
263*12720SWyllys.Ingersoll@Sun.COM 		/*
264*12720SWyllys.Ingersoll@Sun.COM 		 * We will not terminate the active encrypt operation flag,
265*12720SWyllys.Ingersoll@Sun.COM 		 * when the application-supplied buffer is too small, or
266*12720SWyllys.Ingersoll@Sun.COM 		 * the application asks for the length of buffer to hold
267*12720SWyllys.Ingersoll@Sun.COM 		 * the ciphertext.
268*12720SWyllys.Ingersoll@Sun.COM 		 */
269*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
270*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
271*12720SWyllys.Ingersoll@Sun.COM 	}
272*12720SWyllys.Ingersoll@Sun.COM 
273*12720SWyllys.Ingersoll@Sun.COM clean_exit:
274*12720SWyllys.Ingersoll@Sun.COM 	/* Clear context, free key, and release session counter */
275*12720SWyllys.Ingersoll@Sun.COM 	kms_crypt_cleanup(session_p, B_TRUE, B_FALSE);
276*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
277*12720SWyllys.Ingersoll@Sun.COM }
278*12720SWyllys.Ingersoll@Sun.COM 
279*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_EncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)280*12720SWyllys.Ingersoll@Sun.COM C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
281*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
282*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG_PTR pulEncryptedPartLen)
283*12720SWyllys.Ingersoll@Sun.COM {
284*12720SWyllys.Ingersoll@Sun.COM 
285*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
286*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
287*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
288*12720SWyllys.Ingersoll@Sun.COM 
289*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
290*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
291*12720SWyllys.Ingersoll@Sun.COM 
292*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
293*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
294*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
295*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
296*12720SWyllys.Ingersoll@Sun.COM 
297*12720SWyllys.Ingersoll@Sun.COM 	/*
298*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if input buffer is null.  How to handle zero input
299*12720SWyllys.Ingersoll@Sun.COM 	 * length depends on the mechanism in use.  For secret key mechanisms,
300*12720SWyllys.Ingersoll@Sun.COM 	 * unpadded ones yeild zero length output, but padded ones always
301*12720SWyllys.Ingersoll@Sun.COM 	 * result in greater than zero length output.
302*12720SWyllys.Ingersoll@Sun.COM 	 */
303*12720SWyllys.Ingersoll@Sun.COM 	if (pPart == NULL) {
304*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
305*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
306*12720SWyllys.Ingersoll@Sun.COM 	}
307*12720SWyllys.Ingersoll@Sun.COM 
308*12720SWyllys.Ingersoll@Sun.COM 	/*
309*12720SWyllys.Ingersoll@Sun.COM 	 * Only check if pulEncryptedPartLen is NULL.
310*12720SWyllys.Ingersoll@Sun.COM 	 * No need to check if pEncryptedPart is NULL because
311*12720SWyllys.Ingersoll@Sun.COM 	 * application might just ask for the length of buffer to hold
312*12720SWyllys.Ingersoll@Sun.COM 	 * the ciphertext.
313*12720SWyllys.Ingersoll@Sun.COM 	 */
314*12720SWyllys.Ingersoll@Sun.COM 	if (pulEncryptedPartLen == NULL) {
315*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
316*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
317*12720SWyllys.Ingersoll@Sun.COM 	}
318*12720SWyllys.Ingersoll@Sun.COM 
319*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
320*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
321*12720SWyllys.Ingersoll@Sun.COM 
322*12720SWyllys.Ingersoll@Sun.COM 	/*
323*12720SWyllys.Ingersoll@Sun.COM 	 * Application must call C_EncryptInit before calling
324*12720SWyllys.Ingersoll@Sun.COM 	 * C_EncryptUpdate.
325*12720SWyllys.Ingersoll@Sun.COM 	 */
326*12720SWyllys.Ingersoll@Sun.COM 	if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
327*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
328*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_OPERATION_NOT_INITIALIZED);
329*12720SWyllys.Ingersoll@Sun.COM 	}
330*12720SWyllys.Ingersoll@Sun.COM 
331*12720SWyllys.Ingersoll@Sun.COM 	session_p->encrypt.flags |= CRYPTO_OPERATION_UPDATE;
332*12720SWyllys.Ingersoll@Sun.COM 
333*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
334*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
335*12720SWyllys.Ingersoll@Sun.COM 
336*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_encrypt_common(session_p, pPart, ulPartLen,
337*12720SWyllys.Ingersoll@Sun.COM 	    pEncryptedPart, pulEncryptedPartLen, B_TRUE);
338*12720SWyllys.Ingersoll@Sun.COM 
339*12720SWyllys.Ingersoll@Sun.COM 	/*
340*12720SWyllys.Ingersoll@Sun.COM 	 * If CKR_OK or CKR_BUFFER_TOO_SMALL, don't terminate the
341*12720SWyllys.Ingersoll@Sun.COM 	 * current encryption operation.
342*12720SWyllys.Ingersoll@Sun.COM 	 */
343*12720SWyllys.Ingersoll@Sun.COM 	if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL)) {
344*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
345*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
346*12720SWyllys.Ingersoll@Sun.COM 	}
347*12720SWyllys.Ingersoll@Sun.COM 
348*12720SWyllys.Ingersoll@Sun.COM clean_exit:
349*12720SWyllys.Ingersoll@Sun.COM 	/*
350*12720SWyllys.Ingersoll@Sun.COM 	 * After an error occurred, terminate the current encrypt
351*12720SWyllys.Ingersoll@Sun.COM 	 * operation by resetting the active and update flags.
352*12720SWyllys.Ingersoll@Sun.COM 	 */
353*12720SWyllys.Ingersoll@Sun.COM 	kms_crypt_cleanup(session_p, B_TRUE, lock_held);
354*12720SWyllys.Ingersoll@Sun.COM 
355*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
356*12720SWyllys.Ingersoll@Sun.COM }
357*12720SWyllys.Ingersoll@Sun.COM 
358*12720SWyllys.Ingersoll@Sun.COM 
359*12720SWyllys.Ingersoll@Sun.COM CK_RV
C_EncryptFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pLastEncryptedPart,CK_ULONG_PTR pulLastEncryptedPartLen)360*12720SWyllys.Ingersoll@Sun.COM C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart,
361*12720SWyllys.Ingersoll@Sun.COM     CK_ULONG_PTR pulLastEncryptedPartLen)
362*12720SWyllys.Ingersoll@Sun.COM {
363*12720SWyllys.Ingersoll@Sun.COM 
364*12720SWyllys.Ingersoll@Sun.COM 	CK_RV		rv;
365*12720SWyllys.Ingersoll@Sun.COM 	kms_session_t	*session_p;
366*12720SWyllys.Ingersoll@Sun.COM 	boolean_t	lock_held = B_FALSE;
367*12720SWyllys.Ingersoll@Sun.COM 
368*12720SWyllys.Ingersoll@Sun.COM 	if (!kms_initialized)
369*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
370*12720SWyllys.Ingersoll@Sun.COM 
371*12720SWyllys.Ingersoll@Sun.COM 	/* Obtain the session pointer. */
372*12720SWyllys.Ingersoll@Sun.COM 	rv = handle2session(hSession, &session_p);
373*12720SWyllys.Ingersoll@Sun.COM 	if (rv != CKR_OK)
374*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
375*12720SWyllys.Ingersoll@Sun.COM 
376*12720SWyllys.Ingersoll@Sun.COM 	if (pulLastEncryptedPartLen == NULL) {
377*12720SWyllys.Ingersoll@Sun.COM 		rv = CKR_ARGUMENTS_BAD;
378*12720SWyllys.Ingersoll@Sun.COM 		goto clean_exit;
379*12720SWyllys.Ingersoll@Sun.COM 	}
380*12720SWyllys.Ingersoll@Sun.COM 
381*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
382*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
383*12720SWyllys.Ingersoll@Sun.COM 
384*12720SWyllys.Ingersoll@Sun.COM 	/*
385*12720SWyllys.Ingersoll@Sun.COM 	 * Application must call C_EncryptInit before calling
386*12720SWyllys.Ingersoll@Sun.COM 	 * C_EncryptFinal.
387*12720SWyllys.Ingersoll@Sun.COM 	 */
388*12720SWyllys.Ingersoll@Sun.COM 	if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
389*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
390*12720SWyllys.Ingersoll@Sun.COM 		return (CKR_OPERATION_NOT_INITIALIZED);
391*12720SWyllys.Ingersoll@Sun.COM 	}
392*12720SWyllys.Ingersoll@Sun.COM 
393*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_unlock(&session_p->session_mutex);
394*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_FALSE;
395*12720SWyllys.Ingersoll@Sun.COM 
396*12720SWyllys.Ingersoll@Sun.COM 	rv = kms_aes_encrypt_final(session_p, pLastEncryptedPart,
397*12720SWyllys.Ingersoll@Sun.COM 	    pulLastEncryptedPartLen);
398*12720SWyllys.Ingersoll@Sun.COM 
399*12720SWyllys.Ingersoll@Sun.COM 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
400*12720SWyllys.Ingersoll@Sun.COM 	    (pLastEncryptedPart == NULL && rv == CKR_OK)) {
401*12720SWyllys.Ingersoll@Sun.COM 		/*
402*12720SWyllys.Ingersoll@Sun.COM 		 * We will not terminate the active encrypt operation flag,
403*12720SWyllys.Ingersoll@Sun.COM 		 * when the application-supplied buffer is too small, or
404*12720SWyllys.Ingersoll@Sun.COM 		 * the application asks for the length of buffer to hold
405*12720SWyllys.Ingersoll@Sun.COM 		 * the ciphertext.
406*12720SWyllys.Ingersoll@Sun.COM 		 */
407*12720SWyllys.Ingersoll@Sun.COM 		REFRELE(session_p, lock_held);
408*12720SWyllys.Ingersoll@Sun.COM 		return (rv);
409*12720SWyllys.Ingersoll@Sun.COM 	}
410*12720SWyllys.Ingersoll@Sun.COM 
411*12720SWyllys.Ingersoll@Sun.COM 	/* Terminates the active encrypt operation. */
412*12720SWyllys.Ingersoll@Sun.COM 	(void) pthread_mutex_lock(&session_p->session_mutex);
413*12720SWyllys.Ingersoll@Sun.COM 	session_p->encrypt.flags = 0;
414*12720SWyllys.Ingersoll@Sun.COM 	lock_held = B_TRUE;
415*12720SWyllys.Ingersoll@Sun.COM 	REFRELE(session_p, lock_held);
416*12720SWyllys.Ingersoll@Sun.COM 
417*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
418*12720SWyllys.Ingersoll@Sun.COM 
419*12720SWyllys.Ingersoll@Sun.COM clean_exit:
420*12720SWyllys.Ingersoll@Sun.COM 	/* Terminates the active encrypt operation. */
421*12720SWyllys.Ingersoll@Sun.COM 	kms_crypt_cleanup(session_p, B_TRUE, lock_held);
422*12720SWyllys.Ingersoll@Sun.COM 
423*12720SWyllys.Ingersoll@Sun.COM 	return (rv);
424*12720SWyllys.Ingersoll@Sun.COM }
425