tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

shlibsign.c (73409B)


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