1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 /* 6 * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. 7 */ 8 9 #include <kmfapiP.h> 10 #include <sha1.h> 11 #include <security/cryptoki.h> 12 13 #include <ber_der.h> 14 15 #define MAX_PUBLIC_KEY_TEMPLATES (20) 16 #define MAX_PRIVATE_KEY_TEMPLATES (24) 17 #define MAX_SECRET_KEY_TEMPLATES (24) 18 19 typedef struct 20 { 21 KMF_ALGORITHM_INDEX kmfAlgorithmId; 22 CK_KEY_TYPE ckKeyType; 23 CK_MECHANISM_TYPE signmech; 24 CK_MECHANISM_TYPE vfymech; 25 CK_MECHANISM_TYPE hashmech; 26 } ALG_INFO; 27 28 static const ALG_INFO alg_info_map[] = { 29 { KMF_ALGID_RSA, CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, NULL}, 30 { KMF_ALGID_DSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 }, 31 { KMF_ALGID_ECDSA, CKK_EC, CKM_ECDSA, CKM_ECDSA, CKM_SHA_1 }, 32 { KMF_ALGID_SHA1WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA_1 }, 33 { KMF_ALGID_SHA256WithDSA, CKK_DSA, CKM_DSA, CKM_DSA, CKM_SHA256 }, 34 35 /* 36 * For RSA, the verify can be done using a single mechanism, 37 * but signing must be done separately because not all hardware 38 * tokens support the combined hash+key operations. 39 */ 40 { KMF_ALGID_MD5WithRSA, CKK_RSA, CKM_RSA_PKCS, 41 CKM_MD5_RSA_PKCS, CKM_MD5}, 42 { KMF_ALGID_SHA1WithRSA, CKK_RSA, CKM_RSA_PKCS, 43 CKM_SHA1_RSA_PKCS, CKM_SHA_1}, 44 { KMF_ALGID_SHA256WithRSA, CKK_RSA, CKM_RSA_PKCS, 45 CKM_SHA256_RSA_PKCS, CKM_SHA256}, 46 { KMF_ALGID_SHA384WithRSA, CKK_RSA, CKM_RSA_PKCS, 47 CKM_SHA384_RSA_PKCS, CKM_SHA384}, 48 { KMF_ALGID_SHA512WithRSA, CKK_RSA, CKM_RSA_PKCS, 49 CKM_SHA512_RSA_PKCS, CKM_SHA512}, 50 { KMF_ALGID_SHA1WithECDSA, CKK_EC, CKM_ECDSA, 51 CKM_ECDSA, CKM_SHA_1}, 52 { KMF_ALGID_SHA256WithECDSA, CKK_EC, CKM_ECDSA, 53 CKM_ECDSA, CKM_SHA256}, 54 { KMF_ALGID_SHA384WithECDSA, CKK_EC, CKM_ECDSA, 55 CKM_ECDSA, CKM_SHA384}, 56 { KMF_ALGID_SHA512WithECDSA, CKK_EC, CKM_ECDSA, 57 CKM_ECDSA, CKM_SHA512} 58 }; 59 60 KMF_RETURN 61 get_pk11_data(KMF_ALGORITHM_INDEX AlgId, 62 CK_KEY_TYPE *keytype, CK_MECHANISM_TYPE *signmech, 63 CK_MECHANISM_TYPE *hashmech, boolean_t vfy) 64 { 65 uint32_t uIndex; 66 uint32_t uMapSize = 67 sizeof (alg_info_map) / sizeof (ALG_INFO); 68 69 for (uIndex = 0; uIndex < uMapSize; uIndex++) { 70 if (alg_info_map[uIndex].kmfAlgorithmId == AlgId) { 71 if (keytype) 72 *keytype = alg_info_map[uIndex].ckKeyType; 73 if (hashmech) 74 *hashmech = alg_info_map[uIndex].hashmech; 75 if (signmech) 76 *signmech = 77 (vfy ? alg_info_map[uIndex].vfymech : 78 alg_info_map[uIndex].signmech); 79 return (KMF_OK); 80 } 81 } 82 /* no match */ 83 return (KMF_ERR_BAD_ALGORITHM); 84 } 85 86 KMF_RETURN 87 kmf_create_pk11_session(CK_SESSION_HANDLE *sessionp, 88 CK_MECHANISM_TYPE wanted_mech, 89 CK_FLAGS wanted_flags) 90 { 91 CK_RV rv; 92 KMF_RETURN ret; 93 KMF_RETURN kmf_rv = KMF_OK; 94 CK_SLOT_ID_PTR pSlotList; 95 CK_ULONG pulCount; 96 CK_MECHANISM_INFO info; 97 int i; 98 99 ret = init_pk11(); 100 101 if (ret != KMF_OK) 102 return (ret); 103 104 rv = C_GetSlotList(0, NULL, &pulCount); 105 if (rv != CKR_OK) { 106 kmf_rv = KMF_ERR_UNINITIALIZED; 107 goto out; 108 } 109 110 pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID)); 111 if (pSlotList == NULL) { 112 kmf_rv = KMF_ERR_MEMORY; 113 goto out; 114 } 115 116 rv = C_GetSlotList(0, pSlotList, &pulCount); 117 if (rv != CKR_OK) { 118 kmf_rv = KMF_ERR_UNINITIALIZED; 119 goto out; 120 } 121 122 for (i = 0; i < pulCount; i++) { 123 rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info); 124 if (rv == CKR_OK && 125 (info.flags & wanted_flags) == wanted_flags) 126 break; 127 } 128 if (i < pulCount) { 129 rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION, 130 NULL, NULL, sessionp); 131 132 if (rv != CKR_OK) { 133 kmf_rv = KMF_ERR_UNINITIALIZED; 134 } 135 } else { 136 kmf_rv = KMF_ERR_UNINITIALIZED; 137 } 138 139 out: 140 if (pSlotList != NULL) 141 free(pSlotList); 142 return (kmf_rv); 143 144 } 145 146 /* 147 * Name: PKCS_AddTemplate 148 * 149 * Description: 150 * Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will 151 * not expand the array beyond the maximum specified size. 152 * 153 * Returns: 154 * TRUE - Attribute value succesfully added. 155 * FALSE - Maximum array size would be exceded. 156 */ 157 static int 158 PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate, 159 CK_ULONG *ckNumTemplates, 160 CK_ULONG ckMaxTemplates, 161 CK_ATTRIBUTE_TYPE ckAttribCode, 162 CK_BYTE * pckBuffer, 163 CK_ULONG ckBufferLen) 164 { 165 if (*ckNumTemplates >= ckMaxTemplates) { 166 return (FALSE); 167 } 168 169 pTemplate[*ckNumTemplates].type = ckAttribCode; 170 pTemplate[*ckNumTemplates].pValue = pckBuffer; 171 pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen; 172 (*ckNumTemplates)++; 173 174 return (TRUE); 175 } 176 177 /* 178 * Convert an SPKI data record to PKCS#11 179 * public key object. 180 */ 181 static KMF_RETURN 182 PKCS_CreatePublicKey( 183 const KMF_X509_SPKI *pKey, 184 CK_SESSION_HANDLE ckSession, 185 CK_OBJECT_HANDLE *pckPublicKey) 186 { 187 KMF_RETURN mrReturn = KMF_OK; 188 CK_RV ckRv; 189 190 CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES]; 191 CK_ULONG ckNumTemplates = 0; 192 193 /* Common object attributes */ 194 CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY; 195 CK_BBOOL ckToken = 0; 196 CK_BBOOL ckPrivate = 0; 197 198 /* Common key attributes */ 199 CK_KEY_TYPE ckKeyType; 200 CK_BBOOL ckDerive = CK_FALSE; 201 202 /* Common public key attributes */ 203 CK_BBOOL ckEncrypt = 1; 204 CK_BBOOL ckVerify = 1; 205 206 CK_BBOOL ckVerifyRecover = CK_FALSE; 207 CK_BBOOL ckWrap = CK_FALSE; 208 209 /* Key part array */ 210 KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS]; 211 uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS; 212 KMF_ALGORITHM_INDEX AlgorithmId; 213 214 /* Parse the keyblob */ 215 (void) memset(KeyParts, 0, sizeof (KeyParts)); 216 217 AlgorithmId = x509_algoid_to_algid( 218 (KMF_OID *)&pKey->algorithm.algorithm); 219 if (AlgorithmId == KMF_ALGID_NONE) 220 return (KMF_ERR_BAD_ALGORITHM); 221 222 mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts); 223 224 if (mrReturn != KMF_OK) 225 return (mrReturn); 226 227 /* Fill in the common object attributes */ 228 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 229 MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass, 230 sizeof (ckObjClass)) || 231 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 232 MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken, 233 sizeof (ckToken)) || 234 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 235 MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate, 236 sizeof (ckPrivate))) { 237 mrReturn = KMF_ERR_INTERNAL; 238 goto cleanup; 239 } 240 241 /* Fill in the common key attributes */ 242 if (get_pk11_data(AlgorithmId, &ckKeyType, NULL, NULL, 0)) { 243 goto cleanup; 244 } 245 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 246 MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType, 247 sizeof (ckKeyType)) || 248 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 249 MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive, 250 sizeof (ckDerive))) { 251 mrReturn = KMF_ERR_INTERNAL; 252 goto cleanup; 253 } 254 255 /* Add common public key attributes */ 256 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 257 MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt, 258 sizeof (ckEncrypt)) || 259 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 260 MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify, 261 sizeof (ckVerify)) || 262 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 263 MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER, 264 (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) || 265 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 266 MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap, 267 sizeof (ckWrap))) { 268 mrReturn = KMF_ERR_INTERNAL; 269 goto cleanup; 270 } 271 272 /* Add algorithm specific attributes */ 273 switch (ckKeyType) { 274 case CKK_RSA: 275 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 276 MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS, 277 (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data, 278 (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) || 279 280 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 281 MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT, 282 (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data, 283 (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) { 284 mrReturn = KMF_ERR_INTERNAL; 285 goto cleanup; 286 } 287 break; 288 case CKK_DSA: 289 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 290 MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME, 291 (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data, 292 (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) || 293 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 294 MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME, 295 (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data, 296 (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) || 297 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 298 MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE, 299 (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data, 300 (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) || 301 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 302 MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE, 303 (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data, 304 (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) { 305 mrReturn = KMF_ERR_INTERNAL; 306 goto cleanup; 307 } 308 break; 309 case CKK_EC: 310 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 311 MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_POINT, 312 (CK_BYTE *)KeyParts[KMF_ECDSA_POINT].Data, 313 (CK_ULONG)KeyParts[KMF_ECDSA_POINT].Length) || 314 315 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 316 MAX_PUBLIC_KEY_TEMPLATES, CKA_EC_PARAMS, 317 (CK_BYTE *)KeyParts[KMF_ECDSA_PARAMS].Data, 318 (CK_ULONG)KeyParts[KMF_ECDSA_PARAMS].Length)) { 319 mrReturn = KMF_ERR_INTERNAL; 320 goto cleanup; 321 } 322 break; 323 default: 324 mrReturn = KMF_ERR_BAD_PARAMETER; 325 } 326 327 if (mrReturn == KMF_OK) { 328 /* Instantiate the object */ 329 ckRv = C_CreateObject(ckSession, ckTemplate, 330 ckNumTemplates, pckPublicKey); 331 if (ckRv != CKR_OK) 332 mrReturn = KMF_ERR_INTERNAL; 333 } 334 335 cleanup: 336 for (i = 0; i < uNumKeyParts; i++) { 337 kmf_free_data(&KeyParts[i]); 338 } 339 340 return (mrReturn); 341 } 342 343 /* 344 * PKCS_AcquirePublicKeyHandle 345 * 346 * Given an assymetric key keyblob, attempts to find the appropriate 347 * public key. 348 * 349 * Methods of finding the public key: 350 * - Public Key with data present: 351 * Parses the key and creates a temporary session object. 352 * - Public Key with handle: 353 * The handle is type converted and returned. Validity of the handle is 354 * not checked. 355 * - Public Key with label: 356 * Attempts to find a public key with the corresponding label. 357 */ 358 static KMF_RETURN 359 PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, 360 const KMF_X509_SPKI *pKey, 361 CK_KEY_TYPE ckRequestedKeyType, 362 CK_OBJECT_HANDLE *pckKeyHandle) 363 { 364 KMF_RETURN mrReturn = KMF_OK; 365 366 /* Key searching variables */ 367 CK_OBJECT_HANDLE ckKeyHandle = 0; 368 CK_OBJECT_CLASS ckObjClass; 369 CK_KEY_TYPE ckKeyType; 370 CK_ATTRIBUTE ckTemplate[3]; 371 CK_ULONG ckNumTemplates; 372 static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) / 373 sizeof (CK_ATTRIBUTE)); 374 CK_RV ckRv; 375 376 /* Extract the data from the SPKI into individual fields */ 377 mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle); 378 if (mrReturn != KMF_OK) 379 return (mrReturn); 380 381 /* Fetch the key class and algorithm from the object */ 382 ckNumTemplates = 0; 383 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 384 ckMaxTemplates, CKA_CLASS, (CK_BYTE *)&ckObjClass, 385 sizeof (ckObjClass)) || 386 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 387 ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType, 388 sizeof (ckKeyType))) { 389 (void) C_DestroyObject(ckSession, ckKeyHandle); 390 return (KMF_ERR_INTERNAL); 391 } 392 ckRv = C_GetAttributeValue(ckSession, ckKeyHandle, 393 ckTemplate, ckNumTemplates); 394 if (ckRv != CKR_OK) { 395 (void) C_DestroyObject(ckSession, ckKeyHandle); 396 return (ckRv); 397 } 398 399 /* Make sure the results match the expected values */ 400 if ((ckKeyType != ckRequestedKeyType) || 401 (ckObjClass != CKO_PUBLIC_KEY)) { 402 (void) C_DestroyObject(ckSession, ckKeyHandle); 403 return (KMF_ERR_BAD_KEY_FORMAT); 404 } 405 406 /* Set the return values */ 407 *pckKeyHandle = ckKeyHandle; 408 409 return (KMF_OK); 410 } 411 412 /* 413 * Utility routine for verifying generic data using 414 * the cryptographic framework (PKCS#11). 415 * There are situations where we want to force this 416 * operation to happen in a specific keystore. 417 * For example: 418 * libelfsign.so.1 verifies signatures on crypto libraries. 419 * We must use pkcs11 functions to verify the pkcs11 420 * plugins in order to keep the validation within the 421 * Cryptographic Framework's FIPS-140 boundary. To avoid 422 * a circular dependency, pksc11_softtoken.so.1 is 423 * interposed by libkcfd.so.1 via kcfd, which prevents 424 * libpkcs11.so.1's interfaces from being used when libkmf.so.1 425 * is called from kcfd. 426 * 427 * This also saves code and time because verify operations 428 * only use public keys and do not need acccess to any 429 * keystore specific functions. 430 */ 431 KMF_RETURN 432 PKCS_VerifyData(KMF_HANDLE_T handle, 433 KMF_ALGORITHM_INDEX AlgorithmId, 434 KMF_X509_SPKI *keyp, 435 KMF_DATA *data, 436 KMF_DATA *signature) 437 { 438 KMF_RETURN rv = KMF_OK; 439 CK_RV ckRv; 440 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 441 CK_MECHANISM ckMechanism; 442 CK_MECHANISM_TYPE mechtype, hashmech; 443 CK_OBJECT_HANDLE ckKeyHandle = 0; 444 CK_KEY_TYPE pk11keytype; 445 CK_SESSION_HANDLE ckSession = 0; 446 CK_ATTRIBUTE subprime = { CKA_SUBPRIME, NULL, 0 }; 447 CK_BYTE *dataptr; 448 CK_ULONG datalen; 449 KMF_DATA hashData = { 0, NULL }; 450 uchar_t digest[1024]; 451 452 if (AlgorithmId == KMF_ALGID_NONE) 453 return (KMF_ERR_BAD_ALGORITHM); 454 455 if (get_pk11_data(AlgorithmId, &pk11keytype, &mechtype, &hashmech, 1)) 456 return (KMF_ERR_BAD_ALGORITHM); 457 458 /* 459 * Verify in metaslot/softtoken since only the public key is needed 460 * and not all hardware tokens support the combined [hash]-RSA/DSA/EC 461 * mechanisms. 462 */ 463 rv = kmf_create_pk11_session(&ckSession, mechtype, 0); 464 if (rv != KMF_OK) 465 return (rv); 466 467 /* Fetch the verifying key */ 468 rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp, 469 pk11keytype, &ckKeyHandle); 470 471 if (rv != KMF_OK) { 472 (void) C_CloseSession(ckSession); 473 return (rv); 474 } 475 dataptr = data->Data; 476 datalen = data->Length; 477 /* 478 * For some mechanisms, we must compute the hash separately 479 * and then do the verify. 480 */ 481 if (hashmech != 0 && 482 (mechtype == CKM_ECDSA || 483 mechtype == CKM_DSA || 484 mechtype == CKM_RSA_PKCS)) { 485 hashData.Data = digest; 486 hashData.Length = sizeof (digest); 487 488 rv = PKCS_DigestData(handle, ckSession, 489 hashmech, data, &hashData, 490 (mechtype == CKM_RSA_PKCS)); 491 if (rv) 492 goto cleanup; 493 494 dataptr = hashData.Data; 495 datalen = hashData.Length; 496 } 497 if (mechtype == CKM_DSA && 498 hashmech == CKM_SHA256) { 499 /* 500 * FIPS 186-3 says that when using DSA 501 * the hash must be truncated to the size of the 502 * subprime. 503 */ 504 ckRv = C_GetAttributeValue(ckSession, 505 ckKeyHandle, &subprime, 1); 506 if (ckRv != CKR_OK) { 507 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 508 kmfh->lasterr.errcode = ckRv; 509 rv = KMF_ERR_INTERNAL; 510 goto cleanup; 511 } 512 datalen = subprime.ulValueLen; 513 } 514 515 ckMechanism.mechanism = mechtype; 516 ckMechanism.pParameter = NULL; 517 ckMechanism.ulParameterLen = 0; 518 519 ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle); 520 if (ckRv != CKR_OK) { 521 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 522 kmfh->lasterr.errcode = ckRv; 523 rv = KMF_ERR_INTERNAL; 524 goto cleanup; 525 } 526 ckRv = C_Verify(ckSession, 527 dataptr, datalen, 528 (CK_BYTE *)signature->Data, 529 (CK_ULONG)signature->Length); 530 531 if (ckRv != CKR_OK) { 532 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 533 kmfh->lasterr.errcode = ckRv; 534 rv = KMF_ERR_INTERNAL; 535 } 536 537 cleanup: 538 if (ckKeyHandle != 0) 539 (void) C_DestroyObject(ckSession, ckKeyHandle); 540 (void) C_CloseSession(ckSession); 541 return (rv); 542 } 543 544 KMF_RETURN 545 PKCS_EncryptData(KMF_HANDLE_T kmfh, 546 KMF_ALGORITHM_INDEX AlgorithmId, 547 KMF_X509_SPKI *keyp, 548 KMF_DATA *plaintext, 549 KMF_DATA *ciphertext) 550 { 551 KMF_RETURN rv = KMF_OK; 552 CK_RV ckRv; 553 CK_MECHANISM ckMechanism; 554 CK_MECHANISM_TYPE mechtype; 555 CK_KEY_TYPE keytype; 556 CK_OBJECT_HANDLE ckKeyHandle = 0; 557 CK_SESSION_HANDLE ckSession = NULL; 558 CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0; 559 uint8_t *in_data, *out_data; 560 int i, blocks, block_size; 561 CK_ATTRIBUTE ckTemplate[2]; 562 CK_ULONG ckNumTemplates; 563 CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) / 564 sizeof (CK_ATTRIBUTE)); 565 566 if (get_pk11_data(AlgorithmId, &keytype, &mechtype, NULL, 0)) 567 return (KMF_ERR_BAD_ALGORITHM); 568 569 rv = kmf_create_pk11_session(&ckSession, mechtype, CKF_ENCRYPT); 570 if (rv != KMF_OK) 571 return (rv); 572 573 /* Get the public key used in encryption */ 574 rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp, 575 keytype, &ckKeyHandle); 576 577 if (rv != KMF_OK) { 578 (void) C_CloseSession(ckSession); 579 return (rv); 580 } 581 582 /* Get the modulus length */ 583 ckNumTemplates = 0; 584 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates, 585 CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) { 586 if (ckKeyHandle != 0) 587 (void) C_DestroyObject(ckSession, ckKeyHandle); 588 (void) C_CloseSession(ckSession); 589 return (KMF_ERR_INTERNAL); 590 } 591 592 ckRv = C_GetAttributeValue(ckSession, ckKeyHandle, 593 ckTemplate, ckNumTemplates); 594 595 if (ckRv != CKR_OK) { 596 if (ckKeyHandle != 0) 597 (void) C_DestroyObject(ckSession, ckKeyHandle); 598 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 599 kmfh->lasterr.errcode = ckRv; 600 (void) C_CloseSession(ckSession); 601 return (KMF_ERR_INTERNAL); 602 } 603 out_len = ckTemplate[0].ulValueLen; 604 605 if (out_len > ciphertext->Length) { 606 if (ckKeyHandle != 0) 607 (void) C_DestroyObject(ckSession, ckKeyHandle); 608 (void) C_CloseSession(ckSession); 609 return (KMF_ERR_BUFFER_SIZE); 610 } 611 612 ckMechanism.mechanism = mechtype; 613 ckMechanism.pParameter = NULL_PTR; 614 ckMechanism.ulParameterLen = 0; 615 616 /* Compute the fixed input data length for single-part encryption */ 617 block_size = out_len - 11; 618 619 in_data = plaintext->Data; 620 out_data = ciphertext->Data; 621 622 blocks = plaintext->Length/block_size; 623 624 for (i = 0; i < blocks; i++) { 625 ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle); 626 if (ckRv != CKR_OK) { 627 if (ckKeyHandle != 0) 628 (void) C_DestroyObject(ckSession, ckKeyHandle); 629 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 630 kmfh->lasterr.errcode = ckRv; 631 (void) C_CloseSession(ckSession); 632 return (KMF_ERR_INTERNAL); 633 } 634 ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size, 635 (CK_BYTE_PTR)out_data, &out_len); 636 637 if (ckRv != CKR_OK) { 638 if (ckKeyHandle != 0) 639 (void) C_DestroyObject(ckSession, ckKeyHandle); 640 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 641 kmfh->lasterr.errcode = ckRv; 642 (void) C_CloseSession(ckSession); 643 return (KMF_ERR_INTERNAL); 644 } 645 646 out_data += out_len; 647 total_encrypted += out_len; 648 in_data += block_size; 649 } 650 651 if (plaintext->Length % block_size) { 652 /* Encrypt the remaining data */ 653 ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle); 654 if (ckRv != CKR_OK) { 655 if (ckKeyHandle != 0) 656 (void) C_DestroyObject(ckSession, ckKeyHandle); 657 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 658 kmfh->lasterr.errcode = ckRv; 659 (void) C_CloseSession(ckSession); 660 return (KMF_ERR_INTERNAL); 661 } 662 663 in_len = plaintext->Length % block_size; 664 ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len, 665 (CK_BYTE_PTR)out_data, &out_len); 666 667 if (ckRv != CKR_OK) { 668 if (ckKeyHandle != 0) 669 (void) C_DestroyObject(ckSession, ckKeyHandle); 670 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 671 kmfh->lasterr.errcode = ckRv; 672 (void) C_CloseSession(ckSession); 673 return (KMF_ERR_INTERNAL); 674 } 675 676 out_data += out_len; 677 total_encrypted += out_len; 678 in_data += in_len; 679 } 680 681 ciphertext->Length = total_encrypted; 682 683 if (ckKeyHandle != 0) 684 (void) C_DestroyObject(ckSession, ckKeyHandle); 685 686 (void) C_CloseSession(ckSession); 687 return (rv); 688 689 } 690 691 static void 692 create_id_hash(KMF_DATA *IDInput, KMF_DATA *IDOutput) 693 { 694 SHA1_CTX ctx; 695 696 SHA1Init(&ctx); 697 SHA1Update(&ctx, IDInput->Data, IDInput->Length); 698 SHA1Final(IDOutput->Data, &ctx); 699 700 IDOutput->Length = SHA1_DIGEST_LENGTH; 701 } 702 703 KMF_RETURN 704 GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID) 705 { 706 KMF_RETURN rv = KMF_OK; 707 KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS]; 708 uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS; 709 KMF_ALGORITHM_INDEX algId; 710 int i; 711 712 if (ID == NULL || spki == NULL) 713 return (KMF_ERR_BAD_PARAMETER); 714 715 ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH); 716 if (ID->Data == NULL) 717 return (KMF_ERR_MEMORY); 718 719 ID->Length = SHA1_HASH_LENGTH; 720 721 algId = x509_algoid_to_algid(&spki->algorithm.algorithm); 722 if (algId == KMF_ALGID_NONE) 723 return (KMF_ERR_BAD_ALGORITHM); 724 725 rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts); 726 if (rv != KMF_OK) 727 return (rv); 728 729 /* Check the KEY algorithm */ 730 if (algId == KMF_ALGID_RSA) { 731 create_id_hash(&KeyParts[KMF_RSA_MODULUS], ID); 732 } else if (algId == KMF_ALGID_DSA) { 733 create_id_hash(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID); 734 } else if (algId == KMF_ALGID_SHA1WithECDSA || 735 algId == KMF_ALGID_ECDSA) { 736 create_id_hash(&KeyParts[KMF_ECDSA_POINT], ID); 737 } else { 738 /* We only support RSA and DSA keys for now */ 739 rv = KMF_ERR_BAD_ALGORITHM; 740 } 741 742 for (i = 0; i < uNumKeyParts; i++) { 743 if (KeyParts[i].Data != NULL) 744 free(KeyParts[i].Data); 745 } 746 747 if (rv != KMF_OK && ID->Data != NULL) { 748 free(ID->Data); 749 ID->Data = NULL; 750 ID->Length = 0; 751 } 752 753 return (rv); 754 } 755 756 /* 757 * For PKCS1 encoding (necessary for RSA signatures), we 758 * must prepend the following prefixes before computing 759 * the digest. 760 */ 761 static uchar_t SHA1_DER_PREFIX[] = { 762 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 763 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 764 }; 765 static uchar_t MD5_DER_PREFIX[] = { 766 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 767 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 768 0x04, 0x10 769 }; 770 static uchar_t SHA256_DER_PREFIX[] = {0x30, 0x31, 0x30, 0x0d, 771 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 772 0x00, 0x04, 0x20}; 773 774 static uchar_t SHA384_DER_PREFIX[] = {0x30, 0x41, 0x30, 0x0d, 775 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 776 0x00, 0x04, 0x30}; 777 778 static uchar_t SHA512_DER_PREFIX[] = {0x30, 0x51, 0x30, 0x0d, 779 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 780 0x00, 0x04, 0x40}; 781 782 #define MAX_SHA2_DIGEST_LENGTH 64 783 /* 784 * Compute hashes using metaslot (or softtoken). 785 * Not all hardware tokens support the combined HASH + RSA/EC 786 * Signing operations so it is safer to separate the hashing 787 * from the signing. This function generates a hash using a 788 * separate session. The resulting digest can be signed later. 789 */ 790 KMF_RETURN 791 PKCS_DigestData(KMF_HANDLE_T handle, 792 CK_SESSION_HANDLE hSession, 793 CK_MECHANISM_TYPE mechtype, 794 KMF_DATA *tobesigned, KMF_DATA *output, 795 boolean_t pkcs1_encoding) 796 { 797 KMF_RETURN rv = KMF_OK; 798 CK_RV ckrv; 799 CK_MECHANISM mechanism; 800 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 801 CK_BYTE outbuf[MAX_SHA2_DIGEST_LENGTH + 802 sizeof (SHA512_DER_PREFIX)]; 803 CK_ULONG outlen = sizeof (outbuf); 804 805 mechanism.mechanism = mechtype; 806 mechanism.pParameter = NULL; 807 mechanism.ulParameterLen = 0; 808 809 ckrv = C_DigestInit(hSession, &mechanism); 810 if (ckrv != CKR_OK) { 811 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 812 kmfh->lasterr.errcode = ckrv; 813 rv = KMF_ERR_INTERNAL; 814 goto end; 815 } 816 817 ckrv = C_Digest(hSession, tobesigned->Data, 818 tobesigned->Length, outbuf, &outlen); 819 if (ckrv != CKR_OK) { 820 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 821 kmfh->lasterr.errcode = ckrv; 822 rv = KMF_ERR_INTERNAL; 823 } 824 825 if (pkcs1_encoding) { 826 uchar_t *pfx; 827 int pfxlen; 828 switch (mechtype) { 829 case CKM_MD5: 830 pfx = MD5_DER_PREFIX; 831 pfxlen = sizeof (MD5_DER_PREFIX); 832 break; 833 case CKM_SHA_1: 834 pfx = SHA1_DER_PREFIX; 835 pfxlen = sizeof (SHA1_DER_PREFIX); 836 break; 837 case CKM_SHA256: 838 pfx = SHA256_DER_PREFIX; 839 pfxlen = sizeof (SHA256_DER_PREFIX); 840 break; 841 case CKM_SHA384: 842 pfx = SHA384_DER_PREFIX; 843 pfxlen = sizeof (SHA384_DER_PREFIX); 844 break; 845 case CKM_SHA512: 846 pfx = SHA512_DER_PREFIX; 847 pfxlen = sizeof (SHA512_DER_PREFIX); 848 break; 849 default: 850 rv = KMF_ERR_BAD_ALGORITHM; 851 goto end; 852 } 853 (void) memcpy(output->Data, pfx, pfxlen); 854 (void) memcpy(output->Data + pfxlen, outbuf, outlen); 855 output->Length = outlen + pfxlen; 856 } else { 857 (void) memcpy(output->Data, outbuf, outlen); 858 output->Length = outlen; 859 } 860 861 end: 862 return (rv); 863 } 864