master xplshn/aruu / shared / libutil / crypt.c
  1/* See LICENSE file for copyright and license details. */
  2#include <fcntl.h>
  3#include <stdint.h>
  4#include <stdio.h>
  5#include <stdlib.h>
  6#include <string.h>
  7#include <unistd.h>
  8
  9#include "../crypt.h"
 10#include "../text.h"
 11#include "../util.h"
 12
 13static int
 14hexdec(int c)
 15{
 16	if (c >= '0' && c <= '9')
 17		return c - '0';
 18	else if (c >= 'A' && c <= 'F')
 19		return c - 'A' + 10;
 20	else if (c >= 'a' && c <= 'f')
 21		return c - 'a' + 10;
 22	return -1; /* unknown character */
 23}
 24
 25static int
 26mdcheckline(const char *s, uint8_t *md, size_t sz)
 27{
 28	size_t i;
 29	int b1, b2;
 30
 31	for (i = 0; i < sz; i++) {
 32		if (!*s || (b1 = hexdec(*s++)) < 0)
 33			return -1; /* invalid format */
 34		if (!*s || (b2 = hexdec(*s++)) < 0)
 35			return -1; /* invalid format */
 36		if ((uint8_t)((b1 << 4) | b2) != md[i])
 37			return 1; /* value mismatch */
 38	}
 39	return (i == sz) ? 0 : 1;
 40}
 41
 42static void
 43mdchecklist(FILE *listfp, struct crypt_ops *ops, uint8_t *md, size_t sz,
 44            int *formatsucks, int *noread, int *nonmatch)
 45{
 46	int fd;
 47	size_t bufsiz = 0;
 48	int r;
 49	char *line = NULL, *file, *p;
 50
 51	while (getline(&line, &bufsiz, listfp) > 0) {
 52		file = strchr(line, ' ');
 53		if (file == NULL || (file[1] != ' ' && file[1] != '*')) {
 54			(*formatsucks)++;
 55			continue;
 56		}
 57		if ((size_t)(file - line) != sz * 2) {
 58			(*formatsucks)++; /* checksum length mismatch */
 59			continue;
 60		}
 61		*file = '\0';
 62		file += 2;
 63		for (p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */
 64		*p = '\0';
 65		if ((fd = open(file, O_RDONLY)) < 0) {
 66			weprintf("open %s:", file);
 67			(*noread)++;
 68			continue;
 69		}
 70		if (cryptsum(ops, fd, file, md)) {
 71			(*noread)++;
 72			continue;
 73		}
 74		r = mdcheckline(line, md, sz);
 75		if (r == 0) {
 76			printf("%s: OK\n", file);
 77		} else if (r == 1) {
 78			printf("%s: FAILED\n", file);
 79			(*nonmatch)++;
 80		} else {
 81			(*formatsucks)++;
 82		}
 83		close(fd);
 84	}
 85	free(line);
 86}
 87
 88int
 89cryptcheck(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
 90{
 91	FILE *fp;
 92	int formatsucks = 0, noread = 0, nonmatch = 0, ret = 0;
 93
 94	if (argc == 0) {
 95		mdchecklist(stdin, ops, md, sz, &formatsucks, &noread, &nonmatch);
 96	} else {
 97		for (; *argv; argc--, argv++) {
 98			if ((*argv)[0] == '-' && !(*argv)[1]) {
 99				fp = stdin;
100			} else if (!(fp = fopen(*argv, "r"))) {
101				weprintf("fopen %s:", *argv);
102				ret = 1;
103				continue;
104			}
105			mdchecklist(fp, ops, md, sz, &formatsucks, &noread, &nonmatch);
106			if (fp != stdin)
107				fclose(fp);
108		}
109	}
110
111	if (formatsucks) {
112		weprintf("%d improperly formatted line%s\n",
113		         formatsucks, formatsucks > 1 ? "s" : "");
114		ret = 1;
115	}
116	if (noread) {
117		weprintf("%d listed file%s could not be read\n",
118		         noread, noread > 1 ? "s" : "");
119		ret = 1;
120	}
121	if (nonmatch) {
122		weprintf("%d computed checksum%s did NOT match\n",
123		         nonmatch, nonmatch > 1 ? "s" : "");
124		ret = 1;
125	}
126
127	return ret;
128}
129
130int
131cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz)
132{
133	int fd;
134	int ret = 0;
135
136	if (argc == 0) {
137		if (cryptsum(ops, 0, "<stdin>", md))
138			ret = 1;
139		else
140			mdprint(md, "<stdin>", sz);
141	} else {
142		for (; *argv; argc--, argv++) {
143			if ((*argv)[0] == '-' && !(*argv)[1]) {
144				*argv = "<stdin>";
145				fd = 0;
146			} else if ((fd = open(*argv, O_RDONLY)) < 0) {
147				weprintf("open %s:", *argv);
148				ret = 1;
149				continue;
150			}
151			if (cryptsum(ops, fd, *argv, md))
152				ret = 1;
153			else
154				mdprint(md, *argv, sz);
155			if (fd != 0)
156				close(fd);
157		}
158	}
159
160	return ret;
161}
162
163int
164cryptsum(struct crypt_ops *ops, int fd, const char *f, uint8_t *md)
165{
166	uint8_t buf[BUFSIZ];
167	ssize_t n;
168
169	ops->init(ops->s);
170	while ((n = read(fd, buf, sizeof(buf))) > 0)
171		ops->update(ops->s, buf, n);
172	if (n < 0) {
173		weprintf("%s: read error:", f);
174		return 1;
175	}
176	ops->sum(ops->s, md);
177	return 0;
178}
179
180void
181mdprint(const uint8_t *md, const char *f, size_t len)
182{
183	size_t i;
184
185	for (i = 0; i < len; i++)
186		printf("%02x", md[i]);
187	printf("  %s\n", f);
188}