nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / cmd / symkeyutil / symkeyutil.c
blob1c1aff6f31954057569407dba4e67e58e44ab1af
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 ** symkeyutil.c
40 ** utility for managing symetric keys in the database or the token
45 * Wish List for this utility:
46 * 1) Display and Set the CKA_ operation flags for the key.
47 * 2) Modify existing keys
48 * 3) Copy keys
49 * 4) Read CKA_ID and display for keys.
50 * 5) Option to store CKA_ID in a file on key creation.
51 * 6) Encrypt, Decrypt, Hash, and Mac with generated keys.
52 * 7) Use asymetric keys to wrap and unwrap keys.
53 * 8) Derive.
54 * 9) PBE keys.
57 #include <stdio.h>
58 #include <string.h>
60 #include "secutil.h"
62 #include "nspr.h"
64 #include "pk11func.h"
65 #include "secasn1.h"
66 #include "cert.h"
67 #include "cryptohi.h"
68 #include "secoid.h"
69 #include "certdb.h"
70 #include "nss.h"
72 typedef struct _KeyTypes {
73 CK_KEY_TYPE keyType;
74 CK_MECHANISM_TYPE mechType;
75 CK_MECHANISM_TYPE wrapMech;
76 char *label;
77 } KeyTypes;
79 static KeyTypes keyArray[] = {
80 #ifdef RECOGNIZE_ASYMETRIC_TYPES
81 { CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, "rsa" },
82 { CKK_DSA, CKM_DSA, CKM_INVALID_MECHANISM, "dsa" },
83 { CKK_DH, CKM_DH_PKCS_DERIVE, CKM_INVALID_MECHANISM, "dh" },
84 { CKK_EC, CKM_ECDSA, CKM_INVALID_MECHANISM, "ec" },
85 { CKK_X9_42_DH, CKM_X9_42_DH_DERIVE, CKM_INVALID_MECHANISM, "x9.42dh" },
86 { CKK_KEA, CKM_KEA_KEY_DERIVE, CKM_INVALID_MECHANISM, "kea" },
87 #endif
88 { CKK_GENERIC_SECRET, CKM_SHA_1_HMAC, CKM_INVALID_MECHANISM, "generic" },
89 { CKK_RC2, CKM_RC2_CBC, CKM_RC2_ECB,"rc2" },
90 /* don't define a wrap mech for RC-4 since it's note really safe */
91 { CKK_RC4, CKM_RC4, CKM_INVALID_MECHANISM, "rc4" },
92 { CKK_DES, CKM_DES_CBC, CKM_DES_ECB,"des" },
93 { CKK_DES2, CKM_DES2_KEY_GEN, CKM_DES3_ECB, "des2" },
94 { CKK_DES3, CKM_DES3_KEY_GEN, CKM_DES3_ECB, "des3" },
95 { CKK_CAST, CKM_CAST_CBC, CKM_CAST_ECB, "cast" },
96 { CKK_CAST3, CKM_CAST3_CBC, CKM_CAST3_ECB, "cast3" },
97 { CKK_CAST5, CKM_CAST5_CBC, CKM_CAST5_ECB, "cast5" },
98 { CKK_CAST128, CKM_CAST128_CBC, CKM_CAST128_ECB, "cast128" },
99 { CKK_RC5, CKM_RC5_CBC, CKM_RC5_ECB, "rc5" },
100 { CKK_IDEA, CKM_IDEA_CBC, CKM_IDEA_ECB, "idea" },
101 { CKK_SKIPJACK, CKM_SKIPJACK_CBC64, CKM_SKIPJACK_WRAP, "skipjack" },
102 { CKK_BATON, CKM_BATON_CBC128, CKM_BATON_WRAP, "baton" },
103 { CKK_JUNIPER, CKM_JUNIPER_CBC128, CKM_JUNIPER_WRAP, "juniper" },
104 { CKK_CDMF, CKM_CDMF_CBC, CKM_CDMF_ECB, "cdmf" },
105 { CKK_AES, CKM_AES_CBC, CKM_AES_ECB, "aes" },
106 { CKK_CAMELLIA, CKM_CAMELLIA_CBC, CKM_CAMELLIA_ECB, "camellia" },
109 static int keyArraySize = sizeof(keyArray)/sizeof(keyArray[0]);
112 GetLen(PRFileDesc* fd)
114 PRFileInfo info;
116 if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info)) {
117 return -1;
120 return info.size;
124 ReadBuf(char *inFile, SECItem *item)
126 int len;
127 int ret;
128 PRFileDesc* fd = PR_Open(inFile, PR_RDONLY, 0);
129 if (NULL == fd) {
130 SECU_PrintError("symkeyutil", "PR_Open failed");
131 return -1;
134 len = GetLen(fd);
135 if (len < 0) {
136 SECU_PrintError("symkeyutil", "PR_GetOpenFileInfo failed");
137 return -1;
139 item->data = (unsigned char *)PORT_Alloc(len);
140 if (item->data == NULL) {
141 fprintf(stderr,"Failed to allocate %d to read file %s\n",len,inFile);
142 return -1;
145 ret = PR_Read(fd,item->data,item->len);
146 if (ret < 0) {
147 SECU_PrintError("symkeyutil", "PR_Read failed");
148 PORT_Free(item->data);
149 item->data = NULL;
150 return -1;
152 PR_Close(fd);
153 item->len = len;
154 return 0;
158 WriteBuf(char *inFile, SECItem *item)
160 int ret;
161 PRFileDesc* fd = PR_Open(inFile, PR_WRONLY|PR_CREATE_FILE, 0x200);
162 if (NULL == fd) {
163 SECU_PrintError("symkeyutil", "PR_Open failed");
164 return -1;
167 ret = PR_Write(fd,item->data,item->len);
168 if (ret < 0) {
169 SECU_PrintError("symkeyutil", "PR_Write failed");
170 return -1;
172 PR_Close(fd);
173 return 0;
176 CK_KEY_TYPE
177 GetKeyTypeFromString(const char *keyString)
179 int i;
180 for (i=0; i < keyArraySize; i++) {
181 if (PL_strcasecmp(keyString,keyArray[i].label) == 0) {
182 return keyArray[i].keyType;
185 return (CK_KEY_TYPE)-1;
188 CK_MECHANISM_TYPE
189 GetKeyMechFromString(const char *keyString)
191 int i;
192 for (i=0; i < keyArraySize; i++) {
193 if (PL_strcasecmp(keyString,keyArray[i].label) == 0) {
194 return keyArray[i].mechType;
197 return (CK_MECHANISM_TYPE)-1;
200 const char *
201 GetStringFromKeyType(CK_KEY_TYPE type)
203 int i;
204 for (i=0; i < keyArraySize; i++) {
205 if (keyArray[i].keyType == type) {
206 return keyArray[i].label;
209 return "unmatched";
212 CK_MECHANISM_TYPE
213 GetWrapFromKeyType(CK_KEY_TYPE type)
215 int i;
216 for (i=0; i < keyArraySize; i++) {
217 if (keyArray[i].keyType == type) {
218 return keyArray[i].wrapMech;
221 return CKM_INVALID_MECHANISM;
224 CK_MECHANISM_TYPE
225 GetWrapMechanism(PK11SymKey *symKey)
227 CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
229 return GetWrapFromKeyType(type);
233 GetDigit(char c)
235 if (c == 0) {
236 return -1;
238 if (c <= '9' && c >= '0') {
239 return c - '0';
241 if (c <= 'f' && c >= 'a') {
242 return c - 'a' + 0xa;
244 if (c <= 'F' && c >= 'A') {
245 return c - 'A' + 0xa;
247 return -1;
250 char
251 ToDigit(unsigned char c)
253 c = c & 0xf;
254 if (c <= 9) {
255 return (char) (c+'0');
257 return (char) (c+'a'-0xa);
260 char *
261 BufToHex(SECItem *outbuf)
263 int len = outbuf->len * 2 +1;
264 char *string, *ptr;
265 unsigned int i;
267 string = PORT_Alloc(len);
269 ptr = string;
270 for (i=0; i < outbuf->len; i++) {
271 *ptr++ = ToDigit(outbuf->data[i] >> 4);
272 *ptr++ = ToDigit(outbuf->data[i] & 0xf);
274 *ptr = 0;
275 return string;
280 HexToBuf(char *inString, SECItem *outbuf)
282 int len = strlen(inString);
283 int outlen = len+1/2;
284 int trueLen = 0;
286 outbuf->data = PORT_Alloc(outlen);
287 if (outbuf->data) {
288 return -1;
291 while (*inString) {
292 int digit1, digit2;
293 digit1 = GetDigit(*inString++);
294 digit2 = GetDigit(*inString++);
295 if ((digit1 == -1) || (digit2 == -1)) {
296 PORT_Free(outbuf->data);
297 outbuf->data = NULL;
298 return -1;
300 outbuf->data[trueLen++] = digit1 << 4 | digit2;
302 outbuf->len = trueLen;
303 return 0;
306 void
307 printBuf(unsigned char *data, int len)
309 int i;
311 for (i=0; i < len; i++) {
312 printf("%02x",data[i]);
316 void
317 PrintKey(PK11SymKey *symKey)
319 char *name = PK11_GetSymKeyNickname(symKey);
320 int len = PK11_GetKeyLength(symKey);
321 int strength = PK11_GetKeyStrength(symKey, NULL);
322 SECItem *value = NULL;
323 CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
324 (void) PK11_ExtractKeyValue(symKey);
326 value = PK11_GetKeyData(symKey);
328 printf("%-20s %3d %4d %10s ", name ? name: " ", len, strength,
329 GetStringFromKeyType(type));
330 if (value && value->data) {
331 printBuf(value->data, value->len);
332 } else {
333 printf("<restricted>");
335 printf("\n");
338 SECStatus
339 ListKeys(PK11SlotInfo *slot, int *printLabel, void *pwd) {
340 PK11SymKey *keyList;
341 SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
342 if (rv != SECSuccess) {
343 return rv;;
346 keyList = PK11_ListFixedKeysInSlot(slot, NULL, pwd);
347 if (keyList) {
348 if (*printLabel) {
349 printf(" Name Len Strength Type Data\n");
350 *printLabel = 0;
352 printf("%s:\n",PK11_GetTokenName(slot));
354 while (keyList) {
355 PK11SymKey *freeKey = keyList;
356 PrintKey(keyList);
357 keyList = PK11_GetNextSymKey(keyList);
358 PK11_FreeSymKey(freeKey);
360 return SECSuccess;
363 PK11SymKey *
364 FindKey(PK11SlotInfo *slot, char *name, SECItem *id, void *pwd)
366 PK11SymKey *key = NULL;
367 SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
369 if (rv != SECSuccess) {
370 return NULL;
374 if (id->data) {
375 key = PK11_FindFixedKey(slot,CKM_INVALID_MECHANISM, id, pwd);
377 if (name && !key) {
378 key = PK11_ListFixedKeysInSlot(slot,name, pwd);
381 if (key) {
382 printf("Found a key\n");
383 PrintKey(key);
385 return key;
388 PRBool
389 IsKeyList(PK11SymKey *symKey)
391 return (PRBool) (PK11_GetNextSymKey(symKey) != NULL);
394 void
395 FreeKeyList(PK11SymKey *symKey)
397 PK11SymKey *next,*current;
399 for (current = symKey; current; current = next) {
400 next = PK11_GetNextSymKey(current);
401 PK11_FreeSymKey(current);
403 return;
406 static void
407 Usage(char *progName)
409 #define FPS fprintf(stderr,
410 FPS "Type %s -H for more detailed descriptions\n", progName);
411 FPS "Usage:");
412 FPS "\t%s -L [std_opts] [-r]\n", progName);
413 FPS "\t%s -K [-n name] -t type [-s size] [-i id |-j id_file] [std_opts]\n", progName);
414 FPS "\t%s -D <[-n name | -i id | -j id_file> [std_opts]\n", progName);
415 FPS "\t%s -I [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]\n", progName);
416 FPS "\t%s -E <-nname | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]\n", progName);
417 FPS "\t%s -U [-n name] [-t type] [-i id | -j id_file] -k data_file <wrap_opts> [std_opts]\n", progName);
418 FPS "\t%s -W <-n name | -i id | -j id_file> [-t type] -k data_file [-r] <wrap_opts> [std_opts]\n", progName);
419 FPS "\t%s -M <-n name | -i id | -j id_file> -g target_token [std_opts]\n", progName);
420 FPS "\t\t std_opts -> [-d certdir] [-P dbprefix] [-p password] [-f passwordFile] [-h token]\n");
421 FPS "\t\t wrap_opts -> <-w wrap_name | -x wrap_id | -y id_file>\n");
422 exit(1);
425 static void LongUsage(char *progName)
427 int i;
428 FPS "%-15s List all the keys.\n", "-L");
429 FPS "%-15s Generate a new key.\n", "-K");
430 FPS "%-20s Specify the nickname of the new key\n",
431 " -n name");
432 FPS "%-20s Specify the id in hex of the new key\n",
433 " -i key id");
434 FPS "%-20s Specify a file to read the id of the new key\n",
435 " -j key id file");
436 FPS "%-20s Specify the keyType of the new key\n",
437 " -t type");
438 FPS "%-20s", " valid types: ");
439 for (i=0; i < keyArraySize ; i++) {
440 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
442 FPS "%-20s Specify the size of the new key in bytes (required by some types)\n",
443 " -s size");
444 FPS "%-15s Delete a key.\n", "-D");
445 FPS "%-20s Specify the nickname of the key to delete\n",
446 " -n name");
447 FPS "%-20s Specify the id in hex of the key to delete\n",
448 " -i key id");
449 FPS "%-20s Specify a file to read the id of the key to delete\n",
450 " -j key id file");
451 FPS "%-15s Import a new key from a data file.\n", "-I");
452 FPS "%-20s Specify the data file to read the key from.\n",
453 " -k key file");
454 FPS "%-20s Specify the nickname of the new key\n",
455 " -n name");
456 FPS "%-20s Specify the id in hex of the new key\n",
457 " -i key id");
458 FPS "%-20s Specify a file to read the id of the new key\n",
459 " -j key id file");
460 FPS "%-20s Specify the keyType of the new key\n",
461 " -t type");
462 FPS "%-20s", " valid types: ");
463 for (i=0; i < keyArraySize ; i++) {
464 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
466 FPS "%-15s Export a key to a data file.\n", "-E");
467 FPS "%-20s Specify the data file to write the key to.\n",
468 " -k key file");
469 FPS "%-20s Specify the nickname of the key to export\n",
470 " -n name");
471 FPS "%-20s Specify the id in hex of the key to export\n",
472 " -i key id");
473 FPS "%-20s Specify a file to read the id of the key to export\n",
474 " -j key id file");
475 FPS "%-15s Move a key to a new token.\n", "-M");
476 FPS "%-20s Specify the nickname of the key to move\n",
477 " -n name");
478 FPS "%-20s Specify the id in hex of the key to move\n",
479 " -i key id");
480 FPS "%-20s Specify a file to read the id of the key to move\n",
481 " -j key id file");
482 FPS "%-20s Specify the token to move the key to\n",
483 " -g target token");
484 FPS "%-15s Unwrap a new key from a data file.\n", "-U");
485 FPS "%-20s Specify the data file to read the encrypted key from.\n",
486 " -k key file");
487 FPS "%-20s Specify the nickname of the new key\n",
488 " -n name");
489 FPS "%-20s Specify the id in hex of the new key\n",
490 " -i key id");
491 FPS "%-20s Specify a file to read the id of the new key\n",
492 " -j key id file");
493 FPS "%-20s Specify the keyType of the new key\n",
494 " -t type");
495 FPS "%-20s", " valid types: ");
496 for (i=0; i < keyArraySize ; i++) {
497 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
499 FPS "%-20s Specify the nickname of the wrapping key\n",
500 " -w wrap name");
501 FPS "%-20s Specify the id in hex of the wrapping key\n",
502 " -x wrap key id");
503 FPS "%-20s Specify a file to read the id of the wrapping key\n",
504 " -y wrap key id file");
505 FPS "%-15s Wrap a new key to a data file. [not yet implemented]\n", "-W");
506 FPS "%-20s Specify the data file to write the encrypted key to.\n",
507 " -k key file");
508 FPS "%-20s Specify the nickname of the key to wrap\n",
509 " -n name");
510 FPS "%-20s Specify the id in hex of the key to wrap\n",
511 " -i key id");
512 FPS "%-20s Specify a file to read the id of the key to wrap\n",
513 " -j key id file");
514 FPS "%-20s Specify the nickname of the wrapping key\n",
515 " -w wrap name");
516 FPS "%-20s Specify the id in hex of the wrapping key\n",
517 " -x wrap key id");
518 FPS "%-20s Specify a file to read the id of the wrapping key\n",
519 " -y wrap key id file");
520 FPS "%-15s Options valid for all commands\n", "std_opts");
521 FPS "%-20s The directory where the NSS db's reside\n",
522 " -d certdir");
523 FPS "%-20s Prefix for the NSS db's\n",
524 " -P db prefix");
525 FPS "%-20s Specify password on the command line\n",
526 " -p password");
527 FPS "%-20s Specify password file on the command line\n",
528 " -f password file");
529 FPS "%-20s Specify token to act on\n",
530 " -h token");
531 exit(1);
532 #undef FPS
535 /* Certutil commands */
536 enum {
537 cmd_CreateNewKey = 0,
538 cmd_DeleteKey,
539 cmd_ImportKey,
540 cmd_ExportKey,
541 cmd_WrapKey,
542 cmd_UnwrapKey,
543 cmd_MoveKey,
544 cmd_ListKeys,
545 cmd_PrintHelp
548 /* Certutil options */
549 enum {
550 opt_CertDir = 0,
551 opt_PasswordFile,
552 opt_TargetToken,
553 opt_TokenName,
554 opt_KeyID,
555 opt_KeyIDFile,
556 opt_KeyType,
557 opt_Nickname,
558 opt_KeyFile,
559 opt_Password,
560 opt_dbPrefix,
561 opt_RW,
562 opt_KeySize,
563 opt_WrapKeyName,
564 opt_WrapKeyID,
565 opt_WrapKeyIDFile,
566 opt_NoiseFile
569 static secuCommandFlag symKeyUtil_commands[] =
571 { /* cmd_CreateNewKey */ 'K', PR_FALSE, 0, PR_FALSE },
572 { /* cmd_DeleteKey */ 'D', PR_FALSE, 0, PR_FALSE },
573 { /* cmd_ImportKey */ 'I', PR_FALSE, 0, PR_FALSE },
574 { /* cmd_ExportKey */ 'E', PR_FALSE, 0, PR_FALSE },
575 { /* cmd_WrapKey */ 'W', PR_FALSE, 0, PR_FALSE },
576 { /* cmd_UnwrapKey */ 'U', PR_FALSE, 0, PR_FALSE },
577 { /* cmd_MoveKey */ 'M', PR_FALSE, 0, PR_FALSE },
578 { /* cmd_ListKeys */ 'L', PR_FALSE, 0, PR_FALSE },
579 { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE },
582 static secuCommandFlag symKeyUtil_options[] =
584 { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
585 { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE },
586 { /* opt_TargetToken */ 'g', PR_TRUE, 0, PR_FALSE },
587 { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
588 { /* opt_KeyID */ 'i', PR_TRUE, 0, PR_FALSE },
589 { /* opt_KeyIDFile */ 'j', PR_TRUE, 0, PR_FALSE },
590 { /* opt_KeyType */ 't', PR_TRUE, 0, PR_FALSE },
591 { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
592 { /* opt_KeyFile */ 'k', PR_TRUE, 0, PR_FALSE },
593 { /* opt_Password */ 'p', PR_TRUE, 0, PR_FALSE },
594 { /* opt_dbPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
595 { /* opt_RW */ 'r', PR_FALSE, 0, PR_FALSE },
596 { /* opt_KeySize */ 's', PR_TRUE, 0, PR_FALSE },
597 { /* opt_WrapKeyName */ 'w', PR_TRUE, 0, PR_FALSE },
598 { /* opt_WrapKeyID */ 'x', PR_TRUE, 0, PR_FALSE },
599 { /* opt_WrapKeyIDFile */ 'y', PR_TRUE, 0, PR_FALSE },
600 { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE },
603 int
604 main(int argc, char **argv)
606 PK11SlotInfo *slot = NULL;
607 char * slotname = "internal";
608 char * certPrefix = "";
609 CK_MECHANISM_TYPE keyType = CKM_SHA_1_HMAC;
610 int keySize = 0;
611 char * name = NULL;
612 char * wrapName = NULL;
613 secuPWData pwdata = { PW_NONE, 0 };
614 PRBool readOnly = PR_FALSE;
615 SECItem key;
616 SECItem keyID;
617 SECItem wrapKeyID;
618 int commandsEntered = 0;
619 int commandToRun = 0;
620 char *progName;
621 int i;
622 SECStatus rv = SECFailure;
624 secuCommand symKeyUtil;
625 symKeyUtil.numCommands=sizeof(symKeyUtil_commands)/sizeof(secuCommandFlag);
626 symKeyUtil.numOptions=sizeof(symKeyUtil_options)/sizeof(secuCommandFlag);
627 symKeyUtil.commands = symKeyUtil_commands;
628 symKeyUtil.options = symKeyUtil_options;
630 key.data = NULL; key.len = 0;
631 keyID.data = NULL; keyID.len = 0;
632 wrapKeyID.data = NULL; wrapKeyID.len = 0;
634 progName = strrchr(argv[0], '/');
635 progName = progName ? progName+1 : argv[0];
637 rv = SECU_ParseCommandLine(argc, argv, progName, &symKeyUtil);
639 if (rv != SECSuccess)
640 Usage(progName);
642 rv = SECFailure;
644 /* -H print help */
645 if (symKeyUtil.commands[cmd_PrintHelp].activated)
646 LongUsage(progName);
648 /* -f password file, -p password */
649 if (symKeyUtil.options[opt_PasswordFile].arg) {
650 pwdata.source = PW_FROMFILE;
651 pwdata.data = symKeyUtil.options[opt_PasswordFile].arg;
652 } else if (symKeyUtil.options[opt_Password].arg) {
653 pwdata.source = PW_PLAINTEXT;
654 pwdata.data = symKeyUtil.options[opt_Password].arg;
657 /* -d directory */
658 if (symKeyUtil.options[opt_CertDir].activated)
659 SECU_ConfigDirectory(symKeyUtil.options[opt_CertDir].arg);
661 /* -s key size */
662 if (symKeyUtil.options[opt_KeySize].activated) {
663 keySize = PORT_Atoi(symKeyUtil.options[opt_KeySize].arg);
666 /* -h specify token name */
667 if (symKeyUtil.options[opt_TokenName].activated) {
668 if (PL_strcmp(symKeyUtil.options[opt_TokenName].arg, "all") == 0)
669 slotname = NULL;
670 else
671 slotname = PL_strdup(symKeyUtil.options[opt_TokenName].arg);
674 /* -t key type */
675 if (symKeyUtil.options[opt_KeyType].activated) {
676 keyType = GetKeyMechFromString(symKeyUtil.options[opt_KeyType].arg);
677 if (keyType == (CK_MECHANISM_TYPE)-1) {
678 PR_fprintf(PR_STDERR,
679 "%s unknown key type (%s).\n",
680 progName, symKeyUtil.options[opt_KeyType].arg);
681 return 255;
685 /* -k for import and unwrap, it specifies an input file to read from,
686 * for export and wrap it specifies an output file to write to */
687 if (symKeyUtil.options[opt_KeyFile].activated) {
688 if (symKeyUtil.commands[cmd_ImportKey].activated ||
689 symKeyUtil.commands[cmd_UnwrapKey].activated ) {
690 int ret = ReadBuf(symKeyUtil.options[opt_KeyFile].arg, &key);
691 if (ret < 0) {
692 PR_fprintf(PR_STDERR,
693 "%s Couldn't read key file (%s).\n",
694 progName, symKeyUtil.options[opt_KeyFile].arg);
695 return 255;
700 /* -i specify the key ID */
701 if (symKeyUtil.options[opt_KeyID].activated) {
702 int ret = HexToBuf(symKeyUtil.options[opt_KeyID].arg, &keyID);
703 if (ret < 0) {
704 PR_fprintf(PR_STDERR,
705 "%s invalid key ID (%s).\n",
706 progName, symKeyUtil.options[opt_KeyID].arg);
707 return 255;
711 /* -i & -j are mutually exclusive */
712 if ((symKeyUtil.options[opt_KeyID].activated) &&
713 (symKeyUtil.options[opt_KeyIDFile].activated)) {
714 PR_fprintf(PR_STDERR,
715 "%s -i and -j options are mutually exclusive.\n", progName);
716 return 255;
719 /* -x specify the Wrap key ID */
720 if (symKeyUtil.options[opt_WrapKeyID].activated) {
721 int ret = HexToBuf(symKeyUtil.options[opt_WrapKeyID].arg, &wrapKeyID);
722 if (ret < 0) {
723 PR_fprintf(PR_STDERR,
724 "%s invalid key ID (%s).\n",
725 progName, symKeyUtil.options[opt_WrapKeyID].arg);
726 return 255;
730 /* -x & -y are mutually exclusive */
731 if ((symKeyUtil.options[opt_KeyID].activated) &&
732 (symKeyUtil.options[opt_KeyIDFile].activated)) {
733 PR_fprintf(PR_STDERR,
734 "%s -i and -j options are mutually exclusive.\n", progName);
735 return 255;
739 /* -y specify the key ID */
740 if (symKeyUtil.options[opt_WrapKeyIDFile].activated) {
741 int ret = ReadBuf(symKeyUtil.options[opt_WrapKeyIDFile].arg,
742 &wrapKeyID);
743 if (ret < 0) {
744 PR_fprintf(PR_STDERR,
745 "%s Couldn't read key ID file (%s).\n",
746 progName, symKeyUtil.options[opt_WrapKeyIDFile].arg);
747 return 255;
751 /* -P certdb name prefix */
752 if (symKeyUtil.options[opt_dbPrefix].activated)
753 certPrefix = strdup(symKeyUtil.options[opt_dbPrefix].arg);
755 /* Check number of commands entered. */
756 commandsEntered = 0;
757 for (i=0; i< symKeyUtil.numCommands; i++) {
758 if (symKeyUtil.commands[i].activated) {
759 commandToRun = symKeyUtil.commands[i].flag;
760 commandsEntered++;
762 if (commandsEntered > 1)
763 break;
765 if (commandsEntered > 1) {
766 PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
767 PR_fprintf(PR_STDERR, "You entered: ");
768 for (i=0; i< symKeyUtil.numCommands; i++) {
769 if (symKeyUtil.commands[i].activated)
770 PR_fprintf(PR_STDERR, " -%c", symKeyUtil.commands[i].flag);
772 PR_fprintf(PR_STDERR, "\n");
773 return 255;
775 if (commandsEntered == 0) {
776 PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName);
777 Usage(progName);
780 if (symKeyUtil.commands[cmd_ListKeys].activated ||
781 symKeyUtil.commands[cmd_PrintHelp].activated ||
782 symKeyUtil.commands[cmd_ExportKey].activated ||
783 symKeyUtil.commands[cmd_WrapKey].activated) {
784 readOnly = !symKeyUtil.options[opt_RW].activated;
787 if ((symKeyUtil.commands[cmd_ImportKey].activated ||
788 symKeyUtil.commands[cmd_ExportKey].activated ||
789 symKeyUtil.commands[cmd_WrapKey].activated ||
790 symKeyUtil.commands[cmd_UnwrapKey].activated ) &&
791 !symKeyUtil.options[opt_KeyFile].activated) {
792 PR_fprintf(PR_STDERR,
793 "%s -%c: keyfile is required for this command (-k).\n",
794 progName, commandToRun);
795 return 255;
798 /* -E, -D, -W, and all require -n, -i, or -j to identify the key */
799 if ((symKeyUtil.commands[cmd_ExportKey].activated ||
800 symKeyUtil.commands[cmd_DeleteKey].activated ||
801 symKeyUtil.commands[cmd_WrapKey].activated) &&
802 !(symKeyUtil.options[opt_Nickname].activated ||
803 symKeyUtil.options[opt_KeyID].activated ||
804 symKeyUtil.options[opt_KeyIDFile].activated)) {
805 PR_fprintf(PR_STDERR,
806 "%s -%c: nickname or id is required for this command (-n, -i, -j).\n",
807 progName, commandToRun);
808 return 255;
811 /* -W, -U, and all -w, -x, or -y to identify the wrapping key */
812 if (( symKeyUtil.commands[cmd_WrapKey].activated ||
813 symKeyUtil.commands[cmd_UnwrapKey].activated) &&
814 !(symKeyUtil.options[opt_WrapKeyName].activated ||
815 symKeyUtil.options[opt_WrapKeyID].activated ||
816 symKeyUtil.options[opt_WrapKeyIDFile].activated)) {
817 PR_fprintf(PR_STDERR,
818 "%s -%c: wrap key is required for this command (-w, -x, or -y).\n",
819 progName, commandToRun);
820 return 255;
823 /* -M needs the target slot (-g) */
824 if (symKeyUtil.commands[cmd_MoveKey].activated &&
825 !symKeyUtil.options[opt_TargetToken].activated) {
826 PR_fprintf(PR_STDERR,
827 "%s -%c: target token is required for this command (-g).\n",
828 progName, commandToRun);
829 return 255;
832 /* Using slotname == NULL for listing keys and certs on all slots,
833 * but only that. */
834 if (!(symKeyUtil.commands[cmd_ListKeys].activated) && slotname == NULL) {
835 PR_fprintf(PR_STDERR,
836 "%s -%c: cannot use \"-h all\" for this command.\n",
837 progName, commandToRun);
838 return 255;
841 name = SECU_GetOptionArg(&symKeyUtil, opt_Nickname);
842 wrapName = SECU_GetOptionArg(&symKeyUtil, opt_WrapKeyName);
844 PK11_SetPasswordFunc(SECU_GetModulePassword);
846 /* Initialize NSPR and NSS. */
847 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
848 rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix,
849 "secmod.db", readOnly ? NSS_INIT_READONLY: 0);
850 if (rv != SECSuccess) {
851 SECU_PrintPRandOSError(progName);
852 goto shutdown;
854 rv = SECFailure;
856 if (PL_strcmp(slotname, "internal") == 0)
857 slot = PK11_GetInternalKeySlot();
858 else if (slotname != NULL)
859 slot = PK11_FindSlotByName(slotname);
861 /* generating a new key */
862 if (symKeyUtil.commands[cmd_CreateNewKey].activated) {
863 PK11SymKey *symKey;
865 symKey = PK11_TokenKeyGen(slot, keyType, NULL, keySize,
866 NULL, PR_TRUE, &pwdata);
867 if (!symKey) {
868 PR_fprintf(PR_STDERR, "%s: Token Key Gen Failed\n", progName);
869 goto shutdown;
871 if (symKeyUtil.options[opt_Nickname].activated) {
872 rv = PK11_SetSymKeyNickname(symKey, name);
873 if (rv != SECSuccess) {
874 PK11_DeleteTokenSymKey(symKey);
875 PK11_FreeSymKey(symKey);
876 PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n",
877 progName);
878 goto shutdown;
881 rv = SECSuccess;
882 PrintKey(symKey);
883 PK11_FreeSymKey(symKey);
885 if (symKeyUtil.commands[cmd_DeleteKey].activated) {
886 PK11SymKey *symKey = FindKey(slot,name,&keyID,&pwdata);
888 if (!symKey) {
889 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
890 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
891 progName, keyName, PK11_GetTokenName(slot));
892 PORT_Free(keyName);
893 goto shutdown;
896 rv = PK11_DeleteTokenSymKey(symKey);
897 FreeKeyList(symKey);
898 if (rv != SECSuccess) {
899 PR_fprintf(PR_STDERR, "%s: Couldn't Delete Key \n", progName);
900 goto shutdown;
903 if (symKeyUtil.commands[cmd_UnwrapKey].activated) {
904 PK11SymKey *wrapKey = FindKey(slot,wrapName,&wrapKeyID,&pwdata);
905 PK11SymKey *symKey;
906 CK_MECHANISM_TYPE mechanism;
908 if (!wrapKey) {
909 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
910 : PORT_Strdup(wrapName);
911 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
912 progName, keyName, PK11_GetTokenName(slot));
913 PORT_Free(keyName);
914 goto shutdown;
916 mechanism = GetWrapMechanism(wrapKey);
917 if (mechanism == CKM_INVALID_MECHANISM) {
918 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
919 : PORT_Strdup(wrapName);
920 PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n",
921 progName, keyName, PK11_GetTokenName(slot));
922 PORT_Free(keyName);
923 PK11_FreeSymKey(wrapKey);
924 goto shutdown;
927 symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrapKey, mechanism, NULL,
928 &key, keyType, CKA_ENCRYPT, keySize, 0, PR_TRUE);
929 PK11_FreeSymKey(wrapKey);
930 if (!symKey) {
931 PR_fprintf(PR_STDERR, "%s: Unwrap Key Failed\n", progName);
932 goto shutdown;
935 if (symKeyUtil.options[opt_Nickname].activated) {
936 rv = PK11_SetSymKeyNickname(symKey, name);
937 if (rv != SECSuccess) {
938 PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n",
939 progName);
940 PK11_DeleteTokenSymKey(symKey);
941 PK11_FreeSymKey(symKey);
942 goto shutdown;
945 rv = SECSuccess;
946 PrintKey(symKey);
947 PK11_FreeSymKey(symKey);
950 #define MAX_KEY_SIZE 4098
951 if (symKeyUtil.commands[cmd_WrapKey].activated) {
952 PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata);
953 PK11SymKey *wrapKey;
954 CK_MECHANISM_TYPE mechanism;
955 SECItem data;
956 unsigned char buf[MAX_KEY_SIZE];
957 int ret;
959 if (!symKey) {
960 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
961 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
962 progName, keyName, PK11_GetTokenName(slot));
963 PORT_Free(keyName);
964 goto shutdown;
967 wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata);
968 if (!wrapKey) {
969 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
970 : PORT_Strdup(wrapName);
971 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
972 progName, keyName, PK11_GetTokenName(slot));
973 PORT_Free(keyName);
974 PK11_FreeSymKey(symKey);
975 goto shutdown;
978 mechanism = GetWrapMechanism(wrapKey);
979 if (mechanism == CKM_INVALID_MECHANISM) {
980 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
981 : PORT_Strdup(wrapName);
982 PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n",
983 progName, keyName, PK11_GetTokenName(slot));
984 PORT_Free(keyName);
985 PK11_FreeSymKey(symKey);
986 PK11_FreeSymKey(wrapKey);
987 goto shutdown;
990 data.data = buf;
991 data.len = sizeof(buf);
992 rv = PK11_WrapSymKey(mechanism, NULL, wrapKey, symKey, &data);
993 PK11_FreeSymKey(symKey);
994 PK11_FreeSymKey(wrapKey);
995 if (rv != SECSuccess) {
996 PR_fprintf(PR_STDERR, "%s: Couldn't wrap key\n",progName);
997 goto shutdown;
1000 /* WriteBuf outputs it's own error using SECU_PrintError */
1001 ret = WriteBuf(symKeyUtil.options[opt_KeyFile].arg, &data);
1002 if (ret < 0) {
1003 goto shutdown;
1007 if (symKeyUtil.commands[cmd_ImportKey].activated) {
1008 PK11SymKey *symKey = PK11_ImportSymKey(slot, keyType,
1009 PK11_OriginUnwrap, CKA_ENCRYPT, &key,&pwdata);
1010 if (!symKey) {
1011 PR_fprintf(PR_STDERR, "%s: Import Key Failed\n", progName);
1012 goto shutdown;
1014 if (symKeyUtil.options[opt_Nickname].activated) {
1015 rv = PK11_SetSymKeyNickname(symKey, name);
1016 if (rv != SECSuccess) {
1017 PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n",
1018 progName);
1019 PK11_DeleteTokenSymKey(symKey);
1020 PK11_FreeSymKey(symKey);
1021 goto shutdown;
1024 rv = SECSuccess;
1025 PrintKey(symKey);
1026 PK11_FreeSymKey(symKey);
1029 /* List certs (-L) */
1030 if (symKeyUtil.commands[cmd_ListKeys].activated) {
1031 int printLabel = 1;
1032 if (slot) {
1033 rv = ListKeys(slot,&printLabel,&pwdata);
1034 } else {
1035 /* loop over all the slots */
1036 PK11SlotList *slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
1037 PR_FALSE, PR_FALSE, &pwdata);
1038 PK11SlotListElement *se;
1040 if (slotList == NULL) {
1041 PR_fprintf(PR_STDERR, "%s: No tokens found\n",progName);
1043 for (se = PK11_GetFirstSafe(slotList); se;
1044 se=PK11_GetNextSafe(slotList,se, PR_FALSE)) {
1045 rv = ListKeys(se->slot,&printLabel,&pwdata);
1046 if (rv !=SECSuccess) {
1047 break;
1053 /* Move key (-M) */
1054 if (symKeyUtil.commands[cmd_MoveKey].activated) {
1055 PK11SlotInfo *target;
1056 char *targetName = symKeyUtil.options[opt_TargetToken].arg;
1057 PK11SymKey *newKey;
1058 PK11SymKey *symKey = FindKey(slot,name,&keyID,&pwdata);
1059 char *keyName = PK11_GetSymKeyNickname(symKey);
1061 if (!symKey) {
1062 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
1063 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
1064 progName, keyName, PK11_GetTokenName(slot));
1065 PORT_Free(keyName);
1066 goto shutdown;
1068 target = PK11_FindSlotByName(targetName);
1069 if (!target) {
1070 PR_fprintf(PR_STDERR, "%s: Couldn't find slot %s\n",
1071 progName, targetName);
1072 goto shutdown;
1074 rv = PK11_Authenticate(target, PR_FALSE, &pwdata);
1075 if (rv != SECSuccess) {
1076 PR_fprintf(PR_STDERR, "%s: Failed to log into %s\n",
1077 progName, targetName);
1078 goto shutdown;
1080 rv = SECFailure;
1081 newKey = PK11_MoveSymKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey);
1082 if (!newKey) {
1083 PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n",progName);
1084 goto shutdown;
1086 if (keyName) {
1087 rv = PK11_SetSymKeyNickname(newKey, keyName);
1088 if (rv != SECSuccess) {
1089 PK11_DeleteTokenSymKey(newKey);
1090 PK11_FreeSymKey(newKey);
1091 PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n",
1092 progName);
1093 goto shutdown;
1096 PK11_FreeSymKey(newKey);
1097 rv = SECSuccess;
1100 shutdown:
1101 if (rv != SECSuccess) {
1102 PR_fprintf(PR_STDERR, "%s: %s\n", progName,
1103 SECU_Strerror(PORT_GetError()));
1106 if (key.data) {
1107 PORT_Free(key.data);
1110 if (keyID.data) {
1111 PORT_Free(keyID.data);
1114 if (slot) {
1115 PK11_FreeSlot(slot);
1118 if (NSS_Shutdown() != SECSuccess) {
1119 exit(1);
1122 if (rv == SECSuccess) {
1123 return 0;
1124 } else {
1125 return 255;