1 /* 2 * Copyright 2007 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 #pragma ident "%Z%%M% %I% %E% SMI" 10 11 #include <kmfapiP.h> 12 #include <sha1.h> 13 #include <security/cryptoki.h> 14 15 #include <algorithm.h> 16 #include <ber_der.h> 17 18 #define MAX_PUBLIC_KEY_TEMPLATES (20) 19 #define MAX_PRIVATE_KEY_TEMPLATES (24) 20 #define MAX_SECRET_KEY_TEMPLATES (24) 21 22 static KMF_RETURN 23 create_pk11_session(CK_SESSION_HANDLE *sessionp, CK_MECHANISM_TYPE wanted_mech, 24 CK_FLAGS wanted_flags) 25 { 26 CK_RV rv; 27 KMF_RETURN ret; 28 KMF_RETURN kmf_rv = KMF_OK; 29 CK_SLOT_ID_PTR pSlotList; 30 CK_ULONG pulCount; 31 CK_MECHANISM_INFO info; 32 int i; 33 34 ret = init_pk11(); 35 36 if (ret != KMF_OK) 37 return (ret); 38 39 rv = C_GetSlotList(0, NULL, &pulCount); 40 if (rv != CKR_OK) { 41 kmf_rv = KMF_ERR_UNINITIALIZED; 42 goto out; 43 } 44 45 pSlotList = (CK_SLOT_ID_PTR) malloc(pulCount * sizeof (CK_SLOT_ID)); 46 if (pSlotList == NULL) { 47 kmf_rv = KMF_ERR_MEMORY; 48 goto out; 49 } 50 51 rv = C_GetSlotList(0, pSlotList, &pulCount); 52 if (rv != CKR_OK) { 53 kmf_rv = KMF_ERR_UNINITIALIZED; 54 goto out; 55 } 56 57 for (i = 0; i < pulCount; i++) { 58 rv = C_GetMechanismInfo(pSlotList[i], wanted_mech, &info); 59 if (rv == CKR_OK && (info.flags & wanted_flags)) 60 break; 61 } 62 if (i < pulCount) { 63 rv = C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION, 64 NULL, NULL, sessionp); 65 66 if (rv != CKR_OK) { 67 kmf_rv = KMF_ERR_UNINITIALIZED; 68 } 69 } else { 70 kmf_rv = KMF_ERR_UNINITIALIZED; 71 } 72 73 out: 74 if (pSlotList != NULL) 75 free(pSlotList); 76 return (kmf_rv); 77 78 } 79 80 /* 81 * Name: PKCS_AddTemplate 82 * 83 * Description: 84 * Adds a CK_ATTRIBUTE value to an existing array of CK_ATTRIBUTES. Will 85 * not expand the array beyond the maximum specified size. 86 * 87 * Returns: 88 * TRUE - Attribute value succesfully added. 89 * FALSE - Maximum array size would be exceded. 90 */ 91 static int 92 PKCS_AddTemplate(CK_ATTRIBUTE *pTemplate, 93 CK_ULONG *ckNumTemplates, 94 CK_ULONG ckMaxTemplates, 95 CK_ATTRIBUTE_TYPE ckAttribCode, 96 CK_BYTE * pckBuffer, 97 CK_ULONG ckBufferLen) 98 { 99 if (*ckNumTemplates >= ckMaxTemplates) { 100 return (FALSE); 101 } 102 103 pTemplate[*ckNumTemplates].type = ckAttribCode; 104 pTemplate[*ckNumTemplates].pValue = pckBuffer; 105 pTemplate[*ckNumTemplates].ulValueLen = ckBufferLen; 106 (*ckNumTemplates)++; 107 108 return (TRUE); 109 } 110 111 /* 112 * Convert an SPKI data record to PKCS#11 113 * public key object. 114 */ 115 static KMF_RETURN 116 PKCS_CreatePublicKey( 117 const KMF_X509_SPKI *pKey, 118 CK_SESSION_HANDLE ckSession, 119 CK_OBJECT_HANDLE *pckPublicKey) 120 { 121 KMF_RETURN mrReturn = KMF_OK; 122 CK_RV ckRv; 123 124 CK_ATTRIBUTE ckTemplate[MAX_PUBLIC_KEY_TEMPLATES]; 125 CK_ULONG ckNumTemplates = 0; 126 127 /* Common object attributes */ 128 CK_OBJECT_CLASS ckObjClass = CKO_PUBLIC_KEY; 129 CK_BBOOL ckToken = 0; 130 CK_BBOOL ckPrivate = 0; 131 132 /* Common key attributes */ 133 CK_KEY_TYPE ckKeyType; 134 CK_BBOOL ckDerive = CK_FALSE; 135 136 /* Common public key attributes */ 137 CK_BBOOL ckEncrypt = 1; 138 CK_BBOOL ckVerify = 1; 139 140 CK_BBOOL ckVerifyRecover = CK_FALSE; 141 CK_BBOOL ckWrap = CK_FALSE; 142 143 /* Key part array */ 144 KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS]; 145 uint32_t i, uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS; 146 KMF_ALGORITHM_INDEX AlgorithmId; 147 148 /* Parse the keyblob */ 149 (void) memset(KeyParts, 0, sizeof (KeyParts)); 150 151 AlgorithmId = x509_algoid_to_algid( 152 (KMF_OID *)&pKey->algorithm.algorithm); 153 if (AlgorithmId == KMF_ALGID_NONE) 154 return (KMF_ERR_BAD_ALGORITHM); 155 156 mrReturn = ExtractSPKIData(pKey, AlgorithmId, KeyParts, &uNumKeyParts); 157 158 if (mrReturn != KMF_OK) 159 return (mrReturn); 160 161 /* Fill in the common object attributes */ 162 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 163 MAX_PUBLIC_KEY_TEMPLATES, CKA_CLASS, (CK_BYTE *)&ckObjClass, 164 sizeof (ckObjClass)) || 165 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 166 MAX_PUBLIC_KEY_TEMPLATES, CKA_TOKEN, (CK_BYTE *)&ckToken, 167 sizeof (ckToken)) || 168 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 169 MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIVATE, (CK_BYTE *)&ckPrivate, 170 sizeof (ckPrivate))) { 171 mrReturn = KMF_ERR_INTERNAL; 172 goto cleanup; 173 } 174 175 /* Fill in the common key attributes */ 176 if (!pkcs_algid_to_keytype(AlgorithmId, &ckKeyType)) { 177 goto cleanup; 178 } 179 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 180 MAX_PUBLIC_KEY_TEMPLATES, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType, 181 sizeof (ckKeyType)) || 182 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 183 MAX_PUBLIC_KEY_TEMPLATES, CKA_DERIVE, (CK_BYTE *)&ckDerive, 184 sizeof (ckDerive))) { 185 mrReturn = KMF_ERR_INTERNAL; 186 goto cleanup; 187 } 188 189 /* Add common public key attributes */ 190 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 191 MAX_PUBLIC_KEY_TEMPLATES, CKA_ENCRYPT, (CK_BYTE *)&ckEncrypt, 192 sizeof (ckEncrypt)) || 193 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 194 MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY, (CK_BYTE *)&ckVerify, 195 sizeof (ckVerify)) || 196 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 197 MAX_PUBLIC_KEY_TEMPLATES, CKA_VERIFY_RECOVER, 198 (CK_BYTE *)&ckVerifyRecover, sizeof (ckVerifyRecover)) || 199 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 200 MAX_PUBLIC_KEY_TEMPLATES, CKA_WRAP, (CK_BYTE *)&ckWrap, 201 sizeof (ckWrap))) { 202 mrReturn = KMF_ERR_INTERNAL; 203 goto cleanup; 204 } 205 206 /* Add algorithm specific attributes */ 207 switch (ckKeyType) { 208 case CKK_RSA: 209 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 210 MAX_PUBLIC_KEY_TEMPLATES, CKA_MODULUS, 211 (CK_BYTE *)KeyParts[KMF_RSA_MODULUS].Data, 212 (CK_ULONG)KeyParts[KMF_RSA_MODULUS].Length) || 213 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 214 MAX_PUBLIC_KEY_TEMPLATES, CKA_PUBLIC_EXPONENT, 215 (CK_BYTE *)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Data, 216 (CK_ULONG)KeyParts[KMF_RSA_PUBLIC_EXPONENT].Length)) { 217 mrReturn = KMF_ERR_INTERNAL; 218 goto cleanup; 219 } 220 break; 221 case CKK_DSA: 222 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 223 MAX_PUBLIC_KEY_TEMPLATES, CKA_PRIME, 224 (CK_BYTE *)KeyParts[KMF_DSA_PRIME].Data, 225 (CK_ULONG)KeyParts[KMF_DSA_PRIME].Length) || 226 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 227 MAX_PUBLIC_KEY_TEMPLATES, CKA_SUBPRIME, 228 (CK_BYTE *)KeyParts[KMF_DSA_SUB_PRIME].Data, 229 (CK_ULONG)KeyParts[KMF_DSA_SUB_PRIME].Length) || 230 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 231 MAX_PUBLIC_KEY_TEMPLATES, CKA_BASE, 232 (CK_BYTE *)KeyParts[KMF_DSA_BASE].Data, 233 (CK_ULONG)KeyParts[KMF_DSA_BASE].Length) || 234 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 235 MAX_PUBLIC_KEY_TEMPLATES, CKA_VALUE, 236 (CK_BYTE *)KeyParts[KMF_DSA_PUBLIC_VALUE].Data, 237 (CK_ULONG)KeyParts[KMF_DSA_PUBLIC_VALUE].Length)) { 238 mrReturn = KMF_ERR_INTERNAL; 239 goto cleanup; 240 } 241 break; 242 default: 243 mrReturn = KMF_ERR_BAD_PARAMETER; 244 } 245 246 if (mrReturn == KMF_OK) { 247 /* Instantiate the object */ 248 ckRv = C_CreateObject(ckSession, ckTemplate, 249 ckNumTemplates, pckPublicKey); 250 if (ckRv != CKR_OK) 251 mrReturn = KMF_ERR_INTERNAL; 252 } 253 254 cleanup: 255 for (i = 0; i < uNumKeyParts; i++) { 256 kmf_free_data(&KeyParts[i]); 257 } 258 259 return (mrReturn); 260 } 261 262 /* 263 * PKCS_AcquirePublicKeyHandle 264 * 265 * Given an assymetric key keyblob, attempts to find the appropriate 266 * public key. 267 * 268 * Methods of finding the public key: 269 * - Public Key with data present: 270 * Parses the key and creates a temporary session object. 271 * - Public Key with handle: 272 * The handle is type converted and returned. Validity of the handle is 273 * not checked. 274 * - Public Key with label: 275 * Attempts to find a public key with the corresponding label. 276 */ 277 KMF_RETURN 278 PKCS_AcquirePublicKeyHandle(CK_SESSION_HANDLE ckSession, 279 const KMF_X509_SPKI *pKey, 280 CK_KEY_TYPE ckRequestedKeyType, 281 CK_OBJECT_HANDLE *pckKeyHandle, 282 KMF_BOOL *pbTemporary) 283 { 284 KMF_RETURN mrReturn = KMF_OK; 285 286 287 /* Key searching variables */ 288 CK_OBJECT_HANDLE ckKeyHandle; 289 CK_OBJECT_CLASS ckObjClass; 290 CK_KEY_TYPE ckKeyType; 291 CK_ATTRIBUTE ckTemplate[3]; 292 CK_ULONG ckNumTemplates; 293 static const CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) / 294 sizeof (CK_ATTRIBUTE)); 295 CK_RV ckRv; 296 297 /* Extract the data from the SPKI into individual fields */ 298 mrReturn = PKCS_CreatePublicKey(pKey, ckSession, &ckKeyHandle); 299 if (mrReturn != KMF_OK) 300 return (mrReturn); 301 302 *pbTemporary = KMF_TRUE; 303 304 /* Fetch the key class and algorithm from the object */ 305 ckNumTemplates = 0; 306 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 307 ckMaxTemplates, CKA_CLASS, (CK_BYTE *)&ckObjClass, 308 sizeof (ckObjClass)) || 309 !PKCS_AddTemplate(ckTemplate, &ckNumTemplates, 310 ckMaxTemplates, CKA_KEY_TYPE, (CK_BYTE *)&ckKeyType, 311 sizeof (ckKeyType))) { 312 return (KMF_ERR_INTERNAL); 313 } 314 ckRv = C_GetAttributeValue(ckSession, ckKeyHandle, 315 ckTemplate, ckNumTemplates); 316 if (ckRv != CKR_OK) { 317 return (ckRv); 318 } 319 320 /* Make sure the results match the expected values */ 321 if ((ckKeyType != ckRequestedKeyType) || 322 (ckObjClass != CKO_PUBLIC_KEY)) { 323 if (*pbTemporary == KMF_TRUE) { 324 (void) C_DestroyObject(ckSession, ckKeyHandle); 325 } 326 327 return (KMF_ERR_BAD_KEY_FORMAT); 328 } 329 330 /* Set the return values */ 331 *pckKeyHandle = ckKeyHandle; 332 333 return (KMF_OK); 334 } 335 336 KMF_SIGNATURE_MODE 337 PKCS_GetDefaultSignatureMode(KMF_ALGORITHM_INDEX AlgId) 338 { 339 KMF_SIGNATURE_MODE AlgMode; 340 341 switch (AlgId) { 342 case KMF_ALGID_RSA: 343 case KMF_ALGID_MD5WithRSA: 344 case KMF_ALGID_MD2WithRSA: 345 case KMF_ALGID_SHA1WithRSA: 346 AlgMode = KMF_ALGMODE_PKCS1_EMSA_V15; 347 break; 348 default: 349 AlgMode = KMF_ALGMODE_NONE; 350 break; 351 } 352 353 return (AlgMode); 354 } 355 356 KMF_RETURN 357 PKCS_VerifyData(KMF_HANDLE_T kmfh, 358 KMF_ALGORITHM_INDEX AlgorithmId, 359 KMF_X509_SPKI *keyp, 360 KMF_DATA *data, 361 KMF_DATA *signed_data) 362 { 363 KMF_RETURN rv = KMF_OK; 364 PKCS_ALGORITHM_MAP *pAlgMap = NULL; 365 CK_RV ckRv; 366 CK_MECHANISM ckMechanism; 367 CK_OBJECT_HANDLE ckKeyHandle; 368 KMF_BOOL bTempKey; 369 CK_SESSION_HANDLE ckSession = 0; 370 371 if (AlgorithmId == KMF_ALGID_NONE) 372 return (KMF_ERR_BAD_ALGORITHM); 373 374 pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, 375 AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId)); 376 377 if (!pAlgMap) 378 return (KMF_ERR_BAD_ALGORITHM); 379 380 rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism, 381 CKF_VERIFY); 382 383 if (rv != KMF_OK) 384 return (rv); 385 386 /* Fetch the verifying key */ 387 rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp, 388 pAlgMap->key_type, &ckKeyHandle, &bTempKey); 389 390 if (rv != KMF_OK) { 391 (void) C_CloseSession(ckSession); 392 return (rv); 393 } 394 395 ckMechanism.mechanism = pAlgMap->pkcs_mechanism; 396 ckMechanism.pParameter = NULL; 397 ckMechanism.ulParameterLen = 0; 398 399 ckRv = C_VerifyInit(ckSession, &ckMechanism, ckKeyHandle); 400 if (ckRv != CKR_OK) { 401 if (bTempKey) 402 (void) C_DestroyObject(ckSession, ckKeyHandle); 403 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 404 kmfh->lasterr.errcode = ckRv; 405 (void) C_CloseSession(ckSession); 406 return (KMF_ERR_INTERNAL); 407 } 408 409 ckRv = C_Verify(ckSession, (CK_BYTE *)data->Data, 410 (CK_ULONG)data->Length, 411 (CK_BYTE *)signed_data->Data, 412 (CK_ULONG)signed_data->Length); 413 414 if (ckRv != CKR_OK) { 415 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 416 kmfh->lasterr.errcode = ckRv; 417 rv = KMF_ERR_INTERNAL; 418 } 419 if (bTempKey) 420 (void) C_DestroyObject(ckSession, ckKeyHandle); 421 422 (void) C_CloseSession(ckSession); 423 return (rv); 424 425 } 426 427 KMF_RETURN 428 PKCS_EncryptData(KMF_HANDLE_T kmfh, 429 KMF_ALGORITHM_INDEX AlgorithmId, 430 KMF_X509_SPKI *keyp, 431 KMF_DATA *plaintext, 432 KMF_DATA *ciphertext) 433 { 434 KMF_RETURN rv = KMF_OK; 435 PKCS_ALGORITHM_MAP *pAlgMap = NULL; 436 CK_RV ckRv; 437 CK_MECHANISM ckMechanism; 438 CK_OBJECT_HANDLE ckKeyHandle; 439 KMF_BOOL bTempKey; 440 CK_SESSION_HANDLE ckSession = NULL; 441 CK_ULONG out_len = 0, in_len = 0, total_encrypted = 0; 442 uint8_t *in_data, *out_data; 443 int i, blocks, block_size; 444 CK_ATTRIBUTE ckTemplate[2]; 445 CK_ULONG ckNumTemplates; 446 CK_ULONG ckMaxTemplates = (sizeof (ckTemplate) / 447 sizeof (CK_ATTRIBUTE)); 448 449 pAlgMap = pkcs_get_alg_map(KMF_ALGCLASS_SIGNATURE, 450 AlgorithmId, PKCS_GetDefaultSignatureMode(AlgorithmId)); 451 452 if (!pAlgMap) 453 return (KMF_ERR_BAD_ALGORITHM); 454 455 rv = create_pk11_session(&ckSession, pAlgMap->pkcs_mechanism, 456 CKF_ENCRYPT); 457 458 if (rv != KMF_OK) 459 return (rv); 460 461 /* Get the public key used in encryption */ 462 rv = PKCS_AcquirePublicKeyHandle(ckSession, keyp, 463 pAlgMap->key_type, &ckKeyHandle, &bTempKey); 464 465 if (rv != KMF_OK) { 466 (void) C_CloseSession(ckSession); 467 return (rv); 468 } 469 470 /* Get the modulus length */ 471 ckNumTemplates = 0; 472 if (!PKCS_AddTemplate(ckTemplate, &ckNumTemplates, ckMaxTemplates, 473 CKA_MODULUS, (CK_BYTE *)NULL, sizeof (CK_ULONG))) { 474 if (bTempKey) 475 (void) C_DestroyObject(ckSession, ckKeyHandle); 476 (void) C_CloseSession(ckSession); 477 return (KMF_ERR_INTERNAL); 478 } 479 480 ckRv = C_GetAttributeValue(ckSession, ckKeyHandle, 481 ckTemplate, ckNumTemplates); 482 483 if (ckRv != CKR_OK) { 484 if (bTempKey) 485 (void) C_DestroyObject(ckSession, ckKeyHandle); 486 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 487 kmfh->lasterr.errcode = ckRv; 488 (void) C_CloseSession(ckSession); 489 return (KMF_ERR_INTERNAL); 490 } 491 out_len = ckTemplate[0].ulValueLen; 492 493 if (out_len > ciphertext->Length) { 494 if (bTempKey) 495 (void) C_DestroyObject(ckSession, ckKeyHandle); 496 (void) C_CloseSession(ckSession); 497 return (KMF_ERR_BUFFER_SIZE); 498 } 499 500 ckMechanism.mechanism = pAlgMap->pkcs_mechanism; 501 ckMechanism.pParameter = NULL_PTR; 502 ckMechanism.ulParameterLen = 0; 503 504 /* Compute the fixed input data length for single-part encryption */ 505 block_size = out_len - 11; 506 507 in_data = plaintext->Data; 508 out_data = ciphertext->Data; 509 510 blocks = plaintext->Length/block_size; 511 512 for (i = 0; i < blocks; i++) { 513 ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle); 514 if (ckRv != CKR_OK) { 515 if (bTempKey) 516 (void) C_DestroyObject(ckSession, ckKeyHandle); 517 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 518 kmfh->lasterr.errcode = ckRv; 519 (void) C_CloseSession(ckSession); 520 return (KMF_ERR_INTERNAL); 521 } 522 ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, block_size, 523 (CK_BYTE_PTR)out_data, &out_len); 524 525 if (ckRv != CKR_OK) { 526 if (bTempKey) 527 (void) C_DestroyObject(ckSession, ckKeyHandle); 528 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 529 kmfh->lasterr.errcode = ckRv; 530 (void) C_CloseSession(ckSession); 531 return (KMF_ERR_INTERNAL); 532 } 533 534 out_data += out_len; 535 total_encrypted += out_len; 536 in_data += block_size; 537 } 538 539 if (plaintext->Length % block_size) { 540 /* Encrypt the remaining data */ 541 ckRv = C_EncryptInit(ckSession, &ckMechanism, ckKeyHandle); 542 if (ckRv != CKR_OK) { 543 if (bTempKey) 544 (void) C_DestroyObject(ckSession, ckKeyHandle); 545 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 546 kmfh->lasterr.errcode = ckRv; 547 (void) C_CloseSession(ckSession); 548 return (KMF_ERR_INTERNAL); 549 } 550 551 in_len = plaintext->Length % block_size; 552 ckRv = C_Encrypt(ckSession, (CK_BYTE_PTR)in_data, in_len, 553 (CK_BYTE_PTR)out_data, &out_len); 554 555 if (ckRv != CKR_OK) { 556 if (bTempKey) 557 (void) C_DestroyObject(ckSession, ckKeyHandle); 558 kmfh->lasterr.kstype = KMF_KEYSTORE_PK11TOKEN; 559 kmfh->lasterr.errcode = ckRv; 560 (void) C_CloseSession(ckSession); 561 return (KMF_ERR_INTERNAL); 562 } 563 564 out_data += out_len; 565 total_encrypted += out_len; 566 in_data += in_len; 567 } 568 569 ciphertext->Length = total_encrypted; 570 571 if (bTempKey) 572 (void) C_DestroyObject(ckSession, ckKeyHandle); 573 574 (void) C_CloseSession(ckSession); 575 return (rv); 576 577 } 578 579 static void 580 DigestData(KMF_DATA *IDInput, KMF_DATA *IDOutput) 581 { 582 SHA1_CTX ctx; 583 584 SHA1Init(&ctx); 585 SHA1Update(&ctx, IDInput->Data, IDInput->Length); 586 SHA1Final(IDOutput->Data, &ctx); 587 588 IDOutput->Length = SHA1_DIGEST_LENGTH; 589 } 590 591 KMF_RETURN 592 GetIDFromSPKI(KMF_X509_SPKI *spki, KMF_DATA *ID) 593 { 594 KMF_RETURN rv = KMF_OK; 595 KMF_DATA KeyParts[KMF_MAX_PUBLIC_KEY_PARTS]; 596 uint32_t uNumKeyParts = KMF_MAX_PUBLIC_KEY_PARTS; 597 KMF_ALGORITHM_INDEX algId; 598 int i; 599 600 if (ID == NULL || spki == NULL) 601 return (KMF_ERR_BAD_PARAMETER); 602 603 ID->Data = (uchar_t *)malloc(SHA1_HASH_LENGTH); 604 if (ID->Data == NULL) 605 return (KMF_ERR_MEMORY); 606 607 ID->Length = SHA1_HASH_LENGTH; 608 609 algId = x509_algoid_to_algid(&spki->algorithm.algorithm); 610 if (algId == KMF_ALGID_NONE) 611 return (KMF_ERR_BAD_ALGORITHM); 612 613 rv = ExtractSPKIData(spki, algId, KeyParts, &uNumKeyParts); 614 if (rv != KMF_OK) 615 return (rv); 616 617 /* Check the KEY algorithm */ 618 if (algId == KMF_ALGID_RSA) { 619 DigestData(&KeyParts[KMF_RSA_MODULUS], ID); 620 } else if (algId == KMF_ALGID_DSA) { 621 DigestData(&KeyParts[KMF_DSA_PUBLIC_VALUE], ID); 622 } else { 623 /* We only support RSA and DSA keys for now */ 624 rv = KMF_ERR_BAD_ALGORITHM; 625 } 626 627 for (i = 0; i < uNumKeyParts; i++) { 628 if (KeyParts[i].Data != NULL) 629 free(KeyParts[i].Data); 630 } 631 632 if (rv != KMF_OK && ID->Data != NULL) { 633 free(ID->Data); 634 ID->Data = NULL; 635 ID->Length = 0; 636 } 637 638 return (rv); 639 } 640