michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: ** symkeyutil.c michael@0: ** michael@0: ** utility for managing symetric keys in the database or the token michael@0: ** michael@0: */ michael@0: michael@0: /* michael@0: * Wish List for this utility: michael@0: * 1) Display and Set the CKA_ operation flags for the key. michael@0: * 2) Modify existing keys michael@0: * 3) Copy keys michael@0: * 4) Read CKA_ID and display for keys. michael@0: * 5) Option to store CKA_ID in a file on key creation. michael@0: * 6) Encrypt, Decrypt, Hash, and Mac with generated keys. michael@0: * 7) Use asymetric keys to wrap and unwrap keys. michael@0: * 8) Derive. michael@0: * 9) PBE keys. michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "secutil.h" michael@0: michael@0: #include "nspr.h" michael@0: michael@0: #include "pk11func.h" michael@0: #include "secasn1.h" michael@0: #include "cert.h" michael@0: #include "cryptohi.h" michael@0: #include "secoid.h" michael@0: #include "certdb.h" michael@0: #include "nss.h" michael@0: michael@0: typedef struct _KeyTypes { michael@0: CK_KEY_TYPE keyType; michael@0: CK_MECHANISM_TYPE mechType; michael@0: CK_MECHANISM_TYPE wrapMech; michael@0: char *label; michael@0: } KeyTypes; michael@0: michael@0: static KeyTypes keyArray[] = { michael@0: #ifdef RECOGNIZE_ASYMETRIC_TYPES michael@0: { CKK_RSA, CKM_RSA_PKCS, CKM_RSA_PKCS, "rsa" }, michael@0: { CKK_DSA, CKM_DSA, CKM_INVALID_MECHANISM, "dsa" }, michael@0: { CKK_DH, CKM_DH_PKCS_DERIVE, CKM_INVALID_MECHANISM, "dh" }, michael@0: { CKK_EC, CKM_ECDSA, CKM_INVALID_MECHANISM, "ec" }, michael@0: { CKK_X9_42_DH, CKM_X9_42_DH_DERIVE, CKM_INVALID_MECHANISM, "x9.42dh" }, michael@0: { CKK_KEA, CKM_KEA_KEY_DERIVE, CKM_INVALID_MECHANISM, "kea" }, michael@0: #endif michael@0: { CKK_GENERIC_SECRET, CKM_SHA_1_HMAC, CKM_INVALID_MECHANISM, "generic" }, michael@0: { CKK_RC2, CKM_RC2_CBC, CKM_RC2_ECB,"rc2" }, michael@0: /* don't define a wrap mech for RC-4 since it's note really safe */ michael@0: { CKK_RC4, CKM_RC4, CKM_INVALID_MECHANISM, "rc4" }, michael@0: { CKK_DES, CKM_DES_CBC, CKM_DES_ECB,"des" }, michael@0: { CKK_DES2, CKM_DES2_KEY_GEN, CKM_DES3_ECB, "des2" }, michael@0: { CKK_DES3, CKM_DES3_KEY_GEN, CKM_DES3_ECB, "des3" }, michael@0: { CKK_CAST, CKM_CAST_CBC, CKM_CAST_ECB, "cast" }, michael@0: { CKK_CAST3, CKM_CAST3_CBC, CKM_CAST3_ECB, "cast3" }, michael@0: { CKK_CAST5, CKM_CAST5_CBC, CKM_CAST5_ECB, "cast5" }, michael@0: { CKK_CAST128, CKM_CAST128_CBC, CKM_CAST128_ECB, "cast128" }, michael@0: { CKK_RC5, CKM_RC5_CBC, CKM_RC5_ECB, "rc5" }, michael@0: { CKK_IDEA, CKM_IDEA_CBC, CKM_IDEA_ECB, "idea" }, michael@0: { CKK_SKIPJACK, CKM_SKIPJACK_CBC64, CKM_SKIPJACK_WRAP, "skipjack" }, michael@0: { CKK_BATON, CKM_BATON_CBC128, CKM_BATON_WRAP, "baton" }, michael@0: { CKK_JUNIPER, CKM_JUNIPER_CBC128, CKM_JUNIPER_WRAP, "juniper" }, michael@0: { CKK_CDMF, CKM_CDMF_CBC, CKM_CDMF_ECB, "cdmf" }, michael@0: { CKK_AES, CKM_AES_CBC, CKM_AES_ECB, "aes" }, michael@0: { CKK_CAMELLIA, CKM_CAMELLIA_CBC, CKM_CAMELLIA_ECB, "camellia" }, michael@0: }; michael@0: michael@0: static int keyArraySize = sizeof(keyArray)/sizeof(keyArray[0]); michael@0: michael@0: int michael@0: GetLen(PRFileDesc* fd) michael@0: { michael@0: PRFileInfo info; michael@0: michael@0: if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &info)) { michael@0: return -1; michael@0: } michael@0: michael@0: return info.size; michael@0: } michael@0: michael@0: int michael@0: ReadBuf(char *inFile, SECItem *item) michael@0: { michael@0: int len; michael@0: int ret; michael@0: PRFileDesc* fd = PR_Open(inFile, PR_RDONLY, 0); michael@0: if (NULL == fd) { michael@0: SECU_PrintError("symkeyutil", "PR_Open failed"); michael@0: return -1; michael@0: } michael@0: michael@0: len = GetLen(fd); michael@0: if (len < 0) { michael@0: SECU_PrintError("symkeyutil", "PR_GetOpenFileInfo failed"); michael@0: return -1; michael@0: } michael@0: item->data = (unsigned char *)PORT_Alloc(len); michael@0: if (item->data == NULL) { michael@0: fprintf(stderr,"Failed to allocate %d to read file %s\n",len,inFile); michael@0: return -1; michael@0: } michael@0: michael@0: ret = PR_Read(fd,item->data,item->len); michael@0: if (ret < 0) { michael@0: SECU_PrintError("symkeyutil", "PR_Read failed"); michael@0: PORT_Free(item->data); michael@0: item->data = NULL; michael@0: return -1; michael@0: } michael@0: PR_Close(fd); michael@0: item->len = len; michael@0: return 0; michael@0: } michael@0: michael@0: int michael@0: WriteBuf(char *inFile, SECItem *item) michael@0: { michael@0: int ret; michael@0: PRFileDesc* fd = PR_Open(inFile, PR_WRONLY|PR_CREATE_FILE, 0x200); michael@0: if (NULL == fd) { michael@0: SECU_PrintError("symkeyutil", "PR_Open failed"); michael@0: return -1; michael@0: } michael@0: michael@0: ret = PR_Write(fd,item->data,item->len); michael@0: if (ret < 0) { michael@0: SECU_PrintError("symkeyutil", "PR_Write failed"); michael@0: return -1; michael@0: } michael@0: PR_Close(fd); michael@0: return 0; michael@0: } michael@0: michael@0: CK_KEY_TYPE michael@0: GetKeyTypeFromString(const char *keyString) michael@0: { michael@0: int i; michael@0: for (i=0; i < keyArraySize; i++) { michael@0: if (PL_strcasecmp(keyString,keyArray[i].label) == 0) { michael@0: return keyArray[i].keyType; michael@0: } michael@0: } michael@0: return (CK_KEY_TYPE)-1; michael@0: } michael@0: michael@0: CK_MECHANISM_TYPE michael@0: GetKeyMechFromString(const char *keyString) michael@0: { michael@0: int i; michael@0: for (i=0; i < keyArraySize; i++) { michael@0: if (PL_strcasecmp(keyString,keyArray[i].label) == 0) { michael@0: return keyArray[i].mechType; michael@0: } michael@0: } michael@0: return (CK_MECHANISM_TYPE)-1; michael@0: } michael@0: michael@0: const char * michael@0: GetStringFromKeyType(CK_KEY_TYPE type) michael@0: { michael@0: int i; michael@0: for (i=0; i < keyArraySize; i++) { michael@0: if (keyArray[i].keyType == type) { michael@0: return keyArray[i].label; michael@0: } michael@0: } michael@0: return "unmatched"; michael@0: } michael@0: michael@0: CK_MECHANISM_TYPE michael@0: GetWrapFromKeyType(CK_KEY_TYPE type) michael@0: { michael@0: int i; michael@0: for (i=0; i < keyArraySize; i++) { michael@0: if (keyArray[i].keyType == type) { michael@0: return keyArray[i].wrapMech; michael@0: } michael@0: } michael@0: return CKM_INVALID_MECHANISM; michael@0: } michael@0: michael@0: CK_MECHANISM_TYPE michael@0: GetWrapMechanism(PK11SymKey *symKey) michael@0: { michael@0: CK_KEY_TYPE type = PK11_GetSymKeyType(symKey); michael@0: michael@0: return GetWrapFromKeyType(type); michael@0: } michael@0: michael@0: int michael@0: GetDigit(char c) michael@0: { michael@0: if (c == 0) { michael@0: return -1; michael@0: } michael@0: if (c <= '9' && c >= '0') { michael@0: return c - '0'; michael@0: } michael@0: if (c <= 'f' && c >= 'a') { michael@0: return c - 'a' + 0xa; michael@0: } michael@0: if (c <= 'F' && c >= 'A') { michael@0: return c - 'A' + 0xa; michael@0: } michael@0: return -1; michael@0: } michael@0: michael@0: char michael@0: ToDigit(unsigned char c) michael@0: { michael@0: c = c & 0xf; michael@0: if (c <= 9) { michael@0: return (char) (c+'0'); michael@0: } michael@0: return (char) (c+'a'-0xa); michael@0: } michael@0: michael@0: char * michael@0: BufToHex(SECItem *outbuf) michael@0: { michael@0: int len = outbuf->len * 2 +1; michael@0: char *string, *ptr; michael@0: unsigned int i; michael@0: michael@0: string = PORT_Alloc(len); michael@0: michael@0: ptr = string; michael@0: for (i=0; i < outbuf->len; i++) { michael@0: *ptr++ = ToDigit(outbuf->data[i] >> 4); michael@0: *ptr++ = ToDigit(outbuf->data[i] & 0xf); michael@0: } michael@0: *ptr = 0; michael@0: return string; michael@0: } michael@0: michael@0: michael@0: int michael@0: HexToBuf(char *inString, SECItem *outbuf) michael@0: { michael@0: int len = strlen(inString); michael@0: int outlen = len+1/2; michael@0: int trueLen = 0; michael@0: michael@0: outbuf->data = PORT_Alloc(outlen); michael@0: if (outbuf->data) { michael@0: return -1; michael@0: } michael@0: michael@0: while (*inString) { michael@0: int digit1, digit2; michael@0: digit1 = GetDigit(*inString++); michael@0: digit2 = GetDigit(*inString++); michael@0: if ((digit1 == -1) || (digit2 == -1)) { michael@0: PORT_Free(outbuf->data); michael@0: outbuf->data = NULL; michael@0: return -1; michael@0: } michael@0: outbuf->data[trueLen++] = digit1 << 4 | digit2; michael@0: } michael@0: outbuf->len = trueLen; michael@0: return 0; michael@0: } michael@0: michael@0: void michael@0: printBuf(unsigned char *data, int len) michael@0: { michael@0: int i; michael@0: michael@0: for (i=0; i < len; i++) { michael@0: printf("%02x",data[i]); michael@0: } michael@0: } michael@0: michael@0: void michael@0: PrintKey(PK11SymKey *symKey) michael@0: { michael@0: char *name = PK11_GetSymKeyNickname(symKey); michael@0: int len = PK11_GetKeyLength(symKey); michael@0: int strength = PK11_GetKeyStrength(symKey, NULL); michael@0: SECItem *value = NULL; michael@0: CK_KEY_TYPE type = PK11_GetSymKeyType(symKey); michael@0: (void) PK11_ExtractKeyValue(symKey); michael@0: michael@0: value = PK11_GetKeyData(symKey); michael@0: michael@0: printf("%-20s %3d %4d %10s ", name ? name: " ", len, strength, michael@0: GetStringFromKeyType(type)); michael@0: if (value && value->data) { michael@0: printBuf(value->data, value->len); michael@0: } else { michael@0: printf(""); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: michael@0: SECStatus michael@0: ListKeys(PK11SlotInfo *slot, int *printLabel, void *pwd) { michael@0: PK11SymKey *keyList; michael@0: SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd); michael@0: if (rv != SECSuccess) { michael@0: return rv;; michael@0: } michael@0: michael@0: keyList = PK11_ListFixedKeysInSlot(slot, NULL, pwd); michael@0: if (keyList) { michael@0: if (*printLabel) { michael@0: printf(" Name Len Strength Type Data\n"); michael@0: *printLabel = 0; michael@0: } michael@0: printf("%s:\n",PK11_GetTokenName(slot)); michael@0: } michael@0: while (keyList) { michael@0: PK11SymKey *freeKey = keyList; michael@0: PrintKey(keyList); michael@0: keyList = PK11_GetNextSymKey(keyList); michael@0: PK11_FreeSymKey(freeKey); michael@0: } michael@0: return SECSuccess; michael@0: } michael@0: michael@0: PK11SymKey * michael@0: FindKey(PK11SlotInfo *slot, char *name, SECItem *id, void *pwd) michael@0: { michael@0: PK11SymKey *key = NULL; michael@0: SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd); michael@0: michael@0: if (rv != SECSuccess) { michael@0: return NULL; michael@0: } michael@0: michael@0: michael@0: if (id->data) { michael@0: key = PK11_FindFixedKey(slot,CKM_INVALID_MECHANISM, id, pwd); michael@0: } michael@0: if (name && !key) { michael@0: key = PK11_ListFixedKeysInSlot(slot,name, pwd); michael@0: } michael@0: michael@0: if (key) { michael@0: printf("Found a key\n"); michael@0: PrintKey(key); michael@0: } michael@0: return key; michael@0: } michael@0: michael@0: PRBool michael@0: IsKeyList(PK11SymKey *symKey) michael@0: { michael@0: return (PRBool) (PK11_GetNextSymKey(symKey) != NULL); michael@0: } michael@0: michael@0: void michael@0: FreeKeyList(PK11SymKey *symKey) michael@0: { michael@0: PK11SymKey *next,*current; michael@0: michael@0: for (current = symKey; current; current = next) { michael@0: next = PK11_GetNextSymKey(current); michael@0: PK11_FreeSymKey(current); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: static void michael@0: Usage(char *progName) michael@0: { michael@0: #define FPS fprintf(stderr, michael@0: FPS "Type %s -H for more detailed descriptions\n", progName); michael@0: FPS "Usage:"); michael@0: FPS "\t%s -L [std_opts] [-r]\n", progName); michael@0: FPS "\t%s -K [-n name] -t type [-s size] [-i id |-j id_file] [std_opts]\n", progName); michael@0: FPS "\t%s -D <[-n name | -i id | -j id_file> [std_opts]\n", progName); michael@0: FPS "\t%s -I [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]\n", progName); michael@0: FPS "\t%s -E <-nname | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]\n", progName); michael@0: FPS "\t%s -U [-n name] [-t type] [-i id | -j id_file] -k data_file [std_opts]\n", progName); michael@0: FPS "\t%s -W <-n name | -i id | -j id_file> [-t type] -k data_file [-r] [std_opts]\n", progName); michael@0: FPS "\t%s -M <-n name | -i id | -j id_file> -g target_token [std_opts]\n", progName); michael@0: FPS "\t\t std_opts -> [-d certdir] [-P dbprefix] [-p password] [-f passwordFile] [-h token]\n"); michael@0: FPS "\t\t wrap_opts -> <-w wrap_name | -x wrap_id | -y id_file>\n"); michael@0: exit(1); michael@0: } michael@0: michael@0: static void LongUsage(char *progName) michael@0: { michael@0: int i; michael@0: FPS "%-15s List all the keys.\n", "-L"); michael@0: FPS "%-15s Generate a new key.\n", "-K"); michael@0: FPS "%-20s Specify the nickname of the new key\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the new key\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the new key\n", michael@0: " -j key id file"); michael@0: FPS "%-20s Specify the keyType of the new key\n", michael@0: " -t type"); michael@0: FPS "%-20s", " valid types: "); michael@0: for (i=0; i < keyArraySize ; i++) { michael@0: FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':','); michael@0: } michael@0: FPS "%-20s Specify the size of the new key in bytes (required by some types)\n", michael@0: " -s size"); michael@0: FPS "%-15s Delete a key.\n", "-D"); michael@0: FPS "%-20s Specify the nickname of the key to delete\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the key to delete\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the key to delete\n", michael@0: " -j key id file"); michael@0: FPS "%-15s Import a new key from a data file.\n", "-I"); michael@0: FPS "%-20s Specify the data file to read the key from.\n", michael@0: " -k key file"); michael@0: FPS "%-20s Specify the nickname of the new key\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the new key\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the new key\n", michael@0: " -j key id file"); michael@0: FPS "%-20s Specify the keyType of the new key\n", michael@0: " -t type"); michael@0: FPS "%-20s", " valid types: "); michael@0: for (i=0; i < keyArraySize ; i++) { michael@0: FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':','); michael@0: } michael@0: FPS "%-15s Export a key to a data file.\n", "-E"); michael@0: FPS "%-20s Specify the data file to write the key to.\n", michael@0: " -k key file"); michael@0: FPS "%-20s Specify the nickname of the key to export\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the key to export\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the key to export\n", michael@0: " -j key id file"); michael@0: FPS "%-15s Move a key to a new token.\n", "-M"); michael@0: FPS "%-20s Specify the nickname of the key to move\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the key to move\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the key to move\n", michael@0: " -j key id file"); michael@0: FPS "%-20s Specify the token to move the key to\n", michael@0: " -g target token"); michael@0: FPS "%-15s Unwrap a new key from a data file.\n", "-U"); michael@0: FPS "%-20s Specify the data file to read the encrypted key from.\n", michael@0: " -k key file"); michael@0: FPS "%-20s Specify the nickname of the new key\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the new key\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the new key\n", michael@0: " -j key id file"); michael@0: FPS "%-20s Specify the keyType of the new key\n", michael@0: " -t type"); michael@0: FPS "%-20s", " valid types: "); michael@0: for (i=0; i < keyArraySize ; i++) { michael@0: FPS "%s%c", keyArray[i].label, i == keyArraySize-1? '\n':','); michael@0: } michael@0: FPS "%-20s Specify the nickname of the wrapping key\n", michael@0: " -w wrap name"); michael@0: FPS "%-20s Specify the id in hex of the wrapping key\n", michael@0: " -x wrap key id"); michael@0: FPS "%-20s Specify a file to read the id of the wrapping key\n", michael@0: " -y wrap key id file"); michael@0: FPS "%-15s Wrap a new key to a data file. [not yet implemented]\n", "-W"); michael@0: FPS "%-20s Specify the data file to write the encrypted key to.\n", michael@0: " -k key file"); michael@0: FPS "%-20s Specify the nickname of the key to wrap\n", michael@0: " -n name"); michael@0: FPS "%-20s Specify the id in hex of the key to wrap\n", michael@0: " -i key id"); michael@0: FPS "%-20s Specify a file to read the id of the key to wrap\n", michael@0: " -j key id file"); michael@0: FPS "%-20s Specify the nickname of the wrapping key\n", michael@0: " -w wrap name"); michael@0: FPS "%-20s Specify the id in hex of the wrapping key\n", michael@0: " -x wrap key id"); michael@0: FPS "%-20s Specify a file to read the id of the wrapping key\n", michael@0: " -y wrap key id file"); michael@0: FPS "%-15s Options valid for all commands\n", "std_opts"); michael@0: FPS "%-20s The directory where the NSS db's reside\n", michael@0: " -d certdir"); michael@0: FPS "%-20s Prefix for the NSS db's\n", michael@0: " -P db prefix"); michael@0: FPS "%-20s Specify password on the command line\n", michael@0: " -p password"); michael@0: FPS "%-20s Specify password file on the command line\n", michael@0: " -f password file"); michael@0: FPS "%-20s Specify token to act on\n", michael@0: " -h token"); michael@0: exit(1); michael@0: #undef FPS michael@0: } michael@0: michael@0: /* Certutil commands */ michael@0: enum { michael@0: cmd_CreateNewKey = 0, michael@0: cmd_DeleteKey, michael@0: cmd_ImportKey, michael@0: cmd_ExportKey, michael@0: cmd_WrapKey, michael@0: cmd_UnwrapKey, michael@0: cmd_MoveKey, michael@0: cmd_ListKeys, michael@0: cmd_PrintHelp michael@0: }; michael@0: michael@0: /* Certutil options */ michael@0: enum { michael@0: opt_CertDir = 0, michael@0: opt_PasswordFile, michael@0: opt_TargetToken, michael@0: opt_TokenName, michael@0: opt_KeyID, michael@0: opt_KeyIDFile, michael@0: opt_KeyType, michael@0: opt_Nickname, michael@0: opt_KeyFile, michael@0: opt_Password, michael@0: opt_dbPrefix, michael@0: opt_RW, michael@0: opt_KeySize, michael@0: opt_WrapKeyName, michael@0: opt_WrapKeyID, michael@0: opt_WrapKeyIDFile, michael@0: opt_NoiseFile michael@0: }; michael@0: michael@0: static secuCommandFlag symKeyUtil_commands[] = michael@0: { michael@0: { /* cmd_CreateNewKey */ 'K', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_DeleteKey */ 'D', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_ImportKey */ 'I', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_ExportKey */ 'E', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_WrapKey */ 'W', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_UnwrapKey */ 'U', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_MoveKey */ 'M', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_ListKeys */ 'L', PR_FALSE, 0, PR_FALSE }, michael@0: { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE }, michael@0: }; michael@0: michael@0: static secuCommandFlag symKeyUtil_options[] = michael@0: { michael@0: { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_TargetToken */ 'g', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_KeyID */ 'i', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_KeyIDFile */ 'j', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_KeyType */ 't', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_KeyFile */ 'k', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_Password */ 'p', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_dbPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_RW */ 'r', PR_FALSE, 0, PR_FALSE }, michael@0: { /* opt_KeySize */ 's', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_WrapKeyName */ 'w', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_WrapKeyID */ 'x', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_WrapKeyIDFile */ 'y', PR_TRUE, 0, PR_FALSE }, michael@0: { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE }, michael@0: }; michael@0: michael@0: int michael@0: main(int argc, char **argv) michael@0: { michael@0: PK11SlotInfo *slot = NULL; michael@0: char * slotname = "internal"; michael@0: char * certPrefix = ""; michael@0: CK_MECHANISM_TYPE keyType = CKM_SHA_1_HMAC; michael@0: int keySize = 0; michael@0: char * name = NULL; michael@0: char * wrapName = NULL; michael@0: secuPWData pwdata = { PW_NONE, 0 }; michael@0: PRBool readOnly = PR_FALSE; michael@0: SECItem key; michael@0: SECItem keyID; michael@0: SECItem wrapKeyID; michael@0: int commandsEntered = 0; michael@0: int commandToRun = 0; michael@0: char *progName; michael@0: int i; michael@0: SECStatus rv = SECFailure; michael@0: michael@0: secuCommand symKeyUtil; michael@0: symKeyUtil.numCommands=sizeof(symKeyUtil_commands)/sizeof(secuCommandFlag); michael@0: symKeyUtil.numOptions=sizeof(symKeyUtil_options)/sizeof(secuCommandFlag); michael@0: symKeyUtil.commands = symKeyUtil_commands; michael@0: symKeyUtil.options = symKeyUtil_options; michael@0: michael@0: key.data = NULL; key.len = 0; michael@0: keyID.data = NULL; keyID.len = 0; michael@0: wrapKeyID.data = NULL; wrapKeyID.len = 0; michael@0: michael@0: progName = strrchr(argv[0], '/'); michael@0: progName = progName ? progName+1 : argv[0]; michael@0: michael@0: rv = SECU_ParseCommandLine(argc, argv, progName, &symKeyUtil); michael@0: michael@0: if (rv != SECSuccess) michael@0: Usage(progName); michael@0: michael@0: rv = SECFailure; michael@0: michael@0: /* -H print help */ michael@0: if (symKeyUtil.commands[cmd_PrintHelp].activated) michael@0: LongUsage(progName); michael@0: michael@0: /* -f password file, -p password */ michael@0: if (symKeyUtil.options[opt_PasswordFile].arg) { michael@0: pwdata.source = PW_FROMFILE; michael@0: pwdata.data = symKeyUtil.options[opt_PasswordFile].arg; michael@0: } else if (symKeyUtil.options[opt_Password].arg) { michael@0: pwdata.source = PW_PLAINTEXT; michael@0: pwdata.data = symKeyUtil.options[opt_Password].arg; michael@0: } michael@0: michael@0: /* -d directory */ michael@0: if (symKeyUtil.options[opt_CertDir].activated) michael@0: SECU_ConfigDirectory(symKeyUtil.options[opt_CertDir].arg); michael@0: michael@0: /* -s key size */ michael@0: if (symKeyUtil.options[opt_KeySize].activated) { michael@0: keySize = PORT_Atoi(symKeyUtil.options[opt_KeySize].arg); michael@0: } michael@0: michael@0: /* -h specify token name */ michael@0: if (symKeyUtil.options[opt_TokenName].activated) { michael@0: if (PL_strcmp(symKeyUtil.options[opt_TokenName].arg, "all") == 0) michael@0: slotname = NULL; michael@0: else michael@0: slotname = PL_strdup(symKeyUtil.options[opt_TokenName].arg); michael@0: } michael@0: michael@0: /* -t key type */ michael@0: if (symKeyUtil.options[opt_KeyType].activated) { michael@0: keyType = GetKeyMechFromString(symKeyUtil.options[opt_KeyType].arg); michael@0: if (keyType == (CK_MECHANISM_TYPE)-1) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s unknown key type (%s).\n", michael@0: progName, symKeyUtil.options[opt_KeyType].arg); michael@0: return 255; michael@0: } michael@0: } michael@0: michael@0: /* -k for import and unwrap, it specifies an input file to read from, michael@0: * for export and wrap it specifies an output file to write to */ michael@0: if (symKeyUtil.options[opt_KeyFile].activated) { michael@0: if (symKeyUtil.commands[cmd_ImportKey].activated || michael@0: symKeyUtil.commands[cmd_UnwrapKey].activated ) { michael@0: int ret = ReadBuf(symKeyUtil.options[opt_KeyFile].arg, &key); michael@0: if (ret < 0) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s Couldn't read key file (%s).\n", michael@0: progName, symKeyUtil.options[opt_KeyFile].arg); michael@0: return 255; michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* -i specify the key ID */ michael@0: if (symKeyUtil.options[opt_KeyID].activated) { michael@0: int ret = HexToBuf(symKeyUtil.options[opt_KeyID].arg, &keyID); michael@0: if (ret < 0) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s invalid key ID (%s).\n", michael@0: progName, symKeyUtil.options[opt_KeyID].arg); michael@0: return 255; michael@0: } michael@0: } michael@0: michael@0: /* -i & -j are mutually exclusive */ michael@0: if ((symKeyUtil.options[opt_KeyID].activated) && michael@0: (symKeyUtil.options[opt_KeyIDFile].activated)) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -i and -j options are mutually exclusive.\n", progName); michael@0: return 255; michael@0: } michael@0: michael@0: /* -x specify the Wrap key ID */ michael@0: if (symKeyUtil.options[opt_WrapKeyID].activated) { michael@0: int ret = HexToBuf(symKeyUtil.options[opt_WrapKeyID].arg, &wrapKeyID); michael@0: if (ret < 0) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s invalid key ID (%s).\n", michael@0: progName, symKeyUtil.options[opt_WrapKeyID].arg); michael@0: return 255; michael@0: } michael@0: } michael@0: michael@0: /* -x & -y are mutually exclusive */ michael@0: if ((symKeyUtil.options[opt_KeyID].activated) && michael@0: (symKeyUtil.options[opt_KeyIDFile].activated)) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -i and -j options are mutually exclusive.\n", progName); michael@0: return 255; michael@0: } michael@0: michael@0: michael@0: /* -y specify the key ID */ michael@0: if (symKeyUtil.options[opt_WrapKeyIDFile].activated) { michael@0: int ret = ReadBuf(symKeyUtil.options[opt_WrapKeyIDFile].arg, michael@0: &wrapKeyID); michael@0: if (ret < 0) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s Couldn't read key ID file (%s).\n", michael@0: progName, symKeyUtil.options[opt_WrapKeyIDFile].arg); michael@0: return 255; michael@0: } michael@0: } michael@0: michael@0: /* -P certdb name prefix */ michael@0: if (symKeyUtil.options[opt_dbPrefix].activated) michael@0: certPrefix = symKeyUtil.options[opt_dbPrefix].arg; michael@0: michael@0: /* Check number of commands entered. */ michael@0: commandsEntered = 0; michael@0: for (i=0; i< symKeyUtil.numCommands; i++) { michael@0: if (symKeyUtil.commands[i].activated) { michael@0: commandToRun = symKeyUtil.commands[i].flag; michael@0: commandsEntered++; michael@0: } michael@0: if (commandsEntered > 1) michael@0: break; michael@0: } michael@0: if (commandsEntered > 1) { michael@0: PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName); michael@0: PR_fprintf(PR_STDERR, "You entered: "); michael@0: for (i=0; i< symKeyUtil.numCommands; i++) { michael@0: if (symKeyUtil.commands[i].activated) michael@0: PR_fprintf(PR_STDERR, " -%c", symKeyUtil.commands[i].flag); michael@0: } michael@0: PR_fprintf(PR_STDERR, "\n"); michael@0: return 255; michael@0: } michael@0: if (commandsEntered == 0) { michael@0: PR_fprintf(PR_STDERR, "%s: you must enter a command!\n", progName); michael@0: Usage(progName); michael@0: } michael@0: michael@0: if (symKeyUtil.commands[cmd_ListKeys].activated || michael@0: symKeyUtil.commands[cmd_PrintHelp].activated || michael@0: symKeyUtil.commands[cmd_ExportKey].activated || michael@0: symKeyUtil.commands[cmd_WrapKey].activated) { michael@0: readOnly = !symKeyUtil.options[opt_RW].activated; michael@0: } michael@0: michael@0: if ((symKeyUtil.commands[cmd_ImportKey].activated || michael@0: symKeyUtil.commands[cmd_ExportKey].activated || michael@0: symKeyUtil.commands[cmd_WrapKey].activated || michael@0: symKeyUtil.commands[cmd_UnwrapKey].activated ) && michael@0: !symKeyUtil.options[opt_KeyFile].activated) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -%c: keyfile is required for this command (-k).\n", michael@0: progName, commandToRun); michael@0: return 255; michael@0: } michael@0: michael@0: /* -E, -D, -W, and all require -n, -i, or -j to identify the key */ michael@0: if ((symKeyUtil.commands[cmd_ExportKey].activated || michael@0: symKeyUtil.commands[cmd_DeleteKey].activated || michael@0: symKeyUtil.commands[cmd_WrapKey].activated) && michael@0: !(symKeyUtil.options[opt_Nickname].activated || michael@0: symKeyUtil.options[opt_KeyID].activated || michael@0: symKeyUtil.options[opt_KeyIDFile].activated)) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -%c: nickname or id is required for this command (-n, -i, -j).\n", michael@0: progName, commandToRun); michael@0: return 255; michael@0: } michael@0: michael@0: /* -W, -U, and all -w, -x, or -y to identify the wrapping key */ michael@0: if (( symKeyUtil.commands[cmd_WrapKey].activated || michael@0: symKeyUtil.commands[cmd_UnwrapKey].activated) && michael@0: !(symKeyUtil.options[opt_WrapKeyName].activated || michael@0: symKeyUtil.options[opt_WrapKeyID].activated || michael@0: symKeyUtil.options[opt_WrapKeyIDFile].activated)) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -%c: wrap key is required for this command (-w, -x, or -y).\n", michael@0: progName, commandToRun); michael@0: return 255; michael@0: } michael@0: michael@0: /* -M needs the target slot (-g) */ michael@0: if (symKeyUtil.commands[cmd_MoveKey].activated && michael@0: !symKeyUtil.options[opt_TargetToken].activated) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -%c: target token is required for this command (-g).\n", michael@0: progName, commandToRun); michael@0: return 255; michael@0: } michael@0: michael@0: /* Using slotname == NULL for listing keys and certs on all slots, michael@0: * but only that. */ michael@0: if (!(symKeyUtil.commands[cmd_ListKeys].activated) && slotname == NULL) { michael@0: PR_fprintf(PR_STDERR, michael@0: "%s -%c: cannot use \"-h all\" for this command.\n", michael@0: progName, commandToRun); michael@0: return 255; michael@0: } michael@0: michael@0: name = SECU_GetOptionArg(&symKeyUtil, opt_Nickname); michael@0: wrapName = SECU_GetOptionArg(&symKeyUtil, opt_WrapKeyName); michael@0: michael@0: PK11_SetPasswordFunc(SECU_GetModulePassword); michael@0: michael@0: /* Initialize NSPR and NSS. */ michael@0: PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); michael@0: rv = NSS_Initialize(SECU_ConfigDirectory(NULL), certPrefix, certPrefix, michael@0: "secmod.db", readOnly ? NSS_INIT_READONLY: 0); michael@0: if (rv != SECSuccess) { michael@0: SECU_PrintPRandOSError(progName); michael@0: goto shutdown; michael@0: } michael@0: rv = SECFailure; michael@0: michael@0: if (PL_strcmp(slotname, "internal") == 0) michael@0: slot = PK11_GetInternalKeySlot(); michael@0: else if (slotname != NULL) michael@0: slot = PK11_FindSlotByName(slotname); michael@0: michael@0: /* generating a new key */ michael@0: if (symKeyUtil.commands[cmd_CreateNewKey].activated) { michael@0: PK11SymKey *symKey; michael@0: michael@0: symKey = PK11_TokenKeyGen(slot, keyType, NULL, keySize, michael@0: NULL, PR_TRUE, &pwdata); michael@0: if (!symKey) { michael@0: PR_fprintf(PR_STDERR, "%s: Token Key Gen Failed\n", progName); michael@0: goto shutdown; michael@0: } michael@0: if (symKeyUtil.options[opt_Nickname].activated) { michael@0: rv = PK11_SetSymKeyNickname(symKey, name); michael@0: if (rv != SECSuccess) { michael@0: PK11_DeleteTokenSymKey(symKey); michael@0: PK11_FreeSymKey(symKey); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n", michael@0: progName); michael@0: goto shutdown; michael@0: } michael@0: } michael@0: rv = SECSuccess; michael@0: PrintKey(symKey); michael@0: PK11_FreeSymKey(symKey); michael@0: } michael@0: if (symKeyUtil.commands[cmd_DeleteKey].activated) { michael@0: PK11SymKey *symKey = FindKey(slot,name,&keyID,&pwdata); michael@0: michael@0: if (!symKey) { michael@0: char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: goto shutdown; michael@0: } michael@0: michael@0: rv = PK11_DeleteTokenSymKey(symKey); michael@0: FreeKeyList(symKey); michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't Delete Key \n", progName); michael@0: goto shutdown; michael@0: } michael@0: } michael@0: if (symKeyUtil.commands[cmd_UnwrapKey].activated) { michael@0: PK11SymKey *wrapKey = FindKey(slot,wrapName,&wrapKeyID,&pwdata); michael@0: PK11SymKey *symKey; michael@0: CK_MECHANISM_TYPE mechanism; michael@0: michael@0: if (!wrapKey) { michael@0: char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) michael@0: : PORT_Strdup(wrapName); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: goto shutdown; michael@0: } michael@0: mechanism = GetWrapMechanism(wrapKey); michael@0: if (mechanism == CKM_INVALID_MECHANISM) { michael@0: char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) michael@0: : PORT_Strdup(wrapName); michael@0: PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: PK11_FreeSymKey(wrapKey); michael@0: goto shutdown; michael@0: } michael@0: michael@0: symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrapKey, mechanism, NULL, michael@0: &key, keyType, CKA_ENCRYPT, keySize, 0, PR_TRUE); michael@0: PK11_FreeSymKey(wrapKey); michael@0: if (!symKey) { michael@0: PR_fprintf(PR_STDERR, "%s: Unwrap Key Failed\n", progName); michael@0: goto shutdown; michael@0: } michael@0: michael@0: if (symKeyUtil.options[opt_Nickname].activated) { michael@0: rv = PK11_SetSymKeyNickname(symKey, name); michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n", michael@0: progName); michael@0: PK11_DeleteTokenSymKey(symKey); michael@0: PK11_FreeSymKey(symKey); michael@0: goto shutdown; michael@0: } michael@0: } michael@0: rv = SECSuccess; michael@0: PrintKey(symKey); michael@0: PK11_FreeSymKey(symKey); michael@0: } michael@0: michael@0: #define MAX_KEY_SIZE 4098 michael@0: if (symKeyUtil.commands[cmd_WrapKey].activated) { michael@0: PK11SymKey *symKey = FindKey(slot, name, &keyID, &pwdata); michael@0: PK11SymKey *wrapKey; michael@0: CK_MECHANISM_TYPE mechanism; michael@0: SECItem data; michael@0: unsigned char buf[MAX_KEY_SIZE]; michael@0: int ret; michael@0: michael@0: if (!symKey) { michael@0: char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: goto shutdown; michael@0: } michael@0: michael@0: wrapKey = FindKey(slot, wrapName, &wrapKeyID, &pwdata); michael@0: if (!wrapKey) { michael@0: char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) michael@0: : PORT_Strdup(wrapName); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: PK11_FreeSymKey(symKey); michael@0: goto shutdown; michael@0: } michael@0: michael@0: mechanism = GetWrapMechanism(wrapKey); michael@0: if (mechanism == CKM_INVALID_MECHANISM) { michael@0: char *keyName = wrapKeyID.data ? BufToHex(&wrapKeyID) michael@0: : PORT_Strdup(wrapName); michael@0: PR_fprintf(PR_STDERR, "%s: %s on %s is an invalid wrapping key\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: PK11_FreeSymKey(symKey); michael@0: PK11_FreeSymKey(wrapKey); michael@0: goto shutdown; michael@0: } michael@0: michael@0: data.data = buf; michael@0: data.len = sizeof(buf); michael@0: rv = PK11_WrapSymKey(mechanism, NULL, wrapKey, symKey, &data); michael@0: PK11_FreeSymKey(symKey); michael@0: PK11_FreeSymKey(wrapKey); michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't wrap key\n",progName); michael@0: goto shutdown; michael@0: } michael@0: michael@0: /* WriteBuf outputs it's own error using SECU_PrintError */ michael@0: ret = WriteBuf(symKeyUtil.options[opt_KeyFile].arg, &data); michael@0: if (ret < 0) { michael@0: goto shutdown; michael@0: } michael@0: } michael@0: michael@0: if (symKeyUtil.commands[cmd_ImportKey].activated) { michael@0: PK11SymKey *symKey = PK11_ImportSymKey(slot, keyType, michael@0: PK11_OriginUnwrap, CKA_ENCRYPT, &key,&pwdata); michael@0: if (!symKey) { michael@0: PR_fprintf(PR_STDERR, "%s: Import Key Failed\n", progName); michael@0: goto shutdown; michael@0: } michael@0: if (symKeyUtil.options[opt_Nickname].activated) { michael@0: rv = PK11_SetSymKeyNickname(symKey, name); michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't set name on key\n", michael@0: progName); michael@0: PK11_DeleteTokenSymKey(symKey); michael@0: PK11_FreeSymKey(symKey); michael@0: goto shutdown; michael@0: } michael@0: } michael@0: rv = SECSuccess; michael@0: PrintKey(symKey); michael@0: PK11_FreeSymKey(symKey); michael@0: } michael@0: michael@0: /* List certs (-L) */ michael@0: if (symKeyUtil.commands[cmd_ListKeys].activated) { michael@0: int printLabel = 1; michael@0: if (slot) { michael@0: rv = ListKeys(slot,&printLabel,&pwdata); michael@0: } else { michael@0: /* loop over all the slots */ michael@0: PK11SlotList *slotList = PK11_GetAllTokens(CKM_INVALID_MECHANISM, michael@0: PR_FALSE, PR_FALSE, &pwdata); michael@0: if (slotList == NULL) { michael@0: PR_fprintf(PR_STDERR, "%s: No tokens found\n",progName); michael@0: } else { michael@0: PK11SlotListElement *se; michael@0: for (se = PK11_GetFirstSafe(slotList); se; michael@0: se=PK11_GetNextSafe(slotList,se, PR_FALSE)) { michael@0: rv = ListKeys(se->slot,&printLabel,&pwdata); michael@0: if (rv !=SECSuccess) { michael@0: break; michael@0: } michael@0: } michael@0: if (se) { michael@0: SECStatus rv2 = PK11_FreeSlotListElement(slotList, se); michael@0: PORT_Assert(SECSuccess == rv2); michael@0: } michael@0: PK11_FreeSlotList(slotList); michael@0: } michael@0: } michael@0: } michael@0: michael@0: /* Move key (-M) */ michael@0: if (symKeyUtil.commands[cmd_MoveKey].activated) { michael@0: PK11SlotInfo *target; michael@0: char *targetName = symKeyUtil.options[opt_TargetToken].arg; michael@0: PK11SymKey *newKey; michael@0: PK11SymKey *symKey = FindKey(slot,name,&keyID,&pwdata); michael@0: char *keyName = PK11_GetSymKeyNickname(symKey); michael@0: michael@0: if (!symKey) { michael@0: char *keyName = keyID.data ? BufToHex(&keyID) : PORT_Strdup(name); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't find key %s on %s\n", michael@0: progName, keyName, PK11_GetTokenName(slot)); michael@0: PORT_Free(keyName); michael@0: goto shutdown; michael@0: } michael@0: target = PK11_FindSlotByName(targetName); michael@0: if (!target) { michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't find slot %s\n", michael@0: progName, targetName); michael@0: goto shutdown; michael@0: } michael@0: rv = PK11_Authenticate(target, PR_FALSE, &pwdata); michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(PR_STDERR, "%s: Failed to log into %s\n", michael@0: progName, targetName); michael@0: goto shutdown; michael@0: } michael@0: rv = SECFailure; michael@0: newKey = PK11_MoveSymKey(target, CKA_ENCRYPT, 0, PR_TRUE, symKey); michael@0: if (!newKey) { michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't move the key \n",progName); michael@0: goto shutdown; michael@0: } michael@0: if (keyName) { michael@0: rv = PK11_SetSymKeyNickname(newKey, keyName); michael@0: if (rv != SECSuccess) { michael@0: PK11_DeleteTokenSymKey(newKey); michael@0: PK11_FreeSymKey(newKey); michael@0: PR_fprintf(PR_STDERR, "%s: Couldn't set nickname on key\n", michael@0: progName); michael@0: goto shutdown; michael@0: } michael@0: } michael@0: PK11_FreeSymKey(newKey); michael@0: rv = SECSuccess; michael@0: } michael@0: michael@0: shutdown: michael@0: if (rv != SECSuccess) { michael@0: PR_fprintf(PR_STDERR, "%s: %s\n", progName, michael@0: SECU_Strerror(PORT_GetError())); michael@0: } michael@0: michael@0: if (key.data) { michael@0: PORT_Free(key.data); michael@0: } michael@0: michael@0: if (keyID.data) { michael@0: PORT_Free(keyID.data); michael@0: } michael@0: michael@0: if (slot) { michael@0: PK11_FreeSlot(slot); michael@0: } michael@0: michael@0: if (NSS_Shutdown() != SECSuccess) { michael@0: exit(1); michael@0: } michael@0: michael@0: if (rv == SECSuccess) { michael@0: return 0; michael@0: } else { michael@0: return 255; michael@0: } michael@0: } michael@0: michael@0: michael@0: