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 /* 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <limits.h> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <dirent.h> 33 #include <strings.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 #include <sys/mman.h> 38 #include <md5.h> 39 #include <pthread.h> 40 41 #include <cryptoutil.h> 42 43 #include <kmfapi.h> 44 #include <sys/crypto/elfsign.h> 45 #include <libelfsign.h> 46 47 #include <synch.h> 48 49 const char _PATH_ELFSIGN_CRYPTO_CERTS[] = CRYPTO_CERTS_DIR; 50 const char _PATH_ELFSIGN_ETC_CERTS[] = ETC_CERTS_DIR; 51 52 /* 53 * The CACERT and OBJCACERT are the Cryptographic Trust Anchors 54 * for the Solaris Cryptographic Framework. 55 * 56 * The SECACERT is the Signed Execution Trust Anchor that the 57 * Cryptographic Framework uses for FIPS-140 validation of non-crypto 58 * binaries 59 */ 60 static const char _PATH_CRYPTO_CACERT[] = CRYPTO_CERTS_DIR "/CA"; 61 static const char _PATH_CRYPTO_OBJCACERT[] = CRYPTO_CERTS_DIR "/SUNWObjectCA"; 62 static const char _PATH_CRYPTO_SECACERT[] = ETC_CERTS_DIR "/SUNWSolarisCA"; 63 static ELFCert_t CACERT = NULL; 64 static ELFCert_t OBJCACERT = NULL; 65 static ELFCert_t SECACERT = NULL; 66 static pthread_mutex_t ca_mutex = PTHREAD_MUTEX_INITIALIZER; 67 68 static void elfcertlib_freecert(ELFsign_t, ELFCert_t); 69 static ELFCert_t elfcertlib_allocatecert(void); 70 71 /* 72 * elfcertlib_verifycert - Verify the Cert with a Trust Anchor 73 * 74 * IN ess - elfsign context structure 75 * cert 76 * OUT NONE 77 * RETURN TRUE/FALSE 78 * 79 * We first setup the Trust Anchor (CA and SUNWObjectCA) certs 80 * if it hasn't been done already. We verify that the files on disk 81 * are those we expected. 82 * 83 * We then verify the given cert using the publickey of a TA. 84 * If the passed in cert is a TA or it has been verified already we 85 * short cut and return TRUE without futher validation. 86 */ 87 /*ARGSUSED*/ 88 boolean_t 89 elfcertlib_verifycert(ELFsign_t ess, ELFCert_t cert) 90 { 91 KMF_ATTRIBUTE attrlist[8]; 92 int numattr; 93 94 KMF_RETURN rv; 95 if ((cert->c_verified == E_OK) || (cert->c_verified == E_IS_TA)) { 96 return (B_TRUE); 97 } 98 99 (void) pthread_mutex_lock(&ca_mutex); 100 if (CACERT == NULL) { 101 (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_CACERT, 102 NULL, &CACERT, ES_GET); 103 } 104 105 if (OBJCACERT == NULL) { 106 (void) elfcertlib_getcert(ess, (char *)_PATH_CRYPTO_OBJCACERT, 107 NULL, &OBJCACERT, ES_GET); 108 } 109 110 if (SECACERT == NULL) { 111 (void) elfcertlib_getcert(ess, 112 (char *)_PATH_CRYPTO_SECACERT, NULL, &SECACERT, 113 ES_GET_FIPS140); 114 } 115 116 (void) pthread_mutex_unlock(&ca_mutex); 117 118 if (CACERT != NULL) { 119 numattr = 0; 120 kmf_set_attr_at_index(attrlist, numattr++, 121 KMF_CERT_DATA_ATTR, &cert->c_cert.certificate, 122 sizeof (KMF_DATA)); 123 kmf_set_attr_at_index(attrlist, numattr++, 124 KMF_SIGNER_CERT_DATA_ATTR, &CACERT->c_cert.certificate, 125 sizeof (KMF_DATA)); 126 127 rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist); 128 if (rv == KMF_OK) { 129 if (ess->es_certCAcallback != NULL) 130 (ess->es_certvercallback)(ess->es_callbackctx, 131 cert, CACERT); 132 cert->c_verified = E_OK; 133 return (B_TRUE); 134 } 135 } 136 137 if (OBJCACERT != NULL) { 138 numattr = 0; 139 kmf_set_attr_at_index(attrlist, numattr++, 140 KMF_CERT_DATA_ATTR, &cert->c_cert.certificate, 141 sizeof (KMF_DATA)); 142 kmf_set_attr_at_index(attrlist, numattr++, 143 KMF_SIGNER_CERT_DATA_ATTR, &OBJCACERT->c_cert.certificate, 144 sizeof (KMF_DATA)); 145 146 rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist); 147 if (rv == KMF_OK) { 148 if (ess->es_certCAcallback != NULL) 149 (ess->es_certvercallback)(ess->es_callbackctx, 150 cert, OBJCACERT); 151 cert->c_verified = E_OK; 152 return (B_TRUE); 153 } 154 } 155 156 if (SECACERT != NULL) { 157 numattr = 0; 158 kmf_set_attr_at_index(attrlist, numattr++, 159 KMF_CERT_DATA_ATTR, &cert->c_cert.certificate, 160 sizeof (KMF_DATA)); 161 kmf_set_attr_at_index(attrlist, numattr++, 162 KMF_SIGNER_CERT_DATA_ATTR, &SECACERT->c_cert.certificate, 163 sizeof (KMF_DATA)); 164 165 rv = kmf_verify_cert(ess->es_kmfhandle, numattr, attrlist); 166 if (rv == KMF_OK) { 167 if (ess->es_certCAcallback != NULL) 168 (ess->es_certvercallback)(ess->es_callbackctx, 169 cert, SECACERT); 170 cert->c_verified = E_OK; 171 return (B_TRUE); 172 } 173 } 174 175 return (B_FALSE); 176 } 177 178 /* 179 * elfcertlib_getcert - Get the certificate for signer_DN 180 * 181 * IN ess - elfsign context structure 182 * cert_pathname - path to cert (May be NULL) 183 * signer_DN - The DN we are looking for (May be NULL) 184 * action - indicates crypto verification call 185 * OUT certp - allocated/loaded ELFCert_t 186 * 187 * If the cert_pathname is passed use it and don't search. 188 * Otherwise, go looking in certificate directories 189 */ 190 boolean_t 191 elfcertlib_getcert(ELFsign_t ess, char *cert_pathname, 192 char *signer_DN, ELFCert_t *certp, enum ES_ACTION action) 193 { 194 KMF_RETURN rv; 195 ELFCert_t cert = NULL; 196 KMF_X509_DER_CERT certbuf[2]; 197 uint32_t ncerts; 198 boolean_t ret = B_FALSE; 199 char *pathlist[3], **plp; 200 201 cryptodebug("elfcertlib_getcert: path=%s, DN=%s", 202 cert_pathname ? cert_pathname : "-none-", 203 signer_DN ? signer_DN : "-none-"); 204 *certp = NULL; 205 if (cert_pathname == NULL && signer_DN == NULL) { 206 cryptodebug("elfcertlib_getcert: lack of specificity"); 207 return (ret); 208 } 209 210 plp = pathlist; 211 if (cert_pathname != NULL) { 212 /* look in the specified object */ 213 *plp++ = cert_pathname; 214 } else { 215 /* look in the certificate directories */ 216 *plp++ = (char *)_PATH_ELFSIGN_CRYPTO_CERTS; 217 /* 218 * crypto verifications don't search beyond 219 * _PATH_ELFSIGN_CRYPTO_CERTS 220 */ 221 if (action != ES_GET_CRYPTO) 222 *plp++ = (char *)_PATH_ELFSIGN_ETC_CERTS; 223 } 224 *plp = NULL; 225 226 if ((cert = elfcertlib_allocatecert()) == NULL) { 227 return (ret); 228 } 229 230 for (plp = pathlist; *plp; plp++) { 231 KMF_ATTRIBUTE attrlist[8]; 232 KMF_KEYSTORE_TYPE kstype; 233 KMF_CERT_VALIDITY certvalidity; 234 int numattr; 235 236 kstype = KMF_KEYSTORE_OPENSSL; 237 certvalidity = KMF_ALL_CERTS; 238 ncerts = 2; 239 240 numattr = 0; 241 kmf_set_attr_at_index(attrlist, numattr++, 242 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 243 kmf_set_attr_at_index(attrlist, numattr++, 244 KMF_X509_DER_CERT_ATTR, certbuf, 245 sizeof (KMF_X509_DER_CERT)); 246 kmf_set_attr_at_index(attrlist, numattr++, 247 KMF_COUNT_ATTR, &ncerts, sizeof (uint32_t)); 248 if (signer_DN != NULL) { 249 kmf_set_attr_at_index(attrlist, numattr++, 250 KMF_SUBJECT_NAME_ATTR, signer_DN, 251 strlen(signer_DN)); 252 } 253 kmf_set_attr_at_index(attrlist, numattr++, 254 KMF_CERT_VALIDITY_ATTR, &certvalidity, 255 sizeof (KMF_CERT_VALIDITY)); 256 kmf_set_attr_at_index(attrlist, numattr++, 257 KMF_CERT_FILENAME_ATTR, *plp, strlen (*plp)); 258 259 rv = kmf_find_cert(ess->es_kmfhandle, numattr, attrlist); 260 261 if (rv != KMF_OK) 262 continue; 263 /* found one */ 264 cert->c_cert = certbuf[0]; 265 if (ncerts > 1) { 266 /* release any extras */ 267 kmf_free_kmf_cert(ess->es_kmfhandle, &certbuf[1]); 268 if (signer_DN == NULL) { 269 /* There can be only one */ 270 cryptodebug("elfcertlib_getcert: " 271 "too many certificates found in %s", 272 cert_pathname); 273 goto cleanup; 274 } 275 } 276 /* cache subject and issuer */ 277 rv = kmf_get_cert_subject_str(ess->es_kmfhandle, 278 &cert->c_cert.certificate, &cert->c_subject); 279 if (rv != KMF_OK) 280 goto cleanup; 281 282 rv = kmf_get_cert_issuer_str(ess->es_kmfhandle, 283 &cert->c_cert.certificate, &cert->c_issuer); 284 if (rv != KMF_OK) 285 goto cleanup; 286 break; 287 } 288 if (*plp == NULL) { 289 cryptodebug("elfcertlib_getcert: no certificate found"); 290 goto cleanup; 291 } 292 293 cert->c_verified = E_UNCHECKED; 294 295 /* 296 * If the cert we are loading is the trust anchor (ie the CA) then 297 * we mark it as such in cert. This is so that we don't attempt 298 * to verify it later. The CA is always implicitly verified. 299 */ 300 if (cert_pathname != NULL && ( 301 strcmp(cert_pathname, _PATH_CRYPTO_CACERT) == 0 || 302 strcmp(cert_pathname, _PATH_CRYPTO_OBJCACERT) == 0 || 303 strcmp(cert_pathname, _PATH_CRYPTO_SECACERT) == 0)) { 304 if (ess->es_certCAcallback != NULL) 305 (ess->es_certCAcallback)(ess->es_callbackctx, cert, 306 cert_pathname); 307 cert->c_verified = E_IS_TA; 308 } 309 310 ret = B_TRUE; 311 312 cleanup: 313 if (ret) { 314 *certp = cert; 315 } else { 316 if (cert != NULL) 317 elfcertlib_freecert(ess, cert); 318 if (signer_DN != NULL) 319 cryptoerror(LOG_ERR, "unable to find a certificate " 320 "for DN: %s", signer_DN); 321 else 322 cryptoerror(LOG_ERR, "unable to load certificate " 323 "from %s", cert_pathname); 324 } 325 return (ret); 326 } 327 328 /* 329 * elfcertlib_loadprivatekey - Load the private key from path 330 * 331 * IN ess - elfsign context structure 332 * cert 333 * pathname 334 * OUT cert 335 * RETURNS TRUE/FALSE 336 */ 337 boolean_t 338 elfcertlib_loadprivatekey(ELFsign_t ess, ELFCert_t cert, const char *pathname) 339 { 340 KMF_RETURN rv = KMF_OK; 341 KMF_KEY_HANDLE keybuf[2]; 342 KMF_ATTRIBUTE attrlist[16]; 343 uint32_t nkeys; 344 KMF_KEYSTORE_TYPE kstype; 345 KMF_KEY_ALG keytype; 346 KMF_KEY_CLASS keyclass; 347 KMF_ENCODE_FORMAT format; 348 int numattr; 349 350 kstype = KMF_KEYSTORE_OPENSSL; 351 nkeys = 2; 352 keytype = KMF_KEYALG_NONE; 353 keyclass = KMF_ASYM_PRI; 354 format = KMF_FORMAT_UNDEF; 355 356 numattr = 0; 357 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR, 358 &kstype, sizeof (kstype)); 359 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR, 360 keybuf, sizeof (KMF_KEY_HANDLE)); 361 kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR, 362 &nkeys, sizeof (uint32_t)); 363 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR, 364 &keytype, sizeof (keytype)); 365 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR, 366 &keyclass, sizeof (keyclass)); 367 kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR, 368 &format, sizeof (format)); 369 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_FILENAME_ATTR, 370 (char *)pathname, strlen(pathname)); 371 372 rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist); 373 if (rv != KMF_OK) 374 return (B_FALSE); 375 if (nkeys != 1) { 376 /* lack of specificity */ 377 cryptodebug("found %d keys at %s", nkeys, pathname); 378 return (B_FALSE); 379 } 380 cert->c_privatekey = keybuf[0]; 381 cryptodebug("key %s loaded", pathname); 382 return (B_TRUE); 383 } 384 385 /* 386 * elfcertlib_loadtokenkey - Load the private key from token 387 * 388 * IN ess - elfsign context structure 389 * cert 390 * token_label 391 * pin 392 * OUT cert 393 * RETURNS TRUE/FALSE 394 */ 395 boolean_t 396 elfcertlib_loadtokenkey(ELFsign_t ess, ELFCert_t cert, 397 const char *token_label, const char *pin) 398 { 399 KMF_RETURN rv; 400 char *idstr = NULL; 401 char *kmferr; 402 KMF_ATTRIBUTE attrlist[16]; 403 uint32_t nkeys; 404 KMF_KEYSTORE_TYPE kstype; 405 KMF_KEY_ALG keytype; 406 KMF_KEY_CLASS keyclass; 407 KMF_ENCODE_FORMAT format; 408 KMF_CREDENTIAL pincred; 409 boolean_t tokenbool, privatebool; 410 int numattr; 411 412 /* 413 * We will search for the key based on the ID attribute 414 * which was added when the key was created. ID is 415 * a SHA-1 hash of the public modulus shared by the 416 * key and the certificate. 417 */ 418 rv = kmf_get_cert_id_str(&cert->c_cert.certificate, &idstr); 419 if (rv != KMF_OK) { 420 (void) kmf_get_kmf_error_str(rv, &kmferr); 421 cryptodebug("Error getting ID from cert: %s\n", 422 (kmferr ? kmferr : "Unrecognized KMF error")); 423 free(kmferr); 424 return (B_FALSE); 425 } 426 427 kstype = KMF_KEYSTORE_PK11TOKEN; 428 nkeys = 1; 429 keytype = KMF_KEYALG_NONE; 430 keyclass = KMF_ASYM_PRI; 431 format = KMF_FORMAT_UNDEF; 432 pincred.cred = (char *)pin; 433 pincred.credlen = strlen(pin); 434 tokenbool = B_FALSE; 435 privatebool = B_TRUE; 436 437 numattr = 0; 438 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR, 439 &kstype, sizeof (kstype)); 440 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR, 441 &cert->c_privatekey, sizeof (KMF_KEY_HANDLE)); 442 kmf_set_attr_at_index(attrlist, numattr++, KMF_COUNT_ATTR, 443 &nkeys, sizeof (uint32_t)); 444 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYALG_ATTR, 445 &keytype, sizeof (keytype)); 446 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYCLASS_ATTR, 447 &keyclass, sizeof (keyclass)); 448 kmf_set_attr_at_index(attrlist, numattr++, KMF_ENCODE_FORMAT_ATTR, 449 &format, sizeof (format)); 450 kmf_set_attr_at_index(attrlist, numattr++, KMF_IDSTR_ATTR, 451 idstr, strlen(idstr)); 452 kmf_set_attr_at_index(attrlist, numattr++, KMF_CREDENTIAL_ATTR, 453 &pincred, sizeof (KMF_CREDENTIAL)); 454 kmf_set_attr_at_index(attrlist, numattr++, KMF_TOKEN_BOOL_ATTR, 455 &tokenbool, sizeof (tokenbool)); 456 kmf_set_attr_at_index(attrlist, numattr++, KMF_PRIVATE_BOOL_ATTR, 457 &privatebool, sizeof (privatebool)); 458 459 rv = kmf_find_key(ess->es_kmfhandle, numattr, attrlist); 460 free(idstr); 461 if (rv != KMF_OK) { 462 (void) kmf_get_kmf_error_str(rv, &kmferr); 463 cryptodebug("Error finding private key: %s\n", 464 (kmferr ? kmferr : "Unrecognized KMF error")); 465 free(kmferr); 466 return (B_FALSE); 467 } 468 if (nkeys != 1) { 469 cryptodebug("Error finding private key: No key found\n"); 470 return (B_FALSE); 471 } 472 cryptodebug("key found in %s", token_label); 473 cryptodebug("elfcertlib_loadprivatekey = 0x%.8X", 474 &cert->c_privatekey); 475 476 return (B_TRUE); 477 } 478 479 static const CK_BYTE MD5_DER_PREFIX[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 480 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}; 481 482 /* 483 * elfcertlib_sign - sign the given DATA using the privatekey in cert 484 * 485 * IN ess - elfsign context structure 486 * cert 487 * data 488 * data_len 489 * OUT sig - must be big enough to hold the signature of data 490 * Caller must allocate 491 * sig_len - actual length used; 0 on failure. 492 * RETURNS TRUE/FALSE 493 */ 494 /*ARGSUSED*/ 495 boolean_t 496 elfcertlib_sign(ELFsign_t ess, ELFCert_t cert, 497 const uchar_t *data, size_t data_len, 498 uchar_t *sig, size_t *sig_len) 499 { 500 KMF_RETURN ret; 501 KMF_DATA tobesigned; 502 KMF_DATA signature; 503 uchar_t der_data[sizeof (MD5_DER_PREFIX) + MD5_DIGEST_LENGTH]; 504 KMF_ATTRIBUTE attrlist[8]; 505 int numattr; 506 507 if (ess->es_version <= FILESIG_VERSION2) { 508 /* compatibility: take MD5 hash of SHA1 hash */ 509 size_t derlen = MD5_DIGEST_LENGTH; 510 MD5_CTX ctx; 511 512 /* 513 * first: digest using software-based methods, don't 514 * rely on the token for hashing. 515 */ 516 MD5Init(&ctx); 517 MD5Update(&ctx, data, data_len); 518 MD5Final(&der_data[sizeof (MD5_DER_PREFIX)], &ctx); 519 520 /* 521 * second: insert prefix 522 */ 523 (void) memcpy(der_data, MD5_DER_PREFIX, 524 sizeof (MD5_DER_PREFIX)); 525 /* 526 * prepare to sign the local buffer 527 */ 528 tobesigned.Data = (uchar_t *)der_data; 529 tobesigned.Length = sizeof (MD5_DER_PREFIX) + derlen; 530 } else { 531 tobesigned.Data = (uchar_t *)data; 532 tobesigned.Length = data_len; 533 } 534 535 signature.Data = (uchar_t *)sig; 536 signature.Length = *sig_len; 537 538 numattr = 0; 539 kmf_set_attr_at_index(attrlist, numattr++, 540 KMF_KEYSTORE_TYPE_ATTR, &(cert->c_privatekey.kstype), 541 sizeof (KMF_KEYSTORE_TYPE)); 542 kmf_set_attr_at_index(attrlist, numattr++, 543 KMF_KEY_HANDLE_ATTR, &cert->c_privatekey, sizeof (KMF_KEY_HANDLE)); 544 kmf_set_attr_at_index(attrlist, numattr++, 545 KMF_OID_ATTR, (KMF_OID *)&KMFOID_RSA, sizeof (KMF_OID)); 546 kmf_set_attr_at_index(attrlist, numattr++, 547 KMF_DATA_ATTR, &tobesigned, sizeof (KMF_DATA)); 548 kmf_set_attr_at_index(attrlist, numattr++, 549 KMF_OUT_DATA_ATTR, &signature, sizeof (KMF_DATA)); 550 551 ret = kmf_sign_data(ess->es_kmfhandle, numattr, attrlist); 552 553 if (ret != KMF_OK) { 554 char *kmferr; 555 556 (void) kmf_get_kmf_error_str(ret, &kmferr); 557 cryptodebug("Error signing data: %s\n", 558 (kmferr ? kmferr : "Unrecognized KMF error")); 559 free(kmferr); 560 *sig_len = 0; 561 return (B_FALSE); 562 } 563 *sig_len = signature.Length; 564 return (B_TRUE); 565 } 566 567 /* 568 * elfcertlib_verifysig - verify the given DATA using the public key in cert 569 * 570 * IN ess - elfsign context structure 571 * cert 572 * signature 573 * sig_len 574 * data 575 * data_len 576 * OUT N/A 577 * RETURNS TRUE/FALSE 578 */ 579 boolean_t 580 elfcertlib_verifysig(ELFsign_t ess, ELFCert_t cert, 581 const uchar_t *signature, size_t sig_len, 582 const uchar_t *data, size_t data_len) 583 { 584 KMF_RETURN rv; 585 KMF_DATA indata; 586 KMF_DATA insig; 587 KMF_ALGORITHM_INDEX algid; 588 KMF_ATTRIBUTE attrlist[8]; 589 KMF_KEYSTORE_TYPE kstype; 590 int numattr; 591 592 indata.Data = (uchar_t *)data; 593 indata.Length = data_len; 594 insig.Data = (uchar_t *)signature; 595 insig.Length = sig_len; 596 597 if (ess->es_version <= FILESIG_VERSION2) 598 algid = KMF_ALGID_MD5WithRSA; 599 else 600 algid = KMF_ALGID_RSA; 601 602 /* 603 * We tell KMF to use the PKCS11 verification APIs 604 * here to prevent the use of OpenSSL and to keep 605 * all validation within the FIPS-140 boundary for 606 * the Cryptographic Framework. 607 */ 608 kstype = KMF_KEYSTORE_PK11TOKEN; 609 610 numattr = 0; 611 kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR, 612 &kstype, sizeof (kstype)); 613 kmf_set_attr_at_index(attrlist, numattr++, KMF_DATA_ATTR, 614 &indata, sizeof (KMF_DATA)); 615 kmf_set_attr_at_index(attrlist, numattr++, KMF_IN_SIGN_ATTR, 616 &insig, sizeof (KMF_DATA)); 617 kmf_set_attr_at_index(attrlist, numattr++, KMF_SIGNER_CERT_DATA_ATTR, 618 (KMF_DATA *)(&cert->c_cert.certificate), sizeof (KMF_DATA)); 619 kmf_set_attr_at_index(attrlist, numattr++, KMF_ALGORITHM_INDEX_ATTR, 620 &algid, sizeof (algid)); 621 622 rv = kmf_verify_data(ess->es_kmfhandle, numattr, attrlist); 623 624 return ((rv == KMF_OK)); 625 } 626 627 /* 628 * elfcertlib_getdn 629 * 630 * IN cert 631 * OUT NONE 632 * RETURN dn or NULL 633 */ 634 char * 635 elfcertlib_getdn(ELFCert_t cert) 636 { 637 cryptodebug("elfcertlib_getdn"); 638 639 return (cert->c_subject); 640 } 641 642 /* 643 * elfcertlib_getissuer 644 * 645 * IN cert 646 * OUT NONE 647 * RETURN dn or NULL 648 */ 649 char * 650 elfcertlib_getissuer(ELFCert_t cert) 651 { 652 cryptodebug("elfcertlib_issuer"); 653 654 return (cert->c_issuer); 655 } 656 657 boolean_t 658 elfcertlib_init(ELFsign_t ess) 659 { 660 boolean_t rc = B_TRUE; 661 KMF_RETURN rv; 662 if (ess->es_kmfhandle == NULL) { 663 rv = kmf_initialize(&ess->es_kmfhandle, NULL, NULL); 664 if (rv != KMF_OK) { 665 cryptoerror(LOG_ERR, 666 "unable to initialize KMF library"); 667 rc = B_FALSE; 668 } 669 } 670 return (rc); 671 } 672 673 void 674 elfcertlib_fini(ELFsign_t ess) 675 { 676 (void) kmf_finalize(ess->es_kmfhandle); 677 } 678 679 /* 680 * set the token device 681 */ 682 boolean_t 683 elfcertlib_settoken(ELFsign_t ess, char *token) 684 { 685 boolean_t rc = B_TRUE; 686 KMF_RETURN rv; 687 KMF_ATTRIBUTE attrlist[8]; 688 KMF_KEYSTORE_TYPE kstype; 689 boolean_t readonly; 690 int numattr; 691 692 kstype = KMF_KEYSTORE_PK11TOKEN; 693 readonly = B_TRUE; 694 695 numattr = 0; 696 kmf_set_attr_at_index(attrlist, numattr++, 697 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 698 kmf_set_attr_at_index(attrlist, numattr++, 699 KMF_TOKEN_LABEL_ATTR, token, strlen(token)); 700 kmf_set_attr_at_index(attrlist, numattr++, 701 KMF_READONLY_ATTR, &readonly, sizeof (readonly)); 702 703 rv = kmf_configure_keystore(ess->es_kmfhandle, numattr, attrlist); 704 if (rv != KMF_OK) { 705 cryptoerror(LOG_ERR, "unable to select token\n"); 706 rc = B_FALSE; 707 } 708 709 return (rc); 710 } 711 712 /* 713 * set the certificate CA identification callback 714 */ 715 void 716 elfcertlib_setcertCAcallback(ELFsign_t ess, 717 void (*cb)(void *, ELFCert_t, char *)) 718 { 719 ess->es_certCAcallback = cb; 720 } 721 722 /* 723 * set the certificate verification callback 724 */ 725 void 726 elfcertlib_setcertvercallback(ELFsign_t ess, 727 void (*cb)(void *, ELFCert_t, ELFCert_t)) 728 { 729 ess->es_certvercallback = cb; 730 } 731 732 733 /* 734 * elfcertlib_releasecert - release a cert 735 * 736 * IN cert 737 * OUT cert 738 * RETURN N/A 739 * 740 */ 741 void 742 elfcertlib_releasecert(ELFsign_t ess, ELFCert_t cert) 743 { 744 elfcertlib_freecert(ess, cert); 745 } 746 747 /* 748 * elfcertlib_allocatecert - create a new ELFCert_t 749 * 750 * IN N/A 751 * OUT N/A 752 * RETURN ELFCert_t, NULL on failure. 753 */ 754 static ELFCert_t 755 elfcertlib_allocatecert(void) 756 { 757 ELFCert_t cert = NULL; 758 759 cert = malloc(sizeof (struct ELFCert_s)); 760 if (cert == NULL) { 761 cryptoerror(LOG_ERR, 762 "elfcertlib_allocatecert: malloc failed %s", 763 strerror(errno)); 764 return (NULL); 765 } 766 (void) memset(cert, 0, sizeof (struct ELFCert_s)); 767 cert->c_verified = E_UNCHECKED; 768 cert->c_subject = NULL; 769 cert->c_issuer = NULL; 770 return (cert); 771 } 772 773 /* 774 * elfcertlib_freecert - freeup the memory of a cert 775 * 776 * IN cert 777 * OUT cert 778 * RETURN N/A 779 * 780 */ 781 static void 782 elfcertlib_freecert(ELFsign_t ess, ELFCert_t cert) 783 { 784 if (cert == NULL) 785 return; 786 787 free(cert->c_subject); 788 free(cert->c_issuer); 789 790 kmf_free_kmf_cert(ess->es_kmfhandle, &cert->c_cert); 791 kmf_free_kmf_key(ess->es_kmfhandle, &cert->c_privatekey); 792 793 free(cert); 794 } 795