/security/nss/cmd/shlibsign/shlibsign.c

http://github.com/zpao/v8monkey · C · 1123 lines · 916 code · 107 blank · 100 comment · 159 complexity · ffdb2df87dcf4f448496e8e598f8550d 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. * shlibsign creates the checksum (.chk) files for the NSS libraries,
  38. * libsoftokn3/softokn3 and libfreebl/freebl (platforms can have
  39. * multiple freebl variants), that contain the NSS cryptograhic boundary.
  40. *
  41. * The generated .chk files must be put in the same directory as
  42. * the NSS libraries they were generated for.
  43. *
  44. * When in FIPS 140 mode, the NSS Internal FIPS PKCS #11 Module will
  45. * compute the checksum for the NSS cryptographic boundary libraries
  46. * and compare the checksum with the value in .chk file.
  47. *
  48. * $Id: shlibsign.c,v 1.19 2011/04/08 04:02:53 wtc%google.com Exp $
  49. */
  50. #ifdef XP_UNIX
  51. #define USES_LINKS 1
  52. #endif
  53. #include <assert.h>
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #include <string.h>
  57. #include <stdarg.h>
  58. #ifdef USES_LINKS
  59. #include <unistd.h>
  60. #include <sys/param.h>
  61. #include <sys/types.h>
  62. #include <sys/stat.h>
  63. #endif
  64. /* nspr headers */
  65. #include "prlink.h"
  66. #include "prprf.h"
  67. #include "prenv.h"
  68. #include "plgetopt.h"
  69. #include "prinit.h"
  70. #include "prmem.h"
  71. #include "plstr.h"
  72. #include "prerror.h"
  73. /* softoken headers */
  74. #include "pkcs11.h"
  75. #include "pkcs11t.h"
  76. /* freebl headers */
  77. #include "shsign.h"
  78. #define NUM_ELEM(array) (sizeof(array)/sizeof(array[0]))
  79. CK_BBOOL true = CK_TRUE;
  80. CK_BBOOL false = CK_FALSE;
  81. static PRBool verbose = PR_FALSE;
  82. static void
  83. usage (const char *program_name)
  84. {
  85. PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
  86. PR_fprintf (debug_out,
  87. "type %s -H for more detail information.\n", program_name);
  88. PR_fprintf (debug_out,
  89. "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n"
  90. " [-F] [-p pwd] -[P dbprefix ] "
  91. "-i shared_library_name\n",
  92. program_name);
  93. exit(1);
  94. }
  95. static void
  96. long_usage(const char *program_name)
  97. {
  98. PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
  99. PR_fprintf(debug_out, "%s test program usage:\n", program_name);
  100. PR_fprintf(debug_out, "\t-i <infile> shared_library_name to process\n");
  101. PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
  102. PR_fprintf(debug_out, "\t-d <path> database path location\n");
  103. PR_fprintf(debug_out, "\t-P <prefix> database prefix\n");
  104. PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n");
  105. PR_fprintf(debug_out, "\t-F FIPS mode\n");
  106. PR_fprintf(debug_out, "\t-p <pwd> password\n");
  107. PR_fprintf(debug_out, "\t-v verbose output\n");
  108. PR_fprintf(debug_out, "\t-V perform Verify operations\n");
  109. PR_fprintf(debug_out, "\t-? short help message\n");
  110. PR_fprintf(debug_out, "\t-h short help message\n");
  111. PR_fprintf(debug_out, "\t-H this help message\n");
  112. PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your ");
  113. PR_fprintf(debug_out, "library path is using \n");
  114. PR_fprintf(debug_out, "\t pre-existing libraries with generated ");
  115. PR_fprintf(debug_out, "checksum files\n");
  116. PR_fprintf(debug_out, "\t and database in FIPS mode \n");
  117. exit(1);
  118. }
  119. static char *
  120. mkoutput(const char *input)
  121. {
  122. int in_len = strlen(input);
  123. char *output = PR_Malloc(in_len+sizeof(SGN_SUFFIX));
  124. int index = in_len + 1 - sizeof("."SHLIB_SUFFIX);
  125. if ((index > 0) &&
  126. (PL_strncmp(&input[index],
  127. "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
  128. in_len = index;
  129. }
  130. memcpy(output,input,in_len);
  131. memcpy(&output[in_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
  132. return output;
  133. }
  134. static void
  135. lperror(const char *string) {
  136. PRErrorCode errorcode;
  137. errorcode = PR_GetError();
  138. PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode,
  139. PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
  140. }
  141. static void
  142. encodeInt(unsigned char *buf, int val)
  143. {
  144. buf[3] = (val >> 0) & 0xff;
  145. buf[2] = (val >> 8) & 0xff;
  146. buf[1] = (val >> 16) & 0xff;
  147. buf[0] = (val >> 24) & 0xff;
  148. return;
  149. }
  150. static PRStatus
  151. writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
  152. CK_ULONG ulValueLen, char *file)
  153. {
  154. unsigned char buf[4];
  155. int bytesWritten;
  156. if (ulValueLen == 0) {
  157. PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n");
  158. return PR_FAILURE;
  159. }
  160. encodeInt(buf,ulValueLen);
  161. bytesWritten = PR_Write(fd,buf, 4);
  162. if (bytesWritten != 4) {
  163. lperror(file);
  164. return PR_FAILURE;
  165. }
  166. bytesWritten = PR_Write(fd, pValue, ulValueLen);
  167. if (bytesWritten != ulValueLen) {
  168. lperror(file);
  169. return PR_FAILURE;
  170. }
  171. return PR_SUCCESS;
  172. }
  173. static const unsigned char prime[] = { 0x00,
  174. 0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d,
  175. 0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92,
  176. 0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7,
  177. 0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c,
  178. 0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44,
  179. 0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8,
  180. 0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69,
  181. 0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb,
  182. 0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5,
  183. 0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd,
  184. 0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77,
  185. 0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd,
  186. 0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d,
  187. 0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2,
  188. 0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77,
  189. 0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 };
  190. static const unsigned char subprime[] = { 0x0,
  191. 0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5,
  192. 0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54,
  193. 0x0b, 0x31, 0x24, 0xf1 };
  194. static const unsigned char base[] = {
  195. 0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a,
  196. 0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11,
  197. 0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23,
  198. 0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42,
  199. 0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1,
  200. 0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f,
  201. 0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f,
  202. 0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa,
  203. 0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc,
  204. 0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1,
  205. 0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18,
  206. 0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8,
  207. 0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d,
  208. 0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc,
  209. 0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36,
  210. 0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f };
  211. static const unsigned char h[] = {
  212. 0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac,
  213. 0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6,
  214. 0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f,
  215. 0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67,
  216. 0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29,
  217. 0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd,
  218. 0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13,
  219. 0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5,
  220. 0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f,
  221. 0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2,
  222. 0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6,
  223. 0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32,
  224. 0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23,
  225. 0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9,
  226. 0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7,
  227. 0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c };
  228. static const unsigned char seed[] = { 0x00,
  229. 0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68,
  230. 0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed,
  231. 0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85,
  232. 0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b,
  233. 0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d,
  234. 0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83,
  235. 0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2,
  236. 0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4,
  237. 0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00,
  238. 0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3,
  239. 0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36,
  240. 0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e,
  241. 0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2,
  242. 0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe,
  243. 0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc,
  244. 0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c };
  245. static const unsigned int counter=1496;
  246. struct tuple_str {
  247. CK_RV errNum;
  248. const char * errString;
  249. };
  250. typedef struct tuple_str tuple_str;
  251. static const tuple_str errStrings[] = {
  252. {CKR_OK , "CKR_OK "},
  253. {CKR_CANCEL , "CKR_CANCEL "},
  254. {CKR_HOST_MEMORY , "CKR_HOST_MEMORY "},
  255. {CKR_SLOT_ID_INVALID , "CKR_SLOT_ID_INVALID "},
  256. {CKR_GENERAL_ERROR , "CKR_GENERAL_ERROR "},
  257. {CKR_FUNCTION_FAILED , "CKR_FUNCTION_FAILED "},
  258. {CKR_ARGUMENTS_BAD , "CKR_ARGUMENTS_BAD "},
  259. {CKR_NO_EVENT , "CKR_NO_EVENT "},
  260. {CKR_NEED_TO_CREATE_THREADS , "CKR_NEED_TO_CREATE_THREADS "},
  261. {CKR_CANT_LOCK , "CKR_CANT_LOCK "},
  262. {CKR_ATTRIBUTE_READ_ONLY , "CKR_ATTRIBUTE_READ_ONLY "},
  263. {CKR_ATTRIBUTE_SENSITIVE , "CKR_ATTRIBUTE_SENSITIVE "},
  264. {CKR_ATTRIBUTE_TYPE_INVALID , "CKR_ATTRIBUTE_TYPE_INVALID "},
  265. {CKR_ATTRIBUTE_VALUE_INVALID , "CKR_ATTRIBUTE_VALUE_INVALID "},
  266. {CKR_DATA_INVALID , "CKR_DATA_INVALID "},
  267. {CKR_DATA_LEN_RANGE , "CKR_DATA_LEN_RANGE "},
  268. {CKR_DEVICE_ERROR , "CKR_DEVICE_ERROR "},
  269. {CKR_DEVICE_MEMORY , "CKR_DEVICE_MEMORY "},
  270. {CKR_DEVICE_REMOVED , "CKR_DEVICE_REMOVED "},
  271. {CKR_ENCRYPTED_DATA_INVALID , "CKR_ENCRYPTED_DATA_INVALID "},
  272. {CKR_ENCRYPTED_DATA_LEN_RANGE , "CKR_ENCRYPTED_DATA_LEN_RANGE "},
  273. {CKR_FUNCTION_CANCELED , "CKR_FUNCTION_CANCELED "},
  274. {CKR_FUNCTION_NOT_PARALLEL , "CKR_FUNCTION_NOT_PARALLEL "},
  275. {CKR_FUNCTION_NOT_SUPPORTED , "CKR_FUNCTION_NOT_SUPPORTED "},
  276. {CKR_KEY_HANDLE_INVALID , "CKR_KEY_HANDLE_INVALID "},
  277. {CKR_KEY_SIZE_RANGE , "CKR_KEY_SIZE_RANGE "},
  278. {CKR_KEY_TYPE_INCONSISTENT , "CKR_KEY_TYPE_INCONSISTENT "},
  279. {CKR_KEY_NOT_NEEDED , "CKR_KEY_NOT_NEEDED "},
  280. {CKR_KEY_CHANGED , "CKR_KEY_CHANGED "},
  281. {CKR_KEY_NEEDED , "CKR_KEY_NEEDED "},
  282. {CKR_KEY_INDIGESTIBLE , "CKR_KEY_INDIGESTIBLE "},
  283. {CKR_KEY_FUNCTION_NOT_PERMITTED , "CKR_KEY_FUNCTION_NOT_PERMITTED "},
  284. {CKR_KEY_NOT_WRAPPABLE , "CKR_KEY_NOT_WRAPPABLE "},
  285. {CKR_KEY_UNEXTRACTABLE , "CKR_KEY_UNEXTRACTABLE "},
  286. {CKR_MECHANISM_INVALID , "CKR_MECHANISM_INVALID "},
  287. {CKR_MECHANISM_PARAM_INVALID , "CKR_MECHANISM_PARAM_INVALID "},
  288. {CKR_OBJECT_HANDLE_INVALID , "CKR_OBJECT_HANDLE_INVALID "},
  289. {CKR_OPERATION_ACTIVE , "CKR_OPERATION_ACTIVE "},
  290. {CKR_OPERATION_NOT_INITIALIZED , "CKR_OPERATION_NOT_INITIALIZED "},
  291. {CKR_PIN_INCORRECT , "CKR_PIN_INCORRECT "},
  292. {CKR_PIN_INVALID , "CKR_PIN_INVALID "},
  293. {CKR_PIN_LEN_RANGE , "CKR_PIN_LEN_RANGE "},
  294. {CKR_PIN_EXPIRED , "CKR_PIN_EXPIRED "},
  295. {CKR_PIN_LOCKED , "CKR_PIN_LOCKED "},
  296. {CKR_SESSION_CLOSED , "CKR_SESSION_CLOSED "},
  297. {CKR_SESSION_COUNT , "CKR_SESSION_COUNT "},
  298. {CKR_SESSION_HANDLE_INVALID , "CKR_SESSION_HANDLE_INVALID "},
  299. {CKR_SESSION_PARALLEL_NOT_SUPPORTED , "CKR_SESSION_PARALLEL_NOT_SUPPORTED "},
  300. {CKR_SESSION_READ_ONLY , "CKR_SESSION_READ_ONLY "},
  301. {CKR_SESSION_EXISTS , "CKR_SESSION_EXISTS "},
  302. {CKR_SESSION_READ_ONLY_EXISTS , "CKR_SESSION_READ_ONLY_EXISTS "},
  303. {CKR_SESSION_READ_WRITE_SO_EXISTS , "CKR_SESSION_READ_WRITE_SO_EXISTS "},
  304. {CKR_SIGNATURE_INVALID , "CKR_SIGNATURE_INVALID "},
  305. {CKR_SIGNATURE_LEN_RANGE , "CKR_SIGNATURE_LEN_RANGE "},
  306. {CKR_TEMPLATE_INCOMPLETE , "CKR_TEMPLATE_INCOMPLETE "},
  307. {CKR_TEMPLATE_INCONSISTENT , "CKR_TEMPLATE_INCONSISTENT "},
  308. {CKR_TOKEN_NOT_PRESENT , "CKR_TOKEN_NOT_PRESENT "},
  309. {CKR_TOKEN_NOT_RECOGNIZED , "CKR_TOKEN_NOT_RECOGNIZED "},
  310. {CKR_TOKEN_WRITE_PROTECTED , "CKR_TOKEN_WRITE_PROTECTED "},
  311. {CKR_UNWRAPPING_KEY_HANDLE_INVALID , "CKR_UNWRAPPING_KEY_HANDLE_INVALID "},
  312. {CKR_UNWRAPPING_KEY_SIZE_RANGE , "CKR_UNWRAPPING_KEY_SIZE_RANGE "},
  313. {CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"},
  314. {CKR_USER_ALREADY_LOGGED_IN , "CKR_USER_ALREADY_LOGGED_IN "},
  315. {CKR_USER_NOT_LOGGED_IN , "CKR_USER_NOT_LOGGED_IN "},
  316. {CKR_USER_PIN_NOT_INITIALIZED , "CKR_USER_PIN_NOT_INITIALIZED "},
  317. {CKR_USER_TYPE_INVALID , "CKR_USER_TYPE_INVALID "},
  318. {CKR_USER_ANOTHER_ALREADY_LOGGED_IN , "CKR_USER_ANOTHER_ALREADY_LOGGED_IN "},
  319. {CKR_USER_TOO_MANY_TYPES , "CKR_USER_TOO_MANY_TYPES "},
  320. {CKR_WRAPPED_KEY_INVALID , "CKR_WRAPPED_KEY_INVALID "},
  321. {CKR_WRAPPED_KEY_LEN_RANGE , "CKR_WRAPPED_KEY_LEN_RANGE "},
  322. {CKR_WRAPPING_KEY_HANDLE_INVALID , "CKR_WRAPPING_KEY_HANDLE_INVALID "},
  323. {CKR_WRAPPING_KEY_SIZE_RANGE , "CKR_WRAPPING_KEY_SIZE_RANGE "},
  324. {CKR_WRAPPING_KEY_TYPE_INCONSISTENT , "CKR_WRAPPING_KEY_TYPE_INCONSISTENT "},
  325. {CKR_RANDOM_SEED_NOT_SUPPORTED , "CKR_RANDOM_SEED_NOT_SUPPORTED "},
  326. {CKR_RANDOM_NO_RNG , "CKR_RANDOM_NO_RNG "},
  327. {CKR_DOMAIN_PARAMS_INVALID , "CKR_DOMAIN_PARAMS_INVALID "},
  328. {CKR_BUFFER_TOO_SMALL , "CKR_BUFFER_TOO_SMALL "},
  329. {CKR_SAVED_STATE_INVALID , "CKR_SAVED_STATE_INVALID "},
  330. {CKR_INFORMATION_SENSITIVE , "CKR_INFORMATION_SENSITIVE "},
  331. {CKR_STATE_UNSAVEABLE , "CKR_STATE_UNSAVEABLE "},
  332. {CKR_CRYPTOKI_NOT_INITIALIZED , "CKR_CRYPTOKI_NOT_INITIALIZED "},
  333. {CKR_CRYPTOKI_ALREADY_INITIALIZED , "CKR_CRYPTOKI_ALREADY_INITIALIZED "},
  334. {CKR_MUTEX_BAD , "CKR_MUTEX_BAD "},
  335. {CKR_MUTEX_NOT_LOCKED , "CKR_MUTEX_NOT_LOCKED "},
  336. {CKR_FUNCTION_REJECTED , "CKR_FUNCTION_REJECTED "},
  337. {CKR_VENDOR_DEFINED , "CKR_VENDOR_DEFINED "},
  338. {0xCE534351 , "CKR_NETSCAPE_CERTDB_FAILED "},
  339. {0xCE534352 , "CKR_NETSCAPE_KEYDB_FAILED "}
  340. };
  341. static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str);
  342. /* Returns constant error string for "CRV".
  343. * Returns "unknown error" if errNum is unknown.
  344. */
  345. static const char *
  346. CK_RVtoStr(CK_RV errNum) {
  347. CK_ULONG low = 1;
  348. CK_ULONG high = numStrings - 1;
  349. CK_ULONG i;
  350. CK_RV num;
  351. static int initDone;
  352. /* make sure table is in ascending order.
  353. * binary search depends on it.
  354. */
  355. if (!initDone) {
  356. CK_RV lastNum = CKR_OK;
  357. for (i = low; i <= high; ++i) {
  358. num = errStrings[i].errNum;
  359. if (num <= lastNum) {
  360. PR_fprintf(PR_STDERR,
  361. "sequence error in error strings at item %d\n"
  362. "error %d (%s)\n"
  363. "should come after \n"
  364. "error %d (%s)\n",
  365. (int) i, (int) lastNum, errStrings[i-1].errString,
  366. (int) num, errStrings[i].errString);
  367. }
  368. lastNum = num;
  369. }
  370. initDone = 1;
  371. }
  372. /* Do binary search of table. */
  373. while (low + 1 < high) {
  374. i = (low + high) / 2;
  375. num = errStrings[i].errNum;
  376. if (errNum == num)
  377. return errStrings[i].errString;
  378. if (errNum < num)
  379. high = i;
  380. else
  381. low = i;
  382. }
  383. if (errNum == errStrings[low].errNum)
  384. return errStrings[low].errString;
  385. if (errNum == errStrings[high].errNum)
  386. return errStrings[high].errString;
  387. return "unknown error";
  388. }
  389. static void
  390. pk11error(const char *string, CK_RV crv) {
  391. PRErrorCode errorcode;
  392. PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv));
  393. errorcode = PR_GetError();
  394. if (errorcode) {
  395. PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode,
  396. PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
  397. }
  398. }
  399. static void
  400. logIt(const char *fmt, ...) {
  401. va_list args;
  402. if (verbose) {
  403. va_start (args, fmt);
  404. vprintf(fmt, args);
  405. va_end(args);
  406. }
  407. }
  408. static CK_RV
  409. softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char * configDir,
  410. const char * dbPrefix) {
  411. CK_RV crv = CKR_OK;
  412. CK_C_INITIALIZE_ARGS initArgs;
  413. char *moduleSpec = NULL;
  414. initArgs.CreateMutex = NULL;
  415. initArgs.DestroyMutex = NULL;
  416. initArgs.LockMutex = NULL;
  417. initArgs.UnlockMutex = NULL;
  418. initArgs.flags = CKF_OS_LOCKING_OK;
  419. if (configDir) {
  420. moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
  421. "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ",
  422. configDir, dbPrefix, dbPrefix);
  423. } else {
  424. moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' "
  425. "secmod='' flags=noCertDB, noModDB");
  426. }
  427. if (!moduleSpec) {
  428. PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n");
  429. return CKR_HOST_MEMORY;
  430. }
  431. logIt("moduleSpec %s\n", moduleSpec);
  432. initArgs.LibraryParameters = (CK_CHAR_PTR *) moduleSpec;
  433. initArgs.pReserved = NULL;
  434. crv = pFunctionList->C_Initialize(&initArgs);
  435. if (crv != CKR_OK) {
  436. pk11error("C_Initialize failed", crv);
  437. goto cleanup;
  438. }
  439. cleanup:
  440. if (moduleSpec) {
  441. PR_smprintf_free(moduleSpec);
  442. }
  443. return crv;
  444. }
  445. static char *
  446. filePasswd(char *pwFile)
  447. {
  448. unsigned char phrase[200];
  449. PRFileDesc *fd;
  450. PRInt32 nb;
  451. int i;
  452. if (!pwFile)
  453. return 0;
  454. fd = PR_Open(pwFile, PR_RDONLY, 0);
  455. if (!fd) {
  456. lperror(pwFile);
  457. return NULL;
  458. }
  459. nb = PR_Read(fd, phrase, sizeof(phrase));
  460. PR_Close(fd);
  461. /* handle the Windows EOL case */
  462. i = 0;
  463. while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++;
  464. phrase[i] = '\0';
  465. if (nb == 0) {
  466. PR_fprintf(PR_STDERR,"password file contains no data\n");
  467. return NULL;
  468. }
  469. return (char*) PL_strdup((char*)phrase);
  470. }
  471. static void
  472. checkPath(char *string)
  473. {
  474. char *src;
  475. char *dest;
  476. /*
  477. * windows support convert any back slashes to
  478. * forward slashes.
  479. */
  480. for (src=string, dest=string; *src; src++,dest++) {
  481. if (*src == '\\') {
  482. *dest = '/';
  483. }
  484. }
  485. dest--;
  486. /* if the last char is a / set it to 0 */
  487. if (*dest == '/')
  488. *dest = 0;
  489. }
  490. static CK_SLOT_ID *
  491. getSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
  492. CK_ULONG slotIndex) {
  493. CK_RV crv = CKR_OK;
  494. CK_SLOT_ID *pSlotList = NULL;
  495. CK_ULONG slotCount;
  496. /* Get slot list */
  497. crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
  498. NULL, &slotCount);
  499. if (crv != CKR_OK) {
  500. pk11error( "C_GetSlotList failed", crv);
  501. return NULL;
  502. }
  503. if (slotIndex >= slotCount) {
  504. PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count.");
  505. return NULL;
  506. }
  507. pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID));
  508. if (!pSlotList) {
  509. lperror("failed to allocate slot list");
  510. return NULL;
  511. }
  512. crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
  513. pSlotList, &slotCount);
  514. if (crv != CKR_OK) {
  515. pk11error( "C_GetSlotList failed", crv);
  516. if (pSlotList) PR_Free(pSlotList);
  517. return NULL;
  518. }
  519. return pSlotList;
  520. }
  521. int main(int argc, char **argv)
  522. {
  523. PLOptState *optstate;
  524. char *program_name;
  525. char *libname = NULL;
  526. PRLibrary *lib;
  527. PRFileDesc *fd;
  528. PRStatus rv = PR_SUCCESS;
  529. const char *input_file = NULL; /* read/create encrypted data from here */
  530. char *output_file = NULL; /* write new encrypted data here */
  531. int bytesRead;
  532. int bytesWritten;
  533. unsigned char file_buf[512];
  534. int count=0;
  535. int i;
  536. PRBool verify = PR_FALSE;
  537. static PRBool FIPSMODE = PR_FALSE;
  538. #ifdef USES_LINKS
  539. int ret;
  540. struct stat stat_buf;
  541. char link_buf[MAXPATHLEN+1];
  542. char *link_file = NULL;
  543. #endif
  544. char *pwd = NULL;
  545. char *configDir = NULL;
  546. char *dbPrefix = NULL;
  547. char *disableUnload = NULL;
  548. CK_C_GetFunctionList pC_GetFunctionList;
  549. CK_TOKEN_INFO tokenInfo;
  550. CK_FUNCTION_LIST_PTR pFunctionList = NULL;
  551. CK_RV crv = CKR_OK;
  552. CK_SESSION_HANDLE hRwSession;
  553. CK_SLOT_ID *pSlotList = NULL;
  554. CK_ULONG slotIndex = 0;
  555. CK_MECHANISM digestmech;
  556. CK_ULONG digestLen = 0;
  557. CK_BYTE digest[20]; /* SHA1_LENGTH */
  558. CK_BYTE sign[40]; /* DSA SIGNATURE LENGTH */
  559. CK_ULONG signLen = 0 ;
  560. CK_MECHANISM signMech = {
  561. CKM_DSA, NULL, 0
  562. };
  563. /*** DSA Key ***/
  564. CK_MECHANISM dsaKeyPairGenMech;
  565. CK_ATTRIBUTE dsaPubKeyTemplate[5];
  566. CK_ATTRIBUTE dsaPrivKeyTemplate[5];
  567. CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
  568. CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
  569. CK_BYTE dsaPubKey[128];
  570. CK_ATTRIBUTE dsaPubKeyValue;
  571. /* DSA key init */
  572. dsaPubKeyTemplate[0].type = CKA_PRIME;
  573. dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR) &prime;
  574. dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
  575. dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
  576. dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR) &subprime;
  577. dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
  578. dsaPubKeyTemplate[2].type = CKA_BASE;
  579. dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR) &base;
  580. dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
  581. dsaPubKeyTemplate[3].type = CKA_TOKEN;
  582. dsaPubKeyTemplate[3].pValue = &false; /* session object */
  583. dsaPubKeyTemplate[3].ulValueLen = sizeof(false);
  584. dsaPubKeyTemplate[4].type = CKA_VERIFY;
  585. dsaPubKeyTemplate[4].pValue = &true;
  586. dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
  587. dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
  588. dsaKeyPairGenMech.pParameter = NULL;
  589. dsaKeyPairGenMech.ulParameterLen = 0;
  590. dsaPrivKeyTemplate[0].type = CKA_TOKEN;
  591. dsaPrivKeyTemplate[0].pValue = &false; /* session object */
  592. dsaPrivKeyTemplate[0].ulValueLen = sizeof(false);
  593. dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
  594. dsaPrivKeyTemplate[1].pValue = &true;
  595. dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
  596. dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
  597. dsaPrivKeyTemplate[2].pValue = &true;
  598. dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
  599. dsaPrivKeyTemplate[3].type = CKA_SIGN,
  600. dsaPrivKeyTemplate[3].pValue = &true;
  601. dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
  602. dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
  603. dsaPrivKeyTemplate[4].pValue = &false;
  604. dsaPrivKeyTemplate[4].ulValueLen = sizeof(false);
  605. digestmech.mechanism = CKM_SHA_1;
  606. digestmech.pParameter = NULL;
  607. digestmech.ulParameterLen = 0;
  608. program_name = strrchr(argv[0], '/');
  609. program_name = program_name ? (program_name + 1) : argv[0];
  610. optstate = PL_CreateOptState (argc, argv, "i:o:f:Fd:hH?p:P:vVs:");
  611. if (optstate == NULL) {
  612. lperror("PL_CreateOptState failed");
  613. return 1;
  614. }
  615. while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
  616. switch (optstate->option) {
  617. case 'd':
  618. if (!optstate->value) {
  619. PL_DestroyOptState(optstate);
  620. usage(program_name);
  621. }
  622. configDir = PL_strdup(optstate->value);
  623. checkPath(configDir);
  624. break;
  625. case 'i':
  626. if (!optstate->value) {
  627. PL_DestroyOptState(optstate);
  628. usage(program_name);
  629. }
  630. input_file = optstate->value;
  631. break;
  632. case 'o':
  633. if (!optstate->value) {
  634. PL_DestroyOptState(optstate);
  635. usage(program_name);
  636. }
  637. output_file = PL_strdup(optstate->value);
  638. break;
  639. case 'f':
  640. if (!optstate->value) {
  641. PL_DestroyOptState(optstate);
  642. usage(program_name);
  643. }
  644. pwd = filePasswd((char *)optstate->value);
  645. if (!pwd) usage(program_name);
  646. break;
  647. case 'F':
  648. FIPSMODE = PR_TRUE;
  649. break;
  650. case 'p':
  651. if (!optstate->value) {
  652. PL_DestroyOptState(optstate);
  653. usage(program_name);
  654. }
  655. pwd = PL_strdup(optstate->value);
  656. break;
  657. case 'P':
  658. if (!optstate->value) {
  659. PL_DestroyOptState(optstate);
  660. usage(program_name);
  661. }
  662. dbPrefix = PL_strdup(optstate->value);
  663. break;
  664. case 'v':
  665. verbose = PR_TRUE;
  666. break;
  667. case 'V':
  668. verify = PR_TRUE;
  669. break;
  670. case 'H':
  671. PL_DestroyOptState(optstate);
  672. long_usage (program_name);
  673. return 1;
  674. break;
  675. case 'h':
  676. case '?':
  677. default:
  678. PL_DestroyOptState(optstate);
  679. usage(program_name);
  680. return 1;
  681. break;
  682. }
  683. }
  684. PL_DestroyOptState(optstate);
  685. if (!input_file) {
  686. usage(program_name);
  687. return 1;
  688. }
  689. /* Get the platform-dependent library name of the
  690. * NSS cryptographic module.
  691. */
  692. libname = PR_GetLibraryName(NULL, "softokn3");
  693. assert(libname != NULL);
  694. lib = PR_LoadLibrary(libname);
  695. assert(lib != NULL);
  696. PR_FreeLibraryName(libname);
  697. if (FIPSMODE) {
  698. /* FIPSMODE == FC_GetFunctionList */
  699. /* library path must be set to an already signed softokn3/freebl */
  700. pC_GetFunctionList = (CK_C_GetFunctionList)
  701. PR_FindFunctionSymbol(lib, "FC_GetFunctionList");
  702. } else {
  703. /* NON FIPS mode == C_GetFunctionList */
  704. pC_GetFunctionList = (CK_C_GetFunctionList)
  705. PR_FindFunctionSymbol(lib, "C_GetFunctionList");
  706. }
  707. assert(pC_GetFunctionList != NULL);
  708. crv = (*pC_GetFunctionList)(&pFunctionList);
  709. assert(crv == CKR_OK);
  710. if (configDir) {
  711. if (!dbPrefix) {
  712. dbPrefix = PL_strdup("");
  713. }
  714. crv = softokn_Init(pFunctionList, configDir, dbPrefix);
  715. if (crv != CKR_OK) {
  716. logIt("Failed to use provided database directory "
  717. "will just initialize the volatile certdb.\n");
  718. crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
  719. }
  720. } else {
  721. crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
  722. }
  723. if (crv != CKR_OK) {
  724. pk11error( "Initiailzing softoken failed", crv);
  725. goto cleanup;
  726. }
  727. pSlotList = getSlotList(pFunctionList, slotIndex);
  728. if (pSlotList == NULL) {
  729. PR_fprintf(PR_STDERR, "getSlotList failed");
  730. goto cleanup;
  731. }
  732. crv = pFunctionList->C_OpenSession(pSlotList[slotIndex],
  733. CKF_RW_SESSION | CKF_SERIAL_SESSION,
  734. NULL, NULL, &hRwSession);
  735. if (crv != CKR_OK) {
  736. pk11error( "Opening a read/write session failed", crv);
  737. goto cleanup;
  738. }
  739. /* check if a password is needed */
  740. crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo);
  741. if (crv != CKR_OK) {
  742. pk11error( "C_GetTokenInfo failed", crv);
  743. goto cleanup;
  744. }
  745. if (tokenInfo.flags & CKF_LOGIN_REQUIRED) {
  746. if (pwd) {
  747. int pwdLen = strlen((const char*)pwd);
  748. crv = pFunctionList->C_Login(hRwSession, CKU_USER,
  749. (CK_UTF8CHAR_PTR) pwd, (CK_ULONG)pwdLen);
  750. if (crv != CKR_OK) {
  751. pk11error("C_Login failed", crv);
  752. goto cleanup;
  753. }
  754. } else {
  755. PR_fprintf(PR_STDERR, "Please provide the password for the token");
  756. goto cleanup;
  757. }
  758. } else if (pwd) {
  759. logIt("A password was provided but the password was not used.\n");
  760. }
  761. /* Generate a DSA key pair */
  762. logIt("Generate a DSA key pair ... \n");
  763. crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
  764. dsaPubKeyTemplate,
  765. NUM_ELEM(dsaPubKeyTemplate),
  766. dsaPrivKeyTemplate,
  767. NUM_ELEM(dsaPrivKeyTemplate),
  768. &hDSApubKey, &hDSAprivKey);
  769. if (crv != CKR_OK) {
  770. pk11error("DSA key pair generation failed", crv);
  771. goto cleanup;
  772. }
  773. /* open the shared library */
  774. fd = PR_OpenFile(input_file,PR_RDONLY,0);
  775. if (fd == NULL ) {
  776. lperror(input_file);
  777. goto cleanup;
  778. }
  779. #ifdef USES_LINKS
  780. ret = lstat(input_file, &stat_buf);
  781. if (ret < 0) {
  782. perror(input_file);
  783. goto cleanup;
  784. }
  785. if (S_ISLNK(stat_buf.st_mode)) {
  786. char *dirpath,*dirend;
  787. ret = readlink(input_file, link_buf, sizeof(link_buf) - 1);
  788. if (ret < 0) {
  789. perror(input_file);
  790. goto cleanup;
  791. }
  792. link_buf[ret] = 0;
  793. link_file = mkoutput(input_file);
  794. /* get the dirname of input_file */
  795. dirpath = PL_strdup(input_file);
  796. dirend = strrchr(dirpath, '/');
  797. if (dirend) {
  798. *dirend = '\0';
  799. ret = chdir(dirpath);
  800. if (ret < 0) {
  801. perror(dirpath);
  802. goto cleanup;
  803. }
  804. }
  805. PL_strfree(dirpath);
  806. input_file = link_buf;
  807. /* get the basename of link_file */
  808. dirend = strrchr(link_file, '/');
  809. if (dirend) {
  810. char * tmp_file = NULL;
  811. tmp_file = PL_strdup(dirend +1 );
  812. PL_strfree(link_file);
  813. link_file = tmp_file;
  814. }
  815. }
  816. #endif
  817. if (output_file == NULL) {
  818. output_file = mkoutput(input_file);
  819. }
  820. /* compute the digest */
  821. memset(digest, 0, sizeof(digest));
  822. crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
  823. if (crv != CKR_OK) {
  824. pk11error("C_DigestInit failed", crv);
  825. goto cleanup;
  826. }
  827. /* Digest the file */
  828. while ((bytesRead = PR_Read(fd,file_buf,sizeof(file_buf))) > 0) {
  829. crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
  830. bytesRead);
  831. if (crv != CKR_OK) {
  832. pk11error("C_DigestUpdate failed", crv);
  833. goto cleanup;
  834. }
  835. count += bytesRead;
  836. }
  837. /* close the input_File */
  838. PR_Close(fd);
  839. fd = NULL;
  840. if (bytesRead < 0) {
  841. lperror("0 bytes read from input file");
  842. goto cleanup;
  843. }
  844. digestLen = sizeof(digest);
  845. crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
  846. &digestLen);
  847. if (crv != CKR_OK) {
  848. pk11error("C_DigestFinal failed", crv);
  849. goto cleanup;
  850. }
  851. if (digestLen != sizeof(digest)) {
  852. PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
  853. "it should be %lu \n",digestLen, sizeof(digest));
  854. goto cleanup;
  855. }
  856. /* sign the hash */
  857. memset(sign, 0, sizeof(sign));
  858. /* SignUpdate */
  859. crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
  860. if (crv != CKR_OK) {
  861. pk11error("C_SignInit failed", crv);
  862. goto cleanup;
  863. }
  864. signLen = sizeof(sign);
  865. crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE * ) digest, digestLen,
  866. sign, &signLen);
  867. if (crv != CKR_OK) {
  868. pk11error("C_Sign failed", crv);
  869. goto cleanup;
  870. }
  871. if (signLen != sizeof(sign)) {
  872. PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
  873. "it should be %lu \n", signLen, sizeof(sign));
  874. goto cleanup;
  875. }
  876. if (verify) {
  877. crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
  878. if (crv != CKR_OK) {
  879. pk11error("C_VerifyInit failed", crv);
  880. goto cleanup;
  881. }
  882. crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
  883. sign, signLen);
  884. if (crv != CKR_OK) {
  885. pk11error("C_Verify failed", crv);
  886. goto cleanup;
  887. }
  888. }
  889. if (verbose) {
  890. int j;
  891. PR_fprintf(PR_STDERR,"Library File: %s %d bytes\n",input_file, count);
  892. PR_fprintf(PR_STDERR,"Check File: %s\n",output_file);
  893. #ifdef USES_LINKS
  894. if (link_file) {
  895. PR_fprintf(PR_STDERR,"Link: %s\n",link_file);
  896. }
  897. #endif
  898. PR_fprintf(PR_STDERR," hash: %lu bytes\n", digestLen);
  899. #define STEP 10
  900. for (i=0; i < (int) digestLen; i += STEP) {
  901. PR_fprintf(PR_STDERR," ");
  902. for (j=0; j < STEP && (i+j) < (int) digestLen; j++) {
  903. PR_fprintf(PR_STDERR," %02x", digest[i+j]);
  904. }
  905. PR_fprintf(PR_STDERR,"\n");
  906. }
  907. PR_fprintf(PR_STDERR," signature: %lu bytes\n", signLen);
  908. for (i=0; i < (int) signLen; i += STEP) {
  909. PR_fprintf(PR_STDERR," ");
  910. for (j=0; j < STEP && (i+j) < (int) signLen; j++) {
  911. PR_fprintf(PR_STDERR," %02x", sign[i+j]);
  912. }
  913. PR_fprintf(PR_STDERR,"\n");
  914. }
  915. }
  916. /* open the target signature file */
  917. fd = PR_Open(output_file,PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0666);
  918. if (fd == NULL ) {
  919. lperror(output_file);
  920. goto cleanup;
  921. }
  922. /*
  923. * we write the key out in a straight binary format because very
  924. * low level libraries need to read an parse this file. Ideally we should
  925. * just derEncode the public key (which would be pretty simple, and be
  926. * more general), but then we'd need to link the ASN.1 decoder with the
  927. * freebl libraries.
  928. */
  929. file_buf[0] = NSS_SIGN_CHK_MAGIC1;
  930. file_buf[1] = NSS_SIGN_CHK_MAGIC2;
  931. file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
  932. file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
  933. encodeInt(&file_buf[4],12); /* offset to data start */
  934. encodeInt(&file_buf[8],CKK_DSA);
  935. bytesWritten = PR_Write(fd,file_buf, 12);
  936. if (bytesWritten != 12) {
  937. lperror(output_file);
  938. goto cleanup;
  939. }
  940. /* get DSA Public KeyValue */
  941. memset(dsaPubKey, 0, sizeof(dsaPubKey));
  942. dsaPubKeyValue.type =CKA_VALUE;
  943. dsaPubKeyValue.pValue = (CK_VOID_PTR) &dsaPubKey;
  944. dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
  945. crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
  946. &dsaPubKeyValue, 1);
  947. if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
  948. pk11error("C_GetAttributeValue failed", crv);
  949. goto cleanup;
  950. }
  951. /* CKA_PRIME */
  952. rv = writeItem(fd,dsaPubKeyTemplate[0].pValue,
  953. dsaPubKeyTemplate[0].ulValueLen, output_file);
  954. if (rv != PR_SUCCESS) goto cleanup;
  955. /* CKA_SUBPRIME */
  956. rv = writeItem(fd,dsaPubKeyTemplate[1].pValue,
  957. dsaPubKeyTemplate[1].ulValueLen, output_file);
  958. if (rv != PR_SUCCESS) goto cleanup;
  959. /* CKA_BASE */
  960. rv = writeItem(fd,dsaPubKeyTemplate[2].pValue,
  961. dsaPubKeyTemplate[2].ulValueLen, output_file);
  962. if (rv != PR_SUCCESS) goto cleanup;
  963. /* DSA Public Key value */
  964. rv = writeItem(fd,dsaPubKeyValue.pValue,
  965. dsaPubKeyValue.ulValueLen, output_file);
  966. if (rv != PR_SUCCESS) goto cleanup;
  967. /* DSA SIGNATURE */
  968. rv = writeItem(fd,&sign, signLen, output_file);
  969. if (rv != PR_SUCCESS) goto cleanup;
  970. PR_Close(fd);
  971. #ifdef USES_LINKS
  972. if (link_file) {
  973. (void)unlink(link_file);
  974. ret = symlink(output_file, link_file);
  975. if (ret < 0) {
  976. perror(link_file);
  977. goto cleanup;
  978. }
  979. }
  980. #endif
  981. cleanup:
  982. if (pFunctionList) {
  983. /* C_Finalize will automatically logout, close session, */
  984. /* and delete the temp objects on the token */
  985. crv = pFunctionList->C_Finalize(NULL);
  986. if (crv != CKR_OK) {
  987. pk11error("C_Finalize failed", crv);
  988. }
  989. }
  990. if (pSlotList) {
  991. PR_Free(pSlotList);
  992. }
  993. if (pwd) {
  994. PL_strfree(pwd);
  995. }
  996. if (configDir) {
  997. PL_strfree(configDir);
  998. }
  999. if (dbPrefix) {
  1000. PL_strfree(dbPrefix);
  1001. }
  1002. if (output_file) { /* allocated by mkoutput function */
  1003. PL_strfree(output_file);
  1004. }
  1005. #ifdef USES_LINKS
  1006. if (link_file) { /* allocated by mkoutput function */
  1007. PL_strfree(link_file);
  1008. }
  1009. #endif
  1010. disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
  1011. if (!disableUnload) {
  1012. PR_UnloadLibrary(lib);
  1013. }
  1014. PR_Cleanup();
  1015. return crv;
  1016. }