security/nss/cmd/p7sign/p7sign.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  * p7sign -- A command to create a *detached* pkcs7 signature (over a given
     7  * input file).
     8  */
    10 #include "nspr.h"
    11 #include "plgetopt.h"
    12 #include "secutil.h"
    13 #include "secpkcs7.h"
    14 #include "cert.h"
    15 #include "certdb.h"
    16 #include "sechash.h"	/* for HASH_GetHashObject() */
    17 #include "nss.h"
    18 #include "pk11func.h"
    20 #if defined(XP_UNIX)
    21 #include <unistd.h>
    22 #endif
    24 #include <stdio.h>
    25 #include <string.h>
    27 #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
    28 extern int fread(char *, size_t, size_t, FILE*);
    29 extern int fwrite(char *, size_t, size_t, FILE*);
    30 extern int fprintf(FILE *, char *, ...);
    31 #endif
    33 static secuPWData  pwdata          = { PW_NONE, 0 };
    35 static void
    36 Usage(char *progName)
    37 {
    38     fprintf(stderr,
    39 	    "Usage:  %s -k keyname [-d keydir] [-i input] [-o output]\n",
    40 	    progName);
    41     fprintf(stderr, "%-20s Nickname of key to use for signature\n",
    42 	    "-k keyname");
    43     fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n",
    44 	    "-d keydir");
    45     fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
    46 	    "-i input");
    47     fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
    48 	    "-o output");
    49     fprintf(stderr, "%-20s Encapsulate content in signature message\n",
    50 	    "-e");
    51     fprintf(stderr, "%-20s Password to the key databse\n", "-p");
    52     fprintf(stderr, "%-20s password file\n", "-f");
    53     exit(-1);
    54 }
    56 static void
    57 SignOut(void *arg, const char *buf, unsigned long len)
    58 {
    59    FILE *out;
    61    out = (FILE*) arg; 
    62    fwrite (buf, len, 1, out);
    63 }
    65 static int
    66 CreateDigest(SECItem *data, char *digestdata, unsigned int *len, unsigned int maxlen)
    67 {
    68     const SECHashObject *hashObj;
    69     void *hashcx;
    71     /* XXX probably want to extend interface to allow other hash algorithms */
    72     hashObj = HASH_GetHashObject(HASH_AlgSHA1);
    74     hashcx = (* hashObj->create)();
    75     if (hashcx == NULL)
    76 	return -1;
    78     (* hashObj->begin)(hashcx);
    79     (* hashObj->update)(hashcx, data->data, data->len);
    80     (* hashObj->end)(hashcx, (unsigned char *)digestdata, len, maxlen);
    81     (* hashObj->destroy)(hashcx, PR_TRUE);
    82     return 0;
    83 }
    85 static int
    86 SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert, 
    87          PRBool encapsulated)
    88 {
    89     char digestdata[32];
    90     unsigned int len;
    91     SECItem digest, data2sign;
    92     SEC_PKCS7ContentInfo *cinfo;
    93     SECStatus rv;
    95     if (outFile == NULL || inFile == NULL || cert == NULL)
    96 	return -1;
    98     /* suck the file in */
    99 	if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE,
   100 	                         PR_FALSE) != SECSuccess)
   101 	return -1;
   103     if (!encapsulated) {
   104 	/* unfortunately, we must create the digest ourselves */
   105 	/* SEC_PKCS7CreateSignedData should have a flag to not include */
   106 	/* the content for non-encapsulated content at encode time, but */
   107 	/* should always compute the hash itself */
   108 	if (CreateDigest(&data2sign, digestdata, &len, 32) < 0)
   109 	    return -1;
   110 	digest.data = (unsigned char *)digestdata;
   111 	digest.len = len;
   112     }
   114     /* XXX Need a better way to handle that usage stuff! */
   115     cinfo = SEC_PKCS7CreateSignedData (cert, certUsageEmailSigner, NULL,
   116 				       SEC_OID_SHA1,
   117 				       encapsulated ? NULL : &digest,
   118 				       NULL, NULL);
   119     if (cinfo == NULL)
   120 	return -1;
   122     if (encapsulated) {
   123 	SEC_PKCS7SetContent(cinfo, (char *)data2sign.data, data2sign.len);
   124     }
   126     rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
   127     if (rv != SECSuccess) {
   128 	SEC_PKCS7DestroyContentInfo (cinfo);
   129 	return -1;
   130     }
   132     rv = SEC_PKCS7Encode (cinfo, SignOut, outFile, NULL,
   133 			  NULL, &pwdata);
   135     SEC_PKCS7DestroyContentInfo (cinfo);
   137     if (rv != SECSuccess)
   138 	return -1;
   140     return 0;
   141 }
   143 int
   144 main(int argc, char **argv)
   145 {
   146     char *progName;
   147     FILE *outFile;
   148     PRFileDesc *inFile;
   149     char *keyName = NULL;
   150     CERTCertDBHandle *certHandle;
   151     CERTCertificate *cert = NULL;
   152     PRBool encapsulated = PR_FALSE;
   153     PLOptState *optstate;
   154     PLOptStatus status;
   155     SECStatus rv;
   157     progName = strrchr(argv[0], '/');
   158     progName = progName ? progName+1 : argv[0];
   160     inFile = NULL;
   161     outFile = NULL;
   162     keyName = NULL;
   164     /*
   165      * Parse command line arguments
   166      */
   167     optstate = PL_CreateOptState(argc, argv, "ed:k:i:o:p:f:");
   168     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   169 	switch (optstate->option) {
   170 	  case '?':
   171 	    Usage(progName);
   172 	    break;
   174 	  case 'e':
   175 	    /* create a message with the signed content encapsulated */
   176 	    encapsulated = PR_TRUE;
   177 	    break;
   179 	  case 'd':
   180 	    SECU_ConfigDirectory(optstate->value);
   181 	    break;
   183 	  case 'i':
   184 	    inFile = PR_Open(optstate->value, PR_RDONLY, 0);
   185 	    if (!inFile) {
   186 		fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
   187 			progName, optstate->value);
   188 		return -1;
   189 	    }
   190 	    break;
   192 	  case 'k':
   193 	    keyName = strdup(optstate->value);
   194 	    break;
   196 	  case 'o':
   197 	    outFile = fopen(optstate->value, "wb");
   198 	    if (!outFile) {
   199 		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
   200 			progName, optstate->value);
   201 		return -1;
   202 	    }
   203 	    break;
   204 	  case 'p':
   205             pwdata.source = PW_PLAINTEXT;
   206             pwdata.data = strdup (optstate->value);
   207             break;
   209 	  case 'f':
   210               pwdata.source = PW_FROMFILE;
   211               pwdata.data = PORT_Strdup (optstate->value);
   212               break;
   213 	}
   214     }
   216     if (!keyName) Usage(progName);
   218     if (!inFile) inFile = PR_STDIN;
   219     if (!outFile) outFile = stdout;
   221     /* Call the initialization routines */
   222     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
   223     rv = NSS_Init(SECU_ConfigDirectory(NULL));
   224     if (rv != SECSuccess) {
   225 	SECU_PrintPRandOSError(progName);
   226 	goto loser;
   227     }
   229     PK11_SetPasswordFunc(SECU_GetModulePassword);
   231     /* open cert database */
   232     certHandle = CERT_GetDefaultCertDB();
   233     if (certHandle == NULL) {
   234 	rv = SECFailure;
   235 	goto loser;
   236     }
   238     /* find cert */
   239     cert = CERT_FindCertByNickname(certHandle, keyName);
   240     if (cert == NULL) {
   241 	SECU_PrintError(progName,
   242 		        "the corresponding cert for key \"%s\" does not exist",
   243 			keyName);
   244 	rv = SECFailure;
   245 	goto loser;
   246     }
   248     if (SignFile(outFile, inFile, cert, encapsulated)) {
   249 	SECU_PrintError(progName, "problem signing data");
   250 	rv = SECFailure;
   251 	goto loser;
   252     }
   254 loser:
   255     if (pwdata.data) {
   256         PORT_Free(pwdata.data);
   257     }
   258     if (keyName) {
   259         PORT_Free(keyName);
   260     }
   261     if (cert) {
   262         CERT_DestroyCertificate(cert);
   263     }
   264     if (inFile && inFile != PR_STDIN) {
   265         PR_Close(inFile);
   266     }
   267     if (outFile && outFile != stdout) {
   268         fclose(outFile);
   269     }
   270     if (NSS_Shutdown() != SECSuccess) {
   271         SECU_PrintError(progName, "NSS shutdown:");
   272         exit(1);
   273     }
   275     return (rv != SECSuccess);
   276 }

mercurial