security/nss/cmd/symkeyutil/symkeyutil.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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;
  1017                 if (se) {
  1018                     SECStatus rv2 = PK11_FreeSlotListElement(slotList, se);
  1019                     PORT_Assert(SECSuccess == rv2);
  1021                 PK11_FreeSlotList(slotList);
  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;
  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;
  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;
  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;
  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;
  1069 	PK11_FreeSymKey(newKey);
  1070 	rv = SECSuccess;
  1073 shutdown:
  1074     if (rv != SECSuccess) {
  1075 	PR_fprintf(PR_STDERR, "%s: %s\n", progName,
  1076 					SECU_Strerror(PORT_GetError()));
  1079     if (key.data) {
  1080 	PORT_Free(key.data);
  1083     if (keyID.data) {
  1084 	PORT_Free(keyID.data);
  1087     if (slot) {
  1088 	PK11_FreeSlot(slot);
  1091     if (NSS_Shutdown() != SECSuccess) {
  1092         exit(1);
  1095     if (rv == SECSuccess) {
  1096 	return 0;
  1097     } else {
  1098 	return 255;

mercurial