xref: /plan9/sys/src/cmd/sha1sum.c (revision d584e620e1e64710d4ac65e2daf41aeeb4b9a081)
1 /*
2  * sha1sum - compute SHA1 or SHA2 digest
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <bio.h>
7 #include <libsec.h>
8 
9 #pragma	varargck	type	"M"	uchar*
10 
11 typedef struct Sha2 Sha2;
12 struct Sha2 {
13 	int	bits;
14 	int	dlen;
15 	DigestState* (*func)(uchar *, ulong, uchar *, DigestState *);
16 };
17 
18 static Sha2 sha2s[] = {
19 	224,	SHA2_224dlen,	sha2_224,
20 	256,	SHA2_256dlen,	sha2_256,
21 	384,	SHA2_384dlen,	sha2_384,
22 	512,	SHA2_512dlen,	sha2_512,
23 };
24 
25 static DigestState* (*shafunc)(uchar *, ulong, uchar *, DigestState *);
26 static int shadlen;
27 
28 static int
digestfmt(Fmt * fmt)29 digestfmt(Fmt *fmt)
30 {
31 	char buf[SHA2_512dlen*2 + 1];
32 	uchar *p;
33 	int i;
34 
35 	p = va_arg(fmt->args, uchar*);
36 	for(i = 0; i < shadlen; i++)
37 		sprint(buf + 2*i, "%.2ux", p[i]);
38 	return fmtstrcpy(fmt, buf);
39 }
40 
41 static void
sum(int fd,char * name)42 sum(int fd, char *name)
43 {
44 	int n;
45 	uchar buf[8192], digest[SHA2_512dlen];
46 	DigestState *s;
47 
48 	s = (*shafunc)(nil, 0, nil, nil);
49 	while((n = read(fd, buf, sizeof buf)) > 0)
50 		(*shafunc)(buf, n, nil, s);
51 	if(n < 0){
52 		fprint(2, "reading %s: %r\n", name? name: "stdin");
53 		return;
54 	}
55 	(*shafunc)(nil, 0, digest, s);
56 	if(name == nil)
57 		print("%M\n", digest);
58 	else
59 		print("%M\t%s\n", digest, name);
60 }
61 
62 static void
usage(void)63 usage(void)
64 {
65 	fprint(2, "usage: %s [-2 bits] [file...]\n", argv0);
66 	exits("usage");
67 }
68 
69 void
main(int argc,char * argv[])70 main(int argc, char *argv[])
71 {
72 	int i, fd, bits;
73 	Sha2 *sha;
74 
75 	shafunc = sha1;
76 	shadlen = SHA1dlen;
77 	ARGBEGIN{
78 	case '2':
79 		bits = atoi(EARGF(usage()));
80 		for (sha = sha2s; sha < sha2s + nelem(sha2s); sha++)
81 			if (sha->bits == bits)
82 				break;
83 		if (sha >= sha2s + nelem(sha2s))
84 			sysfatal("unknown number of sha2 bits: %d", bits);
85 		shafunc = sha->func;
86 		shadlen = sha->dlen;
87 		break;
88 	default:
89 		usage();
90 	}ARGEND
91 
92 	fmtinstall('M', digestfmt);
93 
94 	if(argc == 0)
95 		sum(0, nil);
96 	else
97 		for(i = 0; i < argc; i++){
98 			fd = open(argv[i], OREAD);
99 			if(fd < 0){
100 				fprint(2, "%s: can't open %s: %r\n", argv0, argv[i]);
101 				continue;
102 			}
103 			sum(fd, argv[i]);
104 			close(fd);
105 		}
106 	exits(nil);
107 }
108