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