Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /*
6 * shlibsign creates the checksum (.chk) files for the NSS libraries,
7 * libsoftokn3/softokn3 and libfreebl/freebl (platforms can have
8 * multiple freebl variants), that contain the NSS cryptograhic boundary.
9 *
10 * The generated .chk files must be put in the same directory as
11 * the NSS libraries they were generated for.
12 *
13 * When in FIPS 140 mode, the NSS Internal FIPS PKCS #11 Module will
14 * compute the checksum for the NSS cryptographic boundary libraries
15 * and compare the checksum with the value in .chk file.
16 */
18 #ifdef XP_UNIX
19 #define USES_LINKS 1
20 #endif
22 #include <assert.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
28 #ifdef USES_LINKS
29 #include <unistd.h>
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #endif
35 /* nspr headers */
36 #include "prlink.h"
37 #include "prprf.h"
38 #include "prenv.h"
39 #include "plgetopt.h"
40 #include "prinit.h"
41 #include "prmem.h"
42 #include "plstr.h"
43 #include "prerror.h"
45 /* softoken headers */
46 #include "pkcs11.h"
47 #include "pkcs11t.h"
49 /* freebl headers */
50 #include "shsign.h"
52 #define NUM_ELEM(array) (sizeof(array)/sizeof(array[0]))
53 CK_BBOOL true = CK_TRUE;
54 CK_BBOOL false = CK_FALSE;
55 static PRBool verbose = PR_FALSE;
57 static void
58 usage (const char *program_name)
59 {
60 PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
61 PR_fprintf (debug_out,
62 "type %s -H for more detail information.\n", program_name);
63 PR_fprintf (debug_out,
64 "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n"
65 " [-F] [-p pwd] -[P dbprefix ] "
66 "-i shared_library_name\n",
67 program_name);
68 exit(1);
69 }
71 static void
72 long_usage(const char *program_name)
73 {
74 PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
75 PR_fprintf(debug_out, "%s test program usage:\n", program_name);
76 PR_fprintf(debug_out, "\t-i <infile> shared_library_name to process\n");
77 PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
78 PR_fprintf(debug_out, "\t-d <path> database path location\n");
79 PR_fprintf(debug_out, "\t-P <prefix> database prefix\n");
80 PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n");
81 PR_fprintf(debug_out, "\t-F FIPS mode\n");
82 PR_fprintf(debug_out, "\t-p <pwd> password\n");
83 PR_fprintf(debug_out, "\t-v verbose output\n");
84 PR_fprintf(debug_out, "\t-V perform Verify operations\n");
85 PR_fprintf(debug_out, "\t-? short help message\n");
86 PR_fprintf(debug_out, "\t-h short help message\n");
87 PR_fprintf(debug_out, "\t-H this help message\n");
88 PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your ");
89 PR_fprintf(debug_out, "library path is using \n");
90 PR_fprintf(debug_out, "\t pre-existing libraries with generated ");
91 PR_fprintf(debug_out, "checksum files\n");
92 PR_fprintf(debug_out, "\t and database in FIPS mode \n");
93 exit(1);
94 }
96 static char *
97 mkoutput(const char *input)
98 {
99 int in_len = strlen(input);
100 char *output = PR_Malloc(in_len+sizeof(SGN_SUFFIX));
101 int index = in_len + 1 - sizeof("."SHLIB_SUFFIX);
103 if ((index > 0) &&
104 (PL_strncmp(&input[index],
105 "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
106 in_len = index;
107 }
108 memcpy(output,input,in_len);
109 memcpy(&output[in_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
110 return output;
111 }
113 static void
114 lperror(const char *string) {
115 PRErrorCode errorcode;
117 errorcode = PR_GetError();
118 PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode,
119 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
120 }
122 static void
123 encodeInt(unsigned char *buf, int val)
124 {
125 buf[3] = (val >> 0) & 0xff;
126 buf[2] = (val >> 8) & 0xff;
127 buf[1] = (val >> 16) & 0xff;
128 buf[0] = (val >> 24) & 0xff;
129 return;
130 }
132 static PRStatus
133 writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
134 CK_ULONG ulValueLen, char *file)
135 {
136 unsigned char buf[4];
137 int bytesWritten;
138 if (ulValueLen == 0) {
139 PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n");
140 return PR_FAILURE;
141 }
143 encodeInt(buf,ulValueLen);
144 bytesWritten = PR_Write(fd,buf, 4);
145 if (bytesWritten != 4) {
146 lperror(file);
147 return PR_FAILURE;
148 }
149 bytesWritten = PR_Write(fd, pValue, ulValueLen);
150 if (bytesWritten != ulValueLen) {
151 lperror(file);
152 return PR_FAILURE;
153 }
154 return PR_SUCCESS;
155 }
157 static const unsigned char prime[] = { 0x00,
158 0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d,
159 0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92,
160 0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7,
161 0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c,
162 0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44,
163 0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8,
164 0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69,
165 0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb,
166 0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5,
167 0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd,
168 0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77,
169 0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd,
170 0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d,
171 0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2,
172 0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77,
173 0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 };
175 static const unsigned char subprime[] = { 0x0,
176 0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5,
177 0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54,
178 0x0b, 0x31, 0x24, 0xf1 };
180 static const unsigned char base[] = {
181 0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a,
182 0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11,
183 0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23,
184 0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42,
185 0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1,
186 0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f,
187 0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f,
188 0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa,
189 0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc,
190 0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1,
191 0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18,
192 0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8,
193 0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d,
194 0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc,
195 0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36,
196 0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f };
198 static const unsigned char h[] = {
199 0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac,
200 0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6,
201 0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f,
202 0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67,
203 0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29,
204 0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd,
205 0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13,
206 0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5,
207 0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f,
208 0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2,
209 0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6,
210 0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32,
211 0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23,
212 0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9,
213 0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7,
214 0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c };
216 static const unsigned char seed[] = { 0x00,
217 0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68,
218 0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed,
219 0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85,
220 0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b,
221 0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d,
222 0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83,
223 0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2,
224 0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4,
225 0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00,
226 0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3,
227 0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36,
228 0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e,
229 0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2,
230 0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe,
231 0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc,
232 0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c };
234 static const unsigned int counter=1496;
236 static const unsigned char prime2[] = { 0x00,
237 0xa4, 0xc2, 0x83, 0x4f, 0x36, 0xd3, 0x4f, 0xae,
238 0xa0, 0xb1, 0x47, 0x43, 0xa8, 0x15, 0xee, 0xad,
239 0xa3, 0x98, 0xa3, 0x29, 0x45, 0xae, 0x5c, 0xd9,
240 0x12, 0x99, 0x09, 0xdc, 0xef, 0x05, 0xb4, 0x98,
241 0x05, 0xaa, 0x07, 0xaa, 0x83, 0x89, 0xd7, 0xba,
242 0xd1, 0x25, 0x56, 0x58, 0xd1, 0x73, 0x3c, 0xd0,
243 0x91, 0x65, 0xbe, 0x27, 0x92, 0x94, 0x86, 0x95,
244 0xdb, 0xcf, 0x07, 0x13, 0xa0, 0x85, 0xd6, 0xaa,
245 0x6c, 0x1d, 0x63, 0xbf, 0xdd, 0xdf, 0xbc, 0x30,
246 0xeb, 0x42, 0x2f, 0x52, 0x11, 0xec, 0x6e, 0x65,
247 0xdf, 0x50, 0xbe, 0x28, 0x3d, 0xa4, 0xec, 0x45,
248 0x19, 0x4c, 0x13, 0x0f, 0x59, 0x74, 0x57, 0x69,
249 0x99, 0x4f, 0x4a, 0x74, 0x7f, 0x8c, 0x9e, 0xa2,
250 0xe7, 0x94, 0xc9, 0x70, 0x70, 0xd0, 0xc4, 0xda,
251 0x49, 0x5b, 0x7a, 0x7d, 0xd9, 0x71, 0x7c, 0x3b,
252 0xdc, 0xd2, 0x8a, 0x74, 0x5f, 0xce, 0x09, 0xa2,
253 0xdb, 0xec, 0xa4, 0xba, 0x75, 0xaa, 0x0a, 0x97,
254 0xa6, 0x82, 0x25, 0x90, 0x90, 0x37, 0xe4, 0x40,
255 0x05, 0x28, 0x8f, 0x98, 0x8e, 0x68, 0x01, 0xaf,
256 0x9b, 0x08, 0x2a, 0x9b, 0xd5, 0xb9, 0x8c, 0x14,
257 0xbf, 0xba, 0xcb, 0x5b, 0xda, 0x4c, 0x95, 0xb8,
258 0xdf, 0x67, 0xa6, 0x6b, 0x76, 0x8c, 0xad, 0x4f,
259 0xfd, 0x6a, 0xd6, 0xcc, 0x62, 0x71, 0x30, 0x30,
260 0xc1, 0x29, 0x84, 0xe4, 0x8e, 0x32, 0x51, 0xb6,
261 0xea, 0xfa, 0xba, 0x00, 0x99, 0x76, 0xea, 0x86,
262 0x90, 0xab, 0x2d, 0xe9, 0xfd, 0x1e, 0x8c, 0xcc,
263 0x3c, 0x2b, 0x5d, 0x13, 0x1b, 0x47, 0xb4, 0xf5,
264 0x09, 0x74, 0x1d, 0xd4, 0x78, 0xb2, 0x42, 0x19,
265 0xd6, 0x24, 0xd1, 0x68, 0xbf, 0x11, 0xf1, 0x38,
266 0xa0, 0x44, 0x9c, 0xc6, 0x51, 0x33, 0xaa, 0x42,
267 0x93, 0x9e, 0x30, 0x58, 0x9e, 0xc0, 0x70, 0xdf,
268 0x7e, 0x64, 0xb1, 0xd8, 0x68, 0x75, 0x98, 0xa7 };
270 static const unsigned char subprime2[] = { 0x00,
271 0x8e, 0xab, 0xf4, 0xbe, 0x45, 0xeb, 0xa3, 0x58,
272 0x4e, 0x60, 0x15, 0x66, 0x5a, 0x4b, 0x25, 0xcf,
273 0x45, 0x77, 0x89, 0x3f, 0x73, 0x34, 0x4a, 0xe0,
274 0x9e, 0xac, 0xfd, 0xdc, 0xff, 0x9c, 0x8d, 0xe7 };
276 static const unsigned char base2[] = { 0x00,
277 0x8d, 0x72, 0x32, 0x46, 0xa6, 0x5c, 0x80, 0xe3,
278 0x43, 0x0a, 0x9e, 0x94, 0x35, 0x86, 0xd4, 0x58,
279 0xa1, 0xca, 0x22, 0xb9, 0x73, 0x46, 0x0b, 0xfb,
280 0x3e, 0x33, 0xf1, 0xd5, 0xd3, 0xb4, 0x26, 0xbf,
281 0x50, 0xd7, 0xf2, 0x09, 0x33, 0x6e, 0xc0, 0x31,
282 0x1b, 0x6d, 0x07, 0x70, 0x86, 0xca, 0x57, 0xf7,
283 0x0b, 0x4a, 0x63, 0xf0, 0x6f, 0xc8, 0x8a, 0xed,
284 0x50, 0x60, 0xf3, 0x11, 0xc7, 0x44, 0xf3, 0xce,
285 0x4e, 0x50, 0x42, 0x2d, 0x85, 0x33, 0x54, 0x57,
286 0x03, 0x8d, 0xdc, 0x66, 0x4d, 0x61, 0x83, 0x17,
287 0x1c, 0x7b, 0x0d, 0x65, 0xbc, 0x8f, 0x2c, 0x19,
288 0x86, 0xfc, 0xe2, 0x9f, 0x5d, 0x67, 0xfc, 0xd4,
289 0xa5, 0xf8, 0x23, 0xa1, 0x1a, 0xa2, 0xe1, 0x11,
290 0x15, 0x84, 0x32, 0x01, 0xee, 0x88, 0xf1, 0x55,
291 0x30, 0xe9, 0x74, 0x3c, 0x1a, 0x2b, 0x54, 0x45,
292 0x2e, 0x39, 0xb9, 0x77, 0xe1, 0x32, 0xaf, 0x2d,
293 0x97, 0xe0, 0x21, 0xec, 0xf5, 0x58, 0xe1, 0xc7,
294 0x2e, 0xe0, 0x71, 0x3d, 0x29, 0xa4, 0xd6, 0xe2,
295 0x5f, 0x85, 0x9c, 0x05, 0x04, 0x46, 0x41, 0x89,
296 0x03, 0x3c, 0xfa, 0xb2, 0xcf, 0xfa, 0xd5, 0x67,
297 0xcc, 0xec, 0x68, 0xfc, 0x83, 0xd9, 0x1f, 0x2e,
298 0x4e, 0x9a, 0x5e, 0x77, 0xa1, 0xff, 0xe6, 0x6f,
299 0x04, 0x8b, 0xf9, 0x6b, 0x47, 0xc6, 0x49, 0xd2,
300 0x88, 0x6e, 0x29, 0xa3, 0x1b, 0xae, 0xe0, 0x4f,
301 0x72, 0x8a, 0x28, 0x94, 0x0c, 0x1d, 0x8c, 0x99,
302 0xa2, 0x6f, 0xf8, 0xba, 0x99, 0x90, 0xc7, 0xe5,
303 0xb1, 0x3c, 0x10, 0x34, 0x86, 0x6a, 0x6a, 0x1f,
304 0x39, 0x63, 0x58, 0xe1, 0x5e, 0x97, 0x95, 0x45,
305 0x40, 0x38, 0x45, 0x6f, 0x02, 0xb5, 0x86, 0x6e,
306 0xae, 0x2f, 0x32, 0x7e, 0xa1, 0x3a, 0x34, 0x2c,
307 0x1c, 0xd3, 0xff, 0x4e, 0x2c, 0x38, 0x1c, 0xaa,
308 0x2e, 0x66, 0xbe, 0x32, 0x3e, 0x3c, 0x06, 0x5f };
310 static const unsigned char h2[] = {
311 0x30, 0x91, 0xa1, 0x2e, 0x40, 0xa5, 0x7d, 0xf7,
312 0xdc, 0xed, 0xee, 0x05, 0xc2, 0x31, 0x91, 0x37,
313 0xda, 0xc5, 0xe3, 0x47, 0xb5, 0x35, 0x4b, 0xfd,
314 0x18, 0xb2, 0x7e, 0x67, 0x1e, 0x92, 0x22, 0xe7,
315 0xf5, 0x00, 0x71, 0xc0, 0x86, 0x8d, 0x90, 0x31,
316 0x36, 0x3e, 0xd0, 0x94, 0x5d, 0x2f, 0x9a, 0x68,
317 0xd2, 0xf8, 0x3d, 0x5e, 0x84, 0x42, 0x35, 0xda,
318 0x75, 0xdd, 0x05, 0xf0, 0x03, 0x31, 0x39, 0xe5,
319 0xfd, 0x2f, 0x5a, 0x7d, 0x56, 0xd8, 0x26, 0xa0,
320 0x51, 0x5e, 0x32, 0xb4, 0xad, 0xee, 0xd4, 0x89,
321 0xae, 0x01, 0x7f, 0xac, 0x86, 0x98, 0x77, 0x26,
322 0x5c, 0x31, 0xd2, 0x5e, 0xbb, 0x7f, 0xf5, 0x4c,
323 0x9b, 0xf0, 0xa6, 0x37, 0x34, 0x08, 0x86, 0x6b,
324 0xce, 0xeb, 0x85, 0x66, 0x0a, 0x26, 0x8a, 0x14,
325 0x92, 0x12, 0x74, 0xf4, 0xf0, 0xcb, 0xb5, 0xfc,
326 0x38, 0xd5, 0x1e, 0xa1, 0x2f, 0x4a, 0x1a, 0xca,
327 0x66, 0xde, 0x6e, 0xe6, 0x6e, 0x1c, 0xef, 0x50,
328 0x41, 0x31, 0x09, 0xe7, 0x4a, 0xb8, 0xa3, 0xaa,
329 0x5a, 0x22, 0xbd, 0x63, 0x0f, 0xe9, 0x0e, 0xdb,
330 0xb3, 0xca, 0x7e, 0x8d, 0x40, 0xb3, 0x3e, 0x0b,
331 0x12, 0x8b, 0xb0, 0x80, 0x4d, 0x6d, 0xb0, 0x54,
332 0xbb, 0x4c, 0x1d, 0x6c, 0xa0, 0x5c, 0x9d, 0x91,
333 0xb3, 0xbb, 0xd9, 0xfc, 0x60, 0xec, 0xc1, 0xbc,
334 0xae, 0x72, 0x3f, 0xa5, 0x4f, 0x36, 0x2d, 0x2c,
335 0x81, 0x03, 0x86, 0xa2, 0x03, 0x38, 0x36, 0x8e,
336 0xad, 0x1d, 0x53, 0xc6, 0xc5, 0x9e, 0xda, 0x08,
337 0x35, 0x4f, 0xb2, 0x78, 0xba, 0xd1, 0x22, 0xde,
338 0xc4, 0x6b, 0xbe, 0x83, 0x71, 0x0f, 0xee, 0x38,
339 0x4a, 0x9f, 0xda, 0x90, 0x93, 0x6b, 0x9a, 0xf2,
340 0xeb, 0x23, 0xfe, 0x41, 0x3f, 0xf1, 0xfc, 0xee,
341 0x7f, 0x67, 0xa7, 0xb8, 0xab, 0x29, 0xf4, 0x75,
342 0x1c, 0xe9, 0xd1, 0x47, 0x7d, 0x86, 0x44, 0xe2 };
344 static const unsigned char seed2[] = { 0x00,
345 0xbc, 0xae, 0xc4, 0xea, 0x4e, 0xd2, 0xed, 0x1c,
346 0x8d, 0x48, 0xed, 0xf2, 0xa5, 0xb4, 0x18, 0xba,
347 0x00, 0xcb, 0x9c, 0x75, 0x8a, 0x39, 0x94, 0x3b,
348 0xd0, 0xd6, 0x01, 0xf7, 0xc1, 0xf5, 0x9d, 0xe5,
349 0xe3, 0xb4, 0x1d, 0xf5, 0x30, 0xfe, 0x99, 0xe4,
350 0x01, 0xab, 0xc0, 0x88, 0x4e, 0x67, 0x8f, 0xc6,
351 0x72, 0x39, 0x2e, 0xac, 0x51, 0xec, 0x91, 0x41,
352 0x47, 0x71, 0x14, 0x8a, 0x1d, 0xca, 0x88, 0x15,
353 0xea, 0xc9, 0x48, 0x9a, 0x71, 0x50, 0x19, 0x38,
354 0xdb, 0x4e, 0x65, 0xd5, 0x13, 0xd8, 0x2a, 0xc4,
355 0xcd, 0xfd, 0x0c, 0xe3, 0xc3, 0x60, 0xae, 0x6d,
356 0x88, 0xf2, 0x3a, 0xd0, 0x64, 0x73, 0x32, 0x89,
357 0xcd, 0x0b, 0xb8, 0xc7, 0xa5, 0x27, 0x84, 0xd5,
358 0x83, 0x3f, 0x0e, 0x10, 0x63, 0x10, 0x78, 0xac,
359 0x6b, 0x56, 0xb2, 0x62, 0x3a, 0x44, 0x56, 0xc0,
360 0xe4, 0x33, 0xd7, 0x63, 0x4c, 0xc9, 0x6b, 0xae,
361 0xfb, 0xe2, 0x9b, 0xf4, 0x96, 0xc7, 0xf0, 0x2a,
362 0x50, 0xde, 0x86, 0x69, 0x4f, 0x42, 0x4b, 0x1c,
363 0x7c, 0xa8, 0x6a, 0xfb, 0x54, 0x47, 0x1b, 0x41,
364 0x31, 0x9e, 0x0a, 0xc6, 0xc0, 0xbc, 0x88, 0x7f,
365 0x5a, 0x42, 0xa9, 0x82, 0x58, 0x32, 0xb3, 0xeb,
366 0x54, 0x83, 0x84, 0x26, 0x92, 0xa6, 0xc0, 0x6e,
367 0x2b, 0xa6, 0x82, 0x82, 0x43, 0x58, 0x84, 0x53,
368 0x31, 0xcf, 0xd0, 0x0a, 0x11, 0x09, 0x44, 0xc8,
369 0x11, 0x36, 0xe0, 0x04, 0x85, 0x2e, 0xd1, 0x29,
370 0x6b, 0x7b, 0x00, 0x71, 0x5f, 0xef, 0x7b, 0x7a,
371 0x2d, 0x91, 0xf9, 0x84, 0x45, 0x4d, 0xc7, 0xe1,
372 0xee, 0xd4, 0xb8, 0x61, 0x3b, 0x13, 0xb7, 0xba,
373 0x95, 0x39, 0xf6, 0x3d, 0x89, 0xbd, 0xa5, 0x80,
374 0x93, 0xf7, 0xe5, 0x17, 0x05, 0xc5, 0x65, 0xb7,
375 0xde, 0xc9, 0x9f, 0x04, 0x87, 0xcf, 0x4f, 0x86,
376 0xc3, 0x29, 0x7d, 0xb7, 0x89, 0xbf, 0xe3, 0xde };
378 static const unsigned int counter2=210;
380 struct tuple_str {
381 CK_RV errNum;
382 const char * errString;
383 };
385 typedef struct tuple_str tuple_str;
387 static const tuple_str errStrings[] = {
388 {CKR_OK , "CKR_OK "},
389 {CKR_CANCEL , "CKR_CANCEL "},
390 {CKR_HOST_MEMORY , "CKR_HOST_MEMORY "},
391 {CKR_SLOT_ID_INVALID , "CKR_SLOT_ID_INVALID "},
392 {CKR_GENERAL_ERROR , "CKR_GENERAL_ERROR "},
393 {CKR_FUNCTION_FAILED , "CKR_FUNCTION_FAILED "},
394 {CKR_ARGUMENTS_BAD , "CKR_ARGUMENTS_BAD "},
395 {CKR_NO_EVENT , "CKR_NO_EVENT "},
396 {CKR_NEED_TO_CREATE_THREADS , "CKR_NEED_TO_CREATE_THREADS "},
397 {CKR_CANT_LOCK , "CKR_CANT_LOCK "},
398 {CKR_ATTRIBUTE_READ_ONLY , "CKR_ATTRIBUTE_READ_ONLY "},
399 {CKR_ATTRIBUTE_SENSITIVE , "CKR_ATTRIBUTE_SENSITIVE "},
400 {CKR_ATTRIBUTE_TYPE_INVALID , "CKR_ATTRIBUTE_TYPE_INVALID "},
401 {CKR_ATTRIBUTE_VALUE_INVALID , "CKR_ATTRIBUTE_VALUE_INVALID "},
402 {CKR_DATA_INVALID , "CKR_DATA_INVALID "},
403 {CKR_DATA_LEN_RANGE , "CKR_DATA_LEN_RANGE "},
404 {CKR_DEVICE_ERROR , "CKR_DEVICE_ERROR "},
405 {CKR_DEVICE_MEMORY , "CKR_DEVICE_MEMORY "},
406 {CKR_DEVICE_REMOVED , "CKR_DEVICE_REMOVED "},
407 {CKR_ENCRYPTED_DATA_INVALID , "CKR_ENCRYPTED_DATA_INVALID "},
408 {CKR_ENCRYPTED_DATA_LEN_RANGE , "CKR_ENCRYPTED_DATA_LEN_RANGE "},
409 {CKR_FUNCTION_CANCELED , "CKR_FUNCTION_CANCELED "},
410 {CKR_FUNCTION_NOT_PARALLEL , "CKR_FUNCTION_NOT_PARALLEL "},
411 {CKR_FUNCTION_NOT_SUPPORTED , "CKR_FUNCTION_NOT_SUPPORTED "},
412 {CKR_KEY_HANDLE_INVALID , "CKR_KEY_HANDLE_INVALID "},
413 {CKR_KEY_SIZE_RANGE , "CKR_KEY_SIZE_RANGE "},
414 {CKR_KEY_TYPE_INCONSISTENT , "CKR_KEY_TYPE_INCONSISTENT "},
415 {CKR_KEY_NOT_NEEDED , "CKR_KEY_NOT_NEEDED "},
416 {CKR_KEY_CHANGED , "CKR_KEY_CHANGED "},
417 {CKR_KEY_NEEDED , "CKR_KEY_NEEDED "},
418 {CKR_KEY_INDIGESTIBLE , "CKR_KEY_INDIGESTIBLE "},
419 {CKR_KEY_FUNCTION_NOT_PERMITTED , "CKR_KEY_FUNCTION_NOT_PERMITTED "},
420 {CKR_KEY_NOT_WRAPPABLE , "CKR_KEY_NOT_WRAPPABLE "},
421 {CKR_KEY_UNEXTRACTABLE , "CKR_KEY_UNEXTRACTABLE "},
422 {CKR_MECHANISM_INVALID , "CKR_MECHANISM_INVALID "},
423 {CKR_MECHANISM_PARAM_INVALID , "CKR_MECHANISM_PARAM_INVALID "},
424 {CKR_OBJECT_HANDLE_INVALID , "CKR_OBJECT_HANDLE_INVALID "},
425 {CKR_OPERATION_ACTIVE , "CKR_OPERATION_ACTIVE "},
426 {CKR_OPERATION_NOT_INITIALIZED , "CKR_OPERATION_NOT_INITIALIZED "},
427 {CKR_PIN_INCORRECT , "CKR_PIN_INCORRECT "},
428 {CKR_PIN_INVALID , "CKR_PIN_INVALID "},
429 {CKR_PIN_LEN_RANGE , "CKR_PIN_LEN_RANGE "},
430 {CKR_PIN_EXPIRED , "CKR_PIN_EXPIRED "},
431 {CKR_PIN_LOCKED , "CKR_PIN_LOCKED "},
432 {CKR_SESSION_CLOSED , "CKR_SESSION_CLOSED "},
433 {CKR_SESSION_COUNT , "CKR_SESSION_COUNT "},
434 {CKR_SESSION_HANDLE_INVALID , "CKR_SESSION_HANDLE_INVALID "},
435 {CKR_SESSION_PARALLEL_NOT_SUPPORTED , "CKR_SESSION_PARALLEL_NOT_SUPPORTED "},
436 {CKR_SESSION_READ_ONLY , "CKR_SESSION_READ_ONLY "},
437 {CKR_SESSION_EXISTS , "CKR_SESSION_EXISTS "},
438 {CKR_SESSION_READ_ONLY_EXISTS , "CKR_SESSION_READ_ONLY_EXISTS "},
439 {CKR_SESSION_READ_WRITE_SO_EXISTS , "CKR_SESSION_READ_WRITE_SO_EXISTS "},
440 {CKR_SIGNATURE_INVALID , "CKR_SIGNATURE_INVALID "},
441 {CKR_SIGNATURE_LEN_RANGE , "CKR_SIGNATURE_LEN_RANGE "},
442 {CKR_TEMPLATE_INCOMPLETE , "CKR_TEMPLATE_INCOMPLETE "},
443 {CKR_TEMPLATE_INCONSISTENT , "CKR_TEMPLATE_INCONSISTENT "},
444 {CKR_TOKEN_NOT_PRESENT , "CKR_TOKEN_NOT_PRESENT "},
445 {CKR_TOKEN_NOT_RECOGNIZED , "CKR_TOKEN_NOT_RECOGNIZED "},
446 {CKR_TOKEN_WRITE_PROTECTED , "CKR_TOKEN_WRITE_PROTECTED "},
447 {CKR_UNWRAPPING_KEY_HANDLE_INVALID , "CKR_UNWRAPPING_KEY_HANDLE_INVALID "},
448 {CKR_UNWRAPPING_KEY_SIZE_RANGE , "CKR_UNWRAPPING_KEY_SIZE_RANGE "},
449 {CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"},
450 {CKR_USER_ALREADY_LOGGED_IN , "CKR_USER_ALREADY_LOGGED_IN "},
451 {CKR_USER_NOT_LOGGED_IN , "CKR_USER_NOT_LOGGED_IN "},
452 {CKR_USER_PIN_NOT_INITIALIZED , "CKR_USER_PIN_NOT_INITIALIZED "},
453 {CKR_USER_TYPE_INVALID , "CKR_USER_TYPE_INVALID "},
454 {CKR_USER_ANOTHER_ALREADY_LOGGED_IN , "CKR_USER_ANOTHER_ALREADY_LOGGED_IN "},
455 {CKR_USER_TOO_MANY_TYPES , "CKR_USER_TOO_MANY_TYPES "},
456 {CKR_WRAPPED_KEY_INVALID , "CKR_WRAPPED_KEY_INVALID "},
457 {CKR_WRAPPED_KEY_LEN_RANGE , "CKR_WRAPPED_KEY_LEN_RANGE "},
458 {CKR_WRAPPING_KEY_HANDLE_INVALID , "CKR_WRAPPING_KEY_HANDLE_INVALID "},
459 {CKR_WRAPPING_KEY_SIZE_RANGE , "CKR_WRAPPING_KEY_SIZE_RANGE "},
460 {CKR_WRAPPING_KEY_TYPE_INCONSISTENT , "CKR_WRAPPING_KEY_TYPE_INCONSISTENT "},
461 {CKR_RANDOM_SEED_NOT_SUPPORTED , "CKR_RANDOM_SEED_NOT_SUPPORTED "},
462 {CKR_RANDOM_NO_RNG , "CKR_RANDOM_NO_RNG "},
463 {CKR_DOMAIN_PARAMS_INVALID , "CKR_DOMAIN_PARAMS_INVALID "},
464 {CKR_BUFFER_TOO_SMALL , "CKR_BUFFER_TOO_SMALL "},
465 {CKR_SAVED_STATE_INVALID , "CKR_SAVED_STATE_INVALID "},
466 {CKR_INFORMATION_SENSITIVE , "CKR_INFORMATION_SENSITIVE "},
467 {CKR_STATE_UNSAVEABLE , "CKR_STATE_UNSAVEABLE "},
468 {CKR_CRYPTOKI_NOT_INITIALIZED , "CKR_CRYPTOKI_NOT_INITIALIZED "},
469 {CKR_CRYPTOKI_ALREADY_INITIALIZED , "CKR_CRYPTOKI_ALREADY_INITIALIZED "},
470 {CKR_MUTEX_BAD , "CKR_MUTEX_BAD "},
471 {CKR_MUTEX_NOT_LOCKED , "CKR_MUTEX_NOT_LOCKED "},
472 {CKR_FUNCTION_REJECTED , "CKR_FUNCTION_REJECTED "},
473 {CKR_VENDOR_DEFINED , "CKR_VENDOR_DEFINED "},
474 {0xCE534351 , "CKR_NETSCAPE_CERTDB_FAILED "},
475 {0xCE534352 , "CKR_NETSCAPE_KEYDB_FAILED "}
477 };
479 static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str);
481 /* Returns constant error string for "CRV".
482 * Returns "unknown error" if errNum is unknown.
483 */
484 static const char *
485 CK_RVtoStr(CK_RV errNum) {
486 CK_ULONG low = 1;
487 CK_ULONG high = numStrings - 1;
488 CK_ULONG i;
489 CK_RV num;
490 static int initDone;
492 /* make sure table is in ascending order.
493 * binary search depends on it.
494 */
495 if (!initDone) {
496 CK_RV lastNum = CKR_OK;
497 for (i = low; i <= high; ++i) {
498 num = errStrings[i].errNum;
499 if (num <= lastNum) {
500 PR_fprintf(PR_STDERR,
501 "sequence error in error strings at item %d\n"
502 "error %d (%s)\n"
503 "should come after \n"
504 "error %d (%s)\n",
505 (int) i, (int) lastNum, errStrings[i-1].errString,
506 (int) num, errStrings[i].errString);
507 }
508 lastNum = num;
509 }
510 initDone = 1;
511 }
513 /* Do binary search of table. */
514 while (low + 1 < high) {
515 i = (low + high) / 2;
516 num = errStrings[i].errNum;
517 if (errNum == num)
518 return errStrings[i].errString;
519 if (errNum < num)
520 high = i;
521 else
522 low = i;
523 }
524 if (errNum == errStrings[low].errNum)
525 return errStrings[low].errString;
526 if (errNum == errStrings[high].errNum)
527 return errStrings[high].errString;
528 return "unknown error";
529 }
531 static void
532 pk11error(const char *string, CK_RV crv) {
533 PRErrorCode errorcode;
535 PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv));
537 errorcode = PR_GetError();
538 if (errorcode) {
539 PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode,
540 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
541 }
542 }
544 static void
545 logIt(const char *fmt, ...) {
546 va_list args;
548 if (verbose) {
549 va_start (args, fmt);
550 vprintf(fmt, args);
551 va_end(args);
552 }
553 }
555 static CK_RV
556 softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char * configDir,
557 const char * dbPrefix) {
559 CK_RV crv = CKR_OK;
560 CK_C_INITIALIZE_ARGS initArgs;
561 char *moduleSpec = NULL;
563 initArgs.CreateMutex = NULL;
564 initArgs.DestroyMutex = NULL;
565 initArgs.LockMutex = NULL;
566 initArgs.UnlockMutex = NULL;
567 initArgs.flags = CKF_OS_LOCKING_OK;
568 if (configDir) {
569 moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
570 "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ",
571 configDir, dbPrefix, dbPrefix);
572 } else {
573 moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' "
574 "secmod='' flags=noCertDB, noModDB");
575 }
576 if (!moduleSpec) {
577 PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n");
578 return CKR_HOST_MEMORY;
579 }
580 logIt("moduleSpec %s\n", moduleSpec);
581 initArgs.LibraryParameters = (CK_CHAR_PTR *) moduleSpec;
582 initArgs.pReserved = NULL;
584 crv = pFunctionList->C_Initialize(&initArgs);
585 if (crv != CKR_OK) {
586 pk11error("C_Initialize failed", crv);
587 goto cleanup;
588 }
590 cleanup:
591 if (moduleSpec) {
592 PR_smprintf_free(moduleSpec);
593 }
595 return crv;
596 }
598 static char *
599 filePasswd(char *pwFile)
600 {
601 unsigned char phrase[200];
602 PRFileDesc *fd;
603 PRInt32 nb;
604 int i;
606 if (!pwFile)
607 return 0;
609 fd = PR_Open(pwFile, PR_RDONLY, 0);
610 if (!fd) {
611 lperror(pwFile);
612 return NULL;
613 }
615 nb = PR_Read(fd, phrase, sizeof(phrase));
617 PR_Close(fd);
618 /* handle the Windows EOL case */
619 i = 0;
620 while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++;
621 phrase[i] = '\0';
622 if (nb == 0) {
623 PR_fprintf(PR_STDERR,"password file contains no data\n");
624 return NULL;
625 }
626 return (char*) PL_strdup((char*)phrase);
627 }
629 static void
630 checkPath(char *string)
631 {
632 char *src;
633 char *dest;
635 /*
636 * windows support convert any back slashes to
637 * forward slashes.
638 */
639 for (src=string, dest=string; *src; src++,dest++) {
640 if (*src == '\\') {
641 *dest = '/';
642 }
643 }
644 dest--;
645 /* if the last char is a / set it to 0 */
646 if (*dest == '/')
647 *dest = 0;
649 }
651 static CK_SLOT_ID *
652 getSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
653 CK_ULONG slotIndex) {
654 CK_RV crv = CKR_OK;
655 CK_SLOT_ID *pSlotList = NULL;
656 CK_ULONG slotCount;
658 /* Get slot list */
659 crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
660 NULL, &slotCount);
661 if (crv != CKR_OK) {
662 pk11error( "C_GetSlotList failed", crv);
663 return NULL;
664 }
666 if (slotIndex >= slotCount) {
667 PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count.");
668 return NULL;
669 }
671 pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID));
672 if (!pSlotList) {
673 lperror("failed to allocate slot list");
674 return NULL;
675 }
676 crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
677 pSlotList, &slotCount);
678 if (crv != CKR_OK) {
679 pk11error( "C_GetSlotList failed", crv);
680 if (pSlotList) PR_Free(pSlotList);
681 return NULL;
682 }
683 return pSlotList;
684 }
686 int main(int argc, char **argv)
687 {
688 PLOptState *optstate;
689 char *program_name;
690 char *libname = NULL;
691 PRLibrary *lib;
692 PRFileDesc *fd;
693 PRStatus rv = PR_SUCCESS;
694 const char *input_file = NULL; /* read/create encrypted data from here */
695 char *output_file = NULL; /* write new encrypted data here */
696 int bytesRead;
697 int bytesWritten;
698 unsigned char file_buf[512];
699 int count=0;
700 int keySize = 0;
701 int i;
702 PRBool verify = PR_FALSE;
703 static PRBool FIPSMODE = PR_FALSE;
704 PRBool successful = PR_FALSE;
706 #ifdef USES_LINKS
707 int ret;
708 struct stat stat_buf;
709 char link_buf[MAXPATHLEN+1];
710 char *link_file = NULL;
711 #endif
713 char *pwd = NULL;
714 char *configDir = NULL;
715 char *dbPrefix = NULL;
716 char *disableUnload = NULL;
718 CK_C_GetFunctionList pC_GetFunctionList;
719 CK_TOKEN_INFO tokenInfo;
720 CK_FUNCTION_LIST_PTR pFunctionList = NULL;
721 CK_RV crv = CKR_OK;
722 CK_SESSION_HANDLE hRwSession;
723 CK_SLOT_ID *pSlotList = NULL;
724 CK_ULONG slotIndex = 0;
725 CK_MECHANISM digestmech;
726 CK_ULONG digestLen = 0;
727 CK_BYTE digest[32]; /* SHA256_LENGTH */
728 CK_BYTE sign[64]; /* DSA SIGNATURE LENGTH */
729 CK_ULONG signLen = 0 ;
730 CK_MECHANISM signMech = {
731 CKM_DSA, NULL, 0
732 };
734 /*** DSA Key ***/
736 CK_MECHANISM dsaKeyPairGenMech;
737 CK_ATTRIBUTE dsaPubKeyTemplate[5];
738 CK_ATTRIBUTE dsaPrivKeyTemplate[5];
739 CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
740 CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
742 CK_BYTE dsaPubKey[384];
743 CK_ATTRIBUTE dsaPubKeyValue;
746 program_name = strrchr(argv[0], '/');
747 program_name = program_name ? (program_name + 1) : argv[0];
748 optstate = PL_CreateOptState (argc, argv, "i:o:f:Fd:hH?k:p:P:vVs:");
749 if (optstate == NULL) {
750 lperror("PL_CreateOptState failed");
751 return 1;
752 }
754 while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
755 switch (optstate->option) {
757 case 'd':
758 if (!optstate->value) {
759 PL_DestroyOptState(optstate);
760 usage(program_name);
761 }
762 configDir = PL_strdup(optstate->value);
763 checkPath(configDir);
764 break;
766 case 'i':
767 if (!optstate->value) {
768 PL_DestroyOptState(optstate);
769 usage(program_name);
770 }
771 input_file = optstate->value;
772 break;
774 case 'o':
775 if (!optstate->value) {
776 PL_DestroyOptState(optstate);
777 usage(program_name);
778 }
779 output_file = PL_strdup(optstate->value);
780 break;
782 case 'k':
783 if (!optstate->value) {
784 PL_DestroyOptState(optstate);
785 usage(program_name);
786 }
787 keySize = atoi(optstate->value);
788 break;
790 case 'f':
791 if (!optstate->value) {
792 PL_DestroyOptState(optstate);
793 usage(program_name);
794 }
795 pwd = filePasswd((char *)optstate->value);
796 if (!pwd) usage(program_name);
797 break;
799 case 'F':
800 FIPSMODE = PR_TRUE;
801 break;
803 case 'p':
804 if (!optstate->value) {
805 PL_DestroyOptState(optstate);
806 usage(program_name);
807 }
808 pwd = PL_strdup(optstate->value);
809 break;
811 case 'P':
812 if (!optstate->value) {
813 PL_DestroyOptState(optstate);
814 usage(program_name);
815 }
816 dbPrefix = PL_strdup(optstate->value);
817 break;
819 case 'v':
820 verbose = PR_TRUE;
821 break;
823 case 'V':
824 verify = PR_TRUE;
825 break;
827 case 'H':
828 PL_DestroyOptState(optstate);
829 long_usage (program_name);
830 return 1;
831 break;
833 case 'h':
834 case '?':
835 default:
836 PL_DestroyOptState(optstate);
837 usage(program_name);
838 return 1;
839 break;
840 }
841 }
842 PL_DestroyOptState(optstate);
844 if (!input_file) {
845 usage(program_name);
846 return 1;
847 }
849 /* Get the platform-dependent library name of the
850 * NSS cryptographic module.
851 */
852 libname = PR_GetLibraryName(NULL, "softokn3");
853 assert(libname != NULL);
854 lib = PR_LoadLibrary(libname);
855 assert(lib != NULL);
856 PR_FreeLibraryName(libname);
859 if (FIPSMODE) {
860 /* FIPSMODE == FC_GetFunctionList */
861 /* library path must be set to an already signed softokn3/freebl */
862 pC_GetFunctionList = (CK_C_GetFunctionList)
863 PR_FindFunctionSymbol(lib, "FC_GetFunctionList");
864 } else {
865 /* NON FIPS mode == C_GetFunctionList */
866 pC_GetFunctionList = (CK_C_GetFunctionList)
867 PR_FindFunctionSymbol(lib, "C_GetFunctionList");
868 }
869 assert(pC_GetFunctionList != NULL);
871 crv = (*pC_GetFunctionList)(&pFunctionList);
872 assert(crv == CKR_OK);
874 if (configDir) {
875 if (!dbPrefix) {
876 dbPrefix = PL_strdup("");
877 }
878 crv = softokn_Init(pFunctionList, configDir, dbPrefix);
879 if (crv != CKR_OK) {
880 logIt("Failed to use provided database directory "
881 "will just initialize the volatile certdb.\n");
882 crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
883 }
884 } else {
885 crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
886 }
888 if (crv != CKR_OK) {
889 pk11error( "Initiailzing softoken failed", crv);
890 goto cleanup;
891 }
893 pSlotList = getSlotList(pFunctionList, slotIndex);
894 if (pSlotList == NULL) {
895 PR_fprintf(PR_STDERR, "getSlotList failed");
896 goto cleanup;
897 }
899 if ((keySize == 0) || (keySize > 1024)) {
900 CK_MECHANISM_INFO mechInfo;
901 crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotIndex],
902 CKM_DSA, &mechInfo);
903 if (crv != CKR_OK) {
904 pk11error( "Couldn't get mechanism info for DSA", crv);
905 goto cleanup;
906 }
908 if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
909 PR_fprintf(PR_STDERR,
910 "token doesn't support DSA2 (Max key size=%d)\n",
911 mechInfo.ulMaxKeySize);
912 goto cleanup;
913 }
915 if ((keySize == 0) && mechInfo.ulMaxKeySize >=2048 ) {
916 keySize = 2048;
917 } else {
918 keySize = 1024;
919 }
920 }
922 /* DSA key init */
923 if (keySize == 1024) {
924 dsaPubKeyTemplate[0].type = CKA_PRIME;
925 dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR) ′
926 dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
927 dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
928 dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR) &subprime;
929 dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
930 dsaPubKeyTemplate[2].type = CKA_BASE;
931 dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR) &base;
932 dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
933 digestmech.mechanism = CKM_SHA_1;
934 digestmech.pParameter = NULL;
935 digestmech.ulParameterLen = 0;
936 } else if (keySize == 2048) {
937 dsaPubKeyTemplate[0].type = CKA_PRIME;
938 dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR) &prime2;
939 dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2);
940 dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
941 dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR) &subprime2;
942 dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2);
943 dsaPubKeyTemplate[2].type = CKA_BASE;
944 dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR) &base2;
945 dsaPubKeyTemplate[2].ulValueLen = sizeof(base2);
946 digestmech.mechanism = CKM_SHA256;
947 digestmech.pParameter = NULL;
948 digestmech.ulParameterLen = 0;
949 } else {
950 /* future - generate pqg */
951 PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported");
952 goto cleanup;
953 }
954 dsaPubKeyTemplate[3].type = CKA_TOKEN;
955 dsaPubKeyTemplate[3].pValue = &false; /* session object */
956 dsaPubKeyTemplate[3].ulValueLen = sizeof(false);
957 dsaPubKeyTemplate[4].type = CKA_VERIFY;
958 dsaPubKeyTemplate[4].pValue = &true;
959 dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
960 dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
961 dsaKeyPairGenMech.pParameter = NULL;
962 dsaKeyPairGenMech.ulParameterLen = 0;
963 dsaPrivKeyTemplate[0].type = CKA_TOKEN;
964 dsaPrivKeyTemplate[0].pValue = &false; /* session object */
965 dsaPrivKeyTemplate[0].ulValueLen = sizeof(false);
966 dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
967 dsaPrivKeyTemplate[1].pValue = &true;
968 dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
969 dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
970 dsaPrivKeyTemplate[2].pValue = &true;
971 dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
972 dsaPrivKeyTemplate[3].type = CKA_SIGN,
973 dsaPrivKeyTemplate[3].pValue = &true;
974 dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
975 dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
976 dsaPrivKeyTemplate[4].pValue = &false;
977 dsaPrivKeyTemplate[4].ulValueLen = sizeof(false);
979 crv = pFunctionList->C_OpenSession(pSlotList[slotIndex],
980 CKF_RW_SESSION | CKF_SERIAL_SESSION,
981 NULL, NULL, &hRwSession);
982 if (crv != CKR_OK) {
983 pk11error( "Opening a read/write session failed", crv);
984 goto cleanup;
985 }
987 /* check if a password is needed */
988 crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo);
989 if (crv != CKR_OK) {
990 pk11error( "C_GetTokenInfo failed", crv);
991 goto cleanup;
992 }
993 if (tokenInfo.flags & CKF_LOGIN_REQUIRED) {
994 if (pwd) {
995 int pwdLen = strlen((const char*)pwd);
996 crv = pFunctionList->C_Login(hRwSession, CKU_USER,
997 (CK_UTF8CHAR_PTR) pwd, (CK_ULONG)pwdLen);
998 if (crv != CKR_OK) {
999 pk11error("C_Login failed", crv);
1000 goto cleanup;
1001 }
1002 } else {
1003 PR_fprintf(PR_STDERR, "Please provide the password for the token");
1004 goto cleanup;
1005 }
1006 } else if (pwd) {
1007 logIt("A password was provided but the password was not used.\n");
1008 }
1010 /* Generate a DSA key pair */
1011 logIt("Generate a DSA key pair ... \n");
1012 crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
1013 dsaPubKeyTemplate,
1014 NUM_ELEM(dsaPubKeyTemplate),
1015 dsaPrivKeyTemplate,
1016 NUM_ELEM(dsaPrivKeyTemplate),
1017 &hDSApubKey, &hDSAprivKey);
1018 if (crv != CKR_OK) {
1019 pk11error("DSA key pair generation failed", crv);
1020 goto cleanup;
1021 }
1023 /* open the shared library */
1024 fd = PR_OpenFile(input_file,PR_RDONLY,0);
1025 if (fd == NULL ) {
1026 lperror(input_file);
1027 goto cleanup;
1028 }
1029 #ifdef USES_LINKS
1030 ret = lstat(input_file, &stat_buf);
1031 if (ret < 0) {
1032 perror(input_file);
1033 goto cleanup;
1034 }
1035 if (S_ISLNK(stat_buf.st_mode)) {
1036 char *dirpath,*dirend;
1037 ret = readlink(input_file, link_buf, sizeof(link_buf) - 1);
1038 if (ret < 0) {
1039 perror(input_file);
1040 goto cleanup;
1041 }
1042 link_buf[ret] = 0;
1043 link_file = mkoutput(input_file);
1044 /* get the dirname of input_file */
1045 dirpath = PL_strdup(input_file);
1046 dirend = strrchr(dirpath, '/');
1047 if (dirend) {
1048 *dirend = '\0';
1049 ret = chdir(dirpath);
1050 if (ret < 0) {
1051 perror(dirpath);
1052 goto cleanup;
1053 }
1054 }
1055 PL_strfree(dirpath);
1056 input_file = link_buf;
1057 /* get the basename of link_file */
1058 dirend = strrchr(link_file, '/');
1059 if (dirend) {
1060 char * tmp_file = NULL;
1061 tmp_file = PL_strdup(dirend +1 );
1062 PL_strfree(link_file);
1063 link_file = tmp_file;
1064 }
1065 }
1066 #endif
1067 if (output_file == NULL) {
1068 output_file = mkoutput(input_file);
1069 }
1071 /* compute the digest */
1072 memset(digest, 0, sizeof(digest));
1073 crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
1074 if (crv != CKR_OK) {
1075 pk11error("C_DigestInit failed", crv);
1076 goto cleanup;
1077 }
1079 /* Digest the file */
1080 while ((bytesRead = PR_Read(fd,file_buf,sizeof(file_buf))) > 0) {
1081 crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
1082 bytesRead);
1083 if (crv != CKR_OK) {
1084 pk11error("C_DigestUpdate failed", crv);
1085 goto cleanup;
1086 }
1087 count += bytesRead;
1088 }
1090 /* close the input_File */
1091 PR_Close(fd);
1092 fd = NULL;
1093 if (bytesRead < 0) {
1094 lperror("0 bytes read from input file");
1095 goto cleanup;
1096 }
1098 digestLen = sizeof(digest);
1099 crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
1100 &digestLen);
1101 if (crv != CKR_OK) {
1102 pk11error("C_DigestFinal failed", crv);
1103 goto cleanup;
1104 }
1106 if (digestLen != sizeof(digest)) {
1107 PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
1108 "it should be %lu \n",digestLen, sizeof(digest));
1109 goto cleanup;
1110 }
1112 /* sign the hash */
1113 memset(sign, 0, sizeof(sign));
1114 /* SignUpdate */
1115 crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
1116 if (crv != CKR_OK) {
1117 pk11error("C_SignInit failed", crv);
1118 goto cleanup;
1119 }
1121 signLen = sizeof(sign);
1122 crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE * ) digest, digestLen,
1123 sign, &signLen);
1124 if (crv != CKR_OK) {
1125 pk11error("C_Sign failed", crv);
1126 goto cleanup;
1127 }
1129 if (signLen != sizeof(sign)) {
1130 PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
1131 "it should be %lu \n", signLen, sizeof(sign));
1132 goto cleanup;
1133 }
1135 if (verify) {
1136 crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
1137 if (crv != CKR_OK) {
1138 pk11error("C_VerifyInit failed", crv);
1139 goto cleanup;
1140 }
1141 crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
1142 sign, signLen);
1143 if (crv != CKR_OK) {
1144 pk11error("C_Verify failed", crv);
1145 goto cleanup;
1146 }
1147 }
1149 if (verbose) {
1150 int j;
1151 PR_fprintf(PR_STDERR,"Library File: %s %d bytes\n",input_file, count);
1152 PR_fprintf(PR_STDERR,"Check File: %s\n",output_file);
1153 #ifdef USES_LINKS
1154 if (link_file) {
1155 PR_fprintf(PR_STDERR,"Link: %s\n",link_file);
1156 }
1157 #endif
1158 PR_fprintf(PR_STDERR," hash: %lu bytes\n", digestLen);
1159 #define STEP 10
1160 for (i=0; i < (int) digestLen; i += STEP) {
1161 PR_fprintf(PR_STDERR," ");
1162 for (j=0; j < STEP && (i+j) < (int) digestLen; j++) {
1163 PR_fprintf(PR_STDERR," %02x", digest[i+j]);
1164 }
1165 PR_fprintf(PR_STDERR,"\n");
1166 }
1167 PR_fprintf(PR_STDERR," signature: %lu bytes\n", signLen);
1168 for (i=0; i < (int) signLen; i += STEP) {
1169 PR_fprintf(PR_STDERR," ");
1170 for (j=0; j < STEP && (i+j) < (int) signLen; j++) {
1171 PR_fprintf(PR_STDERR," %02x", sign[i+j]);
1172 }
1173 PR_fprintf(PR_STDERR,"\n");
1174 }
1175 }
1177 /* open the target signature file */
1178 fd = PR_Open(output_file,PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0666);
1179 if (fd == NULL ) {
1180 lperror(output_file);
1181 goto cleanup;
1182 }
1184 /*
1185 * we write the key out in a straight binary format because very
1186 * low level libraries need to read an parse this file. Ideally we should
1187 * just derEncode the public key (which would be pretty simple, and be
1188 * more general), but then we'd need to link the ASN.1 decoder with the
1189 * freebl libraries.
1190 */
1192 file_buf[0] = NSS_SIGN_CHK_MAGIC1;
1193 file_buf[1] = NSS_SIGN_CHK_MAGIC2;
1194 file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
1195 file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
1196 encodeInt(&file_buf[4],12); /* offset to data start */
1197 encodeInt(&file_buf[8],CKK_DSA);
1198 bytesWritten = PR_Write(fd,file_buf, 12);
1199 if (bytesWritten != 12) {
1200 lperror(output_file);
1201 goto cleanup;
1202 }
1204 /* get DSA Public KeyValue */
1205 memset(dsaPubKey, 0, sizeof(dsaPubKey));
1206 dsaPubKeyValue.type =CKA_VALUE;
1207 dsaPubKeyValue.pValue = (CK_VOID_PTR) &dsaPubKey;
1208 dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
1210 crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
1211 &dsaPubKeyValue, 1);
1212 if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
1213 pk11error("C_GetAttributeValue failed", crv);
1214 goto cleanup;
1215 }
1217 /* CKA_PRIME */
1218 rv = writeItem(fd,dsaPubKeyTemplate[0].pValue,
1219 dsaPubKeyTemplate[0].ulValueLen, output_file);
1220 if (rv != PR_SUCCESS) goto cleanup;
1221 /* CKA_SUBPRIME */
1222 rv = writeItem(fd,dsaPubKeyTemplate[1].pValue,
1223 dsaPubKeyTemplate[1].ulValueLen, output_file);
1224 if (rv != PR_SUCCESS) goto cleanup;
1225 /* CKA_BASE */
1226 rv = writeItem(fd,dsaPubKeyTemplate[2].pValue,
1227 dsaPubKeyTemplate[2].ulValueLen, output_file);
1228 if (rv != PR_SUCCESS) goto cleanup;
1229 /* DSA Public Key value */
1230 rv = writeItem(fd,dsaPubKeyValue.pValue,
1231 dsaPubKeyValue.ulValueLen, output_file);
1232 if (rv != PR_SUCCESS) goto cleanup;
1233 /* DSA SIGNATURE */
1234 rv = writeItem(fd,&sign, signLen, output_file);
1235 if (rv != PR_SUCCESS) goto cleanup;
1236 PR_Close(fd);
1238 #ifdef USES_LINKS
1239 if (link_file) {
1240 (void)unlink(link_file);
1241 ret = symlink(output_file, link_file);
1242 if (ret < 0) {
1243 perror(link_file);
1244 goto cleanup;
1245 }
1246 }
1247 #endif
1249 successful = PR_TRUE;
1251 cleanup:
1252 if (pFunctionList) {
1253 /* C_Finalize will automatically logout, close session, */
1254 /* and delete the temp objects on the token */
1255 crv = pFunctionList->C_Finalize(NULL);
1256 if (crv != CKR_OK) {
1257 pk11error("C_Finalize failed", crv);
1258 }
1259 }
1260 if (pSlotList) {
1261 PR_Free(pSlotList);
1262 }
1263 if (pwd) {
1264 PL_strfree(pwd);
1265 }
1266 if (configDir) {
1267 PL_strfree(configDir);
1268 }
1269 if (dbPrefix) {
1270 PL_strfree(dbPrefix);
1271 }
1272 if (output_file) { /* allocated by mkoutput function */
1273 PL_strfree(output_file);
1274 }
1275 #ifdef USES_LINKS
1276 if (link_file) { /* allocated by mkoutput function */
1277 PL_strfree(link_file);
1278 }
1279 #endif
1281 disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
1282 if (!disableUnload) {
1283 PR_UnloadLibrary(lib);
1284 }
1285 PR_Cleanup();
1287 if (crv != CKR_OK)
1288 return crv;
1290 return (successful) ? 0 : 1;
1291 }