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