hashsum.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis
  2. *
  3. * LibTomCrypt is a library that provides various cryptographic
  4. * algorithms in a highly modular and flexible manner.
  5. *
  6. * The library is free for all purposes without any express
  7. * guarantee it works.
  8. */
  9. /*
  10. * Written by Daniel Richards <kyhwana@world-net.co.nz> 6/7/2002
  11. * hash.c: This app uses libtomcrypt to hash either stdin or a file
  12. * This file is Public Domain. No rights are reserved.
  13. * Compile with 'gcc hashsum.c -o hashsum -ltomcrypt'
  14. * This example isn't really big enough to warrent splitting into
  15. * more functions ;)
  16. */
  17. #include <tomcrypt.h>
  18. #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
  19. #include <libgen.h>
  20. #else
  21. #define basename(x) x
  22. #endif
  23. #if !defined(PATH_MAX) && defined(_MSC_VER)
  24. #include <windows.h>
  25. #define PATH_MAX MAX_PATH
  26. #endif
  27. /* thanks http://stackoverflow.com/a/8198009 */
  28. #define _base(x) ((x >= '0' && x <= '9') ? '0' : \
  29. (x >= 'a' && x <= 'f') ? 'a' - 10 : \
  30. (x >= 'A' && x <= 'F') ? 'A' - 10 : \
  31. '\255')
  32. #define HEXOF(x) (x - _base(x))
  33. static char* hashsum;
  34. static void cleanup(void)
  35. {
  36. free(hashsum);
  37. }
  38. static void die(int status)
  39. {
  40. unsigned long w, x;
  41. FILE* o = status == EXIT_SUCCESS ? stdout : stderr;
  42. fprintf(o, "usage: %s -a algorithm [-c] [file...]\n\n", hashsum);
  43. fprintf(o, "\t-c\tCheck the hash(es) of the file(s) written in [file].\n");
  44. fprintf(o, "\t\t(-a not required)\n");
  45. fprintf(o, "\nAlgorithms:\n\t");
  46. w = 0;
  47. for (x = 0; hash_descriptor[x].name != NULL; x++) {
  48. w += fprintf(o, "%-14s", hash_descriptor[x].name);
  49. if (w >= 70) {
  50. fprintf(o, "\n\t");
  51. w = 0;
  52. }
  53. }
  54. if (w != 0) fprintf(o, "\n");
  55. exit(status);
  56. }
  57. static void printf_hex(unsigned char* hash_buffer, unsigned long w)
  58. {
  59. unsigned long x;
  60. for (x = 0; x < w; x++) {
  61. printf("%02x",hash_buffer[x]);
  62. }
  63. }
  64. static void check_file(int argn, int argc, char **argv)
  65. {
  66. int err, failed, invalid;
  67. unsigned char is_buffer[MAXBLOCKSIZE], should_buffer[MAXBLOCKSIZE];
  68. char buf[PATH_MAX + (MAXBLOCKSIZE * 3)];
  69. /* iterate through all files */
  70. while(argn < argc) {
  71. char* s;
  72. FILE* f = fopen(argv[argn], "rb");
  73. if(f == NULL) {
  74. int n = snprintf(buf, sizeof(buf), "%s: %s", hashsum, argv[argn]);
  75. if (n > 0 && n < (int)sizeof(buf))
  76. perror(buf);
  77. else
  78. perror(argv[argn]);
  79. exit(EXIT_FAILURE);
  80. }
  81. failed = 0;
  82. invalid = 0;
  83. /* read the file line by line */
  84. while((s = fgets(buf, sizeof(buf), f)) != NULL)
  85. {
  86. int tries, n;
  87. unsigned long hash_len, w, x;
  88. char* space = strstr(s, " ");
  89. /* skip lines with comments */
  90. if (buf[0] == '#') continue;
  91. if (space == NULL) {
  92. fprintf(stderr, "%s: no properly formatted checksum lines found\n", hashsum);
  93. goto ERR;
  94. }
  95. hash_len = space - s;
  96. hash_len /= 2;
  97. if (hash_len > sizeof(should_buffer)) {
  98. fprintf(stderr, "%s: hash too long\n", hashsum);
  99. goto ERR;
  100. }
  101. /* convert the hex-string back to binary */
  102. for (x = 0; x < hash_len; ++x) {
  103. should_buffer[x] = HEXOF(s[x*2]) << 4 | HEXOF(s[x*2 + 1]);
  104. }
  105. space++;
  106. if (*space != '*') {
  107. fprintf(stderr, "%s: unsupported input mode '%c'\n", hashsum, *space);
  108. goto ERR;
  109. }
  110. space++;
  111. for (n = 0; n < (buf + sizeof(buf)) - space; ++n) {
  112. if(iscntrl((int)space[n])) {
  113. space[n] = '\0';
  114. break;
  115. }
  116. }
  117. /* try all hash algorithms that have the appropriate hash size */
  118. tries = 0;
  119. for (x = 0; hash_descriptor[x].name != NULL; ++x) {
  120. if (hash_descriptor[x].hashsize == hash_len) {
  121. tries++;
  122. w = sizeof(is_buffer);
  123. if ((err = hash_file(x, space, is_buffer, &w)) != CRYPT_OK) {
  124. fprintf(stderr, "%s: File hash error: %s: %s\n", hashsum, space, error_to_string(err));
  125. ERR:
  126. fclose(f);
  127. exit(EXIT_FAILURE);
  128. }
  129. if(XMEMCMP(should_buffer, is_buffer, w) == 0) {
  130. printf("%s: OK\n", space);
  131. break;
  132. }
  133. }
  134. } /* for */
  135. if (hash_descriptor[x].name == NULL) {
  136. if(tries > 0) {
  137. printf("%s: FAILED\n", space);
  138. failed++;
  139. }
  140. else {
  141. invalid++;
  142. }
  143. }
  144. } /* while */
  145. fclose(f);
  146. if(invalid) {
  147. fprintf(stderr, "%s: WARNING: %d %s is improperly formatted\n", hashsum, invalid, invalid > 1?"lines":"line");
  148. }
  149. if(failed) {
  150. fprintf(stderr, "%s: WARNING: %d computed %s did NOT match\n", hashsum, failed, failed > 1?"checksums":"checksum");
  151. }
  152. argn++;
  153. }
  154. exit(EXIT_SUCCESS);
  155. }
  156. int main(int argc, char **argv)
  157. {
  158. int idxs[TAB_SIZE], idx, check, y, z, err, argn;
  159. unsigned long w, x;
  160. unsigned char hash_buffer[MAXBLOCKSIZE];
  161. hashsum = strdup(basename(argv[0]));
  162. atexit(cleanup);
  163. /* You need to register algorithms before using them */
  164. register_all_ciphers();
  165. register_all_hashes();
  166. if (argc > 1 && (strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0)) {
  167. die(EXIT_SUCCESS);
  168. }
  169. if (argc < 3) {
  170. die(EXIT_FAILURE);
  171. }
  172. for (x = 0; x < sizeof(idxs)/sizeof(idxs[0]); ++x) {
  173. idxs[x] = -2;
  174. }
  175. argn = 1;
  176. check = 0;
  177. idx = 0;
  178. while(argn < argc){
  179. if(strcmp("-a", argv[argn]) == 0) {
  180. argn++;
  181. if(argn < argc) {
  182. idxs[idx] = find_hash(argv[argn]);
  183. if (idxs[idx] == -1) {
  184. struct {
  185. const char* is;
  186. const char* should;
  187. } shasum_compat[] =
  188. {
  189. #ifdef LTC_SHA1
  190. { "1", sha1_desc.name },
  191. #endif
  192. #ifdef LTC_SHA224
  193. { "224", sha224_desc.name },
  194. #endif
  195. #ifdef LTC_SHA256
  196. { "256", sha256_desc.name },
  197. #endif
  198. #ifdef LTC_SHA384
  199. { "384", sha384_desc.name },
  200. #endif
  201. #ifdef LTC_SHA512
  202. { "512", sha512_desc.name },
  203. #endif
  204. #ifdef LTC_SHA512_224
  205. { "512224", sha512_224_desc.name },
  206. #endif
  207. #ifdef LTC_SHA512_256
  208. { "512256", sha512_256_desc.name },
  209. #endif
  210. { NULL, NULL }
  211. };
  212. for (x = 0; shasum_compat[x].is != NULL; ++x) {
  213. if(XSTRCMP(shasum_compat[x].is, argv[argn]) == 0) {
  214. idxs[idx] = find_hash(shasum_compat[x].should);
  215. break;
  216. }
  217. }
  218. }
  219. if (idxs[idx] == -1) {
  220. fprintf(stderr, "%s: Unrecognized algorithm\n", hashsum);
  221. die(EXIT_FAILURE);
  222. }
  223. idx++;
  224. if ((size_t)idx >= sizeof(idxs)/sizeof(idxs[0])) {
  225. fprintf(stderr, "%s: Too many '-a' options chosen\n", hashsum);
  226. die(EXIT_FAILURE);
  227. }
  228. argn++;
  229. continue;
  230. }
  231. else {
  232. die(EXIT_FAILURE);
  233. }
  234. }
  235. if(strcmp("-c", argv[argn]) == 0) {
  236. check = 1;
  237. argn++;
  238. continue;
  239. }
  240. break;
  241. }
  242. if (check == 1) {
  243. check_file(argn, argc, argv);
  244. }
  245. if (argc == argn) {
  246. w = sizeof(hash_buffer);
  247. if ((err = hash_filehandle(idxs[0], stdin, hash_buffer, &w)) != CRYPT_OK) {
  248. fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err));
  249. return EXIT_FAILURE;
  250. } else {
  251. for (x = 0; x < w; x++) {
  252. printf("%02x",hash_buffer[x]);
  253. }
  254. printf(" *-\n");
  255. }
  256. } else {
  257. for (z = argn; z < argc; z++) {
  258. for (y = 0; y < idx; ++y) {
  259. w = sizeof(hash_buffer);
  260. if ((err = hash_file(idxs[y],argv[z],hash_buffer,&w)) != CRYPT_OK) {
  261. fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err));
  262. return EXIT_FAILURE;
  263. } else {
  264. printf_hex(hash_buffer, w);
  265. printf(" *%s\n", argv[z]);
  266. }
  267. }
  268. }
  269. }
  270. return EXIT_SUCCESS;
  271. }
  272. /* ref: $Format:%D$ */
  273. /* git commit: $Format:%H$ */
  274. /* commit time: $Format:%ai$ */