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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <string.h> 28 #include <ctype.h> 29 #include <malloc.h> 30 #include <libgen.h> 31 #include <errno.h> 32 #include <cryptoutil.h> 33 #include <security/cryptoki.h> 34 #include "common.h" 35 #include <kmfapi.h> 36 37 38 static KMF_RETURN 39 genkey_nss(KMF_HANDLE_T kmfhandle, char *token, char *dir, char *prefix, 40 char *keylabel, KMF_KEY_ALG keyAlg, int keylen, KMF_CREDENTIAL *tokencred) 41 { 42 KMF_RETURN kmfrv = KMF_OK; 43 KMF_KEY_HANDLE key; 44 KMF_ATTRIBUTE attlist[20]; 45 int i = 0; 46 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 47 KMF_KEY_ALG keytype; 48 uint32_t keylength; 49 50 if (keylabel == NULL) { 51 cryptoerror(LOG_STDERR, 52 gettext("A key label must be specified \n")); 53 return (KMF_ERR_BAD_PARAMETER); 54 } 55 56 kmfrv = configure_nss(kmfhandle, dir, prefix); 57 if (kmfrv != KMF_OK) 58 return (kmfrv); 59 60 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 61 62 keytype = keyAlg; 63 keylength = keylen; 64 65 kmf_set_attr_at_index(attlist, i, 66 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 67 i++; 68 69 kmf_set_attr_at_index(attlist, i, 70 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE)); 71 i++; 72 73 kmf_set_attr_at_index(attlist, i, 74 KMF_KEYALG_ATTR, &keytype, sizeof (keytype)); 75 i++; 76 77 kmf_set_attr_at_index(attlist, i, 78 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength)); 79 i++; 80 81 if (keylabel != NULL) { 82 kmf_set_attr_at_index(attlist, i, 83 KMF_KEYLABEL_ATTR, keylabel, 84 strlen(keylabel)); 85 i++; 86 } 87 88 if (tokencred != NULL && tokencred->cred != NULL) { 89 kmf_set_attr_at_index(attlist, i, 90 KMF_CREDENTIAL_ATTR, tokencred, 91 sizeof (KMF_CREDENTIAL)); 92 i++; 93 } 94 95 if (token != NULL) { 96 kmf_set_attr_at_index(attlist, i, 97 KMF_TOKEN_LABEL_ATTR, token, 98 strlen(token)); 99 i++; 100 } 101 102 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist); 103 104 return (kmfrv); 105 } 106 107 static KMF_RETURN 108 genkey_pkcs11(KMF_HANDLE_T kmfhandle, char *token, 109 char *keylabel, KMF_KEY_ALG keyAlg, int keylen, 110 char *senstr, char *extstr, boolean_t print_hex, 111 KMF_CREDENTIAL *tokencred) 112 { 113 KMF_RETURN kmfrv = KMF_OK; 114 KMF_KEY_HANDLE key; 115 KMF_RAW_SYM_KEY *rkey = NULL; 116 boolean_t sensitive = B_FALSE; 117 boolean_t not_extractable = B_FALSE; 118 char *hexstr = NULL; 119 int hexstrlen; 120 KMF_ATTRIBUTE attlist[20]; 121 int i = 0; 122 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 123 KMF_KEY_ALG keytype; 124 uint32_t keylength; 125 126 if (keylabel == NULL) { 127 cryptoerror(LOG_STDERR, 128 gettext("A key label must be specified \n")); 129 return (KMF_ERR_BAD_PARAMETER); 130 } 131 132 /* Check the sensitive option value if specified. */ 133 if (senstr != NULL) { 134 if (tolower(senstr[0]) == 'y') 135 sensitive = B_TRUE; 136 else if (tolower(senstr[0]) == 'n') 137 sensitive = B_FALSE; 138 else { 139 cryptoerror(LOG_STDERR, 140 gettext("Incorrect sensitive option value.\n")); 141 return (KMF_ERR_BAD_PARAMETER); 142 } 143 } 144 145 /* Check the extractable option value if specified. */ 146 if (extstr != NULL) { 147 if (tolower(extstr[0]) == 'y') 148 not_extractable = B_FALSE; 149 else if (tolower(extstr[0]) == 'n') 150 not_extractable = B_TRUE; 151 else { 152 cryptoerror(LOG_STDERR, 153 gettext("Incorrect extractable option value.\n")); 154 return (KMF_ERR_BAD_PARAMETER); 155 } 156 } 157 158 /* Select a PKCS11 token first */ 159 kmfrv = select_token(kmfhandle, token, FALSE); 160 if (kmfrv != KMF_OK) { 161 return (kmfrv); 162 } 163 164 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 165 166 keytype = keyAlg; 167 keylength = keylen; /* bits */ 168 169 kmf_set_attr_at_index(attlist, i, 170 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 171 i++; 172 173 kmf_set_attr_at_index(attlist, i, 174 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE)); 175 i++; 176 177 kmf_set_attr_at_index(attlist, i, 178 KMF_KEYALG_ATTR, &keytype, sizeof (keytype)); 179 i++; 180 181 kmf_set_attr_at_index(attlist, i, 182 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength)); 183 i++; 184 185 if (keylabel != NULL) { 186 kmf_set_attr_at_index(attlist, i, 187 KMF_KEYLABEL_ATTR, keylabel, 188 strlen(keylabel)); 189 i++; 190 } 191 192 if (tokencred != NULL && tokencred->cred != NULL) { 193 kmf_set_attr_at_index(attlist, i, 194 KMF_CREDENTIAL_ATTR, tokencred, 195 sizeof (KMF_CREDENTIAL)); 196 i++; 197 } 198 199 kmf_set_attr_at_index(attlist, i, 200 KMF_SENSITIVE_BOOL_ATTR, &sensitive, 201 sizeof (sensitive)); 202 i++; 203 204 kmf_set_attr_at_index(attlist, i, 205 KMF_NON_EXTRACTABLE_BOOL_ATTR, ¬_extractable, 206 sizeof (not_extractable)); 207 i++; 208 209 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist); 210 if (kmfrv != KMF_OK) { 211 goto out; 212 } 213 214 if (print_hex) { 215 if (sensitive == B_TRUE || not_extractable == B_TRUE) { 216 cryptoerror(LOG_STDERR, 217 gettext("Warning: can not reveal the key value " 218 "for a sensitive or non-extractable key.\n")); 219 goto out; 220 } else { 221 rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 222 if (rkey == NULL) { 223 kmfrv = KMF_ERR_MEMORY; 224 goto out; 225 } 226 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 227 kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey); 228 if (kmfrv != KMF_OK) { 229 goto out; 230 } 231 hexstrlen = 2 * rkey->keydata.len + 1; 232 hexstr = malloc(hexstrlen); 233 if (hexstr == NULL) { 234 kmfrv = KMF_ERR_MEMORY; 235 goto out; 236 } 237 238 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr, 239 hexstrlen); 240 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr); 241 } 242 } 243 244 out: 245 kmf_free_raw_sym_key(rkey); 246 247 if (hexstr != NULL) 248 free(hexstr); 249 250 return (kmfrv); 251 } 252 253 254 static KMF_RETURN 255 genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir, 256 char *outkey, boolean_t print_hex) 257 { 258 KMF_RETURN kmfrv = KMF_OK; 259 KMF_KEY_HANDLE key; 260 KMF_RAW_SYM_KEY *rkey = NULL; 261 char *hexstr = NULL; 262 int hexstrlen; 263 KMF_ATTRIBUTE attlist[20]; 264 int i = 0; 265 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 266 KMF_KEY_ALG keytype; 267 uint32_t keylength; 268 char *dirpath; 269 270 if (EMPTYSTRING(outkey)) { 271 cryptoerror(LOG_STDERR, 272 gettext("No output key file was specified for the key\n")); 273 return (KMF_ERR_BAD_PARAMETER); 274 } 275 276 if (verify_file(outkey)) { 277 cryptoerror(LOG_STDERR, 278 gettext("Cannot write the indicated output " 279 "key file (%s).\n"), outkey); 280 return (KMF_ERR_BAD_PARAMETER); 281 } 282 283 (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE)); 284 285 keytype = keyAlg; 286 keylength = keylen; 287 288 dirpath = dir; 289 290 kmf_set_attr_at_index(attlist, i, 291 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 292 i++; 293 294 kmf_set_attr_at_index(attlist, i, 295 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE)); 296 i++; 297 298 kmf_set_attr_at_index(attlist, i, 299 KMF_KEYALG_ATTR, &keytype, sizeof (keytype)); 300 i++; 301 302 kmf_set_attr_at_index(attlist, i, 303 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength)); 304 i++; 305 306 if (dirpath != NULL) { 307 kmf_set_attr_at_index(attlist, i, 308 KMF_DIRPATH_ATTR, dirpath, 309 strlen(dirpath)); 310 i++; 311 } 312 313 if (outkey != NULL) { 314 kmf_set_attr_at_index(attlist, i, 315 KMF_KEY_FILENAME_ATTR, outkey, 316 strlen(outkey)); 317 i++; 318 } 319 320 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist); 321 if (kmfrv != KMF_OK) { 322 goto out; 323 } 324 325 if (print_hex) { 326 rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 327 if (rkey == NULL) { 328 kmfrv = KMF_ERR_MEMORY; 329 goto out; 330 } 331 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 332 kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey); 333 if (kmfrv != KMF_OK) { 334 goto out; 335 } 336 337 hexstrlen = 2 * rkey->keydata.len + 1; 338 hexstr = malloc(hexstrlen); 339 if (hexstr == NULL) { 340 kmfrv = KMF_ERR_MEMORY; 341 goto out; 342 } 343 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr, 344 hexstrlen); 345 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr); 346 } 347 348 out: 349 kmf_free_raw_sym_key(rkey); 350 351 if (hexstr != NULL) 352 free(hexstr); 353 354 return (kmfrv); 355 } 356 357 int 358 pk_genkey(int argc, char *argv[]) 359 { 360 int rv; 361 int opt; 362 extern int optind_av; 363 extern char *optarg_av; 364 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 365 char *tokenname = NULL; 366 char *dir = NULL; 367 char *prefix = NULL; 368 char *keytype = "generic"; 369 char *keylenstr = NULL; 370 int keylen = 0; 371 char *keylabel = NULL; 372 char *outkey = NULL; 373 char *senstr = NULL; 374 char *extstr = NULL; 375 char *printstr = NULL; 376 KMF_HANDLE_T kmfhandle = NULL; 377 KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET; 378 boolean_t print_hex = B_FALSE; 379 KMF_CREDENTIAL tokencred = { NULL, 0 }; 380 381 while ((opt = getopt_av(argc, argv, 382 "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)" 383 "t:(keytype)y:(keylen)K:(outkey)P:(print)" 384 "s:(sensitive)e:(extractable)")) != EOF) { 385 if (EMPTYSTRING(optarg_av)) 386 return (PK_ERR_USAGE); 387 switch (opt) { 388 case 'k': 389 kstype = KS2Int(optarg_av); 390 if (kstype == 0) 391 return (PK_ERR_USAGE); 392 break; 393 case 'l': 394 if (keylabel) 395 return (PK_ERR_USAGE); 396 keylabel = optarg_av; 397 break; 398 case 'T': 399 if (tokenname) 400 return (PK_ERR_USAGE); 401 tokenname = optarg_av; 402 break; 403 case 'd': 404 if (dir) 405 return (PK_ERR_USAGE); 406 dir = optarg_av; 407 break; 408 case 'p': 409 if (prefix) 410 return (PK_ERR_USAGE); 411 prefix = optarg_av; 412 break; 413 case 't': 414 keytype = optarg_av; 415 break; 416 case 'y': 417 if (keylenstr) 418 return (PK_ERR_USAGE); 419 keylenstr = optarg_av; 420 break; 421 case 'K': 422 if (outkey) 423 return (PK_ERR_USAGE); 424 outkey = optarg_av; 425 break; 426 case 'P': 427 if (printstr) 428 return (PK_ERR_USAGE); 429 printstr = optarg_av; 430 break; 431 case 's': 432 if (senstr) 433 return (PK_ERR_USAGE); 434 senstr = optarg_av; 435 break; 436 case 'e': 437 if (extstr) 438 return (PK_ERR_USAGE); 439 extstr = optarg_av; 440 break; 441 default: 442 return (PK_ERR_USAGE); 443 } 444 } 445 446 /* No additional args allowed. */ 447 argc -= optind_av; 448 argv += optind_av; 449 if (argc) { 450 return (PK_ERR_USAGE); 451 } 452 453 /* Check keytype. If not specified, default to AES */ 454 if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) { 455 cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"), 456 keytype); 457 return (PK_ERR_USAGE); 458 } 459 460 /* 461 * Check and set the key length. 462 * - For DES and 3DES, the key size are fixed. Ingore the keylen 463 * option, even if it is specified. 464 * - For AES and ARCFOUR, if keylen is not specified, default to 465 * 128 bits. 466 */ 467 if (keyAlg == KMF_DES) 468 keylen = 64; /* fixed size; ignore input */ 469 else if (keyAlg == KMF_DES3) 470 keylen = 192; /* fixed size; ignore input */ 471 else /* AES, ARCFOUR, or GENERIC SECRET */ { 472 if (keylenstr == NULL) { 473 cryptoerror(LOG_STDERR, 474 gettext("Key length must be specified for " 475 "AES, ARCFOUR or GENERIC symmetric keys.\n")); 476 return (PK_ERR_USAGE); 477 } 478 if (sscanf(keylenstr, "%d", &keylen) != 1) { 479 cryptoerror(LOG_STDERR, 480 gettext("Unrecognized key length (%s).\n"), 481 keytype); 482 return (PK_ERR_USAGE); 483 } 484 if (keylen == 0 || (keylen % 8) != 0) { 485 cryptoerror(LOG_STDERR, 486 gettext("Key length bitlength must be a " 487 "multiple of 8.\n")); 488 return (PK_ERR_USAGE); 489 } 490 } 491 492 /* check the print option */ 493 if (printstr != NULL) { 494 if (kstype == KMF_KEYSTORE_NSS) { 495 cryptoerror(LOG_STDERR, 496 gettext("The print option does not apply " 497 "to the NSS keystore.\n")); 498 return (PK_ERR_USAGE); 499 } 500 501 if (tolower(printstr[0]) == 'y') 502 print_hex = B_TRUE; 503 else if (tolower(printstr[0]) == 'n') 504 print_hex = B_FALSE; 505 else { 506 cryptoerror(LOG_STDERR, 507 gettext("Incorrect print option value.\n")); 508 return (PK_ERR_USAGE); 509 } 510 } 511 512 /* check the sensitive and extractable options */ 513 if ((senstr != NULL || extstr != NULL) && 514 (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) { 515 cryptoerror(LOG_STDERR, 516 gettext("The sensitive or extractable option applies " 517 "to the PKCS11 keystore only.\n")); 518 return (PK_ERR_USAGE); 519 } 520 521 if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) { 522 tokenname = PK_DEFAULT_PK11TOKEN; 523 } else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) { 524 tokenname = DEFAULT_NSS_TOKEN; 525 } 526 DIR_OPTION_CHECK(kstype, dir); 527 528 if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS) 529 (void) get_token_password(kstype, tokenname, &tokencred); 530 531 if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 532 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 533 goto end; 534 } 535 536 if (kstype == KMF_KEYSTORE_NSS) { 537 rv = genkey_nss(kmfhandle, tokenname, dir, prefix, 538 keylabel, keyAlg, keylen, &tokencred); 539 } else if (kstype == KMF_KEYSTORE_OPENSSL) { 540 rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey, 541 print_hex); 542 } else { 543 rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg, 544 keylen, senstr, extstr, print_hex, &tokencred); 545 } 546 547 end: 548 if (rv != KMF_OK) 549 display_error(kmfhandle, rv, 550 gettext("Error generating key")); 551 552 if (tokencred.cred != NULL) 553 free(tokencred.cred); 554 555 (void) kmf_finalize(kmfhandle); 556 if (rv != KMF_OK) 557 return (PK_ERR_USAGE); 558 559 return (0); 560 } 561