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 #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->cred != NULL) { 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->cred != NULL) { 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; 291 292 kmf_set_attr_at_index(attlist, i, 293 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 294 i++; 295 296 kmf_set_attr_at_index(attlist, i, 297 KMF_KEY_HANDLE_ATTR, &key, sizeof (KMF_KEY_HANDLE)); 298 i++; 299 300 kmf_set_attr_at_index(attlist, i, 301 KMF_KEYALG_ATTR, &keytype, sizeof (keytype)); 302 i++; 303 304 kmf_set_attr_at_index(attlist, i, 305 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength)); 306 i++; 307 308 if (dirpath != NULL) { 309 kmf_set_attr_at_index(attlist, i, 310 KMF_DIRPATH_ATTR, dirpath, 311 strlen(dirpath)); 312 i++; 313 } 314 315 if (outkey != NULL) { 316 kmf_set_attr_at_index(attlist, i, 317 KMF_KEY_FILENAME_ATTR, outkey, 318 strlen(outkey)); 319 i++; 320 } 321 322 kmfrv = kmf_create_sym_key(kmfhandle, i, attlist); 323 if (kmfrv != KMF_OK) { 324 goto out; 325 } 326 327 if (print_hex) { 328 rkey = malloc(sizeof (KMF_RAW_SYM_KEY)); 329 if (rkey == NULL) { 330 kmfrv = KMF_ERR_MEMORY; 331 goto out; 332 } 333 (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 334 kmfrv = kmf_get_sym_key_value(kmfhandle, &key, rkey); 335 if (kmfrv != KMF_OK) { 336 goto out; 337 } 338 339 hexstrlen = 2 * rkey->keydata.len + 1; 340 hexstr = malloc(hexstrlen); 341 if (hexstr == NULL) { 342 kmfrv = KMF_ERR_MEMORY; 343 goto out; 344 } 345 tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr, 346 hexstrlen); 347 (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr); 348 } 349 350 out: 351 kmf_free_raw_sym_key(rkey); 352 353 if (hexstr != NULL) 354 free(hexstr); 355 356 return (kmfrv); 357 } 358 359 int 360 pk_genkey(int argc, char *argv[]) 361 { 362 int rv; 363 int opt; 364 extern int optind_av; 365 extern char *optarg_av; 366 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 367 char *tokenname = NULL; 368 char *dir = NULL; 369 char *prefix = NULL; 370 char *keytype = "generic"; 371 char *keylenstr = NULL; 372 int keylen = 0; 373 char *keylabel = NULL; 374 char *outkey = NULL; 375 char *senstr = NULL; 376 char *extstr = NULL; 377 char *printstr = NULL; 378 KMF_HANDLE_T kmfhandle = NULL; 379 KMF_KEY_ALG keyAlg = KMF_GENERIC_SECRET; 380 boolean_t print_hex = B_FALSE; 381 KMF_CREDENTIAL tokencred = {NULL, 0}; 382 383 while ((opt = getopt_av(argc, argv, 384 "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)" 385 "t:(keytype)y:(keylen)K:(outkey)P:(print)" 386 "s:(sensitive)e:(extractable)")) != EOF) { 387 if (EMPTYSTRING(optarg_av)) 388 return (PK_ERR_USAGE); 389 switch (opt) { 390 case 'k': 391 kstype = KS2Int(optarg_av); 392 if (kstype == 0) 393 return (PK_ERR_USAGE); 394 break; 395 case 'l': 396 if (keylabel) 397 return (PK_ERR_USAGE); 398 keylabel = optarg_av; 399 break; 400 case 'T': 401 if (tokenname) 402 return (PK_ERR_USAGE); 403 tokenname = optarg_av; 404 break; 405 case 'd': 406 if (dir) 407 return (PK_ERR_USAGE); 408 dir = optarg_av; 409 break; 410 case 'p': 411 if (prefix) 412 return (PK_ERR_USAGE); 413 prefix = optarg_av; 414 break; 415 case 't': 416 keytype = optarg_av; 417 break; 418 case 'y': 419 if (keylenstr) 420 return (PK_ERR_USAGE); 421 keylenstr = optarg_av; 422 break; 423 case 'K': 424 if (outkey) 425 return (PK_ERR_USAGE); 426 outkey = optarg_av; 427 break; 428 case 'P': 429 if (printstr) 430 return (PK_ERR_USAGE); 431 printstr = optarg_av; 432 break; 433 case 's': 434 if (senstr) 435 return (PK_ERR_USAGE); 436 senstr = optarg_av; 437 break; 438 case 'e': 439 if (extstr) 440 return (PK_ERR_USAGE); 441 extstr = optarg_av; 442 break; 443 default: 444 return (PK_ERR_USAGE); 445 } 446 } 447 448 /* No additional args allowed. */ 449 argc -= optind_av; 450 argv += optind_av; 451 if (argc) { 452 return (PK_ERR_USAGE); 453 } 454 455 /* Check keytype. If not specified, default to AES */ 456 if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) { 457 cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"), 458 keytype); 459 return (PK_ERR_USAGE); 460 } 461 462 /* 463 * Check and set the key length. 464 * - For DES and 3DES, the key size are fixed. Ingore the keylen 465 * option, even if it is specified. 466 * - For AES and ARCFOUR, if keylen is not specified, default to 467 * 128 bits. 468 */ 469 if (keyAlg == KMF_DES) 470 keylen = 64; /* fixed size; ignore input */ 471 else if (keyAlg == KMF_DES3) 472 keylen = 192; /* fixed size; ignore input */ 473 else /* AES, ARCFOUR, or GENERIC SECRET */ { 474 if (keylenstr == NULL) { 475 cryptoerror(LOG_STDERR, 476 gettext("Key length must be specified for " 477 "AES, ARCFOUR or GENERIC symmetric keys.\n")); 478 return (PK_ERR_USAGE); 479 } 480 if (sscanf(keylenstr, "%d", &keylen) != 1) { 481 cryptoerror(LOG_STDERR, 482 gettext("Unrecognized key length (%s).\n"), 483 keytype); 484 return (PK_ERR_USAGE); 485 } 486 if (keylen == 0 || (keylen % 8) != 0) { 487 cryptoerror(LOG_STDERR, 488 gettext("Key length bitlength must be a " 489 "multiple of 8.\n")); 490 return (PK_ERR_USAGE); 491 } 492 } 493 494 /* check the print option */ 495 if (printstr != NULL) { 496 if (kstype == KMF_KEYSTORE_NSS) { 497 cryptoerror(LOG_STDERR, 498 gettext("The print option does not apply " 499 "to the NSS keystore.\n")); 500 return (PK_ERR_USAGE); 501 } 502 503 if (tolower(printstr[0]) == 'y') 504 print_hex = B_TRUE; 505 else if (tolower(printstr[0]) == 'n') 506 print_hex = B_FALSE; 507 else { 508 cryptoerror(LOG_STDERR, 509 gettext("Incorrect print option value.\n")); 510 return (PK_ERR_USAGE); 511 } 512 } 513 514 /* check the sensitive and extractable options */ 515 if ((senstr != NULL || extstr != NULL) && 516 (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) { 517 cryptoerror(LOG_STDERR, 518 gettext("The sensitive or extractable option applies " 519 "to the PKCS11 keystore only.\n")); 520 return (PK_ERR_USAGE); 521 } 522 523 if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) { 524 tokenname = PK_DEFAULT_PK11TOKEN; 525 } else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) { 526 tokenname = DEFAULT_NSS_TOKEN; 527 } 528 529 if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS) 530 (void) get_token_password(kstype, tokenname, &tokencred); 531 532 if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 533 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 534 goto end; 535 } 536 537 if (kstype == KMF_KEYSTORE_NSS) { 538 rv = genkey_nss(kmfhandle, tokenname, dir, prefix, 539 keylabel, keyAlg, keylen, &tokencred); 540 } else if (kstype == KMF_KEYSTORE_OPENSSL) { 541 rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey, 542 print_hex); 543 } else { 544 rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg, 545 keylen, senstr, extstr, print_hex, &tokencred); 546 } 547 548 end: 549 if (rv != KMF_OK) 550 display_error(kmfhandle, rv, 551 gettext("Error generating key")); 552 553 if (tokencred.cred != NULL) 554 free(tokencred.cred); 555 556 (void) kmf_finalize(kmfhandle); 557 if (rv != KMF_OK) 558 return (PK_ERR_USAGE); 559 560 return (0); 561 } 562