~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/cmd/signver/signver.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
16
 * The Initial Developer of the Original Code is
 
17
 * Netscape Communications Corporation.
 
18
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 
19
 * the Initial Developer. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *
 
23
 * Alternatively, the contents of this file may be used under the terms of
 
24
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
25
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
26
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
27
 * of those above. If you wish to allow use of your version of this file only
 
28
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
29
 * use your version of this file under the terms of the MPL, indicate your
 
30
 * decision by deleting the provisions above and replace them with the notice
 
31
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
32
 * the provisions above, a recipient may use your version of this file under
 
33
 * the terms of any one of the MPL, the GPL or the LGPL.
 
34
 *
 
35
 * ***** END LICENSE BLOCK ***** */
 
36
 
 
37
#include "secutil.h"
 
38
#include "secmod.h"
 
39
#include "cert.h"
 
40
#include "secoid.h"
 
41
#include "nss.h"
 
42
 
 
43
/* NSPR 2.0 header files */
 
44
#include "prinit.h"
 
45
#include "prprf.h"
 
46
#include "prsystem.h"
 
47
#include "prmem.h"
 
48
/* Portable layer header files */
 
49
#include "plstr.h"
 
50
#include "sechash.h"    /* for HASH_GetHashObject() */
 
51
 
 
52
static int debugInfo = 0;
 
53
 
 
54
static char *usageInfo[] = {
 
55
        "Options:",
 
56
        " -a                           signature file is ASCII",
 
57
        " -d certdir                   directory containing cert database",
 
58
        " -i dataFileName              input file name containing data,",
 
59
        "                              use - for stdin",
 
60
        " -s signatureFileName         input file name containing signature,",
 
61
        "                              use - for stdin",
 
62
        " -o outputFileName            output file name, default stdout",
 
63
        " -A                           display all information from pkcs #7",
 
64
        " -V                           verify the signed object and display result",
 
65
        " -V -v                        verify the signed object and display",
 
66
        "                              result and reason for failure",
 
67
        "Version 2.0"
 
68
};
 
69
static int nUsageInfo = sizeof(usageInfo)/sizeof(char *);
 
70
 
 
71
extern int SV_PrintPKCS7ContentInfo(FILE *, SECItem *);
 
72
 
 
73
static void Usage(char *progName, FILE *outFile)
 
74
{
 
75
        int i;
 
76
        fprintf(outFile, "Usage:  %s  options\n", progName);
 
77
        for (i = 0; i < nUsageInfo; i++)
 
78
                fprintf(outFile, "%s\n", usageInfo[i]);
 
79
        exit(-1);
 
80
}
 
81
 
 
82
static HASH_HashType
 
83
AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
 
84
{
 
85
        SECOidTag tag;
 
86
 
 
87
        tag = SECOID_GetAlgorithmTag(digestAlgorithms);
 
88
 
 
89
        switch (tag) {
 
90
                case SEC_OID_MD2:
 
91
                        if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgMD2 SEC_OID_MD2\n");
 
92
                        return HASH_AlgMD2;
 
93
                case SEC_OID_MD5:
 
94
                        if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgMD5 SEC_OID_MD5\n");
 
95
                        return HASH_AlgMD5;
 
96
                case SEC_OID_SHA1:
 
97
                        if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgSHA1 SEC_OID_SHA1\n");
 
98
                        return HASH_AlgSHA1;
 
99
                default:
 
100
                        if (debugInfo) PR_fprintf(PR_STDERR, "should never get here\n");
 
101
                        return HASH_AlgNULL;
 
102
        }
 
103
}
 
104
 
 
105
 
 
106
static int
 
107
DigestData (unsigned char *digest, unsigned char *data,
 
108
                        unsigned int *len, unsigned int maxLen,
 
109
                        HASH_HashType hashType)
 
110
{
 
111
        const SECHashObject *hashObj;
 
112
        void *hashcx;
 
113
 
 
114
        hashObj = HASH_GetHashObject(hashType);
 
115
        hashcx = (* hashObj->create)();
 
116
        if (hashcx == NULL)
 
117
        return -1;
 
118
 
 
119
        (* hashObj->begin)(hashcx);
 
120
        (* hashObj->update)(hashcx, data, PORT_Strlen((char *)data));
 
121
        (* hashObj->end)(hashcx, digest, len, maxLen);
 
122
        (* hashObj->destroy)(hashcx, PR_TRUE);
 
123
 
 
124
        return 0;
 
125
}
 
126
 
 
127
enum {
 
128
        cmd_DisplayAllPCKS7Info = 0,
 
129
        cmd_DisplayCertInfo,
 
130
        cmd_DisplaySignerInfo,
 
131
        cmd_VerifySignedObj
 
132
};
 
133
 
 
134
enum {
 
135
        opt_ASCII,
 
136
        opt_CertDir,
 
137
        opt_InputDataFile,
 
138
        opt_ItemNumber,
 
139
        opt_OutputFile,
 
140
        opt_InputSigFile,
 
141
        opt_TypeTag,
 
142
        opt_PrintWhyFailure
 
143
};
 
144
 
 
145
static secuCommandFlag signver_commands[] =
 
146
{
 
147
        { /* cmd_DisplayAllPCKS7Info*/  'A', PR_FALSE, 0, PR_FALSE },
 
148
        { /* cmd_VerifySignedObj    */  'V', PR_FALSE, 0, PR_FALSE }
 
149
};
 
150
 
 
151
static secuCommandFlag signver_options[] =
 
152
{
 
153
        { /* opt_ASCII              */  'a', PR_FALSE, 0, PR_FALSE },
 
154
        { /* opt_CertDir            */  'd', PR_TRUE,  0, PR_FALSE },
 
155
        { /* opt_InputDataFile      */  'i', PR_TRUE,  0, PR_FALSE },
 
156
        { /* opt_OutputFile         */  'o', PR_TRUE,  0, PR_FALSE },
 
157
        { /* opt_InputSigFile       */  's', PR_TRUE,  0, PR_FALSE },
 
158
        { /* opt_TypeTag            */  't', PR_TRUE,  0, PR_FALSE },
 
159
        { /* opt_PrintWhyFailure    */  'v', PR_FALSE, 0, PR_FALSE }
 
160
};
 
161
 
 
162
int main(int argc, char **argv)
 
163
{
 
164
        PRExplodedTime explodedCurrent;
 
165
        SECItem der, data;
 
166
        char *progName;
 
167
        int rv;
 
168
        PRFileDesc *dataFile = 0;
 
169
        PRFileDesc *signFile = 0;
 
170
        FILE *outFile = stdout;
 
171
        char *typeTag = 0;
 
172
        SECStatus secstatus;
 
173
 
 
174
        secuCommand signver;
 
175
        signver.numCommands = sizeof(signver_commands) /sizeof(secuCommandFlag);
 
176
        signver.numOptions = sizeof(signver_options) / sizeof(secuCommandFlag);
 
177
        signver.commands = signver_commands;
 
178
        signver.options = signver_options;
 
179
 
 
180
#ifdef XP_PC
 
181
        progName = strrchr(argv[0], '\\');
 
182
#else
 
183
        progName = strrchr(argv[0], '/');
 
184
#endif
 
185
        progName = progName ? progName+1 : argv[0];
 
186
 
 
187
        /*_asm int 3*/
 
188
 
 
189
        PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &explodedCurrent);
 
190
#if 0
 
191
        if (explodedCurrent.tm_year >= 1998
 
192
                && explodedCurrent.tm_month >= 5 /* months past tm_year (0-11, Jan = 0) */
 
193
                && explodedCurrent.tm_mday >= 1) {
 
194
                PR_fprintf(PR_STDERR, "%s: expired\n", progName);
 
195
                return -1;
 
196
        }
 
197
#endif
 
198
 
 
199
        rv = SECU_ParseCommandLine(argc, argv, progName, &signver);
 
200
 
 
201
        if (SECSuccess != rv) {
 
202
            Usage(progName, outFile);
 
203
        }
 
204
 
 
205
        /*  Set the certdb directory (default is ~/.{browser}) */
 
206
        SECU_ConfigDirectory(signver.options[opt_CertDir].arg);
 
207
 
 
208
        /*  Set the certificate type.  */
 
209
        typeTag = SECU_GetOptionArg(&signver, opt_TypeTag);
 
210
 
 
211
        /*  -i and -s without filenames  */
 
212
        if (signver.options[opt_InputDataFile].activated &&
 
213
            signver.options[opt_InputSigFile].activated &&
 
214
            !PL_strcmp("-", signver.options[opt_InputDataFile].arg) &&
 
215
            !PL_strcmp("-", signver.options[opt_InputSigFile].arg))
 
216
                PR_fprintf(PR_STDERR, 
 
217
                      "%s: Only data or signature file can use stdin (not both).\n",
 
218
                      progName);
 
219
 
 
220
        /*  Open the input data file (no arg == use stdin). */
 
221
        if (signver.options[opt_InputDataFile].activated) {
 
222
                if (PL_strcmp("-", signver.options[opt_InputDataFile].arg))
 
223
                        dataFile = PR_Open(signver.options[opt_InputDataFile].arg, 
 
224
                                           PR_RDONLY, 0);
 
225
                else
 
226
                        dataFile = PR_STDIN;
 
227
                if (!dataFile) {
 
228
                        PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n",
 
229
                                   progName, signver.options[opt_InputDataFile].arg);
 
230
                        return -1;
 
231
                }
 
232
        }
 
233
 
 
234
        /*  Open the input signature file (no arg == use stdin).  */
 
235
        if (signver.options[opt_InputSigFile].activated) {
 
236
                if (PL_strcmp("-", signver.options[opt_InputSigFile].arg))
 
237
                        signFile = PR_Open(signver.options[opt_InputSigFile].arg, 
 
238
                                           PR_RDONLY, 0);
 
239
                else
 
240
                        signFile = PR_STDIN;
 
241
                if (!signFile) {
 
242
                        PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n",
 
243
                                   progName, signver.options[opt_InputSigFile].arg);
 
244
                        return -1;
 
245
                }
 
246
        }
 
247
 
 
248
#if 0
 
249
                                if (!typeTag) ascii = 1;
 
250
#endif
 
251
 
 
252
        /*  Open|Create the output file.  */
 
253
        if (signver.options[opt_OutputFile].activated) {
 
254
                outFile = fopen(signver.options[opt_OutputFile].arg, "w");
 
255
                        /*
 
256
                outFile = PR_Open(signver.options[opt_OutputFile].arg,
 
257
                                  PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 00660);
 
258
                                                  */
 
259
                if (!outFile) {
 
260
                        PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n",
 
261
                                   progName, signver.options[opt_OutputFile].arg);
 
262
                        return -1;
 
263
                }
 
264
        }
 
265
 
 
266
        if (!signFile && !dataFile && !typeTag) 
 
267
                Usage(progName, outFile);
 
268
 
 
269
        if (!signFile && !dataFile && 
 
270
             signver.commands[cmd_VerifySignedObj].activated) {
 
271
                PR_fprintf(PR_STDERR, 
 
272
                           "%s: unable to read all data from standard input\n", 
 
273
                           progName);
 
274
                return -1;
 
275
        } 
 
276
 
 
277
        PR_SetError(0, 0); /* PR_Init("pp", 1, 1, 0);*/
 
278
        secstatus = NSS_Init(SECU_ConfigDirectory(NULL));
 
279
        if (secstatus != SECSuccess) {
 
280
            SECU_PrintPRandOSError(progName);
 
281
            return -1;
 
282
        }
 
283
        SECU_RegisterDynamicOids();
 
284
 
 
285
        rv = SECU_ReadDERFromFile(&der, signFile, 
 
286
                                  signver.options[opt_ASCII].activated);
 
287
 
 
288
        /* Data is untyped, using the specified type */
 
289
        data.data = der.data;
 
290
        data.len = der.len;
 
291
 
 
292
 
 
293
        /* Signature Verification */
 
294
        if (!signver.options[opt_TypeTag].activated) {
 
295
                if (signver.commands[cmd_VerifySignedObj].activated) {
 
296
                        SEC_PKCS7ContentInfo *cinfo;
 
297
 
 
298
                        cinfo = SEC_PKCS7DecodeItem(&data, NULL, NULL, NULL, NULL,
 
299
                                                    NULL, NULL, NULL);
 
300
                        if (cinfo != NULL) {
 
301
#if 0
 
302
                                if (debugInfo) {
 
303
                                        PR_fprintf(PR_STDERR, "Content %s encrypted.\n",
 
304
                                                           SEC_PKCS7ContentIsEncrypted(cinfo) ? "was" : "was not");
 
305
 
 
306
                                        PR_fprintf(PR_STDERR, "Content %s signed.\n",
 
307
                                                           SEC_PKCS7ContentIsSigned(cinfo) ? "was" : "was not");
 
308
                                }
 
309
#endif
 
310
 
 
311
                                if (SEC_PKCS7ContentIsSigned(cinfo)) {
 
312
                                        SEC_PKCS7SignedData *signedData;
 
313
                                        HASH_HashType digestType;
 
314
                                        SECItem digest, data;
 
315
                                        unsigned char *dataToVerify, digestBuffer[32];
 
316
 
 
317
                                        signedData = cinfo->content.signedData;
 
318
 
 
319
                                        /* assume that there is only one digest algorithm for now */
 
320
                                        digestType = 
 
321
                                          AlgorithmToHashType(signedData->digestAlgorithms[0]);
 
322
                                        if (digestType == HASH_AlgNULL) {
 
323
                                                PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n");
 
324
                                                return (-1);
 
325
                                        }
 
326
                                        rv = SECU_FileToItem(&data, dataFile);
 
327
                                        dataToVerify = data.data;
 
328
                                        if (dataToVerify) {
 
329
                                                                   /*certUsageObjectSigner;*/
 
330
                                                SECCertUsage usage = certUsageEmailSigner; 
 
331
                                                
 
332
 
 
333
#if 0
 
334
                                                if (debugInfo) 
 
335
                                                        PR_fprintf(PR_STDERR, "dataToVerify=%s\n", 
 
336
                                                                   dataToVerify);
 
337
#endif
 
338
                                                digest.data = digestBuffer;
 
339
                                                if (DigestData (digest.data, dataToVerify, 
 
340
                                                                &digest.len, 32, digestType)) {
 
341
                                                        PR_fprintf(PR_STDERR, "Fail to compute message digest for verification. Reason: %s\n",
 
342
                                                                          SECU_ErrorString((int16)PORT_GetError()));
 
343
                                                        return (-1);
 
344
                                                }
 
345
#if 0
 
346
                                                if (debugInfo) {
 
347
                                                        PR_fprintf(PR_STDERR, "Data Digest=:");
 
348
                                                        for (i = 0; i < digest.len; i++)
 
349
                                                                PR_fprintf(PR_STDERR, "%02x:", digest.data[i]);
 
350
                                                        PR_fprintf(PR_STDERR, "\n");
 
351
                                                }
 
352
#endif
 
353
 
 
354
 
 
355
                                                if (signver.commands[cmd_VerifySignedObj].activated)
 
356
                                                        fprintf(outFile, "signatureValid=");
 
357
                                                PORT_SetError(0);
 
358
                                                if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage, 
 
359
                                                                       &digest, digestType, PR_FALSE)) {
 
360
                                                        if (signver.commands[cmd_VerifySignedObj].activated)
 
361
                                                                fprintf(outFile, "yes");
 
362
                                                } else {
 
363
                                                        if (signver.commands[cmd_VerifySignedObj].activated){
 
364
                                                                fprintf(outFile, "no");
 
365
                                                        if (signver.options[opt_PrintWhyFailure].activated)
 
366
                                                        fprintf(outFile, ":%s", SECU_ErrorString((int16)PORT_GetError()));
 
367
                                                        }
 
368
                                                }
 
369
                                                if (signver.commands[cmd_VerifySignedObj].activated)
 
370
                                                        fprintf(outFile, "\n");
 
371
 
 
372
                                                SECITEM_FreeItem(&data, PR_FALSE);
 
373
                                        } else {
 
374
                                                PR_fprintf(PR_STDERR, "Cannot read data\n");
 
375
                                                return (-1);
 
376
                                        }
 
377
                                }
 
378
 
 
379
                                SEC_PKCS7DestroyContentInfo(cinfo);
 
380
                        } else
 
381
                                PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n");
 
382
                }
 
383
 
 
384
                if (signver.commands[cmd_DisplayAllPCKS7Info].activated)
 
385
                        SV_PrintPKCS7ContentInfo(outFile, &data);
 
386
 
 
387
        /* Pretty print it */
 
388
        } else if (PL_strcmp(typeTag, SEC_CT_CERTIFICATE) == 0) {
 
389
                rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
 
390
                                                                  SECU_PrintCertificate);
 
391
        } else if (PL_strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0) {
 
392
                rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
 
393
                                                                  SECU_PrintCertificateRequest);
 
394
        } else if (PL_strcmp (typeTag, SEC_CT_CRL) == 0) {
 
395
                rv = SECU_PrintSignedData (outFile, &data, "CRL", 0, SECU_PrintCrl);
 
396
#ifdef HAVE_EPK_TEMPLATE
 
397
        } else if (PL_strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0) {
 
398
                rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
 
399
#endif
 
400
        } else if (PL_strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0) {
 
401
                rv = SECU_PrintPublicKey(outFile, &data, "Public Key", 0);
 
402
        } else if (PL_strcmp(typeTag, SEC_CT_PKCS7) == 0) {
 
403
                rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
 
404
                                                                                "PKCS #7 Content Info", 0);
 
405
        } else {
 
406
                PR_fprintf(PR_STDERR, "%s: don't know how to print out '%s' files\n",
 
407
                                   progName, typeTag);
 
408
                return -1;
 
409
        }
 
410
 
 
411
        if (rv) {
 
412
                PR_fprintf(PR_STDERR, "%s: problem converting data (%s)\n",
 
413
                                   progName, SECU_ErrorString((int16)PORT_GetError()));
 
414
                return -1;
 
415
        }
 
416
 
 
417
       if (NSS_Shutdown() != SECSuccess) {
 
418
           exit(1);
 
419
       }
 
420
 
 
421
        return 0;
 
422
}