| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: md5.c,v 1.92 2017/09/11 16:35:38 millert Exp $ */  | 
    ||
2  | 
    |||
3  | 
    /*  | 
    ||
4  | 
    * Copyright (c) 2001,2003,2005-2007,2010,2013,2014  | 
    ||
5  | 
    * Todd C. Miller <Todd.Miller@courtesan.com>  | 
    ||
6  | 
    *  | 
    ||
7  | 
    * Permission to use, copy, modify, and distribute this software for any  | 
    ||
8  | 
    * purpose with or without fee is hereby granted, provided that the above  | 
    ||
9  | 
    * copyright notice and this permission notice appear in all copies.  | 
    ||
10  | 
    *  | 
    ||
11  | 
    * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  | 
    ||
12  | 
    * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF  | 
    ||
13  | 
    * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR  | 
    ||
14  | 
    * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES  | 
    ||
15  | 
    * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN  | 
    ||
16  | 
    * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  | 
    ||
17  | 
    * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  | 
    ||
18  | 
    *  | 
    ||
19  | 
    * Sponsored in part by the Defense Advanced Research Projects  | 
    ||
20  | 
    * Agency (DARPA) and Air Force Research Laboratory, Air Force  | 
    ||
21  | 
    * Materiel Command, USAF, under agreement number F39502-99-1-0512.  | 
    ||
22  | 
    */  | 
    ||
23  | 
    |||
24  | 
    #include <sys/types.h>  | 
    ||
25  | 
    #include <sys/time.h>  | 
    ||
26  | 
    #include <sys/queue.h>  | 
    ||
27  | 
    #include <sys/resource.h>  | 
    ||
28  | 
    #include <netinet/in.h>  | 
    ||
29  | 
    #include <ctype.h>  | 
    ||
30  | 
    #include <err.h>  | 
    ||
31  | 
    #include <fcntl.h>  | 
    ||
32  | 
    #include <resolv.h>  | 
    ||
33  | 
    #include <stdio.h>  | 
    ||
34  | 
    #include <stdlib.h>  | 
    ||
35  | 
    #include <string.h>  | 
    ||
36  | 
    #include <limits.h>  | 
    ||
37  | 
    #include <time.h>  | 
    ||
38  | 
    #include <unistd.h>  | 
    ||
39  | 
    #include <errno.h>  | 
    ||
40  | 
    |||
41  | 
    #include <md5.h>  | 
    ||
42  | 
    #include <rmd160.h>  | 
    ||
43  | 
    #include <sha1.h>  | 
    ||
44  | 
    #include <sha2.h>  | 
    ||
45  | 
    #include <crc.h>  | 
    ||
46  | 
    |||
47  | 
    #define STYLE_MD5 0  | 
    ||
48  | 
    #define STYLE_CKSUM 1  | 
    ||
49  | 
    #define STYLE_TERSE 2  | 
    ||
50  | 
    |||
51  | 
    #define MAX_DIGEST_LEN 128  | 
    ||
52  | 
    |||
53  | 
    #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))  | 
    ||
54  | 
    #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))  | 
    ||
55  | 
    |||
56  | 
    union ANY_CTX { | 
    ||
57  | 
    #if !defined(SHA2_ONLY)  | 
    ||
58  | 
    CKSUM_CTX cksum;  | 
    ||
59  | 
    MD5_CTX md5;  | 
    ||
60  | 
    RMD160_CTX rmd160;  | 
    ||
61  | 
    SHA1_CTX sha1;  | 
    ||
62  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
63  | 
    SHA2_CTX sha2;  | 
    ||
64  | 
    };  | 
    ||
65  | 
    |||
66  | 
    struct hash_function { | 
    ||
67  | 
    const char *name;  | 
    ||
68  | 
    size_t digestlen;  | 
    ||
69  | 
    int style;  | 
    ||
70  | 
    int base64;  | 
    ||
71  | 
    void *ctx; /* XXX - only used by digest_file() */  | 
    ||
72  | 
    void (*init)(void *);  | 
    ||
73  | 
    void (*update)(void *, const unsigned char *, size_t);  | 
    ||
74  | 
    void (*final)(unsigned char *, void *);  | 
    ||
75  | 
    char * (*end)(void *, char *);  | 
    ||
76  | 
    TAILQ_ENTRY(hash_function) tailq;  | 
    ||
77  | 
    } functions[] = { | 
    ||
78  | 
    #if !defined(SHA2_ONLY)  | 
    ||
79  | 
    	{ | 
    ||
80  | 
    "CKSUM",  | 
    ||
81  | 
    CKSUM_DIGEST_LENGTH,  | 
    ||
82  | 
    STYLE_CKSUM,  | 
    ||
83  | 
    -1,  | 
    ||
84  | 
    NULL,  | 
    ||
85  | 
    (void (*)(void *))CKSUM_Init,  | 
    ||
86  | 
    (void (*)(void *, const unsigned char *, size_t))CKSUM_Update,  | 
    ||
87  | 
    (void (*)(unsigned char *, void *))CKSUM_Final,  | 
    ||
88  | 
    (char *(*)(void *, char *))CKSUM_End  | 
    ||
89  | 
    },  | 
    ||
90  | 
    	{ | 
    ||
91  | 
    "MD5",  | 
    ||
92  | 
    MD5_DIGEST_LENGTH,  | 
    ||
93  | 
    STYLE_MD5,  | 
    ||
94  | 
    0,  | 
    ||
95  | 
    NULL,  | 
    ||
96  | 
    (void (*)(void *))MD5Init,  | 
    ||
97  | 
    (void (*)(void *, const unsigned char *, size_t))MD5Update,  | 
    ||
98  | 
    (void (*)(unsigned char *, void *))MD5Final,  | 
    ||
99  | 
    (char *(*)(void *, char *))MD5End  | 
    ||
100  | 
    },  | 
    ||
101  | 
    	{ | 
    ||
102  | 
    "RMD160",  | 
    ||
103  | 
    RMD160_DIGEST_LENGTH,  | 
    ||
104  | 
    STYLE_MD5,  | 
    ||
105  | 
    0,  | 
    ||
106  | 
    NULL,  | 
    ||
107  | 
    (void (*)(void *))RMD160Init,  | 
    ||
108  | 
    (void (*)(void *, const unsigned char *, size_t))RMD160Update,  | 
    ||
109  | 
    (void (*)(unsigned char *, void *))RMD160Final,  | 
    ||
110  | 
    (char *(*)(void *, char *))RMD160End  | 
    ||
111  | 
    },  | 
    ||
112  | 
    	{ | 
    ||
113  | 
    "SHA1",  | 
    ||
114  | 
    SHA1_DIGEST_LENGTH,  | 
    ||
115  | 
    STYLE_MD5,  | 
    ||
116  | 
    0,  | 
    ||
117  | 
    NULL,  | 
    ||
118  | 
    (void (*)(void *))SHA1Init,  | 
    ||
119  | 
    (void (*)(void *, const unsigned char *, size_t))SHA1Update,  | 
    ||
120  | 
    (void (*)(unsigned char *, void *))SHA1Final,  | 
    ||
121  | 
    (char *(*)(void *, char *))SHA1End  | 
    ||
122  | 
    },  | 
    ||
123  | 
    	{ | 
    ||
124  | 
    "SHA224",  | 
    ||
125  | 
    SHA224_DIGEST_LENGTH,  | 
    ||
126  | 
    STYLE_MD5,  | 
    ||
127  | 
    0,  | 
    ||
128  | 
    NULL,  | 
    ||
129  | 
    (void (*)(void *))SHA224Init,  | 
    ||
130  | 
    (void (*)(void *, const unsigned char *, size_t))SHA224Update,  | 
    ||
131  | 
    (void (*)(unsigned char *, void *))SHA224Final,  | 
    ||
132  | 
    (char *(*)(void *, char *))SHA224End  | 
    ||
133  | 
    },  | 
    ||
134  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
135  | 
    	{ | 
    ||
136  | 
    "SHA256",  | 
    ||
137  | 
    SHA256_DIGEST_LENGTH,  | 
    ||
138  | 
    STYLE_MD5,  | 
    ||
139  | 
    0,  | 
    ||
140  | 
    NULL,  | 
    ||
141  | 
    (void (*)(void *))SHA256Init,  | 
    ||
142  | 
    (void (*)(void *, const unsigned char *, size_t))SHA256Update,  | 
    ||
143  | 
    (void (*)(unsigned char *, void *))SHA256Final,  | 
    ||
144  | 
    (char *(*)(void *, char *))SHA256End  | 
    ||
145  | 
    },  | 
    ||
146  | 
    #if !defined(SHA2_ONLY)  | 
    ||
147  | 
    	{ | 
    ||
148  | 
    "SHA384",  | 
    ||
149  | 
    SHA384_DIGEST_LENGTH,  | 
    ||
150  | 
    STYLE_MD5,  | 
    ||
151  | 
    0,  | 
    ||
152  | 
    NULL,  | 
    ||
153  | 
    (void (*)(void *))SHA384Init,  | 
    ||
154  | 
    (void (*)(void *, const unsigned char *, size_t))SHA384Update,  | 
    ||
155  | 
    (void (*)(unsigned char *, void *))SHA384Final,  | 
    ||
156  | 
    (char *(*)(void *, char *))SHA384End  | 
    ||
157  | 
    },  | 
    ||
158  | 
    	{ | 
    ||
159  | 
    "SHA512/256",  | 
    ||
160  | 
    SHA512_256_DIGEST_LENGTH,  | 
    ||
161  | 
    STYLE_MD5,  | 
    ||
162  | 
    0,  | 
    ||
163  | 
    NULL,  | 
    ||
164  | 
    (void (*)(void *))SHA512_256Init,  | 
    ||
165  | 
    (void (*)(void *, const unsigned char *, size_t))SHA512_256Update,  | 
    ||
166  | 
    (void (*)(unsigned char *, void *))SHA512_256Final,  | 
    ||
167  | 
    (char *(*)(void *, char *))SHA512_256End  | 
    ||
168  | 
    },  | 
    ||
169  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
170  | 
    	{ | 
    ||
171  | 
    "SHA512",  | 
    ||
172  | 
    SHA512_DIGEST_LENGTH,  | 
    ||
173  | 
    STYLE_MD5,  | 
    ||
174  | 
    0,  | 
    ||
175  | 
    NULL,  | 
    ||
176  | 
    (void (*)(void *))SHA512Init,  | 
    ||
177  | 
    (void (*)(void *, const unsigned char *, size_t))SHA512Update,  | 
    ||
178  | 
    (void (*)(unsigned char *, void *))SHA512Final,  | 
    ||
179  | 
    (char *(*)(void *, char *))SHA512End  | 
    ||
180  | 
    },  | 
    ||
181  | 
    	{ | 
    ||
182  | 
    NULL,  | 
    ||
183  | 
    }  | 
    ||
184  | 
    };  | 
    ||
185  | 
    |||
186  | 
    TAILQ_HEAD(hash_list, hash_function);  | 
    ||
187  | 
    |||
188  | 
    void digest_end(const struct hash_function *, void *, char *, size_t, int);  | 
    ||
189  | 
    int digest_file(const char *, struct hash_list *, int);  | 
    ||
190  | 
    void digest_print(const struct hash_function *, const char *, const char *);  | 
    ||
191  | 
    #if !defined(SHA2_ONLY)  | 
    ||
192  | 
    int digest_filelist(const char *, struct hash_function *, int, char **);  | 
    ||
193  | 
    void digest_printstr(const struct hash_function *, const char *, const char *);  | 
    ||
194  | 
    void digest_string(char *, struct hash_list *);  | 
    ||
195  | 
    void digest_test(struct hash_list *);  | 
    ||
196  | 
    void digest_time(struct hash_list *, int);  | 
    ||
197  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
198  | 
    void hash_insert(struct hash_list *, struct hash_function *, int);  | 
    ||
199  | 
    void usage(void) __attribute__((__noreturn__));  | 
    ||
200  | 
    |||
201  | 
    extern char *__progname;  | 
    ||
202  | 
    int qflag = 0;  | 
    ||
203  | 
    FILE *ofile = NULL;  | 
    ||
204  | 
    |||
205  | 
    int  | 
    ||
206  | 
    main(int argc, char **argv)  | 
    ||
207  | 
    { | 
    ||
208  | 
    struct hash_function *hf, *hftmp;  | 
    ||
209  | 
    564  | 
    struct hash_list hl;  | 
    |
210  | 
    size_t len;  | 
    ||
211  | 
    char *cp, *input_string, *selective_checklist;  | 
    ||
212  | 
    const char *optstr;  | 
    ||
213  | 
    int fl, error, base64;  | 
    ||
214  | 
    int bflag, cflag, pflag, rflag, tflag, xflag;  | 
    ||
215  | 
    |||
216  | 
    ✗✓ | 282  | 
    	if (pledge("stdio rpath wpath cpath flock", NULL) == -1) | 
    
217  | 
    err(1, "pledge");  | 
    ||
218  | 
    |||
219  | 
    282  | 
    TAILQ_INIT(&hl);  | 
    |
220  | 
    input_string = NULL;  | 
    ||
221  | 
    selective_checklist = NULL;  | 
    ||
222  | 
    282  | 
    error = bflag = cflag = pflag = qflag = rflag = tflag = xflag = 0;  | 
    |
223  | 
    |||
224  | 
    #if !defined(SHA2_ONLY)  | 
    ||
225  | 
    ✓✓ | 282  | 
    if (strcmp(__progname, "cksum") == 0)  | 
    
226  | 
    69  | 
    optstr = "a:bC:ch:pqrs:tx";  | 
    |
227  | 
    else  | 
    ||
228  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
229  | 
    optstr = "bC:ch:pqrs:tx";  | 
    ||
230  | 
    |||
231  | 
    /* Check for -b option early since it changes behavior. */  | 
    ||
232  | 
    ✓✓ | 573  | 
    	while ((fl = getopt(argc, argv, optstr)) != -1) { | 
    
233  | 
    ✓✗✗ | 291  | 
    		switch (fl) { | 
    
234  | 
    case 'b':  | 
    ||
235  | 
    bflag = 1;  | 
    ||
236  | 
    break;  | 
    ||
237  | 
    case '?':  | 
    ||
238  | 
    usage();  | 
    ||
239  | 
    }  | 
    ||
240  | 
    }  | 
    ||
241  | 
    282  | 
    optind = 1;  | 
    |
242  | 
    282  | 
    optreset = 1;  | 
    |
243  | 
    ✓✓ | 855  | 
    	while ((fl = getopt(argc, argv, optstr)) != -1) { | 
    
244  | 
    ✓✓✗✗ ✗✓✓✗ ✓✗✓✗  | 
    628  | 
    		switch (fl) { | 
    
245  | 
    case 'a':  | 
    ||
246  | 
    ✓✓ | 92  | 
    			while ((cp = strsep(&optarg, " \t,")) != NULL) { | 
    
247  | 
    ✗✓ | 46  | 
    if (*cp == '\0')  | 
    
248  | 
    continue;  | 
    ||
249  | 
    base64 = -1;  | 
    ||
250  | 
    ✓✗ | 552  | 
    				for (hf = functions; hf->name != NULL; hf++) { | 
    
251  | 
    276  | 
    len = strlen(hf->name);  | 
    |
252  | 
    ✓✓ | 276  | 
    if (strncasecmp(cp, hf->name, len) != 0)  | 
    
253  | 
    continue;  | 
    ||
254  | 
    ✓✗ | 46  | 
    					if (cp[len] == '\0') { | 
    
255  | 
    ✓✗ | 46  | 
    if (hf->base64 != -1)  | 
    
256  | 
    46  | 
    base64 = bflag;  | 
    |
257  | 
    break; /* exact match */  | 
    ||
258  | 
    }  | 
    ||
259  | 
    if (cp[len + 1] == '\0' &&  | 
    ||
260  | 
    					    (cp[len] == 'b' || cp[len] == 'x')) { | 
    ||
261  | 
    base64 =  | 
    ||
262  | 
    cp[len] == 'b' ? 1 : 0;  | 
    ||
263  | 
    break; /* match w/ suffix */  | 
    ||
264  | 
    }  | 
    ||
265  | 
    }  | 
    ||
266  | 
    ✗✓ | 46  | 
    				if (hf->name == NULL) { | 
    
267  | 
    					warnx("unknown algorithm \"%s\"", cp); | 
    ||
268  | 
    usage();  | 
    ||
269  | 
    }  | 
    ||
270  | 
    ✗✓ | 46  | 
    				if (hf->base64 == -1 && base64 != -1) { | 
    
271  | 
    					warnx("%s doesn't support %s", | 
    ||
272  | 
    hf->name,  | 
    ||
273  | 
    base64 ? "base64" : "hex");  | 
    ||
274  | 
    usage();  | 
    ||
275  | 
    }  | 
    ||
276  | 
    /* Check for dupes. */  | 
    ||
277  | 
    ✗✓ | 92  | 
    				TAILQ_FOREACH(hftmp, &hl, tailq) { | 
    
278  | 
    if (hftmp->base64 == base64 &&  | 
    ||
279  | 
    strcmp(hf->name, hftmp->name) == 0)  | 
    ||
280  | 
    break;  | 
    ||
281  | 
    }  | 
    ||
282  | 
    ✗✓ | 46  | 
    if (hftmp == NULL)  | 
    
283  | 
    46  | 
    hash_insert(&hl, hf, base64);  | 
    |
284  | 
    }  | 
    ||
285  | 
    break;  | 
    ||
286  | 
    case 'b':  | 
    ||
287  | 
    /* has already been parsed */  | 
    ||
288  | 
    break;  | 
    ||
289  | 
    case 'h':  | 
    ||
290  | 
    ofile = fopen(optarg, "w");  | 
    ||
291  | 
    if (ofile == NULL)  | 
    ||
292  | 
    err(1, "%s", optarg);  | 
    ||
293  | 
    break;  | 
    ||
294  | 
    #if !defined(SHA2_ONLY)  | 
    ||
295  | 
    case 'C':  | 
    ||
296  | 
    selective_checklist = optarg;  | 
    ||
297  | 
    break;  | 
    ||
298  | 
    case 'c':  | 
    ||
299  | 
    cflag = 1;  | 
    ||
300  | 
    break;  | 
    ||
301  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
302  | 
    case 'p':  | 
    ||
303  | 
    pflag = 1;  | 
    ||
304  | 
    46  | 
    break;  | 
    |
305  | 
    case 'q':  | 
    ||
306  | 
    15  | 
    qflag = 1;  | 
    |
307  | 
    15  | 
    break;  | 
    |
308  | 
    case 'r':  | 
    ||
309  | 
    rflag = 1;  | 
    ||
310  | 
    break;  | 
    ||
311  | 
    case 's':  | 
    ||
312  | 
    23  | 
    input_string = optarg;  | 
    |
313  | 
    23  | 
    break;  | 
    |
314  | 
    case 't':  | 
    ||
315  | 
    tflag++;  | 
    ||
316  | 
    break;  | 
    ||
317  | 
    case 'x':  | 
    ||
318  | 
    xflag = 1;  | 
    ||
319  | 
    161  | 
    break;  | 
    |
320  | 
    default:  | 
    ||
321  | 
    usage();  | 
    ||
322  | 
    }  | 
    ||
323  | 
    }  | 
    ||
324  | 
    282  | 
    argc -= optind;  | 
    |
325  | 
    282  | 
    argv += optind;  | 
    |
326  | 
    |||
327  | 
    ✓✗ | 282  | 
    if (ofile == NULL)  | 
    
328  | 
    282  | 
    ofile = stdout;  | 
    |
329  | 
    |||
330  | 
    ✗✓ | 282  | 
    	if (pledge("stdio rpath flock cpath wpath", NULL) == -1) | 
    
331  | 
    err(1, "pledge");  | 
    ||
332  | 
    |||
333  | 
    /* Most arguments are mutually exclusive */  | 
    ||
334  | 
    282  | 
    fl = pflag + (tflag ? 1 : 0) + xflag + cflag + (input_string != NULL);  | 
    |
335  | 
    ✓✗✓✓ ✓✗  | 
    800  | 
    if (fl > 1 || (fl && argc && cflag == 0) || (rflag && qflag) ||  | 
    
336  | 
    ✗✓ | 236  | 
    (selective_checklist != NULL && argc == 0))  | 
    
337  | 
    usage();  | 
    ||
338  | 
    ✗✓ | 236  | 
    	if (selective_checklist || cflag) { | 
    
339  | 
    if (TAILQ_FIRST(&hl) != TAILQ_LAST(&hl, hash_list))  | 
    ||
340  | 
    errx(1, "only a single algorithm may be specified "  | 
    ||
341  | 
    "in -C or -c mode");  | 
    ||
342  | 
    }  | 
    ||
343  | 
    |||
344  | 
    /* No algorithm specified, check the name we were called as. */  | 
    ||
345  | 
    ✓✓ | 236  | 
    	if (TAILQ_EMPTY(&hl)) { | 
    
346  | 
    ✓✗ | 1466  | 
    		for (hf = functions; hf->name != NULL; hf++) { | 
    
347  | 
    ✓✓ | 733  | 
    if (strcasecmp(hf->name, __progname) == 0)  | 
    
348  | 
    break;  | 
    ||
349  | 
    }  | 
    ||
350  | 
    ✗✓ | 190  | 
    if (hf->name == NULL)  | 
    
351  | 
    hf = &functions[0]; /* default to cksum */  | 
    ||
352  | 
    190  | 
    hash_insert(&hl, hf, (hf->base64 == -1 ? 0 : bflag));  | 
    |
353  | 
    190  | 
    }  | 
    |
354  | 
    |||
355  | 
    ✓✓ | 236  | 
    	if (rflag || qflag) { | 
    
356  | 
    15  | 
    const int new_style = rflag ? STYLE_CKSUM : STYLE_TERSE;  | 
    |
357  | 
    ✓✓ | 60  | 
    		TAILQ_FOREACH(hf, &hl, tailq) { | 
    
358  | 
    15  | 
    hf->style = new_style;  | 
    |
359  | 
    }  | 
    ||
360  | 
    15  | 
    }  | 
    |
361  | 
    |||
362  | 
    #if !defined(SHA2_ONLY)  | 
    ||
363  | 
    ✗✓ | 236  | 
    if (tflag)  | 
    
364  | 
    digest_time(&hl, tflag);  | 
    ||
365  | 
    ✓✓ | 236  | 
    else if (xflag)  | 
    
366  | 
    161  | 
    digest_test(&hl);  | 
    |
367  | 
    ✗✓ | 75  | 
    else if (input_string)  | 
    
368  | 
    digest_string(input_string, &hl);  | 
    ||
369  | 
    ✗✓ | 75  | 
    	else if (selective_checklist) { | 
    
370  | 
    int i;  | 
    ||
371  | 
    |||
372  | 
    error = digest_filelist(selective_checklist, TAILQ_FIRST(&hl),  | 
    ||
373  | 
    argc, argv);  | 
    ||
374  | 
    		for (i = 0; i < argc; i++) { | 
    ||
375  | 
    			if (argv[i] != NULL) { | 
    ||
376  | 
    				warnx("%s does not exist in %s", argv[i], | 
    ||
377  | 
    selective_checklist);  | 
    ||
378  | 
    error++;  | 
    ||
379  | 
    }  | 
    ||
380  | 
    }  | 
    ||
381  | 
    ✗✓ | 75  | 
    	} else if (cflag) { | 
    
382  | 
    if (argc == 0)  | 
    ||
383  | 
    			error = digest_filelist("-", TAILQ_FIRST(&hl), 0, NULL); | 
    ||
384  | 
    else  | 
    ||
385  | 
    while (argc--)  | 
    ||
386  | 
    error += digest_filelist(*argv++,  | 
    ||
387  | 
    TAILQ_FIRST(&hl), 0, NULL);  | 
    ||
388  | 
    } else  | 
    ||
389  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
390  | 
    ✓✓ | 75  | 
    if (pflag || argc == 0)  | 
    
391  | 
    23  | 
    		error = digest_file("-", &hl, pflag); | 
    |
392  | 
    else  | 
    ||
393  | 
    ✓✓ | 230  | 
    while (argc--)  | 
    
394  | 
    89  | 
    error += digest_file(*argv++, &hl, 0);  | 
    |
395  | 
    |||
396  | 
    472  | 
    return(error ? EXIT_FAILURE : EXIT_SUCCESS);  | 
    |
397  | 
    236  | 
    }  | 
    |
398  | 
    |||
399  | 
    void  | 
    ||
400  | 
    hash_insert(struct hash_list *hl, struct hash_function *hf, int base64)  | 
    ||
401  | 
    { | 
    ||
402  | 
    struct hash_function *hftmp;  | 
    ||
403  | 
    |||
404  | 
    472  | 
    hftmp = malloc(sizeof(*hftmp));  | 
    |
405  | 
    ✗✓ | 236  | 
    if (hftmp == NULL)  | 
    
406  | 
    err(1, NULL);  | 
    ||
407  | 
    236  | 
    *hftmp = *hf;  | 
    |
408  | 
    236  | 
    hftmp->base64 = base64;  | 
    |
409  | 
    236  | 
    TAILQ_INSERT_TAIL(hl, hftmp, tailq);  | 
    |
410  | 
    236  | 
    }  | 
    |
411  | 
    |||
412  | 
    void  | 
    ||
413  | 
    digest_end(const struct hash_function *hf, void *ctx, char *buf, size_t bsize,  | 
    ||
414  | 
    int base64)  | 
    ||
415  | 
    { | 
    ||
416  | 
    u_char *digest;  | 
    ||
417  | 
    |||
418  | 
    ✗✓ | 3122  | 
    	if (base64 == 1) { | 
    
419  | 
    if ((digest = malloc(hf->digestlen)) == NULL)  | 
    ||
420  | 
    err(1, NULL);  | 
    ||
421  | 
    hf->final(digest, ctx);  | 
    ||
422  | 
    if (b64_ntop(digest, hf->digestlen, buf, bsize) == -1)  | 
    ||
423  | 
    errx(1, "error encoding base64");  | 
    ||
424  | 
    freezero(digest, hf->digestlen);  | 
    ||
425  | 
    	} else { | 
    ||
426  | 
    1561  | 
    hf->end(ctx, buf);  | 
    |
427  | 
    }  | 
    ||
428  | 
    1561  | 
    }  | 
    |
429  | 
    |||
430  | 
    #if !defined(SHA2_ONLY)  | 
    ||
431  | 
    void  | 
    ||
432  | 
    digest_string(char *string, struct hash_list *hl)  | 
    ||
433  | 
    { | 
    ||
434  | 
    struct hash_function *hf;  | 
    ||
435  | 
    char digest[MAX_DIGEST_LEN + 1];  | 
    ||
436  | 
    union ANY_CTX context;  | 
    ||
437  | 
    |||
438  | 
    	TAILQ_FOREACH(hf, hl, tailq) { | 
    ||
439  | 
    hf->init(&context);  | 
    ||
440  | 
    hf->update(&context, string, strlen(string));  | 
    ||
441  | 
    digest_end(hf, &context, digest, sizeof(digest),  | 
    ||
442  | 
    hf->base64);  | 
    ||
443  | 
    digest_printstr(hf, string, digest);  | 
    ||
444  | 
    }  | 
    ||
445  | 
    }  | 
    ||
446  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
447  | 
    |||
448  | 
    void  | 
    ||
449  | 
    digest_print(const struct hash_function *hf, const char *what,  | 
    ||
450  | 
    const char *digest)  | 
    ||
451  | 
    { | 
    ||
452  | 
    ✓✓✓✓ | 
    750  | 
    	switch (hf->style) { | 
    
453  | 
    case STYLE_MD5:  | 
    ||
454  | 
    212  | 
    (void)fprintf(ofile, "%s (%s) = %s\n", hf->name, what, digest);  | 
    |
455  | 
    212  | 
    break;  | 
    |
456  | 
    case STYLE_CKSUM:  | 
    ||
457  | 
    23  | 
    (void)fprintf(ofile, "%s %s\n", digest, what);  | 
    |
458  | 
    23  | 
    break;  | 
    |
459  | 
    case STYLE_TERSE:  | 
    ||
460  | 
    15  | 
    (void)fprintf(ofile, "%s\n", digest);  | 
    |
461  | 
    15  | 
    break;  | 
    |
462  | 
    }  | 
    ||
463  | 
    250  | 
    }  | 
    |
464  | 
    |||
465  | 
    #if !defined(SHA2_ONLY)  | 
    ||
466  | 
    void  | 
    ||
467  | 
    digest_printstr(const struct hash_function *hf, const char *what,  | 
    ||
468  | 
    const char *digest)  | 
    ||
469  | 
    { | 
    ||
470  | 
    ✓✓✗✓ | 
    3864  | 
    	switch (hf->style) { | 
    
471  | 
    case STYLE_MD5:  | 
    ||
472  | 
    1104  | 
    (void)fprintf(ofile, "%s (\"%s\") = %s\n", hf->name, what, digest);  | 
    |
473  | 
    1104  | 
    break;  | 
    |
474  | 
    case STYLE_CKSUM:  | 
    ||
475  | 
    184  | 
    (void)fprintf(ofile, "%s %s\n", digest, what);  | 
    |
476  | 
    184  | 
    break;  | 
    |
477  | 
    case STYLE_TERSE:  | 
    ||
478  | 
    (void)fprintf(ofile, "%s\n", digest);  | 
    ||
479  | 
    break;  | 
    ||
480  | 
    }  | 
    ||
481  | 
    1288  | 
    }  | 
    |
482  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
483  | 
    |||
484  | 
    int  | 
    ||
485  | 
    digest_file(const char *file, struct hash_list *hl, int echo)  | 
    ||
486  | 
    { | 
    ||
487  | 
    struct hash_function *hf;  | 
    ||
488  | 
    FILE *fp;  | 
    ||
489  | 
    size_t nread;  | 
    ||
490  | 
    224  | 
    u_char data[32 * 1024];  | 
    |
491  | 
    112  | 
    char digest[MAX_DIGEST_LEN + 1];  | 
    |
492  | 
    |||
493  | 
    ✓✓ | 112  | 
    if (strcmp(file, "-") == 0)  | 
    
494  | 
    23  | 
    fp = stdin;  | 
    |
495  | 
    ✗✓ | 89  | 
    	else if ((fp = fopen(file, "r")) == NULL) { | 
    
496  | 
    		warn("cannot open %s", file); | 
    ||
497  | 
    return(1);  | 
    ||
498  | 
    }  | 
    ||
499  | 
    |||
500  | 
    ✓✓ | 448  | 
    	TAILQ_FOREACH(hf, hl, tailq) { | 
    
501  | 
    ✗✓ | 112  | 
    if ((hf->ctx = malloc(sizeof(union ANY_CTX))) == NULL)  | 
    
502  | 
    err(1, NULL);  | 
    ||
503  | 
    112  | 
    hf->init(hf->ctx);  | 
    |
504  | 
    }  | 
    ||
505  | 
    ✓✓ | 164168  | 
    	while ((nread = fread(data, 1UL, sizeof(data), fp)) != 0) { | 
    
506  | 
    ✓✓ | 164056  | 
    		if (echo) { | 
    
507  | 
    23  | 
    (void)fwrite(data, nread, 1UL, stdout);  | 
    |
508  | 
    ✗✓ | 23  | 
    if (fflush(stdout) != 0)  | 
    
509  | 
    err(1, "stdout: write error");  | 
    ||
510  | 
    }  | 
    ||
511  | 
    ✓✓ | 656224  | 
    TAILQ_FOREACH(hf, hl, tailq)  | 
    
512  | 
    164056  | 
    hf->update(hf->ctx, data, nread);  | 
    |
513  | 
    }  | 
    ||
514  | 
    ✓✗✗✓ ✗✗  | 
    224  | 
    	if (ferror(fp)) { | 
    
515  | 
    		warn("%s: read error", file); | 
    ||
516  | 
    if (fp != stdin)  | 
    ||
517  | 
    fclose(fp);  | 
    ||
518  | 
    		TAILQ_FOREACH(hf, hl, tailq) { | 
    ||
519  | 
    free(hf->ctx);  | 
    ||
520  | 
    hf->ctx = NULL;  | 
    ||
521  | 
    }  | 
    ||
522  | 
    return(1);  | 
    ||
523  | 
    }  | 
    ||
524  | 
    ✓✓ | 112  | 
    if (fp != stdin)  | 
    
525  | 
    89  | 
    fclose(fp);  | 
    |
526  | 
    ✓✓ | 448  | 
    	TAILQ_FOREACH(hf, hl, tailq) { | 
    
527  | 
    112  | 
    digest_end(hf, hf->ctx, digest, sizeof(digest), hf->base64);  | 
    |
528  | 
    112  | 
    free(hf->ctx);  | 
    |
529  | 
    112  | 
    hf->ctx = NULL;  | 
    |
530  | 
    ✓✓ | 112  | 
    if (fp == stdin)  | 
    
531  | 
    23  | 
    fprintf(ofile, "%s\n", digest);  | 
    |
532  | 
    else  | 
    ||
533  | 
    89  | 
    digest_print(hf, file, digest);  | 
    |
534  | 
    }  | 
    ||
535  | 
    112  | 
    return(0);  | 
    |
536  | 
    112  | 
    }  | 
    |
537  | 
    |||
538  | 
    #if !defined(SHA2_ONLY)  | 
    ||
539  | 
    /*  | 
    ||
540  | 
    * Parse through the input file looking for valid lines.  | 
    ||
541  | 
    * If one is found, use this checksum and file as a reference and  | 
    ||
542  | 
    * generate a new checksum against the file on the filesystem.  | 
    ||
543  | 
    * Print out the result of each comparison.  | 
    ||
544  | 
    */  | 
    ||
545  | 
    int  | 
    ||
546  | 
    digest_filelist(const char *file, struct hash_function *defhash, int selcount,  | 
    ||
547  | 
    char **sel)  | 
    ||
548  | 
    { | 
    ||
549  | 
    int found, base64, error, cmp, i;  | 
    ||
550  | 
    size_t algorithm_max, algorithm_min;  | 
    ||
551  | 
    const char *algorithm;  | 
    ||
552  | 
    char *filename, *checksum, *buf, *p;  | 
    ||
553  | 
    char digest[MAX_DIGEST_LEN + 1];  | 
    ||
554  | 
    char *lbuf = NULL;  | 
    ||
555  | 
    FILE *listfp, *fp;  | 
    ||
556  | 
    size_t len, nread;  | 
    ||
557  | 
    int *sel_found = NULL;  | 
    ||
558  | 
    u_char data[32 * 1024];  | 
    ||
559  | 
    union ANY_CTX context;  | 
    ||
560  | 
    struct hash_function *hf;  | 
    ||
561  | 
    |||
562  | 
    	if (strcmp(file, "-") == 0) { | 
    ||
563  | 
    listfp = stdin;  | 
    ||
564  | 
    	} else if ((listfp = fopen(file, "r")) == NULL) { | 
    ||
565  | 
    		warn("cannot open %s", file); | 
    ||
566  | 
    return(1);  | 
    ||
567  | 
    }  | 
    ||
568  | 
    |||
569  | 
    	if (sel != NULL) { | 
    ||
570  | 
    sel_found = calloc((size_t)selcount, sizeof(*sel_found));  | 
    ||
571  | 
    if (sel_found == NULL)  | 
    ||
572  | 
    err(1, NULL);  | 
    ||
573  | 
    }  | 
    ||
574  | 
    |||
575  | 
    algorithm_max = algorithm_min = strlen(functions[0].name);  | 
    ||
576  | 
    	for (hf = &functions[1]; hf->name != NULL; hf++) { | 
    ||
577  | 
    len = strlen(hf->name);  | 
    ||
578  | 
    algorithm_max = MAXIMUM(algorithm_max, len);  | 
    ||
579  | 
    algorithm_min = MINIMUM(algorithm_min, len);  | 
    ||
580  | 
    }  | 
    ||
581  | 
    |||
582  | 
    error = found = 0;  | 
    ||
583  | 
    	while ((buf = fgetln(listfp, &len))) { | 
    ||
584  | 
    base64 = 0;  | 
    ||
585  | 
    if (buf[len - 1] == '\n')  | 
    ||
586  | 
    buf[len - 1] = '\0';  | 
    ||
587  | 
    		else { | 
    ||
588  | 
    if ((lbuf = malloc(len + 1)) == NULL)  | 
    ||
589  | 
    err(1, NULL);  | 
    ||
590  | 
    |||
591  | 
    (void)memcpy(lbuf, buf, len);  | 
    ||
592  | 
    lbuf[len] = '\0';  | 
    ||
593  | 
    buf = lbuf;  | 
    ||
594  | 
    }  | 
    ||
595  | 
    while (isspace((unsigned char)*buf))  | 
    ||
596  | 
    buf++;  | 
    ||
597  | 
    |||
598  | 
    /*  | 
    ||
599  | 
    * Crack the line into an algorithm, filename, and checksum.  | 
    ||
600  | 
    * Lines are of the form:  | 
    ||
601  | 
    * ALGORITHM (FILENAME) = CHECKSUM  | 
    ||
602  | 
    *  | 
    ||
603  | 
    * Fallback on GNU form:  | 
    ||
604  | 
    * CHECKSUM FILENAME  | 
    ||
605  | 
    */  | 
    ||
606  | 
    p = strchr(buf, ' ');  | 
    ||
607  | 
    		if (p != NULL && *(p + 1) == '(') { | 
    ||
608  | 
    /* BSD form */  | 
    ||
609  | 
    *p = '\0';  | 
    ||
610  | 
    algorithm = buf;  | 
    ||
611  | 
    len = strlen(algorithm);  | 
    ||
612  | 
    if (len > algorithm_max || len < algorithm_min)  | 
    ||
613  | 
    continue;  | 
    ||
614  | 
    |||
615  | 
    filename = p + 2;  | 
    ||
616  | 
    p = strrchr(filename, ')');  | 
    ||
617  | 
    if (p == NULL || strncmp(p + 1, " = ", (size_t)3) != 0)  | 
    ||
618  | 
    continue;  | 
    ||
619  | 
    *p = '\0';  | 
    ||
620  | 
    |||
621  | 
    checksum = p + 4;  | 
    ||
622  | 
    p = strpbrk(checksum, " \t\r");  | 
    ||
623  | 
    if (p != NULL)  | 
    ||
624  | 
    *p = '\0';  | 
    ||
625  | 
    |||
626  | 
    /*  | 
    ||
627  | 
    * Check that the algorithm is one we recognize.  | 
    ||
628  | 
    */  | 
    ||
629  | 
    			for (hf = functions; hf->name != NULL; hf++) { | 
    ||
630  | 
    if (strcasecmp(algorithm, hf->name) == 0)  | 
    ||
631  | 
    break;  | 
    ||
632  | 
    }  | 
    ||
633  | 
    if (hf->name == NULL || *checksum == '\0')  | 
    ||
634  | 
    continue;  | 
    ||
635  | 
    /*  | 
    ||
636  | 
    * Check the length to see if this could be  | 
    ||
637  | 
    * a valid checksum. If hex, it will be 2x the  | 
    ||
638  | 
    * size of the binary data. For base64, we have  | 
    ||
639  | 
    * to check both with and without the '=' padding.  | 
    ||
640  | 
    */  | 
    ||
641  | 
    len = strlen(checksum);  | 
    ||
642  | 
    			if (len != hf->digestlen * 2) { | 
    ||
643  | 
    size_t len2;  | 
    ||
644  | 
    |||
645  | 
    				if (checksum[len - 1] == '=') { | 
    ||
646  | 
    /* use padding */  | 
    ||
647  | 
    len2 = 4 * ((hf->digestlen + 2) / 3);  | 
    ||
648  | 
    				} else { | 
    ||
649  | 
    /* no padding */  | 
    ||
650  | 
    len2 = (4 * hf->digestlen + 2) / 3;  | 
    ||
651  | 
    }  | 
    ||
652  | 
    if (len != len2)  | 
    ||
653  | 
    continue;  | 
    ||
654  | 
    base64 = 1;  | 
    ||
655  | 
    }  | 
    ||
656  | 
    		} else { | 
    ||
657  | 
    /* could be GNU form */  | 
    ||
658  | 
    if ((hf = defhash) == NULL)  | 
    ||
659  | 
    continue;  | 
    ||
660  | 
    algorithm = hf->name;  | 
    ||
661  | 
    checksum = buf;  | 
    ||
662  | 
    if ((p = strchr(checksum, ' ')) == NULL)  | 
    ||
663  | 
    continue;  | 
    ||
664  | 
    			if (hf->style == STYLE_CKSUM) { | 
    ||
665  | 
    if ((p = strchr(p + 1, ' ')) == NULL)  | 
    ||
666  | 
    continue;  | 
    ||
667  | 
    }  | 
    ||
668  | 
    *p++ = '\0';  | 
    ||
669  | 
    while (isspace((unsigned char)*p))  | 
    ||
670  | 
    p++;  | 
    ||
671  | 
    if (*p == '\0')  | 
    ||
672  | 
    continue;  | 
    ||
673  | 
    filename = p;  | 
    ||
674  | 
    p = strpbrk(filename, "\t\r");  | 
    ||
675  | 
    if (p != NULL)  | 
    ||
676  | 
    *p = '\0';  | 
    ||
677  | 
    }  | 
    ||
678  | 
    found = 1;  | 
    ||
679  | 
    |||
680  | 
    /*  | 
    ||
681  | 
    * If only a selection of files is wanted, proceed only  | 
    ||
682  | 
    * if the filename matches one of those in the selection.  | 
    ||
683  | 
    */  | 
    ||
684  | 
    		if (sel != NULL) { | 
    ||
685  | 
    			for (i = 0; i < selcount; i++) { | 
    ||
686  | 
    				if (strcmp(sel[i], filename) == 0) { | 
    ||
687  | 
    sel_found[i] = 1;  | 
    ||
688  | 
    break;  | 
    ||
689  | 
    }  | 
    ||
690  | 
    }  | 
    ||
691  | 
    if (i == selcount)  | 
    ||
692  | 
    continue;  | 
    ||
693  | 
    }  | 
    ||
694  | 
    |||
695  | 
    		if ((fp = fopen(filename, "r")) == NULL) { | 
    ||
696  | 
    			warn("cannot open %s", filename); | 
    ||
697  | 
    			(void)printf("(%s) %s: %s\n", algorithm, filename, | 
    ||
698  | 
    (errno == ENOENT ? "MISSING" : "FAILED"));  | 
    ||
699  | 
    error = 1;  | 
    ||
700  | 
    continue;  | 
    ||
701  | 
    }  | 
    ||
702  | 
    |||
703  | 
    hf->init(&context);  | 
    ||
704  | 
    while ((nread = fread(data, 1UL, sizeof(data), fp)) > 0)  | 
    ||
705  | 
    hf->update(&context, data, nread);  | 
    ||
706  | 
    		if (ferror(fp)) { | 
    ||
707  | 
    			warn("%s: read error", file); | 
    ||
708  | 
    error = 1;  | 
    ||
709  | 
    fclose(fp);  | 
    ||
710  | 
    continue;  | 
    ||
711  | 
    }  | 
    ||
712  | 
    fclose(fp);  | 
    ||
713  | 
    digest_end(hf, &context, digest, sizeof(digest), base64);  | 
    ||
714  | 
    |||
715  | 
    if (base64)  | 
    ||
716  | 
    cmp = strncmp(checksum, digest, len);  | 
    ||
717  | 
    else  | 
    ||
718  | 
    cmp = strcasecmp(checksum, digest);  | 
    ||
719  | 
    		if (cmp == 0) { | 
    ||
720  | 
    if (qflag == 0)  | 
    ||
721  | 
    				(void)printf("(%s) %s: OK\n", algorithm, | 
    ||
722  | 
    filename);  | 
    ||
723  | 
    		} else { | 
    ||
724  | 
    			(void)printf("(%s) %s: FAILED\n", algorithm, filename); | 
    ||
725  | 
    error = 1;  | 
    ||
726  | 
    }  | 
    ||
727  | 
    }  | 
    ||
728  | 
    if (listfp != stdin)  | 
    ||
729  | 
    fclose(listfp);  | 
    ||
730  | 
    if (!found)  | 
    ||
731  | 
    		warnx("%s: no properly formatted checksum lines found", file); | 
    ||
732  | 
    free(lbuf);  | 
    ||
733  | 
    	if (sel_found != NULL) { | 
    ||
734  | 
    /*  | 
    ||
735  | 
    * Mark found files by setting them to NULL so that we can  | 
    ||
736  | 
    * detect files that are missing from the checklist later.  | 
    ||
737  | 
    */  | 
    ||
738  | 
    		for (i = 0; i < selcount; i++) { | 
    ||
739  | 
    if (sel_found[i])  | 
    ||
740  | 
    sel[i] = NULL;  | 
    ||
741  | 
    }  | 
    ||
742  | 
    free(sel_found);  | 
    ||
743  | 
    }  | 
    ||
744  | 
    return(error || !found);  | 
    ||
745  | 
    }  | 
    ||
746  | 
    |||
747  | 
    #define TEST_BLOCK_LEN 10000  | 
    ||
748  | 
    #define TEST_BLOCK_COUNT 10000  | 
    ||
749  | 
    |||
750  | 
    void  | 
    ||
751  | 
    digest_time(struct hash_list *hl, int times)  | 
    ||
752  | 
    { | 
    ||
753  | 
    struct hash_function *hf;  | 
    ||
754  | 
    struct rusage start, stop;  | 
    ||
755  | 
    struct timeval res;  | 
    ||
756  | 
    union ANY_CTX context;  | 
    ||
757  | 
    u_int i;  | 
    ||
758  | 
    u_char data[TEST_BLOCK_LEN];  | 
    ||
759  | 
    char digest[MAX_DIGEST_LEN + 1];  | 
    ||
760  | 
    double elapsed;  | 
    ||
761  | 
    int count = TEST_BLOCK_COUNT;  | 
    ||
762  | 
    while (--times > 0 && count < INT_MAX / 10)  | 
    ||
763  | 
    count *= 10;  | 
    ||
764  | 
    |||
765  | 
    	TAILQ_FOREACH(hf, hl, tailq) { | 
    ||
766  | 
    		(void)printf("%s time trial.  Processing %d %d-byte blocks...", | 
    ||
767  | 
    hf->name, count, TEST_BLOCK_LEN);  | 
    ||
768  | 
    fflush(stdout);  | 
    ||
769  | 
    |||
770  | 
    /* Initialize data based on block number. */  | 
    ||
771  | 
    for (i = 0; i < TEST_BLOCK_LEN; i++)  | 
    ||
772  | 
    data[i] = (u_char)(i & 0xff);  | 
    ||
773  | 
    |||
774  | 
    getrusage(RUSAGE_SELF, &start);  | 
    ||
775  | 
    hf->init(&context);  | 
    ||
776  | 
    for (i = 0; i < count; i++)  | 
    ||
777  | 
    hf->update(&context, data, (size_t)TEST_BLOCK_LEN);  | 
    ||
778  | 
    digest_end(hf, &context, digest, sizeof(digest), hf->base64);  | 
    ||
779  | 
    getrusage(RUSAGE_SELF, &stop);  | 
    ||
780  | 
    timersub(&stop.ru_utime, &start.ru_utime, &res);  | 
    ||
781  | 
    elapsed = res.tv_sec + res.tv_usec / 1000000.0;  | 
    ||
782  | 
    |||
783  | 
    		(void)printf("\nDigest = %s\n", digest); | 
    ||
784  | 
    		(void)printf("Time   = %f seconds\n", elapsed); | 
    ||
785  | 
    		(void)printf("Speed  = %f bytes/second\n", | 
    ||
786  | 
    (double)TEST_BLOCK_LEN * count / elapsed);  | 
    ||
787  | 
    }  | 
    ||
788  | 
    }  | 
    ||
789  | 
    |||
790  | 
    void  | 
    ||
791  | 
    digest_test(struct hash_list *hl)  | 
    ||
792  | 
    { | 
    ||
793  | 
    struct hash_function *hf;  | 
    ||
794  | 
    322  | 
    union ANY_CTX context;  | 
    |
795  | 
    int i;  | 
    ||
796  | 
    161  | 
    char digest[MAX_DIGEST_LEN + 1];  | 
    |
797  | 
    161  | 
    unsigned char buf[1000];  | 
    |
798  | 
    161  | 
    	unsigned const char *test_strings[] = { | 
    |
799  | 
    "",  | 
    ||
800  | 
    "a",  | 
    ||
801  | 
    "abc",  | 
    ||
802  | 
    "message digest",  | 
    ||
803  | 
    "abcdefghijklmnopqrstuvwxyz",  | 
    ||
804  | 
    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",  | 
    ||
805  | 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"  | 
    ||
806  | 
    "0123456789",  | 
    ||
807  | 
    "12345678901234567890123456789012345678901234567890123456789"  | 
    ||
808  | 
    "012345678901234567890",  | 
    ||
809  | 
    };  | 
    ||
810  | 
    |||
811  | 
    ✓✓ | 644  | 
    	TAILQ_FOREACH(hf, hl, tailq) { | 
    
812  | 
    161  | 
    		(void)printf("%s test suite:\n", hf->name); | 
    |
813  | 
    |||
814  | 
    ✓✓ | 2898  | 
    		for (i = 0; i < 8; i++) { | 
    
815  | 
    1288  | 
    hf->init(&context);  | 
    |
816  | 
    2576  | 
    hf->update(&context, test_strings[i],  | 
    |
817  | 
    1288  | 
    strlen(test_strings[i]));  | 
    |
818  | 
    2576  | 
    digest_end(hf, &context, digest, sizeof(digest),  | 
    |
819  | 
    1288  | 
    hf->base64);  | 
    |
820  | 
    1288  | 
    digest_printstr(hf, test_strings[i], digest);  | 
    |
821  | 
    }  | 
    ||
822  | 
    |||
823  | 
    /* Now simulate a string of a million 'a' characters. */  | 
    ||
824  | 
    161  | 
    memset(buf, 'a', sizeof(buf));  | 
    |
825  | 
    161  | 
    hf->init(&context);  | 
    |
826  | 
    ✓✓ | 322322  | 
    for (i = 0; i < 1000; i++)  | 
    
827  | 
    161000  | 
    hf->update(&context, buf, sizeof(buf));  | 
    |
828  | 
    161  | 
    digest_end(hf, &context, digest, sizeof(digest), hf->base64);  | 
    |
829  | 
    161  | 
    digest_print(hf, "one million 'a' characters",  | 
    |
830  | 
    digest);  | 
    ||
831  | 
    }  | 
    ||
832  | 
    161  | 
    }  | 
    |
833  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
834  | 
    |||
835  | 
    void  | 
    ||
836  | 
    usage(void)  | 
    ||
837  | 
    { | 
    ||
838  | 
    #if !defined(SHA2_ONLY)  | 
    ||
839  | 
    ✗✓ | 92  | 
    if (strcmp(__progname, "cksum") == 0)  | 
    
840  | 
    fprintf(stderr, "usage: %s [-bcpqrtx] [-a algorithms] [-C checklist] "  | 
    ||
841  | 
    "[-h hashfile]\n"  | 
    ||
842  | 
    " [-s string] [file ...]\n",  | 
    ||
843  | 
    __progname);  | 
    ||
844  | 
    else  | 
    ||
845  | 
    #endif /* !defined(SHA2_ONLY) */  | 
    ||
846  | 
    46  | 
    fprintf(stderr, "usage:"  | 
    |
847  | 
    "\t%s [-bcpqrtx] [-C checklist] [-h hashfile] [-s string] "  | 
    ||
848  | 
    "[file ...]\n",  | 
    ||
849  | 
    __progname);  | 
    ||
850  | 
    |||
851  | 
    exit(EXIT_FAILURE);  | 
    ||
852  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |