1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14
* The Original Code is the Netscape security libraries.
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.
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.
35
* ***** END LICENSE BLOCK ***** */
43
/* NSPR 2.0 header files */
48
/* Portable layer header files */
50
#include "sechash.h" /* for HASH_GetHashObject() */
52
static int debugInfo = 0;
54
static char *usageInfo[] = {
56
" -a signature file is ASCII",
57
" -d certdir directory containing cert database",
58
" -i dataFileName input file name containing data,",
60
" -s signatureFileName input file name containing signature,",
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",
69
static int nUsageInfo = sizeof(usageInfo)/sizeof(char *);
71
extern int SV_PrintPKCS7ContentInfo(FILE *, SECItem *);
73
static void Usage(char *progName, FILE *outFile)
76
fprintf(outFile, "Usage: %s options\n", progName);
77
for (i = 0; i < nUsageInfo; i++)
78
fprintf(outFile, "%s\n", usageInfo[i]);
83
AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
87
tag = SECOID_GetAlgorithmTag(digestAlgorithms);
91
if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgMD2 SEC_OID_MD2\n");
94
if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgMD5 SEC_OID_MD5\n");
97
if (debugInfo) PR_fprintf(PR_STDERR, "Hash algorithm: HASH_AlgSHA1 SEC_OID_SHA1\n");
100
if (debugInfo) PR_fprintf(PR_STDERR, "should never get here\n");
107
DigestData (unsigned char *digest, unsigned char *data,
108
unsigned int *len, unsigned int maxLen,
109
HASH_HashType hashType)
111
const SECHashObject *hashObj;
114
hashObj = HASH_GetHashObject(hashType);
115
hashcx = (* hashObj->create)();
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);
128
cmd_DisplayAllPCKS7Info = 0,
130
cmd_DisplaySignerInfo,
145
static secuCommandFlag signver_commands[] =
147
{ /* cmd_DisplayAllPCKS7Info*/ 'A', PR_FALSE, 0, PR_FALSE },
148
{ /* cmd_VerifySignedObj */ 'V', PR_FALSE, 0, PR_FALSE }
151
static secuCommandFlag signver_options[] =
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 }
162
int main(int argc, char **argv)
164
PRExplodedTime explodedCurrent;
168
PRFileDesc *dataFile = 0;
169
PRFileDesc *signFile = 0;
170
FILE *outFile = stdout;
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;
181
progName = strrchr(argv[0], '\\');
183
progName = strrchr(argv[0], '/');
185
progName = progName ? progName+1 : argv[0];
189
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &explodedCurrent);
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);
199
rv = SECU_ParseCommandLine(argc, argv, progName, &signver);
201
if (SECSuccess != rv) {
202
Usage(progName, outFile);
205
/* Set the certdb directory (default is ~/.{browser}) */
206
SECU_ConfigDirectory(signver.options[opt_CertDir].arg);
208
/* Set the certificate type. */
209
typeTag = SECU_GetOptionArg(&signver, opt_TypeTag);
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",
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,
228
PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n",
229
progName, signver.options[opt_InputDataFile].arg);
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,
242
PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading.\n",
243
progName, signver.options[opt_InputSigFile].arg);
249
if (!typeTag) ascii = 1;
252
/* Open|Create the output file. */
253
if (signver.options[opt_OutputFile].activated) {
254
outFile = fopen(signver.options[opt_OutputFile].arg, "w");
256
outFile = PR_Open(signver.options[opt_OutputFile].arg,
257
PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 00660);
260
PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n",
261
progName, signver.options[opt_OutputFile].arg);
266
if (!signFile && !dataFile && !typeTag)
267
Usage(progName, outFile);
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",
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);
283
SECU_RegisterDynamicOids();
285
rv = SECU_ReadDERFromFile(&der, signFile,
286
signver.options[opt_ASCII].activated);
288
/* Data is untyped, using the specified type */
289
data.data = der.data;
293
/* Signature Verification */
294
if (!signver.options[opt_TypeTag].activated) {
295
if (signver.commands[cmd_VerifySignedObj].activated) {
296
SEC_PKCS7ContentInfo *cinfo;
298
cinfo = SEC_PKCS7DecodeItem(&data, NULL, NULL, NULL, NULL,
303
PR_fprintf(PR_STDERR, "Content %s encrypted.\n",
304
SEC_PKCS7ContentIsEncrypted(cinfo) ? "was" : "was not");
306
PR_fprintf(PR_STDERR, "Content %s signed.\n",
307
SEC_PKCS7ContentIsSigned(cinfo) ? "was" : "was not");
311
if (SEC_PKCS7ContentIsSigned(cinfo)) {
312
SEC_PKCS7SignedData *signedData;
313
HASH_HashType digestType;
314
SECItem digest, data;
315
unsigned char *dataToVerify, digestBuffer[32];
317
signedData = cinfo->content.signedData;
319
/* assume that there is only one digest algorithm for now */
321
AlgorithmToHashType(signedData->digestAlgorithms[0]);
322
if (digestType == HASH_AlgNULL) {
323
PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n");
326
rv = SECU_FileToItem(&data, dataFile);
327
dataToVerify = data.data;
329
/*certUsageObjectSigner;*/
330
SECCertUsage usage = certUsageEmailSigner;
335
PR_fprintf(PR_STDERR, "dataToVerify=%s\n",
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()));
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");
355
if (signver.commands[cmd_VerifySignedObj].activated)
356
fprintf(outFile, "signatureValid=");
358
if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage,
359
&digest, digestType, PR_FALSE)) {
360
if (signver.commands[cmd_VerifySignedObj].activated)
361
fprintf(outFile, "yes");
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()));
369
if (signver.commands[cmd_VerifySignedObj].activated)
370
fprintf(outFile, "\n");
372
SECITEM_FreeItem(&data, PR_FALSE);
374
PR_fprintf(PR_STDERR, "Cannot read data\n");
379
SEC_PKCS7DestroyContentInfo(cinfo);
381
PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n");
384
if (signver.commands[cmd_DisplayAllPCKS7Info].activated)
385
SV_PrintPKCS7ContentInfo(outFile, &data);
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);
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);
406
PR_fprintf(PR_STDERR, "%s: don't know how to print out '%s' files\n",
412
PR_fprintf(PR_STDERR, "%s: problem converting data (%s)\n",
413
progName, SECU_ErrorString((int16)PORT_GetError()));
417
if (NSS_Shutdown() != SECSuccess) {