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