/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * shlibsign creates the checksum (.chk) files for the NSS libraries, * libsoftokn3/softokn3 and libfreebl/freebl (platforms can have * multiple freebl variants), that contain the NSS cryptograhic boundary. * * The generated .chk files must be put in the same directory as * the NSS libraries they were generated for. * * When in FIPS 140 mode, the NSS Internal FIPS PKCS #11 Module will * compute the checksum for the NSS cryptographic boundary libraries * and compare the checksum with the value in .chk file. */ #ifdef XP_UNIX #define USES_LINKS 1 #endif #include #include #include #include #include #ifdef USES_LINKS #include #include #include #include #endif /* nspr headers */ #include "prlink.h" #include "prprf.h" #include "prenv.h" #include "plgetopt.h" #include "prinit.h" #include "prmem.h" #include "plstr.h" #include "prerror.h" /* softoken headers */ #include "pkcs11.h" #include "pkcs11t.h" /* freebl headers */ #include "shsign.h" #define NUM_ELEM(array) (sizeof(array) / sizeof(array[0])) CK_BBOOL true = CK_TRUE; CK_BBOOL false = CK_FALSE; static PRBool verbose = PR_FALSE; static void usage(const char *program_name) { PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError); PR_fprintf(debug_out, "type %s -H for more detail information.\n", program_name); PR_fprintf(debug_out, "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n" " [-F] [-p pwd] -[P dbprefix ] " "-i shared_library_name\n", program_name); exit(1); } static void long_usage(const char *program_name) { PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError); PR_fprintf(debug_out, "%s test program usage:\n", program_name); PR_fprintf(debug_out, "\t-i shared_library_name to process\n"); PR_fprintf(debug_out, "\t-o checksum outfile\n"); PR_fprintf(debug_out, "\t-d database path location\n"); PR_fprintf(debug_out, "\t-P database prefix\n"); PR_fprintf(debug_out, "\t-f password File : echo pw > file \n"); PR_fprintf(debug_out, "\t-F FIPS mode\n"); PR_fprintf(debug_out, "\t-p password\n"); PR_fprintf(debug_out, "\t-v verbose output\n"); PR_fprintf(debug_out, "\t-V perform Verify operations\n"); PR_fprintf(debug_out, "\t-? short help message\n"); PR_fprintf(debug_out, "\t-h short help message\n"); PR_fprintf(debug_out, "\t-H this help message\n"); PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your "); PR_fprintf(debug_out, "library path is using \n"); PR_fprintf(debug_out, "\t pre-existing libraries with generated "); PR_fprintf(debug_out, "checksum files\n"); PR_fprintf(debug_out, "\t and database in FIPS mode \n"); exit(1); } static char * mkoutput(const char *input) { int in_len = strlen(input); char *output = PR_Malloc(in_len + sizeof(SGN_SUFFIX)); int index = in_len + 1 - sizeof("." SHLIB_SUFFIX); if ((index > 0) && (PL_strncmp(&input[index], "." SHLIB_SUFFIX, sizeof("." SHLIB_SUFFIX)) == 0)) { in_len = index; } memcpy(output, input, in_len); memcpy(&output[in_len], SGN_SUFFIX, sizeof(SGN_SUFFIX)); return output; } static void lperror(const char *string) { PRErrorCode errorcode; errorcode = PR_GetError(); PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode, PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT)); } static void encodeInt(unsigned char *buf, int val) { buf[3] = (val >> 0) & 0xff; buf[2] = (val >> 8) & 0xff; buf[1] = (val >> 16) & 0xff; buf[0] = (val >> 24) & 0xff; return; } static PRStatus writeItem(PRFileDesc *fd, CK_VOID_PTR pValue, CK_ULONG ulValueLen, char *file) { unsigned char buf[4]; int bytesWritten; if (ulValueLen == 0) { PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n"); return PR_FAILURE; } encodeInt(buf, ulValueLen); bytesWritten = PR_Write(fd, buf, 4); if (bytesWritten != 4) { lperror(file); return PR_FAILURE; } bytesWritten = PR_Write(fd, pValue, ulValueLen); if (bytesWritten < 0 || (CK_ULONG)bytesWritten != ulValueLen) { lperror(file); return PR_FAILURE; } return PR_SUCCESS; } static const unsigned char prime[] = { 0x00, 0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d, 0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92, 0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7, 0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c, 0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44, 0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8, 0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69, 0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb, 0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5, 0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd, 0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77, 0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd, 0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d, 0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2, 0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77, 0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 }; static const unsigned char subprime[] = { 0x0, 0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5, 0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54, 0x0b, 0x31, 0x24, 0xf1 }; static const unsigned char base[] = { 0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a, 0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11, 0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23, 0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42, 0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1, 0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f, 0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f, 0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa, 0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc, 0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1, 0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18, 0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8, 0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d, 0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc, 0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36, 0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f }; /* * The constants h, seed, & counter aren't used in the code; they're provided * here (commented-out) so that human readers can verify that our our PQG * parameters were generated properly. static const unsigned char h[] = { 0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac, 0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6, 0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f, 0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67, 0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29, 0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd, 0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13, 0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5, 0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f, 0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2, 0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6, 0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32, 0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23, 0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9, 0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7, 0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c }; static const unsigned char seed[] = { 0x00, 0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68, 0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed, 0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85, 0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b, 0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d, 0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83, 0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2, 0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4, 0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00, 0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3, 0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36, 0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e, 0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2, 0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe, 0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc, 0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c }; static const unsigned int counter=1496; */ static const unsigned char prime2[] = { 0x00, 0xa4, 0xc2, 0x83, 0x4f, 0x36, 0xd3, 0x4f, 0xae, 0xa0, 0xb1, 0x47, 0x43, 0xa8, 0x15, 0xee, 0xad, 0xa3, 0x98, 0xa3, 0x29, 0x45, 0xae, 0x5c, 0xd9, 0x12, 0x99, 0x09, 0xdc, 0xef, 0x05, 0xb4, 0x98, 0x05, 0xaa, 0x07, 0xaa, 0x83, 0x89, 0xd7, 0xba, 0xd1, 0x25, 0x56, 0x58, 0xd1, 0x73, 0x3c, 0xd0, 0x91, 0x65, 0xbe, 0x27, 0x92, 0x94, 0x86, 0x95, 0xdb, 0xcf, 0x07, 0x13, 0xa0, 0x85, 0xd6, 0xaa, 0x6c, 0x1d, 0x63, 0xbf, 0xdd, 0xdf, 0xbc, 0x30, 0xeb, 0x42, 0x2f, 0x52, 0x11, 0xec, 0x6e, 0x65, 0xdf, 0x50, 0xbe, 0x28, 0x3d, 0xa4, 0xec, 0x45, 0x19, 0x4c, 0x13, 0x0f, 0x59, 0x74, 0x57, 0x69, 0x99, 0x4f, 0x4a, 0x74, 0x7f, 0x8c, 0x9e, 0xa2, 0xe7, 0x94, 0xc9, 0x70, 0x70, 0xd0, 0xc4, 0xda, 0x49, 0x5b, 0x7a, 0x7d, 0xd9, 0x71, 0x7c, 0x3b, 0xdc, 0xd2, 0x8a, 0x74, 0x5f, 0xce, 0x09, 0xa2, 0xdb, 0xec, 0xa4, 0xba, 0x75, 0xaa, 0x0a, 0x97, 0xa6, 0x82, 0x25, 0x90, 0x90, 0x37, 0xe4, 0x40, 0x05, 0x28, 0x8f, 0x98, 0x8e, 0x68, 0x01, 0xaf, 0x9b, 0x08, 0x2a, 0x9b, 0xd5, 0xb9, 0x8c, 0x14, 0xbf, 0xba, 0xcb, 0x5b, 0xda, 0x4c, 0x95, 0xb8, 0xdf, 0x67, 0xa6, 0x6b, 0x76, 0x8c, 0xad, 0x4f, 0xfd, 0x6a, 0xd6, 0xcc, 0x62, 0x71, 0x30, 0x30, 0xc1, 0x29, 0x84, 0xe4, 0x8e, 0x32, 0x51, 0xb6, 0xea, 0xfa, 0xba, 0x00, 0x99, 0x76, 0xea, 0x86, 0x90, 0xab, 0x2d, 0xe9, 0xfd, 0x1e, 0x8c, 0xcc, 0x3c, 0x2b, 0x5d, 0x13, 0x1b, 0x47, 0xb4, 0xf5, 0x09, 0x74, 0x1d, 0xd4, 0x78, 0xb2, 0x42, 0x19, 0xd6, 0x24, 0xd1, 0x68, 0xbf, 0x11, 0xf1, 0x38, 0xa0, 0x44, 0x9c, 0xc6, 0x51, 0x33, 0xaa, 0x42, 0x93, 0x9e, 0x30, 0x58, 0x9e, 0xc0, 0x70, 0xdf, 0x7e, 0x64, 0xb1, 0xd8, 0x68, 0x75, 0x98, 0xa7 }; static const unsigned char subprime2[] = { 0x00, 0x8e, 0xab, 0xf4, 0xbe, 0x45, 0xeb, 0xa3, 0x58, 0x4e, 0x60, 0x15, 0x66, 0x5a, 0x4b, 0x25, 0xcf, 0x45, 0x77, 0x89, 0x3f, 0x73, 0x34, 0x4a, 0xe0, 0x9e, 0xac, 0xfd, 0xdc, 0xff, 0x9c, 0x8d, 0xe7 }; static const unsigned char base2[] = { 0x00, 0x8d, 0x72, 0x32, 0x46, 0xa6, 0x5c, 0x80, 0xe3, 0x43, 0x0a, 0x9e, 0x94, 0x35, 0x86, 0xd4, 0x58, 0xa1, 0xca, 0x22, 0xb9, 0x73, 0x46, 0x0b, 0xfb, 0x3e, 0x33, 0xf1, 0xd5, 0xd3, 0xb4, 0x26, 0xbf, 0x50, 0xd7, 0xf2, 0x09, 0x33, 0x6e, 0xc0, 0x31, 0x1b, 0x6d, 0x07, 0x70, 0x86, 0xca, 0x57, 0xf7, 0x0b, 0x4a, 0x63, 0xf0, 0x6f, 0xc8, 0x8a, 0xed, 0x50, 0x60, 0xf3, 0x11, 0xc7, 0x44, 0xf3, 0xce, 0x4e, 0x50, 0x42, 0x2d, 0x85, 0x33, 0x54, 0x57, 0x03, 0x8d, 0xdc, 0x66, 0x4d, 0x61, 0x83, 0x17, 0x1c, 0x7b, 0x0d, 0x65, 0xbc, 0x8f, 0x2c, 0x19, 0x86, 0xfc, 0xe2, 0x9f, 0x5d, 0x67, 0xfc, 0xd4, 0xa5, 0xf8, 0x23, 0xa1, 0x1a, 0xa2, 0xe1, 0x11, 0x15, 0x84, 0x32, 0x01, 0xee, 0x88, 0xf1, 0x55, 0x30, 0xe9, 0x74, 0x3c, 0x1a, 0x2b, 0x54, 0x45, 0x2e, 0x39, 0xb9, 0x77, 0xe1, 0x32, 0xaf, 0x2d, 0x97, 0xe0, 0x21, 0xec, 0xf5, 0x58, 0xe1, 0xc7, 0x2e, 0xe0, 0x71, 0x3d, 0x29, 0xa4, 0xd6, 0xe2, 0x5f, 0x85, 0x9c, 0x05, 0x04, 0x46, 0x41, 0x89, 0x03, 0x3c, 0xfa, 0xb2, 0xcf, 0xfa, 0xd5, 0x67, 0xcc, 0xec, 0x68, 0xfc, 0x83, 0xd9, 0x1f, 0x2e, 0x4e, 0x9a, 0x5e, 0x77, 0xa1, 0xff, 0xe6, 0x6f, 0x04, 0x8b, 0xf9, 0x6b, 0x47, 0xc6, 0x49, 0xd2, 0x88, 0x6e, 0x29, 0xa3, 0x1b, 0xae, 0xe0, 0x4f, 0x72, 0x8a, 0x28, 0x94, 0x0c, 0x1d, 0x8c, 0x99, 0xa2, 0x6f, 0xf8, 0xba, 0x99, 0x90, 0xc7, 0xe5, 0xb1, 0x3c, 0x10, 0x34, 0x86, 0x6a, 0x6a, 0x1f, 0x39, 0x63, 0x58, 0xe1, 0x5e, 0x97, 0x95, 0x45, 0x40, 0x38, 0x45, 0x6f, 0x02, 0xb5, 0x86, 0x6e, 0xae, 0x2f, 0x32, 0x7e, 0xa1, 0x3a, 0x34, 0x2c, 0x1c, 0xd3, 0xff, 0x4e, 0x2c, 0x38, 0x1c, 0xaa, 0x2e, 0x66, 0xbe, 0x32, 0x3e, 0x3c, 0x06, 0x5f }; /* * The constants h2, seed2, & counter2 aren't used in the code; they're provided * here (commented-out) so that human readers can verify that our our PQG * parameters were generated properly. static const unsigned char h2[] = { 0x30, 0x91, 0xa1, 0x2e, 0x40, 0xa5, 0x7d, 0xf7, 0xdc, 0xed, 0xee, 0x05, 0xc2, 0x31, 0x91, 0x37, 0xda, 0xc5, 0xe3, 0x47, 0xb5, 0x35, 0x4b, 0xfd, 0x18, 0xb2, 0x7e, 0x67, 0x1e, 0x92, 0x22, 0xe7, 0xf5, 0x00, 0x71, 0xc0, 0x86, 0x8d, 0x90, 0x31, 0x36, 0x3e, 0xd0, 0x94, 0x5d, 0x2f, 0x9a, 0x68, 0xd2, 0xf8, 0x3d, 0x5e, 0x84, 0x42, 0x35, 0xda, 0x75, 0xdd, 0x05, 0xf0, 0x03, 0x31, 0x39, 0xe5, 0xfd, 0x2f, 0x5a, 0x7d, 0x56, 0xd8, 0x26, 0xa0, 0x51, 0x5e, 0x32, 0xb4, 0xad, 0xee, 0xd4, 0x89, 0xae, 0x01, 0x7f, 0xac, 0x86, 0x98, 0x77, 0x26, 0x5c, 0x31, 0xd2, 0x5e, 0xbb, 0x7f, 0xf5, 0x4c, 0x9b, 0xf0, 0xa6, 0x37, 0x34, 0x08, 0x86, 0x6b, 0xce, 0xeb, 0x85, 0x66, 0x0a, 0x26, 0x8a, 0x14, 0x92, 0x12, 0x74, 0xf4, 0xf0, 0xcb, 0xb5, 0xfc, 0x38, 0xd5, 0x1e, 0xa1, 0x2f, 0x4a, 0x1a, 0xca, 0x66, 0xde, 0x6e, 0xe6, 0x6e, 0x1c, 0xef, 0x50, 0x41, 0x31, 0x09, 0xe7, 0x4a, 0xb8, 0xa3, 0xaa, 0x5a, 0x22, 0xbd, 0x63, 0x0f, 0xe9, 0x0e, 0xdb, 0xb3, 0xca, 0x7e, 0x8d, 0x40, 0xb3, 0x3e, 0x0b, 0x12, 0x8b, 0xb0, 0x80, 0x4d, 0x6d, 0xb0, 0x54, 0xbb, 0x4c, 0x1d, 0x6c, 0xa0, 0x5c, 0x9d, 0x91, 0xb3, 0xbb, 0xd9, 0xfc, 0x60, 0xec, 0xc1, 0xbc, 0xae, 0x72, 0x3f, 0xa5, 0x4f, 0x36, 0x2d, 0x2c, 0x81, 0x03, 0x86, 0xa2, 0x03, 0x38, 0x36, 0x8e, 0xad, 0x1d, 0x53, 0xc6, 0xc5, 0x9e, 0xda, 0x08, 0x35, 0x4f, 0xb2, 0x78, 0xba, 0xd1, 0x22, 0xde, 0xc4, 0x6b, 0xbe, 0x83, 0x71, 0x0f, 0xee, 0x38, 0x4a, 0x9f, 0xda, 0x90, 0x93, 0x6b, 0x9a, 0xf2, 0xeb, 0x23, 0xfe, 0x41, 0x3f, 0xf1, 0xfc, 0xee, 0x7f, 0x67, 0xa7, 0xb8, 0xab, 0x29, 0xf4, 0x75, 0x1c, 0xe9, 0xd1, 0x47, 0x7d, 0x86, 0x44, 0xe2 }; static const unsigned char seed2[] = { 0x00, 0xbc, 0xae, 0xc4, 0xea, 0x4e, 0xd2, 0xed, 0x1c, 0x8d, 0x48, 0xed, 0xf2, 0xa5, 0xb4, 0x18, 0xba, 0x00, 0xcb, 0x9c, 0x75, 0x8a, 0x39, 0x94, 0x3b, 0xd0, 0xd6, 0x01, 0xf7, 0xc1, 0xf5, 0x9d, 0xe5, 0xe3, 0xb4, 0x1d, 0xf5, 0x30, 0xfe, 0x99, 0xe4, 0x01, 0xab, 0xc0, 0x88, 0x4e, 0x67, 0x8f, 0xc6, 0x72, 0x39, 0x2e, 0xac, 0x51, 0xec, 0x91, 0x41, 0x47, 0x71, 0x14, 0x8a, 0x1d, 0xca, 0x88, 0x15, 0xea, 0xc9, 0x48, 0x9a, 0x71, 0x50, 0x19, 0x38, 0xdb, 0x4e, 0x65, 0xd5, 0x13, 0xd8, 0x2a, 0xc4, 0xcd, 0xfd, 0x0c, 0xe3, 0xc3, 0x60, 0xae, 0x6d, 0x88, 0xf2, 0x3a, 0xd0, 0x64, 0x73, 0x32, 0x89, 0xcd, 0x0b, 0xb8, 0xc7, 0xa5, 0x27, 0x84, 0xd5, 0x83, 0x3f, 0x0e, 0x10, 0x63, 0x10, 0x78, 0xac, 0x6b, 0x56, 0xb2, 0x62, 0x3a, 0x44, 0x56, 0xc0, 0xe4, 0x33, 0xd7, 0x63, 0x4c, 0xc9, 0x6b, 0xae, 0xfb, 0xe2, 0x9b, 0xf4, 0x96, 0xc7, 0xf0, 0x2a, 0x50, 0xde, 0x86, 0x69, 0x4f, 0x42, 0x4b, 0x1c, 0x7c, 0xa8, 0x6a, 0xfb, 0x54, 0x47, 0x1b, 0x41, 0x31, 0x9e, 0x0a, 0xc6, 0xc0, 0xbc, 0x88, 0x7f, 0x5a, 0x42, 0xa9, 0x82, 0x58, 0x32, 0xb3, 0xeb, 0x54, 0x83, 0x84, 0x26, 0x92, 0xa6, 0xc0, 0x6e, 0x2b, 0xa6, 0x82, 0x82, 0x43, 0x58, 0x84, 0x53, 0x31, 0xcf, 0xd0, 0x0a, 0x11, 0x09, 0x44, 0xc8, 0x11, 0x36, 0xe0, 0x04, 0x85, 0x2e, 0xd1, 0x29, 0x6b, 0x7b, 0x00, 0x71, 0x5f, 0xef, 0x7b, 0x7a, 0x2d, 0x91, 0xf9, 0x84, 0x45, 0x4d, 0xc7, 0xe1, 0xee, 0xd4, 0xb8, 0x61, 0x3b, 0x13, 0xb7, 0xba, 0x95, 0x39, 0xf6, 0x3d, 0x89, 0xbd, 0xa5, 0x80, 0x93, 0xf7, 0xe5, 0x17, 0x05, 0xc5, 0x65, 0xb7, 0xde, 0xc9, 0x9f, 0x04, 0x87, 0xcf, 0x4f, 0x86, 0xc3, 0x29, 0x7d, 0xb7, 0x89, 0xbf, 0xe3, 0xde }; static const unsigned int counter2=210; */ struct tuple_str { CK_RV errNum; const char *errString; }; typedef struct tuple_str tuple_str; static const tuple_str errStrings[] = { { CKR_OK, "CKR_OK " }, { CKR_CANCEL, "CKR_CANCEL " }, { CKR_HOST_MEMORY, "CKR_HOST_MEMORY " }, { CKR_SLOT_ID_INVALID, "CKR_SLOT_ID_INVALID " }, { CKR_GENERAL_ERROR, "CKR_GENERAL_ERROR " }, { CKR_FUNCTION_FAILED, "CKR_FUNCTION_FAILED " }, { CKR_ARGUMENTS_BAD, "CKR_ARGUMENTS_BAD " }, { CKR_NO_EVENT, "CKR_NO_EVENT " }, { CKR_NEED_TO_CREATE_THREADS, "CKR_NEED_TO_CREATE_THREADS " }, { CKR_CANT_LOCK, "CKR_CANT_LOCK " }, { CKR_ATTRIBUTE_READ_ONLY, "CKR_ATTRIBUTE_READ_ONLY " }, { CKR_ATTRIBUTE_SENSITIVE, "CKR_ATTRIBUTE_SENSITIVE " }, { CKR_ATTRIBUTE_TYPE_INVALID, "CKR_ATTRIBUTE_TYPE_INVALID " }, { CKR_ATTRIBUTE_VALUE_INVALID, "CKR_ATTRIBUTE_VALUE_INVALID " }, { CKR_DATA_INVALID, "CKR_DATA_INVALID " }, { CKR_DATA_LEN_RANGE, "CKR_DATA_LEN_RANGE " }, { CKR_DEVICE_ERROR, "CKR_DEVICE_ERROR " }, { CKR_DEVICE_MEMORY, "CKR_DEVICE_MEMORY " }, { CKR_DEVICE_REMOVED, "CKR_DEVICE_REMOVED " }, { CKR_ENCRYPTED_DATA_INVALID, "CKR_ENCRYPTED_DATA_INVALID " }, { CKR_ENCRYPTED_DATA_LEN_RANGE, "CKR_ENCRYPTED_DATA_LEN_RANGE " }, { CKR_FUNCTION_CANCELED, "CKR_FUNCTION_CANCELED " }, { CKR_FUNCTION_NOT_PARALLEL, "CKR_FUNCTION_NOT_PARALLEL " }, { CKR_FUNCTION_NOT_SUPPORTED, "CKR_FUNCTION_NOT_SUPPORTED " }, { CKR_KEY_HANDLE_INVALID, "CKR_KEY_HANDLE_INVALID " }, { CKR_KEY_SIZE_RANGE, "CKR_KEY_SIZE_RANGE " }, { CKR_KEY_TYPE_INCONSISTENT, "CKR_KEY_TYPE_INCONSISTENT " }, { CKR_KEY_NOT_NEEDED, "CKR_KEY_NOT_NEEDED " }, { CKR_KEY_CHANGED, "CKR_KEY_CHANGED " }, { CKR_KEY_NEEDED, "CKR_KEY_NEEDED " }, { CKR_KEY_INDIGESTIBLE, "CKR_KEY_INDIGESTIBLE " }, { CKR_KEY_FUNCTION_NOT_PERMITTED, "CKR_KEY_FUNCTION_NOT_PERMITTED " }, { CKR_KEY_NOT_WRAPPABLE, "CKR_KEY_NOT_WRAPPABLE " }, { CKR_KEY_UNEXTRACTABLE, "CKR_KEY_UNEXTRACTABLE " }, { CKR_MECHANISM_INVALID, "CKR_MECHANISM_INVALID " }, { CKR_MECHANISM_PARAM_INVALID, "CKR_MECHANISM_PARAM_INVALID " }, { CKR_OBJECT_HANDLE_INVALID, "CKR_OBJECT_HANDLE_INVALID " }, { CKR_OPERATION_ACTIVE, "CKR_OPERATION_ACTIVE " }, { CKR_OPERATION_NOT_INITIALIZED, "CKR_OPERATION_NOT_INITIALIZED " }, { CKR_PIN_INCORRECT, "CKR_PIN_INCORRECT " }, { CKR_PIN_INVALID, "CKR_PIN_INVALID " }, { CKR_PIN_LEN_RANGE, "CKR_PIN_LEN_RANGE " }, { CKR_PIN_EXPIRED, "CKR_PIN_EXPIRED " }, { CKR_PIN_LOCKED, "CKR_PIN_LOCKED " }, { CKR_SESSION_CLOSED, "CKR_SESSION_CLOSED " }, { CKR_SESSION_COUNT, "CKR_SESSION_COUNT " }, { CKR_SESSION_HANDLE_INVALID, "CKR_SESSION_HANDLE_INVALID " }, { CKR_SESSION_PARALLEL_NOT_SUPPORTED, "CKR_SESSION_PARALLEL_NOT_SUPPORTED " }, { CKR_SESSION_READ_ONLY, "CKR_SESSION_READ_ONLY " }, { CKR_SESSION_EXISTS, "CKR_SESSION_EXISTS " }, { CKR_SESSION_READ_ONLY_EXISTS, "CKR_SESSION_READ_ONLY_EXISTS " }, { CKR_SESSION_READ_WRITE_SO_EXISTS, "CKR_SESSION_READ_WRITE_SO_EXISTS " }, { CKR_SIGNATURE_INVALID, "CKR_SIGNATURE_INVALID " }, { CKR_SIGNATURE_LEN_RANGE, "CKR_SIGNATURE_LEN_RANGE " }, { CKR_TEMPLATE_INCOMPLETE, "CKR_TEMPLATE_INCOMPLETE " }, { CKR_TEMPLATE_INCONSISTENT, "CKR_TEMPLATE_INCONSISTENT " }, { CKR_TOKEN_NOT_PRESENT, "CKR_TOKEN_NOT_PRESENT " }, { CKR_TOKEN_NOT_RECOGNIZED, "CKR_TOKEN_NOT_RECOGNIZED " }, { CKR_TOKEN_WRITE_PROTECTED, "CKR_TOKEN_WRITE_PROTECTED " }, { CKR_UNWRAPPING_KEY_HANDLE_INVALID, "CKR_UNWRAPPING_KEY_HANDLE_INVALID " }, { CKR_UNWRAPPING_KEY_SIZE_RANGE, "CKR_UNWRAPPING_KEY_SIZE_RANGE " }, { CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT" }, { CKR_USER_ALREADY_LOGGED_IN, "CKR_USER_ALREADY_LOGGED_IN " }, { CKR_USER_NOT_LOGGED_IN, "CKR_USER_NOT_LOGGED_IN " }, { CKR_USER_PIN_NOT_INITIALIZED, "CKR_USER_PIN_NOT_INITIALIZED " }, { CKR_USER_TYPE_INVALID, "CKR_USER_TYPE_INVALID " }, { CKR_USER_ANOTHER_ALREADY_LOGGED_IN, "CKR_USER_ANOTHER_ALREADY_LOGGED_IN " }, { CKR_USER_TOO_MANY_TYPES, "CKR_USER_TOO_MANY_TYPES " }, { CKR_WRAPPED_KEY_INVALID, "CKR_WRAPPED_KEY_INVALID " }, { CKR_WRAPPED_KEY_LEN_RANGE, "CKR_WRAPPED_KEY_LEN_RANGE " }, { CKR_WRAPPING_KEY_HANDLE_INVALID, "CKR_WRAPPING_KEY_HANDLE_INVALID " }, { CKR_WRAPPING_KEY_SIZE_RANGE, "CKR_WRAPPING_KEY_SIZE_RANGE " }, { CKR_WRAPPING_KEY_TYPE_INCONSISTENT, "CKR_WRAPPING_KEY_TYPE_INCONSISTENT " }, { CKR_RANDOM_SEED_NOT_SUPPORTED, "CKR_RANDOM_SEED_NOT_SUPPORTED " }, { CKR_RANDOM_NO_RNG, "CKR_RANDOM_NO_RNG " }, { CKR_DOMAIN_PARAMS_INVALID, "CKR_DOMAIN_PARAMS_INVALID " }, { CKR_BUFFER_TOO_SMALL, "CKR_BUFFER_TOO_SMALL " }, { CKR_SAVED_STATE_INVALID, "CKR_SAVED_STATE_INVALID " }, { CKR_INFORMATION_SENSITIVE, "CKR_INFORMATION_SENSITIVE " }, { CKR_STATE_UNSAVEABLE, "CKR_STATE_UNSAVEABLE " }, { CKR_CRYPTOKI_NOT_INITIALIZED, "CKR_CRYPTOKI_NOT_INITIALIZED " }, { CKR_CRYPTOKI_ALREADY_INITIALIZED, "CKR_CRYPTOKI_ALREADY_INITIALIZED " }, { CKR_MUTEX_BAD, "CKR_MUTEX_BAD " }, { CKR_MUTEX_NOT_LOCKED, "CKR_MUTEX_NOT_LOCKED " }, { CKR_FUNCTION_REJECTED, "CKR_FUNCTION_REJECTED " }, { CKR_VENDOR_DEFINED, "CKR_VENDOR_DEFINED " }, { 0xCE534351, "CKR_NSS_CERTDB_FAILED " }, { 0xCE534352, "CKR_NSS_KEYDB_FAILED " } }; static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str); /* Returns constant error string for "CRV". * Returns "unknown error" if errNum is unknown. */ static const char * CK_RVtoStr(CK_RV errNum) { CK_ULONG low = 1; CK_ULONG high = numStrings - 1; CK_ULONG i; CK_RV num; static int initDone; /* make sure table is in ascending order. * binary search depends on it. */ if (!initDone) { CK_RV lastNum = CKR_OK; for (i = low; i <= high; ++i) { num = errStrings[i].errNum; if (num <= lastNum) { PR_fprintf(PR_STDERR, "sequence error in error strings at item %d\n" "error %d (%s)\n" "should come after \n" "error %d (%s)\n", (int)i, (int)lastNum, errStrings[i - 1].errString, (int)num, errStrings[i].errString); } lastNum = num; } initDone = 1; } /* Do binary search of table. */ while (low + 1 < high) { i = low + (high - low) / 2; num = errStrings[i].errNum; if (errNum == num) return errStrings[i].errString; if (errNum < num) high = i; else low = i; } if (errNum == errStrings[low].errNum) return errStrings[low].errString; if (errNum == errStrings[high].errNum) return errStrings[high].errString; return "unknown error"; } static void pk11error(const char *string, CK_RV crv) { PRErrorCode errorcode; PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv)); errorcode = PR_GetError(); if (errorcode) { PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode, PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT)); } } static void logIt(const char *fmt, ...) { va_list args; if (verbose) { va_start(args, fmt); vprintf(fmt, args); va_end(args); } } static CK_RV softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char *configDir, const char *dbPrefix) { CK_RV crv = CKR_OK; CK_C_INITIALIZE_ARGS initArgs; char *moduleSpec = NULL; initArgs.CreateMutex = NULL; initArgs.DestroyMutex = NULL; initArgs.LockMutex = NULL; initArgs.UnlockMutex = NULL; initArgs.flags = CKF_OS_LOCKING_OK; if (configDir) { moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' " "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ", configDir, dbPrefix, dbPrefix); } else { moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' " "secmod='' flags=noCertDB, noModDB"); } if (!moduleSpec) { PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n"); return CKR_HOST_MEMORY; } logIt("moduleSpec %s\n", moduleSpec); initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec; initArgs.pReserved = NULL; crv = pFunctionList->C_Initialize(&initArgs); if (crv != CKR_OK) { pk11error("C_Initialize failed", crv); goto cleanup; } cleanup: if (moduleSpec) { PR_smprintf_free(moduleSpec); } return crv; } static char * filePasswd(char *pwFile) { unsigned char phrase[500]; PRFileDesc *fd; PRInt32 nb; int i; if (!pwFile) return 0; fd = PR_Open(pwFile, PR_RDONLY, 0); if (!fd) { lperror(pwFile); return NULL; } nb = PR_Read(fd, phrase, sizeof(phrase)); PR_Close(fd); /* handle the Windows EOL case */ i = 0; while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++; phrase[i] = '\0'; if (nb == 0) { PR_fprintf(PR_STDERR, "password file contains no data\n"); return NULL; } return (char *)PL_strdup((char *)phrase); } static void checkPath(char *string) { char *src; char *dest; /* * windows support convert any back slashes to * forward slashes. */ for (src = string, dest = string; *src; src++, dest++) { if (*src == '\\') { *dest = '/'; } } dest--; /* if the last char is a / set it to 0 */ if (*dest == '/') *dest = 0; } static CK_SLOT_ID * getSlotList(CK_FUNCTION_LIST_PTR pFunctionList, CK_ULONG slotIndex) { CK_RV crv = CKR_OK; CK_SLOT_ID *pSlotList = NULL; CK_ULONG slotCount; /* Get slot list */ crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */, NULL, &slotCount); if (crv != CKR_OK) { pk11error("C_GetSlotList failed", crv); return NULL; } if (slotIndex >= slotCount) { PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count."); return NULL; } pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID)); if (!pSlotList) { lperror("failed to allocate slot list"); return NULL; } crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */, pSlotList, &slotCount); if (crv != CKR_OK) { pk11error("C_GetSlotList failed", crv); if (pSlotList) PR_Free(pSlotList); return NULL; } return pSlotList; } int main(int argc, char **argv) { PLOptState *optstate; char *program_name; char *libname = NULL; PRLibrary *lib = NULL; PRFileDesc *fd; PRStatus rv = PR_SUCCESS; const char *input_file = NULL; /* read/create encrypted data from here */ char *output_file = NULL; /* write new encrypted data here */ int bytesRead; int bytesWritten; unsigned char file_buf[512]; int count = 0; unsigned int keySize = 0; int i; PRBool verify = PR_FALSE; static PRBool FIPSMODE = PR_FALSE; PRBool successful = PR_FALSE; #ifdef USES_LINKS int ret; struct stat stat_buf; char link_buf[MAXPATHLEN + 1]; char *link_file = NULL; #endif char *pwd = NULL; char *configDir = NULL; char *dbPrefix = NULL; char *disableUnload = NULL; CK_C_GetFunctionList pC_GetFunctionList; CK_TOKEN_INFO tokenInfo; CK_FUNCTION_LIST_PTR pFunctionList = NULL; CK_RV crv = CKR_OK; CK_SESSION_HANDLE hRwSession; CK_SLOT_ID *pSlotList = NULL; CK_ULONG slotIndex = 0; CK_MECHANISM digestmech; CK_ULONG digestLen = 0; CK_BYTE digest[32]; /* SHA256_LENGTH */ CK_BYTE sign[64]; /* DSA SIGNATURE LENGTH */ CK_ULONG signLen = 0; CK_MECHANISM signMech = { CKM_DSA, NULL, 0 }; /*** DSA Key ***/ CK_MECHANISM dsaKeyPairGenMech; CK_ATTRIBUTE dsaPubKeyTemplate[5]; CK_ATTRIBUTE dsaPrivKeyTemplate[5]; CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE; CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE; CK_BYTE dsaPubKey[384]; CK_ATTRIBUTE dsaPubKeyValue; program_name = strrchr(argv[0], '/'); program_name = program_name ? (program_name + 1) : argv[0]; optstate = PL_CreateOptState(argc, argv, "i:o:f:Fd:hH?k:p:P:vVs:"); if (optstate == NULL) { lperror("PL_CreateOptState failed"); return 1; } while (PL_GetNextOpt(optstate) == PL_OPT_OK) { switch (optstate->option) { case 'd': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } configDir = PL_strdup(optstate->value); checkPath(configDir); break; case 'i': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } input_file = optstate->value; break; case 'o': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } output_file = PL_strdup(optstate->value); break; case 'k': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } keySize = atoi(optstate->value); break; case 'f': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } pwd = filePasswd((char *)optstate->value); if (!pwd) usage(program_name); break; case 'F': FIPSMODE = PR_TRUE; break; case 'p': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } pwd = PL_strdup(optstate->value); break; case 'P': if (!optstate->value) { PL_DestroyOptState(optstate); usage(program_name); } dbPrefix = PL_strdup(optstate->value); break; case 'v': verbose = PR_TRUE; break; case 'V': verify = PR_TRUE; break; case 'H': PL_DestroyOptState(optstate); long_usage(program_name); return 1; break; case 'h': case '?': default: PL_DestroyOptState(optstate); usage(program_name); return 1; break; } } PL_DestroyOptState(optstate); if (!input_file) { usage(program_name); return 1; } /* Get the platform-dependent library name of the * NSS cryptographic module. */ libname = PR_GetLibraryName(NULL, "softokn3"); assert(libname != NULL); if (!libname) { PR_fprintf(PR_STDERR, "getting softokn3 failed"); goto cleanup; } lib = PR_LoadLibrary(libname); assert(lib != NULL); if (!lib) { PR_fprintf(PR_STDERR, "loading softokn3 failed"); goto cleanup; } PR_FreeLibraryName(libname); if (FIPSMODE) { /* FIPSMODE == FC_GetFunctionList */ /* library path must be set to an already signed softokn3/freebl */ pC_GetFunctionList = (CK_C_GetFunctionList) PR_FindFunctionSymbol(lib, "FC_GetFunctionList"); } else { /* NON FIPS mode == C_GetFunctionList */ pC_GetFunctionList = (CK_C_GetFunctionList) PR_FindFunctionSymbol(lib, "C_GetFunctionList"); } assert(pC_GetFunctionList != NULL); if (!pC_GetFunctionList) { PR_fprintf(PR_STDERR, "getting function list failed"); goto cleanup; } crv = (*pC_GetFunctionList)(&pFunctionList); assert(crv == CKR_OK); if (crv != CKR_OK) { PR_fprintf(PR_STDERR, "loading function list failed"); goto cleanup; } if (configDir) { if (!dbPrefix) { dbPrefix = PL_strdup(""); } crv = softokn_Init(pFunctionList, configDir, dbPrefix); if (crv != CKR_OK) { logIt("Failed to use provided database directory " "will just initialize the volatile certdb.\n"); crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */ } } else { crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */ } if (crv != CKR_OK) { pk11error("Initiailzing softoken failed", crv); goto cleanup; } pSlotList = getSlotList(pFunctionList, slotIndex); if (pSlotList == NULL) { PR_fprintf(PR_STDERR, "getSlotList failed"); goto cleanup; } if ((keySize == 0) || (keySize > 1024)) { CK_MECHANISM_INFO mechInfo; crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotIndex], CKM_DSA, &mechInfo); if (crv != CKR_OK) { pk11error("Couldn't get mechanism info for DSA", crv); goto cleanup; } if (keySize && (mechInfo.ulMaxKeySize < keySize)) { PR_fprintf(PR_STDERR, "token doesn't support DSA2 (Max key size=%d)\n", mechInfo.ulMaxKeySize); goto cleanup; } if ((keySize == 0) && mechInfo.ulMaxKeySize >= 2048) { keySize = 2048; } else { keySize = 1024; } } /* DSA key init */ if (keySize == 1024) { dsaPubKeyTemplate[0].type = CKA_PRIME; dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)′ dsaPubKeyTemplate[0].ulValueLen = sizeof(prime); dsaPubKeyTemplate[1].type = CKA_SUBPRIME; dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime; dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime); dsaPubKeyTemplate[2].type = CKA_BASE; dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base; dsaPubKeyTemplate[2].ulValueLen = sizeof(base); digestmech.mechanism = CKM_SHA_1; digestmech.pParameter = NULL; digestmech.ulParameterLen = 0; } else if (keySize == 2048) { dsaPubKeyTemplate[0].type = CKA_PRIME; dsaPubKeyTemplate[0].pValue = (CK_VOID_PTR)&prime2; dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2); dsaPubKeyTemplate[1].type = CKA_SUBPRIME; dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR)&subprime2; dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2); dsaPubKeyTemplate[2].type = CKA_BASE; dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR)&base2; dsaPubKeyTemplate[2].ulValueLen = sizeof(base2); digestmech.mechanism = CKM_SHA256; digestmech.pParameter = NULL; digestmech.ulParameterLen = 0; } else { /* future - generate pqg */ PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported"); goto cleanup; } dsaPubKeyTemplate[3].type = CKA_TOKEN; dsaPubKeyTemplate[3].pValue = &false; /* session object */ dsaPubKeyTemplate[3].ulValueLen = sizeof(false); dsaPubKeyTemplate[4].type = CKA_VERIFY; dsaPubKeyTemplate[4].pValue = &true; dsaPubKeyTemplate[4].ulValueLen = sizeof(true); dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN; dsaKeyPairGenMech.pParameter = NULL; dsaKeyPairGenMech.ulParameterLen = 0; dsaPrivKeyTemplate[0].type = CKA_TOKEN; dsaPrivKeyTemplate[0].pValue = &false; /* session object */ dsaPrivKeyTemplate[0].ulValueLen = sizeof(false); dsaPrivKeyTemplate[1].type = CKA_PRIVATE; dsaPrivKeyTemplate[1].pValue = &true; dsaPrivKeyTemplate[1].ulValueLen = sizeof(true); dsaPrivKeyTemplate[2].type = CKA_SENSITIVE; dsaPrivKeyTemplate[2].pValue = &true; dsaPrivKeyTemplate[2].ulValueLen = sizeof(true); dsaPrivKeyTemplate[3].type = CKA_SIGN, dsaPrivKeyTemplate[3].pValue = &true; dsaPrivKeyTemplate[3].ulValueLen = sizeof(true); dsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE; dsaPrivKeyTemplate[4].pValue = &false; dsaPrivKeyTemplate[4].ulValueLen = sizeof(false); crv = pFunctionList->C_OpenSession(pSlotList[slotIndex], CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &hRwSession); if (crv != CKR_OK) { pk11error("Opening a read/write session failed", crv); goto cleanup; } /* check if a password is needed */ crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo); if (crv != CKR_OK) { pk11error("C_GetTokenInfo failed", crv); goto cleanup; } if (tokenInfo.flags & CKF_LOGIN_REQUIRED) { if (pwd) { int pwdLen = strlen((const char *)pwd); crv = pFunctionList->C_Login(hRwSession, CKU_USER, (CK_UTF8CHAR_PTR)pwd, (CK_ULONG)pwdLen); if (crv != CKR_OK) { pk11error("C_Login failed", crv); goto cleanup; } } else { PR_fprintf(PR_STDERR, "Please provide the password for the token"); goto cleanup; } } else if (pwd) { logIt("A password was provided but the password was not used.\n"); } /* Generate a DSA key pair */ logIt("Generate a DSA key pair ... \n"); crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech, dsaPubKeyTemplate, NUM_ELEM(dsaPubKeyTemplate), dsaPrivKeyTemplate, NUM_ELEM(dsaPrivKeyTemplate), &hDSApubKey, &hDSAprivKey); if (crv != CKR_OK) { pk11error("DSA key pair generation failed", crv); goto cleanup; } /* open the shared library */ fd = PR_OpenFile(input_file, PR_RDONLY, 0); if (fd == NULL) { lperror(input_file); goto cleanup; } #ifdef USES_LINKS ret = lstat(input_file, &stat_buf); if (ret < 0) { perror(input_file); goto cleanup; } if (S_ISLNK(stat_buf.st_mode)) { char *dirpath, *dirend; ret = readlink(input_file, link_buf, sizeof(link_buf) - 1); if (ret < 0) { perror(input_file); goto cleanup; } link_buf[ret] = 0; link_file = mkoutput(input_file); /* get the dirname of input_file */ dirpath = PL_strdup(input_file); dirend = strrchr(dirpath, '/'); if (dirend) { *dirend = '\0'; ret = chdir(dirpath); if (ret < 0) { perror(dirpath); goto cleanup; } } PL_strfree(dirpath); input_file = link_buf; /* get the basename of link_file */ dirend = strrchr(link_file, '/'); if (dirend) { char *tmp_file = NULL; tmp_file = PL_strdup(dirend + 1); PL_strfree(link_file); link_file = tmp_file; } } #endif if (output_file == NULL) { output_file = mkoutput(input_file); } /* compute the digest */ memset(digest, 0, sizeof(digest)); crv = pFunctionList->C_DigestInit(hRwSession, &digestmech); if (crv != CKR_OK) { pk11error("C_DigestInit failed", crv); goto cleanup; } /* Digest the file */ while ((bytesRead = PR_Read(fd, file_buf, sizeof(file_buf))) > 0) { crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf, bytesRead); if (crv != CKR_OK) { pk11error("C_DigestUpdate failed", crv); goto cleanup; } count += bytesRead; } /* close the input_File */ PR_Close(fd); fd = NULL; if (bytesRead < 0) { lperror("0 bytes read from input file"); goto cleanup; } digestLen = sizeof(digest); crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest, &digestLen); if (crv != CKR_OK) { pk11error("C_DigestFinal failed", crv); goto cleanup; } if (digestLen != sizeof(digest)) { PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu " "it should be %lu \n", digestLen, sizeof(digest)); goto cleanup; } /* sign the hash */ memset(sign, 0, sizeof(sign)); /* SignUpdate */ crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey); if (crv != CKR_OK) { pk11error("C_SignInit failed", crv); goto cleanup; } signLen = sizeof(sign); crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen, sign, &signLen); if (crv != CKR_OK) { pk11error("C_Sign failed", crv); goto cleanup; } if (signLen != sizeof(sign)) { PR_fprintf(PR_STDERR, "signLen has incorrect length %lu " "it should be %lu \n", signLen, sizeof(sign)); goto cleanup; } if (verify) { crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey); if (crv != CKR_OK) { pk11error("C_VerifyInit failed", crv); goto cleanup; } crv = pFunctionList->C_Verify(hRwSession, digest, digestLen, sign, signLen); if (crv != CKR_OK) { pk11error("C_Verify failed", crv); goto cleanup; } } if (verbose) { int j; PR_fprintf(PR_STDERR, "Library File: %s %d bytes\n", input_file, count); PR_fprintf(PR_STDERR, "Check File: %s\n", output_file); #ifdef USES_LINKS if (link_file) { PR_fprintf(PR_STDERR, "Link: %s\n", link_file); } #endif PR_fprintf(PR_STDERR, " hash: %lu bytes\n", digestLen); #define STEP 10 for (i = 0; i < (int)digestLen; i += STEP) { PR_fprintf(PR_STDERR, " "); for (j = 0; j < STEP && (i + j) < (int)digestLen; j++) { PR_fprintf(PR_STDERR, " %02x", digest[i + j]); } PR_fprintf(PR_STDERR, "\n"); } PR_fprintf(PR_STDERR, " signature: %lu bytes\n", signLen); for (i = 0; i < (int)signLen; i += STEP) { PR_fprintf(PR_STDERR, " "); for (j = 0; j < STEP && (i + j) < (int)signLen; j++) { PR_fprintf(PR_STDERR, " %02x", sign[i + j]); } PR_fprintf(PR_STDERR, "\n"); } } /* open the target signature file */ fd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666); if (fd == NULL) { lperror(output_file); goto cleanup; } /* * we write the key out in a straight binary format because very * low level libraries need to read an parse this file. Ideally we should * just derEncode the public key (which would be pretty simple, and be * more general), but then we'd need to link the ASN.1 decoder with the * freebl libraries. */ file_buf[0] = NSS_SIGN_CHK_MAGIC1; file_buf[1] = NSS_SIGN_CHK_MAGIC2; file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION; file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION; encodeInt(&file_buf[4], 12); /* offset to data start */ encodeInt(&file_buf[8], CKK_DSA); bytesWritten = PR_Write(fd, file_buf, 12); if (bytesWritten != 12) { lperror(output_file); goto cleanup; } /* get DSA Public KeyValue */ memset(dsaPubKey, 0, sizeof(dsaPubKey)); dsaPubKeyValue.type = CKA_VALUE; dsaPubKeyValue.pValue = (CK_VOID_PTR)&dsaPubKey; dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey); crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey, &dsaPubKeyValue, 1); if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) { pk11error("C_GetAttributeValue failed", crv); goto cleanup; } /* CKA_PRIME */ rv = writeItem(fd, dsaPubKeyTemplate[0].pValue, dsaPubKeyTemplate[0].ulValueLen, output_file); if (rv != PR_SUCCESS) goto cleanup; /* CKA_SUBPRIME */ rv = writeItem(fd, dsaPubKeyTemplate[1].pValue, dsaPubKeyTemplate[1].ulValueLen, output_file); if (rv != PR_SUCCESS) goto cleanup; /* CKA_BASE */ rv = writeItem(fd, dsaPubKeyTemplate[2].pValue, dsaPubKeyTemplate[2].ulValueLen, output_file); if (rv != PR_SUCCESS) goto cleanup; /* DSA Public Key value */ rv = writeItem(fd, dsaPubKeyValue.pValue, dsaPubKeyValue.ulValueLen, output_file); if (rv != PR_SUCCESS) goto cleanup; /* DSA SIGNATURE */ rv = writeItem(fd, &sign, signLen, output_file); if (rv != PR_SUCCESS) goto cleanup; PR_Close(fd); #ifdef USES_LINKS if (link_file) { (void)unlink(link_file); ret = symlink(output_file, link_file); if (ret < 0) { perror(link_file); goto cleanup; } } #endif successful = PR_TRUE; cleanup: if (pFunctionList) { /* C_Finalize will automatically logout, close session, */ /* and delete the temp objects on the token */ crv = pFunctionList->C_Finalize(NULL); if (crv != CKR_OK) { pk11error("C_Finalize failed", crv); } } if (pSlotList) { PR_Free(pSlotList); } if (pwd) { PL_strfree(pwd); } if (configDir) { PL_strfree(configDir); } if (dbPrefix) { PL_strfree(dbPrefix); } if (output_file) { /* allocated by mkoutput function */ PL_strfree(output_file); } #ifdef USES_LINKS if (link_file) { /* allocated by mkoutput function */ PL_strfree(link_file); } #endif disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD"); if (!disableUnload && lib) { PR_UnloadLibrary(lib); } PR_Cleanup(); if (crv != CKR_OK) return crv; return (successful) ? 0 : 1; }