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)&prime;
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