/* 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
#define COMPAT_MAJOR
0 x01
#define COMPAT_MINOR
0 x02
#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"
/* nss headers for definition of HASH_HashType */
#include "hasht.h"
/* other basic nss header */
#include "secport.h"
#include "basicutil.h"
#include "secitem.h"
#include "nssutil.h"
CK_BBOOL cktrue = CK_TRUE;
CK_BBOOL ckfalse = CK_FALSE;
CK_OBJECT_CLASS secret_key_obj_class = CKO_SECRET_KEY;
static PRBool verbose = PR_FALSE;
static PRBool verify = PR_FALSE;
static PRBool compat = PR_FALSE;
typedef enum {
mode_default,
mode_fips,
mode_nonfips,
} ModeTypes;
static const char *
getFunctionListName(ModeTypes mode)
{
switch (mode) {
case mode_default:
return "C_GetFunctionList" ;
case mode_fips:
return "FC_GetFunctionList" ;
case mode_nonfips:
return "NSC_GetFunctionList" ;
}
return "C_GetFunctionList" ;
}
typedef struct HashTableStruct {
char *name;
CK_MECHANISM_TYPE hash;
CK_MECHANISM_TYPE hmac;
CK_KEY_TYPE keyType;
HASH_HashType hashType;
CK_ULONG hashLength;
} HashTable;
#define CKR_INTERNAL_OUT_FAILURE
0 x80111111
#define CKR_INTERNAL_IN_FAILURE
0 x80222222
#define CKM_SHA1 CKM_SHA_1
#define CKM_SHA1_HMAC CKM_SHA_1_HMAC
#define CKK_SHA1_HMAC CKK_SHA_1_HMAC
#define MKHASH(name, mech) \
{ \
name, CKM_
## mech, CKM_
## mech
## _HMAC, \
CKK_
## mech
## _HMAC, HASH_Alg
## mech, mech
## _LENGTH \
}
static HashTable hashTable[] = {
MKHASH(
"sha-1" , SHA1), MKHASH(
"sha1" , SHA1), MKHASH(
"sha224" , SHA224),
MKHASH(
"sha256" , SHA256), MKHASH(
"sha384" , SHA384),
MKHASH(
"sha512" , SHA512)
};
static size_t hashTableSize = PR_ARRAY_SIZE(hashTable);
const HashTable *
findHash(
const char *hashName)
{
int i;
for (i =
0 ; i < hashTableSize; i++) {
if (PL_strcasecmp(hashTable[i].name, hashName) ==
0 ) {
return &hashTable[i];
}
}
return NULL;
}
static void
usage(
const char *program_name)
{
int i;
const char *comma =
"" ;
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|-C] [-p pwd] -[P dbprefix ] [-t hash]\n"
" [-D] [-k keysize] [-c] [-K key]\n"
" -i shared_library_name\n" ,
program_name);
PR_fprintf(debug_out,
"Valid Hashes: " );
for (i =
0 ; i < hashTableSize; i++) {
PR_fprintf(debug_out,
"%s%s" , comma, hashTable[i].name);
comma =
", " ;
}
PR_fprintf(debug_out,
"\n" );
exit (
1 );
}
static void
long_usage(
const char *program_name)
{
PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
int i;
const char *comma =
"" ;
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-t <hash> Hash for HMAC/or DSA\n" );
PR_fprintf(debug_out,
"\t-D Sign with DSA rather than HMAC\n" );
PR_fprintf(debug_out,
"\t-k <keysize> size of the DSA key\n" );
PR_fprintf(debug_out,
"\t-K <key> key-material to use for hmac (hex-string, without leading 0x)\n" );
PR_fprintf(debug_out,
"\t-c Use compatible versions for old NSS\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 force FIPS mode\n" );
PR_fprintf(debug_out,
"\t-C force Non-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" );
PR_fprintf(debug_out,
"\n\n\tNote: -F and -C are mutually exclusive, " );
PR_fprintf(debug_out,
"you can only include of of them.\n" );
PR_fprintf(debug_out,
"Valid Hashes: " );
for (i =
0 ; i < hashTableSize; i++) {
PR_fprintf(debug_out,
"%s%s" , comma, hashTable[i].name);
comma =
", " ;
}
PR_fprintf(debug_out,
"\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;
}
/*
* There are 3 error functions in this code :
* print_error : just prints the string to stderr . Used in cases where
* the error is discovered in this code rather than returned
* from a library .
* lperror : prints the error from NSPR or NSS code ( including SECUTIL code ) .
* it works like perror for NSPR and NSS .
* pk11error : prints the error based on the pkcs # 11 return code . it also
* looks up the NSPR / NSS error code and prints it if it exists .
*/
static void
print_error(
const char *string)
{
PR_fprintf(PR_STDERR,
"%s\n" , string);
}
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 ) &
0 xff;
buf[
2 ] = (val >>
8 ) &
0 xff;
buf[
1 ] = (val >>
16 ) &
0 xff;
buf[
0 ] = (val >>
24 ) &
0 xff;
return ;
}
static PRStatus
writeItem(PRFileDesc *fd, CK_VOID_PTR pValue, CK_ULONG ulValueLen)
{
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 ) {
return PR_FAILURE;
}
bytesWritten = PR_Write(fd, pValue, ulValueLen);
if (bytesWritten <
0 || (CK_ULONG)bytesWritten != ulValueLen) {
return PR_FAILURE;
}
return PR_SUCCESS;
}
static const unsigned char prime[] = {
0 x00,
0 x97,
0 x44,
0 x1d,
0 xcc,
0 x0d,
0 x39,
0 x0d,
0 x8d,
0 xcb,
0 x75,
0 xdc,
0 x24,
0 x25,
0 x6f,
0 x01,
0 x92,
0 xa1,
0 x11,
0 x07,
0 x6b,
0 x70,
0 xac,
0 x73,
0 xd7,
0 x82,
0 x28,
0 xdf,
0 xab,
0 x82,
0 x0c,
0 x41,
0 x0c,
0 x95,
0 xb3,
0 x3c,
0 x3d,
0 xea,
0 x8a,
0 xe6,
0 x44,
0 x0a,
0 xb8,
0 xab,
0 x90,
0 x15,
0 x41,
0 x11,
0 xe8,
0 x48,
0 x7b,
0 x8d,
0 xb0,
0 x9c,
0 xd3,
0 xf2,
0 x69,
0 x66,
0 xff,
0 x66,
0 x4b,
0 x70,
0 x2b,
0 xbf,
0 xfb,
0 xd6,
0 x68,
0 x85,
0 x76,
0 x1e,
0 x34,
0 xaa,
0 xc5,
0 x57,
0 x6e,
0 x23,
0 x02,
0 x08,
0 x60,
0 x6e,
0 xfd,
0 x67,
0 x76,
0 xe1,
0 x7c,
0 xc8,
0 xcb,
0 x51,
0 x77,
0 xcf,
0 xb1,
0 x3b,
0 x00,
0 x2e,
0 xfa,
0 x21,
0 xcd,
0 x34,
0 x76,
0 x75,
0 x01,
0 x19,
0 xfe,
0 xf8,
0 x5d,
0 x43,
0 xc5,
0 x34,
0 xf3,
0 x7a,
0 x95,
0 xdc,
0 xc2,
0 x58,
0 x07,
0 x19,
0 x2f,
0 x1d,
0 x6f,
0 x9a,
0 x77,
0 x7e,
0 x55,
0 xaa,
0 xe7,
0 x5a,
0 x50,
0 x43,
0 xd3 };
static const unsigned char subprime[] = {
0 x0,
0 xd8,
0 x16,
0 x23,
0 x34,
0 x8a,
0 x9e,
0 x3a,
0 xf5,
0 xd9,
0 x10,
0 x13,
0 x35,
0 xaa,
0 xf3,
0 xf3,
0 x54,
0 x0b,
0 x31,
0 x24,
0 xf1 };
static const unsigned char base[] = {
0 x03,
0 x3a,
0 xad,
0 xfa,
0 x3a,
0 x0c,
0 xea,
0 x0a,
0 x4e,
0 x43,
0 x32,
0 x92,
0 xbb,
0 x87,
0 xf1,
0 x11,
0 xc0,
0 xad,
0 x39,
0 x38,
0 x56,
0 x1a,
0 xdb,
0 x23,
0 x66,
0 xb1,
0 x08,
0 xda,
0 xb6,
0 x19,
0 x51,
0 x42,
0 x93,
0 x4f,
0 xc3,
0 x44,
0 x43,
0 xa8,
0 x05,
0 xc1,
0 xf8,
0 x71,
0 x62,
0 x6f,
0 x3d,
0 xe2,
0 xab,
0 x6f,
0 xd7,
0 x80,
0 x22,
0 x6f,
0 xca,
0 x0d,
0 xf6,
0 x9f,
0 x45,
0 x27,
0 x83,
0 xec,
0 x86,
0 x0c,
0 xda,
0 xaa,
0 xd6,
0 xe0,
0 xd0,
0 x84,
0 xfd,
0 xb1,
0 x4f,
0 xdc,
0 x08,
0 xcd,
0 x68,
0 x3a,
0 x77,
0 xc2,
0 xc5,
0 xf1,
0 x99,
0 x0f,
0 x15,
0 x1b,
0 x6a,
0 x8c,
0 x3d,
0 x18,
0 x2b,
0 x6f,
0 xdc,
0 x2b,
0 xd8,
0 xb5,
0 x9b,
0 xb8,
0 x2d,
0 x57,
0 x92,
0 x1c,
0 x46,
0 x27,
0 xaf,
0 x6d,
0 xe1,
0 x45,
0 xcf,
0 x0b,
0 x3f,
0 xfa,
0 x07,
0 xcc,
0 x14,
0 x8e,
0 xe7,
0 xb8,
0 xaa,
0 xd5,
0 xd1,
0 x36,
0 x1d,
0 x7e,
0 x5e,
0 x7d,
0 xfa,
0 x5b,
0 x77,
0 x1f
};
/*
* 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 [ ] = {
0 x41 , 0 x87 , 0 x47 , 0 x79 , 0 xd8 , 0 xba , 0 x4e , 0 xac ,
0 x44 , 0 x4f , 0 x6b , 0 xd2 , 0 x16 , 0 x5e , 0 x04 , 0 xc6 ,
0 xc2 , 0 x29 , 0 x93 , 0 x5e , 0 xbd , 0 xc7 , 0 xa9 , 0 x8f ,
0 x23 , 0 xa1 , 0 xc8 , 0 xee , 0 x80 , 0 x64 , 0 xd5 , 0 x67 ,
0 x3c , 0 xba , 0 x59 , 0 x9a , 0 x06 , 0 x0c , 0 xcc , 0 x29 ,
0 x56 , 0 xc0 , 0 xb2 , 0 x21 , 0 xe0 , 0 x5b , 0 x52 , 0 xcd ,
0 x84 , 0 x73 , 0 x57 , 0 xfd , 0 xd8 , 0 xc3 , 0 x5b , 0 x13 ,
0 x54 , 0 xd7 , 0 x4a , 0 x06 , 0 x86 , 0 x63 , 0 x09 , 0 xa5 ,
0 xb0 , 0 x59 , 0 xe2 , 0 x32 , 0 x9e , 0 x09 , 0 xa3 , 0 x9f ,
0 x49 , 0 x62 , 0 xcc , 0 xa6 , 0 xf9 , 0 x54 , 0 xd5 , 0 xb2 ,
0 xc3 , 0 x08 , 0 x71 , 0 x7e , 0 xe3 , 0 x37 , 0 x50 , 0 xd6 ,
0 x7b , 0 xa7 , 0 xc2 , 0 x60 , 0 xc1 , 0 xeb , 0 x51 , 0 x32 ,
0 xfa , 0 xad , 0 x35 , 0 x25 , 0 x17 , 0 xf0 , 0 x7f , 0 x23 ,
0 xe5 , 0 xa8 , 0 x01 , 0 x52 , 0 xcf , 0 x2f , 0 xd9 , 0 xa9 ,
0 xf6 , 0 x00 , 0 x21 , 0 x15 , 0 xf1 , 0 xf7 , 0 x70 , 0 xb7 ,
0 x57 , 0 x8a , 0 xd0 , 0 x59 , 0 x6a , 0 x82 , 0 xdc , 0 x9c } ;
static const unsigned char seed [ ] = { 0 x00 ,
0 xcc , 0 x4c , 0 x69 , 0 x74 , 0 xf6 , 0 x72 , 0 x24 , 0 x68 ,
0 x24 , 0 x4f , 0 xd7 , 0 x50 , 0 x11 , 0 x40 , 0 x81 , 0 xed ,
0 x19 , 0 x3c , 0 x8a , 0 x25 , 0 xbc , 0 x78 , 0 x0a , 0 x85 ,
0 x82 , 0 x53 , 0 x70 , 0 x20 , 0 xf6 , 0 x54 , 0 xa5 , 0 x1b ,
0 xf4 , 0 x15 , 0 xcd , 0 xff , 0 xc4 , 0 x88 , 0 xa7 , 0 x9d ,
0 xf3 , 0 x47 , 0 x1c , 0 x0a , 0 xbe , 0 x10 , 0 x29 , 0 x83 ,
0 xb9 , 0 x0f , 0 x4c , 0 xdf , 0 x90 , 0 x16 , 0 x83 , 0 xa2 ,
0 xb3 , 0 xe3 , 0 x2e , 0 xc1 , 0 xc2 , 0 x24 , 0 x6a , 0 xc4 ,
0 x9d , 0 x57 , 0 xba , 0 xcb , 0 x0f , 0 x18 , 0 x75 , 0 x00 ,
0 x33 , 0 x46 , 0 x82 , 0 xec , 0 xd6 , 0 x94 , 0 x77 , 0 xc3 ,
0 x4f , 0 x4c , 0 x58 , 0 x1c , 0 x7f , 0 x61 , 0 x3c , 0 x36 ,
0 xd5 , 0 x2f , 0 xa5 , 0 x66 , 0 xd8 , 0 x2f , 0 xce , 0 x6e ,
0 x8e , 0 x20 , 0 x48 , 0 x4a , 0 xbb , 0 xe3 , 0 xe0 , 0 xb2 ,
0 x50 , 0 x33 , 0 x63 , 0 x8a , 0 x5b , 0 x2d , 0 x6a , 0 xbe ,
0 x4c , 0 x28 , 0 x81 , 0 x53 , 0 x5b , 0 xe4 , 0 xf6 , 0 xfc ,
0 x64 , 0 x06 , 0 x13 , 0 x51 , 0 xeb , 0 x4a , 0 x91 , 0 x9c } ;
static const unsigned int counter = 1496 ;
*/
static const unsigned char prime2[] = {
0 x00,
0 xa4,
0 xc2,
0 x83,
0 x4f,
0 x36,
0 xd3,
0 x4f,
0 xae,
0 xa0,
0 xb1,
0 x47,
0 x43,
0 xa8,
0 x15,
0 xee,
0 xad,
0 xa3,
0 x98,
0 xa3,
0 x29,
0 x45,
0 xae,
0 x5c,
0 xd9,
0 x12,
0 x99,
0 x09,
0 xdc,
0 xef,
0 x05,
0 xb4,
0 x98,
0 x05,
0 xaa,
0 x07,
0 xaa,
0 x83,
0 x89,
0 xd7,
0 xba,
0 xd1,
0 x25,
0 x56,
0 x58,
0 xd1,
0 x73,
0 x3c,
0 xd0,
0 x91,
0 x65,
0 xbe,
0 x27,
0 x92,
0 x94,
0 x86,
0 x95,
0 xdb,
0 xcf,
0 x07,
0 x13,
0 xa0,
0 x85,
0 xd6,
0 xaa,
0 x6c,
0 x1d,
0 x63,
0 xbf,
0 xdd,
0 xdf,
0 xbc,
0 x30,
0 xeb,
0 x42,
0 x2f,
0 x52,
0 x11,
0 xec,
0 x6e,
0 x65,
0 xdf,
0 x50,
0 xbe,
0 x28,
0 x3d,
0 xa4,
0 xec,
0 x45,
0 x19,
0 x4c,
0 x13,
0 x0f,
0 x59,
0 x74,
0 x57,
0 x69,
0 x99,
0 x4f,
0 x4a,
0 x74,
0 x7f,
0 x8c,
0 x9e,
0 xa2,
0 xe7,
0 x94,
0 xc9,
0 x70,
0 x70,
0 xd0,
0 xc4,
0 xda,
0 x49,
0 x5b,
0 x7a,
0 x7d,
0 xd9,
0 x71,
0 x7c,
0 x3b,
0 xdc,
0 xd2,
0 x8a,
0 x74,
0 x5f,
0 xce,
0 x09,
0 xa2,
0 xdb,
0 xec,
0 xa4,
0 xba,
0 x75,
0 xaa,
0 x0a,
0 x97,
0 xa6,
0 x82,
0 x25,
0 x90,
0 x90,
0 x37,
0 xe4,
0 x40,
0 x05,
0 x28,
0 x8f,
0 x98,
0 x8e,
0 x68,
0 x01,
0 xaf,
0 x9b,
0 x08,
0 x2a,
0 x9b,
0 xd5,
0 xb9,
0 x8c,
0 x14,
0 xbf,
0 xba,
0 xcb,
0 x5b,
0 xda,
0 x4c,
0 x95,
0 xb8,
0 xdf,
0 x67,
0 xa6,
0 x6b,
0 x76,
0 x8c,
0 xad,
0 x4f,
0 xfd,
0 x6a,
0 xd6,
0 xcc,
0 x62,
0 x71,
0 x30,
0 x30,
0 xc1,
0 x29,
0 x84,
0 xe4,
0 x8e,
0 x32,
0 x51,
0 xb6,
0 xea,
0 xfa,
0 xba,
0 x00,
0 x99,
0 x76,
0 xea,
0 x86,
0 x90,
0 xab,
0 x2d,
0 xe9,
0 xfd,
0 x1e,
0 x8c,
0 xcc,
0 x3c,
0 x2b,
0 x5d,
0 x13,
0 x1b,
0 x47,
0 xb4,
0 xf5,
0 x09,
0 x74,
0 x1d,
0 xd4,
0 x78,
0 xb2,
0 x42,
0 x19,
0 xd6,
0 x24,
0 xd1,
0 x68,
0 xbf,
0 x11,
0 xf1,
0 x38,
0 xa0,
0 x44,
0 x9c,
0 xc6,
0 x51,
0 x33,
0 xaa,
0 x42,
0 x93,
0 x9e,
0 x30,
0 x58,
0 x9e,
0 xc0,
0 x70,
0 xdf,
0 x7e,
0 x64,
0 xb1,
0 xd8,
0 x68,
0 x75,
0 x98,
0 xa7 };
static const unsigned char subprime2[] = {
0 x00,
0 x8e,
0 xab,
0 xf4,
0 xbe,
0 x45,
0 xeb,
0 xa3,
0 x58,
0 x4e,
0 x60,
0 x15,
0 x66,
0 x5a,
0 x4b,
0 x25,
0 xcf,
0 x45,
0 x77,
0 x89,
0 x3f,
0 x73,
0 x34,
0 x4a,
0 xe0,
0 x9e,
0 xac,
0 xfd,
0 xdc,
0 xff,
0 x9c,
0 x8d,
0 xe7 };
static const unsigned char base2[] = {
0 x00,
0 x8d,
0 x72,
0 x32,
0 x46,
0 xa6,
0 x5c,
0 x80,
0 xe3,
0 x43,
0 x0a,
0 x9e,
0 x94,
0 x35,
0 x86,
0 xd4,
0 x58,
0 xa1,
0 xca,
0 x22,
0 xb9,
0 x73,
0 x46,
0 x0b,
0 xfb,
0 x3e,
0 x33,
0 xf1,
0 xd5,
0 xd3,
0 xb4,
0 x26,
0 xbf,
0 x50,
0 xd7,
0 xf2,
0 x09,
0 x33,
0 x6e,
0 xc0,
0 x31,
0 x1b,
0 x6d,
0 x07,
0 x70,
0 x86,
0 xca,
0 x57,
0 xf7,
0 x0b,
0 x4a,
0 x63,
0 xf0,
0 x6f,
0 xc8,
0 x8a,
0 xed,
0 x50,
0 x60,
0 xf3,
0 x11,
0 xc7,
0 x44,
0 xf3,
0 xce,
0 x4e,
0 x50,
0 x42,
0 x2d,
0 x85,
0 x33,
0 x54,
0 x57,
0 x03,
0 x8d,
0 xdc,
0 x66,
0 x4d,
0 x61,
0 x83,
0 x17,
0 x1c,
0 x7b,
0 x0d,
0 x65,
0 xbc,
0 x8f,
0 x2c,
0 x19,
0 x86,
0 xfc,
0 xe2,
0 x9f,
0 x5d,
0 x67,
0 xfc,
0 xd4,
0 xa5,
0 xf8,
0 x23,
0 xa1,
0 x1a,
0 xa2,
0 xe1,
0 x11,
0 x15,
0 x84,
0 x32,
0 x01,
0 xee,
0 x88,
0 xf1,
0 x55,
0 x30,
0 xe9,
0 x74,
0 x3c,
0 x1a,
0 x2b,
0 x54,
0 x45,
0 x2e,
0 x39,
0 xb9,
0 x77,
0 xe1,
0 x32,
0 xaf,
0 x2d,
0 x97,
0 xe0,
0 x21,
0 xec,
0 xf5,
0 x58,
0 xe1,
0 xc7,
0 x2e,
0 xe0,
0 x71,
0 x3d,
0 x29,
0 xa4,
0 xd6,
0 xe2,
0 x5f,
0 x85,
0 x9c,
0 x05,
0 x04,
0 x46,
0 x41,
0 x89,
0 x03,
0 x3c,
0 xfa,
0 xb2,
0 xcf,
0 xfa,
0 xd5,
0 x67,
0 xcc,
0 xec,
0 x68,
0 xfc,
0 x83,
0 xd9,
0 x1f,
0 x2e,
0 x4e,
0 x9a,
0 x5e,
0 x77,
0 xa1,
0 xff,
0 xe6,
0 x6f,
0 x04,
0 x8b,
0 xf9,
0 x6b,
0 x47,
0 xc6,
0 x49,
0 xd2,
0 x88,
0 x6e,
0 x29,
0 xa3,
0 x1b,
0 xae,
0 xe0,
0 x4f,
0 x72,
0 x8a,
0 x28,
0 x94,
0 x0c,
0 x1d,
0 x8c,
0 x99,
0 xa2,
0 x6f,
0 xf8,
0 xba,
0 x99,
0 x90,
0 xc7,
0 xe5,
0 xb1,
0 x3c,
0 x10,
0 x34,
0 x86,
0 x6a,
0 x6a,
0 x1f,
0 x39,
0 x63,
0 x58,
0 xe1,
0 x5e,
0 x97,
0 x95,
0 x45,
0 x40,
0 x38,
0 x45,
0 x6f,
0 x02,
0 xb5,
0 x86,
0 x6e,
0 xae,
0 x2f,
0 x32,
0 x7e,
0 xa1,
0 x3a,
0 x34,
0 x2c,
0 x1c,
0 xd3,
0 xff,
0 x4e,
0 x2c,
0 x38,
0 x1c,
0 xaa,
0 x2e,
0 x66,
0 xbe,
0 x32,
0 x3e,
0 x3c,
0 x06,
0 x5f };
/*
* 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 [ ] = {
0 x30 , 0 x91 , 0 xa1 , 0 x2e , 0 x40 , 0 xa5 , 0 x7d , 0 xf7 ,
0 xdc , 0 xed , 0 xee , 0 x05 , 0 xc2 , 0 x31 , 0 x91 , 0 x37 ,
0 xda , 0 xc5 , 0 xe3 , 0 x47 , 0 xb5 , 0 x35 , 0 x4b , 0 xfd ,
0 x18 , 0 xb2 , 0 x7e , 0 x67 , 0 x1e , 0 x92 , 0 x22 , 0 xe7 ,
0 xf5 , 0 x00 , 0 x71 , 0 xc0 , 0 x86 , 0 x8d , 0 x90 , 0 x31 ,
0 x36 , 0 x3e , 0 xd0 , 0 x94 , 0 x5d , 0 x2f , 0 x9a , 0 x68 ,
0 xd2 , 0 xf8 , 0 x3d , 0 x5e , 0 x84 , 0 x42 , 0 x35 , 0 xda ,
0 x75 , 0 xdd , 0 x05 , 0 xf0 , 0 x03 , 0 x31 , 0 x39 , 0 xe5 ,
0 xfd , 0 x2f , 0 x5a , 0 x7d , 0 x56 , 0 xd8 , 0 x26 , 0 xa0 ,
0 x51 , 0 x5e , 0 x32 , 0 xb4 , 0 xad , 0 xee , 0 xd4 , 0 x89 ,
0 xae , 0 x01 , 0 x7f , 0 xac , 0 x86 , 0 x98 , 0 x77 , 0 x26 ,
0 x5c , 0 x31 , 0 xd2 , 0 x5e , 0 xbb , 0 x7f , 0 xf5 , 0 x4c ,
0 x9b , 0 xf0 , 0 xa6 , 0 x37 , 0 x34 , 0 x08 , 0 x86 , 0 x6b ,
0 xce , 0 xeb , 0 x85 , 0 x66 , 0 x0a , 0 x26 , 0 x8a , 0 x14 ,
0 x92 , 0 x12 , 0 x74 , 0 xf4 , 0 xf0 , 0 xcb , 0 xb5 , 0 xfc ,
0 x38 , 0 xd5 , 0 x1e , 0 xa1 , 0 x2f , 0 x4a , 0 x1a , 0 xca ,
0 x66 , 0 xde , 0 x6e , 0 xe6 , 0 x6e , 0 x1c , 0 xef , 0 x50 ,
0 x41 , 0 x31 , 0 x09 , 0 xe7 , 0 x4a , 0 xb8 , 0 xa3 , 0 xaa ,
0 x5a , 0 x22 , 0 xbd , 0 x63 , 0 x0f , 0 xe9 , 0 x0e , 0 xdb ,
0 xb3 , 0 xca , 0 x7e , 0 x8d , 0 x40 , 0 xb3 , 0 x3e , 0 x0b ,
0 x12 , 0 x8b , 0 xb0 , 0 x80 , 0 x4d , 0 x6d , 0 xb0 , 0 x54 ,
0 xbb , 0 x4c , 0 x1d , 0 x6c , 0 xa0 , 0 x5c , 0 x9d , 0 x91 ,
0 xb3 , 0 xbb , 0 xd9 , 0 xfc , 0 x60 , 0 xec , 0 xc1 , 0 xbc ,
0 xae , 0 x72 , 0 x3f , 0 xa5 , 0 x4f , 0 x36 , 0 x2d , 0 x2c ,
0 x81 , 0 x03 , 0 x86 , 0 xa2 , 0 x03 , 0 x38 , 0 x36 , 0 x8e ,
0 xad , 0 x1d , 0 x53 , 0 xc6 , 0 xc5 , 0 x9e , 0 xda , 0 x08 ,
0 x35 , 0 x4f , 0 xb2 , 0 x78 , 0 xba , 0 xd1 , 0 x22 , 0 xde ,
0 xc4 , 0 x6b , 0 xbe , 0 x83 , 0 x71 , 0 x0f , 0 xee , 0 x38 ,
0 x4a , 0 x9f , 0 xda , 0 x90 , 0 x93 , 0 x6b , 0 x9a , 0 xf2 ,
0 xeb , 0 x23 , 0 xfe , 0 x41 , 0 x3f , 0 xf1 , 0 xfc , 0 xee ,
0 x7f , 0 x67 , 0 xa7 , 0 xb8 , 0 xab , 0 x29 , 0 xf4 , 0 x75 ,
0 x1c , 0 xe9 , 0 xd1 , 0 x47 , 0 x7d , 0 x86 , 0 x44 , 0 xe2 } ;
static const unsigned char seed2 [ ] = { 0 x00 ,
0 xbc , 0 xae , 0 xc4 , 0 xea , 0 x4e , 0 xd2 , 0 xed , 0 x1c ,
0 x8d , 0 x48 , 0 xed , 0 xf2 , 0 xa5 , 0 xb4 , 0 x18 , 0 xba ,
0 x00 , 0 xcb , 0 x9c , 0 x75 , 0 x8a , 0 x39 , 0 x94 , 0 x3b ,
0 xd0 , 0 xd6 , 0 x01 , 0 xf7 , 0 xc1 , 0 xf5 , 0 x9d , 0 xe5 ,
0 xe3 , 0 xb4 , 0 x1d , 0 xf5 , 0 x30 , 0 xfe , 0 x99 , 0 xe4 ,
0 x01 , 0 xab , 0 xc0 , 0 x88 , 0 x4e , 0 x67 , 0 x8f , 0 xc6 ,
0 x72 , 0 x39 , 0 x2e , 0 xac , 0 x51 , 0 xec , 0 x91 , 0 x41 ,
0 x47 , 0 x71 , 0 x14 , 0 x8a , 0 x1d , 0 xca , 0 x88 , 0 x15 ,
0 xea , 0 xc9 , 0 x48 , 0 x9a , 0 x71 , 0 x50 , 0 x19 , 0 x38 ,
0 xdb , 0 x4e , 0 x65 , 0 xd5 , 0 x13 , 0 xd8 , 0 x2a , 0 xc4 ,
0 xcd , 0 xfd , 0 x0c , 0 xe3 , 0 xc3 , 0 x60 , 0 xae , 0 x6d ,
0 x88 , 0 xf2 , 0 x3a , 0 xd0 , 0 x64 , 0 x73 , 0 x32 , 0 x89 ,
0 xcd , 0 x0b , 0 xb8 , 0 xc7 , 0 xa5 , 0 x27 , 0 x84 , 0 xd5 ,
0 x83 , 0 x3f , 0 x0e , 0 x10 , 0 x63 , 0 x10 , 0 x78 , 0 xac ,
0 x6b , 0 x56 , 0 xb2 , 0 x62 , 0 x3a , 0 x44 , 0 x56 , 0 xc0 ,
0 xe4 , 0 x33 , 0 xd7 , 0 x63 , 0 x4c , 0 xc9 , 0 x6b , 0 xae ,
0 xfb , 0 xe2 , 0 x9b , 0 xf4 , 0 x96 , 0 xc7 , 0 xf0 , 0 x2a ,
0 x50 , 0 xde , 0 x86 , 0 x69 , 0 x4f , 0 x42 , 0 x4b , 0 x1c ,
0 x7c , 0 xa8 , 0 x6a , 0 xfb , 0 x54 , 0 x47 , 0 x1b , 0 x41 ,
0 x31 , 0 x9e , 0 x0a , 0 xc6 , 0 xc0 , 0 xbc , 0 x88 , 0 x7f ,
0 x5a , 0 x42 , 0 xa9 , 0 x82 , 0 x58 , 0 x32 , 0 xb3 , 0 xeb ,
0 x54 , 0 x83 , 0 x84 , 0 x26 , 0 x92 , 0 xa6 , 0 xc0 , 0 x6e ,
0 x2b , 0 xa6 , 0 x82 , 0 x82 , 0 x43 , 0 x58 , 0 x84 , 0 x53 ,
0 x31 , 0 xcf , 0 xd0 , 0 x0a , 0 x11 , 0 x09 , 0 x44 , 0 xc8 ,
0 x11 , 0 x36 , 0 xe0 , 0 x04 , 0 x85 , 0 x2e , 0 xd1 , 0 x29 ,
0 x6b , 0 x7b , 0 x00 , 0 x71 , 0 x5f , 0 xef , 0 x7b , 0 x7a ,
0 x2d , 0 x91 , 0 xf9 , 0 x84 , 0 x45 , 0 x4d , 0 xc7 , 0 xe1 ,
0 xee , 0 xd4 , 0 xb8 , 0 x61 , 0 x3b , 0 x13 , 0 xb7 , 0 xba ,
0 x95 , 0 x39 , 0 xf6 , 0 x3d , 0 x89 , 0 xbd , 0 xa5 , 0 x80 ,
0 x93 , 0 xf7 , 0 xe5 , 0 x17 , 0 x05 , 0 xc5 , 0 x65 , 0 xb7 ,
0 xde , 0 xc9 , 0 x9f , 0 x04 , 0 x87 , 0 xcf , 0 x4f , 0 x86 ,
0 xc3 , 0 x29 , 0 x7d , 0 xb7 , 0 x89 , 0 xbf , 0 xe3 , 0 xde } ;
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 " },
{
0 xCE534351,
"CKR_NSS_CERTDB_FAILED " },
{
0 xCE534352,
"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;
if (NSS_InitializePRErrorTable() != SECSuccess) {
/* this will output the NSPR eror number, and maybe the NSPR
* error string */
lperror(
"Couldn't initialize error table." );
print_error(
"Can not translate error codes to strings." );
/* failure to initialize this table isn't fatal */
}
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;
}
CK_RV
shlibSignDSA(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot,
CK_SESSION_HANDLE hRwSession,
int keySize, PRFileDesc *ifd,
PRFileDesc *ofd,
const HashTable *hash)
{
CK_MECHANISM digestmech;
CK_ULONG digestLen =
0 ;
CK_BYTE digest[HASH_LENGTH_MAX];
CK_BYTE sign[
64 ];
/* DSA2 SIGNATURE LENGTH */
CK_ULONG signLen =
0 ;
CK_ULONG expectedSigLen =
sizeof (sign);
CK_MECHANISM signMech = {
CKM_DSA, NULL,
0
};
int bytesRead;
int bytesWritten;
unsigned char file_buf[
512 ];
NSSSignChkHeader header;
int count =
0 ;
CK_RV crv = CKR_GENERAL_ERROR;
PRStatus rv = PR_SUCCESS;
const char *hashName =
"sha256" ;
/* default hash value */
int i;
/*** 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;
if ((keySize ==
0 ) || (keySize >
1024 )) {
CK_MECHANISM_INFO mechInfo;
crv = pFunctionList->C_GetMechanismInfo(slot,
CKM_DSA, &mechInfo);
if (crv != CKR_OK) {
pk11error(
"Couldn't get mechanism info for DSA" , crv);
return crv;
}
if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
PR_fprintf(PR_STDERR,
"token doesn't support DSA2 (Max key size=%d)\n" ,
mechInfo.ulMaxKeySize);
return crv;
}
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);
hashName =
"sha-1" ;
/* use sha-1 for old dsa keys */
expectedSigLen =
32 ;
}
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 = hash ? hash->hash : CKM_SHA256;
digestmech.pParameter = NULL;
digestmech.ulParameterLen =
0 ;
}
else {
PR_fprintf(PR_STDERR,
"Only keysizes 1024 and 2048 are supported" );
return CKR_GENERAL_ERROR;
}
if (hash == NULL) {
hash = findHash(hashName);
}
if (hash == NULL) {
PR_fprintf(PR_STDERR,
"Internal error, couldn't find hash '%s' in table.\n" ,
hashName);
return CKR_GENERAL_ERROR;
}
digestmech.mechanism = hash->hash;
digestmech.pParameter = NULL;
digestmech.ulParameterLen =
0 ;
dsaPubKeyTemplate[
3 ].type = CKA_TOKEN;
dsaPubKeyTemplate[
3 ].pValue = &ckfalse;
/* session object */
dsaPubKeyTemplate[
3 ].ulValueLen =
sizeof (ckfalse);
dsaPubKeyTemplate[
4 ].type = CKA_VERIFY;
dsaPubKeyTemplate[
4 ].pValue = &cktrue;
dsaPubKeyTemplate[
4 ].ulValueLen =
sizeof (cktrue);
dsaKeyPairGenMech.mechanism = CKM_DSA_KEY_PAIR_GEN;
dsaKeyPairGenMech.pParameter = NULL;
dsaKeyPairGenMech.ulParameterLen =
0 ;
dsaPrivKeyTemplate[
0 ].type = CKA_TOKEN;
dsaPrivKeyTemplate[
0 ].pValue = &ckfalse;
/* session object */
dsaPrivKeyTemplate[
0 ].ulValueLen =
sizeof (ckfalse);
dsaPrivKeyTemplate[
1 ].type = CKA_PRIVATE;
dsaPrivKeyTemplate[
1 ].pValue = &cktrue;
dsaPrivKeyTemplate[
1 ].ulValueLen =
sizeof (cktrue);
dsaPrivKeyTemplate[
2 ].type = CKA_SENSITIVE;
dsaPrivKeyTemplate[
2 ].pValue = &cktrue;
dsaPrivKeyTemplate[
2 ].ulValueLen =
sizeof (cktrue);
dsaPrivKeyTemplate[
3 ].type = CKA_SIGN,
dsaPrivKeyTemplate[
3 ].pValue = &cktrue;
dsaPrivKeyTemplate[
3 ].ulValueLen =
sizeof (cktrue);
dsaPrivKeyTemplate[
4 ].type = CKA_EXTRACTABLE;
dsaPrivKeyTemplate[
4 ].pValue = &ckfalse;
dsaPrivKeyTemplate[
4 ].ulValueLen =
sizeof (ckfalse);
/* Generate a DSA key pair */
logIt(
"Generate a DSA key pair ... \n" );
crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
dsaPubKeyTemplate,
PR_ARRAY_SIZE(dsaPubKeyTemplate),
dsaPrivKeyTemplate,
PR_ARRAY_SIZE(dsaPrivKeyTemplate),
&hDSApubKey, &hDSAprivKey);
if (crv != CKR_OK) {
pk11error(
"DSA key pair generation failed" , crv);
return crv;
}
/* compute the digest */
memset(digest,
0 ,
sizeof (digest));
crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
if (crv != CKR_OK) {
pk11error(
"C_DigestInit failed" , crv);
return crv;
}
/* Digest the file */
while ((bytesRead = PR_Read(ifd, 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);
return crv;
}
count += bytesRead;
}
if (bytesRead <
0 ) {
lperror(
"0 bytes read from input file" );
return CKR_INTERNAL_IN_FAILURE;
}
digestLen =
sizeof (digest);
crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
&digestLen);
if (crv != CKR_OK) {
pk11error(
"C_DigestFinal failed" , crv);
return crv;
}
if (digestLen != hash->hashLength) {
PR_fprintf(PR_STDERR,
"digestLen has incorrect length %lu "
"it should be %lu \n" ,
digestLen,
sizeof (digest));
return crv;
}
/* 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);
return crv;
}
signLen =
sizeof (sign);
crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)digest, digestLen,
sign, &signLen);
if (crv != CKR_OK) {
pk11error(
"C_Sign failed" , crv);
return crv;
}
if (signLen != expectedSigLen) {
PR_fprintf(PR_STDERR,
"signLen has incorrect length %lu "
"it should be %lu \n" ,
signLen, expectedSigLen);
return crv;
}
if (verify) {
crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
if (crv != CKR_OK) {
pk11error(
"C_VerifyInit failed" , crv);
return crv;
}
crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
sign, signLen);
if (crv != CKR_OK) {
pk11error(
"C_Verify failed" , crv);
return crv;
}
}
if (verbose) {
int j;
PR_fprintf(PR_STDERR,
"Library File Size: %d bytes\n" , count);
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" );
}
}
/*
* 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 .
*/
header.magic1 = NSS_SIGN_CHK_MAGIC1;
header.magic2 = NSS_SIGN_CHK_MAGIC2;
header.majorVersion = compat ? COMPAT_MAJOR : NSS_SIGN_CHK_MAJOR_VERSION;
header.minorVersion = compat ? COMPAT_MINOR : NSS_SIGN_CHK_MINOR_VERSION;
encodeInt(header.offset,
sizeof (header));
/* offset to data start */
encodeInt(header.type, CKK_DSA);
bytesWritten = PR_Write(ofd, &header,
sizeof (header));
if (bytesWritten !=
sizeof (header)) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* 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);
return crv;
}
/* CKA_PRIME */
rv = writeItem(ofd, dsaPubKeyTemplate[
0 ].pValue,
dsaPubKeyTemplate[
0 ].ulValueLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* CKA_SUBPRIME */
rv = writeItem(ofd, dsaPubKeyTemplate[
1 ].pValue,
dsaPubKeyTemplate[
1 ].ulValueLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* CKA_BASE */
rv = writeItem(ofd, dsaPubKeyTemplate[
2 ].pValue,
dsaPubKeyTemplate[
2 ].ulValueLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* DSA Public Key value */
rv = writeItem(ofd, dsaPubKeyValue.pValue,
dsaPubKeyValue.ulValueLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* DSA SIGNATURE */
rv = writeItem(ofd, &sign, signLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
return CKR_OK;
}
/* side effect, attrCount is incremented, returns zero on failure */
#define SET_ATTR(attrCount,
template , templateLen, _type, _value, _len) \
if (attrCount >= templateLen) { \
return 0 ; \
} \
template [attrCount].type = _type; \
template [attrCount].pValue = _value; \
template [attrCount++].ulValueLen = _len;
/* build a template. keyLengthptr and key are both optional */
size_t
buildHMACKeyTemplate(CK_ATTRIBUTE *
template ,
size_t templateLength,
const CK_BBOOL *sensitivePtr,
const CK_KEY_TYPE *keyTypePtr,
const CK_ULONG *keyLengthPtr,
const SECItem *key)
{
int attrCount =
0 ;
SET_ATTR(attrCount,
template , templateLength,
CKA_TOKEN, &ckfalse,
sizeof (ckfalse))
SET_ATTR(attrCount,
template , templateLength,
CKA_PRIVATE, &ckfalse,
sizeof (ckfalse))
SET_ATTR(attrCount,
template , templateLength,
CKA_SENSITIVE, (
void *)sensitivePtr,
sizeof (*sensitivePtr))
SET_ATTR(attrCount,
template , templateLength,
CKA_SIGN, &cktrue,
sizeof (cktrue))
SET_ATTR(attrCount,
template , templateLength,
CKA_EXTRACTABLE, &ckfalse,
sizeof (ckfalse))
SET_ATTR(attrCount,
template , templateLength,
CKA_KEY_TYPE, (
void *)keyTypePtr,
sizeof (*keyTypePtr))
if (keyLengthPtr) {
SET_ATTR(attrCount,
template , templateLength,
CKA_VALUE_LEN, (
void *)keyLengthPtr,
sizeof (*keyLengthPtr))
}
if (key) {
SET_ATTR(attrCount,
template , templateLength,
CKA_CLASS, &secret_key_obj_class,
sizeof (secret_key_obj_class))
SET_ATTR(attrCount,
template , templateLength,
CKA_VALUE, (
void *)key->data, key->len)
}
return attrCount;
}
/* helper functions to generate HMAC keys */
CK_RV
generateHMACKey(CK_FUNCTION_LIST_PTR pFunctionList,
CK_SESSION_HANDLE hRwSession, CK_MECHANISM_PTR keyGenMech,
CK_ULONG keyLength, CK_KEY_TYPE keyType, CK_BBOOL sensitive,
CK_OBJECT_HANDLE_PTR phHMACKey)
{
CK_ATTRIBUTE hmacKeyTemplate[
7 ];
size_t templateLen;
templateLen = buildHMACKeyTemplate(hmacKeyTemplate,
PR_ARRAY_SIZE(hmacKeyTemplate),
&sensitive, &keyType, &keyLength, NULL);
if (templateLen ==
0 ) {
/* this can only happen if we didn't declear hmacKeyTemplate
* to be big enough . . . on debug builds crash with a useful
* Assert . otherwise just fail ( won ' t work until the program
* is fixed). */
PORT_Assert(templateLen < PR_ARRAY_SIZE(hmacKeyTemplate));
return CKR_GENERAL_ERROR;
}
return pFunctionList->C_GenerateKey(hRwSession, keyGenMech,
hmacKeyTemplate, templateLen,
phHMACKey);
}
/* generate an hmac and and try to extract it */
CK_RV
generateAndExtractHMACKeyRaw(CK_FUNCTION_LIST_PTR pFunctionList,
CK_SESSION_HANDLE hRwSession, CK_MECHANISM_PTR keyGenMech,
CK_ULONG keyLength, CK_KEY_TYPE keyType,
CK_ATTRIBUTE_PTR pHMACKeyValue,
CK_OBJECT_HANDLE_PTR phHMACKey)
{
CK_RV crv;
crv = generateHMACKey(pFunctionList, hRwSession, keyGenMech, keyLength,
keyType, ckfalse, phHMACKey);
if (crv != CKR_OK) {
return crv;
}
crv = pFunctionList->C_GetAttributeValue(hRwSession, *phHMACKey,
pHMACKeyValue,
1 );
if (crv != CKR_OK) {
pFunctionList->C_DestroyObject(hRwSession, *phHMACKey);
return crv;
}
return crv;
}
/* trick to import a key in FIPS mode.
* There are limitted times when this is legitimate ,
* if you think you need this contact the crypto team
* before using it . Usually if you need this its because
* you are improperly handling FIPS CPS material which is
* not allowed */
CK_RV
fipsImportKey(CK_FUNCTION_LIST_PTR pFunctionList,
CK_SESSION_HANDLE hRwSession,
const SECItem *pKeyItem,
CK_KEY_TYPE keyType, CK_SESSION_HANDLE_PTR phHMACKey)
{
CK_OBJECT_HANDLE hTmpKey;
CK_MECHANISM deriveMech = {
0 , NULL,
0 };
CK_MECHANISM hmacKeyGenMech = {
0 , NULL,
0 };
CK_KEY_DERIVATION_STRING_DATA deriveParams = {
0 };
CK_ATTRIBUTE hmacKeyTemplate[
7 ];
size_t templateLen;
/* put length in an appropriate size variable */
CK_ULONG keyLength = pKeyItem->len;
CK_RV crv;
templateLen = buildHMACKeyTemplate(hmacKeyTemplate,
PR_ARRAY_SIZE(hmacKeyTemplate),
&cktrue, &keyType, &keyLength, NULL);
if (templateLen ==
0 ) {
/* this can only happen if we didn't declear hmacKeyTemplate
* to be big enough . . . on debug builds crash with a useful
* Assert . otherwise just fail ( won ' t work until the program
* is fixed). */
PORT_Assert(templateLen < PR_ARRAY_SIZE(hmacKeyTemplate));
return CKR_GENERAL_ERROR;
}
deriveParams.pData = pKeyItem->data;
deriveParams.ulLen = pKeyItem->len;
deriveMech.mechanism = CKM_CONCATENATE_DATA_AND_BASE;
deriveMech.pParameter = (
void *)&deriveParams;
deriveMech.ulParameterLen =
sizeof (deriveParams);
hmacKeyGenMech.mechanism = CKM_GENERIC_SECRET_KEY_GEN;
/* generate a dummy key */
crv = generateHMACKey(pFunctionList, hRwSession, &hmacKeyGenMech,
pKeyItem->len, keyType, cktrue, &hTmpKey);
if (crv != CKR_OK) {
return crv;
}
/* append the desired key to the front of the dummy key, and
* then truncate the dummy key */
crv = pFunctionList->C_DeriveKey(hRwSession, &deriveMech, hTmpKey,
hmacKeyTemplate,
templateLen,
phHMACKey);
/* done with the dummy key, delete it */
pFunctionList->C_DestroyObject(hRwSession, hTmpKey);
return crv;
}
/* generate an hmac key and extract it. If it fails, assume we are in
* FIPS mode and use generate random to generate a key and use fipsImport
* to import it */
CK_RV
generateAndExtractHMACKey(CK_FUNCTION_LIST_PTR pFunctionList,
CK_SESSION_HANDLE hRwSession, CK_MECHANISM_PTR keyGenMech,
CK_ULONG keyLength, CK_KEY_TYPE keyType,
CK_ATTRIBUTE_PTR pHMACKeyValue,
CK_OBJECT_HANDLE_PTR phHMACKey)
{
SECItem keyItem;
CK_RV crv;
crv = generateAndExtractHMACKeyRaw(pFunctionList, hRwSession, keyGenMech,
keyLength, keyType, pHMACKeyValue,
phHMACKey);
if (crv == CKR_OK) {
return crv;
}
keyItem.data = pHMACKeyValue->pValue;
keyItem.len = keyLength;
crv = pFunctionList->C_GenerateRandom(hRwSession, keyItem.data,
keyItem.len);
if (crv != CKR_OK) {
return crv;
}
pHMACKeyValue->ulValueLen = keyLength;
return fipsImportKey(pFunctionList, hRwSession, &keyItem, keyType,
phHMACKey);
}
/*
* import a user supplied key . If we fail , we are probably in FIPS mode ,
* use fipsImport to import the key
*/
CK_RV
importHMACKey(CK_FUNCTION_LIST_PTR pFunctionList,
CK_SESSION_HANDLE hRwSession, CK_OBJECT_HANDLE_PTR phHMACKey,
CK_KEY_TYPE keyType,
const SECItem *keyItem)
{
CK_ATTRIBUTE hmacKeyTemplate[
8 ];
size_t templateLen;
CK_RV crv;
templateLen = buildHMACKeyTemplate(hmacKeyTemplate,
PR_ARRAY_SIZE(hmacKeyTemplate),
&ckfalse, &keyType, NULL, keyItem);
if (templateLen ==
0 ) {
/* this can only happen if we didn't declear hmacKeyTemplate
* to be big enough . . . on debug builds crash with a useful
* Assert . otherwise just fail ( won ' t work until the program
* is fixed). */
PORT_Assert(templateLen < PR_ARRAY_SIZE(hmacKeyTemplate));
return CKR_GENERAL_ERROR;
}
crv = pFunctionList->C_CreateObject(hRwSession,
hmacKeyTemplate,
templateLen,
phHMACKey);
if (crv != CKR_OK) {
crv = fipsImportKey(pFunctionList, hRwSession,
keyItem, keyType, phHMACKey);
return crv;
}
return crv;
}
CK_RV
shlibSignHMAC(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID slot,
CK_SESSION_HANDLE hRwSession,
int keySize,
char *key,
PRFileDesc *ifd, PRFileDesc *ofd,
const HashTable *hash)
{
CK_MECHANISM hmacMech = {
0 , NULL,
0 };
/* init the HMAC KeyValue */
CK_BYTE keyBuf[HASH_LENGTH_MAX] = {
0 };
CK_ULONG keyLen =
0 ;
CK_BYTE sign[HASH_LENGTH_MAX];
CK_ULONG signLen =
0 ;
int bytesRead;
int bytesWritten;
unsigned char file_buf[
512 ];
NSSSignChkHeader header;
int count =
0 ;
CK_RV crv = CKR_GENERAL_ERROR;
PRStatus rv = PR_SUCCESS;
int i;
/*** HMAC Key ***/
CK_OBJECT_HANDLE hHMACKey = CK_INVALID_HANDLE;
if (hash == NULL) {
hash = findHash(
"sha256" );
}
if (hash == NULL) {
PR_fprintf(PR_STDERR,
"Internal error:Could find sha256 entry in table.\n" );
}
if (key == NULL) {
CK_ATTRIBUTE hmacKeyValue;
CK_MECHANISM hmacKeyGenMech = {
0 , NULL,
0 };
hmacKeyGenMech.mechanism = CKM_GENERIC_SECRET_KEY_GEN;
hmacKeyValue.type = CKA_VALUE;
hmacKeyValue.pValue = (CK_VOID_PTR)&keyBuf;
hmacKeyValue.ulValueLen =
sizeof (keyBuf);
/* Generate a HMAC key */
logIt(
"Generate an HMAC key ... \n" );
crv = generateAndExtractHMACKey(pFunctionList, hRwSession,
&hmacKeyGenMech,
hash->hashLength, hash->keyType,
&hmacKeyValue, &hHMACKey);
if (crv != CKR_OK) {
pk11error(
"HMAC key generation failed" , crv);
return crv;
}
keyLen = hmacKeyValue.ulValueLen;
}
else {
SECItem keyItem = {
0 };
if (SECU_HexString2SECItem(NULL, &keyItem, key) == NULL) {
lperror(
"Reading HMAC key from commandline failed."
" Not a valid hex-key." );
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (keyItem.len != hash->hashLength) {
print_error(
"Supplied HMAC key does not match the HMAC hash length." );
SECITEM_FreeItem(&keyItem, PR_FALSE);
return CKR_ATTRIBUTE_VALUE_INVALID;
}
logIt(
"Using static HMAC key ... \n" );
crv = importHMACKey(pFunctionList, hRwSession, &hHMACKey,
hash->keyType, &keyItem);
if (crv != CKR_OK) {
pk11error(
"HMAC key import failed" , crv);
SECITEM_FreeItem(&keyItem, PR_FALSE);
return crv;
}
if (
sizeof (keyBuf) < keyItem.len) {
/* this is a paranoia check. It really shouldn't happen because
* we already check for keyItem . len ! = hash - > hashLength above ,
* and keyBuf should be big enough for the largest hash length */
print_error(
"Input key is too large" );
SECITEM_FreeItem(&keyItem, PR_FALSE);
return CKR_HOST_MEMORY;
}
/* save the HMAC KeyValue */
PORT_Memcpy(keyBuf, keyItem.data, keyItem.len);
keyLen = keyItem.len;
SECITEM_FreeItem(&keyItem, PR_FALSE);
}
if (crv != CKR_OK) {
pk11error(
"HMAC key generation failed" , crv);
return crv;
}
hmacMech.mechanism = hash->hmac;
/* compute the digest */
memset(sign,
0 ,
sizeof (sign));
crv = pFunctionList->C_SignInit(hRwSession, &hmacMech, hHMACKey);
if (crv != CKR_OK) {
pk11error(
"C_SignInit failed" , crv);
return crv;
}
/* Digest the file */
while ((bytesRead = PR_Read(ifd, file_buf,
sizeof (file_buf))) >
0 ) {
crv = pFunctionList->C_SignUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
bytesRead);
if (crv != CKR_OK) {
pk11error(
"C_SignUpdate failed" , crv);
return crv;
}
count += bytesRead;
}
if (bytesRead <
0 ) {
lperror(
"0 bytes read from input file" );
return CKR_INTERNAL_IN_FAILURE;
}
signLen =
sizeof (sign);
crv = pFunctionList->C_SignFinal(hRwSession, (CK_BYTE_PTR)sign,
&signLen);
if (crv != CKR_OK) {
pk11error(
"C_SignFinal failed" , crv);
return crv;
}
if (signLen != hash->hashLength) {
PR_fprintf(PR_STDERR,
"digestLen has incorrect length %lu "
"it should be %lu \n" ,
signLen, hash->hashLength);
return crv;
}
if (verbose) {
int j;
PR_fprintf(PR_STDERR,
"Library File Size: %d bytes\n" , count);
PR_fprintf(PR_STDERR,
" key: %lu bytes\n" , keyLen);
#define STEP
10
for (i =
0 ; i < (
int )keyLen; i += STEP) {
PR_fprintf(PR_STDERR,
" " );
for (j =
0 ; j < STEP && (i + j) < (
int )keyLen; j++) {
PR_fprintf(PR_STDERR,
" %02x" , keyBuf[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" );
}
}
/*
* 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 .
*/
header.magic1 = NSS_SIGN_CHK_MAGIC1;
header.magic2 = NSS_SIGN_CHK_MAGIC2;
header.majorVersion = NSS_SIGN_CHK_MAJOR_VERSION;
header.minorVersion = NSS_SIGN_CHK_MINOR_VERSION;
encodeInt(header.offset,
sizeof (header));
/* offset to data start */
encodeInt(header.type, NSS_SIGN_CHK_FLAG_HMAC | hash->hashType);
bytesWritten = PR_Write(ofd, &header,
sizeof (header));
if (bytesWritten !=
sizeof (header)) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* HMACKey */
rv = writeItem(ofd, keyBuf, keyLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
/* HMAC SIGNATURE */
rv = writeItem(ofd, &sign, signLen);
if (rv != PR_SUCCESS) {
return CKR_INTERNAL_OUT_FAILURE;
}
return CKR_OK;
}
int
main(
int argc,
char **argv)
{
PLOptState *optstate;
char *program_name;
char *libname = NULL;
PRLibrary *lib = NULL;
PRFileDesc *ifd = NULL;
PRFileDesc *ofd = NULL;
const char *input_file = NULL;
/* read/create encrypted data from here */
char *output_file = NULL;
/* write new encrypted data here */
unsigned int keySize =
0 ;
ModeTypes mode = mode_default;
PRBool useDSA = PR_FALSE;
PRBool successful = PR_FALSE;
const HashTable *hash = NULL;
char *key = NULL;
#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 ;
program_name = strrchr(argv[
0 ],
'/' );
program_name = program_name ? (program_name +
1 ) : argv[
0 ];
optstate = PL_CreateOptState(argc, argv,
"i:o:f:FCd:hH?k:K:p:P:vVs:t:Dc" );
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 'D' :
useDSA = PR_TRUE;
break ;
case 'c' :
compat = PR_TRUE;
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 'K' :
if (!optstate->value) {
PL_DestroyOptState(optstate);
usage(program_name);
}
key = PL_strdup(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' :
if (mode == mode_fips) {
break ;
/* mode is already set to fips */
}
if (mode != mode_default) {
PR_fprintf(PR_STDERR,
"-C and -F are mutually exclusive\n" );
usage(program_name);
}
mode = mode_fips;
break ;
case 'C' :
if (mode == mode_nonfips) {
break ;
/* mode is already set to nonfips */
}
if (mode != mode_default) {
PR_fprintf(PR_STDERR,
"-F and -C are mutually exclusive\n" );
usage(program_name);
}
mode = mode_nonfips;
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 't' :
if (!optstate->value) {
PL_DestroyOptState(optstate);
usage(program_name);
}
hash = findHash(optstate->value);
if (hash == NULL) {
PR_fprintf(PR_STDERR,
"Invalid hash '%s'\n" ,
optstate->value);
usage(program_name);
}
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);
pC_GetFunctionList = (CK_C_GetFunctionList)
PR_FindFunctionSymbol(lib, getFunctionListName(mode));
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;
}
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" );
}
/* open the shared library */
ifd = PR_OpenFile(input_file, PR_RDONLY,
0 );
if (ifd == 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);
}
if (verbose) {
PR_fprintf(PR_STDERR,
"Library File: %s\n" , input_file);
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
}
/* open the target signature file */
ofd = PR_Open(output_file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
0666 );
if (ofd == NULL) {
lperror(output_file);
goto cleanup;
}
if (useDSA) {
crv = shlibSignDSA(pFunctionList, pSlotList[slotIndex], hRwSession,
keySize, ifd, ofd, hash);
}
else {
crv = shlibSignHMAC(pFunctionList, pSlotList[slotIndex], hRwSession,
keySize, key, ifd, ofd, hash);
}
if (crv == CKR_INTERNAL_OUT_FAILURE) {
lperror(output_file);
}
if (crv == CKR_INTERNAL_IN_FAILURE) {
lperror(input_file);
}
PR_Close(ofd);
ofd = NULL;
/* close the input_File */
PR_Close(ifd);
ifd = NULL;
#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
if (ifd) {
PR_Close(ifd);
}
if (ofd) {
PR_Close(ofd);
}
disableUnload = PR_GetEnvSecure(
"NSS_DISABLE_UNLOAD" );
if (!disableUnload && lib) {
PR_UnloadLibrary(lib);
}
PR_Cleanup();
if (crv != CKR_OK)
return crv;
return (successful) ?
0 :
1 ;
}
Messung V0.5 in Prozent C=84 H=91 G=87
¤ Dauer der Verarbeitung: 0.56 Sekunden
¤
*© Formatika GbR, Deutschland