1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <pthread.h> 27 #include <security/cryptoki.h> 28 #include "softGlobal.h" 29 #include "softSession.h" 30 #include "softObject.h" 31 #include "softOps.h" 32 33 34 CK_RV 35 C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 36 CK_OBJECT_HANDLE hKey) 37 { 38 39 CK_RV rv; 40 soft_session_t *session_p; 41 soft_object_t *key_p; 42 boolean_t lock_held = B_FALSE; 43 44 if (!softtoken_initialized) 45 return (CKR_CRYPTOKI_NOT_INITIALIZED); 46 47 /* Obtain the session pointer. */ 48 rv = handle2session(hSession, &session_p); 49 if (rv != CKR_OK) 50 return (rv); 51 52 if (pMechanism == NULL) { 53 rv = CKR_ARGUMENTS_BAD; 54 goto clean_exit; 55 } 56 57 /* Obtain the object pointer. */ 58 HANDLE2OBJECT(hKey, key_p, rv); 59 if (rv != CKR_OK) 60 goto clean_exit; 61 62 /* Check to see if key object allows for decryption. */ 63 if (!(key_p->bool_attr_mask & DECRYPT_BOOL_ON)) { 64 rv = CKR_KEY_FUNCTION_NOT_PERMITTED; 65 goto clean_exit1; 66 } 67 68 (void) pthread_mutex_lock(&session_p->session_mutex); 69 lock_held = B_TRUE; 70 71 /* Check to see if decrypt operation is already active. */ 72 if (session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE) { 73 /* free the memory to avoid memory leak */ 74 soft_crypt_cleanup(session_p, B_FALSE, lock_held); 75 } 76 77 /* 78 * This active flag will remain ON until application calls either 79 * C_Decrypt or C_DecryptFinal to actually obtain the final piece 80 * of plaintext. 81 */ 82 session_p->decrypt.flags = CRYPTO_OPERATION_ACTIVE; 83 84 (void) pthread_mutex_unlock(&session_p->session_mutex); 85 lock_held = B_FALSE; 86 87 rv = soft_decrypt_init(session_p, pMechanism, key_p); 88 89 if (rv != CKR_OK) { 90 (void) pthread_mutex_lock(&session_p->session_mutex); 91 session_p->decrypt.flags &= ~CRYPTO_OPERATION_ACTIVE; 92 lock_held = B_TRUE; 93 } 94 95 clean_exit1: 96 OBJ_REFRELE(key_p); 97 clean_exit: 98 SES_REFRELE(session_p, lock_held); 99 return (rv); 100 } 101 102 103 CK_RV 104 C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, 105 CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 106 { 107 108 CK_RV rv; 109 soft_session_t *session_p; 110 boolean_t lock_held = B_FALSE; 111 112 if (!softtoken_initialized) 113 return (CKR_CRYPTOKI_NOT_INITIALIZED); 114 115 /* Obatin the session pointer. */ 116 rv = handle2session(hSession, &session_p); 117 if (rv != CKR_OK) 118 return (rv); 119 120 /* 121 * Only check if input buffer is null. How to handle zero input 122 * length depents on the mechanism in use. For secret key mechanisms, 123 * unpadded ones yield zero length output, but padded ones always 124 * result in smaller than original, possibly zero, length output. 125 */ 126 if (pEncryptedData == NULL) { 127 rv = CKR_ARGUMENTS_BAD; 128 goto clean_exit; 129 } 130 131 /* 132 * No need to check pData because application might 133 * just want to know the length of decrypted data. 134 */ 135 if (pulDataLen == NULL) { 136 rv = CKR_ARGUMENTS_BAD; 137 goto clean_exit; 138 } 139 140 (void) pthread_mutex_lock(&session_p->session_mutex); 141 lock_held = B_TRUE; 142 143 /* Application must call C_DecryptInit before calling C_Decrypt. */ 144 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 145 SES_REFRELE(session_p, lock_held); 146 return (CKR_OPERATION_NOT_INITIALIZED); 147 } 148 149 /* 150 * C_Decrypt must be called without intervening C_DecryptUpdate 151 * calls. 152 */ 153 if (session_p->decrypt.flags & CRYPTO_OPERATION_UPDATE) { 154 /* 155 * C_Decrypt can not be used to terminate a multi-part 156 * operation, so we'll leave the active decrypt operation 157 * flag on and let the application continue with the 158 * decrypt update operation. 159 */ 160 SES_REFRELE(session_p, lock_held); 161 return (CKR_FUNCTION_FAILED); 162 } 163 164 (void) pthread_mutex_unlock(&session_p->session_mutex); 165 lock_held = B_FALSE; 166 167 rv = soft_decrypt(session_p, pEncryptedData, ulEncryptedDataLen, 168 pData, pulDataLen); 169 170 if ((rv == CKR_BUFFER_TOO_SMALL) || 171 (pData == NULL && rv == CKR_OK)) { 172 /* 173 * We will not terminate the active decrypt operation flag, 174 * when the application-supplied buffer is too small, or 175 * the application asks for the length of buffer to hold 176 * the plaintext. 177 */ 178 SES_REFRELE(session_p, lock_held); 179 return (rv); 180 } 181 182 clean_exit: 183 /* Clear context, free key, and release session counter */ 184 soft_crypt_cleanup(session_p, B_FALSE, B_FALSE); 185 186 return (rv); 187 } 188 189 190 CK_RV 191 C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, 192 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 193 CK_ULONG_PTR pulPartLen) 194 { 195 196 CK_RV rv; 197 soft_session_t *session_p; 198 boolean_t lock_held = B_FALSE; 199 200 if (!softtoken_initialized) 201 return (CKR_CRYPTOKI_NOT_INITIALIZED); 202 203 /* Obtain the session pointer. */ 204 rv = handle2session(hSession, &session_p); 205 if (rv != CKR_OK) 206 return (rv); 207 208 /* 209 * Only check if input buffer is null. How to handle zero input 210 * length depents on the mechanism in use. For secret key mechanisms, 211 * unpadded ones yeild zero length output, but padded ones always 212 * result in smaller than original, possibly zero, length output. 213 */ 214 if (pEncryptedPart == NULL) { 215 rv = CKR_ARGUMENTS_BAD; 216 goto clean_exit; 217 } 218 219 /* 220 * Only check if pulPartLen is NULL. 221 * No need to check if pPart is NULL because application 222 * might just ask for the length of buffer to hold the 223 * recovered data. 224 */ 225 if (pulPartLen == NULL) { 226 rv = CKR_ARGUMENTS_BAD; 227 goto clean_exit; 228 } 229 230 (void) pthread_mutex_lock(&session_p->session_mutex); 231 lock_held = B_TRUE; 232 233 /* 234 * Application must call C_DecryptInit before calling 235 * C_DecryptUpdate. 236 */ 237 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 238 SES_REFRELE(session_p, lock_held); 239 return (CKR_OPERATION_NOT_INITIALIZED); 240 } 241 242 session_p->decrypt.flags |= CRYPTO_OPERATION_UPDATE; 243 244 (void) pthread_mutex_unlock(&session_p->session_mutex); 245 lock_held = B_FALSE; 246 247 rv = soft_decrypt_update(session_p, pEncryptedPart, 248 ulEncryptedPartLen, pPart, pulPartLen); 249 250 /* 251 * If CKR_OK or CKR_BUFFER_TOO_SMALL, don't terminate the 252 * current decryption operation. 253 */ 254 if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL)) { 255 SES_REFRELE(session_p, lock_held); 256 return (rv); 257 } 258 259 clean_exit: 260 /* 261 * After an error occurred, terminate the current decrypt 262 * operation by resetting the active and update flags. 263 */ 264 soft_crypt_cleanup(session_p, B_FALSE, lock_held); 265 266 return (rv); 267 } 268 269 CK_RV 270 C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, 271 CK_ULONG_PTR pulLastPartLen) 272 { 273 274 CK_RV rv; 275 soft_session_t *session_p; 276 boolean_t lock_held = B_FALSE; 277 278 if (!softtoken_initialized) 279 return (CKR_CRYPTOKI_NOT_INITIALIZED); 280 281 /* Obtain the session pointer. */ 282 rv = handle2session(hSession, &session_p); 283 if (rv != CKR_OK) 284 return (rv); 285 286 if (pulLastPartLen == NULL) { 287 rv = CKR_ARGUMENTS_BAD; 288 goto clean_exit; 289 } 290 291 (void) pthread_mutex_lock(&session_p->session_mutex); 292 lock_held = B_TRUE; 293 294 /* 295 * Application must call C_DecryptInit before calling 296 * C_DecryptFinal. 297 */ 298 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 299 SES_REFRELE(session_p, lock_held); 300 return (CKR_OPERATION_NOT_INITIALIZED); 301 } 302 303 (void) pthread_mutex_unlock(&session_p->session_mutex); 304 lock_held = B_FALSE; 305 306 rv = soft_decrypt_final(session_p, pLastPart, pulLastPartLen); 307 308 if ((rv == CKR_BUFFER_TOO_SMALL) || 309 (pLastPart == NULL && rv == CKR_OK)) { 310 /* 311 * We will not terminate the active decrypt operation flag, 312 * when the application-supplied buffer is too small, or 313 * the application asks for the length of buffer to hold 314 * the plaintext. 315 */ 316 SES_REFRELE(session_p, lock_held); 317 return (rv); 318 } 319 320 /* Terminates the active encrypt operation. */ 321 (void) pthread_mutex_lock(&session_p->session_mutex); 322 session_p->decrypt.flags = 0; 323 lock_held = B_TRUE; 324 SES_REFRELE(session_p, lock_held); 325 return (rv); 326 327 clean_exit: 328 /* Terminates the active decrypt operation */ 329 soft_crypt_cleanup(session_p, B_FALSE, lock_held); 330 331 return (rv); 332 } 333