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