Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
5 /*
6 ** symkeyutil.c
7 **
8 ** utility for managing symetric keys in the database or the token
9 **
10 */
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 */
25 #include <stdio.h>
26 #include <string.h>
28 #include "secutil.h"
30 #include "nspr.h"
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"
40 typedef struct _KeyTypes {
41 CK_KEY_TYPE keyType;
42 CK_MECHANISM_TYPE mechType;
43 CK_MECHANISM_TYPE wrapMech;
44 char *label;
45 } KeyTypes;
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 };
77 static int keyArraySize = sizeof(keyArray)/sizeof(keyArray[0]);
79 int
80 GetLen(PRFileDesc* fd)
81 {
82 PRFileInfo info;
84 if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info)) {
85 return -1;
86 }
88 return info.size;
89 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
192 CK_MECHANISM_TYPE
193 GetWrapMechanism(PK11SymKey *symKey)
194 {
195 CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
197 return GetWrapFromKeyType(type);
198 }
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 }
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 }
228 char *
229 BufToHex(SECItem *outbuf)
230 {
231 int len = outbuf->len * 2 +1;
232 char *string, *ptr;
233 unsigned int i;
235 string = PORT_Alloc(len);
237 ptr = string;
238 for (i=0; i < outbuf->len; i++) {
239 *ptr++ = ToDigit(outbuf->data[i] >> 4);
240 *ptr++ = ToDigit(outbuf->data[i] & 0xf);
241 }
242 *ptr = 0;
243 return string;
244 }
247 int
248 HexToBuf(char *inString, SECItem *outbuf)
249 {
250 int len = strlen(inString);
251 int outlen = len+1/2;
252 int trueLen = 0;
254 outbuf->data = PORT_Alloc(outlen);
255 if (outbuf->data) {
256 return -1;
257 }
259 while (*inString) {
260 int digit1, digit2;
261 digit1 = GetDigit(*inString++);
262 digit2 = GetDigit(*inString++);
263 if ((digit1 == -1) || (digit2 == -1)) {
264 PORT_Free(outbuf->data);
265 outbuf->data = NULL;
266 return -1;
267 }
268 outbuf->data[trueLen++] = digit1 << 4 | digit2;
269 }
270 outbuf->len = trueLen;
271 return 0;
272 }
274 void
275 printBuf(unsigned char *data, int len)
276 {
277 int i;
279 for (i=0; i < len; i++) {
280 printf("%02x",data[i]);
281 }
282 }
284 void
285 PrintKey(PK11SymKey *symKey)
286 {
287 char *name = PK11_GetSymKeyNickname(symKey);
288 int len = PK11_GetKeyLength(symKey);
289 int strength = PK11_GetKeyStrength(symKey, NULL);
290 SECItem *value = NULL;
291 CK_KEY_TYPE type = PK11_GetSymKeyType(symKey);
292 (void) PK11_ExtractKeyValue(symKey);
294 value = PK11_GetKeyData(symKey);
296 printf("%-20s %3d %4d %10s ", name ? name: " ", len, strength,
297 GetStringFromKeyType(type));
298 if (value && value->data) {
299 printBuf(value->data, value->len);
300 } else {
301 printf("<restricted>");
302 }
303 printf("\n");
304 }
306 SECStatus
307 ListKeys(PK11SlotInfo *slot, int *printLabel, void *pwd) {
308 PK11SymKey *keyList;
309 SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
310 if (rv != SECSuccess) {
311 return rv;;
312 }
314 keyList = PK11_ListFixedKeysInSlot(slot, NULL, pwd);
315 if (keyList) {
316 if (*printLabel) {
317 printf(" Name Len Strength Type Data\n");
318 *printLabel = 0;
319 }
320 printf("%s:\n",PK11_GetTokenName(slot));
321 }
322 while (keyList) {
323 PK11SymKey *freeKey = keyList;
324 PrintKey(keyList);
325 keyList = PK11_GetNextSymKey(keyList);
326 PK11_FreeSymKey(freeKey);
327 }
328 return SECSuccess;
329 }
331 PK11SymKey *
332 FindKey(PK11SlotInfo *slot, char *name, SECItem *id, void *pwd)
333 {
334 PK11SymKey *key = NULL;
335 SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
337 if (rv != SECSuccess) {
338 return NULL;
339 }
342 if (id->data) {
343 key = PK11_FindFixedKey(slot,CKM_INVALID_MECHANISM, id, pwd);
344 }
345 if (name && !key) {
346 key = PK11_ListFixedKeysInSlot(slot,name, pwd);
347 }
349 if (key) {
350 printf("Found a key\n");
351 PrintKey(key);
352 }
353 return key;
354 }
356 PRBool
357 IsKeyList(PK11SymKey *symKey)
358 {
359 return (PRBool) (PK11_GetNextSymKey(symKey) != NULL);
360 }
362 void
363 FreeKeyList(PK11SymKey *symKey)
364 {
365 PK11SymKey *next,*current;
367 for (current = symKey; current; current = next) {
368 next = PK11_GetNextSymKey(current);
369 PK11_FreeSymKey(current);
370 }
371 return;
372 }
374 static void
375 Usage(char *progName)
376 {
377 #define FPS fprintf(stderr,
378 FPS "Type %s -H for more detailed descriptions\n", progName);
379 FPS "Usage:");
380 FPS "\t%s -L [std_opts] [-r]\n", progName);
381 FPS "\t%s -K [-n name] -t type [-s size] [-i id |-j id_file] [std_opts]\n", progName);
382 FPS "\t%s -D <[-n name | -i id | -j id_file> [std_opts]\n", progName);
383 FPS "\t%s -I [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]\n", progName);
384 FPS "\t%s -E <-nname | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]\n", progName);
385 FPS "\t%s -U [-n name] [-t type] [-i id | -j id_file] -k data_file <wrap_opts> [std_opts]\n", progName);
386 FPS "\t%s -W <-n name | -i id | -j id_file> [-t type] -k data_file [-r] <wrap_opts> [std_opts]\n", progName);
387 FPS "\t%s -M <-n name | -i id | -j id_file> -g target_token [std_opts]\n", progName);
388 FPS "\t\t std_opts -> [-d certdir] [-P dbprefix] [-p password] [-f passwordFile] [-h token]\n");
389 FPS "\t\t wrap_opts -> <-w wrap_name | -x wrap_id | -y id_file>\n");
390 exit(1);
391 }
393 static void LongUsage(char *progName)
394 {
395 int i;
396 FPS "%-15s List all the keys.\n", "-L");
397 FPS "%-15s Generate a new key.\n", "-K");
398 FPS "%-20s Specify the nickname of the new key\n",
399 " -n name");
400 FPS "%-20s Specify the id in hex of the new key\n",
401 " -i key id");
402 FPS "%-20s Specify a file to read the id of the new key\n",
403 " -j key id file");
404 FPS "%-20s Specify the keyType of the new key\n",
405 " -t type");
406 FPS "%-20s", " valid types: ");
407 for (i=0; i < keyArraySize ; i++) {
408 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
409 }
410 FPS "%-20s Specify the size of the new key in bytes (required by some types)\n",
411 " -s size");
412 FPS "%-15s Delete a key.\n", "-D");
413 FPS "%-20s Specify the nickname of the key to delete\n",
414 " -n name");
415 FPS "%-20s Specify the id in hex of the key to delete\n",
416 " -i key id");
417 FPS "%-20s Specify a file to read the id of the key to delete\n",
418 " -j key id file");
419 FPS "%-15s Import a new key from a data file.\n", "-I");
420 FPS "%-20s Specify the data file to read the key from.\n",
421 " -k key file");
422 FPS "%-20s Specify the nickname of the new key\n",
423 " -n name");
424 FPS "%-20s Specify the id in hex of the new key\n",
425 " -i key id");
426 FPS "%-20s Specify a file to read the id of the new key\n",
427 " -j key id file");
428 FPS "%-20s Specify the keyType of the new key\n",
429 " -t type");
430 FPS "%-20s", " valid types: ");
431 for (i=0; i < keyArraySize ; i++) {
432 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
433 }
434 FPS "%-15s Export a key to a data file.\n", "-E");
435 FPS "%-20s Specify the data file to write the key to.\n",
436 " -k key file");
437 FPS "%-20s Specify the nickname of the key to export\n",
438 " -n name");
439 FPS "%-20s Specify the id in hex of the key to export\n",
440 " -i key id");
441 FPS "%-20s Specify a file to read the id of the key to export\n",
442 " -j key id file");
443 FPS "%-15s Move a key to a new token.\n", "-M");
444 FPS "%-20s Specify the nickname of the key to move\n",
445 " -n name");
446 FPS "%-20s Specify the id in hex of the key to move\n",
447 " -i key id");
448 FPS "%-20s Specify a file to read the id of the key to move\n",
449 " -j key id file");
450 FPS "%-20s Specify the token to move the key to\n",
451 " -g target token");
452 FPS "%-15s Unwrap a new key from a data file.\n", "-U");
453 FPS "%-20s Specify the data file to read the encrypted key from.\n",
454 " -k key file");
455 FPS "%-20s Specify the nickname of the new key\n",
456 " -n name");
457 FPS "%-20s Specify the id in hex of the new key\n",
458 " -i key id");
459 FPS "%-20s Specify a file to read the id of the new key\n",
460 " -j key id file");
461 FPS "%-20s Specify the keyType of the new key\n",
462 " -t type");
463 FPS "%-20s", " valid types: ");
464 for (i=0; i < keyArraySize ; i++) {
465 FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':',');
466 }
467 FPS "%-20s Specify the nickname of the wrapping key\n",
468 " -w wrap name");
469 FPS "%-20s Specify the id in hex of the wrapping key\n",
470 " -x wrap key id");
471 FPS "%-20s Specify a file to read the id of the wrapping key\n",
472 " -y wrap key id file");
473 FPS "%-15s Wrap a new key to a data file. [not yet implemented]\n", "-W");
474 FPS "%-20s Specify the data file to write the encrypted key to.\n",
475 " -k key file");
476 FPS "%-20s Specify the nickname of the key to wrap\n",
477 " -n name");
478 FPS "%-20s Specify the id in hex of the key to wrap\n",
479 " -i key id");
480 FPS "%-20s Specify a file to read the id of the key to wrap\n",
481 " -j key id file");
482 FPS "%-20s Specify the nickname of the wrapping key\n",
483 " -w wrap name");
484 FPS "%-20s Specify the id in hex of the wrapping key\n",
485 " -x wrap key id");
486 FPS "%-20s Specify a file to read the id of the wrapping key\n",
487 " -y wrap key id file");
488 FPS "%-15s Options valid for all commands\n", "std_opts");
489 FPS "%-20s The directory where the NSS db's reside\n",
490 " -d certdir");
491 FPS "%-20s Prefix for the NSS db's\n",
492 " -P db prefix");
493 FPS "%-20s Specify password on the command line\n",
494 " -p password");
495 FPS "%-20s Specify password file on the command line\n",
496 " -f password file");
497 FPS "%-20s Specify token to act on\n",
498 " -h token");
499 exit(1);
500 #undef FPS
501 }
503 /* Certutil commands */
504 enum {
505 cmd_CreateNewKey = 0,
506 cmd_DeleteKey,
507 cmd_ImportKey,
508 cmd_ExportKey,
509 cmd_WrapKey,
510 cmd_UnwrapKey,
511 cmd_MoveKey,
512 cmd_ListKeys,
513 cmd_PrintHelp
514 };
516 /* Certutil options */
517 enum {
518 opt_CertDir = 0,
519 opt_PasswordFile,
520 opt_TargetToken,
521 opt_TokenName,
522 opt_KeyID,
523 opt_KeyIDFile,
524 opt_KeyType,
525 opt_Nickname,
526 opt_KeyFile,
527 opt_Password,
528 opt_dbPrefix,
529 opt_RW,
530 opt_KeySize,
531 opt_WrapKeyName,
532 opt_WrapKeyID,
533 opt_WrapKeyIDFile,
534 opt_NoiseFile
535 };
537 static secuCommandFlag symKeyUtil_commands[] =
538 {
539 { /* cmd_CreateNewKey */ 'K', PR_FALSE, 0, PR_FALSE },
540 { /* cmd_DeleteKey */ 'D', PR_FALSE, 0, PR_FALSE },
541 { /* cmd_ImportKey */ 'I', PR_FALSE, 0, PR_FALSE },
542 { /* cmd_ExportKey */ 'E', PR_FALSE, 0, PR_FALSE },
543 { /* cmd_WrapKey */ 'W', PR_FALSE, 0, PR_FALSE },
544 { /* cmd_UnwrapKey */ 'U', PR_FALSE, 0, PR_FALSE },
545 { /* cmd_MoveKey */ 'M', PR_FALSE, 0, PR_FALSE },
546 { /* cmd_ListKeys */ 'L', PR_FALSE, 0, PR_FALSE },
547 { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE },
548 };
550 static secuCommandFlag symKeyUtil_options[] =
551 {
552 { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE },
553 { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE },
554 { /* opt_TargetToken */ 'g', PR_TRUE, 0, PR_FALSE },
555 { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE },
556 { /* opt_KeyID */ 'i', PR_TRUE, 0, PR_FALSE },
557 { /* opt_KeyIDFile */ 'j', PR_TRUE, 0, PR_FALSE },
558 { /* opt_KeyType */ 't', PR_TRUE, 0, PR_FALSE },
559 { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
560 { /* opt_KeyFile */ 'k', PR_TRUE, 0, PR_FALSE },
561 { /* opt_Password */ 'p', PR_TRUE, 0, PR_FALSE },
562 { /* opt_dbPrefix */ 'P', PR_TRUE, 0, PR_FALSE },
563 { /* opt_RW */ 'r', PR_FALSE, 0, PR_FALSE },
564 { /* opt_KeySize */ 's', PR_TRUE, 0, PR_FALSE },
565 { /* opt_WrapKeyName */ 'w', PR_TRUE, 0, PR_FALSE },
566 { /* opt_WrapKeyID */ 'x', PR_TRUE, 0, PR_FALSE },
567 { /* opt_WrapKeyIDFile */ 'y', PR_TRUE, 0, PR_FALSE },
568 { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE },
569 };
571 int
572 main(int argc, char **argv)
573 {
574 PK11SlotInfo *slot = NULL;
575 char * slotname = "internal";
576 char * certPrefix = "";
577 CK_MECHANISM_TYPE keyType = CKM_SHA_1_HMAC;
578 int keySize = 0;
579 char * name = NULL;
580 char * wrapName = NULL;
581 secuPWData pwdata = { PW_NONE, 0 };
582 PRBool readOnly = PR_FALSE;
583 SECItem key;
584 SECItem keyID;
585 SECItem wrapKeyID;
586 int commandsEntered = 0;
587 int commandToRun = 0;
588 char *progName;
589 int i;
590 SECStatus rv = SECFailure;
592 secuCommand symKeyUtil;
593 symKeyUtil.numCommands=sizeof(symKeyUtil_commands)/sizeof(secuCommandFlag);
594 symKeyUtil.numOptions=sizeof(symKeyUtil_options)/sizeof(secuCommandFlag);
595 symKeyUtil.commands = symKeyUtil_commands;
596 symKeyUtil.options = symKeyUtil_options;
598 key.data = NULL; key.len = 0;
599 keyID.data = NULL; keyID.len = 0;
600 wrapKeyID.data = NULL; wrapKeyID.len = 0;
602 progName = strrchr(argv[0], '/');
603 progName = progName ? progName+1 : argv[0];
605 rv = SECU_ParseCommandLine(argc, argv, progName, &symKeyUtil);
607 if (rv != SECSuccess)
608 Usage(progName);
610 rv = SECFailure;
612 /* -H print help */
613 if (symKeyUtil.commands[cmd_PrintHelp].activated)
614 LongUsage(progName);
616 /* -f password file, -p password */
617 if (symKeyUtil.options[opt_PasswordFile].arg) {
618 pwdata.source = PW_FROMFILE;
619 pwdata.data = symKeyUtil.options[opt_PasswordFile].arg;
620 } else if (symKeyUtil.options[opt_Password].arg) {
621 pwdata.source = PW_PLAINTEXT;
622 pwdata.data = symKeyUtil.options[opt_Password].arg;
623 }
625 /* -d directory */
626 if (symKeyUtil.options[opt_CertDir].activated)
627 SECU_ConfigDirectory(symKeyUtil.options[opt_CertDir].arg);
629 /* -s key size */
630 if (symKeyUtil.options[opt_KeySize].activated) {
631 keySize = PORT_Atoi(symKeyUtil.options[opt_KeySize].arg);
632 }
634 /* -h specify token name */
635 if (symKeyUtil.options[opt_TokenName].activated) {
636 if (PL_strcmp(symKeyUtil.options[opt_TokenName].arg, "all") == 0)
637 slotname = NULL;
638 else
639 slotname = PL_strdup(symKeyUtil.options[opt_TokenName].arg);
640 }
642 /* -t key type */
643 if (symKeyUtil.options[opt_KeyType].activated) {
644 keyType = GetKeyMechFromString(symKeyUtil.options[opt_KeyType].arg);
645 if (keyType == (CK_MECHANISM_TYPE)-1) {
646 PR_fprintf(PR_STDERR,
647 "%s unknown key type (%s).\n",
648 progName, symKeyUtil.options[opt_KeyType].arg);
649 return 255;
650 }
651 }
653 /* -k for import and unwrap, it specifies an input file to read from,
654 * for export and wrap it specifies an output file to write to */
655 if (symKeyUtil.options[opt_KeyFile].activated) {
656 if (symKeyUtil.commands[cmd_ImportKey].activated ||
657 symKeyUtil.commands[cmd_UnwrapKey].activated ) {
658 int ret = ReadBuf(symKeyUtil.options[opt_KeyFile].arg, &key);
659 if (ret < 0) {
660 PR_fprintf(PR_STDERR,
661 "%s Couldn't read key file (%s).\n",
662 progName, symKeyUtil.options[opt_KeyFile].arg);
663 return 255;
664 }
665 }
666 }
668 /* -i specify the key ID */
669 if (symKeyUtil.options[opt_KeyID].activated) {
670 int ret = HexToBuf(symKeyUtil.options[opt_KeyID].arg, &keyID);
671 if (ret < 0) {
672 PR_fprintf(PR_STDERR,
673 "%s invalid key ID (%s).\n",
674 progName, symKeyUtil.options[opt_KeyID].arg);
675 return 255;
676 }
677 }
679 /* -i & -j are mutually exclusive */
680 if ((symKeyUtil.options[opt_KeyID].activated) &&
681 (symKeyUtil.options[opt_KeyIDFile].activated)) {
682 PR_fprintf(PR_STDERR,
683 "%s -i and -j options are mutually exclusive.\n", progName);
684 return 255;
685 }
687 /* -x specify the Wrap key ID */
688 if (symKeyUtil.options[opt_WrapKeyID].activated) {
689 int ret = HexToBuf(symKeyUtil.options[opt_WrapKeyID].arg, &wrapKeyID);
690 if (ret < 0) {
691 PR_fprintf(PR_STDERR,
692 "%s invalid key ID (%s).\n",
693 progName, symKeyUtil.options[opt_WrapKeyID].arg);
694 return 255;
695 }
696 }
698 /* -x & -y are mutually exclusive */
699 if ((symKeyUtil.options[opt_KeyID].activated) &&
700 (symKeyUtil.options[opt_KeyIDFile].activated)) {
701 PR_fprintf(PR_STDERR,
702 "%s -i and -j options are mutually exclusive.\n", progName);
703 return 255;
704 }
707 /* -y specify the key ID */
708 if (symKeyUtil.options[opt_WrapKeyIDFile].activated) {
709 int ret = ReadBuf(symKeyUtil.options[opt_WrapKeyIDFile].arg,
710 &wrapKeyID);
711 if (ret < 0) {
712 PR_fprintf(PR_STDERR,
713 "%s Couldn't read key ID file (%s).\n",
714 progName, symKeyUtil.options[opt_WrapKeyIDFile].arg);
715 return 255;
716 }
717 }
719 /* -P certdb name prefix */
720 if (symKeyUtil.options[opt_dbPrefix].activated)
721 certPrefix = symKeyUtil.options[opt_dbPrefix].arg;
723 /* Check number of commands entered. */
724 commandsEntered = 0;
725 for (i=0; i< symKeyUtil.numCommands; i++) {
726 if (symKeyUtil.commands[i].activated) {
727 commandToRun = symKeyUtil.commands[i].flag;
728 commandsEntered++;
729 }
730 if (commandsEntered > 1)
731 break;
732 }
733 if (commandsEntered > 1) {
734 PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
735 PR_fprintf(PR_STDERR, "You entered: ");
736 for (i=0; i< symKeyUtil.numCommands; i++) {
737 if (symKeyUtil.commands[i].activated)
738 PR_fprintf(PR_STDERR, " -%c", symKeyUtil.commands[i].flag);
739 }
740 PR_fprintf(PR_STDERR, "\n");
741 return 255;
742 }
743 if (commandsEntered == 0) {
744 PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName);
745 Usage(progName);
746 }
748 if (symKeyUtil.commands[cmd_ListKeys].activated ||
749 symKeyUtil.commands[cmd_PrintHelp].activated ||
750 symKeyUtil.commands[cmd_ExportKey].activated ||
751 symKeyUtil.commands[cmd_WrapKey].activated) {
752 readOnly = !symKeyUtil.options[opt_RW].activated;
753 }
755 if ((symKeyUtil.commands[cmd_ImportKey].activated ||
756 symKeyUtil.commands[cmd_ExportKey].activated ||
757 symKeyUtil.commands[cmd_WrapKey].activated ||
758 symKeyUtil.commands[cmd_UnwrapKey].activated ) &&
759 !symKeyUtil.options[opt_KeyFile].activated) {
760 PR_fprintf(PR_STDERR,
761 "%s -%c: keyfile is required for this command (-k).\n",
762 progName, commandToRun);
763 return 255;
764 }
766 /* -E, -D, -W, and all require -n, -i, or -j to identify the key */
767 if ((symKeyUtil.commands[cmd_ExportKey].activated ||
768 symKeyUtil.commands[cmd_DeleteKey].activated ||
769 symKeyUtil.commands[cmd_WrapKey].activated) &&
770 !(symKeyUtil.options[opt_Nickname].activated ||
771 symKeyUtil.options[opt_KeyID].activated ||
772 symKeyUtil.options[opt_KeyIDFile].activated)) {
773 PR_fprintf(PR_STDERR,
774 "%s -%c: nickname or id is required for this command (-n, -i, -j).\n",
775 progName, commandToRun);
776 return 255;
777 }
779 /* -W, -U, and all -w, -x, or -y to identify the wrapping key */
780 if (( symKeyUtil.commands[cmd_WrapKey].activated ||
781 symKeyUtil.commands[cmd_UnwrapKey].activated) &&
782 !(symKeyUtil.options[opt_WrapKeyName].activated ||
783 symKeyUtil.options[opt_WrapKeyID].activated ||
784 symKeyUtil.options[opt_WrapKeyIDFile].activated)) {
785 PR_fprintf(PR_STDERR,
786 "%s -%c: wrap key is required for this command (-w, -x, or -y).\n",
787 progName, commandToRun);
788 return 255;
789 }
791 /* -M needs the target slot (-g) */
792 if (symKeyUtil.commands[cmd_MoveKey].activated &&
793 !symKeyUtil.options[opt_TargetToken].activated) {
794 PR_fprintf(PR_STDERR,
795 "%s -%c: target token is required for this command (-g).\n",
796 progName, commandToRun);
797 return 255;
798 }
800 /* Using slotname == NULL for listing keys and certs on all slots,
801 * but only that. */
802 if (!(symKeyUtil.commands[cmd_ListKeys].activated) && slotname == NULL) {
803 PR_fprintf(PR_STDERR,
804 "%s -%c: cannot use \"-h all\" for this command.\n",
805 progName, commandToRun);
806 return 255;
807 }
809 name = SECU_GetOptionArg(&symKeyUtil, opt_Nickname);
810 wrapName = SECU_GetOptionArg(&symKeyUtil, opt_WrapKeyName);
812 PK11_SetPasswordFunc(SECU_GetModulePassword);
814 /* Initialize NSPR and NSS. */
815 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
816 rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix,
817 "secmod.db", readOnly ? NSS_INIT_READONLY: 0);
818 if (rv != SECSuccess) {
819 SECU_PrintPRandOSError(progName);
820 goto shutdown;
821 }
822 rv = SECFailure;
824 if (PL_strcmp(slotname, "internal") == 0)
825 slot = PK11_GetInternalKeySlot();
826 else if (slotname != NULL)
827 slot = PK11_FindSlotByName(slotname);
829 /* generating a new key */
830 if (symKeyUtil.commands[cmd_CreateNewKey].activated) {
831 PK11SymKey *symKey;
833 symKey = PK11_TokenKeyGen(slot, keyType, NULL, keySize,
834 NULL, PR_TRUE, &pwdata);
835 if (!symKey) {
836 PR_fprintf(PR_STDERR, "%s: Token Key Gen Failed\n", progName);
837 goto shutdown;
838 }
839 if (symKeyUtil.options[opt_Nickname].activated) {
840 rv = PK11_SetSymKeyNickname(symKey, name);
841 if (rv != SECSuccess) {
842 PK11_DeleteTokenSymKey(symKey);
843 PK11_FreeSymKey(symKey);
844 PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n",
845 progName);
846 goto shutdown;
847 }
848 }
849 rv = SECSuccess;
850 PrintKey(symKey);
851 PK11_FreeSymKey(symKey);
852 }
853 if (symKeyUtil.commands[cmd_DeleteKey].activated) {
854 PK11SymKey *symKey = FindKey(slot,name,&keyID,&pwdata);
856 if (!symKey) {
857 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
858 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
859 progName, keyName, PK11_GetTokenName(slot));
860 PORT_Free(keyName);
861 goto shutdown;
862 }
864 rv = PK11_DeleteTokenSymKey(symKey);
865 FreeKeyList(symKey);
866 if (rv != SECSuccess) {
867 PR_fprintf(PR_STDERR, "%s: Couldn't Delete Key \n", progName);
868 goto shutdown;
869 }
870 }
871 if (symKeyUtil.commands[cmd_UnwrapKey].activated) {
872 PK11SymKey *wrapKey = FindKey(slot,wrapName,&wrapKeyID,&pwdata);
873 PK11SymKey *symKey;
874 CK_MECHANISM_TYPE mechanism;
876 if (!wrapKey) {
877 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
878 : PORT_Strdup(wrapName);
879 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
880 progName, keyName, PK11_GetTokenName(slot));
881 PORT_Free(keyName);
882 goto shutdown;
883 }
884 mechanism = GetWrapMechanism(wrapKey);
885 if (mechanism == CKM_INVALID_MECHANISM) {
886 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
887 : PORT_Strdup(wrapName);
888 PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n",
889 progName, keyName, PK11_GetTokenName(slot));
890 PORT_Free(keyName);
891 PK11_FreeSymKey(wrapKey);
892 goto shutdown;
893 }
895 symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrapKey, mechanism, NULL,
896 &key, keyType, CKA_ENCRYPT, keySize, 0, PR_TRUE);
897 PK11_FreeSymKey(wrapKey);
898 if (!symKey) {
899 PR_fprintf(PR_STDERR, "%s: Unwrap Key Failed\n", progName);
900 goto shutdown;
901 }
903 if (symKeyUtil.options[opt_Nickname].activated) {
904 rv = PK11_SetSymKeyNickname(symKey, name);
905 if (rv != SECSuccess) {
906 PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n",
907 progName);
908 PK11_DeleteTokenSymKey(symKey);
909 PK11_FreeSymKey(symKey);
910 goto shutdown;
911 }
912 }
913 rv = SECSuccess;
914 PrintKey(symKey);
915 PK11_FreeSymKey(symKey);
916 }
918 #define MAX_KEY_SIZE 4098
919 if (symKeyUtil.commands[cmd_WrapKey].activated) {
920 PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata);
921 PK11SymKey *wrapKey;
922 CK_MECHANISM_TYPE mechanism;
923 SECItem data;
924 unsigned char buf[MAX_KEY_SIZE];
925 int ret;
927 if (!symKey) {
928 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
929 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
930 progName, keyName, PK11_GetTokenName(slot));
931 PORT_Free(keyName);
932 goto shutdown;
933 }
935 wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata);
936 if (!wrapKey) {
937 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
938 : PORT_Strdup(wrapName);
939 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
940 progName, keyName, PK11_GetTokenName(slot));
941 PORT_Free(keyName);
942 PK11_FreeSymKey(symKey);
943 goto shutdown;
944 }
946 mechanism = GetWrapMechanism(wrapKey);
947 if (mechanism == CKM_INVALID_MECHANISM) {
948 char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID)
949 : PORT_Strdup(wrapName);
950 PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n",
951 progName, keyName, PK11_GetTokenName(slot));
952 PORT_Free(keyName);
953 PK11_FreeSymKey(symKey);
954 PK11_FreeSymKey(wrapKey);
955 goto shutdown;
956 }
958 data.data = buf;
959 data.len = sizeof(buf);
960 rv = PK11_WrapSymKey(mechanism, NULL, wrapKey, symKey, &data);
961 PK11_FreeSymKey(symKey);
962 PK11_FreeSymKey(wrapKey);
963 if (rv != SECSuccess) {
964 PR_fprintf(PR_STDERR, "%s: Couldn't wrap key\n",progName);
965 goto shutdown;
966 }
968 /* WriteBuf outputs it's own error using SECU_PrintError */
969 ret = WriteBuf(symKeyUtil.options[opt_KeyFile].arg, &data);
970 if (ret < 0) {
971 goto shutdown;
972 }
973 }
975 if (symKeyUtil.commands[cmd_ImportKey].activated) {
976 PK11SymKey *symKey = PK11_ImportSymKey(slot, keyType,
977 PK11_OriginUnwrap, CKA_ENCRYPT, &key,&pwdata);
978 if (!symKey) {
979 PR_fprintf(PR_STDERR, "%s: Import Key Failed\n", progName);
980 goto shutdown;
981 }
982 if (symKeyUtil.options[opt_Nickname].activated) {
983 rv = PK11_SetSymKeyNickname(symKey, name);
984 if (rv != SECSuccess) {
985 PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n",
986 progName);
987 PK11_DeleteTokenSymKey(symKey);
988 PK11_FreeSymKey(symKey);
989 goto shutdown;
990 }
991 }
992 rv = SECSuccess;
993 PrintKey(symKey);
994 PK11_FreeSymKey(symKey);
995 }
997 /* List certs (-L) */
998 if (symKeyUtil.commands[cmd_ListKeys].activated) {
999 int printLabel = 1;
1000 if (slot) {
1001 rv = ListKeys(slot,&printLabel,&pwdata);
1002 } else {
1003 /* loop over all the slots */
1004 PK11SlotList *slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
1005 PR_FALSE, PR_FALSE, &pwdata);
1006 if (slotList == NULL) {
1007 PR_fprintf(PR_STDERR, "%s: No tokens found\n",progName);
1008 } else {
1009 PK11SlotListElement *se;
1010 for (se = PK11_GetFirstSafe(slotList); se;
1011 se=PK11_GetNextSafe(slotList,se, PR_FALSE)) {
1012 rv = ListKeys(se->slot,&printLabel,&pwdata);
1013 if (rv !=SECSuccess) {
1014 break;
1015 }
1016 }
1017 if (se) {
1018 SECStatus rv2 = PK11_FreeSlotListElement(slotList, se);
1019 PORT_Assert(SECSuccess == rv2);
1020 }
1021 PK11_FreeSlotList(slotList);
1022 }
1023 }
1024 }
1026 /* Move key (-M) */
1027 if (symKeyUtil.commands[cmd_MoveKey].activated) {
1028 PK11SlotInfo *target;
1029 char *targetName = symKeyUtil.options[opt_TargetToken].arg;
1030 PK11SymKey *newKey;
1031 PK11SymKey *symKey = FindKey(slot,name,&keyID,&pwdata);
1032 char *keyName = PK11_GetSymKeyNickname(symKey);
1034 if (!symKey) {
1035 char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name);
1036 PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n",
1037 progName, keyName, PK11_GetTokenName(slot));
1038 PORT_Free(keyName);
1039 goto shutdown;
1040 }
1041 target = PK11_FindSlotByName(targetName);
1042 if (!target) {
1043 PR_fprintf(PR_STDERR, "%s: Couldn't find slot %s\n",
1044 progName, targetName);
1045 goto shutdown;
1046 }
1047 rv = PK11_Authenticate(target, PR_FALSE, &pwdata);
1048 if (rv != SECSuccess) {
1049 PR_fprintf(PR_STDERR, "%s: Failed to log into %s\n",
1050 progName, targetName);
1051 goto shutdown;
1052 }
1053 rv = SECFailure;
1054 newKey = PK11_MoveSymKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey);
1055 if (!newKey) {
1056 PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n",progName);
1057 goto shutdown;
1058 }
1059 if (keyName) {
1060 rv = PK11_SetSymKeyNickname(newKey, keyName);
1061 if (rv != SECSuccess) {
1062 PK11_DeleteTokenSymKey(newKey);
1063 PK11_FreeSymKey(newKey);
1064 PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n",
1065 progName);
1066 goto shutdown;
1067 }
1068 }
1069 PK11_FreeSymKey(newKey);
1070 rv = SECSuccess;
1071 }
1073 shutdown:
1074 if (rv != SECSuccess) {
1075 PR_fprintf(PR_STDERR, "%s: %s\n", progName,
1076 SECU_Strerror(PORT_GetError()));
1077 }
1079 if (key.data) {
1080 PORT_Free(key.data);
1081 }
1083 if (keyID.data) {
1084 PORT_Free(keyID.data);
1085 }
1087 if (slot) {
1088 PK11_FreeSlot(slot);
1089 }
1091 if (NSS_Shutdown() != SECSuccess) {
1092 exit(1);
1093 }
1095 if (rv == SECSuccess) {
1096 return 0;
1097 } else {
1098 return 255;
1099 }
1100 }