kssladm_create.c revision 5536:865d075cefb7
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_X509_DER_CERT *certs, int *paramsize, 93 char *token_label, KMF_DATA *idstr, 94 KMF_CREDENTIAL *creds) 95{ 96 int i, tcsize; 97 kssl_params_t *kssl_params; 98 kssl_key_t *key; 99 char *buf; 100 uint32_t bufsize; 101 static CK_BBOOL true = TRUE; 102 static CK_BBOOL false = FALSE; 103 static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; 104 static CK_KEY_TYPE keytype = CKK_RSA; 105 kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT]; 106 CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = { 107 {CKA_TOKEN, &true, sizeof (true)}, 108 {CKA_EXTRACTABLE, &false, sizeof (false)}, 109 {CKA_CLASS, &class, sizeof (class) }, 110 {CKA_KEY_TYPE, &keytype, sizeof (keytype) }, 111 {CKA_ID, NULL, 0} 112 }; 113 kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = { 114 {SUN_CKA_MODULUS, NULL, 0}, 115 {SUN_CKA_PUBLIC_EXPONENT, NULL, 0}, 116 {SUN_CKA_PRIVATE_EXPONENT, NULL, 0}, 117 {SUN_CKA_PRIME_1, NULL, 0}, 118 {SUN_CKA_PRIME_2, NULL, 0}, 119 {SUN_CKA_EXPONENT_1, NULL, 0}, 120 {SUN_CKA_EXPONENT_2, NULL, 0}, 121 {SUN_CKA_COEFFICIENT, NULL, 0} 122 }; 123 KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT]; 124 int attr_cnt; 125 126 if (nxkey && idstr != NULL) { 127 exkey_attrs[4].pValue = idstr->Data; 128 exkey_attrs[4].ulValueLen = idstr->Length; 129 } 130 tcsize = 0; 131 for (i = 0; i < ncerts; i++) 132 tcsize += certs[i].certificate.Length; 133 134 bufsize = sizeof (kssl_params_t); 135 bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t))); 136 137 if (!nxkey) { 138 bzero(priv_key_bignums, sizeof (KMF_BIGINT) * 139 MAX_ATTR_CNT); 140 /* and the key attributes */ 141 priv_key_bignums[0] = rsa->rawdata.rsa.mod; 142 priv_key_bignums[1] = rsa->rawdata.rsa.pubexp; 143 priv_key_bignums[2] = rsa->rawdata.rsa.priexp; 144 priv_key_bignums[3] = rsa->rawdata.rsa.prime1; 145 priv_key_bignums[4] = rsa->rawdata.rsa.prime2; 146 priv_key_bignums[5] = rsa->rawdata.rsa.exp1; 147 priv_key_bignums[6] = rsa->rawdata.rsa.exp2; 148 priv_key_bignums[7] = rsa->rawdata.rsa.coef; 149 150 if (rsa->rawdata.rsa.mod.val == NULL || 151 rsa->rawdata.rsa.priexp.val == NULL) { 152 (void) fprintf(stderr, 153 "missing required attributes in private key.\n"); 154 return (NULL); 155 } 156 157 attr_cnt = 0; 158 for (i = 0; i < MAX_ATTR_CNT; i++) { 159 if (priv_key_bignums[i].val == NULL) 160 continue; 161 kssl_attrs[attr_cnt].ka_type = 162 kssl_tmpl_attrs[i].ka_type; 163 kssl_attrs[attr_cnt].ka_value_len = 164 priv_key_bignums[i].len; 165 bufsize += sizeof (crypto_object_attribute_t) + 166 kssl_attrs[attr_cnt].ka_value_len; 167 attr_cnt++; 168 } 169 } else { 170 /* 171 * Compute space for the attributes and values that the 172 * kssl kernel module will need in order to search for 173 * the private key. 174 */ 175 for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) { 176 bufsize += sizeof (crypto_object_attribute_t) + 177 exkey_attrs[attr_cnt].ulValueLen; 178 } 179 if (creds) 180 bufsize += creds->credlen; 181 } 182 183 /* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */ 184 bufsize += sizeof (uint32_t); 185 186 /* Now the big memory allocation */ 187 if ((buf = calloc(bufsize, 1)) == NULL) { 188 (void) fprintf(stderr, 189 "Cannot allocate memory for the kssl_params " 190 "and values\n"); 191 return (NULL); 192 } 193 194 /* LINTED */ 195 kssl_params = (kssl_params_t *)buf; 196 197 buf = (char *)(kssl_params + 1); 198 199 if (!nxkey) { 200 /* the keys attributes structs array */ 201 key = &kssl_params->kssl_privkey; 202 key->ks_format = CRYPTO_KEY_ATTR_LIST; 203 key->ks_count = attr_cnt; 204 key->ks_attrs_offset = buf - (char *)kssl_params; 205 buf += attr_cnt * sizeof (kssl_object_attribute_t); 206 207 attr_cnt = 0; 208 /* then the key attributes values */ 209 for (i = 0; i < MAX_ATTR_CNT; i++) { 210 if (priv_key_bignums[i].val == NULL) 211 continue; 212 (void) memcpy(buf, priv_key_bignums[i].val, 213 priv_key_bignums[i].len); 214 kssl_attrs[attr_cnt].ka_value_offset = 215 buf - (char *)kssl_params; 216 buf += kssl_attrs[attr_cnt].ka_value_len; 217 attr_cnt++; 218 } 219 } else { 220 char tlabel[CRYPTO_EXT_SIZE_LABEL]; 221 bzero(tlabel, sizeof (tlabel)); 222 (void) strlcpy(tlabel, token_label, sizeof (tlabel)); 223 224 /* 225 * For a non-extractable key, we must provide the PIN 226 * so the kssl module can access the token to find 227 * the key handle. 228 */ 229 kssl_params->kssl_is_nxkey = 1; 230 bcopy(tlabel, kssl_params->kssl_token.toklabel, 231 CRYPTO_EXT_SIZE_LABEL); 232 kssl_params->kssl_token.pinlen = creds->credlen; 233 kssl_params->kssl_token.tokpin_offset = 234 buf - (char *)kssl_params; 235 kssl_params->kssl_token.ck_rv = 0; 236 bcopy(creds->cred, buf, creds->credlen); 237 buf += creds->credlen; 238 239 /* 240 * Next in the buffer, we must provide the attributes 241 * that the kssl module will use to search in the 242 * token to find the protected key handle. 243 */ 244 key = &kssl_params->kssl_privkey; 245 key->ks_format = CRYPTO_KEY_ATTR_LIST; 246 key->ks_count = attr_cnt; 247 key->ks_attrs_offset = buf - (char *)kssl_params; 248 249 buf += attr_cnt * sizeof (kssl_object_attribute_t); 250 for (i = 0; i < attr_cnt; i++) { 251 bcopy(exkey_attrs[i].pValue, buf, 252 exkey_attrs[i].ulValueLen); 253 254 kssl_attrs[i].ka_type = exkey_attrs[i].type; 255 kssl_attrs[i].ka_value_offset = 256 buf - (char *)kssl_params; 257 kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen; 258 259 buf += exkey_attrs[i].ulValueLen; 260 } 261 } 262 /* Copy the key attributes array here */ 263 bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, 264 attr_cnt * sizeof (kssl_object_attribute_t)); 265 266 buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); 267 268 /* 269 * Finally, add the certificate chain to the buffer. 270 */ 271 kssl_params->kssl_certs.sc_count = ncerts; 272 273 /* First, an array of certificate sizes */ 274 for (i = 0; i < ncerts; i++) { 275 uint32_t certsz = (uint32_t)certs[i].certificate.Length; 276 char *p = buf + (i * sizeof (uint32_t)); 277 bcopy(&certsz, p, sizeof (uint32_t)); 278 } 279 280 kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params; 281 buf += MAX_CHAIN_LENGTH * sizeof (uint32_t); 282 283 kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params; 284 285 /* Now add the certificate data (ASN.1 DER encoded) */ 286 for (i = 0; i < ncerts; i++) { 287 bcopy(certs[i].certificate.Data, buf, 288 certs[i].certificate.Length); 289 buf += certs[i].certificate.Length; 290 } 291 292 *paramsize = bufsize; 293 return (kssl_params); 294} 295 296/* 297 * Extract a sensitive key via wrap/unwrap operations. 298 * 299 * This function requires that we call PKCS#11 API directly since 300 * KMF does not yet support wrapping/unwrapping of keys. By extracting 301 * a sensitive key in wrapped form, we then unwrap it into a session key 302 * object. KMF is then used to find the session key and return it in 303 * KMF_RAW_KEY format which is then passed along to KSSL by the caller. 304 */ 305static KMF_RETURN 306get_sensitive_key_data(KMF_HANDLE_T kmfh, 307 KMF_CREDENTIAL *creds, char *keylabel, 308 char *idstr, KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey) 309{ 310 KMF_RETURN rv = KMF_OK; 311 static CK_BYTE aes_param[16]; 312 static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY; 313 static CK_KEY_TYPE privkey_type = CKK_RSA; 314 static CK_BBOOL true = TRUE; 315 static CK_BBOOL false = FALSE; 316 boolean_t kmftrue = B_TRUE; 317 boolean_t kmffalse = B_FALSE; 318 char *err = NULL; 319 char wrapkey_label[BUFSIZ]; 320 int fd; 321 uint32_t nkeys = 0; 322 CK_RV ckrv; 323 CK_SESSION_HANDLE pk11session; 324 CK_BYTE aes_key_val[16]; 325 int numattr = 0; 326 int idx; 327 KMF_ATTRIBUTE attrlist[16]; 328 KMF_KEYSTORE_TYPE kstype; 329 KMF_KEY_CLASS kclass; 330 KMF_ENCODE_FORMAT format; 331 332 CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, 333 sizeof (aes_param)}; 334 CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE; 335 CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE; 336 CK_BYTE *wrapped_privkey = NULL; 337 CK_ULONG wrapped_privkey_len = 0; 338 339 CK_ATTRIBUTE unwrap_tmpl[] = { 340 /* code below depends on the following attribute order */ 341 {CKA_TOKEN, &false, sizeof (false)}, 342 {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, 343 {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}, 344 {CKA_SENSITIVE, &false, sizeof (false)}, 345 {CKA_PRIVATE, &false, sizeof (false)}, 346 {CKA_LABEL, NULL, 0} 347 }; 348 349 /* 350 * Create a wrap key with random data. 351 */ 352 fd = open("/dev/urandom", O_RDONLY); 353 if (fd == -1) { 354 perror("Error reading /dev/urandom"); 355 return (KMF_ERR_INTERNAL); 356 } 357 if (read(fd, aes_key_val, sizeof (aes_key_val)) != 358 sizeof (aes_key_val)) { 359 perror("Error reading from /dev/urandom"); 360 (void) close(fd); 361 return (KMF_ERR_INTERNAL); 362 } 363 (void) close(fd); 364 365 pk11session = kmf_get_pk11_handle(kmfh); 366 367 /* 368 * Login to create the wrap key stuff. 369 */ 370 ckrv = C_Login(pk11session, CKU_USER, 371 (CK_UTF8CHAR_PTR)creds->cred, creds->credlen); 372 if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) { 373 (void) fprintf(stderr, 374 "Cannot login to the token. error = %s\n", 375 pkcs11_strerror(ckrv)); 376 return (KMF_ERR_INTERNAL); 377 } 378 379 /* 380 * Turn the random key into a PKCS#11 session object. 381 */ 382 ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val, 383 sizeof (aes_key_val), &aes_key_obj); 384 if (ckrv != CKR_OK) { 385 (void) fprintf(stderr, 386 "Cannot create wrapping key. error = %s\n", 387 pkcs11_strerror(ckrv)); 388 return (KMF_ERR_INTERNAL); 389 } 390 391 /* 392 * Find the original private key that we are going to wrap. 393 */ 394 kstype = KMF_KEYSTORE_PK11TOKEN; 395 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 396 &kstype, sizeof (kstype)); 397 numattr++; 398 399 kclass = KMF_ASYM_PRI; 400 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 401 &kclass, sizeof (kclass)); 402 numattr++; 403 404 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 405 creds, sizeof (KMF_CREDENTIAL)); 406 numattr++; 407 408 if (keylabel) { 409 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 410 keylabel, strlen(keylabel)); 411 numattr++; 412 } 413 if (idstr) { 414 kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR, 415 idstr, strlen(idstr)); 416 numattr++; 417 } 418 format = KMF_FORMAT_NATIVE; 419 kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 420 &format, sizeof (format)); 421 numattr++; 422 423 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 424 &kmftrue, sizeof (kmftrue)); 425 numattr++; 426 427 kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR, 428 &kmftrue, sizeof (kmftrue)); 429 numattr++; 430 431 nkeys = 1; 432 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 433 &nkeys, sizeof (nkeys)); 434 numattr++; 435 436 kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 437 key, sizeof (KMF_KEY_HANDLE)); 438 numattr++; 439 440 rv = kmf_find_key(kmfh, numattr, attrlist); 441 if (rv != KMF_OK) { 442 REPORT_KMF_ERROR(rv, "Error finding private key", err); 443 goto out; 444 } 445 446 /* 447 * Get the size of the wrapped private key. 448 */ 449 bzero(aes_param, sizeof (aes_param)); 450 ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech, 451 aes_key_obj, (CK_OBJECT_HANDLE)key->keyp, 452 NULL, &wrapped_privkey_len); 453 if (ckrv != CKR_OK) { 454 /* 455 * Most common error here is that the token doesn't 456 * support the wrapping mechanism or the key is 457 * marked non-extractable. Return an error and let 458 * the caller deal with it gracefully. 459 */ 460 (void) fprintf(stderr, 461 "Cannot get wrap key size. error = %s\n", 462 pkcs11_strerror(ckrv)); 463 rv = KMF_ERR_INTERNAL; 464 goto out; 465 } 466 wrapped_privkey = malloc(wrapped_privkey_len); 467 if (wrapped_privkey == NULL) { 468 rv = KMF_ERR_MEMORY; 469 goto out; 470 } 471 /* 472 * Now get the actual wrapped key data. 473 */ 474 ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech, 475 aes_key_obj, (CK_OBJECT_HANDLE)key->keyp, 476 wrapped_privkey, &wrapped_privkey_len); 477 if (ckrv != CKR_OK) { 478 (void) fprintf(stderr, 479 "Cannot wrap private key. error = %s\n", 480 pkcs11_strerror(ckrv)); 481 rv = KMF_ERR_INTERNAL; 482 goto out; 483 } 484 /* 485 * Create a label for the wrapped session key so we can find 486 * it easier later. 487 */ 488 snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d", 489 getpid()); 490 491 unwrap_tmpl[5].pValue = wrapkey_label; 492 unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label); 493 494 /* 495 * Unwrap the key into the template and create a temporary 496 * session private key. 497 */ 498 ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj, 499 wrapped_privkey, wrapped_privkey_len, 500 unwrap_tmpl, 6, &sess_privkey_obj); 501 if (ckrv != CKR_OK) { 502 (void) fprintf(stderr, 503 "Cannot unwrap private key. error = %s\n", 504 pkcs11_strerror(ckrv)); 505 rv = KMF_ERR_INTERNAL; 506 goto out; 507 } 508 509 /* 510 * Use KMF to find the session key and return it as RAW data 511 * so we can pass it along to KSSL. 512 */ 513 kclass = KMF_ASYM_PRI; 514 if ((idx = kmf_find_attr(KMF_KEYCLASS_ATTR, attrlist, numattr)) != -1) { 515 attrlist[idx].pValue = &kclass; 516 } 517 518 format = KMF_FORMAT_RAWKEY; 519 if ((idx = kmf_find_attr(KMF_ENCODE_FORMAT_ATTR, attrlist, 520 numattr)) != -1) { 521 attrlist[idx].pValue = &format; 522 } 523 if (wrapkey_label != NULL && 524 (idx = kmf_find_attr(KMF_KEYLABEL_ATTR, attrlist, numattr)) != -1) { 525 attrlist[idx].pValue = wrapkey_label; 526 attrlist[idx].valueLen = strlen(wrapkey_label); 527 } 528 529 if ((idx = kmf_find_attr(KMF_PRIVATE_BOOL_ATTR, attrlist, 530 numattr)) != -1) { 531 attrlist[idx].pValue = &kmffalse; 532 } 533 if ((idx = kmf_find_attr(KMF_TOKEN_BOOL_ATTR, attrlist, 534 numattr)) != -1) { 535 attrlist[idx].pValue = &kmffalse; 536 } 537 538 if ((idx = kmf_find_attr(KMF_KEY_HANDLE_ATTR, attrlist, 539 numattr)) != -1) { 540 attrlist[idx].pValue = rawkey; 541 } 542 /* 543 * Clear the IDSTR attribute since it is not part of the 544 * wrapped session key. 545 */ 546 if ((idx = kmf_find_attr(KMF_IDSTR_ATTR, attrlist, 547 numattr)) != -1) { 548 attrlist[idx].pValue = NULL; 549 attrlist[idx].valueLen = 0; 550 } 551 552 /* The wrapped key should not be sensitive. */ 553 kmf_set_attr_at_index(attrlist, numattr, KMF_SENSITIVE_BOOL_ATTR, 554 &false, sizeof (false)); 555 numattr++; 556 557 rv = kmf_find_key(kmfh, numattr, attrlist); 558 if (rv != KMF_OK) { 559 REPORT_KMF_ERROR(rv, "Error finding raw private key", err); 560 goto out; 561 } 562out: 563 if (wrapped_privkey) 564 free(wrapped_privkey); 565 566 if (aes_key_obj != CK_INVALID_HANDLE) 567 C_DestroyObject(pk11session, aes_key_obj); 568 569 if (sess_privkey_obj != CK_INVALID_HANDLE) 570 C_DestroyObject(pk11session, sess_privkey_obj); 571 572 return (rv); 573} 574 575static kssl_params_t * 576load_from_pkcs11(KMF_HANDLE_T kmfh, 577 const char *token_label, const char *password_file, 578 const char *certname, int *bufsize) 579{ 580 KMF_RETURN rv; 581 KMF_X509_DER_CERT cert; 582 KMF_KEY_HANDLE key, rawkey; 583 KMF_CREDENTIAL creds; 584 KMF_DATA iddata = { NULL, 0 }; 585 kssl_params_t *kssl_params = NULL; 586 uint32_t ncerts, nkeys; 587 char *err, *idstr = NULL; 588 char password_buf[1024]; 589 int nxkey = 0; 590 int numattr = 0; 591 KMF_ATTRIBUTE attrlist[16]; 592 KMF_KEYSTORE_TYPE kstype; 593 KMF_KEY_CLASS kclass; 594 KMF_ENCODE_FORMAT format; 595 boolean_t false = B_FALSE; 596 boolean_t true = B_TRUE; 597 598 if (get_passphrase(password_file, password_buf, 599 sizeof (password_buf)) <= 0) { 600 perror("Unable to read passphrase"); 601 goto done; 602 } 603 creds.cred = password_buf; 604 creds.credlen = strlen(password_buf); 605 606 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 607 (void) memset(&rawkey, 0, sizeof (KMF_KEY_HANDLE)); 608 609 kstype = KMF_KEYSTORE_PK11TOKEN; 610 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 611 &kstype, sizeof (kstype)); 612 numattr++; 613 614 if (token_label && strlen(token_label)) { 615 kmf_set_attr_at_index(attrlist, numattr, 616 KMF_TOKEN_LABEL_ATTR, 617 (void *)token_label, strlen(token_label)); 618 numattr++; 619 } 620 621 kmf_set_attr_at_index(attrlist, numattr, KMF_READONLY_ATTR, 622 &false, sizeof (false)); 623 numattr++; 624 625 rv = kmf_configure_keystore(kmfh, numattr, attrlist); 626 if (rv != KMF_OK) { 627 REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err); 628 goto done; 629 } 630 631 /* 632 * Find the certificate matching the given label. 633 */ 634 numattr = 0; 635 kstype = KMF_KEYSTORE_PK11TOKEN; 636 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 637 &kstype, sizeof (kstype)); 638 numattr++; 639 640 if (certname) { 641 kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR, 642 (void *)certname, strlen(certname)); 643 numattr++; 644 } 645 ncerts = 1; 646 647 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 648 &ncerts, sizeof (ncerts)); 649 numattr++; 650 651 kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR, 652 &cert, sizeof (cert)); 653 numattr++; 654 655 rv = kmf_find_cert(kmfh, numattr, attrlist); 656 if (rv != KMF_OK || ncerts == 0) 657 goto done; 658 659 /* 660 * Find the associated private key for this cert by 661 * keying off of the label and the ASCII ID string. 662 */ 663 rv = kmf_get_cert_id_str(&cert.certificate, &idstr); 664 if (rv != KMF_OK) 665 goto done; 666 667 numattr = 1; /* attrlist[0] is already set to kstype */ 668 669 kclass = KMF_ASYM_PRI; 670 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 671 &kclass, sizeof (kclass)); 672 numattr++; 673 674 kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 675 &creds, sizeof (KMF_CREDENTIAL)); 676 numattr++; 677 678 format = KMF_FORMAT_RAWKEY; 679 kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 680 &format, sizeof (format)); 681 numattr++; 682 683 if (certname) { 684 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 685 (void *)certname, strlen(certname)); 686 numattr++; 687 } 688 if (idstr) { 689 kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR, 690 (void *)idstr, strlen(idstr)); 691 numattr++; 692 } 693 kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 694 &true, sizeof (true)); 695 numattr++; 696 697 kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR, 698 &true, sizeof (true)); 699 numattr++; 700 701 /* We only expect to find 1 key at most */ 702 nkeys = 1; 703 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 704 &nkeys, sizeof (nkeys)); 705 numattr++; 706 707 kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 708 &key, sizeof (KMF_KEY_HANDLE)); 709 numattr++; 710 711 rv = kmf_find_key(kmfh, numattr, attrlist); 712 if (rv == KMF_ERR_SENSITIVE_KEY) { 713 kmf_free_kmf_key(kmfh, &key); 714 /* 715 * Get a normal key handle and then do a wrap/unwrap 716 * in order to get the necessary raw data fields needed 717 * to send to KSSL. 718 */ 719 format = KMF_FORMAT_NATIVE; 720 rv = get_sensitive_key_data(kmfh, &creds, 721 (char *)certname, idstr, &key, &rawkey); 722 if (rv == KMF_OK) { 723 /* Swap "key" for "rawkey" */ 724 kmf_free_kmf_key(kmfh, &key); 725 726 key = rawkey; 727 } else { 728 kmf_free_kmf_key(kmfh, &key); 729 730 /* Let kssl try to find the key. */ 731 nxkey = 1; 732 rv = kmf_get_cert_id_data(&cert.certificate, &iddata); 733 } 734 } else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) { 735 kmf_free_kmf_key(kmfh, &key); 736 737 /* Let kssl try to find the key. */ 738 nxkey = 1; 739 rv = kmf_get_cert_id_data(&cert.certificate, &iddata); 740 } else if (rv != KMF_OK || nkeys == 0) 741 goto done; 742 743 if (rv == KMF_OK) 744 kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp, 745 1, &cert, bufsize, (char *)token_label, &iddata, &creds); 746done: 747 if (ncerts != 0) 748 kmf_free_kmf_cert(kmfh, &cert); 749 if (nkeys != 0) 750 kmf_free_kmf_key(kmfh, &key); 751 if (idstr) 752 free(idstr); 753 754 return (kssl_params); 755} 756 757/* 758 * add_cacerts 759 * 760 * Load a chain of certificates from a PEM file. 761 */ 762static kssl_params_t * 763add_cacerts(KMF_HANDLE_T kmfh, 764 kssl_params_t *old_params, const char *cacert_chain_file) 765{ 766 int i, newlen; 767 uint32_t certlen = 0, ncerts; 768 char *buf; 769 KMF_RETURN rv; 770 KMF_X509_DER_CERT *certs = NULL; 771 kssl_params_t *kssl_params; 772 char *err = NULL; 773 int numattr = 0; 774 KMF_ATTRIBUTE attrlist[16]; 775 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 776 777 kstype = KMF_KEYSTORE_OPENSSL; 778 779 ncerts = 0; 780 kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 781 &kstype, sizeof (KMF_KEYSTORE_TYPE)); 782 numattr++; 783 784 kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR, 785 (void *)cacert_chain_file, strlen(cacert_chain_file)); 786 numattr++; 787 788 kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 789 &ncerts, sizeof (ncerts)); 790 numattr++; 791 792 rv = kmf_find_cert(kmfh, numattr, attrlist); 793 if (rv != KMF_OK) { 794 REPORT_KMF_ERROR(rv, "Error finding CA certificates", err); 795 return (0); 796 } 797 certs = (KMF_X509_DER_CERT *)malloc(ncerts * 798 sizeof (KMF_X509_DER_CERT)); 799 if (certs == NULL) { 800 (void) fprintf(stderr, "memory allocation error.\n"); 801 return (NULL); 802 } 803 bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT)); 804 805 /* add new attribute for the cert list to be returned */ 806 kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR, 807 certs, (ncerts * sizeof (KMF_X509_DER_CERT))); 808 numattr++; 809 rv = kmf_find_cert(kmfh, numattr, attrlist); 810 811 if (rv != KMF_OK || ncerts == 0) { 812 bzero(old_params, old_params->kssl_params_size); 813 free(old_params); 814 return (NULL); 815 } 816 817 if (verbose) { 818 (void) printf("%d certificates read successfully\n", ncerts); 819 } 820 821 newlen = old_params->kssl_params_size; 822 for (i = 0; i < ncerts; i++) 823 newlen += certs[i].certificate.Length; 824 825 /* 826 * Get a bigger structure and update the 827 * fields to account for the additional certs. 828 */ 829 kssl_params = realloc(old_params, newlen); 830 831 kssl_params->kssl_params_size = newlen; 832 kssl_params->kssl_certs.sc_count += ncerts; 833 834 /* Put the cert size info starting from sc_sizes[1] */ 835 buf = (char *)kssl_params; 836 buf += kssl_params->kssl_certs.sc_sizes_offset; 837 bcopy(buf, &certlen, sizeof (uint32_t)); 838 buf += sizeof (uint32_t); 839 for (i = 0; i < ncerts; i++) { 840 uint32_t size = (uint32_t)certs[i].certificate.Length; 841 bcopy(&size, buf, sizeof (uint32_t)); 842 buf += sizeof (uint32_t); 843 } 844 845 /* Put the cert_bufs starting from sc_certs[1] */ 846 buf = (char *)kssl_params; 847 buf += kssl_params->kssl_certs.sc_certs_offset; 848 buf += certlen; 849 850 /* now the certs values */ 851 for (i = 0; i < ncerts; i++) { 852 bcopy(certs[i].certificate.Data, buf, 853 certs[i].certificate.Length); 854 buf += certs[i].certificate.Length; 855 } 856 857 for (i = 0; i < ncerts; i++) 858 kmf_free_kmf_cert(kmfh, &certs[i]); 859 free(certs); 860 861 return (kssl_params); 862} 863 864/* 865 * Find a key and certificate(s) from a single PEM file. 866 */ 867static kssl_params_t * 868load_from_pem(KMF_HANDLE_T kmfh, const char *filename, 869 const char *password_file, int *paramsize) 870{ 871 int ncerts = 0, i; 872 kssl_params_t *kssl_params; 873 KMF_RAW_KEY_DATA *rsa = NULL; 874 KMF_X509_DER_CERT *certs = NULL; 875 876 ncerts = PEM_get_rsa_key_certs(kmfh, 877 filename, (char *)password_file, &rsa, &certs); 878 if (rsa == NULL || certs == NULL || ncerts == 0) { 879 return (NULL); 880 } 881 882 if (verbose) 883 (void) printf("%d certificates read successfully\n", ncerts); 884 885 kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL, 886 NULL, NULL); 887 888 for (i = 0; i < ncerts; i++) 889 kmf_free_kmf_cert(kmfh, &certs[i]); 890 free(certs); 891 kmf_free_raw_key(rsa); 892 893 return (kssl_params); 894} 895 896/* 897 * Load a raw key and certificate(s) from a PKCS#12 file. 898 */ 899static kssl_params_t * 900load_from_pkcs12(KMF_HANDLE_T kmfh, const char *filename, 901 const char *password_file, int *paramsize) 902{ 903 KMF_RAW_KEY_DATA *rsa = NULL; 904 kssl_params_t *kssl_params; 905 KMF_X509_DER_CERT *certs = NULL; 906 int ncerts = 0, i; 907 908 ncerts = PKCS12_get_rsa_key_certs(kmfh, filename, 909 password_file, &rsa, &certs); 910 911 if (certs == NULL || ncerts == 0) { 912 (void) fprintf(stderr, 913 "Unable to read cert and/or key from %s\n", filename); 914 return (NULL); 915 } 916 917 if (verbose) 918 (void) printf("%d certificates read successfully\n", ncerts); 919 920 kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL, 921 NULL, NULL); 922 923 for (i = 0; i < ncerts; i++) 924 kmf_free_kmf_cert(kmfh, &certs[i]); 925 free(certs); 926 927 kmf_free_raw_key(rsa); 928 return (kssl_params); 929} 930 931int 932parse_and_set_addr(char *server_address, char *server_port, 933 struct sockaddr_in *addr) 934{ 935 if (server_port == NULL) { 936 return (-1); 937 } 938 939 if (server_address == NULL) { 940 addr->sin_addr.s_addr = INADDR_ANY; 941 } else { 942 addr->sin_addr.s_addr = inet_addr(server_address); 943 if ((int)addr->sin_addr.s_addr == -1) { 944 struct hostent *hp; 945 946 if ((hp = gethostbyname(server_address)) == NULL) { 947 (void) fprintf(stderr, 948 "Error: Unknown host: %s\n", 949 server_address); 950 return (-1); 951 } 952 953 (void) memcpy(&addr->sin_addr.s_addr, 954 hp->h_addr_list[0], 955 sizeof (addr->sin_addr.s_addr)); 956 } 957 } 958 959 errno = 0; 960 addr->sin_port = strtol(server_port, NULL, 10); 961 if (addr->sin_port == 0 || errno != 0) { 962 (void) fprintf(stderr, "Error: Invalid Port value: %s\n", 963 server_port); 964 return (-1); 965 } 966 967 return (0); 968} 969 970/* 971 * The order of the ciphers is important. It is used as the 972 * default order (when -c is not specified). 973 */ 974struct csuite { 975 const char *suite; 976 uint16_t val; 977 boolean_t seen; 978} cipher_suites[CIPHER_SUITE_COUNT - 1] = { 979 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE}, 980 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE}, 981 {"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE}, 982 {"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE}, 983}; 984 985static int 986check_suites(char *suites, uint16_t *sarray) 987{ 988 int i; 989 int err = 0; 990 char *suite; 991 int sindx = 0; 992 993 if (suites != NULL) { 994 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) 995 sarray[i] = CIPHER_NOTSET; 996 } else { 997 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) 998 sarray[i] = cipher_suites[i].val; 999 return (err); 1000 } 1001 1002 suite = strtok(suites, ","); 1003 do { 1004 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) { 1005 if (strcasecmp(suite, cipher_suites[i].suite) == 0) { 1006 if (!cipher_suites[i].seen) { 1007 sarray[sindx++] = cipher_suites[i].val; 1008 cipher_suites[i].seen = B_TRUE; 1009 } 1010 break; 1011 } 1012 } 1013 1014 if (i == (CIPHER_SUITE_COUNT - 1)) { 1015 (void) fprintf(stderr, 1016 "Unknown Cipher suite name: %s\n", suite); 1017 err++; 1018 } 1019 } while ((suite = strtok(NULL, ",")) != NULL); 1020 1021 return (err); 1022} 1023 1024int 1025do_create(int argc, char *argv[]) 1026{ 1027 const char *softtoken_dir = NULL; 1028 const char *token_label = NULL; 1029 const char *password_file = NULL; 1030 const char *cert_key_file = NULL; 1031 const char *cacert_chain_file = NULL; 1032 const char *certname = NULL; 1033 char *suites = NULL; 1034 uint32_t timeout = DEFAULT_SID_TIMEOUT; 1035 uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES; 1036 uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1]; 1037 int proxy_port = -1; 1038 struct sockaddr_in server_addr; 1039 char *format = NULL; 1040 char *port, *addr; 1041 char c; 1042 int pcnt; 1043 kssl_params_t *kssl_params; 1044 int bufsize; 1045 KMF_HANDLE_T kmfh = NULL; 1046 KMF_RETURN rv = KMF_OK; 1047 char *err = NULL; 1048 1049 argc -= 1; 1050 argv += 1; 1051 1052 while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) { 1053 switch (c) { 1054 case 'd': 1055 softtoken_dir = optarg; 1056 break; 1057 case 'c': 1058 suites = optarg; 1059 break; 1060 case 'C': 1061 certname = optarg; 1062 break; 1063 case 'f': 1064 format = optarg; 1065 break; 1066 case 'h': 1067 cacert_chain_file = optarg; 1068 break; 1069 case 'i': 1070 cert_key_file = optarg; 1071 break; 1072 case 'T': 1073 token_label = optarg; 1074 break; 1075 case 'p': 1076 password_file = optarg; 1077 break; 1078 case 't': 1079 timeout = atoi(optarg); 1080 break; 1081 case 'x': 1082 proxy_port = atoi(optarg); 1083 break; 1084 case 'v': 1085 verbose = B_TRUE; 1086 break; 1087 case 'z': 1088 scache_size = atoi(optarg); 1089 break; 1090 default: 1091 goto err; 1092 } 1093 } 1094 1095 pcnt = argc - optind; 1096 if (pcnt == 0) { 1097 port = "443"; /* default SSL port */ 1098 addr = NULL; 1099 } else if (pcnt == 1) { 1100 port = argv[optind]; 1101 addr = NULL; 1102 } else if (pcnt == 2) { 1103 addr = argv[optind]; 1104 port = argv[optind + 1]; 1105 } else { 1106 goto err; 1107 } 1108 1109 if (parse_and_set_addr(addr, port, &server_addr) < 0) { 1110 goto err; 1111 } 1112 1113 if (verbose) { 1114 (void) printf("addr=%s, port = %d\n", 1115 inet_ntoa(server_addr.sin_addr), server_addr.sin_port); 1116 } 1117 1118 if (format == NULL || proxy_port == -1) { 1119 goto err; 1120 } 1121 1122 if (check_suites(suites, kssl_suites) != 0) { 1123 goto err; 1124 } 1125 1126 rv = kmf_initialize(&kmfh, NULL, NULL); 1127 if (rv != KMF_OK) { 1128 REPORT_KMF_ERROR(rv, "Error initializing KMF", err); 1129 return (0); 1130 } 1131 1132 if (strcmp(format, "pkcs11") == 0) { 1133 if (token_label == NULL || certname == NULL) { 1134 goto err; 1135 } 1136 if (softtoken_dir != NULL) { 1137 (void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1); 1138 if (verbose) { 1139 (void) printf( 1140 "SOFTTOKEN_DIR=%s\n", 1141 getenv("SOFTTOKEN_DIR")); 1142 } 1143 } 1144 kssl_params = load_from_pkcs11(kmfh, 1145 token_label, password_file, certname, &bufsize); 1146 } else if (strcmp(format, "pkcs12") == 0) { 1147 if (cert_key_file == NULL) { 1148 goto err; 1149 } 1150 kssl_params = load_from_pkcs12(kmfh, 1151 cert_key_file, password_file, &bufsize); 1152 } else if (strcmp(format, "pem") == 0) { 1153 if (cert_key_file == NULL) { 1154 goto err; 1155 } 1156 kssl_params = load_from_pem(kmfh, 1157 cert_key_file, password_file, &bufsize); 1158 } else { 1159 (void) fprintf(stderr, "Unsupported cert format: %s\n", format); 1160 goto err; 1161 } 1162 1163 if (kssl_params == NULL) { 1164 (void) kmf_finalize(kmfh); 1165 return (FAILURE); 1166 } 1167 1168 /* 1169 * Add the list of supported ciphers to the buffer. 1170 */ 1171 bcopy(kssl_suites, kssl_params->kssl_suites, 1172 sizeof (kssl_params->kssl_suites)); 1173 kssl_params->kssl_params_size = bufsize; 1174 kssl_params->kssl_addr = server_addr; 1175 kssl_params->kssl_session_cache_timeout = timeout; 1176 kssl_params->kssl_proxy_port = proxy_port; 1177 kssl_params->kssl_session_cache_size = scache_size; 1178 1179 if (cacert_chain_file != NULL) { 1180 kssl_params = add_cacerts(kmfh, kssl_params, cacert_chain_file); 1181 if (kssl_params == NULL) { 1182 bzero(kssl_params, bufsize); 1183 free(kssl_params); 1184 (void) kmf_finalize(kmfh); 1185 return (FAILURE); 1186 } 1187 } 1188 1189 if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) { 1190 int err = CRYPTO_FAILED; 1191 1192 if (kssl_params->kssl_is_nxkey) 1193 err = kssl_params->kssl_token.ck_rv; 1194 (void) fprintf(stderr, 1195 "Error loading cert and key: 0x%x\n", err); 1196 bzero(kssl_params, bufsize); 1197 free(kssl_params); 1198 (void) kmf_finalize(kmfh); 1199 return (FAILURE); 1200 } 1201 1202 if (verbose) 1203 (void) printf("Successfully loaded cert and key\n"); 1204 1205 bzero(kssl_params, bufsize); 1206 free(kssl_params); 1207 (void) kmf_finalize(kmfh); 1208 return (SUCCESS); 1209 1210err: 1211 usage_create(B_TRUE); 1212 (void) kmf_finalize(kmfh); 1213 return (SMF_EXIT_ERR_CONFIG); 1214} 1215