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