crypt.c (3700B)
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 13 static int 14 hexdec(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 25 static int 26 mdcheckline(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 0; /* value mismatch */ 38 } 39 return (i == sz) ? 1 : 0; 40 } 41 42 static void 43 mdchecklist(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 if (!(file = strstr(line, " "))) { 53 (*formatsucks)++; 54 continue; 55 } 56 if ((file - line) / 2 != sz) { 57 (*formatsucks)++; /* checksum length mismatch */ 58 continue; 59 } 60 *file = '\0'; 61 file += 2; 62 for (p = file; *p && *p != '\n' && *p != '\r'; p++); /* strip newline */ 63 *p = '\0'; 64 if ((fd = open(file, O_RDONLY)) < 0) { 65 weprintf("open %s:", file); 66 (*noread)++; 67 continue; 68 } 69 if (cryptsum(ops, fd, file, md)) { 70 (*noread)++; 71 continue; 72 } 73 r = mdcheckline(line, md, sz); 74 if (r == 1) { 75 printf("%s: OK\n", file); 76 } else if (r == 0) { 77 printf("%s: FAILED\n", file); 78 (*nonmatch)++; 79 } else { 80 (*formatsucks)++; 81 } 82 close(fd); 83 } 84 free(line); 85 } 86 87 int 88 cryptcheck(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz) 89 { 90 FILE *fp; 91 int formatsucks = 0, noread = 0, nonmatch = 0, ret = 0; 92 93 if (argc == 0) { 94 mdchecklist(stdin, ops, md, sz, &formatsucks, &noread, &nonmatch); 95 } else { 96 for (; *argv; argc--, argv++) { 97 if ((*argv)[0] == '-' && !(*argv)[1]) { 98 fp = stdin; 99 } else if (!(fp = fopen(*argv, "r"))) { 100 weprintf("fopen %s:", *argv); 101 ret = 1; 102 continue; 103 } 104 mdchecklist(fp, ops, md, sz, &formatsucks, &noread, &nonmatch); 105 if (fp != stdin) 106 fclose(fp); 107 } 108 } 109 110 if (formatsucks) { 111 weprintf("%d lines are improperly formatted\n", formatsucks); 112 ret = 1; 113 } 114 if (noread) { 115 weprintf("%d listed file could not be read\n", noread); 116 ret = 1; 117 } 118 if (nonmatch) { 119 weprintf("%d computed checksums did NOT match\n", nonmatch); 120 ret = 1; 121 } 122 123 return ret; 124 } 125 126 int 127 cryptmain(int argc, char *argv[], struct crypt_ops *ops, uint8_t *md, size_t sz) 128 { 129 int fd; 130 int ret = 0; 131 132 if (argc == 0) { 133 if (cryptsum(ops, 0, "<stdin>", md)) 134 ret = 1; 135 else 136 mdprint(md, "<stdin>", sz); 137 } else { 138 for (; *argv; argc--, argv++) { 139 if ((*argv)[0] == '-' && !(*argv)[1]) { 140 *argv = "<stdin>"; 141 fd = 0; 142 } else if ((fd = open(*argv, O_RDONLY)) < 0) { 143 weprintf("open %s:", *argv); 144 ret = 1; 145 continue; 146 } 147 if (cryptsum(ops, fd, *argv, md)) 148 ret = 1; 149 else 150 mdprint(md, *argv, sz); 151 if (fd != 0) 152 close(fd); 153 } 154 } 155 156 return ret; 157 } 158 159 int 160 cryptsum(struct crypt_ops *ops, int fd, const char *f, uint8_t *md) 161 { 162 uint8_t buf[BUFSIZ]; 163 ssize_t n; 164 165 ops->init(ops->s); 166 while ((n = read(fd, buf, sizeof(buf))) > 0) 167 ops->update(ops->s, buf, n); 168 if (n < 0) { 169 weprintf("%s: read error:", f); 170 return 1; 171 } 172 ops->sum(ops->s, md); 173 return 0; 174 } 175 176 void 177 mdprint(const uint8_t *md, const char *f, size_t len) 178 { 179 size_t i; 180 181 for (i = 0; i < len; i++) 182 printf("%02x", md[i]); 183 printf(" %s\n", f); 184 }