shlibsign.c (73409B)
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 #define COMPAT_MAJOR 0x01 23 #define COMPAT_MINOR 0x02 24 25 #include <assert.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <stdarg.h> 30 31 #ifdef USES_LINKS 32 #include <unistd.h> 33 #include <sys/param.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #endif 37 38 /* nspr headers */ 39 #include "prlink.h" 40 #include "prprf.h" 41 #include "prenv.h" 42 #include "plgetopt.h" 43 #include "prinit.h" 44 #include "prmem.h" 45 #include "plstr.h" 46 #include "prerror.h" 47 48 /* softoken headers */ 49 #include "pkcs11.h" 50 #include "pkcs11t.h" 51 52 /* freebl headers */ 53 #include "shsign.h" 54 55 /* nss headers for definition of HASH_HashType */ 56 #include "hasht.h" 57 58 /* other basic nss header */ 59 #include "secport.h" 60 #include "basicutil.h" 61 #include "secitem.h" 62 #include "nssutil.h" 63 64 CK_BBOOL cktrue = CK_TRUE; 65 CK_BBOOL ckfalse = CK_FALSE; 66 CK_OBJECT_CLASS secret_key_obj_class = CKO_SECRET_KEY; 67 static PRBool verbose = PR_FALSE; 68 static PRBool verify = PR_FALSE; 69 static PRBool compat = PR_FALSE; 70 71 typedef enum { 72 mode_default, 73 mode_fips, 74 mode_nonfips, 75 } ModeTypes; 76 77 static const char * 78 getFunctionListName(ModeTypes mode) 79 { 80 switch (mode) { 81 case mode_default: 82 return "C_GetFunctionList"; 83 case mode_fips: 84 return "FC_GetFunctionList"; 85 case mode_nonfips: 86 return "NSC_GetFunctionList"; 87 } 88 return "C_GetFunctionList"; 89 } 90 91 typedef struct HashTableStruct { 92 char *name; 93 CK_MECHANISM_TYPE hash; 94 CK_MECHANISM_TYPE hmac; 95 CK_KEY_TYPE keyType; 96 HASH_HashType hashType; 97 CK_ULONG hashLength; 98 } HashTable; 99 100 #define CKR_INTERNAL_OUT_FAILURE 0x80111111 101 #define CKR_INTERNAL_IN_FAILURE 0x80222222 102 #define CKM_SHA1 CKM_SHA_1 103 #define CKM_SHA1_HMAC CKM_SHA_1_HMAC 104 #define CKK_SHA1_HMAC CKK_SHA_1_HMAC 105 #define MKHASH(name, mech) \ 106 { \ 107 name, CKM_##mech, CKM_##mech##_HMAC, \ 108 CKK_##mech##_HMAC, HASH_Alg##mech, mech##_LENGTH \ 109 } 110 static HashTable hashTable[] = { 111 MKHASH("sha-1", SHA1), MKHASH("sha1", SHA1), MKHASH("sha224", SHA224), 112 MKHASH("sha256", SHA256), MKHASH("sha384", SHA384), 113 MKHASH("sha512", SHA512) 114 }; 115 static size_t hashTableSize = PR_ARRAY_SIZE(hashTable); 116 117 const HashTable * 118 findHash(const char *hashName) 119 { 120 int i; 121 122 for (i = 0; i < hashTableSize; i++) { 123 if (PL_strcasecmp(hashTable[i].name, hashName) == 0) { 124 return &hashTable[i]; 125 } 126 } 127 return NULL; 128 } 129 130 static void 131 usage(const char *program_name) 132 { 133 int i; 134 const char *comma = ""; 135 PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError); 136 PR_fprintf(debug_out, 137 "type %s -H for more detail information.\n", program_name); 138 PR_fprintf(debug_out, 139 "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n" 140 " [-F|-C] [-p pwd] -[P dbprefix ] [-t hash]\n" 141 " [-D] [-k keysize] [-c] [-K key]\n" 142 " -i shared_library_name\n", 143 program_name); 144 PR_fprintf(debug_out, "Valid Hashes: "); 145 for (i = 0; i < hashTableSize; i++) { 146 PR_fprintf(debug_out, "%s%s", comma, hashTable[i].name); 147 comma = ", "; 148 } 149 PR_fprintf(debug_out, "\n"); 150 exit(1); 151 } 152 153 static void 154 long_usage(const char *program_name) 155 { 156 PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError); 157 int i; 158 const char *comma = ""; 159 PR_fprintf(debug_out, "%s test program usage:\n", program_name); 160 PR_fprintf(debug_out, "\t-i <infile> shared_library_name to process\n"); 161 PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n"); 162 PR_fprintf(debug_out, "\t-d <path> database path location\n"); 163 PR_fprintf(debug_out, "\t-t <hash> Hash for HMAC/or DSA\n"); 164 PR_fprintf(debug_out, "\t-D Sign with DSA rather than HMAC\n"); 165 PR_fprintf(debug_out, "\t-k <keysize> size of the DSA key\n"); 166 PR_fprintf(debug_out, "\t-K <key> key-material to use for hmac (hex-string, without leading 0x)\n"); 167 PR_fprintf(debug_out, "\t-c Use compatible versions for old NSS\n"); 168 PR_fprintf(debug_out, "\t-P <prefix> database prefix\n"); 169 PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n"); 170 PR_fprintf(debug_out, "\t-F force FIPS mode\n"); 171 PR_fprintf(debug_out, "\t-C force Non-FIPS mode\n"); 172 PR_fprintf(debug_out, "\t-p <pwd> password\n"); 173 PR_fprintf(debug_out, "\t-v verbose output\n"); 174 PR_fprintf(debug_out, "\t-V perform Verify operations\n"); 175 PR_fprintf(debug_out, "\t-? short help message\n"); 176 PR_fprintf(debug_out, "\t-h short help message\n"); 177 PR_fprintf(debug_out, "\t-H this help message\n"); 178 PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your "); 179 PR_fprintf(debug_out, "library path is using \n"); 180 PR_fprintf(debug_out, "\t pre-existing libraries with generated "); 181 PR_fprintf(debug_out, "checksum files\n"); 182 PR_fprintf(debug_out, "\t and database in FIPS mode \n"); 183 PR_fprintf(debug_out, "\n\n\tNote: -F and -C are mutually exclusive, "); 184 PR_fprintf(debug_out, "you can only include of of them.\n"); 185 PR_fprintf(debug_out, "Valid Hashes: "); 186 for (i = 0; i < hashTableSize; i++) { 187 PR_fprintf(debug_out, "%s%s", comma, hashTable[i].name); 188 comma = ", "; 189 } 190 PR_fprintf(debug_out, "\n"); 191 exit(1); 192 } 193 194 static char * 195 mkoutput(const char *input) 196 { 197 int in_len = strlen(input); 198 char *output = PR_Malloc(in_len + sizeof(SGN_SUFFIX)); 199 int index = in_len + 1 - sizeof("." SHLIB_SUFFIX); 200 201 if ((index > 0) && 202 (PL_strncmp(&input[index], 203 "." SHLIB_SUFFIX, sizeof("." SHLIB_SUFFIX)) == 0)) { 204 in_len = index; 205 } 206 memcpy(output, input, in_len); 207 memcpy(&output[in_len], SGN_SUFFIX, sizeof(SGN_SUFFIX)); 208 return output; 209 } 210 211 /* 212 * There are 3 error functions in this code: 213 * print_error: just prints the string to stderr. Used in cases where 214 * the error is discovered in this code rather than returned 215 * from a library. 216 * lperror: prints the error from NSPR or NSS code (including SECUTIL code). 217 * it works like perror for NSPR and NSS. 218 * pk11error: prints the error based on the pkcs #11 return code. it also 219 * looks up the NSPR/NSS error code and prints it if it exists. 220 */ 221 static void 222 print_error(const char *string) 223 { 224 PR_fprintf(PR_STDERR, "%s\n", string); 225 } 226 227 static void 228 lperror(const char *string) 229 { 230 PRErrorCode errorcode; 231 232 errorcode = PR_GetError(); 233 PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode, 234 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT)); 235 } 236 237 static void 238 encodeInt(unsigned char *buf, int val) 239 { 240 buf[3] = (val >> 0) & 0xff; 241 buf[2] = (val >> 8) & 0xff; 242 buf[1] = (val >> 16) & 0xff; 243 buf[0] = (val >> 24) & 0xff; 244 return; 245 } 246 247 static PRStatus 248 writeItem(PRFileDesc *fd, CK_VOID_PTR pValue, CK_ULONG ulValueLen) 249 { 250 unsigned char buf[4]; 251 int bytesWritten; 252 if (ulValueLen == 0) { 253 PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n"); 254 return PR_FAILURE; 255 } 256 257 encodeInt(buf, ulValueLen); 258 bytesWritten = PR_Write(fd, buf, 4); 259 if (bytesWritten != 4) { 260 return PR_FAILURE; 261 } 262 bytesWritten = PR_Write(fd, pValue, ulValueLen); 263 if (bytesWritten < 0 || (CK_ULONG)bytesWritten != ulValueLen) { 264 return PR_FAILURE; 265 } 266 return PR_SUCCESS; 267 } 268 269 static const unsigned char prime[] = { 0x00, 270 0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d, 271 0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92, 272 0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7, 273 0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c, 274 0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44, 275 0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8, 276 0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69, 277 0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb, 278 0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5, 279 0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd, 280 0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77, 281 0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd, 282 0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d, 283 0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2, 284 0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77, 285 0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 }; 286 287 static const unsigned char subprime[] = { 0x0, 288 0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5, 289 0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54, 290 0x0b, 0x31, 0x24, 0xf1 }; 291 292 static const unsigned char base[] = { 293 0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a, 294 0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11, 295 0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23, 296 0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42, 297 0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1, 298 0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f, 299 0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f, 300 0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa, 301 0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc, 302 0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1, 303 0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18, 304 0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8, 305 0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d, 306 0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc, 307 0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36, 308 0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f 309 }; 310 311 /* 312 * The constants h, seed, & counter aren't used in the code; they're provided 313 * here (commented-out) so that human readers can verify that our our PQG 314 * parameters were generated properly. 315 static const unsigned char h[] = { 316 0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac, 317 0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6, 318 0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f, 319 0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67, 320 0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29, 321 0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd, 322 0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13, 323 0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5, 324 0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f, 325 0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2, 326 0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6, 327 0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32, 328 0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23, 329 0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9, 330 0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7, 331 0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c }; 332 333 static const unsigned char seed[] = { 0x00, 334 0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68, 335 0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed, 336 0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85, 337 0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b, 338 0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d, 339 0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83, 340 0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2, 341 0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4, 342 0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00, 343 0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3, 344 0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36, 345 0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e, 346 0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2, 347 0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe, 348 0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc, 349 0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c }; 350 351 static const unsigned int counter=1496; 352 */ 353 354 static const unsigned char prime2[] = { 0x00, 355 0xa4, 0xc2, 0x83, 0x4f, 0x36, 0xd3, 0x4f, 0xae, 356 0xa0, 0xb1, 0x47, 0x43, 0xa8, 0x15, 0xee, 0xad, 357 0xa3, 0x98, 0xa3, 0x29, 0x45, 0xae, 0x5c, 0xd9, 358 0x12, 0x99, 0x09, 0xdc, 0xef, 0x05, 0xb4, 0x98, 359 0x05, 0xaa, 0x07, 0xaa, 0x83, 0x89, 0xd7, 0xba, 360 0xd1, 0x25, 0x56, 0x58, 0xd1, 0x73, 0x3c, 0xd0, 361 0x91, 0x65, 0xbe, 0x27, 0x92, 0x94, 0x86, 0x95, 362 0xdb, 0xcf, 0x07, 0x13, 0xa0, 0x85, 0xd6, 0xaa, 363 0x6c, 0x1d, 0x63, 0xbf, 0xdd, 0xdf, 0xbc, 0x30, 364 0xeb, 0x42, 0x2f, 0x52, 0x11, 0xec, 0x6e, 0x65, 365 0xdf, 0x50, 0xbe, 0x28, 0x3d, 0xa4, 0xec, 0x45, 366 0x19, 0x4c, 0x13, 0x0f, 0x59, 0x74, 0x57, 0x69, 367 0x99, 0x4f, 0x4a, 0x74, 0x7f, 0x8c, 0x9e, 0xa2, 368 0xe7, 0x94, 0xc9, 0x70, 0x70, 0xd0, 0xc4, 0xda, 369 0x49, 0x5b, 0x7a, 0x7d, 0xd9, 0x71, 0x7c, 0x3b, 370 0xdc, 0xd2, 0x8a, 0x74, 0x5f, 0xce, 0x09, 0xa2, 371 0xdb, 0xec, 0xa4, 0xba, 0x75, 0xaa, 0x0a, 0x97, 372 0xa6, 0x82, 0x25, 0x90, 0x90, 0x37, 0xe4, 0x40, 373 0x05, 0x28, 0x8f, 0x98, 0x8e, 0x68, 0x01, 0xaf, 374 0x9b, 0x08, 0x2a, 0x9b, 0xd5, 0xb9, 0x8c, 0x14, 375 0xbf, 0xba, 0xcb, 0x5b, 0xda, 0x4c, 0x95, 0xb8, 376 0xdf, 0x67, 0xa6, 0x6b, 0x76, 0x8c, 0xad, 0x4f, 377 0xfd, 0x6a, 0xd6, 0xcc, 0x62, 0x71, 0x30, 0x30, 378 0xc1, 0x29, 0x84, 0xe4, 0x8e, 0x32, 0x51, 0xb6, 379 0xea, 0xfa, 0xba, 0x00, 0x99, 0x76, 0xea, 0x86, 380 0x90, 0xab, 0x2d, 0xe9, 0xfd, 0x1e, 0x8c, 0xcc, 381 0x3c, 0x2b, 0x5d, 0x13, 0x1b, 0x47, 0xb4, 0xf5, 382 0x09, 0x74, 0x1d, 0xd4, 0x78, 0xb2, 0x42, 0x19, 383 0xd6, 0x24, 0xd1, 0x68, 0xbf, 0x11, 0xf1, 0x38, 384 0xa0, 0x44, 0x9c, 0xc6, 0x51, 0x33, 0xaa, 0x42, 385 0x93, 0x9e, 0x30, 0x58, 0x9e, 0xc0, 0x70, 0xdf, 386 0x7e, 0x64, 0xb1, 0xd8, 0x68, 0x75, 0x98, 0xa7 }; 387 388 static const unsigned char subprime2[] = { 0x00, 389 0x8e, 0xab, 0xf4, 0xbe, 0x45, 0xeb, 0xa3, 0x58, 390 0x4e, 0x60, 0x15, 0x66, 0x5a, 0x4b, 0x25, 0xcf, 391 0x45, 0x77, 0x89, 0x3f, 0x73, 0x34, 0x4a, 0xe0, 392 0x9e, 0xac, 0xfd, 0xdc, 0xff, 0x9c, 0x8d, 0xe7 }; 393 394 static const unsigned char base2[] = { 0x00, 395 0x8d, 0x72, 0x32, 0x46, 0xa6, 0x5c, 0x80, 0xe3, 396 0x43, 0x0a, 0x9e, 0x94, 0x35, 0x86, 0xd4, 0x58, 397 0xa1, 0xca, 0x22, 0xb9, 0x73, 0x46, 0x0b, 0xfb, 398 0x3e, 0x33, 0xf1, 0xd5, 0xd3, 0xb4, 0x26, 0xbf, 399 0x50, 0xd7, 0xf2, 0x09, 0x33, 0x6e, 0xc0, 0x31, 400 0x1b, 0x6d, 0x07, 0x70, 0x86, 0xca, 0x57, 0xf7, 401 0x0b, 0x4a, 0x63, 0xf0, 0x6f, 0xc8, 0x8a, 0xed, 402 0x50, 0x60, 0xf3, 0x11, 0xc7, 0x44, 0xf3, 0xce, 403 0x4e, 0x50, 0x42, 0x2d, 0x85, 0x33, 0x54, 0x57, 404 0x03, 0x8d, 0xdc, 0x66, 0x4d, 0x61, 0x83, 0x17, 405 0x1c, 0x7b, 0x0d, 0x65, 0xbc, 0x8f, 0x2c, 0x19, 406 0x86, 0xfc, 0xe2, 0x9f, 0x5d, 0x67, 0xfc, 0xd4, 407 0xa5, 0xf8, 0x23, 0xa1, 0x1a, 0xa2, 0xe1, 0x11, 408 0x15, 0x84, 0x32, 0x01, 0xee, 0x88, 0xf1, 0x55, 409 0x30, 0xe9, 0x74, 0x3c, 0x1a, 0x2b, 0x54, 0x45, 410 0x2e, 0x39, 0xb9, 0x77, 0xe1, 0x32, 0xaf, 0x2d, 411 0x97, 0xe0, 0x21, 0xec, 0xf5, 0x58, 0xe1, 0xc7, 412 0x2e, 0xe0, 0x71, 0x3d, 0x29, 0xa4, 0xd6, 0xe2, 413 0x5f, 0x85, 0x9c, 0x05, 0x04, 0x46, 0x41, 0x89, 414 0x03, 0x3c, 0xfa, 0xb2, 0xcf, 0xfa, 0xd5, 0x67, 415 0xcc, 0xec, 0x68, 0xfc, 0x83, 0xd9, 0x1f, 0x2e, 416 0x4e, 0x9a, 0x5e, 0x77, 0xa1, 0xff, 0xe6, 0x6f, 417 0x04, 0x8b, 0xf9, 0x6b, 0x47, 0xc6, 0x49, 0xd2, 418 0x88, 0x6e, 0x29, 0xa3, 0x1b, 0xae, 0xe0, 0x4f, 419 0x72, 0x8a, 0x28, 0x94, 0x0c, 0x1d, 0x8c, 0x99, 420 0xa2, 0x6f, 0xf8, 0xba, 0x99, 0x90, 0xc7, 0xe5, 421 0xb1, 0x3c, 0x10, 0x34, 0x86, 0x6a, 0x6a, 0x1f, 422 0x39, 0x63, 0x58, 0xe1, 0x5e, 0x97, 0x95, 0x45, 423 0x40, 0x38, 0x45, 0x6f, 0x02, 0xb5, 0x86, 0x6e, 424 0xae, 0x2f, 0x32, 0x7e, 0xa1, 0x3a, 0x34, 0x2c, 425 0x1c, 0xd3, 0xff, 0x4e, 0x2c, 0x38, 0x1c, 0xaa, 426 0x2e, 0x66, 0xbe, 0x32, 0x3e, 0x3c, 0x06, 0x5f }; 427 428 /* 429 * The constants h2, seed2, & counter2 aren't used in the code; they're provided 430 * here (commented-out) so that human readers can verify that our our PQG 431 * parameters were generated properly. 432 static const unsigned char h2[] = { 433 0x30, 0x91, 0xa1, 0x2e, 0x40, 0xa5, 0x7d, 0xf7, 434 0xdc, 0xed, 0xee, 0x05, 0xc2, 0x31, 0x91, 0x37, 435 0xda, 0xc5, 0xe3, 0x47, 0xb5, 0x35, 0x4b, 0xfd, 436 0x18, 0xb2, 0x7e, 0x67, 0x1e, 0x92, 0x22, 0xe7, 437 0xf5, 0x00, 0x71, 0xc0, 0x86, 0x8d, 0x90, 0x31, 438 0x36, 0x3e, 0xd0, 0x94, 0x5d, 0x2f, 0x9a, 0x68, 439 0xd2, 0xf8, 0x3d, 0x5e, 0x84, 0x42, 0x35, 0xda, 440 0x75, 0xdd, 0x05, 0xf0, 0x03, 0x31, 0x39, 0xe5, 441 0xfd, 0x2f, 0x5a, 0x7d, 0x56, 0xd8, 0x26, 0xa0, 442 0x51, 0x5e, 0x32, 0xb4, 0xad, 0xee, 0xd4, 0x89, 443 0xae, 0x01, 0x7f, 0xac, 0x86, 0x98, 0x77, 0x26, 444 0x5c, 0x31, 0xd2, 0x5e, 0xbb, 0x7f, 0xf5, 0x4c, 445 0x9b, 0xf0, 0xa6, 0x37, 0x34, 0x08, 0x86, 0x6b, 446 0xce, 0xeb, 0x85, 0x66, 0x0a, 0x26, 0x8a, 0x14, 447 0x92, 0x12, 0x74, 0xf4, 0xf0, 0xcb, 0xb5, 0xfc, 448 0x38, 0xd5, 0x1e, 0xa1, 0x2f, 0x4a, 0x1a, 0xca, 449 0x66, 0xde, 0x6e, 0xe6, 0x6e, 0x1c, 0xef, 0x50, 450 0x41, 0x31, 0x09, 0xe7, 0x4a, 0xb8, 0xa3, 0xaa, 451 0x5a, 0x22, 0xbd, 0x63, 0x0f, 0xe9, 0x0e, 0xdb, 452 0xb3, 0xca, 0x7e, 0x8d, 0x40, 0xb3, 0x3e, 0x0b, 453 0x12, 0x8b, 0xb0, 0x80, 0x4d, 0x6d, 0xb0, 0x54, 454 0xbb, 0x4c, 0x1d, 0x6c, 0xa0, 0x5c, 0x9d, 0x91, 455 0xb3, 0xbb, 0xd9, 0xfc, 0x60, 0xec, 0xc1, 0xbc, 456 0xae, 0x72, 0x3f, 0xa5, 0x4f, 0x36, 0x2d, 0x2c, 457 0x81, 0x03, 0x86, 0xa2, 0x03, 0x38, 0x36, 0x8e, 458 0xad, 0x1d, 0x53, 0xc6, 0xc5, 0x9e, 0xda, 0x08, 459 0x35, 0x4f, 0xb2, 0x78, 0xba, 0xd1, 0x22, 0xde, 460 0xc4, 0x6b, 0xbe, 0x83, 0x71, 0x0f, 0xee, 0x38, 461 0x4a, 0x9f, 0xda, 0x90, 0x93, 0x6b, 0x9a, 0xf2, 462 0xeb, 0x23, 0xfe, 0x41, 0x3f, 0xf1, 0xfc, 0xee, 463 0x7f, 0x67, 0xa7, 0xb8, 0xab, 0x29, 0xf4, 0x75, 464 0x1c, 0xe9, 0xd1, 0x47, 0x7d, 0x86, 0x44, 0xe2 }; 465 466 static const unsigned char seed2[] = { 0x00, 467 0xbc, 0xae, 0xc4, 0xea, 0x4e, 0xd2, 0xed, 0x1c, 468 0x8d, 0x48, 0xed, 0xf2, 0xa5, 0xb4, 0x18, 0xba, 469 0x00, 0xcb, 0x9c, 0x75, 0x8a, 0x39, 0x94, 0x3b, 470 0xd0, 0xd6, 0x01, 0xf7, 0xc1, 0xf5, 0x9d, 0xe5, 471 0xe3, 0xb4, 0x1d, 0xf5, 0x30, 0xfe, 0x99, 0xe4, 472 0x01, 0xab, 0xc0, 0x88, 0x4e, 0x67, 0x8f, 0xc6, 473 0x72, 0x39, 0x2e, 0xac, 0x51, 0xec, 0x91, 0x41, 474 0x47, 0x71, 0x14, 0x8a, 0x1d, 0xca, 0x88, 0x15, 475 0xea, 0xc9, 0x48, 0x9a, 0x71, 0x50, 0x19, 0x38, 476 0xdb, 0x4e, 0x65, 0xd5, 0x13, 0xd8, 0x2a, 0xc4, 477 0xcd, 0xfd, 0x0c, 0xe3, 0xc3, 0x60, 0xae, 0x6d, 478 0x88, 0xf2, 0x3a, 0xd0, 0x64, 0x73, 0x32, 0x89, 479 0xcd, 0x0b, 0xb8, 0xc7, 0xa5, 0x27, 0x84, 0xd5, 480 0x83, 0x3f, 0x0e, 0x10, 0x63, 0x10, 0x78, 0xac, 481 0x6b, 0x56, 0xb2, 0x62, 0x3a, 0x44, 0x56, 0xc0, 482 0xe4, 0x33, 0xd7, 0x63, 0x4c, 0xc9, 0x6b, 0xae, 483 0xfb, 0xe2, 0x9b, 0xf4, 0x96, 0xc7, 0xf0, 0x2a, 484 0x50, 0xde, 0x86, 0x69, 0x4f, 0x42, 0x4b, 0x1c, 485 0x7c, 0xa8, 0x6a, 0xfb, 0x54, 0x47, 0x1b, 0x41, 486 0x31, 0x9e, 0x0a, 0xc6, 0xc0, 0xbc, 0x88, 0x7f, 487 0x5a, 0x42, 0xa9, 0x82, 0x58, 0x32, 0xb3, 0xeb, 488 0x54, 0x83, 0x84, 0x26, 0x92, 0xa6, 0xc0, 0x6e, 489 0x2b, 0xa6, 0x82, 0x82, 0x43, 0x58, 0x84, 0x53, 490 0x31, 0xcf, 0xd0, 0x0a, 0x11, 0x09, 0x44, 0xc8, 491 0x11, 0x36, 0xe0, 0x04, 0x85, 0x2e, 0xd1, 0x29, 492 0x6b, 0x7b, 0x00, 0x71, 0x5f, 0xef, 0x7b, 0x7a, 493 0x2d, 0x91, 0xf9, 0x84, 0x45, 0x4d, 0xc7, 0xe1, 494 0xee, 0xd4, 0xb8, 0x61, 0x3b, 0x13, 0xb7, 0xba, 495 0x95, 0x39, 0xf6, 0x3d, 0x89, 0xbd, 0xa5, 0x80, 496 0x93, 0xf7, 0xe5, 0x17, 0x05, 0xc5, 0x65, 0xb7, 497 0xde, 0xc9, 0x9f, 0x04, 0x87, 0xcf, 0x4f, 0x86, 498 0xc3, 0x29, 0x7d, 0xb7, 0x89, 0xbf, 0xe3, 0xde }; 499 500 static const unsigned int counter2=210; 501 */ 502 503 struct tuple_str { 504 CK_RV errNum; 505 const char *errString; 506 }; 507 508 typedef struct tuple_str tuple_str; 509 510 static const tuple_str errStrings[] = { 511 { CKR_OK, "CKR_OK " }, 512 { CKR_CANCEL, "CKR_CANCEL " }, 513 { CKR_HOST_MEMORY, "CKR_HOST_MEMORY " }, 514 { CKR_SLOT_ID_INVALID, "CKR_SLOT_ID_INVALID " }, 515 { CKR_GENERAL_ERROR, "CKR_GENERAL_ERROR " }, 516 { CKR_FUNCTION_FAILED, "CKR_FUNCTION_FAILED " }, 517 { CKR_ARGUMENTS_BAD, "CKR_ARGUMENTS_BAD " }, 518 { CKR_NO_EVENT, "CKR_NO_EVENT " }, 519 { CKR_NEED_TO_CREATE_THREADS, "CKR_NEED_TO_CREATE_THREADS " }, 520 { CKR_CANT_LOCK, "CKR_CANT_LOCK " }, 521 { CKR_ATTRIBUTE_READ_ONLY, "CKR_ATTRIBUTE_READ_ONLY " }, 522 { CKR_ATTRIBUTE_SENSITIVE, "CKR_ATTRIBUTE_SENSITIVE " }, 523 { CKR_ATTRIBUTE_TYPE_INVALID, "CKR_ATTRIBUTE_TYPE_INVALID " }, 524 { CKR_ATTRIBUTE_VALUE_INVALID, "CKR_ATTRIBUTE_VALUE_INVALID " }, 525 { CKR_DATA_INVALID, "CKR_DATA_INVALID " }, 526 { CKR_DATA_LEN_RANGE, "CKR_DATA_LEN_RANGE " }, 527 { CKR_DEVICE_ERROR, "CKR_DEVICE_ERROR " }, 528 { CKR_DEVICE_MEMORY, "CKR_DEVICE_MEMORY " }, 529 { CKR_DEVICE_REMOVED, "CKR_DEVICE_REMOVED " }, 530 { CKR_ENCRYPTED_DATA_INVALID, "CKR_ENCRYPTED_DATA_INVALID " }, 531 { CKR_ENCRYPTED_DATA_LEN_RANGE, "CKR_ENCRYPTED_DATA_LEN_RANGE " }, 532 { CKR_FUNCTION_CANCELED, "CKR_FUNCTION_CANCELED " }, 533 { CKR_FUNCTION_NOT_PARALLEL, "CKR_FUNCTION_NOT_PARALLEL " }, 534 { CKR_FUNCTION_NOT_SUPPORTED, "CKR_FUNCTION_NOT_SUPPORTED " }, 535 { CKR_KEY_HANDLE_INVALID, "CKR_KEY_HANDLE_INVALID " }, 536 { CKR_KEY_SIZE_RANGE, "CKR_KEY_SIZE_RANGE " }, 537 { CKR_KEY_TYPE_INCONSISTENT, "CKR_KEY_TYPE_INCONSISTENT " }, 538 { CKR_KEY_NOT_NEEDED, "CKR_KEY_NOT_NEEDED " }, 539 { CKR_KEY_CHANGED, "CKR_KEY_CHANGED " }, 540 { CKR_KEY_NEEDED, "CKR_KEY_NEEDED " }, 541 { CKR_KEY_INDIGESTIBLE, "CKR_KEY_INDIGESTIBLE " }, 542 { CKR_KEY_FUNCTION_NOT_PERMITTED, "CKR_KEY_FUNCTION_NOT_PERMITTED " }, 543 { CKR_KEY_NOT_WRAPPABLE, "CKR_KEY_NOT_WRAPPABLE " }, 544 { CKR_KEY_UNEXTRACTABLE, "CKR_KEY_UNEXTRACTABLE " }, 545 { CKR_MECHANISM_INVALID, "CKR_MECHANISM_INVALID " }, 546 { CKR_MECHANISM_PARAM_INVALID, "CKR_MECHANISM_PARAM_INVALID " }, 547 { CKR_OBJECT_HANDLE_INVALID, "CKR_OBJECT_HANDLE_INVALID " }, 548 { CKR_OPERATION_ACTIVE, "CKR_OPERATION_ACTIVE " }, 549 { CKR_OPERATION_NOT_INITIALIZED, "CKR_OPERATION_NOT_INITIALIZED " }, 550 { CKR_PIN_INCORRECT, "CKR_PIN_INCORRECT " }, 551 { CKR_PIN_INVALID, "CKR_PIN_INVALID " }, 552 { CKR_PIN_LEN_RANGE, "CKR_PIN_LEN_RANGE " }, 553 { CKR_PIN_EXPIRED, "CKR_PIN_EXPIRED " }, 554 { CKR_PIN_LOCKED, "CKR_PIN_LOCKED " }, 555 { CKR_SESSION_CLOSED, "CKR_SESSION_CLOSED " }, 556 { CKR_SESSION_COUNT, "CKR_SESSION_COUNT " }, 557 { CKR_SESSION_HANDLE_INVALID, "CKR_SESSION_HANDLE_INVALID " }, 558 { CKR_SESSION_PARALLEL_NOT_SUPPORTED, "CKR_SESSION_PARALLEL_NOT_SUPPORTED " }, 559 { CKR_SESSION_READ_ONLY, "CKR_SESSION_READ_ONLY " }, 560 { CKR_SESSION_EXISTS, "CKR_SESSION_EXISTS " }, 561 { CKR_SESSION_READ_ONLY_EXISTS, "CKR_SESSION_READ_ONLY_EXISTS " }, 562 { CKR_SESSION_READ_WRITE_SO_EXISTS, "CKR_SESSION_READ_WRITE_SO_EXISTS " }, 563 { CKR_SIGNATURE_INVALID, "CKR_SIGNATURE_INVALID " }, 564 { CKR_SIGNATURE_LEN_RANGE, "CKR_SIGNATURE_LEN_RANGE " }, 565 { CKR_TEMPLATE_INCOMPLETE, "CKR_TEMPLATE_INCOMPLETE " }, 566 { CKR_TEMPLATE_INCONSISTENT, "CKR_TEMPLATE_INCONSISTENT " }, 567 { CKR_TOKEN_NOT_PRESENT, "CKR_TOKEN_NOT_PRESENT " }, 568 { CKR_TOKEN_NOT_RECOGNIZED, "CKR_TOKEN_NOT_RECOGNIZED " }, 569 { CKR_TOKEN_WRITE_PROTECTED, "CKR_TOKEN_WRITE_PROTECTED " }, 570 { CKR_UNWRAPPING_KEY_HANDLE_INVALID, "CKR_UNWRAPPING_KEY_HANDLE_INVALID " }, 571 { CKR_UNWRAPPING_KEY_SIZE_RANGE, "CKR_UNWRAPPING_KEY_SIZE_RANGE " }, 572 { CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT" }, 573 { CKR_USER_ALREADY_LOGGED_IN, "CKR_USER_ALREADY_LOGGED_IN " }, 574 { CKR_USER_NOT_LOGGED_IN, "CKR_USER_NOT_LOGGED_IN " }, 575 { CKR_USER_PIN_NOT_INITIALIZED, "CKR_USER_PIN_NOT_INITIALIZED " }, 576 { CKR_USER_TYPE_INVALID, "CKR_USER_TYPE_INVALID " }, 577 { CKR_USER_ANOTHER_ALREADY_LOGGED_IN, "CKR_USER_ANOTHER_ALREADY_LOGGED_IN " }, 578 { CKR_USER_TOO_MANY_TYPES, "CKR_USER_TOO_MANY_TYPES " }, 579 { CKR_WRAPPED_KEY_INVALID, "CKR_WRAPPED_KEY_INVALID " }, 580 { CKR_WRAPPED_KEY_LEN_RANGE, "CKR_WRAPPED_KEY_LEN_RANGE " }, 581 { CKR_WRAPPING_KEY_HANDLE_INVALID, "CKR_WRAPPING_KEY_HANDLE_INVALID " }, 582 { CKR_WRAPPING_KEY_SIZE_RANGE, "CKR_WRAPPING_KEY_SIZE_RANGE " }, 583 { CKR_WRAPPING_KEY_TYPE_INCONSISTENT, "CKR_WRAPPING_KEY_TYPE_INCONSISTENT " }, 584 { CKR_RANDOM_SEED_NOT_SUPPORTED, "CKR_RANDOM_SEED_NOT_SUPPORTED " }, 585 { CKR_RANDOM_NO_RNG, "CKR_RANDOM_NO_RNG " }, 586 { CKR_DOMAIN_PARAMS_INVALID, "CKR_DOMAIN_PARAMS_INVALID " }, 587 { CKR_BUFFER_TOO_SMALL, "CKR_BUFFER_TOO_SMALL " }, 588 { CKR_SAVED_STATE_INVALID, "CKR_SAVED_STATE_INVALID " }, 589 { CKR_INFORMATION_SENSITIVE, "CKR_INFORMATION_SENSITIVE " }, 590 { CKR_STATE_UNSAVEABLE, "CKR_STATE_UNSAVEABLE " }, 591 { CKR_CRYPTOKI_NOT_INITIALIZED, "CKR_CRYPTOKI_NOT_INITIALIZED " }, 592 { CKR_CRYPTOKI_ALREADY_INITIALIZED, "CKR_CRYPTOKI_ALREADY_INITIALIZED " }, 593 { CKR_MUTEX_BAD, "CKR_MUTEX_BAD " }, 594 { CKR_MUTEX_NOT_LOCKED, "CKR_MUTEX_NOT_LOCKED " }, 595 { CKR_FUNCTION_REJECTED, "CKR_FUNCTION_REJECTED " }, 596 { CKR_VENDOR_DEFINED, "CKR_VENDOR_DEFINED " }, 597 { 0xCE534351, "CKR_NSS_CERTDB_FAILED " }, 598 { 0xCE534352, "CKR_NSS_KEYDB_FAILED " } 599 600 }; 601 602 static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str); 603 604 /* Returns constant error string for "CRV". 605 * Returns "unknown error" if errNum is unknown. 606 */ 607 static const char * 608 CK_RVtoStr(CK_RV errNum) 609 { 610 CK_ULONG low = 1; 611 CK_ULONG high = numStrings - 1; 612 CK_ULONG i; 613 CK_RV num; 614 static int initDone; 615 616 /* make sure table is in ascending order. 617 * binary search depends on it. 618 */ 619 if (!initDone) { 620 CK_RV lastNum = CKR_OK; 621 for (i = low; i <= high; ++i) { 622 num = errStrings[i].errNum; 623 if (num <= lastNum) { 624 PR_fprintf(PR_STDERR, 625 "sequence error in error strings at item %d\n" 626 "error %d (%s)\n" 627 "should come after \n" 628 "error %d (%s)\n", 629 (int)i, (int)lastNum, errStrings[i - 1].errString, 630 (int)num, errStrings[i].errString); 631 } 632 lastNum = num; 633 } 634 initDone = 1; 635 } 636 637 /* Do binary search of table. */ 638 while (low + 1 < high) { 639 i = low + (high - low) / 2; 640 num = errStrings[i].errNum; 641 if (errNum == num) 642 return errStrings[i].errString; 643 if (errNum < num) 644 high = i; 645 else 646 low = i; 647 } 648 if (errNum == errStrings[low].errNum) 649 return errStrings[low].errString; 650 if (errNum == errStrings[high].errNum) 651 return errStrings[high].errString; 652 return "unknown error"; 653 } 654 655 static void 656 pk11error(const char *string, CK_RV crv) 657 { 658 PRErrorCode errorcode; 659 660 PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv)); 661 662 errorcode = PR_GetError(); 663 if (errorcode) { 664 PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode, 665 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT)); 666 } 667 } 668 669 static void 670 logIt(const char *fmt, ...) 671 { 672 va_list args; 673 674 if (verbose) { 675 va_start(args, fmt); 676 vprintf(fmt, args); 677 va_end(args); 678 } 679 } 680 681 static CK_RV 682 softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char *configDir, 683 const char *dbPrefix) 684 { 685 686 CK_RV crv = CKR_OK; 687 CK_C_INITIALIZE_ARGS initArgs; 688 char *moduleSpec = NULL; 689 690 if (NSS_InitializePRErrorTable() != SECSuccess) { 691 /* this will output the NSPR eror number, and maybe the NSPR 692 * error string */ 693 lperror("Couldn't initialize error table."); 694 print_error("Can not translate error codes to strings."); 695 /* failure to initialize this table isn't fatal */ 696 } 697 698 initArgs.CreateMutex = NULL; 699 initArgs.DestroyMutex = NULL; 700 initArgs.LockMutex = NULL; 701 initArgs.UnlockMutex = NULL; 702 initArgs.flags = CKF_OS_LOCKING_OK; 703 if (configDir) { 704 moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' " 705 "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ", 706 configDir, dbPrefix, dbPrefix); 707 } else { 708 moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' " 709 "secmod='' flags=noCertDB, noModDB"); 710 } 711 if (!moduleSpec) { 712 PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n"); 713 return CKR_HOST_MEMORY; 714 } 715 logIt("moduleSpec %s\n", moduleSpec); 716 initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec; 717 initArgs.pReserved = NULL; 718 719 crv = pFunctionList->C_Initialize(&initArgs); 720 if (crv != CKR_OK) { 721 pk11error("C_Initialize failed", crv); 722 goto cleanup; 723 } 724 725 cleanup: 726 if (moduleSpec) { 727 PR_smprintf_free(moduleSpec); 728 } 729 730 return crv; 731 } 732 733 static char * 734 filePasswd(char *pwFile) 735 { 736 unsigned char phrase[500]; 737 PRFileDesc *fd; 738 PRInt32 nb; 739 int i; 740 741 if (!pwFile) 742 return 0; 743 744 fd = PR_Open(pwFile, PR_RDONLY, 0); 745 if (!fd) { 746 lperror(pwFile); 747 return NULL; 748 } 749 750 nb = PR_Read(fd, phrase, sizeof(phrase)); 751 752 PR_Close(fd); 753 /* handle the Windows EOL case */ 754 i = 0; 755 while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) 756 i++; 757 phrase[i] = '\0'; 758 if (nb == 0) { 759 PR_fprintf(PR_STDERR, "password file contains no data\n"); 760 return NULL; 761 } 762 return (char *)PL_strdup((char *)phrase); 763 } 764 765 static void 766 checkPath(char *string) 767 { 768 char *src; 769 char *dest; 770 771 /* 772 * windows support convert any back slashes to 773 * forward slashes. 774 */ 775 for (src = string, dest = string; *src; src++, dest++) { 776 if (*src == '\\') { 777 *dest = '/'; 778 } 779 } 780 dest--; 781 /* if the last char is a / set it to 0 */ 782 if (*dest == '/') 783 *dest = 0; 784 } 785 786 static CK_SLOT_ID * 787 getSlotList(CK_FUNCTION_LIST_PTR pFunctionList, 788 CK_ULONG slotIndex) 789 { 790 CK_RV crv = CKR_OK; 791 CK_SLOT_ID *pSlotList = NULL; 792 CK_ULONG slotCount; 793 794 /* Get slot list */ 795 crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */, 796 NULL, &slotCount); 797 if (crv != CKR_OK) { 798 pk11error("C_GetSlotList failed", crv); 799 return NULL; 800 } 801 802 if (slotIndex >= slotCount) { 803 PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count."); 804 return NULL; 805 } 806 807 pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID)); 808 if (!pSlotList) { 809 lperror("failed to allocate slot list"); 810 return NULL; 811 } 812 crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */, 813 pSlotList, &slotCount); 814 if (crv != CKR_OK) { 815 pk11error("C_GetSlotList failed", crv); 816 if (pSlotList) 817 PR_Free(pSlotList); 818 return NULL; 819 } 820 return pSlotList; 821 } 822 823 CK_RV 824 shlibSignDSA(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot, 825 CK_SESSION_HANDLE hRwSession, int keySize, PRFileDesc *ifd, 826 PRFileDesc *ofd, const HashTable *hash) 827 { 828 CK_MECHANISM digestmech; 829 CK_ULONG digestLen = 0; 830 CK_BYTE digest[HASH_LENGTH_MAX]; 831 CK_BYTE sign[64]; /* DSA2 SIGNATURE LENGTH */ 832 CK_ULONG signLen = 0; 833 CK_ULONG expectedSigLen = sizeof(sign); 834 CK_MECHANISM signMech = { 835 CKM_DSA, NULL, 0 836 }; 837 int bytesRead; 838 int bytesWritten; 839 unsigned char file_buf[512]; 840 NSSSignChkHeader header; 841 int count = 0; 842 CK_RV crv = CKR_GENERAL_ERROR; 843 PRStatus rv = PR_SUCCESS; 844 const char *hashName = "sha256"; /* default hash value */ 845 int i; 846 847 /*** DSA Key ***/ 848 CK_MECHANISM dsaKeyPairGenMech; 849 CK_ATTRIBUTE dsaPubKeyTemplate[5]; 850 CK_ATTRIBUTE dsaPrivKeyTemplate[5]; 851 CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE; 852 CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE; 853 CK_BYTE dsaPubKey[384]; 854 CK_ATTRIBUTE dsaPubKeyValue; 855 856 if ((keySize == 0) || (keySize > 1024)) { 857 CK_MECHANISM_INFO mechInfo; 858 crv = pFunctionList->C_GetMechanismInfo(slot, 859 CKM_DSA, &mechInfo); 860 if (crv != CKR_OK) { 861 pk11error("Couldn't get mechanism info for DSA", crv); 862 return crv; 863 } 864 865 if (keySize && (mechInfo.ulMaxKeySize < keySize)) { 866 PR_fprintf(PR_STDERR, 867 "token doesn't support DSA2 (Max key size=%d)\n", 868 mechInfo.ulMaxKeySize); 869 return crv; 870 } 871 872 if ((keySize == 0) && mechInfo.ulMaxKeySize >= 2048) { 873 keySize = 2048; 874 } else { 875 keySize = 1024; 876 } 877 } 878 879 /* DSA key init */ 880 if (keySize == 1024) { 881 dsaPubKeyTemplate[0].type = CKA_PRIME; 882 dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)′ 883 dsaPubKeyTemplate[0].ulValueLen = sizeof(prime); 884 dsaPubKeyTemplate[1].type = CKA_SUBPRIME; 885 dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime; 886 dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime); 887 dsaPubKeyTemplate[2].type = CKA_BASE; 888 dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base; 889 dsaPubKeyTemplate[2].ulValueLen = sizeof(base); 890 hashName = "sha-1"; /* use sha-1 for old dsa keys */ 891 expectedSigLen = 32; 892 } else if (keySize == 2048) { 893 dsaPubKeyTemplate[0].type = CKA_PRIME; 894 dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime2; 895 dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2); 896 dsaPubKeyTemplate[1].type = CKA_SUBPRIME; 897 dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime2; 898 dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2); 899 dsaPubKeyTemplate[2].type = CKA_BASE; 900 dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base2; 901 dsaPubKeyTemplate[2].ulValueLen = sizeof(base2); 902 digestmech.mechanism = hash ? hash->hash : CKM_SHA256; 903 digestmech.pParameter = NULL; 904 digestmech.ulParameterLen = 0; 905 } else { 906 PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported"); 907 return CKR_GENERAL_ERROR; 908 } 909 if (hash == NULL) { 910 hash = findHash(hashName); 911 } 912 if (hash == NULL) { 913 PR_fprintf(PR_STDERR, 914 "Internal error, couldn't find hash '%s' in table.\n", 915 hashName); 916 return CKR_GENERAL_ERROR; 917 } 918 digestmech.mechanism = hash->hash; 919 digestmech.pParameter = NULL; 920 digestmech.ulParameterLen = 0; 921 dsaPubKeyTemplate[3].type = CKA_TOKEN; 922 dsaPubKeyTemplate[3].pValue = &ckfalse; /* session object */ 923 dsaPubKeyTemplate[3].ulValueLen = sizeof(ckfalse); 924 dsaPubKeyTemplate[4].type = CKA_VERIFY; 925 dsaPubKeyTemplate[4].pValue = &cktrue; 926 dsaPubKeyTemplate[4].ulValueLen = sizeof(cktrue); 927 dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN; 928 dsaKeyPairGenMech.pParameter = NULL; 929 dsaKeyPairGenMech.ulParameterLen = 0; 930 dsaPrivKeyTemplate[0].type = CKA_TOKEN; 931 dsaPrivKeyTemplate[0].pValue = &ckfalse; /* session object */ 932 dsaPrivKeyTemplate[0].ulValueLen = sizeof(ckfalse); 933 dsaPrivKeyTemplate[1].type = CKA_PRIVATE; 934 dsaPrivKeyTemplate[1].pValue = &cktrue; 935 dsaPrivKeyTemplate[1].ulValueLen = sizeof(cktrue); 936 dsaPrivKeyTemplate[2].type = CKA_SENSITIVE; 937 dsaPrivKeyTemplate[2].pValue = &cktrue; 938 dsaPrivKeyTemplate[2].ulValueLen = sizeof(cktrue); 939 dsaPrivKeyTemplate[3].type = CKA_SIGN, 940 dsaPrivKeyTemplate[3].pValue = &cktrue; 941 dsaPrivKeyTemplate[3].ulValueLen = sizeof(cktrue); 942 dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE; 943 dsaPrivKeyTemplate[4].pValue = &ckfalse; 944 dsaPrivKeyTemplate[4].ulValueLen = sizeof(ckfalse); 945 946 /* Generate a DSA key pair */ 947 logIt("Generate a DSA key pair ... \n"); 948 crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech, 949 dsaPubKeyTemplate, 950 PR_ARRAY_SIZE(dsaPubKeyTemplate), 951 dsaPrivKeyTemplate, 952 PR_ARRAY_SIZE(dsaPrivKeyTemplate), 953 &hDSApubKey, &hDSAprivKey); 954 if (crv != CKR_OK) { 955 pk11error("DSA key pair generation failed", crv); 956 return crv; 957 } 958 959 /* compute the digest */ 960 memset(digest, 0, sizeof(digest)); 961 crv = pFunctionList->C_DigestInit(hRwSession, &digestmech); 962 if (crv != CKR_OK) { 963 pk11error("C_DigestInit failed", crv); 964 return crv; 965 } 966 967 /* Digest the file */ 968 while ((bytesRead = PR_Read(ifd, file_buf, sizeof(file_buf))) > 0) { 969 crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf, 970 bytesRead); 971 if (crv != CKR_OK) { 972 pk11error("C_DigestUpdate failed", crv); 973 return crv; 974 } 975 count += bytesRead; 976 } 977 978 if (bytesRead < 0) { 979 lperror("0 bytes read from input file"); 980 return CKR_INTERNAL_IN_FAILURE; 981 } 982 983 digestLen = sizeof(digest); 984 crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest, 985 &digestLen); 986 if (crv != CKR_OK) { 987 pk11error("C_DigestFinal failed", crv); 988 return crv; 989 } 990 991 if (digestLen != hash->hashLength) { 992 PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu " 993 "it should be %lu \n", 994 digestLen, sizeof(digest)); 995 return crv; 996 } 997 998 /* sign the hash */ 999 memset(sign, 0, sizeof(sign)); 1000 /* SignUpdate */ 1001 crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey); 1002 if (crv != CKR_OK) { 1003 pk11error("C_SignInit failed", crv); 1004 return crv; 1005 } 1006 1007 signLen = sizeof(sign); 1008 crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen, 1009 sign, &signLen); 1010 if (crv != CKR_OK) { 1011 pk11error("C_Sign failed", crv); 1012 return crv; 1013 } 1014 1015 if (signLen != expectedSigLen) { 1016 PR_fprintf(PR_STDERR, "signLen has incorrect length %lu " 1017 "it should be %lu \n", 1018 signLen, expectedSigLen); 1019 return crv; 1020 } 1021 1022 if (verify) { 1023 crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey); 1024 if (crv != CKR_OK) { 1025 pk11error("C_VerifyInit failed", crv); 1026 return crv; 1027 } 1028 crv = pFunctionList->C_Verify(hRwSession, digest, digestLen, 1029 sign, signLen); 1030 if (crv != CKR_OK) { 1031 pk11error("C_Verify failed", crv); 1032 return crv; 1033 } 1034 } 1035 1036 if (verbose) { 1037 int j; 1038 PR_fprintf(PR_STDERR, "Library File Size: %d bytes\n", count); 1039 PR_fprintf(PR_STDERR, " hash: %lu bytes\n", digestLen); 1040 #define STEP 10 1041 for (i = 0; i < (int)digestLen; i += STEP) { 1042 PR_fprintf(PR_STDERR, " "); 1043 for (j = 0; j < STEP && (i + j) < (int)digestLen; j++) { 1044 PR_fprintf(PR_STDERR, " %02x", digest[i + j]); 1045 } 1046 PR_fprintf(PR_STDERR, "\n"); 1047 } 1048 PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen); 1049 for (i = 0; i < (int)signLen; i += STEP) { 1050 PR_fprintf(PR_STDERR, " "); 1051 for (j = 0; j < STEP && (i + j) < (int)signLen; j++) { 1052 PR_fprintf(PR_STDERR, " %02x", sign[i + j]); 1053 } 1054 PR_fprintf(PR_STDERR, "\n"); 1055 } 1056 } 1057 1058 /* 1059 * we write the key out in a straight binary format because very 1060 * low level libraries need to read an parse this file. Ideally we should 1061 * just derEncode the public key (which would be pretty simple, and be 1062 * more general), but then we'd need to link the ASN.1 decoder with the 1063 * freebl libraries. 1064 */ 1065 1066 header.magic1 = NSS_SIGN_CHK_MAGIC1; 1067 header.magic2 = NSS_SIGN_CHK_MAGIC2; 1068 header.majorVersion = compat ? COMPAT_MAJOR : NSS_SIGN_CHK_MAJOR_VERSION; 1069 header.minorVersion = compat ? COMPAT_MINOR : NSS_SIGN_CHK_MINOR_VERSION; 1070 encodeInt(header.offset, sizeof(header)); /* offset to data start */ 1071 encodeInt(header.type, CKK_DSA); 1072 bytesWritten = PR_Write(ofd, &header, sizeof(header)); 1073 if (bytesWritten != sizeof(header)) { 1074 return CKR_INTERNAL_OUT_FAILURE; 1075 } 1076 1077 /* get DSA Public KeyValue */ 1078 memset(dsaPubKey, 0, sizeof(dsaPubKey)); 1079 dsaPubKeyValue.type = CKA_VALUE; 1080 dsaPubKeyValue.pValue = (CK_VOID_PTR)&dsaPubKey; 1081 dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey); 1082 1083 crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey, 1084 &dsaPubKeyValue, 1); 1085 if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) { 1086 pk11error("C_GetAttributeValue failed", crv); 1087 return crv; 1088 } 1089 1090 /* CKA_PRIME */ 1091 rv = writeItem(ofd, dsaPubKeyTemplate[0].pValue, 1092 dsaPubKeyTemplate[0].ulValueLen); 1093 if (rv != PR_SUCCESS) { 1094 return CKR_INTERNAL_OUT_FAILURE; 1095 } 1096 /* CKA_SUBPRIME */ 1097 rv = writeItem(ofd, dsaPubKeyTemplate[1].pValue, 1098 dsaPubKeyTemplate[1].ulValueLen); 1099 if (rv != PR_SUCCESS) { 1100 return CKR_INTERNAL_OUT_FAILURE; 1101 } 1102 /* CKA_BASE */ 1103 rv = writeItem(ofd, dsaPubKeyTemplate[2].pValue, 1104 dsaPubKeyTemplate[2].ulValueLen); 1105 if (rv != PR_SUCCESS) { 1106 return CKR_INTERNAL_OUT_FAILURE; 1107 } 1108 /* DSA Public Key value */ 1109 rv = writeItem(ofd, dsaPubKeyValue.pValue, 1110 dsaPubKeyValue.ulValueLen); 1111 if (rv != PR_SUCCESS) { 1112 return CKR_INTERNAL_OUT_FAILURE; 1113 } 1114 /* DSA SIGNATURE */ 1115 rv = writeItem(ofd, &sign, signLen); 1116 if (rv != PR_SUCCESS) { 1117 return CKR_INTERNAL_OUT_FAILURE; 1118 } 1119 1120 return CKR_OK; 1121 } 1122 1123 /* side effect, attrCount is incremented, returns zero on failure */ 1124 #define SET_ATTR(attrCount, template, templateLen, _type, _value, _len) \ 1125 if (attrCount >= templateLen) { \ 1126 return 0; \ 1127 } \ 1128 template[attrCount].type = _type; \ 1129 template[attrCount].pValue = _value; \ 1130 template[attrCount++].ulValueLen = _len; 1131 1132 /* build a template. keyLengthptr and key are both optional */ 1133 size_t 1134 buildHMACKeyTemplate(CK_ATTRIBUTE *template, 1135 size_t templateLength, 1136 const CK_BBOOL *sensitivePtr, 1137 const CK_KEY_TYPE *keyTypePtr, 1138 const CK_ULONG *keyLengthPtr, 1139 const SECItem *key) 1140 { 1141 int attrCount = 0; 1142 SET_ATTR(attrCount, template, templateLength, 1143 CKA_TOKEN, &ckfalse, sizeof(ckfalse)) 1144 SET_ATTR(attrCount, template, templateLength, 1145 CKA_PRIVATE, &ckfalse, sizeof(ckfalse)) 1146 SET_ATTR(attrCount, template, templateLength, 1147 CKA_SENSITIVE, (void *)sensitivePtr, sizeof(*sensitivePtr)) 1148 SET_ATTR(attrCount, template, templateLength, 1149 CKA_SIGN, &cktrue, sizeof(cktrue)) 1150 SET_ATTR(attrCount, template, templateLength, 1151 CKA_EXTRACTABLE, &ckfalse, sizeof(ckfalse)) 1152 SET_ATTR(attrCount, template, templateLength, 1153 CKA_KEY_TYPE, (void *)keyTypePtr, sizeof(*keyTypePtr)) 1154 if (keyLengthPtr) { 1155 SET_ATTR(attrCount, template, templateLength, 1156 CKA_VALUE_LEN, (void *)keyLengthPtr, sizeof(*keyLengthPtr)) 1157 } 1158 if (key) { 1159 SET_ATTR(attrCount, template, templateLength, 1160 CKA_CLASS, &secret_key_obj_class, sizeof(secret_key_obj_class)) 1161 SET_ATTR(attrCount, template, templateLength, 1162 CKA_VALUE, (void *)key->data, key->len) 1163 } 1164 return attrCount; 1165 } 1166 1167 /* helper functions to generate HMAC keys */ 1168 CK_RV 1169 generateHMACKey(CK_FUNCTION_LIST_PTR pFunctionList, 1170 CK_SESSION_HANDLE hRwSession, CK_MECHANISM_PTR keyGenMech, 1171 CK_ULONG keyLength, CK_KEY_TYPE keyType, CK_BBOOL sensitive, 1172 CK_OBJECT_HANDLE_PTR phHMACKey) 1173 { 1174 CK_ATTRIBUTE hmacKeyTemplate[7]; 1175 size_t templateLen; 1176 1177 templateLen = buildHMACKeyTemplate(hmacKeyTemplate, 1178 PR_ARRAY_SIZE(hmacKeyTemplate), 1179 &sensitive, &keyType, &keyLength, NULL); 1180 if (templateLen == 0) { 1181 /* this can only happen if we didn't declear hmacKeyTemplate 1182 * to be big enough... on debug builds crash with a useful 1183 * Assert. otherwise just fail (won't work until the program 1184 * is fixed). */ 1185 PORT_Assert(templateLen < PR_ARRAY_SIZE(hmacKeyTemplate)); 1186 return CKR_GENERAL_ERROR; 1187 } 1188 return pFunctionList->C_GenerateKey(hRwSession, keyGenMech, 1189 hmacKeyTemplate, templateLen, 1190 phHMACKey); 1191 } 1192 1193 /* generate an hmac and and try to extract it */ 1194 CK_RV 1195 generateAndExtractHMACKeyRaw(CK_FUNCTION_LIST_PTR pFunctionList, 1196 CK_SESSION_HANDLE hRwSession, CK_MECHANISM_PTR keyGenMech, 1197 CK_ULONG keyLength, CK_KEY_TYPE keyType, 1198 CK_ATTRIBUTE_PTR pHMACKeyValue, 1199 CK_OBJECT_HANDLE_PTR phHMACKey) 1200 { 1201 CK_RV crv; 1202 crv = generateHMACKey(pFunctionList, hRwSession, keyGenMech, keyLength, 1203 keyType, ckfalse, phHMACKey); 1204 if (crv != CKR_OK) { 1205 return crv; 1206 } 1207 crv = pFunctionList->C_GetAttributeValue(hRwSession, *phHMACKey, 1208 pHMACKeyValue, 1); 1209 if (crv != CKR_OK) { 1210 pFunctionList->C_DestroyObject(hRwSession, *phHMACKey); 1211 return crv; 1212 } 1213 return crv; 1214 } 1215 1216 /* trick to import a key in FIPS mode. 1217 * There are limitted times when this is legitimate, 1218 * if you think you need this contact the crypto team 1219 * before using it. Usually if you need this its because 1220 * you are improperly handling FIPS CPS material which is 1221 * not allowed */ 1222 CK_RV 1223 fipsImportKey(CK_FUNCTION_LIST_PTR pFunctionList, 1224 CK_SESSION_HANDLE hRwSession, const SECItem *pKeyItem, 1225 CK_KEY_TYPE keyType, CK_SESSION_HANDLE_PTR phHMACKey) 1226 { 1227 CK_OBJECT_HANDLE hTmpKey; 1228 CK_MECHANISM deriveMech = { 0, NULL, 0 }; 1229 CK_MECHANISM hmacKeyGenMech = { 0, NULL, 0 }; 1230 CK_KEY_DERIVATION_STRING_DATA deriveParams = { 0 }; 1231 CK_ATTRIBUTE hmacKeyTemplate[7]; 1232 size_t templateLen; 1233 /* put length in an appropriate size variable */ 1234 CK_ULONG keyLength = pKeyItem->len; 1235 CK_RV crv; 1236 1237 templateLen = buildHMACKeyTemplate(hmacKeyTemplate, 1238 PR_ARRAY_SIZE(hmacKeyTemplate), 1239 &cktrue, &keyType, &keyLength, NULL); 1240 if (templateLen == 0) { 1241 /* this can only happen if we didn't declear hmacKeyTemplate 1242 * to be big enough... on debug builds crash with a useful 1243 * Assert. otherwise just fail (won't work until the program 1244 * is fixed). */ 1245 PORT_Assert(templateLen < PR_ARRAY_SIZE(hmacKeyTemplate)); 1246 return CKR_GENERAL_ERROR; 1247 } 1248 1249 deriveParams.pData = pKeyItem->data; 1250 deriveParams.ulLen = pKeyItem->len; 1251 deriveMech.mechanism = CKM_CONCATENATE_DATA_AND_BASE; 1252 deriveMech.pParameter = (void *)&deriveParams; 1253 deriveMech.ulParameterLen = sizeof(deriveParams); 1254 hmacKeyGenMech.mechanism = CKM_GENERIC_SECRET_KEY_GEN; 1255 1256 /* generate a dummy key */ 1257 crv = generateHMACKey(pFunctionList, hRwSession, &hmacKeyGenMech, 1258 pKeyItem->len, keyType, cktrue, &hTmpKey); 1259 if (crv != CKR_OK) { 1260 return crv; 1261 } 1262 /* append the desired key to the front of the dummy key, and 1263 * then truncate the dummy key */ 1264 crv = pFunctionList->C_DeriveKey(hRwSession, &deriveMech, hTmpKey, 1265 hmacKeyTemplate, 1266 templateLen, 1267 phHMACKey); 1268 /* done with the dummy key, delete it */ 1269 pFunctionList->C_DestroyObject(hRwSession, hTmpKey); 1270 return crv; 1271 } 1272 1273 /* generate an hmac key and extract it. If it fails, assume we are in 1274 * FIPS mode and use generate random to generate a key and use fipsImport 1275 * to import it */ 1276 CK_RV 1277 generateAndExtractHMACKey(CK_FUNCTION_LIST_PTR pFunctionList, 1278 CK_SESSION_HANDLE hRwSession, CK_MECHANISM_PTR keyGenMech, 1279 CK_ULONG keyLength, CK_KEY_TYPE keyType, 1280 CK_ATTRIBUTE_PTR pHMACKeyValue, 1281 CK_OBJECT_HANDLE_PTR phHMACKey) 1282 { 1283 SECItem keyItem; 1284 CK_RV crv; 1285 1286 crv = generateAndExtractHMACKeyRaw(pFunctionList, hRwSession, keyGenMech, 1287 keyLength, keyType, pHMACKeyValue, 1288 phHMACKey); 1289 if (crv == CKR_OK) { 1290 return crv; 1291 } 1292 keyItem.data = pHMACKeyValue->pValue; 1293 keyItem.len = keyLength; 1294 crv = pFunctionList->C_GenerateRandom(hRwSession, keyItem.data, 1295 keyItem.len); 1296 if (crv != CKR_OK) { 1297 return crv; 1298 } 1299 pHMACKeyValue->ulValueLen = keyLength; 1300 return fipsImportKey(pFunctionList, hRwSession, &keyItem, keyType, 1301 phHMACKey); 1302 } 1303 1304 /* 1305 * import a user supplied key. If we fail, we are probably in FIPS mode, 1306 * use fipsImport to import the key 1307 */ 1308 CK_RV 1309 importHMACKey(CK_FUNCTION_LIST_PTR pFunctionList, 1310 CK_SESSION_HANDLE hRwSession, CK_OBJECT_HANDLE_PTR phHMACKey, 1311 CK_KEY_TYPE keyType, const SECItem *keyItem) 1312 { 1313 CK_ATTRIBUTE hmacKeyTemplate[8]; 1314 size_t templateLen; 1315 CK_RV crv; 1316 1317 templateLen = buildHMACKeyTemplate(hmacKeyTemplate, 1318 PR_ARRAY_SIZE(hmacKeyTemplate), 1319 &ckfalse, &keyType, NULL, keyItem); 1320 if (templateLen == 0) { 1321 /* this can only happen if we didn't declear hmacKeyTemplate 1322 * to be big enough... on debug builds crash with a useful 1323 * Assert. otherwise just fail (won't work until the program 1324 * is fixed). */ 1325 PORT_Assert(templateLen < PR_ARRAY_SIZE(hmacKeyTemplate)); 1326 return CKR_GENERAL_ERROR; 1327 } 1328 1329 crv = pFunctionList->C_CreateObject(hRwSession, 1330 hmacKeyTemplate, 1331 templateLen, 1332 phHMACKey); 1333 if (crv != CKR_OK) { 1334 crv = fipsImportKey(pFunctionList, hRwSession, 1335 keyItem, keyType, phHMACKey); 1336 return crv; 1337 } 1338 return crv; 1339 } 1340 1341 CK_RV 1342 shlibSignHMAC(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot, 1343 CK_SESSION_HANDLE hRwSession, int keySize, char *key, 1344 PRFileDesc *ifd, PRFileDesc *ofd, const HashTable *hash) 1345 { 1346 CK_MECHANISM hmacMech = { 0, NULL, 0 }; 1347 /* init the HMAC KeyValue */ 1348 CK_BYTE keyBuf[HASH_LENGTH_MAX] = { 0 }; 1349 CK_ULONG keyLen = 0; 1350 CK_BYTE sign[HASH_LENGTH_MAX]; 1351 CK_ULONG signLen = 0; 1352 int bytesRead; 1353 int bytesWritten; 1354 unsigned char file_buf[512]; 1355 NSSSignChkHeader header; 1356 int count = 0; 1357 CK_RV crv = CKR_GENERAL_ERROR; 1358 PRStatus rv = PR_SUCCESS; 1359 int i; 1360 1361 /*** HMAC Key ***/ 1362 CK_OBJECT_HANDLE hHMACKey = CK_INVALID_HANDLE; 1363 1364 if (hash == NULL) { 1365 hash = findHash("sha256"); 1366 } 1367 if (hash == NULL) { 1368 PR_fprintf(PR_STDERR, 1369 "Internal error:Could find sha256 entry in table.\n"); 1370 } 1371 1372 if (key == NULL) { 1373 CK_ATTRIBUTE hmacKeyValue; 1374 CK_MECHANISM hmacKeyGenMech = { 0, NULL, 0 }; 1375 hmacKeyGenMech.mechanism = CKM_GENERIC_SECRET_KEY_GEN; 1376 hmacKeyValue.type = CKA_VALUE; 1377 hmacKeyValue.pValue = (CK_VOID_PTR)&keyBuf; 1378 hmacKeyValue.ulValueLen = sizeof(keyBuf); 1379 1380 /* Generate a HMAC key */ 1381 logIt("Generate an HMAC key ... \n"); 1382 crv = generateAndExtractHMACKey(pFunctionList, hRwSession, 1383 &hmacKeyGenMech, 1384 hash->hashLength, hash->keyType, 1385 &hmacKeyValue, &hHMACKey); 1386 if (crv != CKR_OK) { 1387 pk11error("HMAC key generation failed", crv); 1388 return crv; 1389 } 1390 keyLen = hmacKeyValue.ulValueLen; 1391 } else { 1392 SECItem keyItem = { 0 }; 1393 if (SECU_HexString2SECItem(NULL, &keyItem, key) == NULL) { 1394 lperror("Reading HMAC key from commandline failed." 1395 " Not a valid hex-key."); 1396 return CKR_ATTRIBUTE_VALUE_INVALID; 1397 } 1398 1399 if (keyItem.len != hash->hashLength) { 1400 print_error("Supplied HMAC key does not match the HMAC hash length."); 1401 SECITEM_FreeItem(&keyItem, PR_FALSE); 1402 return CKR_ATTRIBUTE_VALUE_INVALID; 1403 } 1404 1405 logIt("Using static HMAC key ... \n"); 1406 crv = importHMACKey(pFunctionList, hRwSession, &hHMACKey, 1407 hash->keyType, &keyItem); 1408 if (crv != CKR_OK) { 1409 pk11error("HMAC key import failed", crv); 1410 SECITEM_FreeItem(&keyItem, PR_FALSE); 1411 return crv; 1412 } 1413 if (sizeof(keyBuf) < keyItem.len) { 1414 /* this is a paranoia check. It really shouldn't happen because 1415 * we already check for keyItem.len != hash->hashLength above, 1416 * and keyBuf should be big enough for the largest hash length */ 1417 print_error("Input key is too large"); 1418 SECITEM_FreeItem(&keyItem, PR_FALSE); 1419 return CKR_HOST_MEMORY; 1420 } 1421 /* save the HMAC KeyValue */ 1422 PORT_Memcpy(keyBuf, keyItem.data, keyItem.len); 1423 keyLen = keyItem.len; 1424 SECITEM_FreeItem(&keyItem, PR_FALSE); 1425 } 1426 1427 if (crv != CKR_OK) { 1428 pk11error("HMAC key generation failed", crv); 1429 return crv; 1430 } 1431 hmacMech.mechanism = hash->hmac; 1432 1433 /* compute the digest */ 1434 memset(sign, 0, sizeof(sign)); 1435 crv = pFunctionList->C_SignInit(hRwSession, &hmacMech, hHMACKey); 1436 if (crv != CKR_OK) { 1437 pk11error("C_SignInit failed", crv); 1438 return crv; 1439 } 1440 1441 /* Digest the file */ 1442 while ((bytesRead = PR_Read(ifd, file_buf, sizeof(file_buf))) > 0) { 1443 crv = pFunctionList->C_SignUpdate(hRwSession, (CK_BYTE_PTR)file_buf, 1444 bytesRead); 1445 if (crv != CKR_OK) { 1446 pk11error("C_SignUpdate failed", crv); 1447 return crv; 1448 } 1449 count += bytesRead; 1450 } 1451 1452 if (bytesRead < 0) { 1453 lperror("0 bytes read from input file"); 1454 return CKR_INTERNAL_IN_FAILURE; 1455 } 1456 1457 signLen = sizeof(sign); 1458 crv = pFunctionList->C_SignFinal(hRwSession, (CK_BYTE_PTR)sign, 1459 &signLen); 1460 if (crv != CKR_OK) { 1461 pk11error("C_SignFinal failed", crv); 1462 return crv; 1463 } 1464 1465 if (signLen != hash->hashLength) { 1466 PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu " 1467 "it should be %lu \n", 1468 signLen, hash->hashLength); 1469 return crv; 1470 } 1471 1472 if (verbose) { 1473 int j; 1474 PR_fprintf(PR_STDERR, "Library File Size: %d bytes\n", count); 1475 PR_fprintf(PR_STDERR, " key: %lu bytes\n", keyLen); 1476 #define STEP 10 1477 for (i = 0; i < (int)keyLen; i += STEP) { 1478 PR_fprintf(PR_STDERR, " "); 1479 for (j = 0; j < STEP && (i + j) < (int)keyLen; j++) { 1480 PR_fprintf(PR_STDERR, " %02x", keyBuf[i + j]); 1481 } 1482 PR_fprintf(PR_STDERR, "\n"); 1483 } 1484 PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen); 1485 for (i = 0; i < (int)signLen; i += STEP) { 1486 PR_fprintf(PR_STDERR, " "); 1487 for (j = 0; j < STEP && (i + j) < (int)signLen; j++) { 1488 PR_fprintf(PR_STDERR, " %02x", sign[i + j]); 1489 } 1490 PR_fprintf(PR_STDERR, "\n"); 1491 } 1492 } 1493 1494 /* 1495 * we write the key out in a straight binary format because very 1496 * low level libraries need to read an parse this file. Ideally we should 1497 * just derEncode the public key (which would be pretty simple, and be 1498 * more general), but then we'd need to link the ASN.1 decoder with the 1499 * freebl libraries. 1500 */ 1501 1502 header.magic1 = NSS_SIGN_CHK_MAGIC1; 1503 header.magic2 = NSS_SIGN_CHK_MAGIC2; 1504 header.majorVersion = NSS_SIGN_CHK_MAJOR_VERSION; 1505 header.minorVersion = NSS_SIGN_CHK_MINOR_VERSION; 1506 encodeInt(header.offset, sizeof(header)); /* offset to data start */ 1507 encodeInt(header.type, NSS_SIGN_CHK_FLAG_HMAC | hash->hashType); 1508 bytesWritten = PR_Write(ofd, &header, sizeof(header)); 1509 if (bytesWritten != sizeof(header)) { 1510 return CKR_INTERNAL_OUT_FAILURE; 1511 } 1512 1513 /* HMACKey */ 1514 rv = writeItem(ofd, keyBuf, keyLen); 1515 if (rv != PR_SUCCESS) { 1516 return CKR_INTERNAL_OUT_FAILURE; 1517 } 1518 /* HMAC SIGNATURE */ 1519 rv = writeItem(ofd, &sign, signLen); 1520 if (rv != PR_SUCCESS) { 1521 return CKR_INTERNAL_OUT_FAILURE; 1522 } 1523 1524 return CKR_OK; 1525 } 1526 1527 int 1528 main(int argc, char **argv) 1529 { 1530 PLOptState *optstate; 1531 char *program_name; 1532 char *libname = NULL; 1533 PRLibrary *lib = NULL; 1534 PRFileDesc *ifd = NULL; 1535 PRFileDesc *ofd = NULL; 1536 const char *input_file = NULL; /* read/create encrypted data from here */ 1537 char *output_file = NULL; /* write new encrypted data here */ 1538 unsigned int keySize = 0; 1539 ModeTypes mode = mode_default; 1540 PRBool useDSA = PR_FALSE; 1541 PRBool successful = PR_FALSE; 1542 const HashTable *hash = NULL; 1543 char *key = NULL; 1544 1545 #ifdef USES_LINKS 1546 int ret; 1547 struct stat stat_buf; 1548 char link_buf[MAXPATHLEN + 1]; 1549 char *link_file = NULL; 1550 #endif 1551 1552 char *pwd = NULL; 1553 char *configDir = NULL; 1554 char *dbPrefix = NULL; 1555 char *disableUnload = NULL; 1556 1557 CK_C_GetFunctionList pC_GetFunctionList; 1558 CK_TOKEN_INFO tokenInfo; 1559 CK_FUNCTION_LIST_PTR pFunctionList = NULL; 1560 CK_RV crv = CKR_OK; 1561 CK_SESSION_HANDLE hRwSession; 1562 CK_SLOT_ID *pSlotList = NULL; 1563 CK_ULONG slotIndex = 0; 1564 1565 program_name = strrchr(argv[0], '/'); 1566 program_name = program_name ? (program_name + 1) : argv[0]; 1567 optstate = PL_CreateOptState(argc, argv, "i:o:f:FCd:hH?k:K:p:P:vVs:t:Dc"); 1568 if (optstate == NULL) { 1569 lperror("PL_CreateOptState failed"); 1570 return 1; 1571 } 1572 1573 while (PL_GetNextOpt(optstate) == PL_OPT_OK) { 1574 switch (optstate->option) { 1575 1576 case 'd': 1577 if (!optstate->value) { 1578 PL_DestroyOptState(optstate); 1579 usage(program_name); 1580 } 1581 configDir = PL_strdup(optstate->value); 1582 checkPath(configDir); 1583 break; 1584 1585 case 'D': 1586 useDSA = PR_TRUE; 1587 break; 1588 1589 case 'c': 1590 compat = PR_TRUE; 1591 break; 1592 1593 case 'i': 1594 if (!optstate->value) { 1595 PL_DestroyOptState(optstate); 1596 usage(program_name); 1597 } 1598 input_file = optstate->value; 1599 break; 1600 1601 case 'o': 1602 if (!optstate->value) { 1603 PL_DestroyOptState(optstate); 1604 usage(program_name); 1605 } 1606 output_file = PL_strdup(optstate->value); 1607 break; 1608 1609 case 'k': 1610 if (!optstate->value) { 1611 PL_DestroyOptState(optstate); 1612 usage(program_name); 1613 } 1614 keySize = atoi(optstate->value); 1615 break; 1616 1617 case 'K': 1618 if (!optstate->value) { 1619 PL_DestroyOptState(optstate); 1620 usage(program_name); 1621 } 1622 key = PL_strdup(optstate->value); 1623 break; 1624 1625 case 'f': 1626 if (!optstate->value) { 1627 PL_DestroyOptState(optstate); 1628 usage(program_name); 1629 } 1630 pwd = filePasswd((char *)optstate->value); 1631 if (!pwd) 1632 usage(program_name); 1633 break; 1634 1635 case 'F': 1636 if (mode == mode_fips) { 1637 break; /* mode is already set to fips */ 1638 } 1639 if (mode != mode_default) { 1640 PR_fprintf(PR_STDERR, "-C and -F are mutually exclusive\n"); 1641 usage(program_name); 1642 } 1643 mode = mode_fips; 1644 break; 1645 1646 case 'C': 1647 if (mode == mode_nonfips) { 1648 break; /* mode is already set to nonfips */ 1649 } 1650 if (mode != mode_default) { 1651 PR_fprintf(PR_STDERR, "-F and -C are mutually exclusive\n"); 1652 usage(program_name); 1653 } 1654 mode = mode_nonfips; 1655 break; 1656 1657 case 'p': 1658 if (!optstate->value) { 1659 PL_DestroyOptState(optstate); 1660 usage(program_name); 1661 } 1662 pwd = PL_strdup(optstate->value); 1663 break; 1664 1665 case 'P': 1666 if (!optstate->value) { 1667 PL_DestroyOptState(optstate); 1668 usage(program_name); 1669 } 1670 dbPrefix = PL_strdup(optstate->value); 1671 break; 1672 1673 case 't': 1674 if (!optstate->value) { 1675 PL_DestroyOptState(optstate); 1676 usage(program_name); 1677 } 1678 hash = findHash(optstate->value); 1679 if (hash == NULL) { 1680 PR_fprintf(PR_STDERR, "Invalid hash '%s'\n", 1681 optstate->value); 1682 usage(program_name); 1683 } 1684 break; 1685 case 'v': 1686 verbose = PR_TRUE; 1687 break; 1688 1689 case 'V': 1690 verify = PR_TRUE; 1691 break; 1692 1693 case 'H': 1694 PL_DestroyOptState(optstate); 1695 long_usage(program_name); 1696 return 1; 1697 break; 1698 1699 case 'h': 1700 case '?': 1701 default: 1702 PL_DestroyOptState(optstate); 1703 usage(program_name); 1704 return 1; 1705 break; 1706 } 1707 } 1708 PL_DestroyOptState(optstate); 1709 1710 if (!input_file) { 1711 usage(program_name); 1712 return 1; 1713 } 1714 1715 /* Get the platform-dependent library name of the 1716 * NSS cryptographic module. 1717 */ 1718 libname = PR_GetLibraryName(NULL, "softokn3"); 1719 assert(libname != NULL); 1720 if (!libname) { 1721 PR_fprintf(PR_STDERR, "getting softokn3 failed"); 1722 goto cleanup; 1723 } 1724 lib = PR_LoadLibrary(libname); 1725 assert(lib != NULL); 1726 if (!lib) { 1727 PR_fprintf(PR_STDERR, "loading softokn3 failed"); 1728 goto cleanup; 1729 } 1730 PR_FreeLibraryName(libname); 1731 1732 pC_GetFunctionList = (CK_C_GetFunctionList) 1733 PR_FindFunctionSymbol(lib, getFunctionListName(mode)); 1734 1735 assert(pC_GetFunctionList != NULL); 1736 if (!pC_GetFunctionList) { 1737 PR_fprintf(PR_STDERR, "getting function list failed"); 1738 goto cleanup; 1739 } 1740 1741 crv = (*pC_GetFunctionList)(&pFunctionList); 1742 assert(crv == CKR_OK); 1743 if (crv != CKR_OK) { 1744 PR_fprintf(PR_STDERR, "loading function list failed"); 1745 goto cleanup; 1746 } 1747 1748 if (configDir) { 1749 if (!dbPrefix) { 1750 dbPrefix = PL_strdup(""); 1751 } 1752 crv = softokn_Init(pFunctionList, configDir, dbPrefix); 1753 if (crv != CKR_OK) { 1754 logIt("Failed to use provided database directory " 1755 "will just initialize the volatile certdb.\n"); 1756 crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */ 1757 } 1758 } else { 1759 crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */ 1760 } 1761 1762 if (crv != CKR_OK) { 1763 pk11error("Initiailzing softoken failed", crv); 1764 goto cleanup; 1765 } 1766 1767 pSlotList = getSlotList(pFunctionList, slotIndex); 1768 if (pSlotList == NULL) { 1769 PR_fprintf(PR_STDERR, "getSlotList failed"); 1770 goto cleanup; 1771 } 1772 1773 crv = pFunctionList->C_OpenSession(pSlotList[slotIndex], 1774 CKF_RW_SESSION | CKF_SERIAL_SESSION, 1775 NULL, NULL, &hRwSession); 1776 if (crv != CKR_OK) { 1777 pk11error("Opening a read/write session failed", crv); 1778 goto cleanup; 1779 } 1780 1781 /* check if a password is needed */ 1782 crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo); 1783 if (crv != CKR_OK) { 1784 pk11error("C_GetTokenInfo failed", crv); 1785 goto cleanup; 1786 } 1787 if (tokenInfo.flags & CKF_LOGIN_REQUIRED) { 1788 if (pwd) { 1789 int pwdLen = strlen((const char *)pwd); 1790 crv = pFunctionList->C_Login(hRwSession, CKU_USER, 1791 (CK_UTF8CHAR_PTR)pwd, (CK_ULONG)pwdLen); 1792 if (crv != CKR_OK) { 1793 pk11error("C_Login failed", crv); 1794 goto cleanup; 1795 } 1796 } else { 1797 PR_fprintf(PR_STDERR, "Please provide the password for the token"); 1798 goto cleanup; 1799 } 1800 } else if (pwd) { 1801 logIt("A password was provided but the password was not used.\n"); 1802 } 1803 1804 /* open the shared library */ 1805 ifd = PR_OpenFile(input_file, PR_RDONLY, 0); 1806 if (ifd == NULL) { 1807 lperror(input_file); 1808 goto cleanup; 1809 } 1810 #ifdef USES_LINKS 1811 ret = lstat(input_file, &stat_buf); 1812 if (ret < 0) { 1813 perror(input_file); 1814 goto cleanup; 1815 } 1816 if (S_ISLNK(stat_buf.st_mode)) { 1817 char *dirpath, *dirend; 1818 ret = readlink(input_file, link_buf, sizeof(link_buf) - 1); 1819 if (ret < 0) { 1820 perror(input_file); 1821 goto cleanup; 1822 } 1823 link_buf[ret] = 0; 1824 link_file = mkoutput(input_file); 1825 /* get the dirname of input_file */ 1826 dirpath = PL_strdup(input_file); 1827 dirend = strrchr(dirpath, '/'); 1828 if (dirend) { 1829 *dirend = '\0'; 1830 ret = chdir(dirpath); 1831 if (ret < 0) { 1832 perror(dirpath); 1833 goto cleanup; 1834 } 1835 } 1836 PL_strfree(dirpath); 1837 input_file = link_buf; 1838 /* get the basename of link_file */ 1839 dirend = strrchr(link_file, '/'); 1840 if (dirend) { 1841 char *tmp_file = NULL; 1842 tmp_file = PL_strdup(dirend + 1); 1843 PL_strfree(link_file); 1844 link_file = tmp_file; 1845 } 1846 } 1847 #endif 1848 if (output_file == NULL) { 1849 output_file = mkoutput(input_file); 1850 } 1851 1852 if (verbose) { 1853 PR_fprintf(PR_STDERR, "Library File: %s\n", input_file); 1854 PR_fprintf(PR_STDERR, "Check File: %s\n", output_file); 1855 #ifdef USES_LINKS 1856 if (link_file) { 1857 PR_fprintf(PR_STDERR, "Link: %s\n", link_file); 1858 } 1859 #endif 1860 } 1861 1862 /* open the target signature file */ 1863 ofd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666); 1864 if (ofd == NULL) { 1865 lperror(output_file); 1866 goto cleanup; 1867 } 1868 1869 if (useDSA) { 1870 crv = shlibSignDSA(pFunctionList, pSlotList[slotIndex], hRwSession, 1871 keySize, ifd, ofd, hash); 1872 } else { 1873 crv = shlibSignHMAC(pFunctionList, pSlotList[slotIndex], hRwSession, 1874 keySize, key, ifd, ofd, hash); 1875 } 1876 if (crv == CKR_INTERNAL_OUT_FAILURE) { 1877 lperror(output_file); 1878 } 1879 if (crv == CKR_INTERNAL_IN_FAILURE) { 1880 lperror(input_file); 1881 } 1882 1883 PR_Close(ofd); 1884 ofd = NULL; 1885 /* close the input_File */ 1886 PR_Close(ifd); 1887 ifd = NULL; 1888 1889 #ifdef USES_LINKS 1890 if (link_file) { 1891 (void)unlink(link_file); 1892 ret = symlink(output_file, link_file); 1893 if (ret < 0) { 1894 perror(link_file); 1895 goto cleanup; 1896 } 1897 } 1898 #endif 1899 successful = PR_TRUE; 1900 1901 cleanup: 1902 if (pFunctionList) { 1903 /* C_Finalize will automatically logout, close session, */ 1904 /* and delete the temp objects on the token */ 1905 crv = pFunctionList->C_Finalize(NULL); 1906 if (crv != CKR_OK) { 1907 pk11error("C_Finalize failed", crv); 1908 } 1909 } 1910 if (pSlotList) { 1911 PR_Free(pSlotList); 1912 } 1913 if (pwd) { 1914 PL_strfree(pwd); 1915 } 1916 if (configDir) { 1917 PL_strfree(configDir); 1918 } 1919 if (dbPrefix) { 1920 PL_strfree(dbPrefix); 1921 } 1922 if (output_file) { /* allocated by mkoutput function */ 1923 PL_strfree(output_file); 1924 } 1925 #ifdef USES_LINKS 1926 if (link_file) { /* allocated by mkoutput function */ 1927 PL_strfree(link_file); 1928 } 1929 #endif 1930 if (ifd) { 1931 PR_Close(ifd); 1932 } 1933 if (ofd) { 1934 PR_Close(ofd); 1935 } 1936 1937 disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); 1938 if (!disableUnload && lib) { 1939 PR_UnloadLibrary(lib); 1940 } 1941 PR_Cleanup(); 1942 1943 if (crv != CKR_OK) 1944 return crv; 1945 1946 return (successful) ? 0 : 1; 1947 }