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