security/nss/cmd/shlibsign/shlibsign.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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/. */
     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  */
    18 #ifdef XP_UNIX
    19 #define USES_LINKS 1
    20 #endif
    22 #include <assert.h>
    23 #include <stdio.h>
    24 #include <stdlib.h>
    25 #include <string.h>
    26 #include <stdarg.h>
    28 #ifdef USES_LINKS
    29 #include <unistd.h>
    30 #include <sys/param.h>
    31 #include <sys/types.h>
    32 #include <sys/stat.h>
    33 #endif
    35 /* nspr headers */
    36 #include "prlink.h"
    37 #include "prprf.h"
    38 #include "prenv.h"
    39 #include "plgetopt.h"
    40 #include "prinit.h"
    41 #include "prmem.h"
    42 #include "plstr.h"
    43 #include "prerror.h"
    45 /* softoken headers */
    46 #include "pkcs11.h"
    47 #include "pkcs11t.h"
    49 /* freebl headers */
    50 #include "shsign.h"
    52 #define NUM_ELEM(array) (sizeof(array)/sizeof(array[0]))
    53 CK_BBOOL true = CK_TRUE;
    54 CK_BBOOL false = CK_FALSE;
    55 static PRBool verbose = PR_FALSE;
    57 static void
    58 usage (const char *program_name)
    59 {
    60     PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
    61     PR_fprintf (debug_out,
    62                 "type %s -H for more detail information.\n", program_name);
    63     PR_fprintf (debug_out,
    64                 "Usage: %s [-v] [-V] [-o outfile] [-d dbdir] [-f pwfile]\n"
    65                 "          [-F] [-p pwd] -[P dbprefix ] "
    66                 "-i shared_library_name\n",
    67                 program_name);
    68     exit(1);
    69 }
    71 static void 
    72 long_usage(const char *program_name) 
    73 {
    74     PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
    75     PR_fprintf(debug_out, "%s test program usage:\n", program_name);
    76     PR_fprintf(debug_out, "\t-i <infile>  shared_library_name to process\n");
    77     PR_fprintf(debug_out, "\t-o <outfile> checksum outfile\n");
    78     PR_fprintf(debug_out, "\t-d <path>    database path location\n");
    79     PR_fprintf(debug_out, "\t-P <prefix>  database prefix\n");
    80     PR_fprintf(debug_out, "\t-f <file>    password File : echo pw > file \n");
    81     PR_fprintf(debug_out, "\t-F           FIPS mode\n"); 
    82     PR_fprintf(debug_out, "\t-p <pwd>     password\n");
    83     PR_fprintf(debug_out, "\t-v           verbose output\n");
    84     PR_fprintf(debug_out, "\t-V           perform Verify operations\n");
    85     PR_fprintf(debug_out, "\t-?           short help message\n");
    86     PR_fprintf(debug_out, "\t-h           short help message\n");
    87     PR_fprintf(debug_out, "\t-H           this help message\n");
    88     PR_fprintf(debug_out, "\n\n\tNote: Use of FIPS mode requires your ");
    89     PR_fprintf(debug_out, "library path is using \n");
    90     PR_fprintf(debug_out, "\t      pre-existing libraries with generated ");
    91     PR_fprintf(debug_out, "checksum files\n");
    92     PR_fprintf(debug_out, "\t      and database in FIPS mode \n");
    93     exit(1);
    94 }
    96 static char * 
    97 mkoutput(const char *input)
    98 {
    99     int in_len = strlen(input);
   100     char *output = PR_Malloc(in_len+sizeof(SGN_SUFFIX));
   101     int index = in_len + 1 - sizeof("."SHLIB_SUFFIX);
   103     if ((index > 0) && 
   104         (PL_strncmp(&input[index],
   105                  "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) {
   106         in_len = index;
   107     }
   108     memcpy(output,input,in_len);
   109     memcpy(&output[in_len],SGN_SUFFIX,sizeof(SGN_SUFFIX));
   110     return output;
   111 }
   113 static void 
   114 lperror(const char *string) {
   115     PRErrorCode errorcode;
   117     errorcode = PR_GetError();
   118     PR_fprintf(PR_STDERR, "%s: %d: %s\n", string, errorcode,
   119                 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
   120 }
   122 static void
   123 encodeInt(unsigned char *buf, int val)
   124 {
   125     buf[3] = (val >> 0) & 0xff;
   126     buf[2] = (val >>  8) & 0xff;
   127     buf[1] = (val >> 16) & 0xff;
   128     buf[0] = (val >> 24) & 0xff;
   129     return;
   130 }
   132 static PRStatus 
   133 writeItem(PRFileDesc *fd, CK_VOID_PTR pValue,
   134           CK_ULONG ulValueLen, char *file)
   135 {
   136     unsigned char buf[4];
   137     int bytesWritten;
   138     if (ulValueLen == 0) {
   139         PR_fprintf(PR_STDERR, "call to writeItem with 0 bytes of data.\n");
   140         return PR_FAILURE;
   141     }
   143     encodeInt(buf,ulValueLen);
   144     bytesWritten = PR_Write(fd,buf, 4);
   145     if (bytesWritten != 4) {
   146         lperror(file);
   147         return PR_FAILURE;
   148     }
   149     bytesWritten = PR_Write(fd, pValue, ulValueLen);
   150     if (bytesWritten != ulValueLen) {
   151         lperror(file);
   152         return PR_FAILURE;
   153     }
   154     return PR_SUCCESS;
   155 }
   157 static const unsigned char prime[] = { 0x00,
   158    0x97, 0x44, 0x1d, 0xcc, 0x0d, 0x39, 0x0d, 0x8d, 
   159    0xcb, 0x75, 0xdc, 0x24, 0x25, 0x6f, 0x01, 0x92, 
   160    0xa1, 0x11, 0x07, 0x6b, 0x70, 0xac, 0x73, 0xd7, 
   161    0x82, 0x28, 0xdf, 0xab, 0x82, 0x0c, 0x41, 0x0c, 
   162    0x95, 0xb3, 0x3c, 0x3d, 0xea, 0x8a, 0xe6, 0x44, 
   163    0x0a, 0xb8, 0xab, 0x90, 0x15, 0x41, 0x11, 0xe8, 
   164    0x48, 0x7b, 0x8d, 0xb0, 0x9c, 0xd3, 0xf2, 0x69, 
   165    0x66, 0xff, 0x66, 0x4b, 0x70, 0x2b, 0xbf, 0xfb, 
   166    0xd6, 0x68, 0x85, 0x76, 0x1e, 0x34, 0xaa, 0xc5, 
   167    0x57, 0x6e, 0x23, 0x02, 0x08, 0x60, 0x6e, 0xfd, 
   168    0x67, 0x76, 0xe1, 0x7c, 0xc8, 0xcb, 0x51, 0x77, 
   169    0xcf, 0xb1, 0x3b, 0x00, 0x2e, 0xfa, 0x21, 0xcd, 
   170    0x34, 0x76, 0x75, 0x01, 0x19, 0xfe, 0xf8, 0x5d, 
   171    0x43, 0xc5, 0x34, 0xf3, 0x7a, 0x95, 0xdc, 0xc2, 
   172    0x58, 0x07, 0x19, 0x2f, 0x1d, 0x6f, 0x9a, 0x77, 
   173    0x7e, 0x55, 0xaa, 0xe7, 0x5a, 0x50, 0x43, 0xd3 };
   175 static const unsigned char subprime[] = { 0x0,
   176    0xd8, 0x16, 0x23, 0x34, 0x8a, 0x9e, 0x3a, 0xf5, 
   177    0xd9, 0x10, 0x13, 0x35, 0xaa, 0xf3, 0xf3, 0x54, 
   178    0x0b, 0x31, 0x24, 0xf1 };
   180 static const unsigned char base[] = { 
   181     0x03, 0x3a, 0xad, 0xfa, 0x3a, 0x0c, 0xea, 0x0a, 
   182     0x4e, 0x43, 0x32, 0x92, 0xbb, 0x87, 0xf1, 0x11, 
   183     0xc0, 0xad, 0x39, 0x38, 0x56, 0x1a, 0xdb, 0x23, 
   184     0x66, 0xb1, 0x08, 0xda, 0xb6, 0x19, 0x51, 0x42, 
   185     0x93, 0x4f, 0xc3, 0x44, 0x43, 0xa8, 0x05, 0xc1, 
   186     0xf8, 0x71, 0x62, 0x6f, 0x3d, 0xe2, 0xab, 0x6f, 
   187     0xd7, 0x80, 0x22, 0x6f, 0xca, 0x0d, 0xf6, 0x9f, 
   188     0x45, 0x27, 0x83, 0xec, 0x86, 0x0c, 0xda, 0xaa, 
   189     0xd6, 0xe0, 0xd0, 0x84, 0xfd, 0xb1, 0x4f, 0xdc, 
   190     0x08, 0xcd, 0x68, 0x3a, 0x77, 0xc2, 0xc5, 0xf1, 
   191     0x99, 0x0f, 0x15, 0x1b, 0x6a, 0x8c, 0x3d, 0x18, 
   192     0x2b, 0x6f, 0xdc, 0x2b, 0xd8, 0xb5, 0x9b, 0xb8, 
   193     0x2d, 0x57, 0x92, 0x1c, 0x46, 0x27, 0xaf, 0x6d, 
   194     0xe1, 0x45, 0xcf, 0x0b, 0x3f, 0xfa, 0x07, 0xcc, 
   195     0x14, 0x8e, 0xe7, 0xb8, 0xaa, 0xd5, 0xd1, 0x36, 
   196     0x1d, 0x7e, 0x5e, 0x7d, 0xfa, 0x5b, 0x77, 0x1f };
   198 static const unsigned char h[] = { 
   199     0x41, 0x87, 0x47, 0x79, 0xd8, 0xba, 0x4e, 0xac, 
   200     0x44, 0x4f, 0x6b, 0xd2, 0x16, 0x5e, 0x04, 0xc6, 
   201     0xc2, 0x29, 0x93, 0x5e, 0xbd, 0xc7, 0xa9, 0x8f, 
   202     0x23, 0xa1, 0xc8, 0xee, 0x80, 0x64, 0xd5, 0x67, 
   203     0x3c, 0xba, 0x59, 0x9a, 0x06, 0x0c, 0xcc, 0x29, 
   204     0x56, 0xc0, 0xb2, 0x21, 0xe0, 0x5b, 0x52, 0xcd, 
   205     0x84, 0x73, 0x57, 0xfd, 0xd8, 0xc3, 0x5b, 0x13, 
   206     0x54, 0xd7, 0x4a, 0x06, 0x86, 0x63, 0x09, 0xa5, 
   207     0xb0, 0x59, 0xe2, 0x32, 0x9e, 0x09, 0xa3, 0x9f, 
   208     0x49, 0x62, 0xcc, 0xa6, 0xf9, 0x54, 0xd5, 0xb2, 
   209     0xc3, 0x08, 0x71, 0x7e, 0xe3, 0x37, 0x50, 0xd6, 
   210     0x7b, 0xa7, 0xc2, 0x60, 0xc1, 0xeb, 0x51, 0x32, 
   211     0xfa, 0xad, 0x35, 0x25, 0x17, 0xf0, 0x7f, 0x23, 
   212     0xe5, 0xa8, 0x01, 0x52, 0xcf, 0x2f, 0xd9, 0xa9, 
   213     0xf6, 0x00, 0x21, 0x15, 0xf1, 0xf7, 0x70, 0xb7, 
   214     0x57, 0x8a, 0xd0, 0x59, 0x6a, 0x82, 0xdc, 0x9c };
   216 static const unsigned char seed[] = { 0x00,
   217     0xcc, 0x4c, 0x69, 0x74, 0xf6, 0x72, 0x24, 0x68, 
   218     0x24, 0x4f, 0xd7, 0x50, 0x11, 0x40, 0x81, 0xed, 
   219     0x19, 0x3c, 0x8a, 0x25, 0xbc, 0x78, 0x0a, 0x85, 
   220     0x82, 0x53, 0x70, 0x20, 0xf6, 0x54, 0xa5, 0x1b, 
   221     0xf4, 0x15, 0xcd, 0xff, 0xc4, 0x88, 0xa7, 0x9d, 
   222     0xf3, 0x47, 0x1c, 0x0a, 0xbe, 0x10, 0x29, 0x83, 
   223     0xb9, 0x0f, 0x4c, 0xdf, 0x90, 0x16, 0x83, 0xa2, 
   224     0xb3, 0xe3, 0x2e, 0xc1, 0xc2, 0x24, 0x6a, 0xc4, 
   225     0x9d, 0x57, 0xba, 0xcb, 0x0f, 0x18, 0x75, 0x00, 
   226     0x33, 0x46, 0x82, 0xec, 0xd6, 0x94, 0x77, 0xc3, 
   227     0x4f, 0x4c, 0x58, 0x1c, 0x7f, 0x61, 0x3c, 0x36, 
   228     0xd5, 0x2f, 0xa5, 0x66, 0xd8, 0x2f, 0xce, 0x6e, 
   229     0x8e, 0x20, 0x48, 0x4a, 0xbb, 0xe3, 0xe0, 0xb2, 
   230     0x50, 0x33, 0x63, 0x8a, 0x5b, 0x2d, 0x6a, 0xbe, 
   231     0x4c, 0x28, 0x81, 0x53, 0x5b, 0xe4, 0xf6, 0xfc, 
   232     0x64, 0x06, 0x13, 0x51, 0xeb, 0x4a, 0x91, 0x9c };
   234 static const unsigned int counter=1496;
   236 static const unsigned char prime2[] = { 0x00,
   237     0xa4, 0xc2, 0x83, 0x4f, 0x36, 0xd3, 0x4f, 0xae,
   238     0xa0, 0xb1, 0x47, 0x43, 0xa8, 0x15, 0xee, 0xad,
   239     0xa3, 0x98, 0xa3, 0x29, 0x45, 0xae, 0x5c, 0xd9,
   240     0x12, 0x99, 0x09, 0xdc, 0xef, 0x05, 0xb4, 0x98,
   241     0x05, 0xaa, 0x07, 0xaa, 0x83, 0x89, 0xd7, 0xba,
   242     0xd1, 0x25, 0x56, 0x58, 0xd1, 0x73, 0x3c, 0xd0,
   243     0x91, 0x65, 0xbe, 0x27, 0x92, 0x94, 0x86, 0x95,
   244     0xdb, 0xcf, 0x07, 0x13, 0xa0, 0x85, 0xd6, 0xaa,
   245     0x6c, 0x1d, 0x63, 0xbf, 0xdd, 0xdf, 0xbc, 0x30,
   246     0xeb, 0x42, 0x2f, 0x52, 0x11, 0xec, 0x6e, 0x65,
   247     0xdf, 0x50, 0xbe, 0x28, 0x3d, 0xa4, 0xec, 0x45,
   248     0x19, 0x4c, 0x13, 0x0f, 0x59, 0x74, 0x57, 0x69,
   249     0x99, 0x4f, 0x4a, 0x74, 0x7f, 0x8c, 0x9e, 0xa2,
   250     0xe7, 0x94, 0xc9, 0x70, 0x70, 0xd0, 0xc4, 0xda,
   251     0x49, 0x5b, 0x7a, 0x7d, 0xd9, 0x71, 0x7c, 0x3b,
   252     0xdc, 0xd2, 0x8a, 0x74, 0x5f, 0xce, 0x09, 0xa2,
   253     0xdb, 0xec, 0xa4, 0xba, 0x75, 0xaa, 0x0a, 0x97,
   254     0xa6, 0x82, 0x25, 0x90, 0x90, 0x37, 0xe4, 0x40,
   255     0x05, 0x28, 0x8f, 0x98, 0x8e, 0x68, 0x01, 0xaf,
   256     0x9b, 0x08, 0x2a, 0x9b, 0xd5, 0xb9, 0x8c, 0x14,
   257     0xbf, 0xba, 0xcb, 0x5b, 0xda, 0x4c, 0x95, 0xb8,
   258     0xdf, 0x67, 0xa6, 0x6b, 0x76, 0x8c, 0xad, 0x4f,
   259     0xfd, 0x6a, 0xd6, 0xcc, 0x62, 0x71, 0x30, 0x30,
   260     0xc1, 0x29, 0x84, 0xe4, 0x8e, 0x32, 0x51, 0xb6,
   261     0xea, 0xfa, 0xba, 0x00, 0x99, 0x76, 0xea, 0x86,
   262     0x90, 0xab, 0x2d, 0xe9, 0xfd, 0x1e, 0x8c, 0xcc,
   263     0x3c, 0x2b, 0x5d, 0x13, 0x1b, 0x47, 0xb4, 0xf5,
   264     0x09, 0x74, 0x1d, 0xd4, 0x78, 0xb2, 0x42, 0x19,
   265     0xd6, 0x24, 0xd1, 0x68, 0xbf, 0x11, 0xf1, 0x38,
   266     0xa0, 0x44, 0x9c, 0xc6, 0x51, 0x33, 0xaa, 0x42,
   267     0x93, 0x9e, 0x30, 0x58, 0x9e, 0xc0, 0x70, 0xdf,
   268     0x7e, 0x64, 0xb1, 0xd8, 0x68, 0x75, 0x98, 0xa7 };
   270 static const unsigned char subprime2[] = { 0x00,
   271     0x8e, 0xab, 0xf4, 0xbe, 0x45, 0xeb, 0xa3, 0x58,
   272     0x4e, 0x60, 0x15, 0x66, 0x5a, 0x4b, 0x25, 0xcf,
   273     0x45, 0x77, 0x89, 0x3f, 0x73, 0x34, 0x4a, 0xe0,
   274     0x9e, 0xac, 0xfd, 0xdc, 0xff, 0x9c, 0x8d, 0xe7 };
   276 static const unsigned char base2[] = { 0x00,
   277     0x8d, 0x72, 0x32, 0x46, 0xa6, 0x5c, 0x80, 0xe3,
   278     0x43, 0x0a, 0x9e, 0x94, 0x35, 0x86, 0xd4, 0x58,
   279     0xa1, 0xca, 0x22, 0xb9, 0x73, 0x46, 0x0b, 0xfb,
   280     0x3e, 0x33, 0xf1, 0xd5, 0xd3, 0xb4, 0x26, 0xbf,
   281     0x50, 0xd7, 0xf2, 0x09, 0x33, 0x6e, 0xc0, 0x31,
   282     0x1b, 0x6d, 0x07, 0x70, 0x86, 0xca, 0x57, 0xf7,
   283     0x0b, 0x4a, 0x63, 0xf0, 0x6f, 0xc8, 0x8a, 0xed,
   284     0x50, 0x60, 0xf3, 0x11, 0xc7, 0x44, 0xf3, 0xce,
   285     0x4e, 0x50, 0x42, 0x2d, 0x85, 0x33, 0x54, 0x57,
   286     0x03, 0x8d, 0xdc, 0x66, 0x4d, 0x61, 0x83, 0x17,
   287     0x1c, 0x7b, 0x0d, 0x65, 0xbc, 0x8f, 0x2c, 0x19,
   288     0x86, 0xfc, 0xe2, 0x9f, 0x5d, 0x67, 0xfc, 0xd4,
   289     0xa5, 0xf8, 0x23, 0xa1, 0x1a, 0xa2, 0xe1, 0x11,
   290     0x15, 0x84, 0x32, 0x01, 0xee, 0x88, 0xf1, 0x55,
   291     0x30, 0xe9, 0x74, 0x3c, 0x1a, 0x2b, 0x54, 0x45,
   292     0x2e, 0x39, 0xb9, 0x77, 0xe1, 0x32, 0xaf, 0x2d,
   293     0x97, 0xe0, 0x21, 0xec, 0xf5, 0x58, 0xe1, 0xc7,
   294     0x2e, 0xe0, 0x71, 0x3d, 0x29, 0xa4, 0xd6, 0xe2,
   295     0x5f, 0x85, 0x9c, 0x05, 0x04, 0x46, 0x41, 0x89,
   296     0x03, 0x3c, 0xfa, 0xb2, 0xcf, 0xfa, 0xd5, 0x67,
   297     0xcc, 0xec, 0x68, 0xfc, 0x83, 0xd9, 0x1f, 0x2e,
   298     0x4e, 0x9a, 0x5e, 0x77, 0xa1, 0xff, 0xe6, 0x6f,
   299     0x04, 0x8b, 0xf9, 0x6b, 0x47, 0xc6, 0x49, 0xd2,
   300     0x88, 0x6e, 0x29, 0xa3, 0x1b, 0xae, 0xe0, 0x4f,
   301     0x72, 0x8a, 0x28, 0x94, 0x0c, 0x1d, 0x8c, 0x99,
   302     0xa2, 0x6f, 0xf8, 0xba, 0x99, 0x90, 0xc7, 0xe5,
   303     0xb1, 0x3c, 0x10, 0x34, 0x86, 0x6a, 0x6a, 0x1f,
   304     0x39, 0x63, 0x58, 0xe1, 0x5e, 0x97, 0x95, 0x45,
   305     0x40, 0x38, 0x45, 0x6f, 0x02, 0xb5, 0x86, 0x6e,
   306     0xae, 0x2f, 0x32, 0x7e, 0xa1, 0x3a, 0x34, 0x2c,
   307     0x1c, 0xd3, 0xff, 0x4e, 0x2c, 0x38, 0x1c, 0xaa,
   308     0x2e, 0x66, 0xbe, 0x32, 0x3e, 0x3c, 0x06, 0x5f };
   310 static const unsigned char h2[] = { 
   311     0x30, 0x91, 0xa1, 0x2e, 0x40, 0xa5, 0x7d, 0xf7,
   312     0xdc, 0xed, 0xee, 0x05, 0xc2, 0x31, 0x91, 0x37,
   313     0xda, 0xc5, 0xe3, 0x47, 0xb5, 0x35, 0x4b, 0xfd,
   314     0x18, 0xb2, 0x7e, 0x67, 0x1e, 0x92, 0x22, 0xe7,
   315     0xf5, 0x00, 0x71, 0xc0, 0x86, 0x8d, 0x90, 0x31,
   316     0x36, 0x3e, 0xd0, 0x94, 0x5d, 0x2f, 0x9a, 0x68,
   317     0xd2, 0xf8, 0x3d, 0x5e, 0x84, 0x42, 0x35, 0xda,
   318     0x75, 0xdd, 0x05, 0xf0, 0x03, 0x31, 0x39, 0xe5,
   319     0xfd, 0x2f, 0x5a, 0x7d, 0x56, 0xd8, 0x26, 0xa0,
   320     0x51, 0x5e, 0x32, 0xb4, 0xad, 0xee, 0xd4, 0x89,
   321     0xae, 0x01, 0x7f, 0xac, 0x86, 0x98, 0x77, 0x26,
   322     0x5c, 0x31, 0xd2, 0x5e, 0xbb, 0x7f, 0xf5, 0x4c,
   323     0x9b, 0xf0, 0xa6, 0x37, 0x34, 0x08, 0x86, 0x6b,
   324     0xce, 0xeb, 0x85, 0x66, 0x0a, 0x26, 0x8a, 0x14,
   325     0x92, 0x12, 0x74, 0xf4, 0xf0, 0xcb, 0xb5, 0xfc,
   326     0x38, 0xd5, 0x1e, 0xa1, 0x2f, 0x4a, 0x1a, 0xca,
   327     0x66, 0xde, 0x6e, 0xe6, 0x6e, 0x1c, 0xef, 0x50,
   328     0x41, 0x31, 0x09, 0xe7, 0x4a, 0xb8, 0xa3, 0xaa,
   329     0x5a, 0x22, 0xbd, 0x63, 0x0f, 0xe9, 0x0e, 0xdb,
   330     0xb3, 0xca, 0x7e, 0x8d, 0x40, 0xb3, 0x3e, 0x0b,
   331     0x12, 0x8b, 0xb0, 0x80, 0x4d, 0x6d, 0xb0, 0x54,
   332     0xbb, 0x4c, 0x1d, 0x6c, 0xa0, 0x5c, 0x9d, 0x91,
   333     0xb3, 0xbb, 0xd9, 0xfc, 0x60, 0xec, 0xc1, 0xbc,
   334     0xae, 0x72, 0x3f, 0xa5, 0x4f, 0x36, 0x2d, 0x2c,
   335     0x81, 0x03, 0x86, 0xa2, 0x03, 0x38, 0x36, 0x8e,
   336     0xad, 0x1d, 0x53, 0xc6, 0xc5, 0x9e, 0xda, 0x08,
   337     0x35, 0x4f, 0xb2, 0x78, 0xba, 0xd1, 0x22, 0xde,
   338     0xc4, 0x6b, 0xbe, 0x83, 0x71, 0x0f, 0xee, 0x38,
   339     0x4a, 0x9f, 0xda, 0x90, 0x93, 0x6b, 0x9a, 0xf2,
   340     0xeb, 0x23, 0xfe, 0x41, 0x3f, 0xf1, 0xfc, 0xee,
   341     0x7f, 0x67, 0xa7, 0xb8, 0xab, 0x29, 0xf4, 0x75,
   342     0x1c, 0xe9, 0xd1, 0x47, 0x7d, 0x86, 0x44, 0xe2 };
   344 static const unsigned char seed2[] = { 0x00,
   345     0xbc, 0xae, 0xc4, 0xea, 0x4e, 0xd2, 0xed, 0x1c,
   346     0x8d, 0x48, 0xed, 0xf2, 0xa5, 0xb4, 0x18, 0xba,
   347     0x00, 0xcb, 0x9c, 0x75, 0x8a, 0x39, 0x94, 0x3b,
   348     0xd0, 0xd6, 0x01, 0xf7, 0xc1, 0xf5, 0x9d, 0xe5,
   349     0xe3, 0xb4, 0x1d, 0xf5, 0x30, 0xfe, 0x99, 0xe4,
   350     0x01, 0xab, 0xc0, 0x88, 0x4e, 0x67, 0x8f, 0xc6,
   351     0x72, 0x39, 0x2e, 0xac, 0x51, 0xec, 0x91, 0x41,
   352     0x47, 0x71, 0x14, 0x8a, 0x1d, 0xca, 0x88, 0x15,
   353     0xea, 0xc9, 0x48, 0x9a, 0x71, 0x50, 0x19, 0x38,
   354     0xdb, 0x4e, 0x65, 0xd5, 0x13, 0xd8, 0x2a, 0xc4,
   355     0xcd, 0xfd, 0x0c, 0xe3, 0xc3, 0x60, 0xae, 0x6d,
   356     0x88, 0xf2, 0x3a, 0xd0, 0x64, 0x73, 0x32, 0x89,
   357     0xcd, 0x0b, 0xb8, 0xc7, 0xa5, 0x27, 0x84, 0xd5,
   358     0x83, 0x3f, 0x0e, 0x10, 0x63, 0x10, 0x78, 0xac,
   359     0x6b, 0x56, 0xb2, 0x62, 0x3a, 0x44, 0x56, 0xc0,
   360     0xe4, 0x33, 0xd7, 0x63, 0x4c, 0xc9, 0x6b, 0xae,
   361     0xfb, 0xe2, 0x9b, 0xf4, 0x96, 0xc7, 0xf0, 0x2a,
   362     0x50, 0xde, 0x86, 0x69, 0x4f, 0x42, 0x4b, 0x1c,
   363     0x7c, 0xa8, 0x6a, 0xfb, 0x54, 0x47, 0x1b, 0x41,
   364     0x31, 0x9e, 0x0a, 0xc6, 0xc0, 0xbc, 0x88, 0x7f,
   365     0x5a, 0x42, 0xa9, 0x82, 0x58, 0x32, 0xb3, 0xeb,
   366     0x54, 0x83, 0x84, 0x26, 0x92, 0xa6, 0xc0, 0x6e,
   367     0x2b, 0xa6, 0x82, 0x82, 0x43, 0x58, 0x84, 0x53,
   368     0x31, 0xcf, 0xd0, 0x0a, 0x11, 0x09, 0x44, 0xc8,
   369     0x11, 0x36, 0xe0, 0x04, 0x85, 0x2e, 0xd1, 0x29,
   370     0x6b, 0x7b, 0x00, 0x71, 0x5f, 0xef, 0x7b, 0x7a,
   371     0x2d, 0x91, 0xf9, 0x84, 0x45, 0x4d, 0xc7, 0xe1,
   372     0xee, 0xd4, 0xb8, 0x61, 0x3b, 0x13, 0xb7, 0xba,
   373     0x95, 0x39, 0xf6, 0x3d, 0x89, 0xbd, 0xa5, 0x80,
   374     0x93, 0xf7, 0xe5, 0x17, 0x05, 0xc5, 0x65, 0xb7,
   375     0xde, 0xc9, 0x9f, 0x04, 0x87, 0xcf, 0x4f, 0x86,
   376     0xc3, 0x29, 0x7d, 0xb7, 0x89, 0xbf, 0xe3, 0xde };
   378 static const unsigned int counter2=210;
   380 struct tuple_str {
   381     CK_RV         errNum;
   382     const char * errString;
   383 };
   385 typedef struct tuple_str tuple_str;
   387 static const tuple_str errStrings[] = {
   388 {CKR_OK                              , "CKR_OK                              "},
   389 {CKR_CANCEL                          , "CKR_CANCEL                          "},
   390 {CKR_HOST_MEMORY                     , "CKR_HOST_MEMORY                     "},
   391 {CKR_SLOT_ID_INVALID                 , "CKR_SLOT_ID_INVALID                 "},
   392 {CKR_GENERAL_ERROR                   , "CKR_GENERAL_ERROR                   "},
   393 {CKR_FUNCTION_FAILED                 , "CKR_FUNCTION_FAILED                 "},
   394 {CKR_ARGUMENTS_BAD                   , "CKR_ARGUMENTS_BAD                   "},
   395 {CKR_NO_EVENT                        , "CKR_NO_EVENT                        "},
   396 {CKR_NEED_TO_CREATE_THREADS          , "CKR_NEED_TO_CREATE_THREADS          "},
   397 {CKR_CANT_LOCK                       , "CKR_CANT_LOCK                       "},
   398 {CKR_ATTRIBUTE_READ_ONLY             , "CKR_ATTRIBUTE_READ_ONLY             "},
   399 {CKR_ATTRIBUTE_SENSITIVE             , "CKR_ATTRIBUTE_SENSITIVE             "},
   400 {CKR_ATTRIBUTE_TYPE_INVALID          , "CKR_ATTRIBUTE_TYPE_INVALID          "},
   401 {CKR_ATTRIBUTE_VALUE_INVALID         , "CKR_ATTRIBUTE_VALUE_INVALID         "},
   402 {CKR_DATA_INVALID                    , "CKR_DATA_INVALID                    "},
   403 {CKR_DATA_LEN_RANGE                  , "CKR_DATA_LEN_RANGE                  "},
   404 {CKR_DEVICE_ERROR                    , "CKR_DEVICE_ERROR                    "},
   405 {CKR_DEVICE_MEMORY                   , "CKR_DEVICE_MEMORY                   "},
   406 {CKR_DEVICE_REMOVED                  , "CKR_DEVICE_REMOVED                  "},
   407 {CKR_ENCRYPTED_DATA_INVALID          , "CKR_ENCRYPTED_DATA_INVALID          "},
   408 {CKR_ENCRYPTED_DATA_LEN_RANGE        , "CKR_ENCRYPTED_DATA_LEN_RANGE        "},
   409 {CKR_FUNCTION_CANCELED               , "CKR_FUNCTION_CANCELED               "},
   410 {CKR_FUNCTION_NOT_PARALLEL           , "CKR_FUNCTION_NOT_PARALLEL           "},
   411 {CKR_FUNCTION_NOT_SUPPORTED          , "CKR_FUNCTION_NOT_SUPPORTED          "},
   412 {CKR_KEY_HANDLE_INVALID              , "CKR_KEY_HANDLE_INVALID              "},
   413 {CKR_KEY_SIZE_RANGE                  , "CKR_KEY_SIZE_RANGE                  "},
   414 {CKR_KEY_TYPE_INCONSISTENT           , "CKR_KEY_TYPE_INCONSISTENT           "},
   415 {CKR_KEY_NOT_NEEDED                  , "CKR_KEY_NOT_NEEDED                  "},
   416 {CKR_KEY_CHANGED                     , "CKR_KEY_CHANGED                     "},
   417 {CKR_KEY_NEEDED                      , "CKR_KEY_NEEDED                      "},
   418 {CKR_KEY_INDIGESTIBLE                , "CKR_KEY_INDIGESTIBLE                "},
   419 {CKR_KEY_FUNCTION_NOT_PERMITTED      , "CKR_KEY_FUNCTION_NOT_PERMITTED      "},
   420 {CKR_KEY_NOT_WRAPPABLE               , "CKR_KEY_NOT_WRAPPABLE               "},
   421 {CKR_KEY_UNEXTRACTABLE               , "CKR_KEY_UNEXTRACTABLE               "},
   422 {CKR_MECHANISM_INVALID               , "CKR_MECHANISM_INVALID               "},
   423 {CKR_MECHANISM_PARAM_INVALID         , "CKR_MECHANISM_PARAM_INVALID         "},
   424 {CKR_OBJECT_HANDLE_INVALID           , "CKR_OBJECT_HANDLE_INVALID           "},
   425 {CKR_OPERATION_ACTIVE                , "CKR_OPERATION_ACTIVE                "},
   426 {CKR_OPERATION_NOT_INITIALIZED       , "CKR_OPERATION_NOT_INITIALIZED       "},
   427 {CKR_PIN_INCORRECT                   , "CKR_PIN_INCORRECT                   "},
   428 {CKR_PIN_INVALID                     , "CKR_PIN_INVALID                     "},
   429 {CKR_PIN_LEN_RANGE                   , "CKR_PIN_LEN_RANGE                   "},
   430 {CKR_PIN_EXPIRED                     , "CKR_PIN_EXPIRED                     "},
   431 {CKR_PIN_LOCKED                      , "CKR_PIN_LOCKED                      "},
   432 {CKR_SESSION_CLOSED                  , "CKR_SESSION_CLOSED                  "},
   433 {CKR_SESSION_COUNT                   , "CKR_SESSION_COUNT                   "},
   434 {CKR_SESSION_HANDLE_INVALID          , "CKR_SESSION_HANDLE_INVALID          "},
   435 {CKR_SESSION_PARALLEL_NOT_SUPPORTED  , "CKR_SESSION_PARALLEL_NOT_SUPPORTED  "},
   436 {CKR_SESSION_READ_ONLY               , "CKR_SESSION_READ_ONLY               "},
   437 {CKR_SESSION_EXISTS                  , "CKR_SESSION_EXISTS                  "},
   438 {CKR_SESSION_READ_ONLY_EXISTS        , "CKR_SESSION_READ_ONLY_EXISTS        "},
   439 {CKR_SESSION_READ_WRITE_SO_EXISTS    , "CKR_SESSION_READ_WRITE_SO_EXISTS    "},
   440 {CKR_SIGNATURE_INVALID               , "CKR_SIGNATURE_INVALID               "},
   441 {CKR_SIGNATURE_LEN_RANGE             , "CKR_SIGNATURE_LEN_RANGE             "},
   442 {CKR_TEMPLATE_INCOMPLETE             , "CKR_TEMPLATE_INCOMPLETE             "},
   443 {CKR_TEMPLATE_INCONSISTENT           , "CKR_TEMPLATE_INCONSISTENT           "},
   444 {CKR_TOKEN_NOT_PRESENT               , "CKR_TOKEN_NOT_PRESENT               "},
   445 {CKR_TOKEN_NOT_RECOGNIZED            , "CKR_TOKEN_NOT_RECOGNIZED            "},
   446 {CKR_TOKEN_WRITE_PROTECTED           , "CKR_TOKEN_WRITE_PROTECTED           "},
   447 {CKR_UNWRAPPING_KEY_HANDLE_INVALID   , "CKR_UNWRAPPING_KEY_HANDLE_INVALID   "},
   448 {CKR_UNWRAPPING_KEY_SIZE_RANGE       , "CKR_UNWRAPPING_KEY_SIZE_RANGE       "},
   449 {CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"},
   450 {CKR_USER_ALREADY_LOGGED_IN          , "CKR_USER_ALREADY_LOGGED_IN          "},
   451 {CKR_USER_NOT_LOGGED_IN              , "CKR_USER_NOT_LOGGED_IN              "},
   452 {CKR_USER_PIN_NOT_INITIALIZED        , "CKR_USER_PIN_NOT_INITIALIZED        "},
   453 {CKR_USER_TYPE_INVALID               , "CKR_USER_TYPE_INVALID               "},
   454 {CKR_USER_ANOTHER_ALREADY_LOGGED_IN  , "CKR_USER_ANOTHER_ALREADY_LOGGED_IN  "},
   455 {CKR_USER_TOO_MANY_TYPES             , "CKR_USER_TOO_MANY_TYPES             "},
   456 {CKR_WRAPPED_KEY_INVALID             , "CKR_WRAPPED_KEY_INVALID             "},
   457 {CKR_WRAPPED_KEY_LEN_RANGE           , "CKR_WRAPPED_KEY_LEN_RANGE           "},
   458 {CKR_WRAPPING_KEY_HANDLE_INVALID     , "CKR_WRAPPING_KEY_HANDLE_INVALID     "},
   459 {CKR_WRAPPING_KEY_SIZE_RANGE         , "CKR_WRAPPING_KEY_SIZE_RANGE         "},
   460 {CKR_WRAPPING_KEY_TYPE_INCONSISTENT  , "CKR_WRAPPING_KEY_TYPE_INCONSISTENT  "},
   461 {CKR_RANDOM_SEED_NOT_SUPPORTED       , "CKR_RANDOM_SEED_NOT_SUPPORTED       "},
   462 {CKR_RANDOM_NO_RNG                   , "CKR_RANDOM_NO_RNG                   "},
   463 {CKR_DOMAIN_PARAMS_INVALID           , "CKR_DOMAIN_PARAMS_INVALID           "},
   464 {CKR_BUFFER_TOO_SMALL                , "CKR_BUFFER_TOO_SMALL                "},
   465 {CKR_SAVED_STATE_INVALID             , "CKR_SAVED_STATE_INVALID             "},
   466 {CKR_INFORMATION_SENSITIVE           , "CKR_INFORMATION_SENSITIVE           "},
   467 {CKR_STATE_UNSAVEABLE                , "CKR_STATE_UNSAVEABLE                "},
   468 {CKR_CRYPTOKI_NOT_INITIALIZED        , "CKR_CRYPTOKI_NOT_INITIALIZED        "},
   469 {CKR_CRYPTOKI_ALREADY_INITIALIZED    , "CKR_CRYPTOKI_ALREADY_INITIALIZED    "},
   470 {CKR_MUTEX_BAD                       , "CKR_MUTEX_BAD                       "},
   471 {CKR_MUTEX_NOT_LOCKED                , "CKR_MUTEX_NOT_LOCKED                "},
   472 {CKR_FUNCTION_REJECTED               , "CKR_FUNCTION_REJECTED               "},
   473 {CKR_VENDOR_DEFINED                  , "CKR_VENDOR_DEFINED                  "},
   474 {0xCE534351                          , "CKR_NETSCAPE_CERTDB_FAILED          "},
   475 {0xCE534352                          , "CKR_NETSCAPE_KEYDB_FAILED           "}
   477 };
   479 static const CK_ULONG numStrings = sizeof(errStrings) / sizeof(tuple_str);
   481 /* Returns constant error string for "CRV".
   482  * Returns "unknown error" if errNum is unknown.
   483  */
   484 static const char *
   485 CK_RVtoStr(CK_RV errNum) {
   486     CK_ULONG low  = 1;
   487     CK_ULONG high = numStrings - 1;
   488     CK_ULONG i;
   489     CK_RV num;
   490     static int initDone;
   492     /* make sure table is in  ascending order.
   493      * binary search depends on it.
   494      */
   495     if (!initDone) {
   496         CK_RV lastNum = CKR_OK;
   497         for (i = low; i <= high; ++i) {
   498             num = errStrings[i].errNum;
   499             if (num <= lastNum) {
   500                 PR_fprintf(PR_STDERR,
   501                         "sequence error in error strings at item %d\n"
   502                         "error %d (%s)\n"
   503                         "should come after \n"
   504                         "error %d (%s)\n",
   505                         (int) i, (int) lastNum, errStrings[i-1].errString,
   506                         (int) num, errStrings[i].errString);
   507             }
   508             lastNum = num;
   509         }
   510         initDone = 1;
   511     }
   513     /* Do binary search of table. */
   514     while (low + 1 < high) {
   515         i = (low + high) / 2;
   516         num = errStrings[i].errNum;
   517         if (errNum == num)
   518             return errStrings[i].errString;
   519         if (errNum < num)
   520             high = i;
   521         else
   522             low = i;
   523     }
   524     if (errNum == errStrings[low].errNum)
   525         return errStrings[low].errString;
   526     if (errNum == errStrings[high].errNum)
   527         return errStrings[high].errString;
   528     return "unknown error";
   529 }
   531 static void 
   532 pk11error(const char *string, CK_RV crv) {
   533     PRErrorCode errorcode;
   535     PR_fprintf(PR_STDERR, "%s: 0x%08lX, %-26s\n", string, crv, CK_RVtoStr(crv));
   537     errorcode = PR_GetError();
   538     if (errorcode) {
   539         PR_fprintf(PR_STDERR, "NSPR error code: %d: %s\n", errorcode,
   540                 PR_ErrorToString(errorcode, PR_LANGUAGE_I_DEFAULT));
   541     }
   542 }
   544 static void 
   545 logIt(const char *fmt, ...) {
   546     va_list args;
   548     if (verbose) {
   549         va_start (args, fmt);
   550         vprintf(fmt, args);
   551         va_end(args);
   552     }
   553 }
   555 static CK_RV 
   556 softokn_Init(CK_FUNCTION_LIST_PTR pFunctionList, const char * configDir,
   557             const char * dbPrefix) {
   559     CK_RV crv = CKR_OK;
   560     CK_C_INITIALIZE_ARGS initArgs;
   561     char *moduleSpec = NULL;
   563     initArgs.CreateMutex = NULL;
   564     initArgs.DestroyMutex = NULL;
   565     initArgs.LockMutex = NULL;
   566     initArgs.UnlockMutex = NULL;
   567     initArgs.flags = CKF_OS_LOCKING_OK;
   568     if (configDir) {
   569         moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
   570                              "keyPrefix='%s' secmod='secmod.db' flags=ReadOnly ",
   571                              configDir, dbPrefix, dbPrefix);
   572     } else {
   573         moduleSpec = PR_smprintf("configdir='' certPrefix='' keyPrefix='' "
   574                                  "secmod='' flags=noCertDB, noModDB");
   575     }
   576     if (!moduleSpec) {
   577         PR_fprintf(PR_STDERR, "softokn_Init: out of memory error\n");
   578         return CKR_HOST_MEMORY;
   579     } 
   580     logIt("moduleSpec %s\n", moduleSpec);
   581     initArgs.LibraryParameters = (CK_CHAR_PTR *) moduleSpec;
   582     initArgs.pReserved = NULL;
   584     crv = pFunctionList->C_Initialize(&initArgs);
   585     if (crv != CKR_OK) {
   586         pk11error("C_Initialize failed", crv);
   587         goto cleanup;
   588     }
   590 cleanup:
   591     if (moduleSpec) {
   592         PR_smprintf_free(moduleSpec);
   593     }
   595     return crv;
   596 }
   598 static char * 
   599 filePasswd(char *pwFile)
   600 {
   601     unsigned char phrase[200];
   602     PRFileDesc *fd;
   603     PRInt32 nb;
   604     int i;
   606     if (!pwFile)
   607         return 0;
   609     fd = PR_Open(pwFile, PR_RDONLY, 0);
   610     if (!fd) {
   611         lperror(pwFile);
   612         return NULL;
   613     }
   615     nb = PR_Read(fd, phrase, sizeof(phrase));
   617     PR_Close(fd);
   618     /* handle the Windows EOL case */
   619     i = 0;
   620     while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb) i++;
   621     phrase[i] = '\0';
   622     if (nb == 0) {
   623         PR_fprintf(PR_STDERR,"password file contains no data\n");
   624         return NULL;
   625     }
   626     return (char*) PL_strdup((char*)phrase);
   627 }
   629 static void 
   630 checkPath(char *string)
   631 {
   632     char *src;
   633     char *dest;
   635     /*
   636      * windows support convert any back slashes to
   637      * forward slashes.
   638      */
   639     for (src=string, dest=string; *src; src++,dest++) {
   640         if (*src == '\\') {
   641             *dest = '/';
   642         }
   643     }
   644     dest--;
   645     /* if the last char is a / set it to 0 */
   646     if (*dest == '/')
   647         *dest = 0;
   649 }
   651 static CK_SLOT_ID *
   652 getSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
   653             CK_ULONG slotIndex) {
   654     CK_RV crv = CKR_OK;
   655     CK_SLOT_ID *pSlotList = NULL;
   656     CK_ULONG slotCount;
   658     /* Get slot list */
   659     crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
   660                                        NULL, &slotCount);
   661     if (crv != CKR_OK) {
   662         pk11error( "C_GetSlotList failed", crv);
   663         return NULL;
   664     }
   666     if (slotIndex >= slotCount) {
   667         PR_fprintf(PR_STDERR, "provided slotIndex is greater than the slot count.");
   668         return NULL;
   669     }
   671     pSlotList = (CK_SLOT_ID *)PR_Malloc(slotCount * sizeof(CK_SLOT_ID));
   672     if (!pSlotList) {
   673         lperror("failed to allocate slot list");
   674         return NULL;
   675     }
   676     crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
   677                                        pSlotList, &slotCount);
   678     if (crv != CKR_OK) {
   679         pk11error( "C_GetSlotList failed", crv);
   680         if (pSlotList) PR_Free(pSlotList);
   681         return NULL;
   682     }
   683     return pSlotList;
   684 }
   686 int main(int argc, char **argv)
   687 {
   688     PLOptState *optstate;
   689     char *program_name;
   690     char *libname = NULL;
   691     PRLibrary *lib;
   692     PRFileDesc *fd;
   693     PRStatus rv = PR_SUCCESS;
   694     const char  *input_file = NULL; /* read/create encrypted data from here */
   695     char  *output_file = NULL;	/* write new encrypted data here */
   696     int bytesRead;
   697     int bytesWritten;
   698     unsigned char file_buf[512];
   699     int count=0;
   700     int keySize = 0;
   701     int i;
   702     PRBool verify = PR_FALSE;
   703     static PRBool FIPSMODE = PR_FALSE;
   704     PRBool successful = PR_FALSE;
   706 #ifdef USES_LINKS
   707     int ret;
   708     struct stat stat_buf;
   709     char link_buf[MAXPATHLEN+1];
   710     char *link_file = NULL;
   711 #endif
   713     char *pwd = NULL;
   714     char *configDir = NULL;
   715     char *dbPrefix = NULL;
   716     char *disableUnload = NULL;
   718     CK_C_GetFunctionList pC_GetFunctionList;
   719     CK_TOKEN_INFO tokenInfo;
   720     CK_FUNCTION_LIST_PTR pFunctionList = NULL;
   721     CK_RV crv = CKR_OK;
   722     CK_SESSION_HANDLE hRwSession;
   723     CK_SLOT_ID *pSlotList = NULL;
   724     CK_ULONG slotIndex = 0; 
   725     CK_MECHANISM digestmech;
   726     CK_ULONG digestLen = 0;
   727     CK_BYTE digest[32]; /* SHA256_LENGTH */
   728     CK_BYTE sign[64];   /* DSA SIGNATURE LENGTH */
   729     CK_ULONG signLen = 0 ;
   730     CK_MECHANISM signMech = {
   731         CKM_DSA, NULL, 0
   732     };
   734     /*** DSA Key ***/
   736     CK_MECHANISM dsaKeyPairGenMech;
   737     CK_ATTRIBUTE dsaPubKeyTemplate[5];
   738     CK_ATTRIBUTE dsaPrivKeyTemplate[5];
   739     CK_OBJECT_HANDLE hDSApubKey = CK_INVALID_HANDLE;
   740     CK_OBJECT_HANDLE hDSAprivKey = CK_INVALID_HANDLE;
   742     CK_BYTE dsaPubKey[384];
   743     CK_ATTRIBUTE dsaPubKeyValue;
   746     program_name = strrchr(argv[0], '/');
   747     program_name = program_name ? (program_name + 1) : argv[0];
   748     optstate = PL_CreateOptState (argc, argv, "i:o:f:Fd:hH?k:p:P:vVs:");
   749     if (optstate == NULL) {
   750         lperror("PL_CreateOptState failed");
   751         return 1;
   752     }
   754     while (PL_GetNextOpt (optstate) == PL_OPT_OK) {
   755         switch (optstate->option) {
   757             case 'd':
   758                 if (!optstate->value) {
   759                     PL_DestroyOptState(optstate);
   760                     usage(program_name);
   761                 }
   762                 configDir = PL_strdup(optstate->value);
   763                 checkPath(configDir);
   764                 break;
   766                 case 'i':
   767                 if (!optstate->value) {
   768                     PL_DestroyOptState(optstate);
   769                     usage(program_name);
   770                 }
   771                 input_file = optstate->value;
   772                 break;
   774                 case 'o':
   775                 if (!optstate->value) {
   776                     PL_DestroyOptState(optstate);
   777                     usage(program_name);
   778                 }
   779                 output_file = PL_strdup(optstate->value);
   780                 break;
   782                 case 'k':
   783                 if (!optstate->value) {
   784                     PL_DestroyOptState(optstate);
   785                     usage(program_name);
   786                 }
   787                 keySize = atoi(optstate->value);
   788                 break;
   790                 case 'f':
   791                 if (!optstate->value) {
   792                     PL_DestroyOptState(optstate);
   793                     usage(program_name);
   794                 }
   795                 pwd = filePasswd((char *)optstate->value);
   796                 if (!pwd) usage(program_name);
   797                 break;
   799                 case 'F':
   800                 FIPSMODE = PR_TRUE;
   801                 break;
   803                 case 'p':
   804                 if (!optstate->value) {
   805                     PL_DestroyOptState(optstate);
   806                     usage(program_name);
   807                 }
   808                 pwd =  PL_strdup(optstate->value);
   809                 break;
   811                 case 'P':
   812                 if (!optstate->value) {
   813                     PL_DestroyOptState(optstate);
   814                     usage(program_name);
   815                 }
   816                 dbPrefix = PL_strdup(optstate->value);
   817                 break;
   819                 case 'v':
   820                 verbose = PR_TRUE;
   821                 break;
   823                 case 'V':
   824                 verify = PR_TRUE;
   825                 break;
   827                 case 'H':
   828                 PL_DestroyOptState(optstate);
   829                 long_usage (program_name);
   830                 return 1;
   831                 break;
   833                 case 'h':
   834                 case '?':
   835                 default:
   836                 PL_DestroyOptState(optstate);
   837                 usage(program_name);
   838                 return 1;
   839                 break;
   840         }
   841     }
   842     PL_DestroyOptState(optstate);
   844     if (!input_file) {
   845         usage(program_name);
   846         return 1;
   847     }
   849     /* Get the platform-dependent library name of the
   850      * NSS cryptographic module.
   851      */
   852     libname = PR_GetLibraryName(NULL, "softokn3");
   853     assert(libname != NULL);
   854     lib = PR_LoadLibrary(libname);
   855     assert(lib != NULL);
   856     PR_FreeLibraryName(libname);
   859     if (FIPSMODE) {
   860         /* FIPSMODE == FC_GetFunctionList */
   861         /* library path must be set to an already signed softokn3/freebl */
   862         pC_GetFunctionList = (CK_C_GetFunctionList)
   863                              PR_FindFunctionSymbol(lib, "FC_GetFunctionList");
   864     } else {
   865         /* NON FIPS mode  == C_GetFunctionList */
   866         pC_GetFunctionList = (CK_C_GetFunctionList)
   867                              PR_FindFunctionSymbol(lib, "C_GetFunctionList");
   868      }
   869     assert(pC_GetFunctionList != NULL);
   871     crv = (*pC_GetFunctionList)(&pFunctionList);
   872     assert(crv == CKR_OK);
   874     if (configDir) {
   875     if (!dbPrefix) {
   876             dbPrefix = PL_strdup("");
   877         }
   878         crv = softokn_Init(pFunctionList, configDir, dbPrefix);
   879         if (crv != CKR_OK) {
   880             logIt("Failed to use provided database directory "
   881                   "will just initialize the volatile certdb.\n");
   882             crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
   883         }
   884     } else {
   885         crv = softokn_Init(pFunctionList, NULL, NULL); /* NoDB Init */
   886     }
   888     if (crv != CKR_OK) {
   889         pk11error( "Initiailzing softoken failed", crv);
   890         goto cleanup;
   891     }
   893     pSlotList = getSlotList(pFunctionList, slotIndex);
   894     if (pSlotList == NULL) {
   895         PR_fprintf(PR_STDERR, "getSlotList failed");
   896         goto cleanup;
   897     }
   899     if ((keySize == 0) || (keySize > 1024)) {
   900 	CK_MECHANISM_INFO mechInfo;
   901 	crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotIndex],
   902 			CKM_DSA, &mechInfo);
   903 	if (crv != CKR_OK) {
   904             pk11error( "Couldn't get mechanism info for DSA", crv);
   905             goto cleanup;
   906 	}
   908 	if (keySize && (mechInfo.ulMaxKeySize < keySize)) {
   909 	    PR_fprintf(PR_STDERR, 
   910 		"token doesn't support DSA2 (Max key size=%d)\n", 
   911 		mechInfo.ulMaxKeySize);
   912 	    goto cleanup;
   913 	}
   915 	if ((keySize == 0) && mechInfo.ulMaxKeySize >=2048 ) {
   916 	    keySize = 2048;
   917 	} else {
   918 	    keySize = 1024;
   919 	}
   920     }
   922     /* DSA key init */
   923     if (keySize == 1024) {
   924 	dsaPubKeyTemplate[0].type       = CKA_PRIME;
   925 	dsaPubKeyTemplate[0].pValue     = (CK_VOID_PTR) &prime;
   926 	dsaPubKeyTemplate[0].ulValueLen = sizeof(prime);
   927 	dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
   928 	dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR) &subprime;
   929 	dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime);
   930 	dsaPubKeyTemplate[2].type = CKA_BASE;
   931 	dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR) &base;
   932 	dsaPubKeyTemplate[2].ulValueLen = sizeof(base);
   933 	digestmech.mechanism = CKM_SHA_1;
   934 	digestmech.pParameter = NULL;
   935 	digestmech.ulParameterLen = 0;
   936     } else if (keySize == 2048) {
   937 	dsaPubKeyTemplate[0].type       = CKA_PRIME;
   938 	dsaPubKeyTemplate[0].pValue     = (CK_VOID_PTR) &prime2;
   939 	dsaPubKeyTemplate[0].ulValueLen = sizeof(prime2);
   940 	dsaPubKeyTemplate[1].type = CKA_SUBPRIME;
   941 	dsaPubKeyTemplate[1].pValue = (CK_VOID_PTR) &subprime2;
   942 	dsaPubKeyTemplate[1].ulValueLen = sizeof(subprime2);
   943 	dsaPubKeyTemplate[2].type = CKA_BASE;
   944 	dsaPubKeyTemplate[2].pValue = (CK_VOID_PTR) &base2;
   945 	dsaPubKeyTemplate[2].ulValueLen = sizeof(base2);
   946 	digestmech.mechanism = CKM_SHA256;
   947 	digestmech.pParameter = NULL;
   948 	digestmech.ulParameterLen = 0;
   949     } else {
   950 	/* future - generate pqg */
   951         PR_fprintf(PR_STDERR, "Only keysizes 1024 and 2048 are supported");
   952 	goto cleanup;
   953     }
   954     dsaPubKeyTemplate[3].type = CKA_TOKEN;
   955     dsaPubKeyTemplate[3].pValue = &false; /* session object */
   956     dsaPubKeyTemplate[3].ulValueLen = sizeof(false);
   957     dsaPubKeyTemplate[4].type = CKA_VERIFY;
   958     dsaPubKeyTemplate[4].pValue = &true;
   959     dsaPubKeyTemplate[4].ulValueLen = sizeof(true);
   960     dsaKeyPairGenMech.mechanism      = CKM_DSA_KEY_PAIR_GEN;
   961     dsaKeyPairGenMech.pParameter = NULL;
   962     dsaKeyPairGenMech.ulParameterLen = 0;
   963     dsaPrivKeyTemplate[0].type       = CKA_TOKEN;
   964     dsaPrivKeyTemplate[0].pValue     = &false; /* session object */
   965     dsaPrivKeyTemplate[0].ulValueLen = sizeof(false);
   966     dsaPrivKeyTemplate[1].type       = CKA_PRIVATE;
   967     dsaPrivKeyTemplate[1].pValue     = &true;
   968     dsaPrivKeyTemplate[1].ulValueLen = sizeof(true);
   969     dsaPrivKeyTemplate[2].type       = CKA_SENSITIVE;
   970     dsaPrivKeyTemplate[2].pValue     = &true; 
   971     dsaPrivKeyTemplate[2].ulValueLen = sizeof(true);
   972     dsaPrivKeyTemplate[3].type       = CKA_SIGN,
   973     dsaPrivKeyTemplate[3].pValue     = &true;
   974     dsaPrivKeyTemplate[3].ulValueLen = sizeof(true);
   975     dsaPrivKeyTemplate[4].type       = CKA_EXTRACTABLE;
   976     dsaPrivKeyTemplate[4].pValue     = &false;
   977     dsaPrivKeyTemplate[4].ulValueLen = sizeof(false);
   979     crv = pFunctionList->C_OpenSession(pSlotList[slotIndex],
   980                                        CKF_RW_SESSION | CKF_SERIAL_SESSION,
   981                                        NULL, NULL, &hRwSession);
   982     if (crv != CKR_OK) {
   983         pk11error( "Opening a read/write session failed", crv);
   984         goto cleanup;
   985     }
   987     /* check if a password is needed */
   988     crv = pFunctionList->C_GetTokenInfo(pSlotList[slotIndex], &tokenInfo);
   989     if (crv != CKR_OK) {
   990         pk11error( "C_GetTokenInfo failed", crv);
   991         goto cleanup;
   992     }
   993     if (tokenInfo.flags & CKF_LOGIN_REQUIRED) {
   994         if (pwd) {
   995             int pwdLen = strlen((const char*)pwd); 
   996             crv = pFunctionList->C_Login(hRwSession, CKU_USER, 
   997                                 (CK_UTF8CHAR_PTR) pwd, (CK_ULONG)pwdLen);
   998             if (crv != CKR_OK) {
   999                 pk11error("C_Login failed", crv);
  1000                 goto cleanup;
  1002         } else {
  1003             PR_fprintf(PR_STDERR, "Please provide the password for the token");
  1004             goto cleanup;
  1006     } else if (pwd) {
  1007         logIt("A password was provided but the password was not used.\n");
  1010     /* Generate a DSA key pair */
  1011     logIt("Generate a DSA key pair ... \n");
  1012     crv = pFunctionList->C_GenerateKeyPair(hRwSession, &dsaKeyPairGenMech,
  1013                                            dsaPubKeyTemplate,
  1014                                            NUM_ELEM(dsaPubKeyTemplate),
  1015                                            dsaPrivKeyTemplate,
  1016                                            NUM_ELEM(dsaPrivKeyTemplate),
  1017                                            &hDSApubKey, &hDSAprivKey);
  1018     if (crv != CKR_OK) {
  1019         pk11error("DSA key pair generation failed", crv);
  1020         goto cleanup;
  1023     /* open the shared library */
  1024     fd = PR_OpenFile(input_file,PR_RDONLY,0);
  1025     if (fd == NULL ) {
  1026         lperror(input_file);
  1027         goto cleanup;
  1029 #ifdef USES_LINKS
  1030     ret = lstat(input_file, &stat_buf);
  1031     if (ret < 0) {
  1032         perror(input_file);
  1033         goto cleanup;
  1035     if (S_ISLNK(stat_buf.st_mode)) {
  1036         char *dirpath,*dirend;
  1037         ret = readlink(input_file, link_buf, sizeof(link_buf) - 1);
  1038         if (ret < 0) {
  1039             perror(input_file);
  1040             goto cleanup;
  1042         link_buf[ret] = 0;
  1043         link_file = mkoutput(input_file);
  1044         /* get the dirname of input_file */
  1045         dirpath = PL_strdup(input_file);
  1046         dirend = strrchr(dirpath, '/');
  1047         if (dirend) {
  1048             *dirend = '\0';
  1049             ret = chdir(dirpath);
  1050             if (ret < 0) {
  1051                 perror(dirpath);
  1052                 goto cleanup;
  1055         PL_strfree(dirpath);
  1056         input_file = link_buf;
  1057         /* get the basename of link_file */
  1058         dirend = strrchr(link_file, '/');
  1059         if (dirend) {
  1060             char * tmp_file = NULL;
  1061             tmp_file = PL_strdup(dirend +1 );
  1062             PL_strfree(link_file);
  1063             link_file = tmp_file;
  1066 #endif
  1067     if (output_file == NULL) {
  1068         output_file = mkoutput(input_file);
  1071     /* compute the digest */
  1072     memset(digest, 0, sizeof(digest));
  1073     crv = pFunctionList->C_DigestInit(hRwSession, &digestmech);
  1074     if (crv != CKR_OK) {
  1075         pk11error("C_DigestInit failed", crv);
  1076         goto cleanup;
  1079     /* Digest the file */
  1080     while ((bytesRead = PR_Read(fd,file_buf,sizeof(file_buf))) > 0) {
  1081         crv = pFunctionList->C_DigestUpdate(hRwSession, (CK_BYTE_PTR)file_buf,
  1082                                             bytesRead);
  1083         if (crv != CKR_OK) {
  1084             pk11error("C_DigestUpdate failed", crv);
  1085             goto cleanup;
  1087         count += bytesRead;
  1090     /* close the input_File */
  1091     PR_Close(fd);
  1092     fd = NULL;
  1093     if (bytesRead < 0) {
  1094         lperror("0 bytes read from input file");
  1095         goto cleanup;
  1098     digestLen = sizeof(digest);
  1099     crv = pFunctionList->C_DigestFinal(hRwSession, (CK_BYTE_PTR)digest,
  1100                                        &digestLen);
  1101     if (crv != CKR_OK) {
  1102         pk11error("C_DigestFinal failed", crv);
  1103         goto cleanup;
  1106     if (digestLen != sizeof(digest)) {
  1107         PR_fprintf(PR_STDERR, "digestLen has incorrect length %lu "
  1108                 "it should be %lu \n",digestLen, sizeof(digest));
  1109         goto cleanup;
  1112     /* sign the hash */
  1113     memset(sign, 0, sizeof(sign));
  1114     /* SignUpdate  */
  1115     crv = pFunctionList->C_SignInit(hRwSession, &signMech, hDSAprivKey);
  1116     if (crv != CKR_OK) {
  1117         pk11error("C_SignInit failed", crv);
  1118         goto cleanup;
  1121     signLen = sizeof(sign);
  1122     crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE * ) digest, digestLen,
  1123                                 sign, &signLen);
  1124     if (crv != CKR_OK) {
  1125         pk11error("C_Sign failed", crv);
  1126         goto cleanup;
  1129     if (signLen != sizeof(sign)) {
  1130         PR_fprintf(PR_STDERR, "signLen has incorrect length %lu "
  1131                     "it should be %lu \n", signLen, sizeof(sign));
  1132         goto cleanup;
  1135     if (verify) {
  1136         crv = pFunctionList->C_VerifyInit(hRwSession, &signMech, hDSApubKey);
  1137         if (crv != CKR_OK) {
  1138             pk11error("C_VerifyInit failed", crv);
  1139             goto cleanup;
  1141         crv = pFunctionList->C_Verify(hRwSession, digest, digestLen,
  1142                                       sign, signLen);
  1143         if (crv != CKR_OK) {
  1144             pk11error("C_Verify failed", crv);
  1145             goto cleanup;
  1149     if (verbose) {
  1150         int j;
  1151         PR_fprintf(PR_STDERR,"Library File: %s %d bytes\n",input_file, count);
  1152         PR_fprintf(PR_STDERR,"Check File: %s\n",output_file);
  1153 #ifdef USES_LINKS
  1154         if (link_file) {
  1155             PR_fprintf(PR_STDERR,"Link: %s\n",link_file);
  1157 #endif
  1158         PR_fprintf(PR_STDERR,"  hash: %lu bytes\n", digestLen);
  1159 #define STEP 10
  1160         for (i=0; i < (int) digestLen; i += STEP) {
  1161             PR_fprintf(PR_STDERR,"   ");
  1162             for (j=0; j < STEP && (i+j) < (int) digestLen; j++) {
  1163                 PR_fprintf(PR_STDERR," %02x", digest[i+j]);
  1165             PR_fprintf(PR_STDERR,"\n");
  1167         PR_fprintf(PR_STDERR,"  signature: %lu bytes\n", signLen);
  1168         for (i=0; i < (int) signLen; i += STEP) {
  1169             PR_fprintf(PR_STDERR,"   ");
  1170             for (j=0; j < STEP && (i+j) < (int) signLen; j++) {
  1171                 PR_fprintf(PR_STDERR," %02x", sign[i+j]);
  1173             PR_fprintf(PR_STDERR,"\n");
  1177     /* open the target signature file */
  1178     fd = PR_Open(output_file,PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0666);
  1179     if (fd == NULL ) {
  1180         lperror(output_file);
  1181         goto cleanup;
  1184     /*
  1185      * we write the key out in a straight binary format because very
  1186      * low level libraries need to read an parse this file. Ideally we should
  1187      * just derEncode the public key (which would be pretty simple, and be
  1188      * more general), but then we'd need to link the ASN.1 decoder with the
  1189      * freebl libraries.
  1190      */
  1192     file_buf[0] = NSS_SIGN_CHK_MAGIC1;
  1193     file_buf[1] = NSS_SIGN_CHK_MAGIC2;
  1194     file_buf[2] = NSS_SIGN_CHK_MAJOR_VERSION;
  1195     file_buf[3] = NSS_SIGN_CHK_MINOR_VERSION;
  1196     encodeInt(&file_buf[4],12);  /* offset to data start */
  1197     encodeInt(&file_buf[8],CKK_DSA);
  1198     bytesWritten = PR_Write(fd,file_buf, 12);
  1199     if (bytesWritten != 12) {
  1200         lperror(output_file);
  1201         goto cleanup;
  1204     /* get DSA Public KeyValue */
  1205     memset(dsaPubKey, 0, sizeof(dsaPubKey));
  1206     dsaPubKeyValue.type =CKA_VALUE;
  1207     dsaPubKeyValue.pValue = (CK_VOID_PTR) &dsaPubKey;
  1208     dsaPubKeyValue.ulValueLen = sizeof(dsaPubKey);
  1210     crv = pFunctionList->C_GetAttributeValue(hRwSession, hDSApubKey,
  1211                                              &dsaPubKeyValue, 1);
  1212     if (crv != CKR_OK && crv != CKR_ATTRIBUTE_TYPE_INVALID) {
  1213         pk11error("C_GetAttributeValue failed", crv);
  1214         goto cleanup;
  1217     /* CKA_PRIME */
  1218     rv = writeItem(fd,dsaPubKeyTemplate[0].pValue,
  1219                    dsaPubKeyTemplate[0].ulValueLen, output_file);
  1220     if (rv != PR_SUCCESS) goto cleanup;
  1221     /* CKA_SUBPRIME */
  1222     rv = writeItem(fd,dsaPubKeyTemplate[1].pValue,
  1223                    dsaPubKeyTemplate[1].ulValueLen, output_file);
  1224     if (rv != PR_SUCCESS) goto cleanup;
  1225     /* CKA_BASE */ 
  1226     rv = writeItem(fd,dsaPubKeyTemplate[2].pValue,
  1227                    dsaPubKeyTemplate[2].ulValueLen, output_file);
  1228     if (rv != PR_SUCCESS) goto cleanup;
  1229     /* DSA Public Key value */
  1230     rv = writeItem(fd,dsaPubKeyValue.pValue,
  1231                    dsaPubKeyValue.ulValueLen, output_file);
  1232     if (rv != PR_SUCCESS) goto cleanup;
  1233     /* DSA SIGNATURE */
  1234     rv = writeItem(fd,&sign, signLen, output_file);
  1235     if (rv != PR_SUCCESS) goto cleanup;
  1236     PR_Close(fd);
  1238 #ifdef USES_LINKS
  1239     if (link_file) {
  1240         (void)unlink(link_file);
  1241         ret = symlink(output_file, link_file);
  1242         if (ret < 0) {
  1243             perror(link_file);
  1244             goto cleanup;
  1247 #endif
  1249     successful = PR_TRUE;
  1251 cleanup:
  1252     if (pFunctionList) {
  1253         /* C_Finalize will automatically logout, close session, */
  1254         /* and delete the temp objects on the token */
  1255         crv = pFunctionList->C_Finalize(NULL);
  1256         if (crv != CKR_OK) {
  1257             pk11error("C_Finalize failed", crv);
  1260     if (pSlotList) {
  1261         PR_Free(pSlotList);
  1263     if (pwd) {
  1264         PL_strfree(pwd);
  1266     if (configDir) {
  1267         PL_strfree(configDir);
  1269     if (dbPrefix) {
  1270         PL_strfree(dbPrefix);
  1272     if (output_file) { /* allocated by mkoutput function */
  1273         PL_strfree(output_file); 
  1275 #ifdef USES_LINKS
  1276     if (link_file) { /* allocated by mkoutput function */
  1277         PL_strfree(link_file); 
  1279 #endif
  1281     disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD");
  1282     if (!disableUnload) {
  1283         PR_UnloadLibrary(lib);
  1285     PR_Cleanup();
  1287     if (crv != CKR_OK)
  1288 	return crv;
  1290     return (successful) ? 0 : 1;

mercurial