symkeyutil.c (35905B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 ** symkeyutil.c 7 ** 8 ** utility for managing symetric keys in the database or the token 9 ** 10 */ 11 12 /* 13 * Wish List for this utility: 14 * 1) Display and Set the CKA_ operation flags for the key. 15 * 2) Modify existing keys 16 * 3) Copy keys 17 * 4) Read CKA_ID and display for keys. 18 * 5) Option to store CKA_ID in a file on key creation. 19 * 6) Encrypt, Decrypt, Hash, and Mac with generated keys. 20 * 7) Use asymetric keys to wrap and unwrap keys. 21 * 8) Derive. 22 * 9) PBE keys. 23 */ 24 25 #include <stdio.h> 26 #include <string.h> 27 28 #include "secutil.h" 29 30 #include "nspr.h" 31 32 #include "pk11func.h" 33 #include "secasn1.h" 34 #include "cert.h" 35 #include "cryptohi.h" 36 #include "secoid.h" 37 #include "certdb.h" 38 #include "nss.h" 39 40 typedef struct _KeyTypes { 41 CK_KEY_TYPE keyType; 42 CK_MECHANISM_TYPE mechType; 43 CK_MECHANISM_TYPE wrapMech; 44 char *label; 45 } KeyTypes; 46 47 static KeyTypes keyArray[] = { 48 #ifdef RECOGNIZE_ASYMETRIC_TYPES 49 { CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, "rsa" }, 50 { CKK_DSA, CKM_DSA, CKM_INVALID_MECHANISM, "dsa" }, 51 { CKK_DH, CKM_DH_PKCS_DERIVE, CKM_INVALID_MECHANISM, "dh" }, 52 { CKK_EC, CKM_ECDSA, CKM_INVALID_MECHANISM, "ec" }, 53 { CKK_X9_42_DH, CKM_X9_42_DH_DERIVE, CKM_INVALID_MECHANISM, "x9.42dh" }, 54 { CKK_KEA, CKM_KEA_KEY_DERIVE, CKM_INVALID_MECHANISM, "kea" }, 55 #endif 56 { CKK_GENERIC_SECRET, CKM_SHA_1_HMAC, CKM_INVALID_MECHANISM, "generic" }, 57 { CKK_RC2, CKM_RC2_CBC, CKM_RC2_ECB, "rc2" }, 58 /* don't define a wrap mech for RC-4 since it's note really safe */ 59 { CKK_RC4, CKM_RC4, CKM_INVALID_MECHANISM, "rc4" }, 60 { CKK_DES, CKM_DES_CBC, CKM_DES_ECB, "des" }, 61 { CKK_DES2, CKM_DES2_KEY_GEN, CKM_DES3_ECB, "des2" }, 62 { CKK_DES3, CKM_DES3_KEY_GEN, CKM_DES3_ECB, "des3" }, 63 { CKK_CAST, CKM_CAST_CBC, CKM_CAST_ECB, "cast" }, 64 { CKK_CAST3, CKM_CAST3_CBC, CKM_CAST3_ECB, "cast3" }, 65 { CKK_CAST5, CKM_CAST5_CBC, CKM_CAST5_ECB, "cast5" }, 66 { CKK_CAST128, CKM_CAST128_CBC, CKM_CAST128_ECB, "cast128" }, 67 { CKK_RC5, CKM_RC5_CBC, CKM_RC5_ECB, "rc5" }, 68 { CKK_IDEA, CKM_IDEA_CBC, CKM_IDEA_ECB, "idea" }, 69 { CKK_SKIPJACK, CKM_SKIPJACK_CBC64, CKM_SKIPJACK_WRAP, "skipjack" }, 70 { CKK_BATON, CKM_BATON_CBC128, CKM_BATON_WRAP, "baton" }, 71 { CKK_JUNIPER, CKM_JUNIPER_CBC128, CKM_JUNIPER_WRAP, "juniper" }, 72 { CKK_CDMF, CKM_CDMF_CBC, CKM_CDMF_ECB, "cdmf" }, 73 { CKK_AES, CKM_AES_CBC, CKM_AES_ECB, "aes" }, 74 { CKK_CAMELLIA, CKM_CAMELLIA_CBC, CKM_CAMELLIA_ECB, "camellia" }, 75 }; 76 77 static int keyArraySize = sizeof(keyArray) / sizeof(keyArray[0]); 78 79 int 80 GetLen(PRFileDesc *fd) 81 { 82 PRFileInfo info; 83 84 if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info)) { 85 return -1; 86 } 87 88 return info.size; 89 } 90 91 int 92 ReadBuf(char *inFile, SECItem *item) 93 { 94 int len; 95 int ret; 96 PRFileDesc *fd = PR_Open(inFile, PR_RDONLY, 0); 97 if (NULL == fd) { 98 SECU_PrintError("symkeyutil", "PR_Open failed"); 99 return -1; 100 } 101 102 len = GetLen(fd); 103 if (len < 0) { 104 SECU_PrintError("symkeyutil", "PR_GetOpenFileInfo failed"); 105 return -1; 106 } 107 item->data = (unsigned char *)PORT_Alloc(len); 108 if (item->data == NULL) { 109 fprintf(stderr, "Failed to allocate %d to read file %s\n", len, inFile); 110 return -1; 111 } 112 113 ret = PR_Read(fd, item->data, item->len); 114 if (ret < 0) { 115 SECU_PrintError("symkeyutil", "PR_Read failed"); 116 PORT_Free(item->data); 117 item->data = NULL; 118 return -1; 119 } 120 PR_Close(fd); 121 item->len = len; 122 return 0; 123 } 124 125 int 126 WriteBuf(char *inFile, SECItem *item) 127 { 128 int ret; 129 PRFileDesc *fd = PR_Open(inFile, PR_WRONLY | PR_CREATE_FILE, 0x200); 130 if (NULL == fd) { 131 SECU_PrintError("symkeyutil", "PR_Open failed"); 132 return -1; 133 } 134 135 ret = PR_Write(fd, item->data, item->len); 136 if (ret < 0) { 137 SECU_PrintError("symkeyutil", "PR_Write failed"); 138 return -1; 139 } 140 PR_Close(fd); 141 return 0; 142 } 143 144 CK_KEY_TYPE 145 GetKeyTypeFromString(const char *keyString) 146 { 147 int i; 148 for (i = 0; i < keyArraySize; i++) { 149 if (PL_strcasecmp(keyString, keyArray[i].label) == 0) { 150 return keyArray[i].keyType; 151 } 152 } 153 return (CK_KEY_TYPE)-1; 154 } 155 156 CK_MECHANISM_TYPE 157 GetKeyMechFromString(const char *keyString) 158 { 159 int i; 160 for (i = 0; i < keyArraySize; i++) { 161 if (PL_strcasecmp(keyString, keyArray[i].label) == 0) { 162 return keyArray[i].mechType; 163 } 164 } 165 return (CK_MECHANISM_TYPE)-1; 166 } 167 168 const char * 169 GetStringFromKeyType(CK_KEY_TYPE type) 170 { 171 int i; 172 for (i = 0; i < keyArraySize; i++) { 173 if (keyArray[i].keyType == type) { 174 return keyArray[i].label; 175 } 176 } 177 return "unmatched"; 178 } 179 180 CK_MECHANISM_TYPE 181 GetWrapFromKeyType(CK_KEY_TYPE type) 182 { 183 int i; 184 for (i = 0; i < keyArraySize; i++) { 185 if (keyArray[i].keyType == type) { 186 return keyArray[i].wrapMech; 187 } 188 } 189 return CKM_INVALID_MECHANISM; 190 } 191 192 CK_MECHANISM_TYPE 193 GetWrapMechanism(PK11SymKey *symKey) 194 { 195 CK_KEY_TYPE type = PK11_GetSymKeyType(symKey); 196 197 return GetWrapFromKeyType(type); 198 } 199 200 int 201 GetDigit(char c) 202 { 203 if (c == 0) { 204 return -1; 205 } 206 if (c <= '9' && c >= '0') { 207 return c - '0'; 208 } 209 if (c <= 'f' && c >= 'a') { 210 return c - 'a' + 0xa; 211 } 212 if (c <= 'F' && c >= 'A') { 213 return c - 'A' + 0xa; 214 } 215 return -1; 216 } 217 218 char 219 ToDigit(unsigned char c) 220 { 221 c = c & 0xf; 222 if (c <= 9) { 223 return (char)(c + '0'); 224 } 225 return (char)(c + 'a' - 0xa); 226 } 227 228 char * 229 BufToHex(SECItem *outbuf) 230 { 231 int len = outbuf->len * 2 + 1; 232 char *string, *ptr; 233 unsigned int i; 234 235 string = PORT_Alloc(len); 236 if (!string) { 237 return NULL; 238 } 239 240 ptr = string; 241 for (i = 0; i < outbuf->len; i++) { 242 *ptr++ = ToDigit(outbuf->data[i] >> 4); 243 *ptr++ = ToDigit(outbuf->data[i] & 0xf); 244 } 245 *ptr = 0; 246 return string; 247 } 248 249 int 250 HexToBuf(char *inString, SECItem *outbuf) 251 { 252 int len = strlen(inString); 253 int outlen = len + 1 / 2; 254 int trueLen = 0; 255 256 outbuf->data = PORT_Alloc(outlen); 257 if (!outbuf->data) { 258 return -1; 259 } 260 261 while (*inString) { 262 int digit1, digit2; 263 digit1 = GetDigit(*inString++); 264 digit2 = GetDigit(*inString++); 265 if ((digit1 == -1) || (digit2 == -1)) { 266 PORT_Free(outbuf->data); 267 outbuf->data = NULL; 268 return -1; 269 } 270 outbuf->data[trueLen++] = digit1 << 4 | digit2; 271 } 272 outbuf->len = trueLen; 273 return 0; 274 } 275 276 void 277 printBuf(unsigned char *data, int len) 278 { 279 int i; 280 281 for (i = 0; i < len; i++) { 282 printf("%02x", data[i]); 283 } 284 } 285 286 void 287 PrintKey(PK11SymKey *symKey) 288 { 289 char *name = PK11_GetSymKeyNickname(symKey); 290 int len = PK11_GetKeyLength(symKey); 291 int strength = PK11_GetKeyStrength(symKey, NULL); 292 SECItem *value = NULL; 293 CK_KEY_TYPE type = PK11_GetSymKeyType(symKey); 294 (void)PK11_ExtractKeyValue(symKey); 295 296 value = PK11_GetKeyData(symKey); 297 298 printf("%-20s %3d %4d %10s ", name ? name : " ", len, strength, 299 GetStringFromKeyType(type)); 300 if (value && value->data) { 301 printBuf(value->data, value->len); 302 } else { 303 printf("<restricted>"); 304 } 305 printf("\n"); 306 PORT_Free(name); 307 } 308 309 SECStatus 310 ListKeys(PK11SlotInfo *slot, int *printLabel, void *pwd) 311 { 312 PK11SymKey *keyList; 313 SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd); 314 if (rv != SECSuccess) { 315 return rv; 316 ; 317 } 318 319 keyList = PK11_ListFixedKeysInSlot(slot, NULL, pwd); 320 if (keyList) { 321 if (*printLabel) { 322 printf(" Name Len Strength Type Data\n"); 323 *printLabel = 0; 324 } 325 printf("%s:\n", PK11_GetTokenName(slot)); 326 } 327 while (keyList) { 328 PK11SymKey *freeKey = keyList; 329 PrintKey(keyList); 330 keyList = PK11_GetNextSymKey(keyList); 331 PK11_FreeSymKey(freeKey); 332 } 333 return SECSuccess; 334 } 335 336 PK11SymKey * 337 FindKey(PK11SlotInfo *slot, char *name, SECItem *id, void *pwd) 338 { 339 PK11SymKey *key = NULL; 340 SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd); 341 342 if (rv != SECSuccess) { 343 return NULL; 344 } 345 346 if (id->data) { 347 key = PK11_FindFixedKey(slot, CKM_INVALID_MECHANISM, id, pwd); 348 } 349 if (name && !key) { 350 key = PK11_ListFixedKeysInSlot(slot, name, pwd); 351 } 352 353 if (key) { 354 printf("Found a key\n"); 355 PrintKey(key); 356 } 357 return key; 358 } 359 360 PRBool 361 IsKeyList(PK11SymKey *symKey) 362 { 363 return (PRBool)(PK11_GetNextSymKey(symKey) != NULL); 364 } 365 366 void 367 FreeKeyList(PK11SymKey *symKey) 368 { 369 PK11SymKey *next, *current; 370 371 for (current = symKey; current; current = next) { 372 next = PK11_GetNextSymKey(current); 373 PK11_FreeSymKey(current); 374 } 375 return; 376 } 377 378 static void 379 Usage(char *progName) 380 { 381 #define FPS fprintf(stderr, 382 FPS "Type %s -H for more detailed descriptions\n", progName); 383 FPS "Usage:"); 384 FPS "\t%s -L [std_opts] [-r]\n", progName); 385 FPS "\t%s -K [-n name] -t type [-s size] [-i id |-j id_file] [std_opts]\n", progName); 386 FPS "\t%s -D <[-n name | -i id | -j id_file> [std_opts]\n", progName); 387 FPS "\t%s -I [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]\n", progName); 388 FPS "\t%s -E <-nname | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]\n", progName); 389 FPS "\t%s -U [-n name] [-t type] [-i id | -j id_file] -k data_file <wrap_opts> [std_opts]\n", progName); 390 FPS "\t%s -W <-n name | -i id | -j id_file> [-t type] -k data_file [-r] <wrap_opts> [std_opts]\n", progName); 391 FPS "\t%s -M <-n name | -i id | -j id_file> -g target_token [std_opts]\n", progName); 392 FPS "\t\t std_opts -> [-d certdir] [-P dbprefix] [-p password] [-f passwordFile] [-h token]\n"); 393 FPS "\t\t wrap_opts -> <-w wrap_name | -x wrap_id | -y id_file>\n"); 394 exit(1); 395 } 396 397 static void 398 LongUsage(char *progName) 399 { 400 int i; 401 FPS "%-15s List all the keys.\n", "-L"); 402 FPS "%-15s Generate a new key.\n", "-K"); 403 FPS "%-20s Specify the nickname of the new key\n", 404 " -n name"); 405 FPS "%-20s Specify the id in hex of the new key\n", 406 " -i key id"); 407 FPS "%-20s Specify a file to read the id of the new key\n", 408 " -j key id file"); 409 FPS "%-20s Specify the keyType of the new key\n", 410 " -t type"); 411 FPS "%-20s", " valid types: "); 412 for (i = 0; i < keyArraySize; i++) { 413 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':','); 414 } 415 FPS "%-20s Specify the size of the new key in bytes (required by some types)\n", 416 " -s size"); 417 FPS "%-15s Delete a key.\n", "-D"); 418 FPS "%-20s Specify the nickname of the key to delete\n", 419 " -n name"); 420 FPS "%-20s Specify the id in hex of the key to delete\n", 421 " -i key id"); 422 FPS "%-20s Specify a file to read the id of the key to delete\n", 423 " -j key id file"); 424 FPS "%-15s Import a new key from a data file.\n", "-I"); 425 FPS "%-20s Specify the data file to read the key from.\n", 426 " -k key file"); 427 FPS "%-20s Specify the nickname of the new key\n", 428 " -n name"); 429 FPS "%-20s Specify the id in hex of the new key\n", 430 " -i key id"); 431 FPS "%-20s Specify a file to read the id of the new key\n", 432 " -j key id file"); 433 FPS "%-20s Specify the keyType of the new key\n", 434 " -t type"); 435 FPS "%-20s", " valid types: "); 436 for (i = 0; i < keyArraySize; i++) { 437 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':','); 438 } 439 FPS "%-15s Export a key to a data file.\n", "-E"); 440 FPS "%-20s Specify the data file to write the key to.\n", 441 " -k key file"); 442 FPS "%-20s Specify the nickname of the key to export\n", 443 " -n name"); 444 FPS "%-20s Specify the id in hex of the key to export\n", 445 " -i key id"); 446 FPS "%-20s Specify a file to read the id of the key to export\n", 447 " -j key id file"); 448 FPS "%-15s Move a key to a new token.\n", "-M"); 449 FPS "%-20s Specify the nickname of the key to move\n", 450 " -n name"); 451 FPS "%-20s Specify the id in hex of the key to move\n", 452 " -i key id"); 453 FPS "%-20s Specify a file to read the id of the key to move\n", 454 " -j key id file"); 455 FPS "%-20s Specify the token to move the key to\n", 456 " -g target token"); 457 FPS "%-15s Unwrap a new key from a data file.\n", "-U"); 458 FPS "%-20s Specify the data file to read the encrypted key from.\n", 459 " -k key file"); 460 FPS "%-20s Specify the nickname of the new key\n", 461 " -n name"); 462 FPS "%-20s Specify the id in hex of the new key\n", 463 " -i key id"); 464 FPS "%-20s Specify a file to read the id of the new key\n", 465 " -j key id file"); 466 FPS "%-20s Specify the keyType of the new key\n", 467 " -t type"); 468 FPS "%-20s", " valid types: "); 469 for (i = 0; i < keyArraySize; i++) { 470 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':','); 471 } 472 FPS "%-20s Specify the nickname of the wrapping key\n", 473 " -w wrap name"); 474 FPS "%-20s Specify the id in hex of the wrapping key\n", 475 " -x wrap key id"); 476 FPS "%-20s Specify a file to read the id of the wrapping key\n", 477 " -y wrap key id file"); 478 FPS "%-15s Wrap a new key to a data file. [not yet implemented]\n", "-W"); 479 FPS "%-20s Specify the data file to write the encrypted key to.\n", 480 " -k key file"); 481 FPS "%-20s Specify the nickname of the key to wrap\n", 482 " -n name"); 483 FPS "%-20s Specify the id in hex of the key to wrap\n", 484 " -i key id"); 485 FPS "%-20s Specify a file to read the id of the key to wrap\n", 486 " -j key id file"); 487 FPS "%-20s Specify the nickname of the wrapping key\n", 488 " -w wrap name"); 489 FPS "%-20s Specify the id in hex of the wrapping key\n", 490 " -x wrap key id"); 491 FPS "%-20s Specify a file to read the id of the wrapping key\n", 492 " -y wrap key id file"); 493 FPS "%-15s Options valid for all commands\n", "std_opts"); 494 FPS "%-20s The directory where the NSS db's reside\n", 495 " -d certdir"); 496 FPS "%-20s Prefix for the NSS db's\n", 497 " -P db prefix"); 498 FPS "%-20s Specify password on the command line\n", 499 " -p password"); 500 FPS "%-20s Specify password file on the command line\n", 501 " -f password file"); 502 FPS "%-20s Specify token to act on\n", 503 " -h token"); 504 exit(1); 505 #undef FPS 506 } 507 508 /* Certutil commands */ 509 enum { 510 cmd_CreateNewKey = 0, 511 cmd_DeleteKey, 512 cmd_ImportKey, 513 cmd_ExportKey, 514 cmd_WrapKey, 515 cmd_UnwrapKey, 516 cmd_MoveKey, 517 cmd_ListKeys, 518 cmd_PrintHelp 519 }; 520 521 /* Certutil options */ 522 enum { 523 opt_CertDir = 0, 524 opt_PasswordFile, 525 opt_TargetToken, 526 opt_TokenName, 527 opt_KeyID, 528 opt_KeyIDFile, 529 opt_KeyType, 530 opt_Nickname, 531 opt_KeyFile, 532 opt_Password, 533 opt_dbPrefix, 534 opt_RW, 535 opt_KeySize, 536 opt_WrapKeyName, 537 opt_WrapKeyID, 538 opt_WrapKeyIDFile, 539 opt_NoiseFile 540 }; 541 542 static secuCommandFlag symKeyUtil_commands[] = { 543 { /* cmd_CreateNewKey */ 'K', PR_FALSE, 0, PR_FALSE }, 544 { /* cmd_DeleteKey */ 'D', PR_FALSE, 0, PR_FALSE }, 545 { /* cmd_ImportKey */ 'I', PR_FALSE, 0, PR_FALSE }, 546 { /* cmd_ExportKey */ 'E', PR_FALSE, 0, PR_FALSE }, 547 { /* cmd_WrapKey */ 'W', PR_FALSE, 0, PR_FALSE }, 548 { /* cmd_UnwrapKey */ 'U', PR_FALSE, 0, PR_FALSE }, 549 { /* cmd_MoveKey */ 'M', PR_FALSE, 0, PR_FALSE }, 550 { /* cmd_ListKeys */ 'L', PR_FALSE, 0, PR_FALSE }, 551 { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE }, 552 }; 553 554 static secuCommandFlag symKeyUtil_options[] = { 555 { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, 556 { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE }, 557 { /* opt_TargetToken */ 'g', PR_TRUE, 0, PR_FALSE }, 558 { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, 559 { /* opt_KeyID */ 'i', PR_TRUE, 0, PR_FALSE }, 560 { /* opt_KeyIDFile */ 'j', PR_TRUE, 0, PR_FALSE }, 561 { /* opt_KeyType */ 't', PR_TRUE, 0, PR_FALSE }, 562 { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE }, 563 { /* opt_KeyFile */ 'k', PR_TRUE, 0, PR_FALSE }, 564 { /* opt_Password */ 'p', PR_TRUE, 0, PR_FALSE }, 565 { /* opt_dbPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, 566 { /* opt_RW */ 'r', PR_FALSE, 0, PR_FALSE }, 567 { /* opt_KeySize */ 's', PR_TRUE, 0, PR_FALSE }, 568 { /* opt_WrapKeyName */ 'w', PR_TRUE, 0, PR_FALSE }, 569 { /* opt_WrapKeyID */ 'x', PR_TRUE, 0, PR_FALSE }, 570 { /* opt_WrapKeyIDFile */ 'y', PR_TRUE, 0, PR_FALSE }, 571 { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE }, 572 }; 573 574 int 575 main(int argc, char **argv) 576 { 577 PK11SlotInfo *slot = NULL; 578 char *slotname = "internal"; 579 char *certPrefix = ""; 580 CK_MECHANISM_TYPE keyType = CKM_SHA_1_HMAC; 581 int keySize = 0; 582 char *name = NULL; 583 char *wrapName = NULL; 584 secuPWData pwdata = { PW_NONE, 0 }; 585 PRBool readOnly = PR_FALSE; 586 SECItem key; 587 SECItem keyID; 588 SECItem wrapKeyID; 589 int commandsEntered = 0; 590 int commandToRun = 0; 591 char *progName; 592 int i; 593 SECStatus rv = SECFailure; 594 595 secuCommand symKeyUtil; 596 symKeyUtil.numCommands = sizeof(symKeyUtil_commands) / sizeof(secuCommandFlag); 597 symKeyUtil.numOptions = sizeof(symKeyUtil_options) / sizeof(secuCommandFlag); 598 symKeyUtil.commands = symKeyUtil_commands; 599 symKeyUtil.options = symKeyUtil_options; 600 601 key.data = NULL; 602 key.len = 0; 603 keyID.data = NULL; 604 keyID.len = 0; 605 wrapKeyID.data = NULL; 606 wrapKeyID.len = 0; 607 608 progName = strrchr(argv[0], '/'); 609 progName = progName ? progName + 1 : argv[0]; 610 611 rv = SECU_ParseCommandLine(argc, argv, progName, &symKeyUtil); 612 613 if (rv != SECSuccess) 614 Usage(progName); 615 616 rv = SECFailure; 617 618 /* -H print help */ 619 if (symKeyUtil.commands[cmd_PrintHelp].activated) 620 LongUsage(progName); 621 622 /* -f password file, -p password */ 623 if (symKeyUtil.options[opt_PasswordFile].arg) { 624 pwdata.source = PW_FROMFILE; 625 pwdata.data = symKeyUtil.options[opt_PasswordFile].arg; 626 } else if (symKeyUtil.options[opt_Password].arg) { 627 pwdata.source = PW_PLAINTEXT; 628 pwdata.data = symKeyUtil.options[opt_Password].arg; 629 } 630 631 /* -d directory */ 632 if (symKeyUtil.options[opt_CertDir].activated) 633 SECU_ConfigDirectory(symKeyUtil.options[opt_CertDir].arg); 634 635 /* -s key size */ 636 if (symKeyUtil.options[opt_KeySize].activated) { 637 keySize = PORT_Atoi(symKeyUtil.options[opt_KeySize].arg); 638 } 639 640 /* -h specify token name */ 641 if (symKeyUtil.options[opt_TokenName].activated) { 642 if (PL_strcmp(symKeyUtil.options[opt_TokenName].arg, "all") == 0) 643 slotname = NULL; 644 else 645 slotname = PL_strdup(symKeyUtil.options[opt_TokenName].arg); 646 } 647 648 /* -t key type */ 649 if (symKeyUtil.options[opt_KeyType].activated) { 650 keyType = GetKeyMechFromString(symKeyUtil.options[opt_KeyType].arg); 651 if (keyType == (CK_MECHANISM_TYPE)-1) { 652 PR_fprintf(PR_STDERR, 653 "%s unknown key type (%s).\n", 654 progName, symKeyUtil.options[opt_KeyType].arg); 655 return 255; 656 } 657 } 658 659 /* -k for import and unwrap, it specifies an input file to read from, 660 * for export and wrap it specifies an output file to write to */ 661 if (symKeyUtil.options[opt_KeyFile].activated) { 662 if (symKeyUtil.commands[cmd_ImportKey].activated || 663 symKeyUtil.commands[cmd_UnwrapKey].activated) { 664 int ret = ReadBuf(symKeyUtil.options[opt_KeyFile].arg, &key); 665 if (ret < 0) { 666 PR_fprintf(PR_STDERR, 667 "%s Couldn't read key file (%s).\n", 668 progName, symKeyUtil.options[opt_KeyFile].arg); 669 return 255; 670 } 671 } 672 } 673 674 /* -i specify the key ID */ 675 if (symKeyUtil.options[opt_KeyID].activated) { 676 int ret = HexToBuf(symKeyUtil.options[opt_KeyID].arg, &keyID); 677 if (ret < 0) { 678 PR_fprintf(PR_STDERR, 679 "%s invalid key ID (%s).\n", 680 progName, symKeyUtil.options[opt_KeyID].arg); 681 return 255; 682 } 683 } 684 685 /* -i & -j are mutually exclusive */ 686 if ((symKeyUtil.options[opt_KeyID].activated) && 687 (symKeyUtil.options[opt_KeyIDFile].activated)) { 688 PR_fprintf(PR_STDERR, 689 "%s -i and -j options are mutually exclusive.\n", progName); 690 return 255; 691 } 692 693 /* -x specify the Wrap key ID */ 694 if (symKeyUtil.options[opt_WrapKeyID].activated) { 695 int ret = HexToBuf(symKeyUtil.options[opt_WrapKeyID].arg, &wrapKeyID); 696 if (ret < 0) { 697 PR_fprintf(PR_STDERR, 698 "%s invalid key ID (%s).\n", 699 progName, symKeyUtil.options[opt_WrapKeyID].arg); 700 return 255; 701 } 702 } 703 704 /* -x & -y are mutually exclusive */ 705 if ((symKeyUtil.options[opt_KeyID].activated) && 706 (symKeyUtil.options[opt_KeyIDFile].activated)) { 707 PR_fprintf(PR_STDERR, 708 "%s -i and -j options are mutually exclusive.\n", progName); 709 return 255; 710 } 711 712 /* -y specify the key ID */ 713 if (symKeyUtil.options[opt_WrapKeyIDFile].activated) { 714 int ret = ReadBuf(symKeyUtil.options[opt_WrapKeyIDFile].arg, 715 &wrapKeyID); 716 if (ret < 0) { 717 PR_fprintf(PR_STDERR, 718 "%s Couldn't read key ID file (%s).\n", 719 progName, symKeyUtil.options[opt_WrapKeyIDFile].arg); 720 return 255; 721 } 722 } 723 724 /* -P certdb name prefix */ 725 if (symKeyUtil.options[opt_dbPrefix].activated) 726 certPrefix = symKeyUtil.options[opt_dbPrefix].arg; 727 728 /* Check number of commands entered. */ 729 commandsEntered = 0; 730 for (i = 0; i < symKeyUtil.numCommands; i++) { 731 if (symKeyUtil.commands[i].activated) { 732 commandToRun = symKeyUtil.commands[i].flag; 733 commandsEntered++; 734 } 735 if (commandsEntered > 1) 736 break; 737 } 738 if (commandsEntered > 1) { 739 PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName); 740 PR_fprintf(PR_STDERR, "You entered: "); 741 for (i = 0; i < symKeyUtil.numCommands; i++) { 742 if (symKeyUtil.commands[i].activated) 743 PR_fprintf(PR_STDERR, " -%c", symKeyUtil.commands[i].flag); 744 } 745 PR_fprintf(PR_STDERR, "\n"); 746 return 255; 747 } 748 if (commandsEntered == 0) { 749 PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName); 750 Usage(progName); 751 } 752 753 if (symKeyUtil.commands[cmd_ListKeys].activated || 754 symKeyUtil.commands[cmd_PrintHelp].activated || 755 symKeyUtil.commands[cmd_ExportKey].activated || 756 symKeyUtil.commands[cmd_WrapKey].activated) { 757 readOnly = !symKeyUtil.options[opt_RW].activated; 758 } 759 760 if ((symKeyUtil.commands[cmd_ImportKey].activated || 761 symKeyUtil.commands[cmd_ExportKey].activated || 762 symKeyUtil.commands[cmd_WrapKey].activated || 763 symKeyUtil.commands[cmd_UnwrapKey].activated) && 764 !symKeyUtil.options[opt_KeyFile].activated) { 765 PR_fprintf(PR_STDERR, 766 "%s -%c: keyfile is required for this command (-k).\n", 767 progName, commandToRun); 768 return 255; 769 } 770 771 /* -E, -D, -W, and all require -n, -i, or -j to identify the key */ 772 if ((symKeyUtil.commands[cmd_ExportKey].activated || 773 symKeyUtil.commands[cmd_DeleteKey].activated || 774 symKeyUtil.commands[cmd_WrapKey].activated) && 775 !(symKeyUtil.options[opt_Nickname].activated || 776 symKeyUtil.options[opt_KeyID].activated || 777 symKeyUtil.options[opt_KeyIDFile].activated)) { 778 PR_fprintf(PR_STDERR, 779 "%s -%c: nickname or id is required for this command (-n, -i, -j).\n", 780 progName, commandToRun); 781 return 255; 782 } 783 784 /* -W, -U, and all -w, -x, or -y to identify the wrapping key */ 785 if ((symKeyUtil.commands[cmd_WrapKey].activated || 786 symKeyUtil.commands[cmd_UnwrapKey].activated) && 787 !(symKeyUtil.options[opt_WrapKeyName].activated || 788 symKeyUtil.options[opt_WrapKeyID].activated || 789 symKeyUtil.options[opt_WrapKeyIDFile].activated)) { 790 PR_fprintf(PR_STDERR, 791 "%s -%c: wrap key is required for this command (-w, -x, or -y).\n", 792 progName, commandToRun); 793 return 255; 794 } 795 796 /* -M needs the target slot (-g) */ 797 if (symKeyUtil.commands[cmd_MoveKey].activated && 798 !symKeyUtil.options[opt_TargetToken].activated) { 799 PR_fprintf(PR_STDERR, 800 "%s -%c: target token is required for this command (-g).\n", 801 progName, commandToRun); 802 return 255; 803 } 804 805 /* Using slotname == NULL for listing keys and certs on all slots, 806 * but only that. */ 807 if (!(symKeyUtil.commands[cmd_ListKeys].activated) && slotname == NULL) { 808 PR_fprintf(PR_STDERR, 809 "%s -%c: cannot use \"-h all\" for this command.\n", 810 progName, commandToRun); 811 return 255; 812 } 813 814 name = SECU_GetOptionArg(&symKeyUtil, opt_Nickname); 815 wrapName = SECU_GetOptionArg(&symKeyUtil, opt_WrapKeyName); 816 817 PK11_SetPasswordFunc(SECU_GetModulePassword); 818 819 /* Initialize NSPR and NSS. */ 820 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 821 rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix, 822 "secmod.db", readOnly ? NSS_INIT_READONLY : 0); 823 if (rv != SECSuccess) { 824 SECU_PrintPRandOSError(progName); 825 goto shutdown; 826 } 827 rv = SECFailure; 828 829 if (PL_strcmp(slotname, "internal") == 0) 830 slot = PK11_GetInternalKeySlot(); 831 else if (slotname != NULL) 832 slot = PK11_FindSlotByName(slotname); 833 834 /* generating a new key */ 835 if (symKeyUtil.commands[cmd_CreateNewKey].activated) { 836 PK11SymKey *symKey; 837 838 symKey = PK11_TokenKeyGen(slot, keyType, NULL, keySize, 839 NULL, PR_TRUE, &pwdata); 840 if (!symKey) { 841 PR_fprintf(PR_STDERR, "%s: Token Key Gen Failed\n", progName); 842 goto shutdown; 843 } 844 if (symKeyUtil.options[opt_Nickname].activated) { 845 rv = PK11_SetSymKeyNickname(symKey, name); 846 if (rv != SECSuccess) { 847 PK11_DeleteTokenSymKey(symKey); 848 PK11_FreeSymKey(symKey); 849 PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n", 850 progName); 851 goto shutdown; 852 } 853 } 854 rv = SECSuccess; 855 PrintKey(symKey); 856 PK11_FreeSymKey(symKey); 857 } 858 if (symKeyUtil.commands[cmd_DeleteKey].activated) { 859 PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata); 860 861 if (!symKey) { 862 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); 863 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", 864 progName, keyName, PK11_GetTokenName(slot)); 865 PORT_Free(keyName); 866 goto shutdown; 867 } 868 869 rv = PK11_DeleteTokenSymKey(symKey); 870 FreeKeyList(symKey); 871 if (rv != SECSuccess) { 872 PR_fprintf(PR_STDERR, "%s: Couldn't Delete Key \n", progName); 873 goto shutdown; 874 } 875 } 876 if (symKeyUtil.commands[cmd_UnwrapKey].activated) { 877 PK11SymKey *wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata); 878 PK11SymKey *symKey; 879 CK_MECHANISM_TYPE mechanism; 880 881 if (!wrapKey) { 882 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) 883 : PORT_Strdup(wrapName); 884 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", 885 progName, keyName, PK11_GetTokenName(slot)); 886 PORT_Free(keyName); 887 goto shutdown; 888 } 889 mechanism = GetWrapMechanism(wrapKey); 890 if (mechanism == CKM_INVALID_MECHANISM) { 891 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) 892 : PORT_Strdup(wrapName); 893 PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n", 894 progName, keyName, PK11_GetTokenName(slot)); 895 PORT_Free(keyName); 896 PK11_FreeSymKey(wrapKey); 897 goto shutdown; 898 } 899 900 symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrapKey, mechanism, NULL, 901 &key, keyType, CKA_ENCRYPT, keySize, 0, PR_TRUE); 902 PK11_FreeSymKey(wrapKey); 903 if (!symKey) { 904 PR_fprintf(PR_STDERR, "%s: Unwrap Key Failed\n", progName); 905 goto shutdown; 906 } 907 908 if (symKeyUtil.options[opt_Nickname].activated) { 909 rv = PK11_SetSymKeyNickname(symKey, name); 910 if (rv != SECSuccess) { 911 PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n", 912 progName); 913 PK11_DeleteTokenSymKey(symKey); 914 PK11_FreeSymKey(symKey); 915 goto shutdown; 916 } 917 } 918 rv = SECSuccess; 919 PrintKey(symKey); 920 PK11_FreeSymKey(symKey); 921 } 922 923 #define MAX_KEY_SIZE 4098 924 if (symKeyUtil.commands[cmd_WrapKey].activated) { 925 PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata); 926 PK11SymKey *wrapKey; 927 CK_MECHANISM_TYPE mechanism; 928 SECItem data; 929 unsigned char buf[MAX_KEY_SIZE]; 930 int ret; 931 932 if (!symKey) { 933 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); 934 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", 935 progName, keyName, PK11_GetTokenName(slot)); 936 PORT_Free(keyName); 937 goto shutdown; 938 } 939 940 wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata); 941 if (!wrapKey) { 942 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) 943 : PORT_Strdup(wrapName); 944 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", 945 progName, keyName, PK11_GetTokenName(slot)); 946 PORT_Free(keyName); 947 PK11_FreeSymKey(symKey); 948 goto shutdown; 949 } 950 951 mechanism = GetWrapMechanism(wrapKey); 952 if (mechanism == CKM_INVALID_MECHANISM) { 953 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) 954 : PORT_Strdup(wrapName); 955 PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n", 956 progName, keyName, PK11_GetTokenName(slot)); 957 PORT_Free(keyName); 958 PK11_FreeSymKey(symKey); 959 PK11_FreeSymKey(wrapKey); 960 goto shutdown; 961 } 962 963 data.data = buf; 964 data.len = sizeof(buf); 965 rv = PK11_WrapSymKey(mechanism, NULL, wrapKey, symKey, &data); 966 PK11_FreeSymKey(symKey); 967 PK11_FreeSymKey(wrapKey); 968 if (rv != SECSuccess) { 969 PR_fprintf(PR_STDERR, "%s: Couldn't wrap key\n", progName); 970 goto shutdown; 971 } 972 973 /* WriteBuf outputs it's own error using SECU_PrintError */ 974 ret = WriteBuf(symKeyUtil.options[opt_KeyFile].arg, &data); 975 if (ret < 0) { 976 goto shutdown; 977 } 978 } 979 980 if (symKeyUtil.commands[cmd_ImportKey].activated) { 981 PK11SymKey *symKey = PK11_ImportSymKey(slot, keyType, 982 PK11_OriginUnwrap, CKA_ENCRYPT, &key, &pwdata); 983 if (!symKey) { 984 PR_fprintf(PR_STDERR, "%s: Import Key Failed\n", progName); 985 goto shutdown; 986 } 987 if (symKeyUtil.options[opt_Nickname].activated) { 988 rv = PK11_SetSymKeyNickname(symKey, name); 989 if (rv != SECSuccess) { 990 PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n", 991 progName); 992 PK11_DeleteTokenSymKey(symKey); 993 PK11_FreeSymKey(symKey); 994 goto shutdown; 995 } 996 } 997 rv = SECSuccess; 998 PrintKey(symKey); 999 PK11_FreeSymKey(symKey); 1000 } 1001 1002 /* List certs (-L) */ 1003 if (symKeyUtil.commands[cmd_ListKeys].activated) { 1004 int printLabel = 1; 1005 if (slot) { 1006 rv = ListKeys(slot, &printLabel, &pwdata); 1007 } else { 1008 /* loop over all the slots */ 1009 PK11SlotList *slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 1010 PR_FALSE, PR_FALSE, &pwdata); 1011 if (slotList == NULL) { 1012 PR_fprintf(PR_STDERR, "%s: No tokens found\n", progName); 1013 } else { 1014 PK11SlotListElement *se; 1015 for (se = PK11_GetFirstSafe(slotList); se; 1016 se = PK11_GetNextSafe(slotList, se, PR_FALSE)) { 1017 rv = ListKeys(se->slot, &printLabel, &pwdata); 1018 if (rv != SECSuccess) { 1019 break; 1020 } 1021 } 1022 if (se) { 1023 PORT_CheckSuccess(PK11_FreeSlotListElement(slotList, se)); 1024 } 1025 PK11_FreeSlotList(slotList); 1026 } 1027 } 1028 } 1029 1030 /* Move key (-M) */ 1031 if (symKeyUtil.commands[cmd_MoveKey].activated) { 1032 PK11SlotInfo *target; 1033 char *targetName = symKeyUtil.options[opt_TargetToken].arg; 1034 PK11SymKey *newKey; 1035 PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata); 1036 char *keyName; 1037 1038 if (!symKey) { 1039 keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); 1040 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", 1041 progName, keyName, PK11_GetTokenName(slot)); 1042 PORT_Free(keyName); 1043 goto shutdown; 1044 } 1045 target = PK11_FindSlotByName(targetName); 1046 if (!target) { 1047 PR_fprintf(PR_STDERR, "%s: Couldn't find slot %s\n", 1048 progName, targetName); 1049 goto shutdown; 1050 } 1051 rv = PK11_Authenticate(target, PR_FALSE, &pwdata); 1052 if (rv != SECSuccess) { 1053 PR_fprintf(PR_STDERR, "%s: Failed to log into %s\n", 1054 progName, targetName); 1055 goto shutdown; 1056 } 1057 rv = SECFailure; 1058 newKey = PK11_MoveSymKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey); 1059 if (!newKey) { 1060 PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n", progName); 1061 goto shutdown; 1062 } 1063 keyName = PK11_GetSymKeyNickname(symKey); 1064 if (keyName) { 1065 rv = PK11_SetSymKeyNickname(newKey, keyName); 1066 if (rv != SECSuccess) { 1067 PK11_DeleteTokenSymKey(newKey); 1068 PK11_FreeSymKey(newKey); 1069 PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n", 1070 progName); 1071 goto shutdown; 1072 } 1073 } 1074 PK11_FreeSymKey(newKey); 1075 rv = SECSuccess; 1076 } 1077 1078 shutdown: 1079 if (rv != SECSuccess) { 1080 PR_fprintf(PR_STDERR, "%s: %s\n", progName, 1081 SECU_Strerror(PORT_GetError())); 1082 } 1083 1084 if (key.data) { 1085 PORT_Free(key.data); 1086 } 1087 1088 if (keyID.data) { 1089 PORT_Free(keyID.data); 1090 } 1091 1092 if (slot) { 1093 PK11_FreeSlot(slot); 1094 } 1095 1096 if (NSS_Shutdown() != SECSuccess) { 1097 exit(1); 1098 } 1099 1100 if (rv == SECSuccess) { 1101 return 0; 1102 } else { 1103 return 255; 1104 } 1105 }