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