kssladm_create.c revision 3408:67ca9373b99e
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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#include <errno.h> 30#include <sys/sysmacros.h> 31#include <security/cryptoki.h> 32#include <security/pkcs11.h> 33#include <stdio.h> 34#include <strings.h> 35#include <sys/types.h> 36#include <sys/stat.h> 37#include <sys/socket.h> 38#include <netinet/in.h> 39#include <arpa/inet.h> 40#include <netdb.h> 41#include <fcntl.h> 42#include <inet/kssl/kssl.h> 43#include <cryptoutil.h> 44#include <libscf.h> 45#include "kssladm.h" 46 47#include <kmfapi.h> 48 49void 50usage_create(boolean_t do_print) 51{ 52 if (do_print) 53 (void) fprintf(stderr, "Usage:\n"); 54 (void) fprintf(stderr, "kssladm create" 55 " -f pkcs11 [-d softtoken_directory] -T <token_label>" 56 " -C <certificate_label> -x <proxy_port>" 57 " [-h <ca_certchain_file>]" 58 " [options] [<server_address>] [<server_port>]\n"); 59 60 (void) fprintf(stderr, "kssladm create" 61 " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>" 62 " [options] [<server_address>] [<server_port>]\n"); 63 64 (void) fprintf(stderr, "kssladm create" 65 " -f pem -i <cert_and_key_pemfile> -x <proxy_port>" 66 " [options] [<server_address>] [<server_port>]\n"); 67 68 (void) fprintf(stderr, "options are:\n" 69 "\t[-c <ciphersuites>]\n" 70 "\t[-p <password_file>]\n" 71 "\t[-t <ssl_session_cache_timeout>]\n" 72 "\t[-z <ssl_session_cache_size>]\n" 73 "\t[-v]\n"); 74} 75 76/* 77 * Everything is allocated in one single contiguous buffer. 78 * The layout is the following: 79 * . the kssl_params_t structure 80 * . optional buffer containing pin (if key is non extractable) 81 * . the array of key attribute structs, (value of ck_attrs) 82 * . the key attributes values (values of ck_attrs[i].ck_value); 83 * . the array of sizes of the certificates, (referred to as sc_sizes[]) 84 * . the certificates values (referred to as sc_certs[]) 85 * 86 * The address of the certs and key attributes values are offsets 87 * from the beginning of the big buffer. sc_sizes_offset points 88 * to sc_sizes[0] and sc_certs_offset points to sc_certs[0]. 89 */ 90static kssl_params_t * 91kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts, 92 KMF_DATA *certs, int *paramsize, char *token_label, KMF_DATA *idstr, 93 KMF_CREDENTIAL *creds) 94{ 95 int i, tcsize; 96 kssl_params_t *kssl_params; 97 kssl_key_t *key; 98 char *buf; 99 uint32_t bufsize; 100 static CK_BBOOL true = TRUE; 101 static CK_BBOOL false = FALSE; 102 static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; 103 static CK_KEY_TYPE keytype = CKK_RSA; 104 kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT]; 105 CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = { 106 {CKA_TOKEN, &true, sizeof (true)}, 107 {CKA_EXTRACTABLE, &false, sizeof (false)}, 108 {CKA_CLASS, &class, sizeof (class) }, 109 {CKA_KEY_TYPE, &keytype, sizeof (keytype) }, 110 {CKA_ID, NULL, 0} 111 }; 112 kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = { 113 {SUN_CKA_MODULUS, NULL, 0}, 114 {SUN_CKA_PUBLIC_EXPONENT, NULL, 0}, 115 {SUN_CKA_PRIVATE_EXPONENT, NULL, 0}, 116 {SUN_CKA_PRIME_1, NULL, 0}, 117 {SUN_CKA_PRIME_2, NULL, 0}, 118 {SUN_CKA_EXPONENT_1, NULL, 0}, 119 {SUN_CKA_EXPONENT_2, NULL, 0}, 120 {SUN_CKA_COEFFICIENT, NULL, 0} 121 }; 122 KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT]; 123 int attr_cnt; 124 125 if (nxkey && idstr != NULL) { 126 exkey_attrs[4].pValue = idstr->Data; 127 exkey_attrs[4].ulValueLen = idstr->Length; 128 } 129 tcsize = 0; 130 for (i = 0; i < ncerts; i++) 131 tcsize += certs[i].Length; 132 133 bufsize = sizeof (kssl_params_t); 134 bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t))); 135 136 if (!nxkey) { 137 bzero(priv_key_bignums, sizeof (KMF_BIGINT) * 138 MAX_ATTR_CNT); 139 /* and the key attributes */ 140 priv_key_bignums[0] = rsa->rawdata.rsa.mod; 141 priv_key_bignums[1] = rsa->rawdata.rsa.pubexp; 142 priv_key_bignums[2] = rsa->rawdata.rsa.priexp; 143 priv_key_bignums[3] = rsa->rawdata.rsa.prime1; 144 priv_key_bignums[4] = rsa->rawdata.rsa.prime2; 145 priv_key_bignums[5] = rsa->rawdata.rsa.exp1; 146 priv_key_bignums[6] = rsa->rawdata.rsa.exp2; 147 priv_key_bignums[7] = rsa->rawdata.rsa.coef; 148 149 if (rsa->rawdata.rsa.mod.val == NULL || 150 rsa->rawdata.rsa.priexp.val == NULL) { 151 (void) fprintf(stderr, 152 "missing required attributes in private key.\n"); 153 return (NULL); 154 } 155 156 attr_cnt = 0; 157 for (i = 0; i < MAX_ATTR_CNT; i++) { 158 if (priv_key_bignums[i].val == NULL) 159 continue; 160 kssl_attrs[attr_cnt].ka_type = 161 kssl_tmpl_attrs[i].ka_type; 162 kssl_attrs[attr_cnt].ka_value_len = 163 priv_key_bignums[i].len; 164 bufsize += sizeof (crypto_object_attribute_t) + 165 kssl_attrs[attr_cnt].ka_value_len; 166 attr_cnt++; 167 } 168 } else { 169 /* 170 * Compute space for the attributes and values that the 171 * kssl kernel module will need in order to search for 172 * the private key. 173 */ 174 for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) { 175 bufsize += sizeof (crypto_object_attribute_t) + 176 exkey_attrs[attr_cnt].ulValueLen; 177 } 178 if (creds) 179 bufsize += creds->credlen; 180 } 181 182 /* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */ 183 bufsize += sizeof (uint32_t); 184 185 /* Now the big memory allocation */ 186 if ((buf = calloc(bufsize, 1)) == NULL) { 187 (void) fprintf(stderr, 188 "Cannot allocate memory for the kssl_params " 189 "and values\n"); 190 return (NULL); 191 } 192 193 /* LINTED */ 194 kssl_params = (kssl_params_t *)buf; 195 196 buf = (char *)(kssl_params + 1); 197 198 if (!nxkey) { 199 /* the keys attributes structs array */ 200 key = &kssl_params->kssl_privkey; 201 key->ks_format = CRYPTO_KEY_ATTR_LIST; 202 key->ks_count = attr_cnt; 203 key->ks_attrs_offset = buf - (char *)kssl_params; 204 buf += attr_cnt * sizeof (kssl_object_attribute_t); 205 206 attr_cnt = 0; 207 /* then the key attributes values */ 208 for (i = 0; i < MAX_ATTR_CNT; i++) { 209 if (priv_key_bignums[i].val == NULL) 210 continue; 211 (void) memcpy(buf, priv_key_bignums[i].val, 212 priv_key_bignums[i].len); 213 kssl_attrs[attr_cnt].ka_value_offset = 214 buf - (char *)kssl_params; 215 buf += kssl_attrs[attr_cnt].ka_value_len; 216 attr_cnt++; 217 } 218 } else { 219 char tlabel[CRYPTO_EXT_SIZE_LABEL]; 220 bzero(tlabel, sizeof (tlabel)); 221 (void) strlcpy(tlabel, token_label, sizeof (tlabel)); 222 223 /* 224 * For a non-extractable key, we must provide the PIN 225 * so the kssl module can access the token to find 226 * the key handle. 227 */ 228 kssl_params->kssl_is_nxkey = 1; 229 bcopy(tlabel, kssl_params->kssl_token.toklabel, 230 CRYPTO_EXT_SIZE_LABEL); 231 kssl_params->kssl_token.pinlen = creds->credlen; 232 kssl_params->kssl_token.tokpin_offset = 233 buf - (char *)kssl_params; 234 kssl_params->kssl_token.ck_rv = 0; 235 bcopy(creds->cred, buf, creds->credlen); 236 buf += creds->credlen; 237 238 /* 239 * Next in the buffer, we must provide the attributes 240 * that the kssl module will use to search in the 241 * token to find the protected key handle. 242 */ 243 key = &kssl_params->kssl_privkey; 244 key->ks_format = CRYPTO_KEY_ATTR_LIST; 245 key->ks_count = attr_cnt; 246 key->ks_attrs_offset = buf - (char *)kssl_params; 247 248 buf += attr_cnt * sizeof (kssl_object_attribute_t); 249 for (i = 0; i < attr_cnt; i++) { 250 bcopy(exkey_attrs[i].pValue, buf, 251 exkey_attrs[i].ulValueLen); 252 253 kssl_attrs[i].ka_type = exkey_attrs[i].type; 254 kssl_attrs[i].ka_value_offset = 255 buf - (char *)kssl_params; 256 kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen; 257 258 buf += exkey_attrs[i].ulValueLen; 259 } 260 } 261 /* Copy the key attributes array here */ 262 bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, 263 attr_cnt * sizeof (kssl_object_attribute_t)); 264 265 buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); 266 267 /* 268 * Finally, add the certificate chain to the buffer. 269 */ 270 kssl_params->kssl_certs.sc_count = ncerts; 271 272 /* First, an array of certificate sizes */ 273 for (i = 0; i < ncerts; i++) { 274 uint32_t certsz = (uint32_t)certs[i].Length; 275 char *p = buf + (i * sizeof (uint32_t)); 276 bcopy(&certsz, p, sizeof (uint32_t)); 277 } 278 279 kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params; 280 buf += MAX_CHAIN_LENGTH * sizeof (uint32_t); 281 282 kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params; 283 284 /* Now add the certificate data (ASN.1 DER encoded) */ 285 for (i = 0; i < ncerts; i++) { 286 bcopy(certs[i].Data, buf, certs[i].Length); 287 buf += certs[i].Length; 288 } 289 290 *paramsize = bufsize; 291 return (kssl_params); 292} 293 294/* 295 * Extract a sensitive key via wrap/unwrap operations. 296 * 297 * This function requires that we call PKCS#11 API directly since 298 * KMF does not yet support wrapping/unwrapping of keys. By extracting 299 * a sensitive key in wrapped form, we then unwrap it into a session key 300 * object. KMF is then used to find the session key and return it in 301 * KMF_RAW_KEY format which is then passed along to KSSL by the caller. 302 */ 303static KMF_RETURN 304get_sensitive_key_data(KMF_HANDLE_T kmfh, KMF_FINDKEY_PARAMS *fkparams, 305 KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey) 306{ 307 KMF_RETURN rv = KMF_OK; 308 static CK_BYTE aes_param[16]; 309 static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY; 310 static CK_KEY_TYPE privkey_type = CKK_RSA; 311 static CK_BBOOL true = TRUE; 312 static CK_BBOOL false = FALSE; 313 char *err = NULL; 314 char wrapkey_label[BUFSIZ]; 315 int fd; 316 uint32_t nkeys = 0; 317 CK_RV ckrv; 318 CK_SESSION_HANDLE pk11session; 319 CK_BYTE aes_key_val[16]; 320 321 CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, 322 sizeof (aes_param)}; 323 CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE; 324 CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE; 325 CK_BYTE *wrapped_privkey = NULL; 326 CK_ULONG wrapped_privkey_len = 0; 327 328 CK_ATTRIBUTE unwrap_tmpl[] = { 329 /* code below depends on the following attribute order */ 330 {CKA_TOKEN, &false, sizeof (false)}, 331 {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, 332 {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}, 333 {CKA_SENSITIVE, &false, sizeof (false)}, 334 {CKA_PRIVATE, &false, sizeof (false)}, 335 {CKA_LABEL, NULL, 0} 336 }; 337 338 /* 339 * Create a wrap key with random data. 340 */ 341 fd = open("/dev/urandom", O_RDONLY); 342 if (fd == -1) { 343 perror("Error reading /dev/urandom"); 344 return (KMF_ERR_INTERNAL); 345 } 346 if (read(fd, aes_key_val, sizeof (aes_key_val)) != 347 sizeof (aes_key_val)) { 348 perror("Error reading from /dev/urandom"); 349 (void) close(fd); 350 return (KMF_ERR_INTERNAL); 351 } 352 (void) close(fd); 353 354 pk11session = KMF_GetPK11Handle(kmfh); 355 356 /* 357 * Login to create the wrap key stuff. 358 */ 359 ckrv = C_Login(pk11session, CKU_USER, 360 (CK_UTF8CHAR_PTR)fkparams->cred.cred, 361 fkparams->cred.credlen); 362 if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) { 363 (void) fprintf(stderr, 364 "Cannot login to the token. error = %s\n", 365 pkcs11_strerror(ckrv)); 366 return (KMF_ERR_INTERNAL); 367 } 368 369 /* 370 * Turn the random key into a PKCS#11 session object. 371 */ 372 ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val, 373 sizeof (aes_key_val), &aes_key_obj); 374 if (ckrv != CKR_OK) { 375 (void) fprintf(stderr, 376 "Cannot create wrapping key. error = %s\n", 377 pkcs11_strerror(ckrv)); 378 return (KMF_ERR_INTERNAL); 379 } 380 381 /* 382 * Find the original private key that we are going to wrap. 383 */ 384 rv = KMF_FindKey(kmfh, fkparams, key, &nkeys); 385 if (rv != KMF_OK) { 386 REPORT_KMF_ERROR(rv, "Error finding private key", err); 387 goto out; 388 } 389 390 /* 391 * Get the size of the wrapped private key. 392 */ 393 bzero(aes_param, sizeof (aes_param)); 394 ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech, 395 aes_key_obj, (CK_OBJECT_HANDLE)key->keyp, 396 NULL, &wrapped_privkey_len); 397 if (ckrv != CKR_OK) { 398 /* 399 * Most common error here is that the token doesn't 400 * support the wrapping mechanism or the key is 401 * marked non-extractable. Return an error and let 402 * the caller deal with it gracefully. 403 */ 404 (void) fprintf(stderr, 405 "Cannot get wrap key size. error = %s\n", 406 pkcs11_strerror(ckrv)); 407 rv = KMF_ERR_INTERNAL; 408 goto out; 409 } 410 wrapped_privkey = malloc(wrapped_privkey_len); 411 if (wrapped_privkey == NULL) { 412 rv = KMF_ERR_MEMORY; 413 goto out; 414 } 415 /* 416 * Now get the actual wrapped key data. 417 */ 418 ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech, 419 aes_key_obj, (CK_OBJECT_HANDLE)key->keyp, 420 wrapped_privkey, &wrapped_privkey_len); 421 if (ckrv != CKR_OK) { 422 (void) fprintf(stderr, 423 "Cannot wrap private key. error = %s\n", 424 pkcs11_strerror(ckrv)); 425 rv = KMF_ERR_INTERNAL; 426 goto out; 427 } 428 /* 429 * Create a label for the wrapped session key so we can find 430 * it easier later. 431 */ 432 snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d", 433 getpid()); 434 435 unwrap_tmpl[5].pValue = wrapkey_label; 436 unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label); 437 438 /* 439 * Unwrap the key into the template and create a temporary 440 * session private key. 441 */ 442 ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj, 443 wrapped_privkey, wrapped_privkey_len, 444 unwrap_tmpl, 6, &sess_privkey_obj); 445 if (ckrv != CKR_OK) { 446 (void) fprintf(stderr, 447 "Cannot unwrap private key. error = %s\n", 448 pkcs11_strerror(ckrv)); 449 rv = KMF_ERR_INTERNAL; 450 goto out; 451 } 452 453 /* 454 * Use KMF to find the session key and return it as RAW data 455 * so we can pass it along to KSSL. 456 */ 457 fkparams->kstype = KMF_KEYSTORE_PK11TOKEN; 458 fkparams->keyclass = KMF_ASYM_PRI; 459 fkparams->format = KMF_FORMAT_RAWKEY; 460 fkparams->findLabel = wrapkey_label; 461 fkparams->pkcs11parms.sensitive = FALSE; 462 fkparams->pkcs11parms.private = FALSE; 463 fkparams->pkcs11parms.token = FALSE; /* <-- very important! */ 464 465 rv = KMF_FindKey(kmfh, fkparams, rawkey, &nkeys); 466 if (rv != KMF_OK) { 467 REPORT_KMF_ERROR(rv, "Error finding raw private key", err); 468 goto out; 469 } 470out: 471 if (wrapped_privkey) 472 free(wrapped_privkey); 473 474 if (aes_key_obj != CK_INVALID_HANDLE) 475 C_DestroyObject(pk11session, aes_key_obj); 476 477 if (sess_privkey_obj != CK_INVALID_HANDLE) 478 C_DestroyObject(pk11session, sess_privkey_obj); 479 480 return (rv); 481} 482 483static kssl_params_t * 484load_from_pkcs11(const char *token_label, const char *password_file, 485 const char *certname, int *bufsize) 486{ 487 KMF_RETURN rv; 488 KMF_HANDLE_T kmfh; 489 KMF_X509_DER_CERT cert; 490 KMF_KEY_HANDLE key, rawkey; 491 KMF_CREDENTIAL creds; 492 KMF_FINDCERT_PARAMS fcparams; 493 KMF_FINDKEY_PARAMS fkparams; 494 KMF_CONFIG_PARAMS cfgparams; 495 KMF_DATA iddata = { NULL, 0 }; 496 kssl_params_t *kssl_params = NULL; 497 uint32_t ncerts, nkeys; 498 char *err, *idstr = NULL; 499 char password_buf[1024]; 500 int nxkey = 0; 501 502 rv = KMF_Initialize(&kmfh, NULL, NULL); 503 if (rv != KMF_OK) { 504 REPORT_KMF_ERROR(rv, "Error initializing KMF", err); 505 return (0); 506 } 507 if (get_passphrase(password_file, password_buf, 508 sizeof (password_buf)) <= 0) { 509 perror("Unable to read passphrase"); 510 goto done; 511 } 512 creds.cred = password_buf; 513 creds.credlen = strlen(password_buf); 514 515 bzero(&cfgparams, sizeof (cfgparams)); 516 bzero(&fcparams, sizeof (fcparams)); 517 bzero(&fkparams, sizeof (fkparams)); 518 519 cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN; 520 cfgparams.pkcs11config.label = (char *)token_label; 521 cfgparams.pkcs11config.readonly = B_FALSE; 522 523 rv = KMF_ConfigureKeystore(kmfh, &cfgparams); 524 if (rv != KMF_OK) { 525 REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err); 526 goto done; 527 } 528 529 /* 530 * Find the certificate matching the given label. 531 */ 532 fcparams.kstype = KMF_KEYSTORE_PK11TOKEN; 533 fcparams.certLabel = (char *)certname; 534 rv = KMF_FindCert(kmfh, &fcparams, &cert, &ncerts); 535 if (rv != KMF_OK || ncerts == 0) 536 goto done; 537 538 /* 539 * Find the associated private key for this cert by 540 * keying off of the label and the ASCII ID string. 541 */ 542 rv = KMF_GetCertIDString(&cert.certificate, &idstr); 543 if (rv != KMF_OK) 544 goto done; 545 546 fkparams.kstype = KMF_KEYSTORE_PK11TOKEN; 547 fkparams.keyclass = KMF_ASYM_PRI; 548 fkparams.cred = creds; 549 fkparams.format = KMF_FORMAT_RAWKEY; 550 fkparams.findLabel = (char *)certname; 551 fkparams.idstr = idstr; 552 fkparams.pkcs11parms.private = TRUE; 553 fkparams.pkcs11parms.token = TRUE; 554 555 rv = KMF_FindKey(kmfh, &fkparams, &key, &nkeys); 556 if (rv == KMF_ERR_SENSITIVE_KEY) { 557 KMF_FreeKMFKey(kmfh, &key); 558 /* 559 * Get a normal key handle and then do a wrap/unwrap 560 * in order to get the necessary raw data fields needed 561 * to send to KSSL. 562 */ 563 fkparams.format = KMF_FORMAT_NATIVE; 564 rv = get_sensitive_key_data(kmfh, &fkparams, &key, &rawkey); 565 if (rv == KMF_OK) { 566 /* Swap "key" for "rawkey" */ 567 KMF_FreeKMFKey(kmfh, &key); 568 569 key = rawkey; 570 } else { 571 KMF_FreeKMFKey(kmfh, &key); 572 573 /* Let kssl try to find the key. */ 574 nxkey = 1; 575 rv = KMF_GetCertIDData(&cert.certificate, &iddata); 576 } 577 } else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) { 578 KMF_FreeKMFKey(kmfh, &key); 579 580 /* Let kssl try to find the key. */ 581 nxkey = 1; 582 rv = KMF_GetCertIDData(&cert.certificate, &iddata); 583 } else if (rv != KMF_OK || nkeys == 0) 584 goto done; 585 586 if (rv == KMF_OK) 587 kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp, 588 1, &cert.certificate, bufsize, 589 (char *)token_label, &iddata, &creds); 590done: 591 if (ncerts != 0) 592 KMF_FreeKMFCert(kmfh, &cert); 593 if (nkeys != 0) 594 KMF_FreeKMFKey(kmfh, &key); 595 if (idstr) 596 free(idstr); 597 598 if (kmfh != NULL) 599 (void) KMF_Finalize(kmfh); 600 601 return (kssl_params); 602} 603 604/* 605 * add_cacerts 606 * 607 * Load a chain of certificates from a PEM file. 608 */ 609static kssl_params_t * 610add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file) 611{ 612 int i, newlen; 613 uint32_t certlen = 0, ncerts; 614 char *buf; 615 KMF_RETURN rv; 616 KMF_X509_DER_CERT *certs = NULL; 617 KMF_FINDCERT_PARAMS fcparms; 618 kssl_params_t *kssl_params; 619 KMF_HANDLE_T kmfh; 620 char *err = NULL; 621 622 bzero(&fcparms, sizeof (fcparms)); 623 fcparms.kstype = KMF_KEYSTORE_OPENSSL; 624 fcparms.sslparms.certfile = (char *)cacert_chain_file; 625 626 rv = KMF_Initialize(&kmfh, NULL, NULL); 627 if (rv != KMF_OK) { 628 REPORT_KMF_ERROR(rv, "Error initializing KMF", err); 629 return (0); 630 } 631 rv = KMF_FindCert(kmfh, &fcparms, NULL, &ncerts); 632 if (rv != KMF_OK) { 633 REPORT_KMF_ERROR(rv, "Error finding CA certificates", err); 634 (void) KMF_Finalize(kmfh); 635 return (0); 636 } 637 certs = (KMF_X509_DER_CERT *)malloc(ncerts * 638 sizeof (KMF_X509_DER_CERT)); 639 if (certs == NULL) { 640 (void) fprintf(stderr, "memory allocation error.\n"); 641 (void) KMF_Finalize(kmfh); 642 return (NULL); 643 } 644 bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT)); 645 rv = KMF_FindCert(kmfh, &fcparms, certs, &ncerts); 646 647 (void) KMF_Finalize(kmfh); 648 649 if (rv != KMF_OK || ncerts == 0) { 650 bzero(old_params, old_params->kssl_params_size); 651 free(old_params); 652 return (NULL); 653 } 654 655 if (verbose) { 656 (void) printf("%d certificates read successfully\n", ncerts); 657 } 658 659 newlen = old_params->kssl_params_size; 660 for (i = 0; i < ncerts; i++) 661 newlen += certs[i].certificate.Length; 662 663 /* 664 * Get a bigger structure and update the 665 * fields to account for the additional certs. 666 */ 667 kssl_params = realloc(old_params, newlen); 668 669 kssl_params->kssl_params_size = newlen; 670 kssl_params->kssl_certs.sc_count += ncerts; 671 672 /* Put the cert size info starting from sc_sizes[1] */ 673 buf = (char *)kssl_params; 674 buf += kssl_params->kssl_certs.sc_sizes_offset; 675 bcopy(buf, &certlen, sizeof (uint32_t)); 676 buf += sizeof (uint32_t); 677 for (i = 0; i < ncerts; i++) { 678 uint32_t size = (uint32_t)certs[i].certificate.Length; 679 bcopy(&size, buf, sizeof (uint32_t)); 680 buf += sizeof (uint32_t); 681 } 682 683 /* Put the cert_bufs starting from sc_certs[1] */ 684 buf = (char *)kssl_params; 685 buf += kssl_params->kssl_certs.sc_certs_offset; 686 buf += certlen; 687 688 /* now the certs values */ 689 for (i = 0; i < ncerts; i++) { 690 bcopy(certs[i].certificate.Data, buf, 691 certs[i].certificate.Length); 692 buf += certs[i].certificate.Length; 693 } 694 695 for (i = 0; i < ncerts; i++) 696 KMF_FreeKMFCert(kmfh, &certs[i]); 697 free(certs); 698 699 return (kssl_params); 700} 701 702/* 703 * Find a key and certificate(s) from a single PEM file. 704 */ 705static kssl_params_t * 706load_from_pem(const char *filename, const char *password_file, int *paramsize) 707{ 708 int ncerts = 0, i; 709 kssl_params_t *kssl_params; 710 KMF_RAW_KEY_DATA *rsa = NULL; 711 KMF_DATA *certs = NULL; 712 713 ncerts = PEM_get_rsa_key_certs(filename, (char *)password_file, 714 &rsa, &certs); 715 if (rsa == NULL || certs == NULL || ncerts == 0) { 716 return (NULL); 717 } 718 719 if (verbose) 720 (void) printf("%d certificates read successfully\n", ncerts); 721 722 kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL, 723 NULL, NULL); 724 725 for (i = 0; i < ncerts; i++) 726 KMF_FreeData(&certs[i]); 727 free(certs); 728 KMF_FreeRawKey(rsa); 729 730 return (kssl_params); 731} 732 733/* 734 * Load a raw key and certificate(s) from a PKCS#12 file. 735 */ 736static kssl_params_t * 737load_from_pkcs12(const char *filename, const char *password_file, 738 int *paramsize) 739{ 740 KMF_RAW_KEY_DATA *rsa = NULL; 741 kssl_params_t *kssl_params; 742 KMF_DATA *certs = NULL; 743 int ncerts = 0, i; 744 745 ncerts = PKCS12_get_rsa_key_certs(filename, 746 password_file, &rsa, &certs); 747 748 if (certs == NULL || ncerts == 0) { 749 (void) fprintf(stderr, 750 "Unable to read cert and/or key from %s\n", filename); 751 return (NULL); 752 } 753 754 if (verbose) 755 (void) printf("%d certificates read successfully\n", ncerts); 756 757 kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL, 758 NULL, NULL); 759 760 for (i = 0; i < ncerts; i++) 761 KMF_FreeData(&certs[i]); 762 free(certs); 763 764 KMF_FreeRawKey(rsa); 765 return (kssl_params); 766} 767 768int 769parse_and_set_addr(char *server_address, char *server_port, 770 struct sockaddr_in *addr) 771{ 772 if (server_port == NULL) { 773 return (-1); 774 } 775 776 if (server_address == NULL) { 777 addr->sin_addr.s_addr = INADDR_ANY; 778 } else { 779 addr->sin_addr.s_addr = inet_addr(server_address); 780 if ((int)addr->sin_addr.s_addr == -1) { 781 struct hostent *hp; 782 783 if ((hp = gethostbyname(server_address)) == NULL) { 784 (void) fprintf(stderr, 785 "Error: Unknown host: %s\n", 786 server_address); 787 return (-1); 788 } 789 790 (void) memcpy(&addr->sin_addr.s_addr, 791 hp->h_addr_list[0], 792 sizeof (addr->sin_addr.s_addr)); 793 } 794 } 795 796 errno = 0; 797 addr->sin_port = strtol(server_port, NULL, 10); 798 if (addr->sin_port == 0 || errno != 0) { 799 (void) fprintf(stderr, "Error: Invalid Port value: %s\n", 800 server_port); 801 return (-1); 802 } 803 804 return (0); 805} 806 807/* 808 * The order of the ciphers is important. It is used as the 809 * default order (when -c is not specified). 810 */ 811struct csuite { 812 const char *suite; 813 uint16_t val; 814 boolean_t seen; 815} cipher_suites[CIPHER_SUITE_COUNT - 1] = { 816 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE}, 817 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE}, 818 {"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE}, 819 {"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE}, 820}; 821 822static int 823check_suites(char *suites, uint16_t *sarray) 824{ 825 int i; 826 int err = 0; 827 char *suite; 828 int sindx = 0; 829 830 if (suites != NULL) { 831 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) 832 sarray[i] = CIPHER_NOTSET; 833 } else { 834 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) 835 sarray[i] = cipher_suites[i].val; 836 return (err); 837 } 838 839 suite = strtok(suites, ","); 840 do { 841 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) { 842 if (strcasecmp(suite, cipher_suites[i].suite) == 0) { 843 if (!cipher_suites[i].seen) { 844 sarray[sindx++] = cipher_suites[i].val; 845 cipher_suites[i].seen = B_TRUE; 846 } 847 break; 848 } 849 } 850 851 if (i == (CIPHER_SUITE_COUNT - 1)) { 852 (void) fprintf(stderr, 853 "Unknown Cipher suite name: %s\n", suite); 854 err++; 855 } 856 } while ((suite = strtok(NULL, ",")) != NULL); 857 858 return (err); 859} 860 861int 862do_create(int argc, char *argv[]) 863{ 864 const char *softtoken_dir = NULL; 865 const char *token_label = NULL; 866 const char *password_file = NULL; 867 const char *cert_key_file = NULL; 868 const char *cacert_chain_file = NULL; 869 const char *certname = NULL; 870 char *suites = NULL; 871 uint32_t timeout = DEFAULT_SID_TIMEOUT; 872 uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES; 873 uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1]; 874 int proxy_port = -1; 875 struct sockaddr_in server_addr; 876 char *format = NULL; 877 char *port, *addr; 878 char c; 879 int pcnt; 880 kssl_params_t *kssl_params; 881 int bufsize; 882 883 argc -= 1; 884 argv += 1; 885 886 while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) { 887 switch (c) { 888 case 'd': 889 softtoken_dir = optarg; 890 break; 891 case 'c': 892 suites = optarg; 893 break; 894 case 'C': 895 certname = optarg; 896 break; 897 case 'f': 898 format = optarg; 899 break; 900 case 'h': 901 cacert_chain_file = optarg; 902 break; 903 case 'i': 904 cert_key_file = optarg; 905 break; 906 case 'T': 907 token_label = optarg; 908 break; 909 case 'p': 910 password_file = optarg; 911 break; 912 case 't': 913 timeout = atoi(optarg); 914 break; 915 case 'x': 916 proxy_port = atoi(optarg); 917 break; 918 case 'v': 919 verbose = B_TRUE; 920 break; 921 case 'z': 922 scache_size = atoi(optarg); 923 break; 924 default: 925 goto err; 926 } 927 } 928 929 pcnt = argc - optind; 930 if (pcnt == 0) { 931 port = "443"; /* default SSL port */ 932 addr = NULL; 933 } else if (pcnt == 1) { 934 port = argv[optind]; 935 addr = NULL; 936 } else if (pcnt == 2) { 937 addr = argv[optind]; 938 port = argv[optind + 1]; 939 } else { 940 goto err; 941 } 942 943 if (parse_and_set_addr(addr, port, &server_addr) < 0) { 944 goto err; 945 } 946 947 if (verbose) { 948 (void) printf("addr=%s, port = %d\n", 949 inet_ntoa(server_addr.sin_addr), server_addr.sin_port); 950 } 951 952 if (format == NULL || proxy_port == -1) { 953 goto err; 954 } 955 956 if (check_suites(suites, kssl_suites) != 0) { 957 goto err; 958 } 959 960 if (strcmp(format, "pkcs11") == 0) { 961 if (token_label == NULL || certname == NULL) { 962 goto err; 963 } 964 if (softtoken_dir != NULL) { 965 (void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1); 966 if (verbose) { 967 (void) printf( 968 "SOFTTOKEN_DIR=%s\n", 969 getenv("SOFTTOKEN_DIR")); 970 } 971 } 972 kssl_params = load_from_pkcs11( 973 token_label, password_file, certname, &bufsize); 974 } else if (strcmp(format, "pkcs12") == 0) { 975 if (cert_key_file == NULL) { 976 goto err; 977 } 978 kssl_params = load_from_pkcs12( 979 cert_key_file, password_file, &bufsize); 980 } else if (strcmp(format, "pem") == 0) { 981 if (cert_key_file == NULL) { 982 goto err; 983 } 984 kssl_params = load_from_pem( 985 cert_key_file, password_file, &bufsize); 986 } else { 987 (void) fprintf(stderr, "Unsupported cert format: %s\n", format); 988 goto err; 989 } 990 991 if (kssl_params == NULL) { 992 return (FAILURE); 993 } 994 995 /* 996 * Add the list of supported ciphers to the buffer. 997 */ 998 bcopy(kssl_suites, kssl_params->kssl_suites, 999 sizeof (kssl_params->kssl_suites)); 1000 kssl_params->kssl_params_size = bufsize; 1001 kssl_params->kssl_addr = server_addr; 1002 kssl_params->kssl_session_cache_timeout = timeout; 1003 kssl_params->kssl_proxy_port = proxy_port; 1004 kssl_params->kssl_session_cache_size = scache_size; 1005 1006 if (cacert_chain_file != NULL) { 1007 kssl_params = add_cacerts(kssl_params, cacert_chain_file); 1008 if (kssl_params == NULL) { 1009 return (FAILURE); 1010 } 1011 } 1012 1013 if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) { 1014 int err = CRYPTO_FAILED; 1015 1016 if (kssl_params->kssl_is_nxkey) 1017 err = kssl_params->kssl_token.ck_rv; 1018 (void) fprintf(stderr, 1019 "Error loading cert and key: 0x%x\n", err); 1020 return (FAILURE); 1021 } 1022 1023 if (verbose) 1024 (void) printf("Successfully loaded cert and key\n"); 1025 1026 bzero(kssl_params, bufsize); 1027 free(kssl_params); 1028 return (SUCCESS); 1029 1030err: 1031 usage_create(B_TRUE); 1032 return (SMF_EXIT_ERR_CONFIG); 1033} 1034