security/nss/cmd/digest/digest.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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 "pk11func.h"
     7 #include "secoid.h"
     9 #if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
    10 #if !defined(WIN32)
    11 extern int fread(char *, size_t, size_t, FILE*);
    12 extern int fwrite(char *, size_t, size_t, FILE*);
    13 extern int fprintf(FILE *, char *, ...);
    14 #endif
    15 #endif
    17 #include "plgetopt.h"
    19 static SECOidData *
    20 HashTypeToOID(HASH_HashType hashtype)
    21 {
    22     SECOidTag hashtag;
    24     if (hashtype <= HASH_AlgNULL || hashtype >= HASH_AlgTOTAL)
    25 	return NULL;
    27     switch (hashtype) {
    28       case HASH_AlgMD2:
    29 	hashtag = SEC_OID_MD2;
    30 	break;
    31       case HASH_AlgMD5:
    32 	hashtag = SEC_OID_MD5;
    33 	break;
    34       case HASH_AlgSHA1:
    35 	hashtag = SEC_OID_SHA1;
    36 	break;
    37       default:
    38 	fprintf(stderr, "A new hash type has been added to HASH_HashType.\n");
    39 	fprintf(stderr, "This program needs to be updated!\n");
    40 	return NULL;
    41     }
    43     return SECOID_FindOIDByTag(hashtag);
    44 }
    46 static SECOidData *
    47 HashNameToOID(const char *hashName)
    48 {
    49     HASH_HashType htype;
    50     SECOidData *hashOID;
    52     for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
    53 	hashOID = HashTypeToOID(htype);
    54 	if (PORT_Strcasecmp(hashName, hashOID->desc) == 0)
    55 	    break;
    56     }
    58     if (htype == HASH_AlgTOTAL)
    59 	return NULL;
    61     return hashOID;
    62 }
    64 static void
    65 Usage(char *progName)
    66 {
    67     HASH_HashType htype;
    69     fprintf(stderr,
    70 	    "Usage:  %s -t type [-i input] [-o output]\n",
    71 	    progName);
    72     fprintf(stderr, "%-20s Specify the digest method (must be one of\n",
    73 	    "-t type");
    74     fprintf(stderr, "%-20s ", "");
    75     for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
    76 	fprintf(stderr, "%s", HashTypeToOID(htype)->desc);
    77 	if (htype == (HASH_AlgTOTAL - 2))
    78 	    fprintf(stderr, " or ");
    79 	else if (htype != (HASH_AlgTOTAL - 1))
    80 	    fprintf(stderr, ", ");
    81     }
    82     fprintf(stderr, " (case ignored))\n");
    83     fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
    84 	    "-i input");
    85     fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
    86 	    "-o output");
    87     exit(-1);
    88 }
    90 static int
    91 DigestFile(FILE *outFile, FILE *inFile, SECOidData *hashOID)
    92 {
    93     int nb;
    94     unsigned char ibuf[4096], digest[32];
    95     PK11Context *hashcx;
    96     unsigned int len;
    97     SECStatus rv;
    99     hashcx = PK11_CreateDigestContext(hashOID->offset);
   100     if (hashcx == NULL) {
   101 	return -1;
   102     }
   103     PK11_DigestBegin(hashcx);
   106     for (;;) {
   107 	if (feof(inFile)) break;
   108 	nb = fread(ibuf, 1, sizeof(ibuf), inFile);
   109 	if (nb != sizeof(ibuf)) {
   110 	    if (nb == 0) {
   111 		if (ferror(inFile)) {
   112 		    PORT_SetError(SEC_ERROR_IO);
   113 		    PK11_DestroyContext(hashcx,PR_TRUE);
   114 		    return -1;
   115 		}
   116 		/* eof */
   117 		break;
   118 	    }
   119 	}
   120 	rv = PK11_DigestOp(hashcx, ibuf, nb);
   121 	if (rv != SECSuccess) {
   122 	   PK11_DestroyContext(hashcx, PR_TRUE);
   123 	   return -1;
   124 	}
   125     }
   127     rv = PK11_DigestFinal(hashcx, digest, &len, 32);
   128     PK11_DestroyContext(hashcx, PR_TRUE);
   130     if (rv != SECSuccess) return -1;
   132     nb = fwrite(digest, 1, len, outFile);
   133     if (nb != len) {
   134 	PORT_SetError(SEC_ERROR_IO);
   135 	return -1;
   136     }
   138     return 0;
   139 }
   141 #include "nss.h"
   143 int
   144 main(int argc, char **argv)
   145 {
   146     char *progName;
   147     FILE *inFile, *outFile;
   148     char *hashName;
   149     SECOidData *hashOID;
   150     PLOptState *optstate;
   151     PLOptStatus status;
   152     SECStatus   rv;
   154     progName = strrchr(argv[0], '/');
   155     progName = progName ? progName+1 : argv[0];
   157     inFile = NULL;
   158     outFile = NULL;
   159     hashName = NULL;
   161     rv = NSS_Init("/tmp");
   162     if (rv != SECSuccess) {
   163     	fprintf(stderr, "%s: NSS_Init failed in directory %s\n",
   164 	        progName, "/tmp");
   165         return -1;
   166     }
   168     /*
   169      * Parse command line arguments
   170      */
   171     optstate = PL_CreateOptState(argc, argv, "t:i:o:");
   172     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   173 	switch (optstate->option) {
   174 	  case '?':
   175 	    Usage(progName);
   176 	    break;
   178 	  case 'i':
   179 	    inFile = fopen(optstate->value, "r");
   180 	    if (!inFile) {
   181 		fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
   182 			progName, optstate->value);
   183 		return -1;
   184 	    }
   185 	    break;
   187 	  case 'o':
   188 	    outFile = fopen(optstate->value, "w");
   189 	    if (!outFile) {
   190 		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
   191 			progName, optstate->value);
   192 		return -1;
   193 	    }
   194 	    break;
   196 	  case 't':
   197 	    hashName = strdup(optstate->value);
   198 	    break;
   199 	}
   200     }
   202     if (!hashName) Usage(progName);
   204     if (!inFile) inFile = stdin;
   205     if (!outFile) outFile = stdout;
   207     hashOID = HashNameToOID(hashName);
   208     if (hashOID == NULL) {
   209 	fprintf(stderr, "%s: invalid digest type\n", progName);
   210 	Usage(progName);
   211     }
   213     if (DigestFile(outFile, inFile, hashOID)) {
   214 	fprintf(stderr, "%s: problem digesting data (%s)\n",
   215 		progName, SECU_Strerror(PORT_GetError()));
   216 	return -1;
   217     }
   219     if (NSS_Shutdown() != SECSuccess) {
   220         exit(1);
   221     } 
   223     return 0;
   224 }

mercurial