10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52786Sdinak * Common Development and Distribution License (the "License").
62786Sdinak * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*9341SAnthony.Scarpino@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <pthread.h>
270Sstevel@tonic-gate #include <security/cryptoki.h>
280Sstevel@tonic-gate #include "softGlobal.h"
290Sstevel@tonic-gate #include "softSession.h"
300Sstevel@tonic-gate #include "softObject.h"
310Sstevel@tonic-gate #include "softOps.h"
320Sstevel@tonic-gate
330Sstevel@tonic-gate
340Sstevel@tonic-gate CK_RV
C_EncryptInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)350Sstevel@tonic-gate C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
360Sstevel@tonic-gate CK_OBJECT_HANDLE hKey)
370Sstevel@tonic-gate {
380Sstevel@tonic-gate
390Sstevel@tonic-gate CK_RV rv;
400Sstevel@tonic-gate soft_session_t *session_p;
410Sstevel@tonic-gate soft_object_t *key_p;
420Sstevel@tonic-gate boolean_t lock_held = B_FALSE;
430Sstevel@tonic-gate
440Sstevel@tonic-gate if (!softtoken_initialized)
450Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
460Sstevel@tonic-gate
470Sstevel@tonic-gate /* Obtain the session pointer. */
480Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
490Sstevel@tonic-gate if (rv != CKR_OK)
500Sstevel@tonic-gate return (rv);
510Sstevel@tonic-gate
520Sstevel@tonic-gate if (pMechanism == NULL) {
530Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
540Sstevel@tonic-gate goto clean_exit;
550Sstevel@tonic-gate }
560Sstevel@tonic-gate
570Sstevel@tonic-gate /* Obtain the object pointer. */
580Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv);
590Sstevel@tonic-gate if (rv != CKR_OK)
600Sstevel@tonic-gate goto clean_exit;
610Sstevel@tonic-gate
620Sstevel@tonic-gate /* Check to see if key object allows for encryption. */
630Sstevel@tonic-gate if (!(key_p->bool_attr_mask & ENCRYPT_BOOL_ON)) {
64*9341SAnthony.Scarpino@Sun.COM rv = CKR_KEY_FUNCTION_NOT_PERMITTED;
650Sstevel@tonic-gate goto clean_exit1;
660Sstevel@tonic-gate }
670Sstevel@tonic-gate
680Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
690Sstevel@tonic-gate lock_held = B_TRUE;
700Sstevel@tonic-gate
710Sstevel@tonic-gate /* Check to see if encrypt operation is already active. */
720Sstevel@tonic-gate if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
730Sstevel@tonic-gate /* free the memory to avoid memory leak */
740Sstevel@tonic-gate soft_crypt_cleanup(session_p, B_TRUE, lock_held);
750Sstevel@tonic-gate }
760Sstevel@tonic-gate
770Sstevel@tonic-gate /*
780Sstevel@tonic-gate * This active flag will remain ON until application calls either
790Sstevel@tonic-gate * C_Encrypt or C_EncryptFinal to actually obtain the final piece
800Sstevel@tonic-gate * of ciphertext.
810Sstevel@tonic-gate */
820Sstevel@tonic-gate session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
830Sstevel@tonic-gate
840Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
850Sstevel@tonic-gate lock_held = B_FALSE;
860Sstevel@tonic-gate
870Sstevel@tonic-gate rv = soft_encrypt_init(session_p, pMechanism, key_p);
880Sstevel@tonic-gate
890Sstevel@tonic-gate if (rv != CKR_OK) {
900Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
910Sstevel@tonic-gate session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
920Sstevel@tonic-gate lock_held = B_TRUE;
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
950Sstevel@tonic-gate clean_exit1:
960Sstevel@tonic-gate OBJ_REFRELE(key_p);
970Sstevel@tonic-gate clean_exit:
980Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
990Sstevel@tonic-gate return (rv);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate CK_RV
C_Encrypt(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)1040Sstevel@tonic-gate C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
1050Sstevel@tonic-gate CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate CK_RV rv;
1090Sstevel@tonic-gate soft_session_t *session_p;
1100Sstevel@tonic-gate boolean_t lock_held = B_FALSE;
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate if (!softtoken_initialized)
1130Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /* Obtain the session pointer. */
1160Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
1170Sstevel@tonic-gate if (rv != CKR_OK)
1180Sstevel@tonic-gate return (rv);
1190Sstevel@tonic-gate
1202786Sdinak /*
1212786Sdinak * Only check if input buffer is null. How to handle zero input
1222786Sdinak * length depends on the mechanism in use. For secret key mechanisms,
1232786Sdinak * unpadded ones yield zero length output, but padded ones always
1242786Sdinak * result in greater than zero length output.
1252786Sdinak */
1260Sstevel@tonic-gate if (pData == NULL) {
1270Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
1280Sstevel@tonic-gate goto clean_exit;
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /*
1320Sstevel@tonic-gate * Only check if pulEncryptedDataLen is NULL.
1330Sstevel@tonic-gate * No need to check if pEncryptedData is NULL because
1340Sstevel@tonic-gate * application might just ask for the length of buffer to hold
1350Sstevel@tonic-gate * the ciphertext.
1360Sstevel@tonic-gate */
1370Sstevel@tonic-gate if (pulEncryptedDataLen == NULL) {
1380Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
1390Sstevel@tonic-gate goto clean_exit;
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
1430Sstevel@tonic-gate lock_held = B_TRUE;
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /* Application must call C_EncryptInit before calling C_Encrypt. */
1460Sstevel@tonic-gate if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
1470Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
1480Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate * C_Encrypt must be called without intervening C_EncryptUpdate
1530Sstevel@tonic-gate * calls.
1540Sstevel@tonic-gate */
1550Sstevel@tonic-gate if (session_p->encrypt.flags & CRYPTO_OPERATION_UPDATE) {
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate * C_Encrypt can not be used to terminate a multi-part
1580Sstevel@tonic-gate * operation, so we'll leave the active encrypt operation
1590Sstevel@tonic-gate * flag on and let the application continue with the
1600Sstevel@tonic-gate * encrypt update operation.
1610Sstevel@tonic-gate */
1620Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
1630Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
1670Sstevel@tonic-gate lock_held = B_FALSE;
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate rv = soft_encrypt(session_p, pData, ulDataLen, pEncryptedData,
1700Sstevel@tonic-gate pulEncryptedDataLen);
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) ||
1730Sstevel@tonic-gate (pEncryptedData == NULL && rv == CKR_OK)) {
1740Sstevel@tonic-gate /*
1750Sstevel@tonic-gate * We will not terminate the active encrypt operation flag,
1760Sstevel@tonic-gate * when the application-supplied buffer is too small, or
1770Sstevel@tonic-gate * the application asks for the length of buffer to hold
1780Sstevel@tonic-gate * the ciphertext.
1790Sstevel@tonic-gate */
1800Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
1810Sstevel@tonic-gate return (rv);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate clean_exit:
1852940Sizick /* Clear context, free key, and release session counter */
1862940Sizick soft_crypt_cleanup(session_p, B_TRUE, B_FALSE);
1870Sstevel@tonic-gate return (rv);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate CK_RV
C_EncryptUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)1920Sstevel@tonic-gate C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
1930Sstevel@tonic-gate CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
1940Sstevel@tonic-gate CK_ULONG_PTR pulEncryptedPartLen)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate CK_RV rv;
1980Sstevel@tonic-gate soft_session_t *session_p;
1990Sstevel@tonic-gate boolean_t lock_held = B_FALSE;
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate if (!softtoken_initialized)
2020Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /* Obtain the session pointer. */
2050Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
2060Sstevel@tonic-gate if (rv != CKR_OK)
2070Sstevel@tonic-gate return (rv);
2080Sstevel@tonic-gate
2092786Sdinak /*
2102786Sdinak * Only check if input buffer is null. How to handle zero input
2112786Sdinak * length depends on the mechanism in use. For secret key mechanisms,
2122786Sdinak * unpadded ones yeild zero length output, but padded ones always
2132786Sdinak * result in greater than zero length output.
2142786Sdinak */
2150Sstevel@tonic-gate if (pPart == NULL) {
2160Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
2170Sstevel@tonic-gate goto clean_exit;
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * Only check if pulEncryptedPartLen is NULL.
2220Sstevel@tonic-gate * No need to check if pEncryptedPart is NULL because
2230Sstevel@tonic-gate * application might just ask for the length of buffer to hold
2240Sstevel@tonic-gate * the ciphertext.
2250Sstevel@tonic-gate */
2260Sstevel@tonic-gate if (pulEncryptedPartLen == NULL) {
2270Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
2280Sstevel@tonic-gate goto clean_exit;
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
2320Sstevel@tonic-gate lock_held = B_TRUE;
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * Application must call C_EncryptInit before calling
2360Sstevel@tonic-gate * C_EncryptUpdate.
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
2390Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
2400Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate session_p->encrypt.flags |= CRYPTO_OPERATION_UPDATE;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
2460Sstevel@tonic-gate lock_held = B_FALSE;
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate rv = soft_encrypt_update(session_p, pPart, ulPartLen,
2490Sstevel@tonic-gate pEncryptedPart, pulEncryptedPartLen);
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate * If CKR_OK or CKR_BUFFER_TOO_SMALL, don't terminate the
2530Sstevel@tonic-gate * current encryption operation.
2540Sstevel@tonic-gate */
2550Sstevel@tonic-gate if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL)) {
2560Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
2570Sstevel@tonic-gate return (rv);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate clean_exit:
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * After an error occurred, terminate the current encrypt
2630Sstevel@tonic-gate * operation by resetting the active and update flags.
2640Sstevel@tonic-gate */
2650Sstevel@tonic-gate soft_crypt_cleanup(session_p, B_TRUE, lock_held);
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate return (rv);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate CK_RV
C_EncryptFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pLastEncryptedPart,CK_ULONG_PTR pulLastEncryptedPartLen)2720Sstevel@tonic-gate C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart,
2730Sstevel@tonic-gate CK_ULONG_PTR pulLastEncryptedPartLen)
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate CK_RV rv;
2770Sstevel@tonic-gate soft_session_t *session_p;
2780Sstevel@tonic-gate boolean_t lock_held = B_FALSE;
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate if (!softtoken_initialized)
2810Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate /* Obtain the session pointer. */
2840Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
2850Sstevel@tonic-gate if (rv != CKR_OK)
2860Sstevel@tonic-gate return (rv);
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate if (pulLastEncryptedPartLen == NULL) {
2890Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
2900Sstevel@tonic-gate goto clean_exit;
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
2940Sstevel@tonic-gate lock_held = B_TRUE;
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate * Application must call C_EncryptInit before calling
2980Sstevel@tonic-gate * C_EncryptFinal.
2990Sstevel@tonic-gate */
3000Sstevel@tonic-gate if (!(session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE)) {
3010Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
3020Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
3060Sstevel@tonic-gate lock_held = B_FALSE;
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate rv = soft_encrypt_final(session_p, pLastEncryptedPart,
3090Sstevel@tonic-gate pulLastEncryptedPartLen);
3100Sstevel@tonic-gate
3110Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) ||
3120Sstevel@tonic-gate (pLastEncryptedPart == NULL && rv == CKR_OK)) {
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate * We will not terminate the active encrypt operation flag,
3150Sstevel@tonic-gate * when the application-supplied buffer is too small, or
3160Sstevel@tonic-gate * the application asks for the length of buffer to hold
3170Sstevel@tonic-gate * the ciphertext.
3180Sstevel@tonic-gate */
3190Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
3200Sstevel@tonic-gate return (rv);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate /* Terminates the active encrypt operation. */
3240Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
3250Sstevel@tonic-gate session_p->encrypt.flags = 0;
3260Sstevel@tonic-gate lock_held = B_TRUE;
3270Sstevel@tonic-gate SES_REFRELE(session_p, lock_held);
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate return (rv);
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate clean_exit:
3320Sstevel@tonic-gate /* Terminates the active encrypt operation. */
3330Sstevel@tonic-gate soft_crypt_cleanup(session_p, B_TRUE, lock_held);
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate return (rv);
3360Sstevel@tonic-gate }
337