kmsDecrypt.c revision 12720:3db6e0082404
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 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 22 */ 23 24#include <string.h> 25#include <strings.h> 26#include <security/cryptoki.h> 27#include "kmsGlobal.h" 28#include "kmsCrypt.h" 29 30 31/* 32 * kms_decrypt_init() 33 * 34 * Arguments: 35 * session_p: pointer to kms_session_t struct 36 * pMechanism: pointer to CK_MECHANISM struct provided by application 37 * key_p: pointer to key kms_object_t struct 38 * 39 * Description: 40 * called by C_DecryptInit(). This function calls the corresponding 41 * decrypt init routine based on the mechanism. 42 * 43 * Returns: 44 * CKR_OK: success 45 * CKR_HOST_MEMORY: run out of system memory 46 * CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism 47 * CKR_MECHANISM_INVALID: invalid mechanism type 48 * CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use 49 * with the specified mechanism 50 */ 51CK_RV 52kms_decrypt_init(kms_session_t *session_p, CK_MECHANISM_PTR pMechanism, 53 kms_object_t *key_p) 54{ 55 56 CK_RV rv; 57 58 switch (pMechanism->mechanism) { 59 case CKM_AES_CBC: 60 case CKM_AES_CBC_PAD: 61 { 62 kms_aes_ctx_t *kms_aes_ctx; 63 64 if (key_p->key_type != CKK_AES) { 65 return (CKR_KEY_TYPE_INCONSISTENT); 66 } 67 68 if ((pMechanism->pParameter == NULL) || 69 (pMechanism->ulParameterLen != AES_BLOCK_LEN)) { 70 return (CKR_MECHANISM_PARAM_INVALID); 71 } 72 73 rv = kms_aes_crypt_init_common(session_p, pMechanism, 74 key_p, B_FALSE); 75 76 if (rv != CKR_OK) 77 return (rv); 78 79 (void) pthread_mutex_lock(&session_p->session_mutex); 80 81 kms_aes_ctx = (kms_aes_ctx_t *)session_p->decrypt.context; 82 83 /* Save Initialization Vector (IV) in the context. */ 84 (void) memcpy(kms_aes_ctx->ivec, pMechanism->pParameter, 85 AES_BLOCK_LEN); 86 87 /* Allocate a context for AES cipher-block chaining. */ 88 kms_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init( 89 kms_aes_ctx->key_sched, kms_aes_ctx->keysched_len, 90 kms_aes_ctx->ivec); 91 92 if (kms_aes_ctx->aes_cbc == NULL) { 93 bzero(kms_aes_ctx->key_sched, 94 kms_aes_ctx->keysched_len); 95 free(kms_aes_ctx->key_sched); 96 free(session_p->decrypt.context); 97 session_p->decrypt.context = NULL; 98 (void) pthread_mutex_unlock(&session_p->session_mutex); 99 return (CKR_HOST_MEMORY); 100 } 101 102 (void) pthread_mutex_unlock(&session_p->session_mutex); 103 104 return (rv); 105 } 106 default: 107 return (CKR_MECHANISM_INVALID); 108 } 109} 110 111CK_RV 112C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, 113 CK_OBJECT_HANDLE hKey) 114{ 115 CK_RV rv; 116 kms_session_t *session_p; 117 kms_object_t *key_p; 118 boolean_t lock_held = B_FALSE; 119 120 if (!kms_initialized) 121 return (CKR_CRYPTOKI_NOT_INITIALIZED); 122 123 /* Obtain the session pointer. */ 124 rv = handle2session(hSession, &session_p); 125 if (rv != CKR_OK) 126 return (rv); 127 128 if (pMechanism == NULL) { 129 rv = CKR_ARGUMENTS_BAD; 130 goto clean_exit; 131 } 132 133 /* Obtain the object pointer. */ 134 HANDLE2OBJECT(hKey, key_p, rv); 135 if (rv != CKR_OK) 136 goto clean_exit; 137 138 /* Check to see if key object allows for decryption. */ 139 if (!(key_p->bool_attr_mask & DECRYPT_BOOL_ON)) { 140 rv = CKR_KEY_FUNCTION_NOT_PERMITTED; 141 goto clean_exit1; 142 } 143 144 (void) pthread_mutex_lock(&session_p->session_mutex); 145 lock_held = B_TRUE; 146 147 /* Check to see if decrypt operation is already active. */ 148 if (session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE) { 149 /* free the memory to avoid memory leak */ 150 kms_crypt_cleanup(session_p, B_FALSE, lock_held); 151 } 152 153 /* 154 * This active flag will remain ON until application calls either 155 * C_Decrypt or C_DecryptFinal to actually obtain the final piece 156 * of plaintext. 157 */ 158 session_p->decrypt.flags = CRYPTO_OPERATION_ACTIVE; 159 160 (void) pthread_mutex_unlock(&session_p->session_mutex); 161 lock_held = B_FALSE; 162 163 rv = kms_decrypt_init(session_p, pMechanism, key_p); 164 165 if (rv != CKR_OK) { 166 (void) pthread_mutex_lock(&session_p->session_mutex); 167 session_p->decrypt.flags &= ~CRYPTO_OPERATION_ACTIVE; 168 lock_held = B_TRUE; 169 } 170 171clean_exit1: 172 OBJ_REFRELE(key_p); 173clean_exit: 174 REFRELE(session_p, lock_held); 175 return (rv); 176} 177 178CK_RV 179C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, 180 CK_ULONG ulEncryptedData, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) 181{ 182 CK_RV rv; 183 kms_session_t *session_p; 184 boolean_t lock_held = B_FALSE; 185 186 if (!kms_initialized) 187 return (CKR_CRYPTOKI_NOT_INITIALIZED); 188 189 /* Obatin the session pointer. */ 190 rv = handle2session(hSession, &session_p); 191 if (rv != CKR_OK) 192 return (rv); 193 194 /* 195 * Only check if input buffer is null. How to handle zero input 196 * length depents on the mechanism in use. For secret key mechanisms, 197 * unpadded ones yield zero length output, but padded ones always 198 * result in smaller than original, possibly zero, length output. 199 */ 200 if (pEncryptedData == NULL) { 201 rv = CKR_ARGUMENTS_BAD; 202 goto clean_exit; 203 } 204 205 /* 206 * No need to check pData because application might 207 * just want to know the length of decrypted data. 208 */ 209 if (pulDataLen == NULL) { 210 rv = CKR_ARGUMENTS_BAD; 211 goto clean_exit; 212 } 213 214 (void) pthread_mutex_lock(&session_p->session_mutex); 215 lock_held = B_TRUE; 216 217 /* Application must call C_DecryptInit before calling C_Decrypt. */ 218 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 219 REFRELE(session_p, lock_held); 220 return (CKR_OPERATION_NOT_INITIALIZED); 221 } 222 223 /* 224 * C_Decrypt must be called without intervening C_DecryptUpdate 225 * calls. 226 */ 227 if (session_p->decrypt.flags & CRYPTO_OPERATION_UPDATE) { 228 /* 229 * C_Decrypt can not be used to terminate a multi-part 230 * operation, so we'll leave the active decrypt operation 231 * flag on and let the application continue with the 232 * decrypt update operation. 233 */ 234 REFRELE(session_p, lock_held); 235 return (CKR_FUNCTION_FAILED); 236 } 237 238 (void) pthread_mutex_unlock(&session_p->session_mutex); 239 lock_held = B_FALSE; 240 241 rv = kms_aes_decrypt_common(session_p, pEncryptedData, 242 ulEncryptedData, pData, pulDataLen, FALSE); 243 244 if ((rv == CKR_BUFFER_TOO_SMALL) || 245 (pData == NULL && rv == CKR_OK)) { 246 /* 247 * We will not terminate the active decrypt operation flag, 248 * when the application-supplied buffer is too small, or 249 * the application asks for the length of buffer to hold 250 * the plaintext. 251 */ 252 REFRELE(session_p, lock_held); 253 return (rv); 254 } 255 256clean_exit: 257 /* Clear context, free key, and release session counter */ 258 kms_crypt_cleanup(session_p, B_FALSE, B_FALSE); 259 260 return (rv); 261} 262 263CK_RV 264C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, 265 CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, 266 CK_ULONG_PTR pulPartLen) 267{ 268 269 CK_RV rv; 270 kms_session_t *session_p; 271 boolean_t lock_held = B_FALSE; 272 273 if (!kms_initialized) 274 return (CKR_CRYPTOKI_NOT_INITIALIZED); 275 276 /* Obtain the session pointer. */ 277 rv = handle2session(hSession, &session_p); 278 if (rv != CKR_OK) 279 return (rv); 280 281 /* 282 * Only check if input buffer is null. How to handle zero input 283 * length depents on the mechanism in use. For secret key mechanisms, 284 * unpadded ones yeild zero length output, but padded ones always 285 * result in smaller than original, possibly zero, length output. 286 */ 287 if (pEncryptedPart == NULL) { 288 rv = CKR_ARGUMENTS_BAD; 289 goto clean_exit; 290 } 291 292 /* 293 * Only check if pulPartLen is NULL. 294 * No need to check if pPart is NULL because application 295 * might just ask for the length of buffer to hold the 296 * recovered data. 297 */ 298 if (pulPartLen == NULL) { 299 rv = CKR_ARGUMENTS_BAD; 300 goto clean_exit; 301 } 302 303 (void) pthread_mutex_lock(&session_p->session_mutex); 304 lock_held = B_TRUE; 305 306 /* 307 * Application must call C_DecryptInit before calling 308 * C_DecryptUpdate. 309 */ 310 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 311 REFRELE(session_p, lock_held); 312 return (CKR_OPERATION_NOT_INITIALIZED); 313 } 314 315 session_p->decrypt.flags |= CRYPTO_OPERATION_UPDATE; 316 317 (void) pthread_mutex_unlock(&session_p->session_mutex); 318 lock_held = B_FALSE; 319 320 rv = kms_aes_decrypt_common(session_p, pEncryptedPart, 321 ulEncryptedPartLen, pPart, pulPartLen, B_TRUE); 322 323 /* 324 * If CKR_OK or CKR_BUFFER_TOO_SMALL, don't terminate the 325 * current decryption operation. 326 */ 327 if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL)) { 328 REFRELE(session_p, lock_held); 329 return (rv); 330 } 331 332clean_exit: 333 /* 334 * After an error occurred, terminate the current decrypt 335 * operation by resetting the active and update flags. 336 */ 337 kms_crypt_cleanup(session_p, B_FALSE, lock_held); 338 339 return (rv); 340} 341 342CK_RV 343C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, 344 CK_ULONG_PTR pulLastPartLen) 345{ 346 347 CK_RV rv; 348 kms_session_t *session_p; 349 boolean_t lock_held = B_FALSE; 350 351 if (!kms_initialized) 352 return (CKR_CRYPTOKI_NOT_INITIALIZED); 353 354 /* Obtain the session pointer. */ 355 rv = handle2session(hSession, &session_p); 356 if (rv != CKR_OK) 357 return (rv); 358 359 if (pulLastPartLen == NULL) { 360 rv = CKR_ARGUMENTS_BAD; 361 goto clean_exit; 362 } 363 364 (void) pthread_mutex_lock(&session_p->session_mutex); 365 lock_held = B_TRUE; 366 367 /* 368 * Application must call C_DecryptInit before calling 369 * C_DecryptFinal. 370 */ 371 if (!(session_p->decrypt.flags & CRYPTO_OPERATION_ACTIVE)) { 372 REFRELE(session_p, lock_held); 373 return (CKR_OPERATION_NOT_INITIALIZED); 374 } 375 376 (void) pthread_mutex_unlock(&session_p->session_mutex); 377 lock_held = B_FALSE; 378 379 rv = kms_aes_decrypt_final(session_p, pLastPart, pulLastPartLen); 380 381 if ((rv == CKR_BUFFER_TOO_SMALL) || 382 (pLastPart == NULL && rv == CKR_OK)) { 383 /* 384 * We will not terminate the active decrypt operation flag, 385 * when the application-supplied buffer is too small, or 386 * the application asks for the length of buffer to hold 387 * the plaintext. 388 */ 389 REFRELE(session_p, lock_held); 390 return (rv); 391 } 392 393 /* Terminates the active encrypt operation. */ 394 (void) pthread_mutex_lock(&session_p->session_mutex); 395 session_p->decrypt.flags = 0; 396 lock_held = B_TRUE; 397 REFRELE(session_p, lock_held); 398 return (rv); 399 400clean_exit: 401 /* Terminates the active decrypt operation */ 402 kms_crypt_cleanup(session_p, B_FALSE, lock_held); 403 404 return (rv); 405} 406