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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright (c) 2018, Joyent, Inc. 25 */ 26 27 #include <strings.h> 28 #include <md5.h> 29 #include <pthread.h> 30 #include <stdlib.h> 31 #include <sys/sha1.h> 32 #include <sys/sha2.h> 33 #include <sys/types.h> 34 #include <security/cryptoki.h> 35 #include "softGlobal.h" 36 #include "softOps.h" 37 #include "softSession.h" 38 #include "softObject.h" 39 40 41 /* 42 * soft_digest_init() 43 * 44 * Arguments: 45 * session_p: pointer to soft_session_t struct 46 * pMechanism: pointer to CK_MECHANISM struct provided by application 47 * 48 * Description: 49 * called by C_DigestInit(). This function allocates space for 50 * context, then calls the corresponding software provided digest 51 * init routine based on the mechanism. 52 * 53 * Returns: 54 * CKR_OK: success 55 * CKR_HOST_MEMORY: run out of system memory 56 * CKR_MECHANISM_INVALID: invalid mechanism type 57 */ 58 CK_RV 59 soft_digest_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism) 60 { 61 62 switch (pMechanism->mechanism) { 63 64 case CKM_MD5: 65 (void) pthread_mutex_lock(&session_p->session_mutex); 66 67 session_p->digest.context = malloc(sizeof (MD5_CTX)); 68 69 if (session_p->digest.context == NULL) { 70 (void) pthread_mutex_unlock(&session_p->session_mutex); 71 return (CKR_HOST_MEMORY); 72 } 73 74 session_p->digest.mech.mechanism = CKM_MD5; 75 (void) pthread_mutex_unlock(&session_p->session_mutex); 76 77 MD5Init((MD5_CTX *)session_p->digest.context); 78 79 break; 80 81 case CKM_SHA_1: 82 83 (void) pthread_mutex_lock(&session_p->session_mutex); 84 85 session_p->digest.context = malloc(sizeof (SHA1_CTX)); 86 87 if (session_p->digest.context == NULL) { 88 (void) pthread_mutex_unlock(&session_p->session_mutex); 89 return (CKR_HOST_MEMORY); 90 } 91 92 session_p->digest.mech.mechanism = CKM_SHA_1; 93 session_p->digest.mech.pParameter = pMechanism->pParameter; 94 session_p->digest.mech.ulParameterLen = 95 pMechanism->ulParameterLen; 96 (void) pthread_mutex_unlock(&session_p->session_mutex); 97 98 SHA1Init((SHA1_CTX *)session_p->digest.context); 99 100 break; 101 102 case CKM_SHA256: 103 case CKM_SHA384: 104 case CKM_SHA512: 105 106 (void) pthread_mutex_lock(&session_p->session_mutex); 107 108 session_p->digest.context = malloc(sizeof (SHA2_CTX)); 109 110 if (session_p->digest.context == NULL) { 111 (void) pthread_mutex_unlock(&session_p->session_mutex); 112 return (CKR_HOST_MEMORY); 113 } 114 115 switch (pMechanism->mechanism) { 116 case CKM_SHA256: 117 session_p->digest.mech.mechanism = CKM_SHA256; 118 (void) pthread_mutex_unlock(&session_p->session_mutex); 119 SHA2Init(SHA256, 120 (SHA2_CTX *)session_p->digest.context); 121 break; 122 123 case CKM_SHA384: 124 session_p->digest.mech.mechanism = CKM_SHA384; 125 (void) pthread_mutex_unlock(&session_p->session_mutex); 126 SHA2Init(SHA384, 127 (SHA2_CTX *)session_p->digest.context); 128 break; 129 130 case CKM_SHA512: 131 session_p->digest.mech.mechanism = CKM_SHA512; 132 (void) pthread_mutex_unlock(&session_p->session_mutex); 133 SHA2Init(SHA512, 134 (SHA2_CTX *)session_p->digest.context); 135 break; 136 } 137 break; 138 139 default: 140 return (CKR_MECHANISM_INVALID); 141 } 142 143 return (CKR_OK); 144 } 145 146 147 /* 148 * soft_digest_common() 149 * 150 * Arguments: 151 * session_p: pointer to soft_session_t struct 152 * pData: pointer to the input data to be digested 153 * ulDataLen: length of the input data 154 * pDigest: pointer to the output data after digesting 155 * pulDigestLen: length of the output data 156 * 157 * Description: 158 * called by soft_digest() or soft_digest_final(). This function 159 * determines the length of output buffer and calls the corresponding 160 * software provided digest routine based on the mechanism. 161 * 162 * Returns: 163 * CKR_OK: success 164 * CKR_MECHANISM_INVALID: invalid mechanism type 165 * CKR_BUFFER_TOO_SMALL: the output buffer provided by application 166 * is too small 167 */ 168 CK_RV 169 soft_digest_common(soft_session_t *session_p, CK_BYTE_PTR pData, 170 CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) 171 { 172 173 CK_ULONG digestLen = 0; 174 size_t len = 0; 175 176 /* 177 * Determine the output data length based on the mechanism 178 */ 179 switch (session_p->digest.mech.mechanism) { 180 181 case CKM_MD5: 182 digestLen = 16; 183 break; 184 185 case CKM_SHA_1: 186 digestLen = 20; 187 break; 188 189 case CKM_SHA256: 190 digestLen = 32; 191 break; 192 193 case CKM_SHA384: 194 digestLen = 48; 195 break; 196 197 case CKM_SHA512: 198 digestLen = 64; 199 break; 200 201 default: 202 return (CKR_MECHANISM_INVALID); 203 } 204 205 if (pDigest == NULL) { 206 /* 207 * Application only wants to know the length of the 208 * buffer needed to hold the message digest. 209 */ 210 *pulDigestLen = digestLen; 211 return (CKR_OK); 212 } 213 214 if (*pulDigestLen < digestLen) { 215 /* 216 * Application provides buffer too small to hold the 217 * digest message. Return the length of buffer needed 218 * to the application. 219 */ 220 *pulDigestLen = digestLen; 221 return (CKR_BUFFER_TOO_SMALL); 222 } 223 224 /* 225 * Call the corresponding system provided software digest routine. 226 * If the soft_digest_common() is called by soft_digest_final() 227 * the pData is NULL, and the ulDataLen is zero. 228 */ 229 switch (session_p->digest.mech.mechanism) { 230 231 case CKM_MD5: 232 if (pData != NULL) { 233 /* 234 * this is called by soft_digest() 235 */ 236 #ifdef __sparcv9 237 MD5Update((MD5_CTX *)session_p->digest.context, 238 /* LINTED */ 239 pData, (uint_t)ulDataLen); 240 #else /* !__sparcv9 */ 241 MD5Update((MD5_CTX *)session_p->digest.context, 242 pData, ulDataLen); 243 #endif /* __sparcv9 */ 244 MD5Final(pDigest, (MD5_CTX *)session_p->digest.context); 245 } else { 246 /* 247 * this is called by soft_digest_final() 248 */ 249 MD5Final(pDigest, (MD5_CTX *)session_p->digest.context); 250 len = sizeof (MD5_CTX); 251 } 252 break; 253 254 case CKM_SHA_1: 255 if (pData != NULL) { 256 /* 257 * this is called by soft_digest() 258 */ 259 260 #ifdef __sparcv9 261 SHA1Update((SHA1_CTX *)session_p->digest.context, 262 /* LINTED */ 263 pData, (uint32_t)ulDataLen); 264 #else /* !__sparcv9 */ 265 SHA1Update((SHA1_CTX *)session_p->digest.context, 266 pData, ulDataLen); 267 #endif /* __sparcv9 */ 268 SHA1Final(pDigest, 269 (SHA1_CTX *)session_p->digest.context); 270 } else { 271 /* 272 * this is called by soft_digest_final() 273 */ 274 SHA1Final(pDigest, 275 (SHA1_CTX *)session_p->digest.context); 276 len = sizeof (SHA1_CTX); 277 } 278 break; 279 case CKM_SHA256: 280 case CKM_SHA384: 281 case CKM_SHA512: 282 if (pData != NULL) { 283 /* 284 * this is called by soft_digest() 285 */ 286 287 SHA2Update((SHA2_CTX *)session_p->digest.context, 288 pData, ulDataLen); 289 290 SHA2Final(pDigest, 291 (SHA2_CTX *)session_p->digest.context); 292 } else { 293 /* 294 * this is called by soft_digest_final() 295 */ 296 SHA2Final(pDigest, 297 (SHA2_CTX *)session_p->digest.context); 298 len = sizeof (SHA2_CTX); 299 } 300 301 break; 302 } 303 304 /* Paranoia on behalf of C_DigestKey callers: bzero the context */ 305 if (session_p->digest.flags & CRYPTO_KEY_DIGESTED) { 306 explicit_bzero(session_p->digest.context, len); 307 session_p->digest.flags &= ~CRYPTO_KEY_DIGESTED; 308 } 309 *pulDigestLen = digestLen; 310 (void) pthread_mutex_lock(&session_p->session_mutex); 311 free(session_p->digest.context); 312 session_p->digest.context = NULL; 313 (void) pthread_mutex_unlock(&session_p->session_mutex); 314 315 return (CKR_OK); 316 } 317 318 319 /* 320 * soft_digest() 321 * 322 * Arguments: 323 * session_p: pointer to soft_session_t struct 324 * pData: pointer to the input data to be digested 325 * ulDataLen: length of the input data 326 * pDigest: pointer to the output data after digesting 327 * pulDigestLen: length of the output data 328 * 329 * Description: 330 * called by C_Digest(). This function calls soft_digest_common(). 331 * 332 * Returns: 333 * see return values in soft_digest_common(). 334 */ 335 CK_RV 336 soft_digest(soft_session_t *session_p, CK_BYTE_PTR pData, CK_ULONG ulDataLen, 337 CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) 338 { 339 340 return (soft_digest_common(session_p, pData, ulDataLen, 341 pDigest, pulDigestLen)); 342 } 343 344 345 /* 346 * soft_digest_update() 347 * 348 * Arguments: 349 * session_p: pointer to soft_session_t struct 350 * pPart: pointer to the input data to be digested 351 * ulPartLen: length of the input data 352 * 353 * Description: 354 * called by C_DigestUpdate(). This function calls the corresponding 355 * software provided digest update routine based on the mechanism. 356 * 357 * Returns: 358 * CKR_OK: success 359 * CKR_MECHANISM_INVALID: invalid MECHANISM type. 360 */ 361 CK_RV 362 soft_digest_update(soft_session_t *session_p, CK_BYTE_PTR pPart, 363 CK_ULONG ulPartLen) 364 { 365 366 switch (session_p->digest.mech.mechanism) { 367 368 case CKM_MD5: 369 #ifdef __sparcv9 370 MD5Update((MD5_CTX *)session_p->digest.context, 371 /* LINTED */ 372 pPart, (uint_t)ulPartLen); 373 #else /* !__sparcv9 */ 374 MD5Update((MD5_CTX *)session_p->digest.context, 375 pPart, ulPartLen); 376 #endif /* __sparcv9 */ 377 break; 378 379 case CKM_SHA_1: 380 #ifdef __sparcv9 381 SHA1Update((SHA1_CTX *)session_p->digest.context, 382 /* LINTED */ 383 pPart, (uint32_t)ulPartLen); 384 #else /* !__sparcv9 */ 385 SHA1Update((SHA1_CTX *)session_p->digest.context, 386 pPart, ulPartLen); 387 #endif /* __sparcv9 */ 388 break; 389 390 case CKM_SHA256: 391 case CKM_SHA384: 392 case CKM_SHA512: 393 SHA2Update((SHA2_CTX *)session_p->digest.context, 394 pPart, ulPartLen); 395 break; 396 397 default: 398 return (CKR_MECHANISM_INVALID); 399 } 400 401 return (CKR_OK); 402 } 403 404 405 /* 406 * soft_digest_final() 407 * 408 * Arguments: 409 * session_p: pointer to soft_session_t struct 410 * pDigest: pointer to the output data after digesting 411 * pulDigestLen: length of the output data 412 * 413 * Description: 414 * called by C_DigestFinal(). This function calls soft_digest_common(). 415 * 416 * Returns: 417 * see return values in soft_digest_common(). 418 */ 419 CK_RV 420 soft_digest_final(soft_session_t *session_p, CK_BYTE_PTR pDigest, 421 CK_ULONG_PTR pulDigestLen) 422 { 423 424 return (soft_digest_common(session_p, NULL, 0, 425 pDigest, pulDigestLen)); 426 } 427 428 /* 429 * Perform digest init operation internally for the support of 430 * CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA1_KEY_DERIVATION 431 * and CKM_MD5_KEY_DERIVATION mechanisms. 432 * 433 * This function is called with the session being held, and without 434 * its mutex taken. 435 */ 436 CK_RV 437 soft_digest_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR 438 pMechanism) 439 { 440 441 CK_RV rv; 442 443 (void) pthread_mutex_lock(&session_p->session_mutex); 444 445 /* Check to see if digest operation is already active */ 446 if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) { 447 (void) pthread_mutex_unlock(&session_p->session_mutex); 448 return (CKR_OPERATION_ACTIVE); 449 } 450 451 session_p->digest.flags = CRYPTO_OPERATION_ACTIVE; 452 453 (void) pthread_mutex_unlock(&session_p->session_mutex); 454 455 rv = soft_digest_init(session_p, pMechanism); 456 457 if (rv != CKR_OK) { 458 (void) pthread_mutex_lock(&session_p->session_mutex); 459 session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE; 460 (void) pthread_mutex_unlock(&session_p->session_mutex); 461 } 462 463 return (rv); 464 } 465 466 /* 467 * Call soft_digest_update() function with the value of a secret key. 468 */ 469 CK_RV 470 soft_digest_key(soft_session_t *session_p, soft_object_t *key_p) 471 { 472 473 CK_RV rv; 474 475 /* Only secret key is allowed to be digested */ 476 if (key_p->class != CKO_SECRET_KEY) 477 return (CKR_KEY_INDIGESTIBLE); 478 479 if ((OBJ_SEC_VALUE(key_p) == NULL) || 480 (OBJ_SEC_VALUE_LEN(key_p) == 0)) 481 return (CKR_KEY_SIZE_RANGE); 482 483 rv = soft_digest_update(session_p, OBJ_SEC_VALUE(key_p), 484 OBJ_SEC_VALUE_LEN(key_p)); 485 486 return (rv); 487 488 } 489 490 /* 491 * This function releases allocated digest context. The caller 492 * may (lock_held == B_TRUE) or may not (lock_held == B_FALSE) 493 * hold a session mutex. 494 */ 495 void 496 soft_digest_cleanup(soft_session_t *session_p, boolean_t lock_held) 497 { 498 boolean_t lock_true = B_TRUE; 499 500 if (!lock_held) 501 (void) pthread_mutex_lock(&session_p->session_mutex); 502 503 if (session_p->digest.context != NULL) { 504 free(session_p->digest.context); 505 session_p->digest.context = NULL; 506 } 507 508 session_p->digest.flags = 0; 509 510 if (!lock_held) 511 SES_REFRELE(session_p, lock_true); 512 513 }