/security/nss/cmd/symkeyutil/symkeyutil.c

http://github.com/zpao/v8monkey · C · 1135 lines · 942 code · 111 blank · 82 comment · 170 complexity · 74edd309e078e3f93db62f91a1badf90 MD5 · raw file

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