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 2006 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 <arpa/inet.h> 30 #include <errno.h> 31 #include <sys/sysmacros.h> 32 #include <netdb.h> /* hostent */ 33 #include <netinet/in.h> 34 #include <openssl/rsa.h> 35 #include <security/cryptoki.h> 36 #include <security/pkcs11.h> 37 #include <cryptoutil.h> 38 #include <stdio.h> 39 #include <strings.h> 40 #include <sys/socket.h> 41 #include <libscf.h> 42 #include <inet/kssl/kssl.h> 43 #include "kssladm.h" 44 45 void 46 usage_create(boolean_t do_print) 47 { 48 if (do_print) 49 (void) fprintf(stderr, "Usage:\n"); 50 (void) fprintf(stderr, "kssladm create" 51 " -f pkcs11 [-d softtoken_directory] -T <token_label>" 52 " -C <certificate_label> -x <proxy_port>" 53 " [-h <ca_certchain_file>]" 54 " [options] [<server_address>] [<server_port>]\n"); 55 56 (void) fprintf(stderr, "kssladm create" 57 " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>" 58 " [options] [<server_address>] [<server_port>]\n"); 59 60 (void) fprintf(stderr, "kssladm create" 61 " -f pem -i <cert_and_key_pemfile> -x <proxy_port>" 62 " [options] [<server_address>] [<server_port>]\n"); 63 64 (void) fprintf(stderr, "options are:\n" 65 "\t[-c <ciphersuites>]\n" 66 "\t[-p <password_file>]\n" 67 "\t[-t <ssl_session_cache_timeout>]\n" 68 "\t[-z <ssl_session_cache_size>]\n" 69 "\t[-v]\n"); 70 } 71 72 static uchar_t * 73 get_cert_val(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE cert_obj, int *len) 74 { 75 CK_RV rv; 76 uchar_t *buf; 77 CK_ATTRIBUTE cert_attrs[] = {{CKA_VALUE, NULL, 0}}; 78 79 /* the certs ... */ 80 rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1); 81 if (rv != CKR_OK) { 82 (void) fprintf(stderr, "Cannot get cert size." 83 " error = %s\n", pkcs11_strerror(rv)); 84 return (NULL); 85 } 86 87 buf = malloc(cert_attrs[0].ulValueLen); 88 if (buf == NULL) 89 return (NULL); 90 cert_attrs[0].pValue = buf; 91 92 rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1); 93 if (rv != CKR_OK) { 94 (void) fprintf(stderr, "Cannot get cert value." 95 " error = %s\n", pkcs11_strerror(rv)); 96 free(buf); 97 return (NULL); 98 } 99 100 *len = cert_attrs[0].ulValueLen; 101 return (buf); 102 } 103 104 #define REQ_ATTR_CNT 2 105 #define OPT_ATTR_CNT 6 106 #define MAX_ATTR_CNT (REQ_ATTR_CNT + OPT_ATTR_CNT) 107 108 /* 109 * Everything is allocated in one single contiguous buffer. 110 * The layout is the following: 111 * . the kssl_params_t structure 112 * . the array of key attribute structs, (value of ck_attrs) 113 * . the key attributes values (values of ck_attrs[i].ck_value); 114 * . the array of sizes of the certificates, (referred to as sc_sizes[]) 115 * . the certificates values (referred to as sc_certs[]) 116 * 117 * The address of the certs and key attributes values are offsets 118 * from the beginning of the big buffer. sc_sizes_offset points 119 * to sc_sizes[0] and sc_certs_offset points to sc_certs[0]. 120 */ 121 static kssl_params_t * 122 pkcs11_to_kssl(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE privkey_obj, 123 CK_OBJECT_HANDLE cert_obj, int *paramsize) 124 { 125 int i; 126 CK_RV rv; 127 CK_ATTRIBUTE privkey_attrs[MAX_ATTR_CNT] = { 128 {CKA_MODULUS, NULL_PTR, 0}, 129 {CKA_PRIVATE_EXPONENT, NULL_PTR, 0} 130 }; 131 CK_ATTRIBUTE privkey_opt_attrs[OPT_ATTR_CNT] = { 132 {CKA_PUBLIC_EXPONENT, NULL_PTR, 0}, 133 {CKA_PRIME_1, NULL_PTR, 0}, 134 {CKA_PRIME_2, NULL_PTR, 0}, 135 {CKA_EXPONENT_1, NULL_PTR, 0}, 136 {CKA_EXPONENT_2, NULL_PTR, 0}, 137 {CKA_COEFFICIENT, NULL_PTR, 0} 138 }; 139 CK_ATTRIBUTE cert_attrs[] = { {CKA_VALUE, NULL, 0} }; 140 kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT]; 141 kssl_params_t *kssl_params; 142 kssl_key_t *key; 143 char *buf; 144 uint32_t cert_size, bufsize; 145 int attr_cnt; 146 147 /* the certs ... */ 148 rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1); 149 if (rv != CKR_OK) { 150 (void) fprintf(stderr, "Cannot get cert size." 151 " error = %s\n", pkcs11_strerror(rv)); 152 return (NULL); 153 } 154 155 /* Get the sizes */ 156 bufsize = sizeof (kssl_params_t); 157 cert_size = (uint32_t)cert_attrs[0].ulValueLen; 158 bufsize += cert_size + MAX_CHAIN_LENGTH * sizeof (uint32_t); 159 160 /* and the required key attributes */ 161 rv = C_GetAttributeValue(sess, privkey_obj, privkey_attrs, 162 REQ_ATTR_CNT); 163 if (rv != CKR_OK) { 164 (void) fprintf(stderr, 165 "Cannot get private key object attributes. error = %s\n", 166 pkcs11_strerror(rv)); 167 return (NULL); 168 } 169 for (i = 0; i < REQ_ATTR_CNT; i++) { 170 bufsize += sizeof (crypto_object_attribute_t) + 171 privkey_attrs[i].ulValueLen; 172 } 173 attr_cnt = REQ_ATTR_CNT; 174 175 /* 176 * Get the optional key attributes. The return values could be 177 * CKR_ATTRIBUTE_TYPE_INVALID with ulValueLen set to -1 OR 178 * CKR_OK with ulValueLen set to 0. The latter is done by 179 * soft token and seems dubious. 180 */ 181 rv = C_GetAttributeValue(sess, privkey_obj, privkey_opt_attrs, 182 OPT_ATTR_CNT); 183 if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) { 184 (void) fprintf(stderr, 185 "Cannot get private key object attributes. error = %s\n", 186 pkcs11_strerror(rv)); 187 return (NULL); 188 } 189 for (i = 0; i < OPT_ATTR_CNT; i++) { 190 if (privkey_opt_attrs[i].ulValueLen == (CK_ULONG)-1 || 191 privkey_opt_attrs[i].ulValueLen == 0) 192 continue; 193 /* Structure copy */ 194 privkey_attrs[attr_cnt] = privkey_opt_attrs[i]; 195 bufsize += sizeof (crypto_object_attribute_t) + 196 privkey_opt_attrs[i].ulValueLen; 197 attr_cnt++; 198 } 199 200 /* Add 4-byte cushion as sc_sizes[0] needs 32-bit aligment */ 201 bufsize += sizeof (uint32_t); 202 203 /* Now the big memory allocation */ 204 if ((buf = calloc(bufsize, 1)) == NULL) { 205 (void) fprintf(stderr, 206 "Cannot allocate memory for the kssl_params " 207 "and values\n"); 208 return (NULL); 209 } 210 211 /* LINTED */ 212 kssl_params = (kssl_params_t *)buf; 213 214 buf = (char *)(kssl_params + 1); 215 216 /* the keys attributes structs array */ 217 key = &kssl_params->kssl_privkey; 218 key->ks_format = CRYPTO_KEY_ATTR_LIST; 219 key->ks_count = attr_cnt; 220 key->ks_attrs_offset = buf - (char *)kssl_params; 221 buf += attr_cnt * sizeof (kssl_object_attribute_t); 222 223 /* then the attributes values */ 224 for (i = 0; i < attr_cnt; i++) { 225 privkey_attrs[i].pValue = buf; 226 /* 227 * We assume the attribute types in the kernel are 228 * the same as the PKCS #11 values. 229 */ 230 kssl_attrs[i].ka_type = privkey_attrs[i].type; 231 kssl_attrs[i].ka_value_offset = buf - (char *)kssl_params; 232 233 kssl_attrs[i].ka_value_len = privkey_attrs[i].ulValueLen; 234 235 buf += privkey_attrs[i].ulValueLen; 236 } 237 238 /* then the key attributes values */ 239 rv = C_GetAttributeValue(sess, privkey_obj, privkey_attrs, attr_cnt); 240 if (rv != CKR_OK) { 241 (void) fprintf(stderr, 242 "Cannot get private key object attributes." 243 " error = %s\n", pkcs11_strerror(rv)); 244 return (NULL); 245 } 246 247 bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, 248 attr_cnt * sizeof (kssl_object_attribute_t)); 249 250 buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); 251 kssl_params->kssl_certs.sc_count = 1; 252 bcopy(&cert_size, buf, sizeof (uint32_t)); 253 kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params; 254 buf += MAX_CHAIN_LENGTH * sizeof (uint32_t); 255 256 /* now the certs values */ 257 cert_attrs[0].pValue = buf; 258 kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params; 259 buf += cert_attrs[0].ulValueLen; 260 261 rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1); 262 if (rv != CKR_OK) { 263 (void) fprintf(stderr, "Cannot get cert value." 264 " error = %s\n", pkcs11_strerror(rv)); 265 return (NULL); 266 } 267 268 *paramsize = bufsize; 269 return (kssl_params); 270 } 271 272 #define max_num_cert 32 273 274 static kssl_params_t * 275 load_from_pkcs11(const char *token_label, const char *password_file, 276 const char *certname, int *bufsize) 277 { 278 static CK_BBOOL true = TRUE; 279 static CK_BBOOL false = FALSE; 280 281 CK_RV rv; 282 CK_SLOT_ID slot; 283 CK_SLOT_ID_PTR pk11_slots; 284 CK_ULONG slotcnt = 10; 285 CK_TOKEN_INFO token_info; 286 CK_SESSION_HANDLE sess; 287 static CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; 288 static CK_CERTIFICATE_TYPE cert_type = CKC_X_509; 289 CK_ATTRIBUTE cert_tmpl[4] = { 290 {CKA_TOKEN, &true, sizeof (true)}, 291 {CKA_LABEL, NULL, 0}, 292 {CKA_CLASS, &cert_class, sizeof (cert_class)}, 293 {CKA_CERTIFICATE_TYPE, &cert_type, sizeof (cert_type)} 294 }; 295 CK_ULONG cert_tmpl_count = 4, cert_obj_count = 1; 296 CK_OBJECT_HANDLE cert_obj, privkey_obj; 297 CK_OBJECT_HANDLE cert_objs[max_num_cert]; 298 static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY; 299 static CK_KEY_TYPE privkey_type = CKK_RSA; 300 CK_ATTRIBUTE privkey_tmpl[] = { 301 {CKA_MODULUS, NULL, 0}, 302 {CKA_TOKEN, &true, sizeof (true)}, 303 {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, 304 {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)} 305 }; 306 CK_ULONG privkey_tmpl_count = 4, privkey_obj_count = 1; 307 static CK_BYTE modulus[1024]; 308 CK_ATTRIBUTE privkey_attrs[1] = { 309 {CKA_MODULUS, modulus, sizeof (modulus)}, 310 }; 311 boolean_t bingo = B_FALSE; 312 int blen, mlen; 313 uchar_t *mval, *ber_buf; 314 char token_label_padded[sizeof (token_info.label) + 1]; 315 316 (void) snprintf(token_label_padded, sizeof (token_label_padded), 317 "%-32s", token_label); 318 319 rv = C_Initialize(NULL_PTR); 320 321 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 322 (void) fprintf(stderr, 323 "Cannot initialize PKCS#11. error = %s\n", 324 pkcs11_strerror(rv)); 325 return (NULL); 326 } 327 328 /* Get slot count */ 329 rv = C_GetSlotList(1, NULL_PTR, &slotcnt); 330 if (rv != CKR_OK || slotcnt == 0) { 331 (void) fprintf(stderr, 332 "Cannot get PKCS#11 slot list. error = %s\n", 333 pkcs11_strerror(rv)); 334 return (NULL); 335 } 336 337 pk11_slots = calloc(slotcnt, sizeof (CK_SLOT_ID)); 338 if (pk11_slots == NULL) { 339 (void) fprintf(stderr, 340 "Cannot get memory for %ld slots\n", slotcnt); 341 return (NULL); 342 } 343 344 rv = C_GetSlotList(1, pk11_slots, &slotcnt); 345 if (rv != CKR_OK) { 346 (void) fprintf(stderr, 347 "Cannot get PKCS#11 slot list. error = %s\n", 348 pkcs11_strerror(rv)); 349 return (NULL); 350 } 351 352 if (verbose) 353 (void) printf("Found %ld slots\n", slotcnt); 354 355 /* Search the token that matches the label */ 356 while (slotcnt > 0) { 357 rv = C_GetTokenInfo(pk11_slots[--slotcnt], &token_info); 358 if (rv != CKR_OK) 359 continue; 360 361 if (verbose) 362 (void) printf("slot [%ld] = %s\n", 363 slotcnt, token_info.label); 364 if (memcmp(token_label_padded, token_info.label, 365 sizeof (token_info.label)) == 0) { 366 bingo = B_TRUE; 367 slot = pk11_slots[slotcnt]; 368 break; 369 } 370 if (verbose) { 371 token_info.label[31] = '\0'; 372 (void) printf("found slot [%s]\n", token_info.label); 373 } 374 } 375 376 if (!bingo) { 377 (void) fprintf(stderr, "no matching PKCS#11 token found\n"); 378 return (NULL); 379 } 380 381 rv = C_OpenSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, 382 &sess); 383 if (rv != CKR_OK) { 384 (void) fprintf(stderr, "Cannot open session. error = %s\n", 385 pkcs11_strerror(rv)); 386 return (NULL); 387 } 388 389 cert_tmpl[1].pValue = (CK_VOID_PTR) certname; 390 cert_tmpl[1].ulValueLen = strlen(certname); 391 392 rv = C_FindObjectsInit(sess, cert_tmpl, cert_tmpl_count); 393 if (rv != CKR_OK) { 394 (void) fprintf(stderr, 395 "Cannot initialize cert search." 396 " error = %s\n", pkcs11_strerror(rv)); 397 return (NULL); 398 } 399 400 rv = C_FindObjects(sess, cert_objs, 401 (certname == NULL ? 1 : max_num_cert), &cert_obj_count); 402 if (rv != CKR_OK) { 403 (void) fprintf(stderr, 404 "Cannot retrieve cert object. error = %s\n", 405 pkcs11_strerror(rv)); 406 return (NULL); 407 } 408 409 /* Who cares if this fails! */ 410 (void) C_FindObjectsFinal(sess); 411 if (verbose) 412 (void) printf("found %ld certificates\n", cert_obj_count); 413 414 if (cert_obj_count == 0) { 415 (void) fprintf(stderr, "\"%s\" not found.\n", certname); 416 (void) fprintf(stderr, "no certs. bye.\n"); 417 return (NULL); 418 } 419 420 cert_obj = cert_objs[0]; 421 422 /* Get the modulus value from the certificate */ 423 ber_buf = get_cert_val(sess, cert_obj, &blen); 424 if (ber_buf == NULL) { 425 (void) fprintf(stderr, 426 "Cannot get certificate data for \"%s\".\n", certname); 427 return (NULL); 428 } 429 430 mval = get_modulus(ber_buf, blen, &mlen); 431 if (mval == NULL) { 432 (void) fprintf(stderr, 433 "Cannot get Modulus in certificate \"%s\".\n", certname); 434 return (NULL); 435 } 436 437 /* Now get the private key */ 438 439 /* Gotta authenticate first if login is required. */ 440 if (token_info.flags & CKF_LOGIN_REQUIRED) { 441 char passphrase[1024]; 442 CK_ULONG ulPinLen; 443 444 ulPinLen = get_passphrase( 445 password_file, passphrase, sizeof (passphrase)); 446 if (ulPinLen == 0) { 447 (void) fprintf(stderr, "Unable to read passphrase"); 448 return (NULL); 449 } 450 451 rv = C_Login(sess, CKU_USER, (CK_UTF8CHAR_PTR)passphrase, 452 ulPinLen); 453 if (rv != CKR_OK) { 454 (void) fprintf(stderr, "Cannot login to the token." 455 " error = %s\n", pkcs11_strerror(rv)); 456 return (NULL); 457 } 458 } 459 460 privkey_tmpl[0].pValue = mval; 461 privkey_tmpl[0].ulValueLen = mlen; 462 463 rv = C_FindObjectsInit(sess, privkey_tmpl, privkey_tmpl_count); 464 if (rv != CKR_OK) { 465 (void) fprintf(stderr, "Cannot intialize private key search." 466 " error = %s\n", pkcs11_strerror(rv)); 467 return (NULL); 468 } 469 470 rv = C_FindObjects(sess, &privkey_obj, 1, &privkey_obj_count); 471 if (rv != CKR_OK) { 472 (void) fprintf(stderr, "Cannot retrieve private key object " 473 " error = %s\n", pkcs11_strerror(rv)); 474 return (NULL); 475 } 476 /* Who cares if this fails! */ 477 (void) C_FindObjectsFinal(sess); 478 479 480 (void) printf("found %ld private keys\n", privkey_obj_count); 481 482 if (privkey_obj_count == 0) { 483 (void) fprintf(stderr, "no private keys. bye.\n"); 484 return (NULL); 485 } 486 487 rv = C_GetAttributeValue(sess, privkey_obj, privkey_attrs, 1); 488 if (rv != CKR_OK) { 489 (void) fprintf(stderr, 490 "Cannot get private key object attributes." 491 " error = %s\n", pkcs11_strerror(rv)); 492 return (NULL); 493 } 494 495 if (verbose) { 496 (void) printf("private key attributes: \n"); 497 (void) printf("\tmodulus: size %ld value:", 498 privkey_attrs[0].ulValueLen); 499 } 500 501 /* Now wrap the key, then unwrap it */ 502 503 { 504 CK_BYTE aes_key_val[16] = { 505 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 506 static CK_BYTE aes_param[16] = { 507 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 508 CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, 16}; 509 CK_OBJECT_HANDLE aes_key_obj, sess_privkey_obj; 510 CK_BYTE *wrapped_privkey; 511 CK_ULONG wrapped_privkey_len; 512 513 CK_ATTRIBUTE unwrap_tmpl[] = { 514 {CKA_TOKEN, &false, sizeof (false)}, 515 {CKA_CLASS, &privkey_class, sizeof (privkey_class)}, 516 {CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}, 517 {CKA_SENSITIVE, &false, sizeof (false)}, 518 {CKA_PRIVATE, &false, sizeof (false)} 519 }; 520 521 rv = SUNW_C_KeyToObject(sess, CKM_AES_CBC_PAD, aes_key_val, 16, 522 &aes_key_obj); 523 524 if (rv != CKR_OK) { 525 (void) fprintf(stderr, 526 "Cannot create wrapping key. error = %s\n", 527 pkcs11_strerror(rv)); 528 return (NULL); 529 } 530 531 /* get the size of the wrapped key */ 532 rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj, 533 NULL, &wrapped_privkey_len); 534 if (rv != CKR_OK) { 535 (void) fprintf(stderr, "Cannot get key size. error = %s\n", 536 pkcs11_strerror(rv)); 537 return (NULL); 538 } 539 540 wrapped_privkey = malloc(wrapped_privkey_len * sizeof (CK_BYTE)); 541 if (wrapped_privkey == NULL) { 542 return (NULL); 543 } 544 545 /* do the actual key wrapping */ 546 rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj, 547 wrapped_privkey, &wrapped_privkey_len); 548 if (rv != CKR_OK) { 549 (void) fprintf(stderr, "Cannot wrap private key. error = %s\n", 550 pkcs11_strerror(rv)); 551 return (NULL); 552 } 553 554 (void) C_Logout(sess); 555 (void) printf("private key successfully wrapped, " 556 "wrapped blob length: %ld\n", 557 wrapped_privkey_len); 558 559 rv = C_UnwrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, 560 wrapped_privkey, wrapped_privkey_len, 561 unwrap_tmpl, 5, &sess_privkey_obj); 562 if (rv != CKR_OK) { 563 (void) fprintf(stderr, "Cannot unwrap private key." 564 " error = %s\n", pkcs11_strerror(rv)); 565 return (NULL); 566 } 567 (void) printf("session private key successfully unwrapped\n"); 568 569 return (pkcs11_to_kssl(sess, sess_privkey_obj, cert_obj, bufsize)); 570 } 571 } 572 573 /* 574 * See the comments for pkcs11_to_kssl() for the layout of the 575 * returned buffer. 576 */ 577 static kssl_params_t * 578 openssl_to_kssl(RSA *rsa, int ncerts, uchar_t *cert_bufs[], int *cert_sizes, 579 int *paramsize) 580 { 581 int i, tcsize; 582 kssl_params_t *kssl_params; 583 kssl_key_t *key; 584 char *buf; 585 uint32_t bufsize; 586 kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT]; 587 kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = { 588 {SUN_CKA_MODULUS, NULL, 0}, 589 {SUN_CKA_PUBLIC_EXPONENT, NULL, 0}, 590 {SUN_CKA_PRIVATE_EXPONENT, NULL, 0}, 591 {SUN_CKA_PRIME_1, NULL, 0}, 592 {SUN_CKA_PRIME_2, NULL, 0}, 593 {SUN_CKA_EXPONENT_1, NULL, 0}, 594 {SUN_CKA_EXPONENT_2, NULL, 0}, 595 {SUN_CKA_COEFFICIENT, NULL, 0} 596 }; 597 BIGNUM *priv_key_bignums[MAX_ATTR_CNT]; 598 int attr_cnt; 599 600 tcsize = 0; 601 for (i = 0; i < ncerts; i++) 602 tcsize += cert_sizes[i]; 603 604 bufsize = sizeof (kssl_params_t); 605 bufsize += (tcsize + MAX_CHAIN_LENGTH * sizeof (uint32_t)); 606 607 /* and the key attributes */ 608 priv_key_bignums[0] = rsa->n; /* MODULUS */ 609 priv_key_bignums[1] = rsa->e; /* PUBLIC_EXPONENT */ 610 priv_key_bignums[2] = rsa->d; /* PRIVATE_EXPONENT */ 611 priv_key_bignums[3] = rsa->p; /* PRIME_1 */ 612 priv_key_bignums[4] = rsa->q; /* PRIME_2 */ 613 priv_key_bignums[5] = rsa->dmp1; /* EXPONENT_1 */ 614 priv_key_bignums[6] = rsa->dmq1; /* EXPONENT_2 */ 615 priv_key_bignums[7] = rsa->iqmp; /* COEFFICIENT */ 616 617 if (rsa->n == NULL || rsa->d == NULL) { 618 (void) fprintf(stderr, 619 "missing required attributes in private key.\n"); 620 return (NULL); 621 } 622 623 attr_cnt = 0; 624 for (i = 0; i < MAX_ATTR_CNT; i++) { 625 if (priv_key_bignums[i] == NULL) 626 continue; 627 kssl_attrs[attr_cnt].ka_type = kssl_tmpl_attrs[i].ka_type; 628 kssl_attrs[attr_cnt].ka_value_len = 629 BN_num_bytes(priv_key_bignums[i]); 630 bufsize += sizeof (crypto_object_attribute_t) + 631 kssl_attrs[attr_cnt].ka_value_len; 632 attr_cnt++; 633 } 634 635 /* Add 4-byte cushion as sc_sizes[0] needs 32-bit aligment */ 636 bufsize += sizeof (uint32_t); 637 638 /* Now the big memory allocation */ 639 if ((buf = calloc(bufsize, 1)) == NULL) { 640 (void) fprintf(stderr, 641 "Cannot allocate memory for the kssl_params " 642 "and values\n"); 643 return (NULL); 644 } 645 646 /* LINTED */ 647 kssl_params = (kssl_params_t *)buf; 648 649 buf = (char *)(kssl_params + 1); 650 651 /* the keys attributes structs array */ 652 key = &kssl_params->kssl_privkey; 653 key->ks_format = CRYPTO_KEY_ATTR_LIST; 654 key->ks_count = attr_cnt; 655 key->ks_attrs_offset = buf - (char *)kssl_params; 656 buf += attr_cnt * sizeof (kssl_object_attribute_t); 657 658 attr_cnt = 0; 659 /* then the key attributes values */ 660 for (i = 0; i < MAX_ATTR_CNT; i++) { 661 if (priv_key_bignums[i] == NULL) 662 continue; 663 (void) BN_bn2bin(priv_key_bignums[i], (unsigned char *)buf); 664 kssl_attrs[attr_cnt].ka_value_offset = 665 buf - (char *)kssl_params; 666 buf += kssl_attrs[attr_cnt].ka_value_len; 667 attr_cnt++; 668 } 669 670 bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset, 671 attr_cnt * sizeof (kssl_object_attribute_t)); 672 673 buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t)); 674 kssl_params->kssl_certs.sc_count = ncerts; 675 bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t)); 676 kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params; 677 buf += MAX_CHAIN_LENGTH * sizeof (uint32_t); 678 679 kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params; 680 /* now the certs values */ 681 for (i = 0; i < ncerts; i++) { 682 bcopy(cert_bufs[i], buf, cert_sizes[i]); 683 buf += cert_sizes[i]; 684 } 685 686 *paramsize = bufsize; 687 return (kssl_params); 688 } 689 690 static kssl_params_t * 691 add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file, 692 const char *password_file) 693 { 694 int i, ncerts, newlen; 695 int *cert_sizes; 696 uint32_t certlen = 0; 697 char *buf; 698 uchar_t **cert_bufs; 699 kssl_params_t *kssl_params; 700 701 ncerts = 0; 702 cert_bufs = PEM_get_rsa_key_certs(cacert_chain_file, 703 (char *)password_file, NULL, &cert_sizes, &ncerts); 704 if (cert_bufs == NULL || ncerts == 0) { 705 free(old_params); 706 return (NULL); 707 } 708 709 if (verbose) { 710 (void) printf("%d certificates read successfully\n", ncerts); 711 } 712 713 newlen = old_params->kssl_params_size; 714 for (i = 0; i < ncerts; i++) 715 newlen += cert_sizes[i]; 716 717 /* 718 * Get a bigger structure and update the 719 * fields to account for the additional certs. 720 */ 721 kssl_params = realloc(old_params, newlen); 722 723 kssl_params->kssl_params_size = newlen; 724 kssl_params->kssl_certs.sc_count += ncerts; 725 726 /* Put the cert_sizes starting from sc_sizes[1] */ 727 buf = (char *)kssl_params; 728 buf += kssl_params->kssl_certs.sc_sizes_offset; 729 bcopy(buf, &certlen, sizeof (uint32_t)); 730 buf += sizeof (uint32_t); 731 bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t)); 732 733 /* Put the cert_bufs starting from sc_certs[1] */ 734 buf = (char *)kssl_params; 735 buf += kssl_params->kssl_certs.sc_certs_offset; 736 buf += certlen; 737 738 /* now the certs values */ 739 for (i = 0; i < ncerts; i++) { 740 bcopy(cert_bufs[i], buf, cert_sizes[i]); 741 buf += cert_sizes[i]; 742 } 743 744 for (i = 0; i < ncerts; i++) 745 free(cert_bufs[i]); 746 free(cert_bufs); 747 free(cert_sizes); 748 749 return (kssl_params); 750 } 751 752 static kssl_params_t * 753 load_from_pem(const char *filename, const char *password_file, int *paramsize) 754 { 755 uchar_t **cert_bufs; 756 int *cert_sizes, ncerts, i; 757 RSA *rsa; 758 kssl_params_t *kssl_params; 759 760 ncerts = 0; 761 cert_bufs = PEM_get_rsa_key_certs(filename, (char *)password_file, 762 &rsa, &cert_sizes, &ncerts); 763 if (rsa == NULL || cert_bufs == NULL || ncerts == 0) { 764 return (NULL); 765 } 766 767 if (verbose) 768 (void) printf("%d certificates read successfully\n", ncerts); 769 770 kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs, 771 cert_sizes, paramsize); 772 773 for (i = 0; i < ncerts; i++) 774 free(cert_bufs[i]); 775 free(cert_bufs); 776 free(cert_sizes); 777 RSA_free(rsa); 778 return (kssl_params); 779 } 780 781 static kssl_params_t * 782 load_from_pkcs12(const char *filename, const char *password_file, 783 int *paramsize) 784 { 785 RSA *rsa; 786 kssl_params_t *kssl_params; 787 uchar_t **cert_bufs; 788 int *cert_sizes, ncerts, i; 789 790 ncerts = 0; 791 cert_bufs = PKCS12_get_rsa_key_certs(filename, password_file, &rsa, 792 &cert_sizes, &ncerts); 793 if (cert_bufs == NULL || ncerts == 0) { 794 (void) fprintf(stderr, 795 "Unable to read cert and/or key from %s\n", filename); 796 return (NULL); 797 } 798 799 if (verbose) 800 (void) printf("%d certificates read successfully\n", ncerts); 801 802 kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs, 803 cert_sizes, paramsize); 804 805 for (i = 0; i < ncerts; i++) 806 free(cert_bufs[i]); 807 free(cert_bufs); 808 free(cert_sizes); 809 810 RSA_free(rsa); 811 return (kssl_params); 812 } 813 814 815 int 816 parse_and_set_addr(char *server_address, char *server_port, 817 struct sockaddr_in *addr) 818 { 819 if (server_port == NULL) { 820 return (-1); 821 } 822 823 if (server_address == NULL) { 824 addr->sin_addr.s_addr = INADDR_ANY; 825 } else { 826 addr->sin_addr.s_addr = inet_addr(server_address); 827 if ((int)addr->sin_addr.s_addr == -1) { 828 struct hostent *hp; 829 830 if ((hp = gethostbyname(server_address)) == NULL) { 831 (void) fprintf(stderr, 832 "Error: Unknown host: %s\n", 833 server_address); 834 return (-1); 835 } 836 837 (void) memcpy(&addr->sin_addr.s_addr, 838 hp->h_addr_list[0], 839 sizeof (addr->sin_addr.s_addr)); 840 } 841 } 842 843 errno = 0; 844 addr->sin_port = strtol(server_port, NULL, 10); 845 if (addr->sin_port == 0 || errno != 0) { 846 (void) fprintf(stderr, "Error: Invalid Port value: %s\n", 847 server_port); 848 return (-1); 849 } 850 851 return (0); 852 } 853 854 /* 855 * The order of the ciphers is important. It is used as the 856 * default order (when -c is not specified). 857 */ 858 struct csuite { 859 const char *suite; 860 uint16_t val; 861 boolean_t seen; 862 } cipher_suites[CIPHER_SUITE_COUNT - 1] = { 863 {"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE}, 864 {"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE}, 865 {"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE}, 866 {"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE}, 867 }; 868 869 static int 870 check_suites(char *suites, uint16_t *sarray) 871 { 872 int i; 873 int err = 0; 874 char *suite; 875 int sindx = 0; 876 877 if (suites != NULL) { 878 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) 879 sarray[i] = CIPHER_NOTSET; 880 } else { 881 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) 882 sarray[i] = cipher_suites[i].val; 883 return (err); 884 } 885 886 suite = strtok(suites, ","); 887 do { 888 for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) { 889 if (strcasecmp(suite, cipher_suites[i].suite) == 0) { 890 if (!cipher_suites[i].seen) { 891 sarray[sindx++] = cipher_suites[i].val; 892 cipher_suites[i].seen = B_TRUE; 893 } 894 break; 895 } 896 } 897 898 if (i == (CIPHER_SUITE_COUNT - 1)) { 899 (void) fprintf(stderr, 900 "Unknown Cipher suite name: %s\n", suite); 901 err++; 902 } 903 } while ((suite = strtok(NULL, ",")) != NULL); 904 905 return (err); 906 } 907 908 int 909 do_create(int argc, char *argv[]) 910 { 911 const char *softtoken_dir = NULL; 912 const char *token_label = NULL; 913 const char *password_file = NULL; 914 const char *cert_key_file = NULL; 915 const char *cacert_chain_file = NULL; 916 const char *certname = NULL; 917 char *suites = NULL; 918 uint32_t timeout = DEFAULT_SID_TIMEOUT; 919 uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES; 920 int proxy_port = -1; 921 struct sockaddr_in server_addr; 922 char *format = NULL; 923 char *port, *addr; 924 char c; 925 int pcnt; 926 kssl_params_t *kssl_params; 927 int bufsize; 928 929 argc -= 1; 930 argv += 1; 931 932 while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) { 933 switch (c) { 934 case 'd': 935 softtoken_dir = optarg; 936 break; 937 case 'c': 938 suites = optarg; 939 break; 940 case 'C': 941 certname = optarg; 942 break; 943 case 'f': 944 format = optarg; 945 break; 946 case 'h': 947 cacert_chain_file = optarg; 948 break; 949 case 'i': 950 cert_key_file = optarg; 951 break; 952 case 'T': 953 token_label = optarg; 954 break; 955 case 'p': 956 password_file = optarg; 957 break; 958 case 't': 959 timeout = atoi(optarg); 960 break; 961 case 'x': 962 proxy_port = atoi(optarg); 963 break; 964 case 'v': 965 verbose = B_TRUE; 966 break; 967 case 'z': 968 scache_size = atoi(optarg); 969 break; 970 default: 971 goto err; 972 } 973 } 974 975 pcnt = argc - optind; 976 if (pcnt == 0) { 977 port = "443"; /* default SSL port */ 978 addr = NULL; 979 } else if (pcnt == 1) { 980 port = argv[optind]; 981 addr = NULL; 982 } else if (pcnt == 2) { 983 addr = argv[optind]; 984 port = argv[optind + 1]; 985 } else { 986 goto err; 987 } 988 989 if (parse_and_set_addr(addr, port, &server_addr) < 0) { 990 goto err; 991 } 992 993 if (verbose) { 994 (void) printf("addr=%s, port = %d\n", 995 inet_ntoa(server_addr.sin_addr), server_addr.sin_port); 996 } 997 998 if (format == NULL || proxy_port == -1) { 999 goto err; 1000 } 1001 1002 if (strcmp(format, "pkcs11") == 0) { 1003 if (token_label == NULL || certname == NULL) { 1004 goto err; 1005 } 1006 if (softtoken_dir != NULL) { 1007 (void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1); 1008 if (verbose) { 1009 (void) printf( 1010 "SOFTTOKEN_DIR=%s\n", 1011 getenv("SOFTTOKEN_DIR")); 1012 } 1013 } 1014 kssl_params = load_from_pkcs11( 1015 token_label, password_file, certname, &bufsize); 1016 } else if (strcmp(format, "pkcs12") == 0) { 1017 if (cert_key_file == NULL) { 1018 goto err; 1019 } 1020 kssl_params = load_from_pkcs12( 1021 cert_key_file, password_file, &bufsize); 1022 } else if (strcmp(format, "pem") == 0) { 1023 if (cert_key_file == NULL) { 1024 goto err; 1025 } 1026 kssl_params = load_from_pem( 1027 cert_key_file, password_file, &bufsize); 1028 } else { 1029 (void) fprintf(stderr, "Unsupported cert format: %s\n", format); 1030 goto err; 1031 } 1032 1033 if (kssl_params == NULL) { 1034 return (FAILURE); 1035 } 1036 1037 if (check_suites(suites, kssl_params->kssl_suites) != 0) 1038 goto err; 1039 1040 kssl_params->kssl_params_size = bufsize; 1041 kssl_params->kssl_addr = server_addr; 1042 kssl_params->kssl_session_cache_timeout = timeout; 1043 kssl_params->kssl_proxy_port = proxy_port; 1044 kssl_params->kssl_session_cache_size = scache_size; 1045 1046 if (cacert_chain_file != NULL) { 1047 kssl_params = add_cacerts(kssl_params, cacert_chain_file, 1048 password_file); 1049 if (kssl_params == NULL) { 1050 return (FAILURE); 1051 } 1052 } 1053 1054 if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) { 1055 (void) fprintf(stderr, "Error loading cert and key"); 1056 return (FAILURE); 1057 } 1058 1059 if (verbose) 1060 (void) printf("Successfully loaded cert and key\n"); 1061 1062 free(kssl_params); 1063 return (SUCCESS); 1064 1065 err: 1066 usage_create(B_TRUE); 1067 return (SMF_EXIT_ERR_CONFIG); 1068 } 1069