Back to index

lightning-sunbird  0.9+nobinonly
digest.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "secutil.h"
00038 #include "pk11func.h"
00039 #include "secoid.h"
00040 
00041 #if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
00042 #if !defined(WIN32)
00043 extern int fread(char *, size_t, size_t, FILE*);
00044 extern int fwrite(char *, size_t, size_t, FILE*);
00045 extern int fprintf(FILE *, char *, ...);
00046 #endif
00047 #endif
00048 
00049 #include "plgetopt.h"
00050 
00051 static SECOidData *
00052 HashTypeToOID(HASH_HashType hashtype)
00053 {
00054     SECOidTag hashtag;
00055 
00056     if (hashtype <= HASH_AlgNULL || hashtype >= HASH_AlgTOTAL)
00057        return NULL;
00058 
00059     switch (hashtype) {
00060       case HASH_AlgMD2:
00061        hashtag = SEC_OID_MD2;
00062        break;
00063       case HASH_AlgMD5:
00064        hashtag = SEC_OID_MD5;
00065        break;
00066       case HASH_AlgSHA1:
00067        hashtag = SEC_OID_SHA1;
00068        break;
00069       default:
00070        fprintf(stderr, "A new hash type has been added to HASH_HashType.\n");
00071        fprintf(stderr, "This program needs to be updated!\n");
00072        return NULL;
00073     }
00074 
00075     return SECOID_FindOIDByTag(hashtag);
00076 }
00077 
00078 static SECOidData *
00079 HashNameToOID(const char *hashName)
00080 {
00081     HASH_HashType htype;
00082     SECOidData *hashOID;
00083 
00084     for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
00085        hashOID = HashTypeToOID(htype);
00086        if (PORT_Strcasecmp(hashName, hashOID->desc) == 0)
00087            break;
00088     }
00089 
00090     if (htype == HASH_AlgTOTAL)
00091        return NULL;
00092 
00093     return hashOID;
00094 }
00095 
00096 static void
00097 Usage(char *progName)
00098 {
00099     HASH_HashType htype;
00100 
00101     fprintf(stderr,
00102            "Usage:  %s -t type [-i input] [-o output]\n",
00103            progName);
00104     fprintf(stderr, "%-20s Specify the digest method (must be one of\n",
00105            "-t type");
00106     fprintf(stderr, "%-20s ", "");
00107     for (htype = HASH_AlgNULL + 1; htype < HASH_AlgTOTAL; htype++) {
00108        fprintf(stderr, HashTypeToOID(htype)->desc);
00109        if (htype == (HASH_AlgTOTAL - 2))
00110            fprintf(stderr, " or ");
00111        else if (htype != (HASH_AlgTOTAL - 1))
00112            fprintf(stderr, ", ");
00113     }
00114     fprintf(stderr, " (case ignored))\n");
00115     fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
00116            "-i input");
00117     fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
00118            "-o output");
00119     exit(-1);
00120 }
00121 
00122 static int
00123 DigestFile(FILE *outFile, FILE *inFile, SECOidData *hashOID)
00124 {
00125     int nb;
00126     unsigned char ibuf[4096], digest[32];
00127     PK11Context *hashcx;
00128     unsigned int len;
00129     SECStatus rv;
00130 
00131     hashcx = PK11_CreateDigestContext(hashOID->offset);
00132     if (hashcx == NULL) {
00133        return -1;
00134     }
00135     PK11_DigestBegin(hashcx);
00136 
00137 
00138     for (;;) {
00139        if (feof(inFile)) break;
00140        nb = fread(ibuf, 1, sizeof(ibuf), inFile);
00141        if (nb != sizeof(ibuf)) {
00142            if (nb == 0) {
00143               if (ferror(inFile)) {
00144                   PORT_SetError(SEC_ERROR_IO);
00145                   PK11_DestroyContext(hashcx,PR_TRUE);
00146                   return -1;
00147               }
00148               /* eof */
00149               break;
00150            }
00151        }
00152        rv = PK11_DigestOp(hashcx, ibuf, nb);
00153        if (rv != SECSuccess) {
00154           PK11_DestroyContext(hashcx, PR_TRUE);
00155           return -1;
00156        }
00157     }
00158 
00159     rv = PK11_DigestFinal(hashcx, digest, &len, 32);
00160     PK11_DestroyContext(hashcx, PR_TRUE);
00161 
00162     if (rv != SECSuccess) return -1;
00163 
00164     nb = fwrite(digest, 1, len, outFile);
00165     if (nb != len) {
00166        PORT_SetError(SEC_ERROR_IO);
00167        return -1;
00168     }
00169 
00170     return 0;
00171 }
00172 
00173 #include "nss.h"
00174 
00175 int
00176 main(int argc, char **argv)
00177 {
00178     char *progName;
00179     FILE *inFile, *outFile;
00180     char *hashName;
00181     SECOidData *hashOID;
00182     PLOptState *optstate;
00183     PLOptStatus status;
00184     SECStatus   rv;
00185 
00186     progName = strrchr(argv[0], '/');
00187     progName = progName ? progName+1 : argv[0];
00188 
00189     inFile = NULL;
00190     outFile = NULL;
00191     hashName = NULL;
00192 
00193     rv = NSS_Init("/tmp");
00194     if (rv != SECSuccess) {
00195        fprintf(stderr, "%s: NSS_Init failed in directory %s\n",
00196                progName, "/tmp");
00197         return -1;
00198     }
00199 
00200     /*
00201      * Parse command line arguments
00202      */
00203     optstate = PL_CreateOptState(argc, argv, "t:i:o:");
00204     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
00205        switch (optstate->option) {
00206          case '?':
00207            Usage(progName);
00208            break;
00209 
00210          case 'i':
00211            inFile = fopen(optstate->value, "r");
00212            if (!inFile) {
00213               fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
00214                      progName, optstate->value);
00215               return -1;
00216            }
00217            break;
00218 
00219          case 'o':
00220            outFile = fopen(optstate->value, "w");
00221            if (!outFile) {
00222               fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
00223                      progName, optstate->value);
00224               return -1;
00225            }
00226            break;
00227 
00228          case 't':
00229            hashName = strdup(optstate->value);
00230            break;
00231        }
00232     }
00233 
00234     if (!hashName) Usage(progName);
00235 
00236     if (!inFile) inFile = stdin;
00237     if (!outFile) outFile = stdout;
00238 
00239     hashOID = HashNameToOID(hashName);
00240     if (hashOID == NULL) {
00241        fprintf(stderr, "%s: invalid digest type\n", progName);
00242        Usage(progName);
00243     }
00244 
00245     if (DigestFile(outFile, inFile, hashOID)) {
00246        fprintf(stderr, "%s: problem digesting data (%s)\n",
00247               progName, SECU_Strerror(PORT_GetError()));
00248        return -1;
00249     }
00250 
00251     if (NSS_Shutdown() != SECSuccess) {
00252         exit(1);
00253     } 
00254     
00255     return 0;
00256 }