4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/crypto/ioctl.h>
30 #include <security/cryptoki.h>
31 #include "kernelGlobal.h"
32 #include "kernelSession.h"
33 #include "kernelObject.h"
37 * Real decryptInit work. The caller doesn't hold the session lock.
40 kernel_decrypt_init(kernel_session_t
*session_p
, kernel_object_t
*key_p
,
41 CK_MECHANISM_PTR pMechanism
)
44 crypto_decrypt_init_t decrypt_init
;
45 crypto_mech_type_t k_mech_type
;
46 boolean_t ses_lock_held
= B_FALSE
;
49 /* Check to see if key object allows for decryption. */
50 if (key_p
->is_lib_obj
&& !(key_p
->bool_attr_mask
& DECRYPT_BOOL_ON
)) {
51 return (CKR_KEY_TYPE_INCONSISTENT
);
54 /* Get the kernel's internal mechanism number. */
55 rv
= kernel_mech(pMechanism
->mechanism
, &k_mech_type
);
59 (void) pthread_mutex_lock(&session_p
->session_mutex
);
60 ses_lock_held
= B_TRUE
;
63 * This active flag will remain ON until application calls either
64 * C_Decrypt or C_DecryptFinal to actually obtain the final piece
67 session_p
->decrypt
.flags
= CRYPTO_OPERATION_ACTIVE
;
70 if (!key_p
->is_lib_obj
) {
71 decrypt_init
.di_key
.ck_format
= CRYPTO_KEY_REFERENCE
;
72 decrypt_init
.di_key
.ck_obj_id
= key_p
->k_handle
;
74 if (key_p
->class == CKO_SECRET_KEY
) {
75 decrypt_init
.di_key
.ck_format
= CRYPTO_KEY_RAW
;
76 decrypt_init
.di_key
.ck_data
=
77 get_symmetric_key_value(key_p
);
78 if (decrypt_init
.di_key
.ck_data
== NULL
) {
82 /* KEF key lengths are expressed in bits */
83 decrypt_init
.di_key
.ck_length
=
84 OBJ_SEC(key_p
)->sk_value_len
<< 3;
86 } else if (key_p
->key_type
== CKK_RSA
) {
87 if (get_rsa_private_key(key_p
, &decrypt_init
.di_key
) !=
93 rv
= CKR_KEY_TYPE_INCONSISTENT
;
98 decrypt_init
.di_session
= session_p
->k_session
;
99 session_p
->decrypt
.mech
= *pMechanism
;
101 /* Cache this capability value for efficiency */
102 if (INPLACE_MECHANISM(session_p
->decrypt
.mech
.mechanism
)) {
103 session_p
->decrypt
.flags
|= CRYPTO_OPERATION_INPLACE_OK
;
105 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
107 ses_lock_held
= B_FALSE
;
108 decrypt_init
.di_mech
.cm_type
= k_mech_type
;
109 decrypt_init
.di_mech
.cm_param
= pMechanism
->pParameter
;
110 decrypt_init
.di_mech
.cm_param_len
= pMechanism
->ulParameterLen
;
112 while ((r
= ioctl(kernel_fd
, CRYPTO_DECRYPT_INIT
, &decrypt_init
)) < 0) {
117 rv
= CKR_FUNCTION_FAILED
;
119 rv
= crypto2pkcs11_error_number(decrypt_init
.di_return_value
);
122 /* Free memory allocated for decrypt_init.di_key */
123 if (key_p
->is_lib_obj
) {
124 if (key_p
->class == CKO_SECRET_KEY
) {
125 free(decrypt_init
.di_key
.ck_data
);
126 } else if (key_p
->key_type
== CKK_RSA
) {
127 free_key_attributes(&decrypt_init
.di_key
);
133 if (!ses_lock_held
) {
134 (void) pthread_mutex_lock(&session_p
->session_mutex
);
135 ses_lock_held
= B_TRUE
;
139 session_p
->decrypt
.flags
&= ~CRYPTO_OPERATION_ACTIVE
;
142 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
143 ses_lock_held
= B_FALSE
;
150 C_DecryptInit(CK_SESSION_HANDLE hSession
, CK_MECHANISM_PTR pMechanism
,
151 CK_OBJECT_HANDLE hKey
)
155 kernel_session_t
*session_p
;
156 kernel_object_t
*key_p
;
157 boolean_t ses_lock_held
= B_FALSE
;
159 if (!kernel_initialized
)
160 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
162 if (pMechanism
== NULL
) {
163 return (CKR_ARGUMENTS_BAD
);
166 /* Obtain the session pointer. */
167 rv
= handle2session(hSession
, &session_p
);
171 /* Obtain the object pointer. */
172 HANDLE2OBJECT(hKey
, key_p
, rv
);
174 rv
= kernel_decrypt_init(session_p
, key_p
, pMechanism
);
178 REFRELE(session_p
, ses_lock_held
);
185 * Real decrypt work. The caller doesn't hold the session lock.
188 kernel_decrypt(kernel_session_t
*session_p
, CK_BYTE_PTR pEncryptedData
,
189 CK_ULONG ulEncryptedData
, CK_BYTE_PTR pData
, CK_ULONG_PTR pulDataLen
)
191 crypto_decrypt_t decrypt
;
192 boolean_t ses_lock_held
= B_FALSE
;
197 (void) pthread_mutex_lock(&session_p
->session_mutex
);
198 ses_lock_held
= B_TRUE
;
200 /* Application must call C_DecryptInit before calling C_Decrypt. */
201 if (!(session_p
->decrypt
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
202 rv
= CKR_OPERATION_NOT_INITIALIZED
;
207 * C_Decrypt must be called without intervening C_DecryptUpdate
210 if (session_p
->decrypt
.flags
& CRYPTO_OPERATION_UPDATE
) {
212 * C_Decrypt cannot be used to terminate a multiple-part
213 * operation, so we'll leave the active decrypt operation
214 * flag on and let the application continue with the
215 * decrypt update operation.
217 rv
= CKR_FUNCTION_FAILED
;
221 decrypt
.cd_session
= session_p
->k_session
;
224 * Certain mechanisms, where the length of the plaintext is
225 * same as the transformed ciphertext, can be optimized
226 * by the kernel into an in-place operation. Unfortunately,
227 * some applications use a plaintext buffer that is larger
228 * than it needs to be. We fix that here.
230 inplace
= (session_p
->decrypt
.flags
& CRYPTO_OPERATION_INPLACE_OK
) != 0;
232 if (ulEncryptedData
< *pulDataLen
&& inplace
) {
233 decrypt
.cd_datalen
= ulEncryptedData
;
235 decrypt
.cd_datalen
= *pulDataLen
;
237 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
238 ses_lock_held
= B_FALSE
;
240 decrypt
.cd_databuf
= (char *)pData
;
241 decrypt
.cd_encrlen
= ulEncryptedData
;
242 decrypt
.cd_encrbuf
= (char *)pEncryptedData
;
244 ((inplace
&& (pData
!= NULL
)) || (pData
== pEncryptedData
)) &&
245 (decrypt
.cd_datalen
== decrypt
.cd_encrlen
) ?
246 CRYPTO_INPLACE_OPERATION
: 0;
248 while ((r
= ioctl(kernel_fd
, CRYPTO_DECRYPT
, &decrypt
)) < 0) {
253 rv
= CKR_FUNCTION_FAILED
;
255 rv
= crypto2pkcs11_error_number(decrypt
.cd_return_value
);
258 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
259 *pulDataLen
= decrypt
.cd_datalen
;
264 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
270 C_Decrypt(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pEncryptedData
,
271 CK_ULONG ulEncryptedData
, CK_BYTE_PTR pData
, CK_ULONG_PTR pulDataLen
)
274 kernel_session_t
*session_p
;
275 boolean_t ses_lock_held
= B_FALSE
;
277 if (!kernel_initialized
)
278 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
280 /* Obtain the session pointer. */
281 rv
= handle2session(hSession
, &session_p
);
286 * No need to check pData because application might
287 * just want to know the length of decrypted data.
289 if (pulDataLen
== NULL
) {
290 rv
= CKR_ARGUMENTS_BAD
;
294 rv
= kernel_decrypt(session_p
, pEncryptedData
, ulEncryptedData
, pData
,
297 if ((rv
== CKR_BUFFER_TOO_SMALL
) ||
298 (rv
== CKR_OK
&& pData
== NULL
)) {
300 * We will not terminate the active decrypt operation flag,
301 * when the application-supplied buffer is too small, or
302 * the application asks for the length of buffer to hold
305 REFRELE(session_p
, ses_lock_held
);
311 * Terminates the active decrypt operation.
312 * Application needs to call C_DecryptInit again for next
315 (void) pthread_mutex_lock(&session_p
->session_mutex
);
316 session_p
->decrypt
.flags
= 0;
317 ses_lock_held
= B_TRUE
;
318 REFRELE(session_p
, ses_lock_held
);
325 C_DecryptUpdate(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pEncryptedPart
,
326 CK_ULONG ulEncryptedPartLen
, CK_BYTE_PTR pPart
,
327 CK_ULONG_PTR pulPartLen
)
331 kernel_session_t
*session_p
;
332 boolean_t ses_lock_held
= B_FALSE
;
334 crypto_decrypt_update_t decrypt_update
;
337 if (!kernel_initialized
)
338 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
340 /* Obtain the session pointer. */
341 rv
= handle2session(hSession
, &session_p
);
345 if (pEncryptedPart
== NULL
) {
346 rv
= CKR_ARGUMENTS_BAD
;
351 * Only check if pulPartLen is NULL.
352 * No need to check if pPart is NULL because application
353 * might just ask for the length of buffer to hold the
356 if (pulPartLen
== NULL
) {
357 rv
= CKR_ARGUMENTS_BAD
;
361 (void) pthread_mutex_lock(&session_p
->session_mutex
);
362 ses_lock_held
= B_TRUE
;
365 * Application must call C_DecryptInit before calling
368 if (!(session_p
->decrypt
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
369 REFRELE(session_p
, ses_lock_held
);
370 return (CKR_OPERATION_NOT_INITIALIZED
);
373 session_p
->decrypt
.flags
|= CRYPTO_OPERATION_UPDATE
;
375 decrypt_update
.du_session
= session_p
->k_session
;
376 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
377 ses_lock_held
= B_FALSE
;
379 decrypt_update
.du_datalen
= *pulPartLen
;
380 decrypt_update
.du_databuf
= (char *)pPart
;
381 decrypt_update
.du_encrlen
= ulEncryptedPartLen
;
382 decrypt_update
.du_encrbuf
= (char *)pEncryptedPart
;
384 inplace
= (session_p
->decrypt
.flags
& CRYPTO_OPERATION_INPLACE_OK
) != 0;
385 decrypt_update
.du_flags
=
386 ((inplace
&& (pPart
!= NULL
)) || (pPart
== pEncryptedPart
)) &&
387 (decrypt_update
.du_datalen
== decrypt_update
.du_encrlen
) ?
388 CRYPTO_INPLACE_OPERATION
: 0;
390 while ((r
= ioctl(kernel_fd
, CRYPTO_DECRYPT_UPDATE
,
391 &decrypt_update
)) < 0) {
396 rv
= CKR_FUNCTION_FAILED
;
398 rv
= crypto2pkcs11_error_number(
399 decrypt_update
.du_return_value
);
403 * If CKR_OK or CKR_BUFFER_TOO_SMALL, set the output length.
404 * We don't terminate the current decryption operation.
406 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
) {
407 *pulPartLen
= decrypt_update
.du_datalen
;
408 REFRELE(session_p
, ses_lock_held
);
414 * After an error occurred, terminate the current decrypt
415 * operation by resetting the active and update flags.
417 (void) pthread_mutex_lock(&session_p
->session_mutex
);
418 session_p
->decrypt
.flags
= 0;
419 ses_lock_held
= B_TRUE
;
420 REFRELE(session_p
, ses_lock_held
);
427 C_DecryptFinal(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pLastPart
,
428 CK_ULONG_PTR pulLastPartLen
)
432 kernel_session_t
*session_p
;
433 boolean_t ses_lock_held
= B_FALSE
;
434 crypto_decrypt_final_t decrypt_final
;
437 if (!kernel_initialized
)
438 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
440 /* Obtain the session pointer. */
441 rv
= handle2session(hSession
, &session_p
);
445 if (pulLastPartLen
== NULL
) {
446 rv
= CKR_ARGUMENTS_BAD
;
450 (void) pthread_mutex_lock(&session_p
->session_mutex
);
451 ses_lock_held
= B_TRUE
;
454 * Application must call C_DecryptInit before calling
457 if (!(session_p
->decrypt
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
458 REFRELE(session_p
, ses_lock_held
);
459 return (CKR_OPERATION_NOT_INITIALIZED
);
462 decrypt_final
.df_session
= session_p
->k_session
;
463 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
464 ses_lock_held
= B_FALSE
;
466 decrypt_final
.df_datalen
= *pulLastPartLen
;
467 decrypt_final
.df_databuf
= (char *)pLastPart
;
469 while ((r
= ioctl(kernel_fd
, CRYPTO_DECRYPT_FINAL
,
470 &decrypt_final
)) < 0) {
475 rv
= CKR_FUNCTION_FAILED
;
477 rv
= crypto2pkcs11_error_number(decrypt_final
.df_return_value
);
480 if (rv
== CKR_OK
|| rv
== CKR_BUFFER_TOO_SMALL
)
481 *pulLastPartLen
= decrypt_final
.df_datalen
;
483 if (rv
== CKR_BUFFER_TOO_SMALL
||
484 (rv
== CKR_OK
&& pLastPart
== NULL
)) {
486 * We will not terminate the active decrypt operation flag,
487 * when the application-supplied buffer is too small, or
488 * the application asks for the length of buffer to hold
491 REFRELE(session_p
, ses_lock_held
);
496 /* Terminates the active decrypt operation */
497 (void) pthread_mutex_lock(&session_p
->session_mutex
);
498 session_p
->decrypt
.flags
= 0;
499 ses_lock_held
= B_TRUE
;
500 REFRELE(session_p
, ses_lock_held
);