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