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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <link.h> 30 #include <fcntl.h> 31 #include <ctype.h> 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <sys/socket.h> 36 #include <ber_der.h> 37 #include <kmfapiP.h> 38 #include <pem_encode.h> 39 #include <libgen.h> 40 #include <cryptoutil.h> 41 42 #define CERTFILE_TEMPNAME "/tmp/user.certXXXXXX" 43 #define CRLFILE_TEMPNAME "/tmp/crlXXXXXX" 44 #define X509_FORMAT_VERSION 2 45 46 static KMF_RETURN 47 get_keyalg_from_cert(KMF_DATA *cert, KMF_KEY_ALG *keyalg) 48 { 49 KMF_RETURN rv; 50 KMF_X509_CERTIFICATE *SignerCert = NULL; 51 KMF_ALGORITHM_INDEX AlgorithmId; 52 53 rv = DerDecodeSignedCertificate(cert, &SignerCert); 54 55 if (rv != KMF_OK) 56 return (rv); 57 58 /* Get the algorithm info from the signer certificate */ 59 AlgorithmId = X509_AlgorithmOidToAlgId( 60 &SignerCert->signature.algorithmIdentifier.algorithm); 61 62 switch (AlgorithmId) { 63 case KMF_ALGID_MD5WithRSA: 64 case KMF_ALGID_MD2WithRSA: 65 case KMF_ALGID_SHA1WithRSA: 66 *keyalg = KMF_RSA; 67 break; 68 case KMF_ALGID_SHA1WithDSA: 69 *keyalg = KMF_DSA; 70 break; 71 default: 72 rv = KMF_ERR_BAD_ALGORITHM; 73 } 74 75 KMF_FreeSignedCert(SignerCert); 76 free(SignerCert); 77 return (rv); 78 } 79 80 /* 81 * 82 * Name: find_private_key_by_cert 83 * 84 * Description: 85 * This function finds the corresponding private key in keystore 86 * for a certificate 87 * 88 * Parameters: 89 * handle(input) - opaque handle for KMF session 90 * params(input) - contains parameters used to find the private key 91 * SignerCertData(input) - pointer to a KMF_DATA structure containing a 92 * signer certificate 93 * key(output) - contains the found private key handle 94 * 95 * Returns: 96 * A KMF_RETURN value indicating success or specifying a particular 97 * error condition. 98 * The value KMF_OK indicates success. All other values represent 99 * an error condition. 100 * 101 */ 102 static KMF_RETURN 103 find_private_key_by_cert(KMF_HANDLE_T handle, 104 KMF_CRYPTOWITHCERT_PARAMS *params, 105 KMF_DATA *SignerCertData, 106 KMF_KEY_HANDLE *key) 107 { 108 109 KMF_RETURN ret; 110 KMF_KEY_ALG keytype; 111 KMF_PLUGIN *plugin; 112 113 if (handle == NULL || params == NULL || 114 SignerCertData == NULL || key == NULL) 115 return (KMF_ERR_BAD_PARAMETER); 116 117 (void) memset(key, 0, sizeof (KMF_KEY_HANDLE)); 118 ret = get_keyalg_from_cert(SignerCertData, &keytype); 119 if (ret != KMF_OK) 120 return (ret); 121 122 /* Find the private key from the keystore */ 123 plugin = FindPlugin(handle, params->kstype); 124 125 if (plugin != NULL && plugin->funclist->GetPrikeyByCert != NULL) { 126 CLEAR_ERROR(handle, ret); 127 return (plugin->funclist->GetPrikeyByCert(handle, 128 params, SignerCertData, key, keytype)); 129 } else { 130 return (KMF_ERR_PLUGIN_NOTFOUND); 131 } 132 133 } 134 135 static KMF_RETURN 136 check_key_usage(void *handle, 137 const KMF_DATA *cert, 138 const KMF_KU_PURPOSE purpose) 139 { 140 KMF_X509EXT_BASICCONSTRAINTS constraint; 141 KMF_BOOL critical = B_FALSE; 142 KMF_X509EXT_KEY_USAGE keyusage; 143 KMF_RETURN ret = KMF_OK; 144 145 if (handle == NULL || cert == NULL) 146 return (KMF_ERR_BAD_PARAMETER); 147 148 (void) memset(&constraint, 0, sizeof (KMF_X509EXT_BASICCONSTRAINTS)); 149 (void) memset(&keyusage, 0, sizeof (KMF_X509EXT_KEY_USAGE)); 150 151 ret = KMF_GetCertKeyUsageExt(cert, &keyusage); 152 if (ret != KMF_OK) 153 /* 154 * If absent or error, the cert is assumed to be invalid 155 * for all key usage checking. 156 */ 157 return (ret); 158 159 160 switch (purpose) { 161 case KMF_KU_SIGN_CERT: 162 /* 163 * RFC 3280: 164 * The keyCertSign bit is asserted when the subject 165 * public key is used for verifying a signature on 166 * public key certificates. If the keyCertSign bit 167 * is asserted, then the cA bit in the basic constraints 168 * extension (section 4.2.1.10) MUST also be asserted. 169 * The basic constraints extension MUST appear as a 170 * critical extension in all CA certificates that 171 * contain public keys used to validate digital 172 * signatures on certificates. 173 */ 174 ret = KMF_GetCertBasicConstraintExt(cert, &critical, 175 &constraint); 176 177 if ((ret != KMF_ERR_EXTENSION_NOT_FOUND) && (ret != KMF_OK)) { 178 /* real error */ 179 return (ret); 180 } 181 182 if ((!critical) || (!constraint.cA) || 183 (!(keyusage.KeyUsageBits & KMF_keyCertSign))) 184 return (KMF_ERR_KEYUSAGE); 185 break; 186 case KMF_KU_SIGN_DATA: 187 /* 188 * RFC 3280: 189 * The digitalSignature bit is asserted when the subject 190 * public key is used with a digital signature mechanism 191 * to support security services other than certificate 192 * signing(bit 5), or CRL signing(bit 6). 193 */ 194 if (!(keyusage.KeyUsageBits & KMF_digitalSignature)) 195 return (KMF_ERR_KEYUSAGE); 196 break; 197 case KMF_KU_ENCRYPT_DATA: 198 /* 199 * RFC 3280: 200 * The dataEncipherment bit is asserted when the subject 201 * public key is used for enciphering user data, other than 202 * cryptographic keys. 203 */ 204 if (!(keyusage.KeyUsageBits & KMF_dataEncipherment)) 205 return (KMF_ERR_KEYUSAGE); 206 break; 207 default: 208 return (KMF_ERR_BAD_PARAMETER); 209 } 210 211 return (KMF_OK); 212 } 213 214 KMF_RETURN 215 KMF_FindCert(KMF_HANDLE_T handle, KMF_FINDCERT_PARAMS *target, 216 KMF_X509_DER_CERT *kmf_cert, 217 uint32_t *num_certs) 218 { 219 KMF_PLUGIN *plugin; 220 KMF_RETURN rv = KMF_OK; 221 222 223 CLEAR_ERROR(handle, rv); 224 if (rv != KMF_OK) 225 return (rv); 226 227 if (target == NULL || num_certs == NULL) 228 return (KMF_ERR_BAD_PARAMETER); /* ILLEGAL ARGS ERROR */ 229 230 if ((target->find_cert_validity < KMF_ALL_CERTS) || 231 (target->find_cert_validity > KMF_EXPIRED_CERTS)) 232 return (KMF_ERR_BAD_PARAMETER); 233 234 plugin = FindPlugin(handle, target->kstype); 235 236 if (plugin != NULL && plugin->funclist->FindCert != NULL) { 237 return (plugin->funclist->FindCert(handle, target, 238 kmf_cert, num_certs)); 239 } 240 241 return (KMF_ERR_PLUGIN_NOTFOUND); 242 } 243 244 #define NODATA(d) (d.Data == NULL || d.Length == NULL) 245 246 KMF_RETURN 247 KMF_EncodeCertRecord(KMF_X509_CERTIFICATE *CertData, KMF_DATA *encodedCert) 248 { 249 KMF_RETURN ret; 250 251 if (CertData == NULL || encodedCert == NULL) 252 return (KMF_ERR_BAD_PARAMETER); 253 254 /* 255 * Validate that all required fields are present. 256 */ 257 if (NODATA(CertData->certificate.version) || 258 NODATA(CertData->certificate.signature.algorithm) || 259 NODATA(CertData->certificate.subjectPublicKeyInfo.subjectPublicKey) || 260 CertData->certificate.serialNumber.val == NULL || 261 CertData->certificate.serialNumber.len == 0 || 262 CertData->certificate.subject.numberOfRDNs == 0 || 263 CertData->certificate.issuer.numberOfRDNs == 0) { 264 return (KMF_ERR_INCOMPLETE_TBS_CERT); 265 } 266 267 encodedCert->Length = 0; 268 encodedCert->Data = NULL; 269 270 /* Pack the new certificate */ 271 ret = DerEncodeSignedCertificate(CertData, encodedCert); 272 273 return (ret); 274 } 275 276 /* 277 * 278 * Name: KMF_SignCertWithKey 279 * 280 * Description: 281 * This function signs a certificate using the private key and 282 * returns the result as a signed, encoded certificate in SignedCert 283 * 284 * Parameters: 285 * handle(input) - opaque handle for KMF session 286 * CertToBeSigned(input) - pointer to a KMF_DATA structure containing a 287 * DER encoded certificate to be signed 288 * Signkey(input) - pointer to private key handle needed for signing 289 * SignedCert(output) - pointer to the KMF_DATA structure containing the 290 * signed certificate 291 * 292 * Returns: 293 * A KMF_RETURN value indicating success or specifying a particular 294 * error condition. 295 * The value KMF_OK indicates success. All other values represent 296 * an error condition. 297 * 298 */ 299 KMF_RETURN 300 KMF_SignCertWithKey(KMF_HANDLE_T handle, 301 const KMF_DATA *CertToBeSigned, 302 KMF_KEY_HANDLE *Signkey, 303 KMF_DATA *SignedCert) 304 { 305 KMF_RETURN err; 306 307 CLEAR_ERROR(handle, err); 308 if (err != KMF_OK) 309 return (err); 310 311 if (CertToBeSigned == NULL || 312 Signkey == NULL || SignedCert == NULL) 313 return (KMF_ERR_BAD_PARAMETER); 314 315 err = SignCert(handle, CertToBeSigned, Signkey, SignedCert); 316 317 return (err); 318 } 319 320 /* 321 * 322 * Name: KMF_SignCertWithCert 323 * 324 * Description: 325 * This function signs a certificate using the signer cert and 326 * returns the result as a signed, encoded certificate in SignedCert 327 * 328 * Parameters: 329 * handle(input) - opaque handle for KMF session 330 * params(input) - contains parameters to be used for signing 331 * CertToBeSigned(input) - pointer to a KMF_DATA structure containing a 332 * DER encoded certificate to be signed 333 * SignerCert(input) - pointer to a KMF_DATA structure containing a 334 * signer certificate 335 * SignedCert(output) - pointer to the KMF_DATA structure containing the 336 * DER encoded signed certificate 337 * 338 * Returns: 339 * A KMF_RETURN value indicating success or specifying a particular 340 * error condition. 341 * The value KMF_OK indicates success. All other values represent 342 * an error condition. 343 * 344 */ 345 KMF_RETURN 346 KMF_SignCertWithCert(KMF_HANDLE_T handle, 347 KMF_CRYPTOWITHCERT_PARAMS *params, 348 const KMF_DATA *CertToBeSigned, 349 KMF_DATA *SignerCert, 350 KMF_DATA *SignedCert) 351 { 352 KMF_RETURN ret; 353 KMF_KEY_HANDLE Signkey; 354 355 CLEAR_ERROR(handle, ret); 356 if (ret != KMF_OK) 357 return (ret); 358 359 if (CertToBeSigned == NULL || 360 SignerCert == NULL || SignedCert == NULL) 361 return (KMF_ERR_BAD_PARAMETER); 362 363 /* check the keyUsage of signer's certificate */ 364 ret = check_key_usage(handle, SignerCert, KMF_KU_SIGN_CERT); 365 if (ret != KMF_OK) 366 return (ret); 367 368 /* 369 * Retrieve the private key from the keystore for the 370 * signer certificate. 371 */ 372 ret = find_private_key_by_cert(handle, params, SignerCert, &Signkey); 373 if (ret != KMF_OK) 374 return (ret); 375 376 ret = SignCert(handle, CertToBeSigned, &Signkey, SignedCert); 377 378 KMF_FreeKMFKey(handle, &Signkey); 379 380 return (ret); 381 } 382 383 /* 384 * 385 * Name: KMF_SignDataWithCert 386 * 387 * Description: 388 * This function signs a block of data using the signer cert and 389 * returns the the signature in output 390 * 391 * Parameters: 392 * handle(input) - opaque handle for KMF session 393 * params(input) - contains parameters to be used for signing 394 * tobesigned(input) - pointer to a KMF_DATA structure containing a 395 * the data to be signed 396 * output(output) - pointer to the KMF_DATA structure containing the 397 * signed data 398 * SignerCertData(input) - pointer to a KMF_DATA structure containing a 399 * signer certificate 400 * 401 * Returns: 402 * A KMF_RETURN value indicating success or specifying a particular 403 * error condition. 404 * The value KMF_OK indicates success. All other values represent 405 * an error condition. 406 * 407 */ 408 KMF_RETURN 409 KMF_SignDataWithCert(KMF_HANDLE_T handle, 410 KMF_CRYPTOWITHCERT_PARAMS *params, 411 KMF_DATA *tobesigned, 412 KMF_DATA *output, 413 KMF_DATA *SignerCertData) 414 { 415 416 KMF_RETURN ret; 417 KMF_KEY_HANDLE Signkey; 418 KMF_X509_CERTIFICATE *SignerCert = NULL; 419 KMF_PLUGIN *plugin; 420 KMF_ALGORITHM_INDEX AlgId; 421 KMF_DATA signature = {0, NULL}; 422 423 CLEAR_ERROR(handle, ret); 424 if (ret != KMF_OK) 425 return (ret); 426 427 if (tobesigned == NULL || 428 SignerCertData == NULL || output == NULL) 429 return (KMF_ERR_BAD_PARAMETER); 430 431 /* check the keyUsage of signer's certificate */ 432 ret = check_key_usage(handle, SignerCertData, KMF_KU_SIGN_DATA); 433 if (ret != KMF_OK) 434 return (ret); 435 436 /* 437 * Retrieve the private key from the keystore based on 438 * the signer certificate. 439 */ 440 ret = find_private_key_by_cert(handle, params, SignerCertData, 441 &Signkey); 442 if (ret != KMF_OK) { 443 goto cleanup; 444 } 445 446 ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert); 447 if (ret != KMF_OK) 448 goto cleanup; 449 450 plugin = FindPlugin(handle, Signkey.kstype); 451 if (plugin != NULL && plugin->funclist->SignData != NULL) { 452 ret = plugin->funclist->SignData(handle, &Signkey, 453 CERT_ALG_OID(SignerCert), tobesigned, output); 454 if (ret != KMF_OK) 455 goto cleanup; 456 457 AlgId = X509_AlgorithmOidToAlgId(CERT_ALG_OID(SignerCert)); 458 459 /* 460 * For DSA, NSS returns an encoded signature. Decode the 461 * signature as DSA signature should be 40-byte long. 462 */ 463 if ((AlgId == KMF_ALGID_SHA1WithDSA) && 464 (plugin->type == KMF_KEYSTORE_NSS)) { 465 ret = DerDecodeDSASignature(output, &signature); 466 if (ret != KMF_OK) { 467 goto cleanup; 468 } else { 469 output->Length = signature.Length; 470 (void) memcpy(output->Data, signature.Data, 471 signature.Length); 472 } 473 } else if (AlgId == KMF_ALGID_NONE) { 474 ret = KMF_ERR_BAD_ALGORITHM; 475 } 476 } else { 477 ret = KMF_ERR_PLUGIN_NOTFOUND; 478 } 479 480 cleanup: 481 if (signature.Data) 482 free(signature.Data); 483 484 KMF_FreeKMFKey(handle, &Signkey); 485 if (SignerCert != NULL) { 486 KMF_FreeSignedCert(SignerCert); 487 free(SignerCert); 488 } 489 490 return (ret); 491 } 492 493 /* 494 * 495 * Name: KMF_VerifyCertWithKey 496 * 497 * Description: 498 * This function verifies that the CertToBeVerified was signed 499 * using a specific private key and that the certificate has not 500 * been altered since it was signed using that private key 501 * 502 * Parameters: 503 * handle(input) - opaque handle for KMF session 504 * KMFKey(input) - holds public key information for verification 505 * CertToBeVerified(input) - A signed certificate whose signature 506 * is to be verified 507 * 508 * Returns: 509 * A KMF_RETURN value indicating success or specifying a particular 510 * error condition. The value KMF_OK indicates success. All other 511 * values represent an error condition. 512 */ 513 KMF_RETURN 514 KMF_VerifyCertWithKey(KMF_HANDLE_T handle, 515 KMF_KEY_HANDLE *KMFKey, 516 const KMF_DATA *CertToBeVerified) 517 { 518 KMF_RETURN err; 519 KMF_DATA derkey = {0, NULL}; 520 KMF_PLUGIN *plugin; 521 522 CLEAR_ERROR(handle, err); 523 if (err != KMF_OK) 524 return (err); 525 526 if (KMFKey == NULL || 527 CertToBeVerified == NULL) 528 return (KMF_ERR_BAD_PARAMETER); 529 530 /* The keystore must extract the pubkey data */ 531 plugin = FindPlugin(handle, KMFKey->kstype); 532 if (plugin != NULL && plugin->funclist->EncodePubkeyData != NULL) { 533 err = plugin->funclist->EncodePubkeyData(handle, 534 KMFKey, &derkey); 535 } else { 536 return (KMF_ERR_PLUGIN_NOTFOUND); 537 } 538 539 if (err == KMF_OK && derkey.Length > 0) { 540 /* check the caller and do other setup for this SPI call */ 541 err = VerifyCertWithKey(handle, &derkey, CertToBeVerified); 542 543 if (derkey.Data != NULL) 544 free(derkey.Data); 545 } 546 547 return (err); 548 } 549 550 /* 551 * 552 * Name: KMF_VerifyCertWithCert 553 * 554 * Description: 555 * Function to verify the signature of a signed certificate 556 * 557 * Parameters: 558 * handle - pointer to KMF handle 559 * CertToBeVerified(input) - pointer to the signed certificate 560 * SignerCert(input) - pointer to certificate used in signing 561 * 562 * Returns: 563 * A KMF_RETURN value. 564 * The value KMF_OK indicates success. 565 * All other values represent an error condition. 566 */ 567 KMF_RETURN 568 KMF_VerifyCertWithCert(KMF_HANDLE_T handle, 569 const KMF_DATA *CertToBeVerified, 570 const KMF_DATA *SignerCert) 571 { 572 KMF_RETURN ret; 573 574 CLEAR_ERROR(handle, ret); 575 if (ret != KMF_OK) 576 return (ret); 577 578 if (CertToBeVerified == NULL || 579 SignerCert == NULL) 580 return (KMF_ERR_BAD_PARAMETER); 581 582 /* check the keyUsage of signer's certificate */ 583 ret = check_key_usage(handle, SignerCert, KMF_KU_SIGN_CERT); 584 if (ret != KMF_OK) 585 return (ret); 586 587 ret = VerifyCertWithCert(handle, CertToBeVerified, SignerCert); 588 return (ret); 589 } 590 591 /* 592 * 593 * Name: KMF_VerifyDataWithCert 594 * 595 * Description: 596 * This function verifies the signature of a block of data using a signer 597 * certificate. 598 * 599 * Parameters: 600 * handle(input) - opaque handle for KMF session 601 * indata(input) - pointer to the block of data whose signature 602 * is to be verified 603 * insig(input) - pointer to the signature to be verified 604 * SignerCert(input) - pointer to signer cert for verification 605 * 606 * Returns: 607 * A KMF_RETURN value indicating success or specifying a particular 608 * error condition. 609 * The value KMF_OK indicates success. All other values represent 610 * an error condition. 611 * 612 */ 613 KMF_RETURN 614 KMF_VerifyDataWithCert(KMF_HANDLE_T handle, 615 KMF_DATA *indata, 616 KMF_DATA *insig, 617 const KMF_DATA *SignerCert) 618 { 619 KMF_RETURN ret; 620 621 CLEAR_ERROR(handle, ret); 622 if (ret != KMF_OK) 623 return (ret); 624 625 if (SignerCert == NULL || 626 indata == NULL || insig == NULL) 627 return (KMF_ERR_BAD_PARAMETER); 628 629 /* check the keyUsage of signer's certificate */ 630 ret = check_key_usage(handle, SignerCert, KMF_KU_SIGN_DATA); 631 if (ret != KMF_OK) 632 return (ret); 633 634 return (VerifyDataWithCert(handle, indata, insig, SignerCert)); 635 } 636 637 /* 638 * Name: KMF_EncryptWithCert 639 * 640 * Description: 641 * Uses the public key from the cert to encrypt the plaintext 642 * into the ciphertext. 643 * 644 * Parameters: 645 * handle(input) - opaque handle for KMF session 646 * cert(input) - pointer to a DER encoded certificate for encryption 647 * by using its public key 648 * plaintext(input) - pointer to the plaintext to be encrypted 649 * ciphertext(output) - pointer to the ciphertext contains 650 * encrypted data 651 * 652 * Returns: 653 * A KMF_RETURN value indicating success or specifying a particular 654 * error condition. 655 * The value KMF_OK indicates success. All other values represent 656 * an error condition. 657 * 658 */ 659 KMF_RETURN 660 KMF_EncryptWithCert(KMF_HANDLE_T handle, 661 KMF_DATA *cert, 662 KMF_DATA *plaintext, 663 KMF_DATA *ciphertext) 664 { 665 KMF_RETURN ret; 666 667 CLEAR_ERROR(handle, ret); 668 if (ret != KMF_OK) 669 return (ret); 670 671 if (cert == NULL || 672 plaintext == NULL || ciphertext == NULL) 673 return (KMF_ERR_BAD_PARAMETER); 674 675 /* check the keyUsage of the certificate */ 676 ret = check_key_usage(handle, cert, KMF_KU_ENCRYPT_DATA); 677 if (ret != KMF_OK) 678 return (ret); 679 680 return (EncryptWithCert(handle, cert, plaintext, ciphertext)); 681 } 682 683 /* 684 * Name: KMF_DecryptWithCert 685 * 686 * Description: 687 * Uses the private key associated with the cert to decrypt 688 * the ciphertext into the plaintext. 689 * 690 * Parameters: 691 * handle(input) - opaque handle for KMF session 692 * params(input) - contains parameters to be used to find the private 693 * key for decryption 694 * cert(input) - pointer to a DER encoded certificate for decryption 695 * by using its private key 696 * ciphertext(input) - pointer to the ciphertext contains to be 697 * decrypted data 698 * plaintext(output) - pointer to the plaintext after decryption 699 * 700 * Returns: 701 * A KMF_RETURN value indicating success or specifying a particular 702 * error condition. 703 * The value KMF_OK indicates success. All other values represent 704 * an error condition. 705 * 706 */ 707 KMF_RETURN 708 KMF_DecryptWithCert(KMF_HANDLE_T handle, 709 KMF_CRYPTOWITHCERT_PARAMS *params, 710 KMF_DATA *cert, 711 KMF_DATA *ciphertext, 712 KMF_DATA *plaintext) 713 { 714 KMF_RETURN ret; 715 KMF_KEY_HANDLE Signkey; 716 KMF_X509_CERTIFICATE *x509cert = NULL; 717 KMF_X509_SPKI *spki_ptr; 718 KMF_PLUGIN *plugin; 719 KMF_ALGORITHM_INDEX AlgorithmId; 720 721 722 CLEAR_ERROR(handle, ret); 723 if (ret != KMF_OK) 724 return (ret); 725 726 if (cert == NULL || 727 plaintext == NULL || ciphertext == NULL) 728 return (KMF_ERR_BAD_PARAMETER); 729 730 /* check the keyUsage of the certificate */ 731 ret = check_key_usage(handle, cert, KMF_KU_ENCRYPT_DATA); 732 if (ret != KMF_OK) 733 return (ret); 734 735 /* 736 * Retrieve the private key from the keystore based on 737 * the certificate. 738 */ 739 ret = find_private_key_by_cert(handle, params, cert, &Signkey); 740 if (ret != KMF_OK) { 741 return (ret); 742 } 743 744 /* Decode the cert so we can get the alogorithm */ 745 ret = DerDecodeSignedCertificate(cert, &x509cert); 746 if (ret != KMF_OK) 747 goto cleanup; 748 749 spki_ptr = &x509cert->certificate.subjectPublicKeyInfo; 750 AlgorithmId = X509_AlgorithmOidToAlgId((KMF_OID *) 751 &spki_ptr->algorithm.algorithm); 752 753 /* DSA does not support decrypt */ 754 if (AlgorithmId == KMF_ALGID_DSA) { 755 ret = KMF_ERR_BAD_ALGORITHM; 756 goto cleanup; 757 } 758 759 plugin = FindPlugin(handle, Signkey.kstype); 760 761 if (plugin != NULL && plugin->funclist->DecryptData != NULL) { 762 ret = plugin->funclist->DecryptData(handle, 763 &Signkey, &spki_ptr->algorithm.algorithm, 764 ciphertext, plaintext); 765 } else { 766 ret = KMF_ERR_PLUGIN_NOTFOUND; 767 } 768 769 cleanup: 770 KMF_FreeKMFKey(handle, &Signkey); 771 KMF_FreeSignedCert(x509cert); 772 free(x509cert); 773 774 return (ret); 775 } 776 777 KMF_RETURN 778 KMF_StoreCert(KMF_HANDLE_T handle, KMF_STORECERT_PARAMS *target, 779 KMF_DATA *pcert) 780 { 781 KMF_PLUGIN *plugin; 782 KMF_RETURN ret; 783 784 CLEAR_ERROR(handle, ret); 785 if (ret != KMF_OK) 786 return (ret); 787 788 if (target == NULL || pcert == NULL) 789 return (KMF_ERR_BAD_PARAMETER); 790 791 plugin = FindPlugin(handle, target->kstype); 792 793 if (plugin != NULL && plugin->funclist->StoreCert != NULL) { 794 return (plugin->funclist->StoreCert(handle, target, pcert)); 795 } else { 796 return (KMF_ERR_PLUGIN_NOTFOUND); 797 } 798 } 799 800 KMF_RETURN 801 KMF_ImportCert(KMF_HANDLE_T handle, KMF_IMPORTCERT_PARAMS *target) 802 { 803 KMF_PLUGIN *plugin; 804 KMF_RETURN ret; 805 806 CLEAR_ERROR(handle, ret); 807 if (ret != KMF_OK) 808 return (ret); 809 810 if (target == NULL) 811 return (KMF_ERR_BAD_PARAMETER); 812 813 plugin = FindPlugin(handle, target->kstype); 814 815 if (plugin != NULL && plugin->funclist->ImportCert != NULL) { 816 return (plugin->funclist->ImportCert(handle, target)); 817 } else { 818 return (KMF_ERR_PLUGIN_NOTFOUND); 819 } 820 } 821 822 KMF_RETURN 823 KMF_DeleteCertFromKeystore(KMF_HANDLE_T handle, KMF_DELETECERT_PARAMS *target) 824 { 825 KMF_PLUGIN *plugin; 826 KMF_RETURN ret; 827 828 CLEAR_ERROR(handle, ret); 829 if (ret != KMF_OK) 830 return (ret); 831 832 if (target == NULL || 833 (target->find_cert_validity < KMF_ALL_CERTS) || 834 (target->find_cert_validity > KMF_EXPIRED_CERTS)) 835 return (KMF_ERR_BAD_PARAMETER); 836 837 plugin = FindPlugin(handle, target->kstype); 838 839 if (plugin != NULL && plugin->funclist->DeleteCert != NULL) { 840 return (plugin->funclist->DeleteCert(handle, target)); 841 } else { 842 return (KMF_ERR_PLUGIN_NOTFOUND); 843 } 844 } 845 846 /* 847 * This function gets the CRL URI entries from the certificate's Distribution 848 * points extension, and downloads the CRL file. The function also returns 849 * the URI string and the format of the CRL file. The caller should free 850 * the space allocated for the returned URI string. 851 */ 852 static KMF_RETURN 853 cert_get_crl(KMF_HANDLE_T handle, const KMF_DATA *cert, char *proxy, 854 char *filename, char **retn_uri, KMF_ENCODE_FORMAT *format) 855 { 856 KMF_RETURN ret = KMF_OK; 857 KMF_X509EXT_CRLDISTPOINTS crl_dps; 858 boolean_t done = B_FALSE; 859 char uri[1024]; 860 char *proxyname = NULL; 861 char *proxy_port_s = NULL; 862 int proxy_port = 0; 863 int i, j; 864 char *path = NULL; 865 866 if (handle == NULL || cert == NULL || filename == NULL || 867 retn_uri == NULL || format == NULL) 868 return (KMF_ERR_BAD_PARAMETER); 869 870 /* Get the proxy info */ 871 if (proxy != NULL) { 872 proxyname = strtok(proxy, ":"); 873 proxy_port_s = strtok(NULL, "\0"); 874 if (proxy_port_s != NULL) { 875 proxy_port = strtol(proxy_port_s, NULL, 0); 876 } else { 877 proxy_port = 8080; /* default */ 878 } 879 } 880 881 /* 882 * Get the CRL URI from the certificate's CRL Distribution 883 * Points extension and download the CRL file. There maybe more than 884 * one CRL URI entries in the DP extension, so we will continue 885 * the process until a CRL file is sucessfully downloaded or we 886 * are running out the CRL URI's. 887 */ 888 ret = KMF_GetCertCRLDistributionPointsExt((const KMF_DATA *)cert, 889 &crl_dps); 890 if (ret != KMF_OK) 891 goto out; 892 893 for (i = 0; i < crl_dps.number; i++) { 894 KMF_CRL_DIST_POINT *dp = &(crl_dps.dplist[i]); 895 KMF_GENERALNAMES *fullname = &(dp->name.full_name); 896 KMF_DATA *data; 897 898 if (done) 899 break; 900 for (j = 0; j < fullname->number; j++) { 901 data = &(fullname->namelist[j].name); 902 (void) memcpy(uri, data->Data, data->Length); 903 uri[data->Length] = '\0'; 904 ret = KMF_DownloadCRL(handle, uri, proxyname, 905 proxy_port, 30, filename, format); 906 if (ret == KMF_OK) { 907 done = B_TRUE; 908 path = malloc(data->Length + 1); 909 if (path == NULL) { 910 ret = KMF_ERR_MEMORY; 911 goto out; 912 } 913 (void) strncpy(path, uri, data->Length); 914 *retn_uri = path; 915 break; 916 } 917 } 918 } 919 920 out: 921 KMF_FreeCRLDistributionPoints(&crl_dps); 922 return (ret); 923 } 924 925 static KMF_RETURN 926 cert_crl_check(KMF_HANDLE_T handle, 927 KMF_VALIDATECERT_PARAMS *params, 928 KMF_DATA *user_cert, 929 KMF_DATA *issuer_cert) 930 { 931 KMF_POLICY_RECORD *policy; 932 KMF_RETURN ret = KMF_OK; 933 KMF_IMPORTCRL_PARAMS icrl_params; 934 KMF_FINDCERTINCRL_PARAMS fcrl_params; 935 KMF_OPENSSL_PARAMS ssl_params; 936 KMF_VERIFYCRL_PARAMS vcrl_params; 937 char user_certfile[MAXPATHLEN]; 938 char crlfile_tmp[MAXPATHLEN]; 939 KMF_CHECKCRLDATE_PARAMS ccrldate_params; 940 char *basefilename = NULL; 941 char *dir = NULL; 942 char *crlfilename = NULL; 943 char *proxy = NULL; 944 char *uri = NULL; 945 KMF_ENCODE_FORMAT format; 946 947 if (handle == NULL || params == NULL || 948 user_cert == NULL || issuer_cert == NULL) 949 return (KMF_ERR_BAD_PARAMETER); 950 951 policy = handle->policy; 952 953 (void) memset(&icrl_params, 0, sizeof (icrl_params)); 954 (void) memset(&vcrl_params, 0, sizeof (vcrl_params)); 955 (void) memset(&ccrldate_params, 0, sizeof (ccrldate_params)); 956 (void) memset(&fcrl_params, 0, sizeof (fcrl_params)); 957 (void) memset(&ssl_params, 0, sizeof (ssl_params)); 958 959 /* 960 * If the get-crl-uri policy is TRUE, then download the CRL 961 * file first. The newly downloaded file will be stored in the 962 * NSS internal database for NSS keystore, and stored in a file for 963 * the File-based CRL plugins (OpenSSL and PKCS11). 964 * 965 * For file-based plugins, if the get-crl-uri policy is FALSE, 966 * then the caller should provide a CRL file in the policy. 967 * Also, after this step is done, the "crlfilename" variable should 968 * contain the proper CRL file to be used for the rest of CRL 969 * validation process. 970 */ 971 basefilename = policy->validation_info.crl_info.basefilename; 972 dir = policy->validation_info.crl_info.directory; 973 if (policy->validation_info.crl_info.get_crl_uri) { 974 /* 975 * Create a temporary file to hold the new CRL file initially. 976 */ 977 (void) strlcpy(crlfile_tmp, CRLFILE_TEMPNAME, 978 sizeof (crlfile_tmp)); 979 if (mkstemp(crlfile_tmp) == -1) { 980 ret = KMF_ERR_INTERNAL; 981 goto cleanup; 982 } 983 984 /* 985 * Get the URI entry from the certificate's CRL distribution 986 * points extension and download the CRL file. 987 */ 988 proxy = policy->validation_info.crl_info.proxy; 989 ret = cert_get_crl(handle, user_cert, proxy, crlfile_tmp, 990 &uri, &format); 991 if (ret != KMF_OK) { 992 (void) unlink(crlfile_tmp); 993 goto cleanup; 994 } 995 996 /* Cache the CRL file. */ 997 if (params->kstype == KMF_KEYSTORE_NSS) { 998 /* 999 * For NSS keystore, import this CRL file into th 1000 * internal database. 1001 */ 1002 icrl_params.kstype = KMF_KEYSTORE_NSS; 1003 icrl_params.nssparms.slotlabel = NULL; 1004 icrl_params.nssparms.crlfile = crlfile_tmp; 1005 icrl_params.nssparms.crl_check = B_FALSE; 1006 ret = KMF_ImportCRL(handle, &icrl_params); 1007 (void) unlink(crlfile_tmp); 1008 if (ret != KMF_OK) 1009 goto cleanup; 1010 } else { 1011 /* 1012 * For File-based CRL plugin's, find the cache 1013 * location from the CRL policy's attributes and 1014 * cache it. 1015 */ 1016 if (basefilename == NULL) 1017 basefilename = basename(uri); 1018 1019 crlfilename = get_fullpath(dir == NULL ? "./" : dir, 1020 basefilename); 1021 if (crlfilename == NULL) { 1022 (void) unlink(crlfile_tmp); 1023 ret = KMF_ERR_BAD_CRLFILE; 1024 goto cleanup; 1025 } 1026 1027 if (rename(crlfile_tmp, crlfilename) == -1) { 1028 (void) unlink(crlfile_tmp); 1029 ret = KMF_ERR_WRITE_FILE; 1030 goto cleanup; 1031 } 1032 } 1033 } else { 1034 /* 1035 * If the get_crl_uri policy is FALSE, for File-based CRL 1036 * plugins, get the input CRL file from the policy. 1037 */ 1038 if (params->kstype != KMF_KEYSTORE_NSS) { 1039 if (basefilename == NULL) { 1040 ret = KMF_ERR_BAD_PARAMETER; 1041 goto cleanup; 1042 } 1043 1044 crlfilename = get_fullpath(dir == NULL ? "./" : dir, 1045 basefilename); 1046 if (crlfilename == NULL) { 1047 ret = KMF_ERR_BAD_CRLFILE; 1048 goto cleanup; 1049 } 1050 } 1051 } 1052 1053 /* 1054 * Check the CRL signature if needed. 1055 */ 1056 if (!policy->validation_info.crl_info.ignore_crl_sign) { 1057 /* 1058 * NSS CRL is not file based, and its signature 1059 * has been verified during CRL import. 1060 */ 1061 if (params->kstype != KMF_KEYSTORE_NSS) { 1062 vcrl_params.crl_name = crlfilename; 1063 vcrl_params.tacert = issuer_cert; 1064 1065 ret = KMF_VerifyCRLFile(handle, &vcrl_params); 1066 if (ret != KMF_OK) { 1067 goto cleanup; 1068 } 1069 } 1070 } 1071 1072 /* 1073 * Check the CRL validity if needed. 1074 */ 1075 if (!policy->validation_info.crl_info.ignore_crl_date) { 1076 /* 1077 * This is for file-based CRL, but not for NSS CRL. 1078 */ 1079 if (params->kstype != KMF_KEYSTORE_NSS) { 1080 ccrldate_params.crl_name = crlfilename; 1081 1082 ret = KMF_CheckCRLDate(handle, &ccrldate_params); 1083 if (ret != KMF_OK) { 1084 goto cleanup; 1085 } 1086 } 1087 } 1088 1089 /* 1090 * Check the CRL revocation for the certificate. 1091 */ 1092 fcrl_params.kstype = params->kstype; 1093 switch (params->kstype) { 1094 case KMF_KEYSTORE_NSS: 1095 fcrl_params.certLabel = params->certLabel; 1096 break; 1097 case KMF_KEYSTORE_PK11TOKEN: 1098 /* 1099 * Create temporary file to hold the user certificate. 1100 */ 1101 (void) strlcpy(user_certfile, CERTFILE_TEMPNAME, 1102 sizeof (user_certfile)); 1103 if (mkstemp(user_certfile) == -1) { 1104 ret = KMF_ERR_INTERNAL; 1105 goto cleanup; 1106 } 1107 1108 ret = KMF_CreateCertFile(user_cert, KMF_FORMAT_ASN1, 1109 user_certfile); 1110 if (ret != KMF_OK) { 1111 goto cleanup; 1112 } 1113 1114 ssl_params.certfile = user_certfile; 1115 ssl_params.crlfile = crlfilename; 1116 fcrl_params.sslparms = ssl_params; 1117 break; 1118 case KMF_KEYSTORE_OPENSSL: 1119 ssl_params.certfile = params->ks_opt_u.openssl_opts.certfile; 1120 ssl_params.crlfile = crlfilename; 1121 fcrl_params.sslparms = ssl_params; 1122 break; 1123 default: 1124 ret = KMF_ERR_PLUGIN_NOTFOUND; 1125 goto cleanup; 1126 } 1127 1128 ret = KMF_FindCertInCRL(handle, &fcrl_params); 1129 if (ret == KMF_ERR_NOT_REVOKED) { 1130 ret = KMF_OK; 1131 } 1132 1133 cleanup: 1134 (void) unlink(user_certfile); 1135 1136 if (crlfilename != NULL) 1137 free(crlfilename); 1138 1139 if (uri != NULL) 1140 free(uri); 1141 1142 return (ret); 1143 } 1144 1145 static KMF_RETURN 1146 cert_ocsp_check(KMF_HANDLE_T handle, 1147 KMF_VALIDATECERT_PARAMS *params, 1148 KMF_DATA *user_cert, 1149 KMF_DATA *issuer_cert, 1150 KMF_DATA *response) 1151 { 1152 KMF_RETURN ret = KMF_OK; 1153 KMF_POLICY_RECORD *policy; 1154 KMF_FINDCERT_PARAMS fc_target; 1155 KMF_OCSPRESPONSE_PARAMS_INPUT resp_params_in; 1156 KMF_OCSPRESPONSE_PARAMS_OUTPUT resp_params_out; 1157 KMF_DATA *new_response = NULL; 1158 boolean_t ignore_response_sign = B_FALSE; 1159 uint32_t ltime; 1160 KMF_DATA *signer_cert = NULL; 1161 KMF_BIGINT sernum = { NULL, 0 }; 1162 1163 if (handle == NULL || params == NULL || user_cert == NULL || 1164 issuer_cert == NULL) 1165 return (KMF_ERR_BAD_PARAMETER); 1166 1167 policy = handle->policy; 1168 1169 /* 1170 * Get the response lifetime from policy. 1171 */ 1172 if (policy->VAL_OCSP_BASIC.response_lifetime != NULL && 1173 (str2lifetime(policy->VAL_OCSP_BASIC.response_lifetime, <ime) 1174 < 0)) 1175 return (KMF_ERR_OCSP_RESPONSE_LIFETIME); 1176 1177 /* 1178 * Get the ignore_response_sign policy. 1179 * 1180 * If ignore_response_sign is FALSE, we need to verify the response. 1181 * Find the OCSP Responder certificate if it is specified in the OCSP 1182 * policy. 1183 */ 1184 ignore_response_sign = policy->VAL_OCSP_BASIC.ignore_response_sign; 1185 1186 if (ignore_response_sign == B_FALSE && 1187 policy->VAL_OCSP.has_resp_cert == B_TRUE) { 1188 char *signer_name; 1189 KMF_OPENSSL_PARAMS ssl_params; 1190 KMF_X509_DER_CERT signer_retrcert; 1191 uchar_t *bytes = NULL; 1192 size_t bytelen; 1193 uint32_t num = 0; 1194 1195 if (policy->VAL_OCSP_RESP_CERT.name == NULL || 1196 policy->VAL_OCSP_RESP_CERT.serial == NULL) 1197 return (KMF_ERR_POLICY_NOT_FOUND); 1198 1199 signer_cert = malloc(sizeof (KMF_DATA)); 1200 if (signer_cert == NULL) { 1201 ret = KMF_ERR_MEMORY; 1202 goto out; 1203 } 1204 (void) memset(signer_cert, 0, sizeof (KMF_DATA)); 1205 1206 signer_name = policy->VAL_OCSP_RESP_CERT.name; 1207 ret = KMF_HexString2Bytes( 1208 (uchar_t *)policy->VAL_OCSP_RESP_CERT.serial, 1209 &bytes, &bytelen); 1210 if (ret != KMF_OK || bytes == NULL) { 1211 ret = KMF_ERR_OCSP_POLICY; 1212 goto out; 1213 } 1214 1215 sernum.val = bytes; 1216 sernum.len = bytelen; 1217 1218 (void) memset(&fc_target, 0, sizeof (fc_target)); 1219 (void) memset(&ssl_params, 0, sizeof (ssl_params)); 1220 1221 fc_target.subject = signer_name; 1222 fc_target.serial = &sernum; 1223 1224 switch (params->kstype) { 1225 case KMF_KEYSTORE_NSS: 1226 fc_target.kstype = KMF_KEYSTORE_NSS; 1227 params->nssparms.slotlabel = 1228 params->nssparms.slotlabel; 1229 break; 1230 1231 case KMF_KEYSTORE_OPENSSL: 1232 fc_target.kstype = KMF_KEYSTORE_OPENSSL; 1233 ssl_params.dirpath = 1234 params->sslparms.dirpath == NULL ? 1235 "./" : params->sslparms.dirpath; 1236 fc_target.sslparms = ssl_params; 1237 break; 1238 1239 case KMF_KEYSTORE_PK11TOKEN: 1240 fc_target.kstype = KMF_KEYSTORE_PK11TOKEN; 1241 break; 1242 default: 1243 ret = KMF_ERR_BAD_PARAMETER; 1244 goto out; 1245 break; 1246 } 1247 1248 num = 0; 1249 ret = KMF_FindCert(handle, &fc_target, NULL, &num); 1250 if (ret != KMF_OK || num != 1) { 1251 if (num == 0) 1252 ret = KMF_ERR_CERT_NOT_FOUND; 1253 if (num > 0) 1254 ret = KMF_ERR_CERT_MULTIPLE_FOUND; 1255 goto out; 1256 } 1257 1258 (void) memset(&signer_retrcert, 0, sizeof (KMF_X509_DER_CERT)); 1259 ret = KMF_FindCert(handle, &fc_target, &signer_retrcert, &num); 1260 if (ret == KMF_OK) { 1261 signer_cert->Length = 1262 signer_retrcert.certificate.Length; 1263 signer_cert->Data = signer_retrcert.certificate.Data; 1264 } else { 1265 goto out; 1266 } 1267 } 1268 1269 /* 1270 * If the caller provides an OCSP response, we will use it directly. 1271 * Otherwise, we will try to fetch an OCSP response for the given 1272 * certificate now. 1273 */ 1274 if (response == NULL) { 1275 new_response = (KMF_DATA *) malloc(sizeof (KMF_DATA)); 1276 if (new_response == NULL) { 1277 ret = KMF_ERR_MEMORY; 1278 goto out; 1279 } 1280 new_response->Data = NULL; 1281 new_response->Length = 0; 1282 1283 ret = KMF_GetOCSPForCert(handle, user_cert, issuer_cert, 1284 new_response); 1285 if (ret != KMF_OK) 1286 goto out; 1287 } 1288 1289 /* 1290 * Process the OCSP response and retrieve the certificate status. 1291 */ 1292 resp_params_in.issuer_cert = issuer_cert; 1293 resp_params_in.user_cert = user_cert; 1294 resp_params_in.signer_cert = signer_cert; 1295 resp_params_in.response = 1296 response == NULL ? new_response : response; 1297 resp_params_in.response_lifetime = ltime; 1298 resp_params_in.ignore_response_sign = ignore_response_sign; 1299 1300 ret = KMF_GetOCSPStatusForCert(handle, &resp_params_in, 1301 &resp_params_out); 1302 if (ret == KMF_OK) { 1303 switch (resp_params_out.cert_status) { 1304 case OCSP_GOOD: 1305 break; 1306 case OCSP_UNKNOWN: 1307 ret = KMF_ERR_OCSP_UNKNOWN_CERT; 1308 break; 1309 case OCSP_REVOKED: 1310 ret = KMF_ERR_OCSP_REVOKED; 1311 break; 1312 } 1313 } 1314 1315 out: 1316 if (new_response) { 1317 KMF_FreeData(new_response); 1318 free(new_response); 1319 } 1320 1321 if (signer_cert) { 1322 KMF_FreeData(signer_cert); 1323 free(signer_cert); 1324 } 1325 1326 if (sernum.val != NULL) 1327 free(sernum.val); 1328 1329 return (ret); 1330 } 1331 1332 static KMF_RETURN 1333 cert_ku_check(KMF_HANDLE_T handle, KMF_DATA *cert) 1334 { 1335 KMF_POLICY_RECORD *policy; 1336 KMF_X509EXT_KEY_USAGE keyusage; 1337 KMF_RETURN ret = KMF_OK; 1338 KMF_X509EXT_BASICCONSTRAINTS constraint; 1339 KMF_BOOL critical = B_FALSE; 1340 1341 if (handle == NULL || cert == NULL) 1342 return (KMF_ERR_BAD_PARAMETER); 1343 1344 policy = handle->policy; 1345 (void) memset(&keyusage, 0, sizeof (keyusage)); 1346 ret = KMF_GetCertKeyUsageExt(cert, &keyusage); 1347 1348 if (ret == KMF_ERR_EXTENSION_NOT_FOUND) { 1349 if (policy->ku_bits) { 1350 /* keyusage is not set in cert but is set in policy */ 1351 return (KMF_ERR_KEYUSAGE); 1352 } else { 1353 /* no keyusage set in both cert and policy */ 1354 return (KMF_OK); 1355 } 1356 } 1357 1358 if (ret != KMF_OK) { 1359 /* real error */ 1360 return (ret); 1361 } 1362 1363 /* 1364 * If KeyCertSign is set, then constraints.cA must be TRUE and 1365 * marked critical. 1366 */ 1367 if ((keyusage.KeyUsageBits & KMF_keyCertSign)) { 1368 (void) memset(&constraint, 0, sizeof (constraint)); 1369 ret = KMF_GetCertBasicConstraintExt(cert, 1370 &critical, &constraint); 1371 1372 if (ret != KMF_OK) { 1373 /* real error */ 1374 return (ret); 1375 } 1376 if (!constraint.cA || !critical) 1377 return (KMF_ERR_KEYUSAGE); 1378 } 1379 1380 /* 1381 * Rule: if the KU bit is set in policy, the corresponding KU bit 1382 * must be set in the certificate (but not vice versa). 1383 */ 1384 if ((policy->ku_bits & keyusage.KeyUsageBits) == policy->ku_bits) { 1385 return (KMF_OK); 1386 } else { 1387 return (KMF_ERR_KEYUSAGE); 1388 } 1389 1390 } 1391 1392 static KMF_RETURN 1393 cert_eku_check(KMF_HANDLE_T handle, KMF_DATA *cert) 1394 { 1395 KMF_POLICY_RECORD *policy; 1396 KMF_RETURN ret = KMF_OK; 1397 KMF_X509EXT_EKU eku; 1398 uint16_t cert_eku = 0, policy_eku = 0; 1399 int i; 1400 1401 if (handle == NULL || cert == NULL) 1402 return (KMF_ERR_BAD_PARAMETER); 1403 policy = handle->policy; 1404 1405 /* 1406 * If the policy does not have any EKU, then there is 1407 * nothing further to check. 1408 */ 1409 if (policy->eku_set.eku_count == 0) 1410 return (KMF_OK); 1411 1412 ret = KMF_GetCertEKU(cert, &eku); 1413 if ((ret != KMF_ERR_EXTENSION_NOT_FOUND) && (ret != KMF_OK)) { 1414 /* real error */ 1415 return (ret); 1416 } 1417 1418 if (ret == KMF_ERR_EXTENSION_NOT_FOUND) { 1419 cert_eku = 0; 1420 } else { 1421 /* 1422 * Build the EKU bitmap based on the certificate 1423 */ 1424 for (i = 0; i < eku.nEKUs; i++) { 1425 if (IsEqualOid(&eku.keyPurposeIdList[i], 1426 (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) { 1427 cert_eku |= KMF_EKU_SERVERAUTH; 1428 } else if (IsEqualOid(&eku.keyPurposeIdList[i], 1429 (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) { 1430 cert_eku |= KMF_EKU_CLIENTAUTH; 1431 } else if (IsEqualOid(&eku.keyPurposeIdList[i], 1432 (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) { 1433 cert_eku |= KMF_EKU_CODESIGNING; 1434 } else if (IsEqualOid(&eku.keyPurposeIdList[i], 1435 (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection)) { 1436 cert_eku |= KMF_EKU_EMAIL; 1437 } else if (IsEqualOid(&eku.keyPurposeIdList[i], 1438 (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) { 1439 cert_eku |= KMF_EKU_TIMESTAMP; 1440 } else if (IsEqualOid(&eku.keyPurposeIdList[i], 1441 (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) { 1442 cert_eku |= KMF_EKU_OCSPSIGNING; 1443 } else if (!policy->ignore_unknown_ekus) { 1444 return (KMF_ERR_KEYUSAGE); 1445 } 1446 } /* for */ 1447 } 1448 1449 1450 /* 1451 * Build the EKU bitmap based on the policy 1452 */ 1453 for (i = 0; i < policy->eku_set.eku_count; i++) { 1454 if (IsEqualOid(&policy->eku_set.ekulist[i], 1455 (KMF_OID *)&KMFOID_PKIX_KP_ServerAuth)) { 1456 policy_eku |= KMF_EKU_SERVERAUTH; 1457 } else if (IsEqualOid(&policy->eku_set.ekulist[i], 1458 (KMF_OID *)&KMFOID_PKIX_KP_ClientAuth)) { 1459 policy_eku |= KMF_EKU_CLIENTAUTH; 1460 } else if (IsEqualOid(&policy->eku_set.ekulist[i], 1461 (KMF_OID *)&KMFOID_PKIX_KP_CodeSigning)) { 1462 policy_eku |= KMF_EKU_CODESIGNING; 1463 } else if (IsEqualOid(&policy->eku_set.ekulist[i], 1464 (KMF_OID *)&KMFOID_PKIX_KP_EmailProtection)) { 1465 policy_eku |= KMF_EKU_EMAIL; 1466 } else if (IsEqualOid(&policy->eku_set.ekulist[i], 1467 (KMF_OID *)&KMFOID_PKIX_KP_TimeStamping)) { 1468 policy_eku |= KMF_EKU_TIMESTAMP; 1469 } else if (IsEqualOid(&policy->eku_set.ekulist[i], 1470 (KMF_OID *)&KMFOID_PKIX_KP_OCSPSigning)) { 1471 policy_eku |= KMF_EKU_OCSPSIGNING; 1472 } else if (!policy->ignore_unknown_ekus) { 1473 return (KMF_ERR_KEYUSAGE); 1474 } 1475 } /* for */ 1476 1477 /* 1478 * Rule: if the EKU OID is set in policy, the corresponding EKU OID 1479 * must be set in the certificate (but not vice versa). 1480 */ 1481 if ((policy_eku & cert_eku) == policy_eku) { 1482 return (KMF_OK); 1483 } else { 1484 return (KMF_ERR_KEYUSAGE); 1485 } 1486 } 1487 1488 static KMF_RETURN 1489 kmf_find_issuer_cert(KMF_HANDLE_T handle, 1490 KMF_VALIDATECERT_PARAMS *params, 1491 char *user_issuer, 1492 KMF_DATA *issuer_cert) 1493 { 1494 1495 KMF_RETURN ret = KMF_OK; 1496 KMF_FINDCERT_PARAMS fc_target; 1497 KMF_OPENSSL_PARAMS ssl_params; 1498 KMF_X509_DER_CERT *certlist = NULL; 1499 uint32_t i, num = 0; 1500 time_t t_notbefore; 1501 time_t t_notafter; 1502 time_t latest; 1503 KMF_DATA tmp_cert = {0, NULL}; 1504 1505 if (handle == NULL || params == NULL || 1506 user_issuer == NULL || issuer_cert == NULL) 1507 return (KMF_ERR_BAD_PARAMETER); 1508 1509 (void) memset(&fc_target, 0, sizeof (fc_target)); 1510 (void) memset(&ssl_params, 0, sizeof (ssl_params)); 1511 1512 fc_target.subject = user_issuer; 1513 1514 switch (params->kstype) { 1515 case KMF_KEYSTORE_NSS: 1516 fc_target.kstype = KMF_KEYSTORE_NSS; 1517 fc_target.nssparms.slotlabel = params->nssparms.slotlabel; 1518 break; 1519 1520 case KMF_KEYSTORE_OPENSSL: 1521 fc_target.kstype = KMF_KEYSTORE_OPENSSL; 1522 /* setup dirpath to search for TA in a directory */ 1523 if (params->sslparms.dirpath == NULL) { 1524 ssl_params.dirpath = "./"; 1525 } else { 1526 ssl_params.dirpath = params->sslparms.dirpath; 1527 } 1528 ssl_params.certfile = NULL; 1529 fc_target.sslparms = ssl_params; 1530 break; 1531 1532 case KMF_KEYSTORE_PK11TOKEN: 1533 fc_target.kstype = KMF_KEYSTORE_PK11TOKEN; 1534 break; 1535 default: 1536 return (KMF_ERR_PLUGIN_NOTFOUND); 1537 } 1538 1539 num = 0; 1540 ret = KMF_FindCert(handle, &fc_target, NULL, &num); 1541 if (ret == KMF_OK && num > 0) { 1542 certlist = (KMF_X509_DER_CERT *)malloc(num * 1543 sizeof (KMF_X509_DER_CERT)); 1544 1545 if (certlist == NULL) { 1546 ret = KMF_ERR_MEMORY; 1547 goto out; 1548 } 1549 1550 (void) memset(certlist, 0, num * 1551 sizeof (KMF_X509_DER_CERT)); 1552 1553 ret = KMF_FindCert(handle, &fc_target, certlist, &num); 1554 if (ret != KMF_OK) { 1555 free(certlist); 1556 certlist = NULL; 1557 goto out; 1558 } 1559 } else { 1560 goto out; 1561 } 1562 1563 if (num == 1) { 1564 /* only one issuer cert is found */ 1565 tmp_cert.Length = certlist[0].certificate.Length; 1566 tmp_cert.Data = certlist[0].certificate.Data; 1567 } else { 1568 /* 1569 * More than one issuer certs are found. We will 1570 * pick the latest one. 1571 */ 1572 latest = 0; 1573 for (i = 0; i < num; i++) { 1574 ret = KMF_GetCertValidity(&certlist[i].certificate, 1575 &t_notbefore, &t_notafter); 1576 if (ret != KMF_OK) { 1577 ret = KMF_ERR_VALIDITY_PERIOD; 1578 goto out; 1579 } 1580 1581 if (t_notbefore > latest) { 1582 tmp_cert.Length = 1583 certlist[i].certificate.Length; 1584 tmp_cert.Data = 1585 certlist[i].certificate.Data; 1586 latest = t_notbefore; 1587 } 1588 1589 } 1590 } 1591 1592 issuer_cert->Length = tmp_cert.Length; 1593 issuer_cert->Data = malloc(tmp_cert.Length); 1594 if (issuer_cert->Data == NULL) { 1595 ret = KMF_ERR_MEMORY; 1596 goto out; 1597 } 1598 (void) memcpy(issuer_cert->Data, tmp_cert.Data, 1599 tmp_cert.Length); 1600 1601 out: 1602 if (certlist != NULL) { 1603 for (i = 0; i < num; i++) 1604 KMF_FreeKMFCert(handle, &certlist[i]); 1605 free(certlist); 1606 } 1607 1608 return (ret); 1609 1610 } 1611 1612 static KMF_RETURN 1613 kmf_find_ta_cert(KMF_HANDLE_T handle, 1614 KMF_VALIDATECERT_PARAMS *params, 1615 KMF_DATA *ta_cert, 1616 KMF_X509_NAME *user_issuerDN) 1617 { 1618 1619 KMF_POLICY_RECORD *policy; 1620 KMF_RETURN ret = KMF_OK; 1621 KMF_FINDCERT_PARAMS fc_target; 1622 KMF_OPENSSL_PARAMS ssl_params; 1623 uint32_t num = 0; 1624 char *ta_name; 1625 KMF_BIGINT serial = { NULL, 0 }; 1626 uchar_t *bytes = NULL; 1627 size_t bytelen; 1628 KMF_X509_DER_CERT ta_retrCert; 1629 char *ta_subject = NULL; 1630 KMF_X509_NAME ta_subjectDN; 1631 1632 if (handle == NULL || params == NULL || 1633 ta_cert == NULL || user_issuerDN == NULL) 1634 return (KMF_ERR_BAD_PARAMETER); 1635 1636 policy = handle->policy; 1637 ta_name = policy->ta_name; 1638 1639 ret = KMF_HexString2Bytes((uchar_t *)policy->ta_serial, 1640 &bytes, &bytelen); 1641 if (ret != KMF_OK || bytes == NULL) { 1642 ret = KMF_ERR_TA_POLICY; 1643 goto out; 1644 } 1645 1646 (void) memset(&fc_target, 0, sizeof (fc_target)); 1647 (void) memset(&ssl_params, 0, sizeof (ssl_params)); 1648 1649 serial.val = bytes; 1650 serial.len = bytelen; 1651 fc_target.serial = &serial; 1652 fc_target.subject = ta_name; 1653 1654 switch (params->kstype) { 1655 case KMF_KEYSTORE_NSS: 1656 fc_target.kstype = KMF_KEYSTORE_NSS; 1657 fc_target.nssparms.slotlabel = params->nssparms.slotlabel; 1658 break; 1659 1660 case KMF_KEYSTORE_OPENSSL: 1661 fc_target.kstype = KMF_KEYSTORE_OPENSSL; 1662 /* setup dirpath to search for TA in a directory */ 1663 if (params->sslparms.dirpath == NULL) { 1664 ssl_params.dirpath = "./"; 1665 } else { 1666 ssl_params.dirpath = params->sslparms.dirpath; 1667 } 1668 ssl_params.certfile = NULL; 1669 fc_target.sslparms = ssl_params; 1670 break; 1671 1672 case KMF_KEYSTORE_PK11TOKEN: 1673 fc_target.kstype = KMF_KEYSTORE_PK11TOKEN; 1674 break; 1675 default: 1676 ret = KMF_ERR_PLUGIN_NOTFOUND; 1677 goto out; 1678 } 1679 1680 num = 0; 1681 ret = KMF_FindCert(handle, &fc_target, NULL, &num); 1682 if (ret != KMF_OK || num != 1) { 1683 if (num == 0) 1684 ret = KMF_ERR_CERT_NOT_FOUND; 1685 if (num > 1) 1686 ret = KMF_ERR_CERT_MULTIPLE_FOUND; 1687 goto out; 1688 } 1689 1690 (void) memset(&ta_retrCert, 0, sizeof (KMF_X509_DER_CERT)); 1691 1692 ret = KMF_FindCert(handle, &fc_target, &ta_retrCert, &num); 1693 if (ret == KMF_OK) { 1694 ta_cert->Length = ta_retrCert.certificate.Length; 1695 ta_cert->Data = malloc(ta_retrCert.certificate.Length); 1696 if (ta_cert->Data == NULL) { 1697 ret = KMF_ERR_MEMORY; 1698 goto out; 1699 } 1700 (void) memcpy(ta_cert->Data, ta_retrCert.certificate.Data, 1701 ta_retrCert.certificate.Length); 1702 } else { 1703 goto out; 1704 } 1705 1706 /* 1707 * The found TA's name must be matching with issuer name in 1708 * subscriber's certificate. 1709 */ 1710 (void) memset(&ta_subjectDN, 0, sizeof (ta_subjectDN)); 1711 1712 ret = KMF_GetCertSubjectNameString(handle, ta_cert, &ta_subject); 1713 if (ret != KMF_OK) 1714 goto out; 1715 1716 ret = KMF_DNParser(ta_subject, &ta_subjectDN); 1717 if (ret != KMF_OK) 1718 goto out; 1719 1720 if (KMF_CompareRDNs(user_issuerDN, &ta_subjectDN) != 0) 1721 ret = KMF_ERR_CERT_NOT_FOUND; 1722 1723 KMF_FreeDN(&ta_subjectDN); 1724 1725 /* Make sure the TA cert has the correct extensions */ 1726 if (ret == KMF_OK) 1727 ret = check_key_usage(handle, ta_cert, KMF_KU_SIGN_CERT); 1728 out: 1729 if (ta_retrCert.certificate.Data) 1730 KMF_FreeKMFCert(handle, &ta_retrCert); 1731 1732 if ((ret != KMF_OK) && (ta_cert->Data != NULL)) 1733 free(ta_cert->Data); 1734 1735 if (serial.val != NULL) 1736 free(serial.val); 1737 1738 if (ta_subject) 1739 free(ta_subject); 1740 1741 return (ret); 1742 } 1743 1744 KMF_RETURN 1745 KMF_ValidateCert(KMF_HANDLE_T handle, 1746 KMF_VALIDATECERT_PARAMS *params, 1747 int *result) 1748 { 1749 KMF_RETURN ret = KMF_OK; 1750 KMF_FINDCERT_PARAMS fc_target; 1751 KMF_OPENSSL_PARAMS ssl_params; 1752 KMF_X509_DER_CERT user_retrCert; 1753 KMF_DATA ta_cert = {0, NULL}; 1754 KMF_DATA user_cert = {0, NULL}; 1755 KMF_DATA issuer_cert = {0, NULL}; 1756 uint32_t num = 0; 1757 char *user_issuer = NULL, *user_subject = NULL; 1758 KMF_X509_NAME user_issuerDN, user_subjectDN; 1759 boolean_t self_signed = B_FALSE; 1760 KMF_POLICY_RECORD *policy; 1761 1762 CLEAR_ERROR(handle, ret); 1763 if (ret != KMF_OK) 1764 return (ret); 1765 1766 if ((params == NULL) || (result == NULL)) 1767 return (KMF_ERR_BAD_PARAMETER); 1768 1769 policy = handle->policy; 1770 1771 *result = KMF_CERT_VALIDATE_OK; 1772 (void) memset(&fc_target, 0, sizeof (fc_target)); 1773 (void) memset(&ssl_params, 0, sizeof (ssl_params)); 1774 (void) memset(&user_issuerDN, 0, sizeof (user_issuerDN)); 1775 (void) memset(&user_subjectDN, 0, sizeof (user_subjectDN)); 1776 1777 fc_target.kstype = params->kstype; 1778 fc_target.certLabel = params->certLabel; 1779 fc_target.issuer = params->issuer; 1780 fc_target.subject = params->subject; 1781 fc_target.idstr = params->idstr; 1782 fc_target.serial = params->serial; 1783 if (params->kstype == KMF_KEYSTORE_NSS) 1784 fc_target.ks_opt_u.nss_opts = params->ks_opt_u.nss_opts; 1785 else if (params->kstype == KMF_KEYSTORE_OPENSSL) 1786 fc_target.ks_opt_u.openssl_opts = params->ks_opt_u.openssl_opts; 1787 else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) 1788 fc_target.ks_opt_u.pkcs11_opts = params->ks_opt_u.pkcs11_opts; 1789 else 1790 return (KMF_ERR_PLUGIN_NOTFOUND); 1791 1792 /* 1793 * Find the Subscriber's certificate based on the input parameter 1794 */ 1795 ret = KMF_FindCert(handle, &fc_target, NULL, &num); 1796 if (ret != KMF_OK || num != 1) { 1797 (*result) = (*result) | KMF_CERT_VALIDATE_ERR_USER; 1798 if (num == 0) 1799 ret = KMF_ERR_CERT_NOT_FOUND; 1800 if (num > 1) 1801 ret = KMF_ERR_CERT_MULTIPLE_FOUND; 1802 goto out; 1803 } 1804 1805 (void) memset(&user_retrCert, 0, sizeof (KMF_X509_DER_CERT)); 1806 1807 ret = KMF_FindCert(handle, &fc_target, &user_retrCert, &num); 1808 if (ret == KMF_OK) { 1809 user_cert.Length = user_retrCert.certificate.Length; 1810 user_cert.Data = user_retrCert.certificate.Data; 1811 } else { 1812 *result |= KMF_CERT_VALIDATE_ERR_USER; 1813 goto out; 1814 } 1815 1816 if ((ret = KMF_GetCertIssuerNameString(handle, &user_cert, 1817 &user_issuer)) != KMF_OK) { 1818 *result |= KMF_CERT_VALIDATE_ERR_USER; 1819 goto out; 1820 } 1821 1822 if ((ret = KMF_DNParser(user_issuer, &user_issuerDN)) != KMF_OK) { 1823 *result |= KMF_CERT_VALIDATE_ERR_USER; 1824 goto out; 1825 } 1826 1827 if ((ret = KMF_GetCertSubjectNameString(handle, &user_cert, 1828 &user_subject)) != KMF_OK) { 1829 *result |= KMF_CERT_VALIDATE_ERR_USER; 1830 KMF_FreeDN(&user_issuerDN); 1831 goto out; 1832 } 1833 1834 if ((ret = KMF_DNParser(user_subject, &user_subjectDN)) != KMF_OK) { 1835 *result |= KMF_CERT_VALIDATE_ERR_USER; 1836 KMF_FreeDN(&user_issuerDN); 1837 goto out; 1838 } 1839 1840 if ((KMF_CompareRDNs(&user_issuerDN, &user_subjectDN)) == 0) { 1841 /* 1842 * this is a self-signed cert 1843 */ 1844 self_signed = B_TRUE; 1845 } 1846 1847 KMF_FreeDN(&user_subjectDN); 1848 1849 /* 1850 * Check KeyUsage extension of the subscriber's certificate 1851 */ 1852 ret = cert_ku_check(handle, &user_cert); 1853 if (ret != KMF_OK) { 1854 *result |= KMF_CERT_VALIDATE_ERR_KEYUSAGE; 1855 goto out; 1856 } 1857 1858 /* 1859 * Validate Extended KeyUsage extension 1860 */ 1861 ret = cert_eku_check(handle, &user_cert); 1862 if (ret != KMF_OK) { 1863 *result |= KMF_CERT_VALIDATE_ERR_EXT_KEYUSAGE; 1864 goto out; 1865 } 1866 1867 /* 1868 * Check the certificate's validity period 1869 * 1870 * This step is needed when "ignore_date" in policy is set 1871 * to false. 1872 */ 1873 if (!policy->ignore_date) { 1874 /* 1875 * Validate expiration date 1876 */ 1877 ret = KMF_CheckCertDate(handle, &user_cert); 1878 if (ret != KMF_OK) { 1879 *result |= KMF_CERT_VALIDATE_ERR_TIME; 1880 goto out; 1881 } 1882 } 1883 1884 /* 1885 * When "ignore_trust_anchor" in policy is set to FALSE, 1886 * we will try to find the TA cert based on the TA policy 1887 * attributes. 1888 * 1889 * TA's subject name (ta_name) and serial number (ta_serial) 1890 * are defined as optional attributes in policy dtd, but they 1891 * should exist in policy when "ignore_trust_anchor" is set 1892 * to FALSE. The policy verification code has enforced that. 1893 */ 1894 if (policy->ignore_trust_anchor) { 1895 goto check_revocation; 1896 } 1897 1898 ret = kmf_find_ta_cert(handle, params, &ta_cert, &user_issuerDN); 1899 if (ret != KMF_OK) { 1900 *result |= KMF_CERT_VALIDATE_ERR_TA; 1901 goto out; 1902 } 1903 1904 /* 1905 * Verify the signature of subscriber's certificate using 1906 * TA certificate. 1907 */ 1908 if (self_signed) { 1909 ret = KMF_VerifyCertWithCert(handle, 1910 &user_cert, &user_cert); 1911 } else { 1912 ret = KMF_VerifyCertWithCert(handle, 1913 &user_cert, &ta_cert); 1914 } 1915 if (ret != KMF_OK) { 1916 *result |= KMF_CERT_VALIDATE_ERR_SIGNATURE; 1917 goto out; 1918 } 1919 1920 check_revocation: 1921 /* 1922 * Check certificate revocation 1923 */ 1924 if (self_signed) { 1925 /* skip revocation checking */ 1926 goto out; 1927 } 1928 1929 /* 1930 * When CRL or OCSP revocation method is set in the policy, 1931 * we will try to find the issuer of the subscriber certificate 1932 * using the issuer name of the subscriber certificate. The 1933 * issuer certificate will be used to do the CRL checking 1934 * and OCSP checking. 1935 */ 1936 if (!(policy->revocation & KMF_REVOCATION_METHOD_CRL) && 1937 !(policy->revocation & KMF_REVOCATION_METHOD_OCSP)) { 1938 goto out; 1939 } 1940 1941 ret = kmf_find_issuer_cert(handle, params, user_issuer, 1942 &issuer_cert); 1943 if (ret != KMF_OK) { 1944 *result |= KMF_CERT_VALIDATE_ERR_ISSUER; 1945 goto out; 1946 } 1947 1948 if (policy->revocation & KMF_REVOCATION_METHOD_CRL) { 1949 ret = cert_crl_check(handle, params, 1950 &user_cert, &issuer_cert); 1951 if (ret != KMF_OK) { 1952 *result |= KMF_CERT_VALIDATE_ERR_CRL; 1953 goto out; 1954 } 1955 } 1956 1957 if (policy->revocation & KMF_REVOCATION_METHOD_OCSP) { 1958 ret = cert_ocsp_check(handle, params, 1959 &user_cert, &issuer_cert, params->ocsp_response); 1960 if (ret != KMF_OK) { 1961 *result |= KMF_CERT_VALIDATE_ERR_OCSP; 1962 goto out; 1963 } 1964 } 1965 1966 out: 1967 if (user_retrCert.certificate.Data) 1968 KMF_FreeKMFCert(handle, &user_retrCert); 1969 1970 if (user_issuer) { 1971 KMF_FreeDN(&user_issuerDN); 1972 free(user_issuer); 1973 } 1974 1975 if (user_subject) 1976 free(user_subject); 1977 1978 if (ta_cert.Data) 1979 free(ta_cert.Data); 1980 1981 if (issuer_cert.Data) 1982 free(issuer_cert.Data); 1983 1984 return (ret); 1985 1986 } 1987 1988 KMF_RETURN 1989 KMF_CreateCertFile(KMF_DATA *certdata, KMF_ENCODE_FORMAT format, 1990 char *certfile) 1991 { 1992 KMF_RETURN rv = KMF_OK; 1993 int fd = -1; 1994 KMF_DATA pemdata = {NULL, 0}; 1995 1996 if (certdata == NULL || certfile == NULL) 1997 return (KMF_ERR_BAD_PARAMETER); 1998 1999 if (format != KMF_FORMAT_PEM && format != KMF_FORMAT_ASN1) 2000 return (KMF_ERR_BAD_PARAMETER); 2001 2002 if (format == KMF_FORMAT_PEM) { 2003 int len; 2004 rv = KMF_Der2Pem(KMF_CERT, 2005 certdata->Data, certdata->Length, 2006 &pemdata.Data, &len); 2007 if (rv != KMF_OK) 2008 goto cleanup; 2009 pemdata.Length = (size_t)len; 2010 } 2011 2012 if ((fd = open(certfile, O_CREAT |O_RDWR, 0644)) == -1) { 2013 rv = KMF_ERR_OPEN_FILE; 2014 goto cleanup; 2015 } 2016 2017 if (format == KMF_FORMAT_PEM) { 2018 if (write(fd, pemdata.Data, pemdata.Length) != 2019 pemdata.Length) { 2020 rv = KMF_ERR_WRITE_FILE; 2021 } 2022 } else { 2023 if (write(fd, certdata->Data, certdata->Length) != 2024 certdata->Length) { 2025 rv = KMF_ERR_WRITE_FILE; 2026 } 2027 } 2028 2029 cleanup: 2030 if (fd != -1) 2031 (void) close(fd); 2032 2033 KMF_FreeData(&pemdata); 2034 2035 return (rv); 2036 } 2037 2038 KMF_RETURN 2039 KMF_IsCertFile(KMF_HANDLE_T handle, char *filename, KMF_ENCODE_FORMAT *pformat) 2040 { 2041 KMF_PLUGIN *plugin; 2042 KMF_RETURN (*IsCertFileFn)(void *, char *, KMF_ENCODE_FORMAT *); 2043 2044 KMF_RETURN ret; 2045 2046 CLEAR_ERROR(handle, ret); 2047 if (ret != KMF_OK) 2048 return (ret); 2049 2050 if (filename == NULL || pformat == NULL) { 2051 return (KMF_ERR_BAD_PARAMETER); 2052 } 2053 2054 /* 2055 * This framework function is actually implemented in the openssl 2056 * plugin library, so we find the function address and call it. 2057 */ 2058 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 2059 if (plugin == NULL || plugin->dldesc == NULL) { 2060 return (KMF_ERR_PLUGIN_NOTFOUND); 2061 } 2062 2063 IsCertFileFn = (KMF_RETURN(*)())dlsym(plugin->dldesc, 2064 "OpenSSL_IsCertFile"); 2065 if (IsCertFileFn == NULL) { 2066 return (KMF_ERR_FUNCTION_NOT_FOUND); 2067 } 2068 2069 return (IsCertFileFn(handle, filename, pformat)); 2070 } 2071 2072 /* 2073 * This function checks the validity period of a der-encoded certificate. 2074 */ 2075 KMF_RETURN 2076 KMF_CheckCertDate(KMF_HANDLE_T handle, KMF_DATA *cert) 2077 { 2078 KMF_RETURN rv; 2079 struct tm *gmt; 2080 time_t t_now; 2081 time_t t_notbefore; 2082 time_t t_notafter; 2083 KMF_POLICY_RECORD *policy; 2084 uint32_t adj; 2085 2086 CLEAR_ERROR(handle, rv); 2087 if (rv != KMF_OK) 2088 return (rv); 2089 2090 if (cert == NULL || cert->Data == NULL || 2091 cert->Length == 0) 2092 return (KMF_ERR_BAD_PARAMETER); 2093 2094 policy = handle->policy; 2095 rv = KMF_GetCertValidity(cert, &t_notbefore, &t_notafter); 2096 if (rv != KMF_OK) 2097 return (rv); 2098 2099 /* 2100 * Get the current time. The time returned from time() is local which 2101 * cannot be used directly. It must be converted to UTC/GMT first. 2102 */ 2103 t_now = time(NULL); 2104 gmt = gmtime(&t_now); 2105 t_now = mktime(gmt); 2106 2107 /* 2108 * Adjust the validity time 2109 */ 2110 if (policy->validity_adjusttime != NULL) { 2111 if (str2lifetime(policy->validity_adjusttime, &adj) < 0) 2112 return (KMF_ERR_VALIDITY_PERIOD); 2113 } else { 2114 adj = 0; 2115 } 2116 2117 t_notafter += adj; 2118 t_notbefore -= adj; 2119 2120 if (t_now <= t_notafter && t_now >= t_notbefore) { 2121 rv = KMF_OK; 2122 } else { 2123 rv = KMF_ERR_VALIDITY_PERIOD; 2124 } 2125 2126 return (rv); 2127 } 2128 2129 KMF_RETURN 2130 KMF_ExportPK12(KMF_HANDLE_T handle, 2131 KMF_EXPORTP12_PARAMS *params, 2132 char *filename) 2133 { 2134 KMF_RETURN rv; 2135 KMF_PLUGIN *plugin; 2136 KMF_KEYSTORE_TYPE kstype; 2137 KMF_X509_DER_CERT *certlist = NULL; 2138 KMF_KEY_HANDLE *keys = NULL; 2139 uint32_t numkeys; 2140 uint32_t numcerts; 2141 int i; 2142 2143 CLEAR_ERROR(handle, rv); 2144 if (rv != KMF_OK) 2145 return (rv); 2146 2147 if (params == NULL || filename == NULL) 2148 return (KMF_ERR_BAD_PARAMETER); 2149 kstype = params->kstype; 2150 if (kstype == KMF_KEYSTORE_PK11TOKEN) { 2151 KMF_FINDCERT_PARAMS fcargs; 2152 2153 (void) memset(&fcargs, 0, sizeof (fcargs)); 2154 2155 fcargs.kstype = kstype; 2156 fcargs.certLabel = params->certLabel; 2157 fcargs.issuer = params->issuer; 2158 fcargs.subject = params->subject; 2159 fcargs.serial = params->serial; 2160 fcargs.idstr = params->idstr; 2161 2162 /* 2163 * Special processing because PKCS11 doesn't have 2164 * a native PKCS12 operation. 2165 */ 2166 rv = KMF_FindCert(handle, &fcargs, NULL, &numcerts); 2167 if (rv == KMF_OK && numcerts > 0) { 2168 certlist = (KMF_X509_DER_CERT *)malloc(numcerts * 2169 sizeof (KMF_X509_DER_CERT)); 2170 if (certlist == NULL) 2171 return (KMF_ERR_MEMORY); 2172 (void) memset(certlist, 0, numcerts * 2173 sizeof (KMF_X509_DER_CERT)); 2174 rv = KMF_FindCert(handle, &fcargs, 2175 certlist, &numcerts); 2176 if (rv != KMF_OK) { 2177 free(certlist); 2178 return (rv); 2179 } 2180 } else { 2181 return (rv); 2182 } 2183 2184 numkeys = 0; 2185 for (i = 0; i < numcerts; i++) { 2186 KMF_CRYPTOWITHCERT_PARAMS fkparms; 2187 KMF_KEY_HANDLE newkey; 2188 2189 fkparms.kstype = kstype; 2190 fkparms.format = KMF_FORMAT_RAWKEY; 2191 fkparms.cred = params->cred; 2192 fkparms.certLabel = certlist[i].kmf_private.label; 2193 2194 rv = find_private_key_by_cert(handle, &fkparms, 2195 &certlist[i].certificate, &newkey); 2196 if (rv == KMF_OK) { 2197 numkeys++; 2198 keys = realloc(keys, 2199 numkeys * sizeof (KMF_KEY_HANDLE)); 2200 if (keys == NULL) { 2201 free(certlist); 2202 rv = KMF_ERR_MEMORY; 2203 goto out; 2204 } 2205 keys[numkeys - 1] = newkey; 2206 } else if (rv == KMF_ERR_KEY_NOT_FOUND) { 2207 /* it is OK if a key is not found */ 2208 rv = KMF_OK; 2209 } 2210 } 2211 if (rv == KMF_OK) { 2212 /* 2213 * Switch the keystore type to use OpenSSL for 2214 * exporting the raw cert and key data as PKCS12. 2215 */ 2216 kstype = KMF_KEYSTORE_OPENSSL; 2217 } else { 2218 rv = KMF_ERR_KEY_NOT_FOUND; 2219 goto out; 2220 } 2221 } 2222 plugin = FindPlugin(handle, kstype); 2223 if (plugin != NULL && plugin->funclist->ExportP12 != NULL) { 2224 rv = plugin->funclist->ExportP12(handle, 2225 params, numcerts, certlist, 2226 numkeys, keys, filename); 2227 } else { 2228 rv = KMF_ERR_PLUGIN_NOTFOUND; 2229 } 2230 2231 out: 2232 if (certlist != NULL) { 2233 for (i = 0; i < numcerts; i++) 2234 KMF_FreeKMFCert(handle, &certlist[i]); 2235 free(certlist); 2236 } 2237 if (keys != NULL) { 2238 for (i = 0; i < numkeys; i++) 2239 KMF_FreeKMFKey(handle, &keys[i]); 2240 free(keys); 2241 } 2242 2243 return (rv); 2244 } 2245 2246 KMF_RETURN 2247 KMF_ImportPK12(KMF_HANDLE_T handle, char *filename, 2248 KMF_CREDENTIAL *cred, 2249 KMF_DATA **certs, int *ncerts, 2250 KMF_RAW_KEY_DATA **rawkeys, int *nkeys) 2251 { 2252 KMF_RETURN rv; 2253 KMF_PLUGIN *plugin; 2254 KMF_RETURN (*openpkcs12)(KMF_HANDLE *, 2255 char *, KMF_CREDENTIAL *, 2256 KMF_DATA **, int *, 2257 KMF_RAW_KEY_DATA **, int *); 2258 2259 CLEAR_ERROR(handle, rv); 2260 if (rv != KMF_OK) 2261 return (rv); 2262 2263 if (filename == NULL || 2264 cred == NULL || 2265 certs == NULL || ncerts == NULL || 2266 rawkeys == NULL || nkeys == NULL) 2267 return (KMF_ERR_BAD_PARAMETER); 2268 2269 /* 2270 * Use the pkcs12 reader from the OpenSSL plugin. 2271 */ 2272 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 2273 if (plugin == NULL || plugin->dldesc == NULL) { 2274 return (KMF_ERR_PLUGIN_NOTFOUND); 2275 } 2276 2277 openpkcs12 = (KMF_RETURN(*)())dlsym(plugin->dldesc, 2278 "openssl_read_pkcs12"); 2279 if (openpkcs12 == NULL) { 2280 return (KMF_ERR_FUNCTION_NOT_FOUND); 2281 } 2282 2283 /* Use OpenSSL interfaces to get raw key and cert data */ 2284 rv = openpkcs12(handle, filename, cred, certs, ncerts, 2285 rawkeys, nkeys); 2286 2287 return (rv); 2288 } 2289 2290 KMF_RETURN 2291 KMF_ImportKeypair(KMF_HANDLE_T handle, char *filename, 2292 KMF_CREDENTIAL *cred, 2293 KMF_DATA **certs, int *ncerts, 2294 KMF_RAW_KEY_DATA **rawkeys, int *nkeys) 2295 { 2296 KMF_RETURN rv; 2297 KMF_PLUGIN *plugin; 2298 KMF_RETURN (*import_keypair)(KMF_HANDLE *, 2299 char *, KMF_CREDENTIAL *, 2300 KMF_DATA **, int *, 2301 KMF_RAW_KEY_DATA **, int *); 2302 2303 CLEAR_ERROR(handle, rv); 2304 if (rv != KMF_OK) 2305 return (rv); 2306 2307 if (filename == NULL || 2308 cred == NULL || 2309 certs == NULL || ncerts == NULL || 2310 rawkeys == NULL || nkeys == NULL) 2311 return (KMF_ERR_BAD_PARAMETER); 2312 2313 /* 2314 * Use the Keypair reader from the OpenSSL plugin. 2315 */ 2316 plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL); 2317 if (plugin == NULL || plugin->dldesc == NULL) { 2318 return (KMF_ERR_PLUGIN_NOTFOUND); 2319 } 2320 2321 import_keypair = (KMF_RETURN(*)())dlsym(plugin->dldesc, 2322 "openssl_import_keypair"); 2323 if (import_keypair == NULL) { 2324 return (KMF_ERR_FUNCTION_NOT_FOUND); 2325 } 2326 2327 /* Use OpenSSL interfaces to get raw key and cert data */ 2328 rv = import_keypair(handle, filename, cred, certs, ncerts, 2329 rawkeys, nkeys); 2330 2331 return (rv); 2332 } 2333 2334 KMF_BOOL 2335 IsEqualOid(KMF_OID *Oid1, KMF_OID *Oid2) 2336 { 2337 return ((Oid1->Length == Oid2->Length) && 2338 !memcmp(Oid1->Data, Oid2->Data, Oid1->Length)); 2339 } 2340 2341 static KMF_RETURN 2342 copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid, 2343 KMF_X509_ALGORITHM_IDENTIFIER *srcid) 2344 { 2345 KMF_RETURN ret = KMF_OK; 2346 if (!destid || !srcid) 2347 return (KMF_ERR_BAD_PARAMETER); 2348 2349 destid->algorithm.Length = srcid->algorithm.Length; 2350 destid->algorithm.Data = malloc(destid->algorithm.Length); 2351 if (destid->algorithm.Data == NULL) 2352 return (KMF_ERR_MEMORY); 2353 2354 (void) memcpy(destid->algorithm.Data, srcid->algorithm.Data, 2355 destid->algorithm.Length); 2356 2357 destid->parameters.Length = srcid->parameters.Length; 2358 if (destid->parameters.Length > 0) { 2359 destid->parameters.Data = malloc(destid->parameters.Length); 2360 if (destid->parameters.Data == NULL) 2361 return (KMF_ERR_MEMORY); 2362 2363 (void) memcpy(destid->parameters.Data, srcid->parameters.Data, 2364 destid->parameters.Length); 2365 } else { 2366 destid->parameters.Data = NULL; 2367 } 2368 return (ret); 2369 } 2370 2371 KMF_RETURN 2372 SignCert(KMF_HANDLE_T handle, 2373 const KMF_DATA *SubjectCert, 2374 KMF_KEY_HANDLE *Signkey, 2375 KMF_DATA *SignedCert) 2376 { 2377 KMF_X509_CERTIFICATE *subj_cert = NULL; 2378 KMF_DATA data_to_sign = {0, NULL}; 2379 KMF_DATA signed_data = {0, NULL}; 2380 KMF_RETURN ret = KMF_OK; 2381 KMF_ALGORITHM_INDEX algid; 2382 2383 if (!SignedCert) 2384 return (KMF_ERR_BAD_PARAMETER); 2385 2386 SignedCert->Length = 0; 2387 SignedCert->Data = NULL; 2388 2389 if (!SubjectCert) 2390 return (KMF_ERR_BAD_PARAMETER); 2391 2392 if (!SubjectCert->Data || !SubjectCert->Length) 2393 return (KMF_ERR_BAD_PARAMETER); 2394 2395 /* 2396 * Shortcut - just extract the already encoded TBS cert data from 2397 * the original data buffer. Since we haven't changed anything, 2398 * there is no need to re-encode it. 2399 */ 2400 ret = ExtractX509CertParts((KMF_DATA *)SubjectCert, 2401 &data_to_sign, NULL); 2402 if (ret != KMF_OK) { 2403 goto cleanup; 2404 } 2405 2406 /* Estimate the signed data length generously */ 2407 signed_data.Length = data_to_sign.Length*2; 2408 signed_data.Data = calloc(1, signed_data.Length); 2409 if (!signed_data.Data) { 2410 ret = KMF_ERR_MEMORY; 2411 goto cleanup; 2412 } 2413 2414 /* 2415 * If we got here OK, decode into a structure and then re-encode 2416 * the complete certificate. 2417 */ 2418 ret = DerDecodeSignedCertificate(SubjectCert, &subj_cert); 2419 if (ret != KMF_OK) { 2420 goto cleanup; 2421 } 2422 2423 /* We are re-signing this cert, so clear out old signature data */ 2424 if (subj_cert->signature.algorithmIdentifier.algorithm.Length == 0) { 2425 KMF_FreeAlgOID(&subj_cert->signature.algorithmIdentifier); 2426 ret = copy_algoid(&subj_cert->signature.algorithmIdentifier, 2427 &subj_cert->certificate.signature); 2428 } 2429 2430 if (ret) 2431 goto cleanup; 2432 2433 /* Sign the data */ 2434 ret = KMF_SignDataWithKey(handle, Signkey, 2435 CERT_ALG_OID(subj_cert), 2436 &data_to_sign, &signed_data); 2437 2438 if (ret != KMF_OK) 2439 goto cleanup; 2440 2441 algid = X509_AlgorithmOidToAlgId(CERT_SIG_OID(subj_cert)); 2442 2443 /* 2444 * For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded 2445 * signature. So we must encode the signature correctly. 2446 */ 2447 if (algid == KMF_ALGID_SHA1WithDSA) { 2448 2449 KMF_DATA signature; 2450 2451 ret = DerEncodeDSASignature(&signed_data, &signature); 2452 KMF_FreeData(&signed_data); 2453 2454 if (ret != KMF_OK) 2455 goto cleanup; 2456 2457 subj_cert->signature.encrypted = signature; 2458 } else { 2459 subj_cert->signature.encrypted = signed_data; 2460 } 2461 2462 /* Now, re-encode the cert with the new signature */ 2463 ret = DerEncodeSignedCertificate(subj_cert, SignedCert); 2464 2465 cleanup: 2466 /* Cleanup & return */ 2467 if (ret != KMF_OK) 2468 KMF_FreeData(SignedCert); 2469 2470 KMF_FreeData(&data_to_sign); 2471 2472 if (subj_cert != NULL) { 2473 KMF_FreeSignedCert(subj_cert); 2474 free(subj_cert); 2475 } 2476 2477 return (ret); 2478 } 2479 2480 KMF_RETURN 2481 VerifyCertWithKey(KMF_HANDLE_T handle, 2482 KMF_DATA *derkey, 2483 const KMF_DATA *CertToBeVerified) 2484 { 2485 KMF_RETURN ret = KMF_OK; 2486 KMF_X509_CERTIFICATE *signed_cert = NULL; 2487 KMF_X509_SPKI spki; 2488 KMF_DATA data_to_verify = {0, NULL}; 2489 KMF_DATA signed_data = {0, NULL}; 2490 KMF_DATA signature = { 0, NULL }; 2491 KMF_ALGORITHM_INDEX algid; 2492 2493 /* check the caller and do other setup for this SPI call */ 2494 if (handle == NULL || CertToBeVerified == NULL || 2495 derkey == NULL || derkey->Data == NULL) 2496 return (KMF_ERR_BAD_PARAMETER); 2497 2498 (void) memset(&spki, 0, sizeof (KMF_X509_SPKI)); 2499 2500 ret = ExtractX509CertParts((KMF_DATA *)CertToBeVerified, 2501 &data_to_verify, &signed_data); 2502 2503 if (ret != KMF_OK) 2504 goto cleanup; 2505 2506 ret = DerDecodeSPKI(derkey, &spki); 2507 if (ret != KMF_OK) 2508 goto cleanup; 2509 2510 /* Decode the signer cert so we can get the Algorithm data */ 2511 ret = DerDecodeSignedCertificate(CertToBeVerified, &signed_cert); 2512 if (ret != KMF_OK) 2513 return (ret); 2514 2515 algid = X509_AlgorithmOidToAlgId(CERT_SIG_OID(signed_cert)); 2516 2517 if (algid == KMF_ALGID_NONE) 2518 return (KMF_ERR_BAD_ALGORITHM); 2519 2520 if (algid == KMF_ALGID_SHA1WithDSA) { 2521 ret = DerDecodeDSASignature(&signed_data, &signature); 2522 if (ret != KMF_OK) 2523 goto cleanup; 2524 } else { 2525 signature.Data = signed_data.Data; 2526 signature.Length = signed_data.Length; 2527 } 2528 2529 ret = PKCS_VerifyData(handle, algid, &spki, 2530 &data_to_verify, &signature); 2531 2532 cleanup: 2533 if (data_to_verify.Data != NULL) 2534 free(data_to_verify.Data); 2535 2536 if (signed_data.Data != NULL) 2537 free(signed_data.Data); 2538 2539 if (signed_cert) { 2540 KMF_FreeSignedCert(signed_cert); 2541 free(signed_cert); 2542 } 2543 if (algid == KMF_ALGID_SHA1WithDSA) { 2544 free(signature.Data); 2545 } 2546 2547 KMF_FreeAlgOID(&spki.algorithm); 2548 KMF_FreeData(&spki.subjectPublicKey); 2549 2550 return (ret); 2551 } 2552 2553 KMF_RETURN 2554 VerifyDataWithKey(KMF_HANDLE_T handle, 2555 KMF_DATA *derkey, 2556 KMF_ALGORITHM_INDEX sigAlg, 2557 KMF_DATA *indata, 2558 KMF_DATA *insig) 2559 { 2560 KMF_RETURN ret = KMF_OK; 2561 KMF_X509_SPKI spki; 2562 2563 if (!indata || !insig || !derkey || !derkey->Data) 2564 return (KMF_ERR_BAD_PARAMETER); 2565 2566 ret = DerDecodeSPKI(derkey, &spki); 2567 if (ret != KMF_OK) 2568 goto cleanup; 2569 2570 ret = PKCS_VerifyData(handle, sigAlg, &spki, indata, insig); 2571 2572 cleanup: 2573 KMF_FreeAlgOID(&spki.algorithm); 2574 KMF_FreeData(&spki.subjectPublicKey); 2575 2576 return (ret); 2577 } 2578 2579 KMF_RETURN 2580 VerifyCertWithCert(KMF_HANDLE_T handle, 2581 const KMF_DATA *CertToBeVerifiedData, 2582 const KMF_DATA *SignerCertData) 2583 { 2584 KMF_RETURN ret = KMF_OK; 2585 KMF_X509_CERTIFICATE *SignerCert = NULL; 2586 KMF_X509_CERTIFICATE *ToBeVerifiedCert = NULL; 2587 KMF_X509_SPKI *pubkey; 2588 KMF_DATA data_to_verify = {0, NULL}; 2589 KMF_DATA signed_data = {0, NULL}; 2590 KMF_DATA signature; 2591 KMF_ALGORITHM_INDEX algid; 2592 2593 if (!CertToBeVerifiedData || 2594 !CertToBeVerifiedData->Data || 2595 !CertToBeVerifiedData->Length) 2596 return (KMF_ERR_BAD_PARAMETER); 2597 2598 if (!SignerCertData || 2599 !SignerCertData->Data || 2600 !SignerCertData->Length) 2601 return (KMF_ERR_BAD_PARAMETER); 2602 2603 /* Decode the cert into parts for verification */ 2604 ret = ExtractX509CertParts((KMF_DATA *)CertToBeVerifiedData, 2605 &data_to_verify, &signed_data); 2606 if (ret != KMF_OK) 2607 goto cleanup; 2608 2609 /* Decode the signer cert so we can get the SPKI data */ 2610 ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert); 2611 if (ret != KMF_OK) 2612 goto cleanup; 2613 2614 /* 2615 * TODO ! Validate the SignerCert to make sure it is OK to be 2616 * used to verify other certs. Or - should this be done the calling 2617 * application? 2618 */ 2619 /* ValidateCert(SignerCert); */ 2620 2621 /* Get the public key info from the signer certificate */ 2622 pubkey = &SignerCert->certificate.subjectPublicKeyInfo; 2623 2624 /* Decode the to-be-verified cert so we know what algorithm to use */ 2625 ret = DerDecodeSignedCertificate(CertToBeVerifiedData, 2626 &ToBeVerifiedCert); 2627 2628 if (ret != KMF_OK) 2629 goto cleanup; 2630 2631 algid = X509_AlgorithmOidToAlgId(CERT_SIG_OID(ToBeVerifiedCert)); 2632 2633 if (algid == KMF_ALGID_SHA1WithDSA) { 2634 ret = DerDecodeDSASignature(&signed_data, &signature); 2635 if (ret != KMF_OK) 2636 goto cleanup; 2637 } else { 2638 signature.Data = signed_data.Data; 2639 signature.Length = signed_data.Length; 2640 } 2641 2642 ret = PKCS_VerifyData(handle, algid, pubkey, 2643 &data_to_verify, &signature); 2644 2645 cleanup: 2646 KMF_FreeData(&data_to_verify); 2647 KMF_FreeData(&signed_data); 2648 2649 if (SignerCert) { 2650 KMF_FreeSignedCert(SignerCert); 2651 free(SignerCert); 2652 } 2653 2654 if (ToBeVerifiedCert) { 2655 KMF_FreeSignedCert(ToBeVerifiedCert); 2656 free(ToBeVerifiedCert); 2657 } 2658 2659 if (algid == KMF_ALGID_SHA1WithDSA) { 2660 free(signature.Data); 2661 } 2662 2663 return (ret); 2664 } 2665 2666 KMF_RETURN 2667 VerifyDataWithCert(KMF_HANDLE_T handle, 2668 KMF_DATA *indata, 2669 KMF_DATA *insig, 2670 const KMF_DATA *SignerCertData) 2671 { 2672 KMF_RETURN ret = KMF_OK; 2673 KMF_X509_CERTIFICATE *SignerCert = NULL; 2674 KMF_X509_SPKI *pubkey; 2675 KMF_ALGORITHM_INDEX algid; 2676 2677 if (!indata || 2678 !indata->Data || 2679 !indata->Length) 2680 return (KMF_ERR_BAD_PARAMETER); 2681 2682 if (!insig || 2683 !insig->Data || 2684 !insig->Length) 2685 return (KMF_ERR_BAD_PARAMETER); 2686 2687 2688 if (!SignerCertData || 2689 !SignerCertData->Data || 2690 !SignerCertData->Length) 2691 return (KMF_ERR_BAD_PARAMETER); 2692 2693 /* Decode the signer cert so we can get the SPKI data */ 2694 ret = DerDecodeSignedCertificate(SignerCertData, &SignerCert); 2695 if (ret != KMF_OK) 2696 goto cleanup; 2697 2698 /* Get the public key info from the signer certificate */ 2699 pubkey = &SignerCert->certificate.subjectPublicKeyInfo; 2700 2701 algid = X509_AlgorithmOidToAlgId(CERT_ALG_OID(SignerCert)); 2702 if (algid == KMF_ALGID_NONE) { 2703 ret = KMF_ERR_BAD_ALGORITHM; 2704 } else { 2705 ret = PKCS_VerifyData(handle, algid, 2706 pubkey, indata, insig); 2707 } 2708 2709 cleanup: 2710 if (SignerCert) { 2711 KMF_FreeSignedCert(SignerCert); 2712 free(SignerCert); 2713 } 2714 2715 return (ret); 2716 } 2717 2718 KMF_RETURN 2719 SignCsr(KMF_HANDLE_T handle, 2720 const KMF_DATA *SubjectCsr, 2721 KMF_KEY_HANDLE *Signkey, 2722 KMF_X509_ALGORITHM_IDENTIFIER *algo, 2723 KMF_DATA *SignedCsr) 2724 { 2725 2726 KMF_CSR_DATA subj_csr; 2727 KMF_TBS_CSR *tbs_csr = NULL; 2728 KMF_DATA signed_data = {0, NULL}; 2729 KMF_RETURN ret = KMF_OK; 2730 2731 if (!SignedCsr) 2732 return (KMF_ERR_BAD_PARAMETER); 2733 2734 SignedCsr->Length = 0; 2735 SignedCsr->Data = NULL; 2736 2737 if (!SubjectCsr) 2738 return (KMF_ERR_BAD_PARAMETER); 2739 2740 if (!SubjectCsr->Data || !SubjectCsr->Length) 2741 return (KMF_ERR_BAD_PARAMETER); 2742 2743 (void) memset(&subj_csr, 0, sizeof (subj_csr)); 2744 /* Estimate the signed data length generously */ 2745 signed_data.Length = SubjectCsr->Length*2; 2746 signed_data.Data = calloc(1, signed_data.Length); 2747 if (!signed_data.Data) { 2748 ret = KMF_ERR_MEMORY; 2749 goto cleanup; 2750 } 2751 2752 /* Sign the data */ 2753 ret = KMF_SignDataWithKey(handle, Signkey, &algo->algorithm, 2754 (KMF_DATA *)SubjectCsr, &signed_data); 2755 2756 if (KMF_OK != ret) 2757 goto cleanup; 2758 2759 /* 2760 * If we got here OK, decode into a structure and then re-encode 2761 * the complete CSR. 2762 */ 2763 ret = DerDecodeTbsCsr(SubjectCsr, &tbs_csr); 2764 if (ret) 2765 goto cleanup; 2766 2767 (void) memcpy(&subj_csr.csr, tbs_csr, sizeof (KMF_TBS_CSR)); 2768 2769 ret = copy_algoid(&subj_csr.signature.algorithmIdentifier, algo); 2770 if (ret) 2771 goto cleanup; 2772 2773 subj_csr.signature.encrypted = signed_data; 2774 2775 /* Now, re-encode the CSR with the new signature */ 2776 ret = DerEncodeSignedCsr(&subj_csr, SignedCsr); 2777 if (ret != KMF_OK) { 2778 KMF_FreeData(SignedCsr); 2779 goto cleanup; 2780 } 2781 2782 /* Cleanup & return */ 2783 cleanup: 2784 free(tbs_csr); 2785 2786 KMF_FreeTBSCSR(&subj_csr.csr); 2787 2788 KMF_FreeAlgOID(&subj_csr.signature.algorithmIdentifier); 2789 KMF_FreeData(&signed_data); 2790 2791 return (ret); 2792 } 2793 2794 KMF_RETURN 2795 EncryptWithCert(KMF_HANDLE_T handle, 2796 KMF_DATA *cert, 2797 KMF_DATA *plaintext, 2798 KMF_DATA *ciphertext) 2799 { 2800 KMF_RETURN ret = KMF_OK; 2801 KMF_X509_CERTIFICATE *x509cert = NULL; 2802 KMF_X509_SPKI *pubkey; 2803 KMF_OID *alg; 2804 KMF_ALGORITHM_INDEX algid; 2805 2806 /* Decode the cert so we can get the SPKI data */ 2807 if ((ret = DerDecodeSignedCertificate(cert, &x509cert)) != KMF_OK) 2808 return (ret); 2809 2810 /* Get the public key info from the certificate */ 2811 pubkey = &x509cert->certificate.subjectPublicKeyInfo; 2812 2813 /* Use the algorithm in SPKI to encrypt data */ 2814 alg = &pubkey->algorithm.algorithm; 2815 2816 algid = X509_AlgorithmOidToAlgId(alg); 2817 2818 /* DSA does not support encrypt */ 2819 if (algid == KMF_ALGID_DSA || algid == KMF_ALGID_NONE) { 2820 KMF_FreeSignedCert(x509cert); 2821 free(x509cert); 2822 return (KMF_ERR_BAD_ALGORITHM); 2823 } 2824 2825 ret = PKCS_EncryptData(handle, algid, pubkey, plaintext, ciphertext); 2826 KMF_FreeSignedCert(x509cert); 2827 free(x509cert); 2828 2829 return (ret); 2830 } 2831