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