security/nss/cmd/signver/signver.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 #include "secutil.h"
     6 #include "secmod.h"
     7 #include "cert.h"
     8 #include "secoid.h"
     9 #include "nss.h"
    11 /* NSPR 2.0 header files */
    12 #include "prinit.h"
    13 #include "prprf.h"
    14 #include "prsystem.h"
    15 #include "prmem.h"
    16 /* Portable layer header files */
    17 #include "plstr.h"
    18 #include "sechash.h"	/* for HASH_GetHashObject() */
    20 static PRBool debugInfo;
    21 static PRBool verbose;
    22 static PRBool doVerify;
    23 static PRBool displayAll;
    25 static const char * const usageInfo[] = {
    26     "signver - verify a detached PKCS7 signature - Version " NSS_VERSION,
    27     "Commands:",
    28     " -A		    display all information from pkcs #7",
    29     " -V		    verify the signed object and display result",
    30     "Options:",
    31     " -a		    signature file is ASCII",
    32     " -d certdir	    directory containing cert database",
    33     " -i dataFileName	    input file containing signed data (default stdin)",
    34     " -o outputFileName     output file name, default stdout",
    35     " -s signatureFileName  input file for signature (default stdin)",
    36     " -v		    display verbose reason for failure"
    37 };
    38 static int nUsageInfo = sizeof(usageInfo)/sizeof(char *);
    40 extern int SV_PrintPKCS7ContentInfo(FILE *, SECItem *);
    42 static void Usage(char *progName, FILE *outFile)
    43 {
    44     int i;
    45     fprintf(outFile, "Usage:  %s [ commands ] options\n", progName);
    46     for (i = 0; i < nUsageInfo; i++)
    47 	fprintf(outFile, "%s\n", usageInfo[i]);
    48     exit(-1);
    49 }
    51 static HASH_HashType
    52 AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
    53 {
    54     SECOidTag	  tag  = SECOID_GetAlgorithmTag(digestAlgorithms);
    55     HASH_HashType hash = HASH_GetHashTypeByOidTag(tag);
    56     return hash;
    57 }
    60 static SECStatus
    61 DigestContent (SECItem * digest, SECItem * content, HASH_HashType hashType)
    62 {
    63     unsigned int maxLen = digest->len;
    64     unsigned int len	= HASH_ResultLen(hashType);
    65     SECStatus	 rv;
    67     if (len > maxLen) {
    68 	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    69 	return SECFailure;
    70     }
    72     rv = HASH_HashBuf(hashType, digest->data, content->data, content->len);
    73     if (rv == SECSuccess)
    74 	digest->len = len;
    75     return rv;
    76 }
    78 enum {
    79     cmd_DisplayAllPCKS7Info = 0,
    80     cmd_VerifySignedObj
    81 };
    83 enum {
    84     opt_ASCII,
    85     opt_CertDir,
    86     opt_InputDataFile,
    87     opt_ItemNumber,
    88     opt_OutputFile,
    89     opt_InputSigFile,
    90     opt_PrintWhyFailure,
    91     opt_DebugInfo
    92 };
    94 static secuCommandFlag signver_commands[] =
    95 {
    96     { /* cmd_DisplayAllPCKS7Info*/  'A', PR_FALSE, 0, PR_FALSE },
    97     { /* cmd_VerifySignedObj	*/  'V', PR_FALSE, 0, PR_FALSE }
    98 };
   100 static secuCommandFlag signver_options[] =
   101 {
   102     { /* opt_ASCII		*/  'a', PR_FALSE, 0, PR_FALSE },
   103     { /* opt_CertDir		*/  'd', PR_TRUE,  0, PR_FALSE },
   104     { /* opt_InputDataFile	*/  'i', PR_TRUE,  0, PR_FALSE },
   105     { /* opt_OutputFile 	*/  'o', PR_TRUE,  0, PR_FALSE },
   106     { /* opt_InputSigFile	*/  's', PR_TRUE,  0, PR_FALSE },
   107     { /* opt_PrintWhyFailure	*/  'v', PR_FALSE, 0, PR_FALSE },
   108     { /* opt_DebugInfo		*/    0, PR_FALSE, 0, PR_FALSE, "debug" }
   109 };
   111 int main(int argc, char **argv)
   112 {
   113     PRFileDesc *contentFile = NULL;
   114     PRFileDesc *signFile = PR_STDIN;
   115     FILE *	outFile  = stdout;
   116     char *	progName;
   117     SECStatus	rv;
   118     int 	result	 = 1;
   119     SECItem	pkcs7der, content;
   120     secuCommand signver;
   122     pkcs7der.data  = NULL;
   123     content.data = NULL;
   125     signver.numCommands = sizeof(signver_commands) /sizeof(secuCommandFlag);
   126     signver.numOptions = sizeof(signver_options) / sizeof(secuCommandFlag);
   127     signver.commands = signver_commands;
   128     signver.options = signver_options;
   130 #ifdef XP_PC
   131     progName = strrchr(argv[0], '\\');
   132 #else
   133     progName = strrchr(argv[0], '/');
   134 #endif
   135     progName = progName ? progName+1 : argv[0];
   137     rv = SECU_ParseCommandLine(argc, argv, progName, &signver);
   138     if (SECSuccess != rv) {
   139 	Usage(progName, outFile);
   140     }
   141     debugInfo = signver.options[opt_DebugInfo	    ].activated;
   142     verbose   = signver.options[opt_PrintWhyFailure ].activated;
   143     doVerify  = signver.commands[cmd_VerifySignedObj].activated;
   144     displayAll= signver.commands[cmd_DisplayAllPCKS7Info].activated;
   145     if (!doVerify && !displayAll)
   146 	doVerify = PR_TRUE;
   148     /*	Set the certdb directory (default is ~/.netscape) */
   149     rv = NSS_Init(SECU_ConfigDirectory(signver.options[opt_CertDir].arg));
   150     if (rv != SECSuccess) {
   151 	SECU_PrintPRandOSError(progName);
   152 	return result;
   153     }
   154     /* below here, goto cleanup */
   155     SECU_RegisterDynamicOids();
   157     /*	Open the input content file. */
   158     if (signver.options[opt_InputDataFile].activated &&
   159 	signver.options[opt_InputDataFile].arg) {
   160 	if (PL_strcmp("-", signver.options[opt_InputDataFile].arg)) {
   161 	    contentFile = PR_Open(signver.options[opt_InputDataFile].arg,
   162 			       PR_RDONLY, 0);
   163 	    if (!contentFile) {
   164 		PR_fprintf(PR_STDERR,
   165 			   "%s: unable to open \"%s\" for reading.\n",
   166 			   progName, signver.options[opt_InputDataFile].arg);
   167 		goto cleanup;
   168 	    }
   169 	} else
   170 	    contentFile = PR_STDIN;
   171     }
   173     /*	Open the input signature file.	*/
   174     if (signver.options[opt_InputSigFile].activated &&
   175 	signver.options[opt_InputSigFile].arg) {
   176 	if (PL_strcmp("-", signver.options[opt_InputSigFile].arg)) {
   177 	    signFile = PR_Open(signver.options[opt_InputSigFile].arg,
   178 			       PR_RDONLY, 0);
   179 	    if (!signFile) {
   180 		PR_fprintf(PR_STDERR,
   181 			   "%s: unable to open \"%s\" for reading.\n",
   182 			   progName, signver.options[opt_InputSigFile].arg);
   183 		goto cleanup;
   184 	    }
   185 	}
   186     }
   188     if (contentFile == PR_STDIN && signFile == PR_STDIN && doVerify) {
   189 	PR_fprintf(PR_STDERR,
   190 	    "%s: cannot read both content and signature from standard input\n",
   191 		   progName);
   192 	goto cleanup;
   193     }
   195     /*	Open|Create the output file.  */
   196     if (signver.options[opt_OutputFile].activated) {
   197 	outFile = fopen(signver.options[opt_OutputFile].arg, "w");
   198 	if (!outFile) {
   199 	    PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing.\n",
   200 		       progName, signver.options[opt_OutputFile].arg);
   201 	    goto cleanup;
   202 	}
   203     }
   205     /* read in the input files' contents */
   206     rv = SECU_ReadDERFromFile(&pkcs7der, signFile,
   207 			      signver.options[opt_ASCII].activated, PR_FALSE);
   208     if (signFile != PR_STDIN)
   209 	PR_Close(signFile);
   210     if (rv != SECSuccess) {
   211 	SECU_PrintError(progName, "problem reading PKCS7 input");
   212 	goto cleanup;
   213     }
   214     if (contentFile) {
   215 	rv = SECU_FileToItem(&content, contentFile);
   216 	if (contentFile != PR_STDIN)
   217 	    PR_Close(contentFile);
   218 	if (rv != SECSuccess)
   219 	    content.data = NULL;
   220     }
   222     /* Signature Verification */
   223     if (doVerify) {
   224 	SEC_PKCS7ContentInfo *cinfo;
   225 	SEC_PKCS7SignedData *signedData;
   226 	HASH_HashType digestType;
   227 	PRBool contentIsSigned;
   229 	cinfo = SEC_PKCS7DecodeItem(&pkcs7der, NULL, NULL, NULL, NULL,
   230 				    NULL, NULL, NULL);
   231 	if (cinfo == NULL) {
   232 	    PR_fprintf(PR_STDERR, "Unable to decode PKCS7 data\n");
   233 	    goto cleanup;
   234 	}
   235 	/* below here, goto done */
   237 	contentIsSigned = SEC_PKCS7ContentIsSigned(cinfo);
   238 	if (debugInfo) {
   239 	    PR_fprintf(PR_STDERR, "Content is%s encrypted.\n",
   240 		       SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
   241 	}
   242 	if (debugInfo || !contentIsSigned) {
   243 	    PR_fprintf(PR_STDERR, "Content is%s signed.\n",
   244 		       contentIsSigned ? "" : " not");
   245 	}
   247 	if (!contentIsSigned)
   248 	    goto done;
   250 	signedData = cinfo->content.signedData;
   252 	/* assume that there is only one digest algorithm for now */
   253 	digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]);
   254 	if (digestType == HASH_AlgNULL) {
   255 	    PR_fprintf(PR_STDERR, "Invalid hash algorithmID\n");
   256 	    goto done;
   257 	}
   258 	if (content.data) {
   259 	    SECCertUsage   usage = certUsageEmailSigner;
   260 	    SECItem	   digest;
   261 	    unsigned char  digestBuffer[HASH_LENGTH_MAX];
   263 	    if (debugInfo)
   264 		PR_fprintf(PR_STDERR, "contentToVerify=%s\n", content.data);
   266 	    digest.data = digestBuffer;
   267 	    digest.len	= sizeof digestBuffer;
   269 	    if (DigestContent(&digest, &content, digestType)) {
   270 		SECU_PrintError(progName, "Message digest computation failure");
   271 		goto done;
   272 	    }
   274 	    if (debugInfo) {
   275 		unsigned int i;
   276 		PR_fprintf(PR_STDERR, "Data Digest=:");
   277 		for (i = 0; i < digest.len; i++)
   278 		    PR_fprintf(PR_STDERR, "%02x:", digest.data[i]);
   279 		PR_fprintf(PR_STDERR, "\n");
   280 	    }
   282 	    fprintf(outFile, "signatureValid=");
   283 	    PORT_SetError(0);
   284 	    if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage,
   285 				   &digest, digestType, PR_FALSE)) {
   286 		fprintf(outFile, "yes");
   287 	    } else {
   288 		fprintf(outFile, "no");
   289 		if (verbose) {
   290 		    fprintf(outFile, ":%s",
   291 			    SECU_Strerror(PORT_GetError()));
   292 		}
   293 	    }
   294 	    fprintf(outFile, "\n");
   295 	    result = 0;
   296 	}
   297 done:
   298 	SEC_PKCS7DestroyContentInfo(cinfo);
   299     }
   301     if (displayAll) {
   302 	if (SV_PrintPKCS7ContentInfo(outFile, &pkcs7der))
   303 	    result = 1;
   304     }
   306 cleanup:
   307     SECITEM_FreeItem(&pkcs7der, PR_FALSE);
   308     SECITEM_FreeItem(&content, PR_FALSE);
   310     if (NSS_Shutdown() != SECSuccess) {
   311 	result = 1;
   312     }
   314     return result;
   315 }

mercurial