1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * shlibsign creates the checksum (.chk) files for the NSS libraries,
39 * libsoftokn3/softokn3 and libfreebl/freebl (platforms can have
40 * multiple freebl variants), that contain the NSS cryptograhic boundary.
42 * The generated .chk files must be put in the same directory as
43 * the NSS libraries they were generated for.
45 * When in FIPS 140 mode, the NSS Internal FIPS PKCS #11 Module will
46 * compute the checksum for the NSS cryptographic boundary libraries
47 * and compare the checksum with the value in .chk file.
49 * $Id: shlibsign.c,v 1.19 2011/04/08 04:02:53 wtc%google.com Exp $
64 #include <sys/param.h>
65 #include <sys/types.h>
79 /* softoken headers */
86 #define NUM_ELEM(array) (sizeof(array)/sizeof(array[0]))
87 CK_BBOOL true = CK_TRUE;
88 CK_BBOOL false = CK_FALSE;
89 static PRBool verbose = PR_FALSE;
92 usage (const char *program_name)
94 PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
95 PR_fprintf (debug_out,
96 "type %s -H for more detail information.\n", program_name);
97 PR_fprintf (debug_out,
98 "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n"
99 " [-F] [-p pwd] -[P dbprefix ] "
100 "-i shared_library_name\n",
106 long_usage(const char *program_name)
108 PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
109 PR_fprintf(debug_out, "%s test program usage:\n", program_name);
110 PR_fprintf(debug_out, "\t-i <infile> shared_library_name to process\n");
111 PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
112 PR_fprintf(debug_out, "\t-d <path> database path location\n");
113 PR_fprintf(debug_out, "\t-P <prefix> database prefix\n");
114 PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n");
115 PR_fprintf(debug_out, "\t-F FIPS mode\n");
116 PR_fprintf(debug_out, "\t-p <pwd> password\n");
117 PR_fprintf(debug_out, "\t-v verbose output\n");
118 PR_fprintf(debug_out, "\t-V perform Verify operations\n");
119 PR_fprintf(debug_out, "\t-? short help message\n");
120 PR_fprintf(debug_out, "\t-h short help message\n");
121 PR_fprintf(debug_out, "\t-H this help message\n");
122 PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your ");
123 PR_fprintf(debug_out, "library path is using \n");
124 PR_fprintf(debug_out, "\t pre-existing libraries with generated ");
125 PR_fprintf(debug_out, "checksum files\n");
126 PR_fprintf(debug_out, "\t and database in FIPS mode \n");
131 mkoutput(const char *input)
133 int in_len = strlen(input);
134 char *output = PR_Malloc(in_len+sizeof(SGN_SUFFIX));
135 int index = in_len + 1 - sizeof("."SHLIB_SUFFIX);
138 (PL_strncmp(&input[index],
139 "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
142 memcpy(output,input,in_len);
143 memcpy(&output[in_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
148 lperror(const char *string) {
149 PRErrorCode errorcode;
151 errorcode = PR_GetError();
152 PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode,
153 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
157 encodeInt(unsigned char *buf, int val)
159 buf[3] = (val >> 0) & 0xff;
160 buf[2] = (val >> 8) & 0xff;
161 buf[1] = (val >> 16) & 0xff;
162 buf[0] = (val >> 24) & 0xff;
167 writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
168 CK_ULONG ulValueLen, char *file)
170 unsigned char buf[4];
172 if (ulValueLen == 0) {
173 PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n");
177 encodeInt(buf,ulValueLen);
178 bytesWritten = PR_Write(fd,buf, 4);
179 if (bytesWritten != 4) {
183 bytesWritten = PR_Write(fd, pValue, ulValueLen);
184 if (bytesWritten != ulValueLen) {
191 static const unsigned char prime[] = { 0x00,
192 0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d,
193 0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92,
194 0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7,
195 0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c,
196 0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44,
197 0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8,
198 0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69,
199 0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb,
200 0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5,
201 0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd,
202 0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77,
203 0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd,
204 0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d,
205 0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2,
206 0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77,
207 0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 };
209 static const unsigned char subprime[] = { 0x0,
210 0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5,
211 0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54,
212 0x0b, 0x31, 0x24, 0xf1 };
214 static const unsigned char base[] = {
215 0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a,
216 0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11,
217 0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23,
218 0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42,
219 0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1,
220 0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f,
221 0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f,
222 0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa,
223 0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc,
224 0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1,
225 0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18,
226 0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8,
227 0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d,
228 0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc,
229 0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36,
230 0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f };
232 static const unsigned char h[] = {
233 0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac,
234 0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6,
235 0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f,
236 0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67,
237 0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29,
238 0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd,
239 0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13,
240 0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5,
241 0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f,
242 0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2,
243 0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6,
244 0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32,
245 0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23,
246 0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9,
247 0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7,
248 0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c };
250 static const unsigned char seed[] = { 0x00,
251 0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68,
252 0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed,
253 0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85,
254 0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b,
255 0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d,
256 0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83,
257 0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2,
258 0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4,
259 0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00,
260 0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3,
261 0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36,
262 0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e,
263 0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2,
264 0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe,
265 0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc,
266 0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c };
268 static const unsigned int counter=1496;
272 const char * errString;
275 typedef struct tuple_str tuple_str;
277 static const tuple_str errStrings[] = {
278 {CKR_OK , "CKR_OK "},
279 {CKR_CANCEL , "CKR_CANCEL "},
280 {CKR_HOST_MEMORY , "CKR_HOST_MEMORY "},
281 {CKR_SLOT_ID_INVALID , "CKR_SLOT_ID_INVALID "},
282 {CKR_GENERAL_ERROR , "CKR_GENERAL_ERROR "},
283 {CKR_FUNCTION_FAILED , "CKR_FUNCTION_FAILED "},
284 {CKR_ARGUMENTS_BAD , "CKR_ARGUMENTS_BAD "},
285 {CKR_NO_EVENT , "CKR_NO_EVENT "},
286 {CKR_NEED_TO_CREATE_THREADS , "CKR_NEED_TO_CREATE_THREADS "},
287 {CKR_CANT_LOCK , "CKR_CANT_LOCK "},
288 {CKR_ATTRIBUTE_READ_ONLY , "CKR_ATTRIBUTE_READ_ONLY "},
289 {CKR_ATTRIBUTE_SENSITIVE , "CKR_ATTRIBUTE_SENSITIVE "},
290 {CKR_ATTRIBUTE_TYPE_INVALID , "CKR_ATTRIBUTE_TYPE_INVALID "},
291 {CKR_ATTRIBUTE_VALUE_INVALID , "CKR_ATTRIBUTE_VALUE_INVALID "},
292 {CKR_DATA_INVALID , "CKR_DATA_INVALID "},
293 {CKR_DATA_LEN_RANGE , "CKR_DATA_LEN_RANGE "},
294 {CKR_DEVICE_ERROR , "CKR_DEVICE_ERROR "},
295 {CKR_DEVICE_MEMORY , "CKR_DEVICE_MEMORY "},
296 {CKR_DEVICE_REMOVED , "CKR_DEVICE_REMOVED "},
297 {CKR_ENCRYPTED_DATA_INVALID , "CKR_ENCRYPTED_DATA_INVALID "},
298 {CKR_ENCRYPTED_DATA_LEN_RANGE , "CKR_ENCRYPTED_DATA_LEN_RANGE "},
299 {CKR_FUNCTION_CANCELED , "CKR_FUNCTION_CANCELED "},
300 {CKR_FUNCTION_NOT_PARALLEL , "CKR_FUNCTION_NOT_PARALLEL "},
301 {CKR_FUNCTION_NOT_SUPPORTED , "CKR_FUNCTION_NOT_SUPPORTED "},
302 {CKR_KEY_HANDLE_INVALID , "CKR_KEY_HANDLE_INVALID "},
303 {CKR_KEY_SIZE_RANGE , "CKR_KEY_SIZE_RANGE "},
304 {CKR_KEY_TYPE_INCONSISTENT , "CKR_KEY_TYPE_INCONSISTENT "},
305 {CKR_KEY_NOT_NEEDED , "CKR_KEY_NOT_NEEDED "},
306 {CKR_KEY_CHANGED , "CKR_KEY_CHANGED "},
307 {CKR_KEY_NEEDED , "CKR_KEY_NEEDED "},
308 {CKR_KEY_INDIGESTIBLE , "CKR_KEY_INDIGESTIBLE "},
309 {CKR_KEY_FUNCTION_NOT_PERMITTED , "CKR_KEY_FUNCTION_NOT_PERMITTED "},
310 {CKR_KEY_NOT_WRAPPABLE , "CKR_KEY_NOT_WRAPPABLE "},
311 {CKR_KEY_UNEXTRACTABLE , "CKR_KEY_UNEXTRACTABLE "},
312 {CKR_MECHANISM_INVALID , "CKR_MECHANISM_INVALID "},
313 {CKR_MECHANISM_PARAM_INVALID , "CKR_MECHANISM_PARAM_INVALID "},
314 {CKR_OBJECT_HANDLE_INVALID , "CKR_OBJECT_HANDLE_INVALID "},
315 {CKR_OPERATION_ACTIVE , "CKR_OPERATION_ACTIVE "},
316 {CKR_OPERATION_NOT_INITIALIZED , "CKR_OPERATION_NOT_INITIALIZED "},
317 {CKR_PIN_INCORRECT , "CKR_PIN_INCORRECT "},
318 {CKR_PIN_INVALID , "CKR_PIN_INVALID "},
319 {CKR_PIN_LEN_RANGE , "CKR_PIN_LEN_RANGE "},
320 {CKR_PIN_EXPIRED , "CKR_PIN_EXPIRED "},
321 {CKR_PIN_LOCKED , "CKR_PIN_LOCKED "},
322 {CKR_SESSION_CLOSED , "CKR_SESSION_CLOSED "},
323 {CKR_SESSION_COUNT , "CKR_SESSION_COUNT "},
324 {CKR_SESSION_HANDLE_INVALID , "CKR_SESSION_HANDLE_INVALID "},
325 {CKR_SESSION_PARALLEL_NOT_SUPPORTED , "CKR_SESSION_PARALLEL_NOT_SUPPORTED "},
326 {CKR_SESSION_READ_ONLY , "CKR_SESSION_READ_ONLY "},
327 {CKR_SESSION_EXISTS , "CKR_SESSION_EXISTS "},
328 {CKR_SESSION_READ_ONLY_EXISTS , "CKR_SESSION_READ_ONLY_EXISTS "},
329 {CKR_SESSION_READ_WRITE_SO_EXISTS , "CKR_SESSION_READ_WRITE_SO_EXISTS "},
330 {CKR_SIGNATURE_INVALID , "CKR_SIGNATURE_INVALID "},
331 {CKR_SIGNATURE_LEN_RANGE , "CKR_SIGNATURE_LEN_RANGE "},
332 {CKR_TEMPLATE_INCOMPLETE , "CKR_TEMPLATE_INCOMPLETE "},
333 {CKR_TEMPLATE_INCONSISTENT , "CKR_TEMPLATE_INCONSISTENT "},
334 {CKR_TOKEN_NOT_PRESENT , "CKR_TOKEN_NOT_PRESENT "},
335 {CKR_TOKEN_NOT_RECOGNIZED , "CKR_TOKEN_NOT_RECOGNIZED "},
336 {CKR_TOKEN_WRITE_PROTECTED , "CKR_TOKEN_WRITE_PROTECTED "},
337 {CKR_UNWRAPPING_KEY_HANDLE_INVALID , "CKR_UNWRAPPING_KEY_HANDLE_INVALID "},
338 {CKR_UNWRAPPING_KEY_SIZE_RANGE , "CKR_UNWRAPPING_KEY_SIZE_RANGE "},
339 {CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"},
340 {CKR_USER_ALREADY_LOGGED_IN , "CKR_USER_ALREADY_LOGGED_IN "},
341 {CKR_USER_NOT_LOGGED_IN , "CKR_USER_NOT_LOGGED_IN "},
342 {CKR_USER_PIN_NOT_INITIALIZED , "CKR_USER_PIN_NOT_INITIALIZED "},
343 {CKR_USER_TYPE_INVALID , "CKR_USER_TYPE_INVALID "},
344 {CKR_USER_ANOTHER_ALREADY_LOGGED_IN , "CKR_USER_ANOTHER_ALREADY_LOGGED_IN "},
345 {CKR_USER_TOO_MANY_TYPES , "CKR_USER_TOO_MANY_TYPES "},
346 {CKR_WRAPPED_KEY_INVALID , "CKR_WRAPPED_KEY_INVALID "},
347 {CKR_WRAPPED_KEY_LEN_RANGE , "CKR_WRAPPED_KEY_LEN_RANGE "},
348 {CKR_WRAPPING_KEY_HANDLE_INVALID , "CKR_WRAPPING_KEY_HANDLE_INVALID "},
349 {CKR_WRAPPING_KEY_SIZE_RANGE , "CKR_WRAPPING_KEY_SIZE_RANGE "},
350 {CKR_WRAPPING_KEY_TYPE_INCONSISTENT , "CKR_WRAPPING_KEY_TYPE_INCONSISTENT "},
351 {CKR_RANDOM_SEED_NOT_SUPPORTED , "CKR_RANDOM_SEED_NOT_SUPPORTED "},
352 {CKR_RANDOM_NO_RNG , "CKR_RANDOM_NO_RNG "},
353 {CKR_DOMAIN_PARAMS_INVALID , "CKR_DOMAIN_PARAMS_INVALID "},
354 {CKR_BUFFER_TOO_SMALL , "CKR_BUFFER_TOO_SMALL "},
355 {CKR_SAVED_STATE_INVALID , "CKR_SAVED_STATE_INVALID "},
356 {CKR_INFORMATION_SENSITIVE , "CKR_INFORMATION_SENSITIVE "},
357 {CKR_STATE_UNSAVEABLE , "CKR_STATE_UNSAVEABLE "},
358 {CKR_CRYPTOKI_NOT_INITIALIZED , "CKR_CRYPTOKI_NOT_INITIALIZED "},
359 {CKR_CRYPTOKI_ALREADY_INITIALIZED , "CKR_CRYPTOKI_ALREADY_INITIALIZED "},
360 {CKR_MUTEX_BAD , "CKR_MUTEX_BAD "},
361 {CKR_MUTEX_NOT_LOCKED , "CKR_MUTEX_NOT_LOCKED "},
362 {CKR_FUNCTION_REJECTED , "CKR_FUNCTION_REJECTED "},
363 {CKR_VENDOR_DEFINED , "CKR_VENDOR_DEFINED "},
364 {0xCE534351 , "CKR_NETSCAPE_CERTDB_FAILED "},
365 {0xCE534352 , "CKR_NETSCAPE_KEYDB_FAILED "}
369 static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str);
371 /* Returns constant error string for "CRV".
372 * Returns "unknown error" if errNum is unknown.
375 CK_RVtoStr(CK_RV errNum) {
377 CK_ULONG high = numStrings - 1;
382 /* make sure table is in ascending order.
383 * binary search depends on it.
386 CK_RV lastNum = CKR_OK;
387 for (i = low; i <= high; ++i) {
388 num = errStrings[i].errNum;
389 if (num <= lastNum) {
390 PR_fprintf(PR_STDERR,
391 "sequence error in error strings at item %d\n"
393 "should come after \n"
395 (int) i, (int) lastNum, errStrings[i-1].errString,
396 (int) num, errStrings[i].errString);
403 /* Do binary search of table. */
404 while (low + 1 < high) {
405 i = (low + high) / 2;
406 num = errStrings[i].errNum;
408 return errStrings[i].errString;
414 if (errNum == errStrings[low].errNum)
415 return errStrings[low].errString;
416 if (errNum == errStrings[high].errNum)
417 return errStrings[high].errString;
418 return "unknown error";
422 pk11error(const char *string, CK_RV crv) {
423 PRErrorCode errorcode;
425 PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv));
427 errorcode = PR_GetError();
429 PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode,
430 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
435 logIt(const char *fmt, ...) {
439 va_start (args, fmt);
446 softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char * configDir,
447 const char * dbPrefix) {
450 CK_C_INITIALIZE_ARGS initArgs;
451 char *moduleSpec = NULL;
453 initArgs.CreateMutex = NULL;
454 initArgs.DestroyMutex = NULL;
455 initArgs.LockMutex = NULL;
456 initArgs.UnlockMutex = NULL;
457 initArgs.flags = CKF_OS_LOCKING_OK;
459 moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
460 "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ",
461 configDir, dbPrefix, dbPrefix);
463 moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' "
464 "secmod='' flags=noCertDB, noModDB");
467 PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n");
468 return CKR_HOST_MEMORY;
470 logIt("moduleSpec %s\n", moduleSpec);
471 initArgs.LibraryParameters = (CK_CHAR_PTR *) moduleSpec;
472 initArgs.pReserved = NULL;
474 crv = pFunctionList->C_Initialize(&initArgs);
476 pk11error("C_Initialize failed", crv);
482 PR_smprintf_free(moduleSpec);
489 filePasswd(char *pwFile)
491 unsigned char phrase[200];
499 fd = PR_Open(pwFile, PR_RDONLY, 0);
505 nb = PR_Read(fd, phrase, sizeof(phrase));
508 /* handle the Windows EOL case */
510 while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++;
513 PR_fprintf(PR_STDERR,"password file contains no data\n");
516 return (char*) PL_strdup((char*)phrase);
520 checkPath(char *string)
526 * windows support convert any back slashes to
529 for (src=string, dest=string; *src; src++,dest++) {
535 /* if the last char is a / set it to 0 */
542 getSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
543 CK_ULONG slotIndex) {
545 CK_SLOT_ID *pSlotList = NULL;
549 crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
552 pk11error( "C_GetSlotList failed", crv);
556 if (slotIndex >= slotCount) {
557 PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count.");
561 pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID));
563 lperror("failed to allocate slot list");
566 crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
567 pSlotList, &slotCount);
569 pk11error( "C_GetSlotList failed", crv);
570 if (pSlotList) PR_Free(pSlotList);
576 int main(int argc, char **argv)
578 PLOptState *optstate;
580 char *libname = NULL;
583 PRStatus rv = PR_SUCCESS;
584 const char *input_file = NULL; /* read/create encrypted data from here */
585 char *output_file = NULL; /* write new encrypted data here */
588 unsigned char file_buf[512];
591 PRBool verify = PR_FALSE;
592 static PRBool FIPSMODE = PR_FALSE;
596 struct stat stat_buf;
597 char link_buf[MAXPATHLEN+1];
598 char *link_file = NULL;
602 char *configDir = NULL;
603 char *dbPrefix = NULL;
604 char *disableUnload = NULL;
606 CK_C_GetFunctionList pC_GetFunctionList;
607 CK_TOKEN_INFO tokenInfo;
608 CK_FUNCTION_LIST_PTR pFunctionList = NULL;
610 CK_SESSION_HANDLE hRwSession;
611 CK_SLOT_ID *pSlotList = NULL;
612 CK_ULONG slotIndex = 0;
613 CK_MECHANISM digestmech;
614 CK_ULONG digestLen = 0;
615 CK_BYTE digest[20]; /* SHA1_LENGTH */
616 CK_BYTE sign[40]; /* DSA SIGNATURE LENGTH */
617 CK_ULONG signLen = 0 ;
618 CK_MECHANISM signMech = {
624 CK_MECHANISM dsaKeyPairGenMech;
625 CK_ATTRIBUTE dsaPubKeyTemplate[5];
626 CK_ATTRIBUTE dsaPrivKeyTemplate[5];
627 CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
628 CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
630 CK_BYTE dsaPubKey[128];
631 CK_ATTRIBUTE dsaPubKeyValue;
634 dsaPubKeyTemplate[0].type = CKA_PRIME;
635 dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR) ′
636 dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
637 dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
638 dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR) &subprime;
639 dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
640 dsaPubKeyTemplate[2].type = CKA_BASE;
641 dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR) &base;
642 dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
643 dsaPubKeyTemplate[3].type = CKA_TOKEN;
644 dsaPubKeyTemplate[3].pValue = &false; /* session object */
645 dsaPubKeyTemplate[3].ulValueLen = sizeof(false);
646 dsaPubKeyTemplate[4].type = CKA_VERIFY;
647 dsaPubKeyTemplate[4].pValue = &true;
648 dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
649 dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
650 dsaKeyPairGenMech.pParameter = NULL;
651 dsaKeyPairGenMech.ulParameterLen = 0;
652 dsaPrivKeyTemplate[0].type = CKA_TOKEN;
653 dsaPrivKeyTemplate[0].pValue = &false; /* session object */
654 dsaPrivKeyTemplate[0].ulValueLen = sizeof(false);
655 dsaPrivKeyTemplate[1].type = CKA_PRIVATE;
656 dsaPrivKeyTemplate[1].pValue = &true;
657 dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
658 dsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
659 dsaPrivKeyTemplate[2].pValue = &true;
660 dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
661 dsaPrivKeyTemplate[3].type = CKA_SIGN,
662 dsaPrivKeyTemplate[3].pValue = &true;
663 dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
664 dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
665 dsaPrivKeyTemplate[4].pValue = &false;
666 dsaPrivKeyTemplate[4].ulValueLen = sizeof(false);
667 digestmech.mechanism = CKM_SHA_1;
668 digestmech.pParameter = NULL;
669 digestmech.ulParameterLen = 0;
671 program_name = strrchr(argv[0], '/');
672 program_name = program_name ? (program_name + 1) : argv[0];
673 optstate = PL_CreateOptState (argc, argv, "i:o:f:Fd:hH?p:P:vVs:");
674 if (optstate == NULL) {
675 lperror("PL_CreateOptState failed");
679 while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
680 switch (optstate->option) {
683 if (!optstate->value) {
684 PL_DestroyOptState(optstate);
687 configDir = PL_strdup(optstate->value);
688 checkPath(configDir);
692 if (!optstate->value) {
693 PL_DestroyOptState(optstate);
696 input_file = optstate->value;
700 if (!optstate->value) {
701 PL_DestroyOptState(optstate);
704 output_file = PL_strdup(optstate->value);
708 if (!optstate->value) {
709 PL_DestroyOptState(optstate);
712 pwd = filePasswd((char *)optstate->value);
713 if (!pwd) usage(program_name);
721 if (!optstate->value) {
722 PL_DestroyOptState(optstate);
725 pwd = PL_strdup(optstate->value);
729 if (!optstate->value) {
730 PL_DestroyOptState(optstate);
733 dbPrefix = PL_strdup(optstate->value);
745 PL_DestroyOptState(optstate);
746 long_usage (program_name);
753 PL_DestroyOptState(optstate);
759 PL_DestroyOptState(optstate);
766 /* Get the platform-dependent library name of the
767 * NSS cryptographic module.
769 libname = PR_GetLibraryName(NULL, "softokn3");
770 assert(libname != NULL);
771 lib = PR_LoadLibrary(libname);
773 PR_FreeLibraryName(libname);
777 /* FIPSMODE == FC_GetFunctionList */
778 /* library path must be set to an already signed softokn3/freebl */
779 pC_GetFunctionList = (CK_C_GetFunctionList)
780 PR_FindFunctionSymbol(lib, "FC_GetFunctionList");
782 /* NON FIPS mode == C_GetFunctionList */
783 pC_GetFunctionList = (CK_C_GetFunctionList)
784 PR_FindFunctionSymbol(lib, "C_GetFunctionList");
786 assert(pC_GetFunctionList != NULL);
788 crv = (*pC_GetFunctionList)(&pFunctionList);
789 assert(crv == CKR_OK);
793 dbPrefix = PL_strdup("");
795 crv = softokn_Init(pFunctionList, configDir, dbPrefix);
797 logIt("Failed to use provided database directory "
798 "will just initialize the volatile certdb.\n");
799 crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
802 crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
806 pk11error( "Initiailzing softoken failed", crv);
810 pSlotList = getSlotList(pFunctionList, slotIndex);
811 if (pSlotList == NULL) {
812 PR_fprintf(PR_STDERR, "getSlotList failed");
816 crv = pFunctionList->C_OpenSession(pSlotList[slotIndex],
817 CKF_RW_SESSION | CKF_SERIAL_SESSION,
818 NULL, NULL, &hRwSession);
820 pk11error( "Opening a read/write session failed", crv);
824 /* check if a password is needed */
825 crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo);
827 pk11error( "C_GetTokenInfo failed", crv);
830 if (tokenInfo.flags & CKF_LOGIN_REQUIRED) {
832 int pwdLen = strlen((const char*)pwd);
833 crv = pFunctionList->C_Login(hRwSession, CKU_USER,
834 (CK_UTF8CHAR_PTR) pwd, (CK_ULONG)pwdLen);
836 pk11error("C_Login failed", crv);
840 PR_fprintf(PR_STDERR, "Please provide the password for the token");
844 logIt("A password was provided but the password was not used.\n");
847 /* Generate a DSA key pair */
848 logIt("Generate a DSA key pair ... \n");
849 crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
851 NUM_ELEM(dsaPubKeyTemplate),
853 NUM_ELEM(dsaPrivKeyTemplate),
854 &hDSApubKey, &hDSAprivKey);
856 pk11error("DSA key pair generation failed", crv);
860 /* open the shared library */
861 fd = PR_OpenFile(input_file,PR_RDONLY,0);
867 ret = lstat(input_file, &stat_buf);
872 if (S_ISLNK(stat_buf.st_mode)) {
873 char *dirpath,*dirend;
874 ret = readlink(input_file, link_buf, sizeof(link_buf) - 1);
880 link_file = mkoutput(input_file);
881 /* get the dirname of input_file */
882 dirpath = PL_strdup(input_file);
883 dirend = strrchr(dirpath, '/');
886 ret = chdir(dirpath);
893 input_file = link_buf;
894 /* get the basename of link_file */
895 dirend = strrchr(link_file, '/');
897 char * tmp_file = NULL;
898 tmp_file = PL_strdup(dirend +1 );
899 PL_strfree(link_file);
900 link_file = tmp_file;
904 if (output_file == NULL) {
905 output_file = mkoutput(input_file);
908 /* compute the digest */
909 memset(digest, 0, sizeof(digest));
910 crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
912 pk11error("C_DigestInit failed", crv);
916 /* Digest the file */
917 while ((bytesRead = PR_Read(fd,file_buf,sizeof(file_buf))) > 0) {
918 crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
921 pk11error("C_DigestUpdate failed", crv);
927 /* close the input_File */
931 lperror("0 bytes read from input file");
935 digestLen = sizeof(digest);
936 crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
939 pk11error("C_DigestFinal failed", crv);
943 if (digestLen != sizeof(digest)) {
944 PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
945 "it should be %lu \n",digestLen, sizeof(digest));
950 memset(sign, 0, sizeof(sign));
952 crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
954 pk11error("C_SignInit failed", crv);
958 signLen = sizeof(sign);
959 crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE * ) digest, digestLen,
962 pk11error("C_Sign failed", crv);
966 if (signLen != sizeof(sign)) {
967 PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
968 "it should be %lu \n", signLen, sizeof(sign));
973 crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
975 pk11error("C_VerifyInit failed", crv);
978 crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
981 pk11error("C_Verify failed", crv);
988 PR_fprintf(PR_STDERR,"Library File: %s %d bytes\n",input_file, count);
989 PR_fprintf(PR_STDERR,"Check File: %s\n",output_file);
992 PR_fprintf(PR_STDERR,"Link: %s\n",link_file);
995 PR_fprintf(PR_STDERR," hash: %lu bytes\n", digestLen);
997 for (i=0; i < (int) digestLen; i += STEP) {
998 PR_fprintf(PR_STDERR," ");
999 for (j=0; j < STEP && (i+j) < (int) digestLen; j++) {
1000 PR_fprintf(PR_STDERR," %02x", digest[i+j]);
1002 PR_fprintf(PR_STDERR,"\n");
1004 PR_fprintf(PR_STDERR," signature: %lu bytes\n", signLen);
1005 for (i=0; i < (int) signLen; i += STEP) {
1006 PR_fprintf(PR_STDERR," ");
1007 for (j=0; j < STEP && (i+j) < (int) signLen; j++) {
1008 PR_fprintf(PR_STDERR," %02x", sign[i+j]);
1010 PR_fprintf(PR_STDERR,"\n");
1014 /* open the target signature file */
1015 fd = PR_Open(output_file,PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0666);
1017 lperror(output_file);
1022 * we write the key out in a straight binary format because very
1023 * low level libraries need to read an parse this file. Ideally we should
1024 * just derEncode the public key (which would be pretty simple, and be
1025 * more general), but then we'd need to link the ASN.1 decoder with the
1029 file_buf[0] = NSS_SIGN_CHK_MAGIC1;
1030 file_buf[1] = NSS_SIGN_CHK_MAGIC2;
1031 file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
1032 file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
1033 encodeInt(&file_buf[4],12); /* offset to data start */
1034 encodeInt(&file_buf[8],CKK_DSA);
1035 bytesWritten = PR_Write(fd,file_buf, 12);
1036 if (bytesWritten != 12) {
1037 lperror(output_file);
1041 /* get DSA Public KeyValue */
1042 memset(dsaPubKey, 0, sizeof(dsaPubKey));
1043 dsaPubKeyValue.type =CKA_VALUE;
1044 dsaPubKeyValue.pValue = (CK_VOID_PTR) &dsaPubKey;
1045 dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
1047 crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
1048 &dsaPubKeyValue, 1);
1049 if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
1050 pk11error("C_GetAttributeValue failed", crv);
1055 rv = writeItem(fd,dsaPubKeyTemplate[0].pValue,
1056 dsaPubKeyTemplate[0].ulValueLen, output_file);
1057 if (rv != PR_SUCCESS) goto cleanup;
1059 rv = writeItem(fd,dsaPubKeyTemplate[1].pValue,
1060 dsaPubKeyTemplate[1].ulValueLen, output_file);
1061 if (rv != PR_SUCCESS) goto cleanup;
1063 rv = writeItem(fd,dsaPubKeyTemplate[2].pValue,
1064 dsaPubKeyTemplate[2].ulValueLen, output_file);
1065 if (rv != PR_SUCCESS) goto cleanup;
1066 /* DSA Public Key value */
1067 rv = writeItem(fd,dsaPubKeyValue.pValue,
1068 dsaPubKeyValue.ulValueLen, output_file);
1069 if (rv != PR_SUCCESS) goto cleanup;
1071 rv = writeItem(fd,&sign, signLen, output_file);
1072 if (rv != PR_SUCCESS) goto cleanup;
1077 (void)unlink(link_file);
1078 ret = symlink(output_file, link_file);
1087 if (pFunctionList) {
1088 /* C_Finalize will automatically logout, close session, */
1089 /* and delete the temp objects on the token */
1090 crv = pFunctionList->C_Finalize(NULL);
1091 if (crv != CKR_OK) {
1092 pk11error("C_Finalize failed", crv);
1102 PL_strfree(configDir);
1105 PL_strfree(dbPrefix);
1107 if (output_file) { /* allocated by mkoutput function */
1108 PL_strfree(output_file);
1111 if (link_file) { /* allocated by mkoutput function */
1112 PL_strfree(link_file);
1116 disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
1117 if (!disableUnload) {
1118 PR_UnloadLibrary(lib);