1 /*-
2 * Copyright (c) 2001-2003 Allan Saddi <allan@saddi.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY ALLAN SADDI AND HIS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL ALLAN SADDI OR HIS CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $Id: sha.c 351 2003-02-23 23:24:40Z asaddi $
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif /* HAVE_CONFIG_H */
32
33 #if HAVE_INTTYPES_H
34 # include <inttypes.h>
35 #else
36 # if HAVE_STDINT_H
37 # include <stdint.h>
38 # endif
39 #endif
40
41 #include <errno.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #if HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif /* HAVE_UNISTD_H */
48
49 #include "sha1.h"
50 #include "sha256.h"
51 #include "sha384.h"
52 #include "sha512.h"
53
54 #include "version.h"
55
56 #ifndef lint
57 static const char rcsid[] =
58 "$Id: sha.c 351 2003-02-23 23:24:40Z asaddi $";
59 #endif /* !lint */
60
61 static char *prog;
62
63 #define SHA_BUFFER_SIZE 65536
64 static uint8_t *buffer;
65
66 static int
shaFile(char * name,FILE * f,int which)67 shaFile (char *name, FILE *f, int which)
68 {
69 union {
70 SHA1Context sha1;
71 SHA256Context sha256;
72 SHA384Context sha384;
73 SHA512Context sha512;
74 } s;
75 size_t len;
76 uint8_t hash[SHA512_HASH_SIZE];
77 int hashLen, i;
78 int success = 1;
79
80 switch (which) {
81 case 1:
82 SHA1Init (&s.sha1);
83 break;
84 case 2:
85 SHA256Init (&s.sha256);
86 break;
87 case 3:
88 SHA384Init (&s.sha384);
89 break;
90 case 5:
91 SHA512Init (&s.sha512);
92 break;
93 default:
94 abort ();
95 }
96
97 while ((len = fread (buffer, 1, SHA_BUFFER_SIZE, f)) > 0) {
98 switch (which) {
99 case 1:
100 SHA1Update (&s.sha1, buffer, len);
101 break;
102 case 2:
103 SHA256Update (&s.sha256, buffer, len);
104 break;
105 case 3:
106 SHA384Update (&s.sha384, buffer, len);
107 break;
108 case 5:
109 SHA512Update (&s.sha512, buffer, len);
110 break;
111 default:
112 abort ();
113 }
114 }
115
116 if (ferror (f)) {
117 #if HAVE_STRERROR
118 fprintf (stderr, "%s: %s: %s\n", prog, name ? name : "stdin",
119 strerror (errno));
120 #else
121 fprintf (stderr, "%s: %s: %s\n", prog, name ? name : "stdin",
122 "Read error");
123 #endif
124 success = 0;
125 }
126 else {
127 switch (which) {
128 case 1:
129 SHA1Final (&s.sha1, hash);
130 hashLen = SHA1_HASH_SIZE;
131 break;
132 case 2:
133 SHA256Final (&s.sha256, hash);
134 hashLen = SHA256_HASH_SIZE;
135 break;
136 case 3:
137 SHA384Final (&s.sha384, hash);
138 hashLen = SHA384_HASH_SIZE;
139 break;
140 case 5:
141 SHA512Final (&s.sha512, hash);
142 hashLen = SHA512_HASH_SIZE;
143 break;
144 default:
145 abort ();
146 }
147
148 for (i = 0; i < hashLen; i++)
149 printf ("%02x", hash[i]);
150
151 if (name)
152 printf (" %s\n", name);
153 else
154 printf ("\n");
155 }
156
157 memset (&s, 0, sizeof (s));
158
159 return success;
160 }
161
162 static void
help(int which)163 help (int which)
164 {
165 fprintf (stderr, "\nOptions:\n"
166 "\t-1\tUse SHA-1 %s\n"
167 "\t-2\tUse SHA-256 %s\n"
168 "\t-3\tUse SHA-384 %s\n"
169 "\t-5\tUse SHA-512 %s\n"
170 "\t-V\tDisplay version information\n"
171 "\t-h\tDisplay this summary\n\n"
172 "Only one of -1, -2, -3, -5 may be specified\n",
173 which == 1 ? "(Default)" : "",
174 which == 2 ? "(Default)" : "",
175 which == 3 ? "(Default)" : "",
176 which == 5 ? "(Default)" : "");
177 }
178
179 static void
usage(void)180 usage (void)
181 {
182 fprintf (stderr, "Usage: %s [-1235Vh] [file ...]\n", prog);
183 }
184
185 static void
burnBuffer(void)186 burnBuffer (void)
187 {
188 memset (buffer, 0, SHA_BUFFER_SIZE);
189 }
190
191 int
main(int argc,char * argv[])192 main (int argc, char *argv[])
193 {
194 int ch;
195 char *whichStr;
196 int whichDef = 1;
197 int which = 0;
198 long offs;
199 int i;
200 FILE *f;
201 int failure = 0;
202
203 prog = argv[0];
204
205 if ((whichStr = getenv ("SHA_DEFAULT")) && *whichStr) {
206 switch (*whichStr) {
207 case '1':
208 whichDef = 1;
209 break;
210 case '2':
211 whichDef = 2;
212 break;
213 case '3':
214 whichDef = 3;
215 break;
216 case '5':
217 whichDef = 5;
218 break;
219 }
220 }
221
222 while ((ch = getopt (argc, argv, "1235Vh")) != -1) {
223 switch (ch) {
224 case '1':
225 case '2':
226 case '3':
227 case '5':
228 if (!which)
229 which = ch - '0';
230 else {
231 usage ();
232 help (whichDef);
233 exit (1);
234 }
235 break;
236 case 'V':
237 fprintf (stderr, "%s version " VERSION_STRING " (" VERSION_DATE ")\n",
238 prog);
239 exit (1);
240 case 'h':
241 usage ();
242 help (whichDef);
243 exit (1);
244 case '?':
245 default:
246 usage ();
247 exit (1);
248 }
249 }
250 argc -= optind;
251 argv += optind;
252
253 if (!which)
254 which = whichDef;
255
256 /* Allocate a suitable buffer. */
257 if (!(buffer = malloc (SHA_BUFFER_SIZE + 7))) {
258 perror (prog);
259 exit (1);
260 }
261
262 /* Ensure it is on a 64-bit boundary. */
263 if ((offs = (long) buffer & 7L))
264 buffer += 8 - offs;
265
266 atexit (burnBuffer);
267
268 /* If given no arguments, process stdin. */
269 if (!argc) {
270 if (shaFile (NULL, stdin, which))
271 exit (0);
272 else
273 exit (1);
274 }
275
276 for (i = 0; i < argc; i++) {
277 if ((f = fopen (argv[i], "rb"))) {
278 if (!shaFile (argv[i], f, which))
279 failure = 1;
280 fclose (f);
281 }
282 else {
283 #if HAVE_STRERROR
284 fprintf (stderr, "%s: %s: %s\n", prog, argv[i], strerror (errno));
285 #else
286 fprintf (stderr, "%s: %s: %s\n", prog, argv[i],
287 "No such file or directory");
288 #endif
289 failure = 1;
290 }
291 }
292
293 exit (failure);
294 }
295