security/nss/cmd/p7verify/p7verify.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  * p7verify -- A command to do a verification of a *detached* pkcs7 signature.
     7  */
     9 #include "nspr.h"
    10 #include "secutil.h"
    11 #include "plgetopt.h"
    12 #include "secpkcs7.h"
    13 #include "cert.h"
    14 #include "certdb.h"
    15 #include "secoid.h"
    16 #include "sechash.h"	/* for HASH_GetHashObject() */
    17 #include "nss.h"
    19 #if defined(XP_UNIX)
    20 #include <unistd.h>
    21 #endif
    23 #include <stdio.h>
    24 #include <string.h>
    26 #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
    27 extern int fread(char *, size_t, size_t, FILE*);
    28 extern int fprintf(FILE *, char *, ...);
    29 #endif
    32 static HASH_HashType
    33 AlgorithmToHashType(SECAlgorithmID *digestAlgorithms)
    34 {
    36     SECOidTag tag;
    38     tag = SECOID_GetAlgorithmTag(digestAlgorithms);
    40     switch (tag) {
    41       case SEC_OID_MD2:
    42 	return HASH_AlgMD2;
    43       case SEC_OID_MD5:
    44 	return HASH_AlgMD5;
    45       case SEC_OID_SHA1:
    46 	return HASH_AlgSHA1;
    47       default:
    48 	fprintf(stderr, "should never get here\n");
    49 	return HASH_AlgNULL;
    50     }
    51 }
    53 static int
    54 DigestFile(unsigned char *digest, unsigned int *len, unsigned int maxLen,
    55 	   FILE *inFile, HASH_HashType hashType)
    56 {
    57     int nb;
    58     unsigned char ibuf[4096];
    59     const SECHashObject *hashObj;
    60     void *hashcx;
    62     hashObj = HASH_GetHashObject(hashType);
    64     hashcx = (* hashObj->create)();
    65     if (hashcx == NULL)
    66 	return -1;
    68     (* hashObj->begin)(hashcx);
    70     for (;;) {
    71 	if (feof(inFile)) break;
    72 	nb = fread(ibuf, 1, sizeof(ibuf), inFile);
    73 	if (nb != sizeof(ibuf)) {
    74 	    if (nb == 0) {
    75 		if (ferror(inFile)) {
    76 		    PORT_SetError(SEC_ERROR_IO);
    77 		    (* hashObj->destroy)(hashcx, PR_TRUE);
    78 		    return -1;
    79 		}
    80 		/* eof */
    81 		break;
    82 	    }
    83 	}
    84 	(* hashObj->update)(hashcx, ibuf, nb);
    85     }
    87     (* hashObj->end)(hashcx, digest, len, maxLen);
    88     (* hashObj->destroy)(hashcx, PR_TRUE);
    90     return 0;
    91 }
    94 static void
    95 Usage(char *progName)
    96 {
    97     fprintf(stderr,
    98 	    "Usage:  %s -c content -s signature [-d dbdir] [-u certusage]\n",
    99 	    progName);
   100     fprintf(stderr, "%-20s content file that was signed\n",
   101 	    "-c content");
   102     fprintf(stderr, "%-20s file containing signature for that content\n",
   103 	    "-s signature");
   104     fprintf(stderr,
   105 	    "%-20s Key/Cert database directory (default is ~/.netscape)\n",
   106 	    "-d dbdir");
   107     fprintf(stderr, "%-20s Define the type of certificate usage (default is certUsageEmailSigner)\n",
   108 	    "-u certusage");
   109     fprintf(stderr, "%-25s  0 - certUsageSSLClient\n", " ");
   110     fprintf(stderr, "%-25s  1 - certUsageSSLServer\n", " ");
   111     fprintf(stderr, "%-25s  2 - certUsageSSLServerWithStepUp\n", " ");
   112     fprintf(stderr, "%-25s  3 - certUsageSSLCA\n", " ");
   113     fprintf(stderr, "%-25s  4 - certUsageEmailSigner\n", " ");
   114     fprintf(stderr, "%-25s  5 - certUsageEmailRecipient\n", " ");
   115     fprintf(stderr, "%-25s  6 - certUsageObjectSigner\n", " ");
   116     fprintf(stderr, "%-25s  7 - certUsageUserCertImport\n", " ");
   117     fprintf(stderr, "%-25s  8 - certUsageVerifyCA\n", " ");
   118     fprintf(stderr, "%-25s  9 - certUsageProtectedObjectSigner\n", " ");
   119     fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", " ");
   120     fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", " ");
   122     exit(-1);
   123 }
   125 static int
   126 HashDecodeAndVerify(FILE *out, FILE *content, PRFileDesc *signature,
   127 		    SECCertUsage usage, char *progName)
   128 {
   129     SECItem derdata;
   130     SEC_PKCS7ContentInfo *cinfo;
   131     SEC_PKCS7SignedData *signedData;
   132     HASH_HashType digestType;
   133     SECItem digest;
   134     unsigned char buffer[32];
   136     if (SECU_ReadDERFromFile(&derdata, signature, PR_FALSE,
   137                              PR_FALSE) != SECSuccess) {
   138 	SECU_PrintError(progName, "error reading signature file");
   139 	return -1;
   140     }
   142     cinfo = SEC_PKCS7DecodeItem(&derdata, NULL, NULL, NULL, NULL,
   143 				NULL, NULL, NULL);
   144     if (cinfo == NULL)
   145 	return -1;
   147     if (! SEC_PKCS7ContentIsSigned(cinfo)) {
   148 	fprintf (out, "Signature file is pkcs7 data, but not signed.\n");
   149 	return -1;
   150     }
   152     signedData = cinfo->content.signedData;
   154     /* assume that there is only one digest algorithm for now */
   155     digestType = AlgorithmToHashType(signedData->digestAlgorithms[0]);
   156     if (digestType == HASH_AlgNULL) {
   157 	fprintf (out, "Invalid hash algorithmID\n");
   158 	return -1;
   159     }
   161     digest.data = buffer;
   162     if (DigestFile (digest.data, &digest.len, 32, content, digestType)) {
   163 	SECU_PrintError (progName, "problem computing message digest");
   164 	return -1;
   165     }
   167     fprintf(out, "Signature is ");
   168     if (SEC_PKCS7VerifyDetachedSignature (cinfo, usage, &digest, digestType,
   169 					  PR_FALSE))
   170 	fprintf(out, "valid.\n");
   171     else
   172 	fprintf(out, "invalid (Reason: %s).\n",
   173 		SECU_Strerror(PORT_GetError()));
   175     SEC_PKCS7DestroyContentInfo(cinfo);
   176     return 0;
   177 }
   180 int
   181 main(int argc, char **argv)
   182 {
   183     char *progName;
   184     FILE *contentFile, *outFile;
   185     PRFileDesc *signatureFile;
   186     SECCertUsage certUsage = certUsageEmailSigner;
   187     PLOptState *optstate;
   188     PLOptStatus status;
   189     SECStatus rv;
   191     progName = strrchr(argv[0], '/');
   192     progName = progName ? progName+1 : argv[0];
   194     contentFile = NULL;
   195     signatureFile = NULL;
   196     outFile = NULL;
   198     /*
   199      * Parse command line arguments
   200      */
   201     optstate = PL_CreateOptState(argc, argv, "c:d:o:s:u:");
   202     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   203 	switch (optstate->option) {
   204 	  case '?':
   205 	    Usage(progName);
   206 	    break;
   208 	  case 'c':
   209 	    contentFile = fopen(optstate->value, "r");
   210 	    if (!contentFile) {
   211 		fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
   212 			progName, optstate->value);
   213 		return -1;
   214 	    }
   215 	    break;
   217 	  case 'd':
   218 	    SECU_ConfigDirectory(optstate->value);
   219 	    break;
   221 	  case 'o':
   222 	    outFile = fopen(optstate->value, "w");
   223 	    if (!outFile) {
   224 		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
   225 			progName, optstate->value);
   226 		return -1;
   227 	    }
   228 	    break;
   230 	  case 's':
   231 	    signatureFile = PR_Open(optstate->value, PR_RDONLY, 0);
   232 	    if (!signatureFile) {
   233 		fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
   234 			progName, optstate->value);
   235 		return -1;
   236 	    }
   237 	    break;
   239 	  case 'u': {
   240 	    int usageType;
   242 	    usageType = atoi (strdup(optstate->value));
   243 	    if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
   244 		return -1;
   245 	    certUsage = (SECCertUsage)usageType;
   246 	    break;
   247 	  }
   249 	}
   250     }
   252     if (!contentFile) Usage (progName);
   253     if (!signatureFile) Usage (progName);
   254     if (!outFile) outFile = stdout;
   256     /* Call the NSS initialization routines */
   257     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
   258     rv = NSS_Init(SECU_ConfigDirectory(NULL));
   259     if (rv != SECSuccess) {
   260     	SECU_PrintPRandOSError(progName);
   261 	return -1;
   262     }
   264     if (HashDecodeAndVerify(outFile, contentFile, signatureFile,
   265 			    certUsage, progName)) {
   266 	SECU_PrintError(progName, "problem decoding/verifying signature");
   267 	return -1;
   268     }
   270     if (NSS_Shutdown() != SECSuccess) {
   271         exit(1);
   272     }
   274     return 0;
   275 }

mercurial