|
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 "secoid.h" |
|
8 |
|
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 |
|
16 |
|
17 #include "plgetopt.h" |
|
18 |
|
19 static SECOidData * |
|
20 HashTypeToOID(HASH_HashType hashtype) |
|
21 { |
|
22 SECOidTag hashtag; |
|
23 |
|
24 if (hashtype <= HASH_AlgNULL || hashtype >= HASH_AlgTOTAL) |
|
25 return NULL; |
|
26 |
|
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 } |
|
42 |
|
43 return SECOID_FindOIDByTag(hashtag); |
|
44 } |
|
45 |
|
46 static SECOidData * |
|
47 HashNameToOID(const char *hashName) |
|
48 { |
|
49 HASH_HashType htype; |
|
50 SECOidData *hashOID; |
|
51 |
|
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 } |
|
57 |
|
58 if (htype == HASH_AlgTOTAL) |
|
59 return NULL; |
|
60 |
|
61 return hashOID; |
|
62 } |
|
63 |
|
64 static void |
|
65 Usage(char *progName) |
|
66 { |
|
67 HASH_HashType htype; |
|
68 |
|
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 } |
|
89 |
|
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; |
|
98 |
|
99 hashcx = PK11_CreateDigestContext(hashOID->offset); |
|
100 if (hashcx == NULL) { |
|
101 return -1; |
|
102 } |
|
103 PK11_DigestBegin(hashcx); |
|
104 |
|
105 |
|
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 } |
|
126 |
|
127 rv = PK11_DigestFinal(hashcx, digest, &len, 32); |
|
128 PK11_DestroyContext(hashcx, PR_TRUE); |
|
129 |
|
130 if (rv != SECSuccess) return -1; |
|
131 |
|
132 nb = fwrite(digest, 1, len, outFile); |
|
133 if (nb != len) { |
|
134 PORT_SetError(SEC_ERROR_IO); |
|
135 return -1; |
|
136 } |
|
137 |
|
138 return 0; |
|
139 } |
|
140 |
|
141 #include "nss.h" |
|
142 |
|
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; |
|
153 |
|
154 progName = strrchr(argv[0], '/'); |
|
155 progName = progName ? progName+1 : argv[0]; |
|
156 |
|
157 inFile = NULL; |
|
158 outFile = NULL; |
|
159 hashName = NULL; |
|
160 |
|
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 } |
|
167 |
|
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; |
|
177 |
|
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; |
|
186 |
|
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; |
|
195 |
|
196 case 't': |
|
197 hashName = strdup(optstate->value); |
|
198 break; |
|
199 } |
|
200 } |
|
201 |
|
202 if (!hashName) Usage(progName); |
|
203 |
|
204 if (!inFile) inFile = stdin; |
|
205 if (!outFile) outFile = stdout; |
|
206 |
|
207 hashOID = HashNameToOID(hashName); |
|
208 if (hashOID == NULL) { |
|
209 fprintf(stderr, "%s: invalid digest type\n", progName); |
|
210 Usage(progName); |
|
211 } |
|
212 |
|
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 } |
|
218 |
|
219 if (NSS_Shutdown() != SECSuccess) { |
|
220 exit(1); |
|
221 } |
|
222 |
|
223 return 0; |
|
224 } |