mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-15 20:10:33 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
1302 lines
47 KiB
C
1302 lines
47 KiB
C
/* 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 <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#ifdef USES_LINKS
|
|
#include <unistd.h>
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#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 <infile> shared_library_name to process\n");
|
|
PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
|
|
PR_fprintf(debug_out, "\t-d <path> database path location\n");
|
|
PR_fprintf(debug_out, "\t-P <prefix> database prefix\n");
|
|
PR_fprintf(debug_out, "\t-f <file> password File : echo pw > file \n");
|
|
PR_fprintf(debug_out, "\t-F FIPS mode\n");
|
|
PR_fprintf(debug_out, "\t-p <pwd> 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 != 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_NETSCAPE_CERTDB_FAILED "},
|
|
{0xCE534352 , "CKR_NETSCAPE_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) / 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[200];
|
|
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;
|
|
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);
|
|
lib = PR_LoadLibrary(libname);
|
|
assert(lib != NULL);
|
|
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);
|
|
|
|
crv = (*pC_GetFunctionList)(&pFunctionList);
|
|
assert(crv == CKR_OK);
|
|
|
|
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_GetEnv("NSS_DISABLE_UNLOAD");
|
|
if (!disableUnload) {
|
|
PR_UnloadLibrary(lib);
|
|
}
|
|
PR_Cleanup();
|
|
|
|
if (crv != CKR_OK)
|
|
return crv;
|
|
|
|
return (successful) ? 0 : 1;
|
|
}
|