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