1*d584e620SDavid du Colombier /*
2*d584e620SDavid du Colombier * sha1sum - compute SHA1 or SHA2 digest
3*d584e620SDavid du Colombier */
480ee5cbfSDavid du Colombier #include <u.h>
580ee5cbfSDavid du Colombier #include <libc.h>
680ee5cbfSDavid du Colombier #include <bio.h>
780ee5cbfSDavid du Colombier #include <libsec.h>
880ee5cbfSDavid du Colombier
980ee5cbfSDavid du Colombier #pragma varargck type "M" uchar*
1080ee5cbfSDavid du Colombier
11*d584e620SDavid du Colombier typedef struct Sha2 Sha2;
12*d584e620SDavid du Colombier struct Sha2 {
13*d584e620SDavid du Colombier int bits;
14*d584e620SDavid du Colombier int dlen;
15*d584e620SDavid du Colombier DigestState* (*func)(uchar *, ulong, uchar *, DigestState *);
16*d584e620SDavid du Colombier };
17*d584e620SDavid du Colombier
18*d584e620SDavid du Colombier static Sha2 sha2s[] = {
19*d584e620SDavid du Colombier 224, SHA2_224dlen, sha2_224,
20*d584e620SDavid du Colombier 256, SHA2_256dlen, sha2_256,
21*d584e620SDavid du Colombier 384, SHA2_384dlen, sha2_384,
22*d584e620SDavid du Colombier 512, SHA2_512dlen, sha2_512,
23*d584e620SDavid du Colombier };
24*d584e620SDavid du Colombier
25*d584e620SDavid du Colombier static DigestState* (*shafunc)(uchar *, ulong, uchar *, DigestState *);
26*d584e620SDavid du Colombier static int shadlen;
27*d584e620SDavid du Colombier
2880ee5cbfSDavid du Colombier static int
digestfmt(Fmt * fmt)299a747e4fSDavid du Colombier digestfmt(Fmt *fmt)
3080ee5cbfSDavid du Colombier {
31*d584e620SDavid du Colombier char buf[SHA2_512dlen*2 + 1];
3280ee5cbfSDavid du Colombier uchar *p;
3380ee5cbfSDavid du Colombier int i;
3480ee5cbfSDavid du Colombier
359a747e4fSDavid du Colombier p = va_arg(fmt->args, uchar*);
36*d584e620SDavid du Colombier for(i = 0; i < shadlen; i++)
3780ee5cbfSDavid du Colombier sprint(buf + 2*i, "%.2ux", p[i]);
389a747e4fSDavid du Colombier return fmtstrcpy(fmt, buf);
3980ee5cbfSDavid du Colombier }
4080ee5cbfSDavid du Colombier
4180ee5cbfSDavid du Colombier static void
sum(int fd,char * name)4280ee5cbfSDavid du Colombier sum(int fd, char *name)
4380ee5cbfSDavid du Colombier {
4480ee5cbfSDavid du Colombier int n;
45*d584e620SDavid du Colombier uchar buf[8192], digest[SHA2_512dlen];
4680ee5cbfSDavid du Colombier DigestState *s;
4780ee5cbfSDavid du Colombier
48*d584e620SDavid du Colombier s = (*shafunc)(nil, 0, nil, nil);
4980ee5cbfSDavid du Colombier while((n = read(fd, buf, sizeof buf)) > 0)
50*d584e620SDavid du Colombier (*shafunc)(buf, n, nil, s);
51225077b0SDavid du Colombier if(n < 0){
52225077b0SDavid du Colombier fprint(2, "reading %s: %r\n", name? name: "stdin");
53225077b0SDavid du Colombier return;
54225077b0SDavid du Colombier }
55*d584e620SDavid du Colombier (*shafunc)(nil, 0, digest, s);
5680ee5cbfSDavid du Colombier if(name == nil)
5780ee5cbfSDavid du Colombier print("%M\n", digest);
5880ee5cbfSDavid du Colombier else
5980ee5cbfSDavid du Colombier print("%M\t%s\n", digest, name);
6080ee5cbfSDavid du Colombier }
6180ee5cbfSDavid du Colombier
62*d584e620SDavid du Colombier static void
usage(void)63*d584e620SDavid du Colombier usage(void)
64*d584e620SDavid du Colombier {
65*d584e620SDavid du Colombier fprint(2, "usage: %s [-2 bits] [file...]\n", argv0);
66*d584e620SDavid du Colombier exits("usage");
67*d584e620SDavid du Colombier }
68*d584e620SDavid du Colombier
6980ee5cbfSDavid du Colombier void
main(int argc,char * argv[])7080ee5cbfSDavid du Colombier main(int argc, char *argv[])
7180ee5cbfSDavid du Colombier {
72*d584e620SDavid du Colombier int i, fd, bits;
73*d584e620SDavid du Colombier Sha2 *sha;
7480ee5cbfSDavid du Colombier
75*d584e620SDavid du Colombier shafunc = sha1;
76*d584e620SDavid du Colombier shadlen = SHA1dlen;
7780ee5cbfSDavid du Colombier ARGBEGIN{
78*d584e620SDavid du Colombier case '2':
79*d584e620SDavid du Colombier bits = atoi(EARGF(usage()));
80*d584e620SDavid du Colombier for (sha = sha2s; sha < sha2s + nelem(sha2s); sha++)
81*d584e620SDavid du Colombier if (sha->bits == bits)
82*d584e620SDavid du Colombier break;
83*d584e620SDavid du Colombier if (sha >= sha2s + nelem(sha2s))
84*d584e620SDavid du Colombier sysfatal("unknown number of sha2 bits: %d", bits);
85*d584e620SDavid du Colombier shafunc = sha->func;
86*d584e620SDavid du Colombier shadlen = sha->dlen;
87*d584e620SDavid du Colombier break;
8880ee5cbfSDavid du Colombier default:
89*d584e620SDavid du Colombier usage();
9080ee5cbfSDavid du Colombier }ARGEND
9180ee5cbfSDavid du Colombier
929a747e4fSDavid du Colombier fmtinstall('M', digestfmt);
9380ee5cbfSDavid du Colombier
9480ee5cbfSDavid du Colombier if(argc == 0)
9580ee5cbfSDavid du Colombier sum(0, nil);
96*d584e620SDavid du Colombier else
97*d584e620SDavid du Colombier for(i = 0; i < argc; i++){
9880ee5cbfSDavid du Colombier fd = open(argv[i], OREAD);
9980ee5cbfSDavid du Colombier if(fd < 0){
100*d584e620SDavid du Colombier fprint(2, "%s: can't open %s: %r\n", argv0, argv[i]);
10180ee5cbfSDavid du Colombier continue;
10280ee5cbfSDavid du Colombier }
10380ee5cbfSDavid du Colombier sum(fd, argv[i]);
10480ee5cbfSDavid du Colombier close(fd);
10580ee5cbfSDavid du Colombier }
10680ee5cbfSDavid du Colombier exits(nil);
10780ee5cbfSDavid du Colombier }
108