Rizin
unix-like reverse engineering framework and cli tools
rz-hash.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <stdio.h>
5 #include <string.h>
6 #include <rz_io.h>
7 #include <rz_main.h>
8 #include <rz_hash.h>
9 #include <rz_util/rz_print.h>
10 #include <rz_util.h>
11 #include <rz_crypto.h>
12 #include <rz_lib.h>
13 
14 #define RZ_HASH_DEFAULT_BLOCK_SIZE 0x1000
15 
16 typedef struct {
17  ut8 *buf;
18  size_t len;
19 } RzHashBuffer;
20 
21 typedef enum {
27 } RzHashMode;
28 
29 typedef enum {
40 } RzHashOp;
41 
42 typedef struct {
45 } RzHashOffset;
46 
47 typedef struct rz_hash_context {
49  bool as_prefix;
52  bool use_stdin;
53  char *algorithm;
54  char *compare;
55  char *input;
56  char *iv;
57  const char **files;
66  /* Output here */
67  PJ *pj;
69 
70 typedef bool (*RzHashRun)(RzHashContext *ctx, RzIO *io, const char *filename);
71 
72 static void rz_hash_show_help(bool usage_only) {
73  printf("Usage: rz-hash [-vhBkjLq] [-b S] [-a A] [-c H] [-E A] [-D A] [-s S] [-x S] [-f O] [-t O] [files|-] ...\n");
74  if (usage_only) {
75  return;
76  }
77  printf(
78  " -v Shows version\n"
79  " -h Shows this help page\n"
80  " - Input read from stdin instead from a file\n"
81  " -a algo Hash algorithm to use and you can specify multiple ones by\n"
82  " appending a comma (example: sha1,md4,md5,sha256)\n"
83  " -B Outputs the calculated value for each block\n"
84  " -b size Sets the block size\n"
85  " -c value Compare calculated value with a given one (hexadecimal)\n"
86  " -e endian Sets the endianness (default: 'big' accepted: 'big' or 'little')\n"
87  " -D algo Decrypt the given input; use -S to set key and -I to set IV (if needed)\n"
88  " -E algo Encrypt the given input; use -S to set key and -I to set IV (if needed)\n"
89  " -f from Starts the calculation at given offset\n"
90  " -t to Stops the calculation at given offset\n"
91  " -I iv Sets the initialization vector (IV)\n"
92  " -i times Repeat the calculation N times\n"
93  " -j Outputs the result as a JSON structure\n"
94  " -k Outputs the calculated value using openssh's randomkey algorithm\n"
95  " -L List all algorithms\n"
96  " -q Sets quiet mode (use -qq to get only the calculated value)\n"
97  " -S seed Sets the seed for -a, use '^' to append it before the input, use '@'\n"
98  " prefix to load it from a file and '-' from read it\n"
99  " -K key Sets the hmac key for -a and the key for -E/-D, use '@' prefix to\n"
100  " load it from a file and '-' from read it\n"
101  " from stdin (you can combine them)\n"
102  " -s string Input read from a zero-terminated string instead from a file\n"
103  " -x hex Input read from a hexadecimal value instead from a file\n"
104  "\n"
105  " All the inputs (besides -s/-x/-c) can be hexadecimal or strings\n"
106  " if 's:' prefix is specified\n");
107 }
108 
110  char flags[7] = { 0 };
111 
112  printf("flags algorithm license author\n");
113 
114  const RzHashPlugin *rmdp;
115  for (size_t i = 0; (rmdp = rz_hash_plugin_by_index(ctx->rh, i)); ++i) {
116  snprintf(flags, sizeof(flags), "____h%c", rmdp->support_hmac ? 'm' : '_');
117  printf("%6s %-14s %-10s %s\n", flags, rmdp->name, rmdp->license, rmdp->author);
118  }
119 
120  const RzCryptoPlugin *rcp;
121  for (size_t i = 0; (rcp = rz_crypto_plugin_by_index(i)); i++) {
122  if (!strncmp("base", rcp->name, 4) || !strcmp("punycode", rcp->name)) {
123  snprintf(flags, sizeof(flags), "__ed__");
124  } else if (!strcmp("rol", rcp->name)) {
125  snprintf(flags, sizeof(flags), "E_____");
126  } else if (!strcmp("ror", rcp->name)) {
127  snprintf(flags, sizeof(flags), "_D____");
128  } else {
129  snprintf(flags, sizeof(flags), "ED____");
130  }
131  printf("%6s %-14s %-10s %s\n", flags, rcp->name, rcp->license, rcp->author);
132  }
133  printf(
134  "\n"
135  "flags legenda:\n"
136  " E = encryption, D = decryption\n"
137  " e = encoding, d = encoding\n"
138  " h = hash, m = hmac\n");
139 }
140 
141 #define rz_hash_bool_error(x, o, f, ...) \
142  (x)->operation = o; \
143  RZ_LOG_ERROR("rz-hash: error, " f, ##__VA_ARGS__); \
144  return false;
145 
146 #define rz_hash_error(x, o, f, ...) \
147  (x)->operation = o; \
148  RZ_LOG_ERROR("rz-hash: error, " f, ##__VA_ARGS__); \
149  return;
150 
151 #define rz_hash_set_val(x, k, d, v) \
152  do { \
153  if ((k) != (d)) { \
154  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "invalid combination of arguments for '-%c' (expected " #d " but found something else)\n", c); \
155  } \
156  (k) = (v); \
157  } while (0)
158 
159 #define rz_hash_ctx_set_val(x, k, d, v) \
160  do { \
161  if ((x)->k != (d)) { \
162  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "invalid combination of arguments for '-%c' (expected " #d " but found something else)\n", c); \
163  } \
164  (x)->k = (v); \
165  } while (0)
166 
167 #define rz_hash_ctx_set_bool(x, k, i, t, f) \
168  do { \
169  if (i && !strcmp(i, t)) { \
170  (x)->k = true; \
171  } else if (i && !strcmp(i, f)) { \
172  (x)->k = false; \
173  } else { \
174  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "expected '%s' or '%s' but got '%s'\n", t, f, i); \
175  } \
176  } while (0)
177 
178 #define rz_hash_ctx_set_quiet(x) \
179  do { \
180  if ((x)->mode == RZ_HASH_MODE_STANDARD) { \
181  (x)->mode = RZ_HASH_MODE_QUIET; \
182  } else if ((x)->mode == RZ_HASH_MODE_QUIET) { \
183  (x)->mode = RZ_HASH_MODE_VERY_QUIET; \
184  } else if ((x)->mode == RZ_HASH_MODE_JSON) { \
185  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "can't be quiet when json mode is selected\n"); \
186  } else if ((x)->mode == RZ_HASH_MODE_RANDOMART) { \
187  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "can't be quiet when openssh mode is selected\n"); \
188  } \
189  } while (0)
190 
191 #define rz_hash_ctx_set_signed(x, k, i) \
192  do { \
193  (x)->k = strtoll((i), NULL, 0); \
194  if ((x)->k < 1) { \
195  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "argument must be > 0\n"); \
196  } \
197  } while (0)
198 
199 #define rz_hash_ctx_set_unsigned(x, k, i) \
200  do { \
201  (x)->k = strtoull((i), NULL, 0); \
202  if ((x)->k < 1) { \
203  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "argument must be > 0\n"); \
204  } \
205  } while (0)
206 
207 #define rz_hash_ctx_set_input(x, k, s, h) \
208  do { \
209  if ((x)->k) { \
210  rz_hash_error(x, RZ_HASH_OP_UNKNOWN, "invalid combination of arguments for '-%c'\n", c); \
211  } else if (h || strlen(s) < 1) { \
212  (x)->k = strdup(s); \
213  } else { \
214  (x)->k = rz_str_newf("s:%s", s); \
215  } \
216  } while (0)
217 
218 #define rz_hash_ctx_set_mode(x, m) rz_hash_ctx_set_val(x, mode, RZ_HASH_MODE_STANDARD, m)
219 #define rz_hash_ctx_set_op(x, o) rz_hash_ctx_set_val(x, operation, RZ_HASH_OP_UNKNOWN, o)
220 #define rz_hash_ctx_set_str(x, k, s) rz_hash_ctx_set_val(x, k, NULL, strdup(s))
221 
222 static bool hash_parse_string(const char *option, const char *string, ut8 **buffer, size_t *bufsize) {
223  char *sstdin = NULL;
224  int stringlen = 0;
225  if (!strcmp(string, "-")) {
226  string = sstdin = rz_stdin_slurp(&stringlen);
227  } else {
228  stringlen = strlen(string);
229  }
230  if (stringlen < 1 || !string) {
231  RZ_LOG_ERROR("rz-hash: error, option %s is empty.\n", option);
232  free(sstdin);
233  return false;
234  }
235 
236  ut8 *b = (ut8 *)malloc(stringlen + 1);
237  if (!b) {
238  RZ_LOG_ERROR("rz-hash: error, failed to allocate string in memory.\n");
239  free(sstdin);
240  return false;
241  }
242 
243  memcpy(b, string, stringlen);
244  b[stringlen] = 0;
245  stringlen = rz_str_unescape((char *)b);
246 
247  *buffer = b;
248  *bufsize = stringlen;
249  free(sstdin);
250 
251  return true;
252 }
253 
254 static bool hash_parse_hexadecimal(const char *option, const char *hexadecimal, ut8 **buffer, size_t *bufsize) {
255  char *sstdin = NULL;
256  int hexlen = 0;
257  if (!strcmp(hexadecimal, "-")) {
258  hexadecimal = sstdin = rz_stdin_slurp(&hexlen);
259  } else {
260  hexlen = strlen(hexadecimal);
261  }
262 
263  if (hexlen < 1 || !hexadecimal) {
264  RZ_LOG_ERROR("rz-hash: error, option %s is empty.\n", option);
265  free(sstdin);
266  return false;
267  } else if (hexlen & 1) {
268  RZ_LOG_ERROR("rz-hash: error, option %s is not a valid hexadecimal (len is not pair: %d).\n", option, hexlen);
269  free(sstdin);
270  return false;
271  }
272  *buffer = NULL;
273  st64 binlen = hexlen >> 1;
274  ut8 *b = (ut8 *)malloc(binlen);
275  if (b) {
276  *bufsize = rz_hex_str2bin(hexadecimal, b);
277  if (*bufsize < 1) {
278  RZ_LOG_ERROR("rz-hash: error, option %s is not a valid hexadecimal.\n", option);
279  free(b);
280  free(sstdin);
281  return false;
282  }
283  *buffer = b;
284  }
285 
286  free(sstdin);
287  return true;
288 }
289 
290 static bool hash_parse_any(RzHashContext *ctx, const char *option, const char *arg, RzHashBuffer *hb) {
291  ssize_t arglen = strlen(arg);
292  if (arglen < 1) {
293  rz_hash_bool_error(ctx, RZ_HASH_OP_ERROR, "option %s is empty.\n", option);
294  }
295  if (!strcmp(arg, "-")) {
296  int stdinlen = 0;
297  hb->buf = (ut8 *)rz_stdin_slurp(&stdinlen);
298  hb->len = stdinlen;
299  } else if (arg[0] == '@') {
300  hb->buf = (ut8 *)rz_file_slurp(arg + 1, &hb->len);
301  } else if (!strncmp(arg, "s:", 2)) {
302  if (!hash_parse_string(option, arg + 2, &hb->buf, &hb->len)) {
303  ctx->operation = RZ_HASH_OP_ERROR;
304  return false;
305  }
306  } else {
307  if (!hash_parse_hexadecimal(option, arg, &hb->buf, &hb->len)) {
308  ctx->operation = RZ_HASH_OP_ERROR;
309  return false;
310  }
311  }
312  if (!hb->buf) {
313  rz_hash_bool_error(ctx, RZ_HASH_OP_ERROR, "failed to allocate buffer memory for %s option.\n", option);
314  }
315  return true;
316 }
317 
318 static void hash_parse_cmdline(int argc, const char **argv, RzHashContext *ctx) {
319  const char *seed = NULL;
320  const char *key = NULL;
321 
322  RzGetopt opt;
323  int c;
324  rz_getopt_init(&opt, argc, argv, "jD:e:vE:a:i:I:S:K:s:x:b:nBhf:t:kLqc:");
325  while ((c = rz_getopt_next(&opt)) != -1) {
326  switch (c) {
327  case 'q': rz_hash_ctx_set_quiet(ctx); break;
328  case 'i': rz_hash_ctx_set_signed(ctx, iterate, opt.arg); break;
329  case 'j': rz_hash_ctx_set_mode(ctx, RZ_HASH_MODE_JSON); break;
330  case 'S': rz_hash_set_val(ctx, seed, NULL, opt.arg); break;
331  case 'K': rz_hash_set_val(ctx, key, NULL, opt.arg); break;
332  case 'I': rz_hash_ctx_set_str(ctx, iv, opt.arg); break;
333  case 'D':
334  rz_hash_ctx_set_str(ctx, algorithm, opt.arg);
336  break;
337  case 'E':
338  rz_hash_ctx_set_str(ctx, algorithm, opt.arg);
340  break;
341  case 'L': rz_hash_ctx_set_op(ctx, RZ_HASH_OP_LIST_ALGO); break;
342  case 'e': rz_hash_ctx_set_bool(ctx, little_endian, opt.arg, "little", "big"); break;
344  case 'a':
345  rz_hash_ctx_set_str(ctx, algorithm, opt.arg);
347  break;
348  case 'B': ctx->show_blocks = true; break;
349  case 'b': rz_hash_ctx_set_unsigned(ctx, block_size, opt.arg); break;
350  case 'f': rz_hash_ctx_set_unsigned(ctx, offset.from, opt.arg); break;
351  case 't': rz_hash_ctx_set_unsigned(ctx, offset.to, opt.arg); break;
352  case 'v': ctx->operation = RZ_HASH_OP_VERSION; break;
353  case 'h': ctx->operation = RZ_HASH_OP_HELP; break;
354  case 's': rz_hash_ctx_set_input(ctx, input, opt.arg, false); break;
355  case 'x': rz_hash_ctx_set_input(ctx, input, opt.arg, true); break;
356  case 'c': rz_hash_ctx_set_str(ctx, compare, opt.arg); break;
357  default:
358  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "unknown flag '%c'\n", c);
359  }
360  }
361 
362  if (ctx->operation == RZ_HASH_OP_HELP ||
363  ctx->operation == RZ_HASH_OP_VERSION ||
364  ctx->operation == RZ_HASH_OP_LIST_ALGO) {
365  return;
366  }
367 
368  if (opt.ind >= argc && !ctx->input) {
369  ctx->operation = RZ_HASH_OP_USAGE;
370  return;
371  }
372 
373  if (!ctx->algorithm) {
374  rz_hash_ctx_set_str(ctx, algorithm, "sha256");
376  }
377 
378  if (!ctx->input && !strcmp(argv[argc - 1], "-")) {
379  ctx->use_stdin = true;
380  } else {
381  ctx->files = RZ_NEWS(const char *, argc - opt.ind);
382  if (!ctx->files) {
383  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "failed to allocate file array memory.\n");
384  }
385  ctx->nfiles = 0;
386  for (int i = opt.ind; i < argc; ++i) {
387  if (IS_NULLSTR(argv[i])) {
388  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "cannot open a file without a name.\n");
389  }
390  if (rz_file_is_directory(argv[i])) {
391  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "cannot open directories (%s).\n", argv[i]);
392  }
393  ctx->files[ctx->nfiles++] = argv[i];
394  }
395  }
396 
397  if (ctx->nfiles < 1 && !ctx->use_stdin && !ctx->input) {
398  ctx->operation = RZ_HASH_OP_USAGE;
399  return;
400  }
401 
402  if (strstr(ctx->algorithm, "luhn")) {
403  if (strchr(ctx->algorithm, ',')) {
404  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' is incompatible with multiple algorithms.\n");
405  }
406  if (!ctx->input || strncmp(ctx->input, "s:", 2)) {
407  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' requires -s option.\n");
408  }
409  if (ctx->mode == RZ_HASH_MODE_RANDOMART) {
410  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' is incompatible with -k option.\n");
411  }
412  if (ctx->show_blocks) {
413  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' is incompatible with -B option.\n");
414  }
415  if (ctx->block_size < strlen(ctx->algorithm + 2)) {
416  ctx->block_size = strlen(ctx->algorithm + 2);
417  }
418  if (ctx->compare) {
419  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' is incompatible with -c option.\n");
420  }
421  if (seed) {
422  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' is incompatible with -S option.\n");
423  }
424  if (key) {
425  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "algorithm 'luhn' is incompatible with -K option.\n");
426  }
427  ctx->operation = RZ_HASH_OP_LUHN;
428  } else if (ctx->operation == RZ_HASH_OP_ENCRYPT || ctx->operation == RZ_HASH_OP_DECRYPT) {
429  if (!key && strncmp("base", ctx->algorithm, 4) && strcmp("punycode", ctx->algorithm)) {
430  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -K is required for algorithm '%s'.\n", ctx->algorithm);
431  }
432  if (ctx->compare) {
433  ssize_t len = strlen(ctx->compare);
434  if (!strncmp(ctx->algorithm, "base", 4)) {
435  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -c is incompatible with -E or -D with algorithm base64 or base91.\n");
436  } else if (strchr(ctx->algorithm, ',')) {
437  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -c incompatible with multiple algorithms.\n");
438  } else if (len < 1 || c & 1) {
439  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -c value length is not multiple of 2 (expected hexadecimal value).\n");
440  }
441  }
442  if (ctx->show_blocks) {
443  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -B is incompatible with -E/-D.\n");
444  }
445  if (ctx->mode == RZ_HASH_MODE_RANDOMART) {
446  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -k is incompatible with -E/-D.\n");
447  }
448  } else if (ctx->operation == RZ_HASH_OP_HASH) {
449  if (ctx->iv) {
450  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -I is incompatible with -a; use -S to define a seed or -K to define an hmac key.\n");
451  }
452  if (ctx->show_blocks && ctx->compare) {
453  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -B is incompatible with -c option.\n");
454  }
455  if (ctx->mode == RZ_HASH_MODE_RANDOMART && ctx->compare) {
456  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -c is incompatible with -k option.\n");
457  }
458  if (ctx->mode == RZ_HASH_MODE_RANDOMART && strchr(ctx->algorithm, ',')) {
459  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -a with multiple algorithms is incompatible with -k option.\n");
460  }
461  }
462 
463  if (ctx->offset.from && ctx->offset.to && ctx->offset.from >= ctx->offset.to) {
464  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "option -f value (%" PFMT64u ") is greater or equal to -t value (%" PFMT64u ").\n", ctx->offset.from, ctx->offset.to);
465  }
466  if (ctx->block_size && ctx->offset.from && ctx->offset.to && (ctx->offset.to - ctx->offset.from) % ctx->block_size) {
467  rz_hash_error(ctx, RZ_HASH_OP_ERROR, "range between %" PFMT64u " and %" PFMT64u " is not a multiple of %" PFMT64u ".\n", ctx->offset.from, ctx->offset.to, ctx->block_size);
468  }
469 
470  if (seed) {
471  if (seed[0] == '^') {
472  seed++;
473  ctx->as_prefix = true;
474  }
475  if (!hash_parse_any(ctx, "-S", seed, &ctx->seed)) {
476  return;
477  }
478  }
479 
480  if (key && !hash_parse_any(ctx, "-K", key, &ctx->key)) {
481  return;
482  }
483 
484  if (!ctx->block_size) {
485  ctx->block_size = RZ_HASH_DEFAULT_BLOCK_SIZE;
486  }
487 }
488 
490  free(ctx->algorithm);
491  free(ctx->compare);
492  free(ctx->iv);
493  free(ctx->input);
494  free((char **)ctx->files);
495  free(ctx->seed.buf);
496  pj_free(ctx->pj);
497  rz_hash_free(ctx->rh);
498 }
499 
501  RzIODesc *desc = NULL;
502  int size;
503  char *uri = NULL;
504  ut8 *buffer = NULL;
505 
506  buffer = (ut8 *)rz_stdin_slurp(&size);
507  if (size < 1 || !buffer) {
508  goto rz_hash_context_create_desc_io_stdin_end;
509  }
510 
511  uri = rz_str_newf("malloc://%d", size);
512  if (!uri) {
514  goto rz_hash_context_create_desc_io_stdin_end;
515  }
516 
517  desc = rz_io_open_nomap(io, uri, RZ_PERM_R, 0);
518  if (!desc) {
519  RZ_LOG_ERROR("rz-hash: error, cannot open malloc://%d\n", size);
520  goto rz_hash_context_create_desc_io_stdin_end;
521  }
522 
523  if (rz_io_pwrite_at(io, 0, buffer, size) != size) {
524  RZ_LOG_ERROR("rz-hash: error, cannot write into malloc://%d buffer\n", size);
526  desc = NULL;
527  goto rz_hash_context_create_desc_io_stdin_end;
528  }
529 
530 rz_hash_context_create_desc_io_stdin_end:
531  free(buffer);
532  free(uri);
533  return desc;
534 }
535 
537  RzIODesc *desc = NULL;
538  char *uri = NULL;
539  ut8 *buffer = NULL;
540  size_t size;
541 
542  bool is_string = !strncmp(input, "s:", 2);
543 
544  if (is_string) {
545  if (!hash_parse_string("-s", input + 2, &buffer, &size)) {
546  goto rz_hash_context_create_desc_io_string_end;
547  }
548  } else {
549  if (!hash_parse_hexadecimal("-x", input, &buffer, &size)) {
550  goto rz_hash_context_create_desc_io_string_end;
551  }
552  }
553  if (!buffer || (!is_string && size < 1)) {
555  goto rz_hash_context_create_desc_io_string_end;
556  } else if (is_string && size < 1) {
557  goto rz_hash_context_create_desc_io_string_end;
558  }
559 
560  uri = rz_str_newf("malloc://%" PFMTSZu, size);
561  if (!uri) {
563  goto rz_hash_context_create_desc_io_string_end;
564  }
565 
566  desc = rz_io_open_nomap(io, uri, RZ_PERM_R, 0);
567  if (!desc) {
568  RZ_LOG_ERROR("rz-hash: error, cannot open malloc://%" PFMTSZu "\n", size);
569  goto rz_hash_context_create_desc_io_string_end;
570  }
571 
572  if (rz_io_pwrite_at(io, 0, buffer, size) != size) {
573  RZ_LOG_ERROR("rz-hash: error, cannot write into malloc://%" PFMTSZu " buffer\n", size);
575  desc = NULL;
576  goto rz_hash_context_create_desc_io_string_end;
577  }
578 
579 rz_hash_context_create_desc_io_string_end:
580  free(buffer);
581  free(uri);
582  return desc;
583 }
584 
586  bool result = false;
587  RzIODesc *desc = NULL;
588 
589  RzIO *io = rz_io_new();
590  if (!io) {
592  return false;
593  }
594 
595  if (ctx->mode == RZ_HASH_MODE_JSON) {
596  ctx->pj = pj_new();
597  if (!ctx->pj) {
598  RZ_LOG_ERROR("rz-hash: error, failed to allocate JSON memory.\n");
599  goto rz_hash_context_run_end;
600  }
601  pj_o(ctx->pj);
602  }
603  if (ctx->use_stdin) {
605  if (!desc) {
606  RZ_LOG_ERROR("rz-hash: error, cannot read stdin\n");
607  goto rz_hash_context_run_end;
608  }
609  if (ctx->mode == RZ_HASH_MODE_JSON) {
610  pj_ka(ctx->pj, "stdin");
611  }
612  if (!run(ctx, io, "stdin")) {
613  goto rz_hash_context_run_end;
614  }
615  if (ctx->mode == RZ_HASH_MODE_JSON) {
616  pj_end(ctx->pj);
617  }
618  } else if (ctx->input) {
619  if (strlen(ctx->input) > 0) {
621  if (!desc) {
622  RZ_LOG_ERROR("rz-hash: error, cannot read string\n");
623  goto rz_hash_context_run_end;
624  }
625  }
626  if (ctx->mode == RZ_HASH_MODE_JSON) {
627  pj_ka(ctx->pj, !strncmp(ctx->input, "s:", 2) ? "string" : "hexadecimal");
628  }
629  if (!run(ctx, io, !strncmp(ctx->input, "s:", 2) ? "string" : "hexadecimal")) {
630  goto rz_hash_context_run_end;
631  }
632  if (ctx->mode == RZ_HASH_MODE_JSON) {
633  pj_end(ctx->pj);
634  }
635  } else {
636  for (ut32 i = 0; i < ctx->nfiles; ++i) {
637  desc = rz_io_open_nomap(io, ctx->files[i], RZ_PERM_R, 0);
638  if (!desc) {
639  RZ_LOG_ERROR("rz-hash: error, cannot open file '%s'\n", ctx->files[i]);
640  goto rz_hash_context_run_end;
641  }
642  if (ctx->mode == RZ_HASH_MODE_JSON) {
643  pj_ka(ctx->pj, ctx->files[i]);
644  }
645  if (!run(ctx, io, ctx->files[i])) {
646  goto rz_hash_context_run_end;
647  }
648  if (ctx->mode == RZ_HASH_MODE_JSON) {
649  pj_end(ctx->pj);
650  }
652  desc = NULL;
653  }
654  }
655  if (ctx->mode == RZ_HASH_MODE_JSON) {
656  pj_end(ctx->pj);
657  printf("%s\n", pj_string(ctx->pj));
658  }
659  result = true;
660 
661 rz_hash_context_run_end:
663  rz_io_free(io);
664  return result;
665 }
666 
667 static void hash_print_crypto(RzHashContext *ctx, const char *hname, const ut8 *buffer, int len, ut64 from, ut64 to) {
668  char *value = ctx->operation == RZ_HASH_OP_ENCRYPT ? malloc(len * 2 + 1) : malloc(len + 1);
669  if (!value) {
670  RZ_LOG_ERROR("rz-hash: error, cannot allocate value memory\n");
671  return;
672  }
673 
674  if (ctx->operation == RZ_HASH_OP_ENCRYPT) {
675  for (int i = 0, bsize; i < len; i++) {
676  bsize = (len - i) * 2 + 1;
677  snprintf(value + (i * 2), bsize, "%02x", buffer[i]);
678  }
679  } else {
680  memcpy(value, buffer, len);
681  value[len] = 0;
682  }
683 
684  switch (ctx->mode) {
685  case RZ_HASH_MODE_JSON:
686  pj_kn(ctx->pj, "from", from);
687  pj_kn(ctx->pj, "to", to);
688  pj_ks(ctx->pj, "name", hname);
689  pj_ks(ctx->pj, "value", value);
690  break;
693  printf("0x%08" PFMT64x "-0x%08" PFMT64x " %s: ", from, to, hname);
694  fflush(stdout);
695  if (write(1, buffer, len) != len) {
696  RZ_LOG_ERROR("rz-hash: error, cannot write on stdout\n");
697  }
698  printf("\n");
699  break;
700  case RZ_HASH_MODE_QUIET:
701  printf("%s: ", hname);
702  fflush(stdout);
703  if (write(1, buffer, len) != len) {
704  RZ_LOG_ERROR("rz-hash: error, cannot write on stdout\n");
705  }
706  printf("\n");
707  break;
709  if (write(1, buffer, len) != len) {
710  RZ_LOG_ERROR("rz-hash: error, cannot write on stdout\n");
711  }
712  break;
713  }
714  free(value);
715 }
716 
717 static void hash_print_digest(RzHashContext *ctx, RzHashCfg *md, const char *hname, ut64 from, ut64 to, const char *filename) {
718  RzHashSize len = 0;
719  char *value = NULL;
720  char *rndart = NULL;
721  const ut8 *buffer;
722 
723  buffer = rz_hash_cfg_get_result(md, hname, &len);
724  value = rz_hash_cfg_get_result_string(md, hname, NULL, ctx->little_endian);
725  if (!value || !buffer) {
726  free(value);
727  return;
728  }
729 
730  bool has_seed = !ctx->iv && ctx->seed.len > 0;
731  const char *hmac = ctx->key.len > 0 ? "hmac-" : "";
732 
733  switch (ctx->mode) {
734  case RZ_HASH_MODE_JSON:
735  pj_kb(ctx->pj, "seed", has_seed);
736  pj_kb(ctx->pj, "hmac", ctx->key.len > 0);
737  pj_kn(ctx->pj, "from", from);
738  pj_kn(ctx->pj, "to", to);
739  pj_ks(ctx->pj, "name", hname);
740  pj_ks(ctx->pj, "value", value);
741  break;
743  printf("%s: 0x%08" PFMT64x "-0x%08" PFMT64x " %s%s: %s%s\n", filename, from, to, hmac, hname, value, has_seed ? " with seed" : "");
744  break;
746  rndart = rz_hash_cfg_randomart(buffer, len, from);
747  printf("%s%s\n%s\n", hmac, hname, rndart);
748  break;
749  case RZ_HASH_MODE_QUIET:
750  printf("%s: %s%s: %s\n", filename, hmac, hname, value);
751  break;
753  puts(value);
754  break;
755  }
756  free(value);
757  free(rndart);
758 }
759 
760 static void hash_context_compare_hashes(RzHashContext *ctx, size_t filesize, bool result, const char *hname, const char *filename) {
761  ut64 to = ctx->offset.to ? ctx->offset.to : filesize;
762  const char *hmac = ctx->key.len > 0 ? "hmac-" : "";
763  switch (ctx->mode) {
764  case RZ_HASH_MODE_JSON:
765  pj_kb(ctx->pj, "seed", ctx->seed.len > 0);
766  pj_kb(ctx->pj, "hmac", ctx->key.len > 0);
767  pj_kb(ctx->pj, "compare", result);
768  pj_kn(ctx->pj, "from", ctx->offset.from);
769  pj_kn(ctx->pj, "to", to);
770  pj_ks(ctx->pj, "name", hname);
771  break;
774  printf("%s: 0x%08" PFMT64x "-0x%08" PFMT64x " %s%s: computed hash %s the expected one\n", filename, ctx->offset.from, to, hmac, hname, result ? "matches" : "doesn't match");
775  break;
776  case RZ_HASH_MODE_QUIET:
777  printf("%s: %s%s: computed hash %s the expected one\n", filename, hmac, hname, result ? "matches" : "doesn't match");
778  break;
780  printf("%s", result ? "true" : "false");
781  break;
782  }
783 }
784 
786  if (!strcmp(ctx->algorithm, "all")) {
787  const RzHashPlugin *plugin;
789  if (!list) {
790  return NULL;
791  }
792  for (ut64 i = 0; (plugin = rz_hash_plugin_by_index(ctx->rh, i)); ++i) {
793  rz_list_append(list, (void *)plugin->name);
794  }
795  return list;
796  }
797  return rz_str_split_list(ctx->algorithm, ",", 0);
798 }
799 
800 static bool calculate_hash(RzHashContext *ctx, RzIO *io, const char *filename) {
801  bool result = false;
802  const char *algorithm;
803  RzList *algorithms = NULL;
804  RzListIter *it;
805  RzHashCfg *md = NULL;
806  ut64 bsize = 0;
807  ut64 filesize;
808  ut8 *block = NULL;
809  ut8 *cmphash = NULL;
810  const ut8 *digest = NULL;
811  RzHashSize digest_size = 0;
812 
813  algorithms = parse_hash_algorithms(ctx);
814  if (!algorithms || rz_list_length(algorithms) < 1) {
815  RZ_LOG_ERROR("rz-hash: error, empty list of hash algorithms\n");
816  goto calculate_hash_end;
817  }
818 
819  filesize = rz_io_desc_size(io->desc);
820 
821  md = rz_hash_cfg_new(ctx->rh);
822  if (!md) {
823  RZ_LOG_ERROR("rz-hash: error, cannot allocate hash context memory\n");
824  goto calculate_hash_end;
825  }
826 
827  if (ctx->offset.to > filesize) {
828  RZ_LOG_ERROR("rz-hash: error, -t value is greater than file size\n");
829  goto calculate_hash_end;
830  }
831 
832  if (ctx->offset.from > filesize) {
833  RZ_LOG_ERROR("rz-hash: error, -f value is greater than file size\n");
834  goto calculate_hash_end;
835  }
836 
837  bsize = ctx->block_size;
838  block = malloc(bsize);
839  if (!block) {
840  RZ_LOG_ERROR("rz-hash: error, cannot allocate block memory\n");
841  goto calculate_hash_end;
842  }
843 
844  rz_list_foreach (algorithms, it, algorithm) {
845  if (!rz_hash_cfg_configure(md, algorithm)) {
846  goto calculate_hash_end;
847  }
848  }
849 
850  if (ctx->key.len > 0 && !rz_hash_cfg_hmac(md, ctx->key.buf, ctx->key.len)) {
851  goto calculate_hash_end;
852  }
853 
854  if (ctx->compare) {
855  ut64 to = ctx->offset.to ? ctx->offset.to : filesize;
856  size_t cmphashlen = 0;
857  bool result = false;
858 
859  if (!hash_parse_hexadecimal("-c", ctx->compare, &cmphash, &cmphashlen)) {
860  // RZ_LOG_ERROR("rz-hash: error, cannot allocate block memory\n");
861  goto calculate_hash_end;
862  }
863 
864  if (!rz_hash_cfg_init(md)) {
865  goto calculate_hash_end;
866  }
867 
868  if (ctx->as_prefix && ctx->seed.buf &&
869  !rz_hash_cfg_update(md, ctx->seed.buf, ctx->seed.len)) {
870  goto calculate_hash_end;
871  }
872 
873  for (ut64 j = ctx->offset.from; j < to; j += bsize) {
874  int read = rz_io_pread_at(io, j, block, to - j > bsize ? bsize : (to - j));
875  if (!rz_hash_cfg_update(md, block, read)) {
876  goto calculate_hash_end;
877  }
878  }
879 
880  if (!ctx->as_prefix && ctx->seed.buf &&
881  !rz_hash_cfg_update(md, ctx->seed.buf, ctx->seed.len)) {
882  goto calculate_hash_end;
883  }
884  if (!rz_hash_cfg_final(md) ||
885  !rz_hash_cfg_iterate(md, ctx->iterate)) {
886  goto calculate_hash_end;
887  }
888 
889  rz_list_foreach (algorithms, it, algorithm) {
890  digest = rz_hash_cfg_get_result(md, algorithm, &digest_size);
891  if (digest_size != cmphashlen) {
892  result = false;
893  } else {
894  result = !memcmp(cmphash, digest, digest_size);
895  }
896 
897  if (ctx->mode == RZ_HASH_MODE_JSON) {
898  pj_o(ctx->pj);
899  }
900  hash_context_compare_hashes(ctx, filesize, result, algorithm, filename);
901  if (ctx->mode == RZ_HASH_MODE_JSON) {
902  pj_end(ctx->pj);
903  }
904  }
905  } else if (ctx->show_blocks) {
906  ut64 to = ctx->offset.to ? ctx->offset.to : filesize;
907  for (ut64 j = ctx->offset.from; j < to; j += bsize) {
908  int read = rz_io_pread_at(io, j, block, to - j > bsize ? bsize : (to - j));
909  if (!rz_hash_cfg_init(md) ||
910  !rz_hash_cfg_update(md, block, read) ||
911  !rz_hash_cfg_final(md) ||
912  !rz_hash_cfg_iterate(md, ctx->iterate)) {
913  goto calculate_hash_end;
914  }
915 
916  rz_list_foreach (algorithms, it, algorithm) {
917  digest = rz_hash_cfg_get_result(md, algorithm, &digest_size);
918  if (ctx->mode == RZ_HASH_MODE_JSON) {
919  pj_o(ctx->pj);
920  }
921  hash_print_digest(ctx, md, algorithm, j, j + bsize, filename);
922  if (ctx->mode == RZ_HASH_MODE_JSON) {
923  pj_end(ctx->pj);
924  }
925  }
926  }
927  } else {
928  ut64 to = ctx->offset.to ? ctx->offset.to : filesize;
929  if (!rz_hash_cfg_init(md)) {
930  goto calculate_hash_end;
931  }
932 
933  if (ctx->as_prefix && ctx->seed.buf &&
934  !rz_hash_cfg_update(md, ctx->seed.buf, ctx->seed.len)) {
935  goto calculate_hash_end;
936  }
937 
938  for (ut64 j = ctx->offset.from; j < to; j += bsize) {
939  int read = rz_io_pread_at(io, j, block, to - j > bsize ? bsize : (to - j));
940  if (!rz_hash_cfg_update(md, block, read)) {
941  goto calculate_hash_end;
942  }
943  }
944 
945  if (!ctx->as_prefix && ctx->seed.buf &&
946  !rz_hash_cfg_update(md, ctx->seed.buf, ctx->seed.len)) {
947  goto calculate_hash_end;
948  }
949 
950  if (!rz_hash_cfg_final(md) ||
951  !rz_hash_cfg_iterate(md, ctx->iterate)) {
952  goto calculate_hash_end;
953  }
954 
955  rz_list_foreach (algorithms, it, algorithm) {
956  digest = rz_hash_cfg_get_result(md, algorithm, &digest_size);
957 
958  if (ctx->mode == RZ_HASH_MODE_JSON) {
959  pj_o(ctx->pj);
960  }
961  hash_print_digest(ctx, md, algorithm, ctx->offset.from, to, filename);
962  if (ctx->mode == RZ_HASH_MODE_JSON) {
963  pj_end(ctx->pj);
964  }
965  }
966  }
967  result = true;
968 
969 calculate_hash_end:
970  rz_list_free(algorithms);
971  free(block);
972  free(cmphash);
974  return result;
975 }
976 
977 static bool calculate_decrypt(RzHashContext *ctx, RzIO *io, const char *filename) {
978  RzCrypto *cry = NULL;
979  bool result = false;
980  ut8 *iv = NULL;
981  size_t ivlen = 0;
982  ut64 filesize = 0;
983  ut64 bsize = 0;
984  ut8 *block = NULL;
985 
986  if (ctx->iv) {
987  if (!strncmp(ctx->iv, "s:", 2)) {
988  if (!hash_parse_string("-I", ctx->iv + 2, &iv, &ivlen)) {
989  goto calculate_decrypt_end;
990  }
991  } else {
992  if (!hash_parse_hexadecimal("-I", ctx->iv, &iv, &ivlen)) {
993  goto calculate_decrypt_end;
994  }
995  }
996  }
997 
998  cry = rz_crypto_new();
999  if (!cry) {
1000  RZ_LOG_ERROR("rz-hash: error, failed to allocate memory\n");
1001  goto calculate_decrypt_end;
1002  }
1003 
1004  if (!rz_crypto_use(cry, ctx->algorithm)) {
1005  RZ_LOG_ERROR("rz-hash: error, unknown encryption algorithm '%s'\n", ctx->algorithm);
1006  goto calculate_decrypt_end;
1007  }
1008 
1009  if (!rz_crypto_set_key(cry, ctx->key.buf, ctx->key.len, 0, RZ_CRYPTO_DIR_DECRYPT)) {
1010  RZ_LOG_ERROR("rz-hash: error, invalid key\n");
1011  goto calculate_decrypt_end;
1012  }
1013 
1014  if (iv && !rz_crypto_set_iv(cry, iv, ivlen)) {
1015  RZ_LOG_ERROR("rz-hash: error, invalid IV.\n");
1016  goto calculate_decrypt_end;
1017  }
1018 
1019  filesize = rz_io_desc_size(io->desc);
1020  if (filesize < 1) {
1021  RZ_LOG_ERROR("rz-hash: error, file size is less than 1\n");
1022  goto calculate_decrypt_end;
1023  }
1024 
1025  bsize = ctx->block_size;
1026  block = malloc(bsize);
1027  if (!block) {
1028  RZ_LOG_ERROR("rz-hash: error, cannot allocate block memory\n");
1029  goto calculate_decrypt_end;
1030  }
1031 
1032  ut64 to = ctx->offset.to ? ctx->offset.to : filesize;
1033  for (ut64 j = ctx->offset.from; j < to; j += bsize) {
1034  int read = rz_io_pread_at(io, j, block, to - j > bsize ? bsize : (to - j));
1035  rz_crypto_update(cry, block, read);
1036  }
1037 
1038  rz_crypto_final(cry, NULL, 0);
1039 
1040  int plaintext_size = 0;
1041  const ut8 *plaintext = rz_crypto_get_output(cry, &plaintext_size);
1042 
1043  hash_print_crypto(ctx, ctx->algorithm, plaintext, plaintext_size, ctx->offset.from, to);
1044  result = true;
1045 
1046 calculate_decrypt_end:
1047  free(block);
1048  free(iv);
1049  rz_crypto_free(cry);
1050  return result;
1051 }
1052 
1053 static bool calculate_encrypt(RzHashContext *ctx, RzIO *io, const char *filename) {
1054  RzCrypto *cry = NULL;
1055  bool result = false;
1056  ut8 *iv = NULL;
1057  size_t ivlen = 0;
1058  ut64 filesize = 0;
1059  ut64 bsize = 0;
1060  ut8 *block = NULL;
1061 
1062  bool requires_key = !strncmp("base", ctx->algorithm, 4) || !strcmp("punycode", ctx->algorithm);
1063  if (!requires_key && ctx->key.len < 1) {
1064  RZ_LOG_ERROR("rz-hash: error, cannot encrypt without a key\n");
1065  goto calculate_encrypt_end;
1066  }
1067 
1068  if (ctx->iv) {
1069  if (!strncmp(ctx->iv, "s:", 2)) {
1070  if (!hash_parse_string("-I", ctx->iv + 2, &iv, &ivlen)) {
1071  goto calculate_encrypt_end;
1072  }
1073  } else {
1074  if (!hash_parse_hexadecimal("-I", ctx->iv, &iv, &ivlen)) {
1075  goto calculate_encrypt_end;
1076  }
1077  }
1078  }
1079 
1080  cry = rz_crypto_new();
1081  if (!cry) {
1082  RZ_LOG_ERROR("rz-hash: error, failed to allocate memory\n");
1083  goto calculate_encrypt_end;
1084  }
1085 
1086  if (!rz_crypto_use(cry, ctx->algorithm)) {
1087  RZ_LOG_ERROR("rz-hash: error, unknown encryption algorithm '%s'\n", ctx->algorithm);
1088  goto calculate_encrypt_end;
1089  }
1090 
1091  if (!rz_crypto_set_key(cry, ctx->key.buf, ctx->key.len, 0, RZ_CRYPTO_DIR_ENCRYPT)) {
1092  RZ_LOG_ERROR("rz-hash: error, invalid key\n");
1093  goto calculate_encrypt_end;
1094  }
1095 
1096  if (iv && !rz_crypto_set_iv(cry, iv, ivlen)) {
1097  RZ_LOG_ERROR("rz-hash: error, invalid IV.\n");
1098  goto calculate_encrypt_end;
1099  }
1100 
1101  filesize = rz_io_desc_size(io->desc);
1102  if (filesize < 1) {
1103  RZ_LOG_ERROR("rz-hash: error, file size is less than 1\n");
1104  goto calculate_encrypt_end;
1105  }
1106 
1107  bsize = ctx->block_size;
1108  block = malloc(bsize);
1109  if (!block) {
1110  RZ_LOG_ERROR("rz-hash: error, cannot allocate block memory\n");
1111  goto calculate_encrypt_end;
1112  }
1113 
1114  ut64 to = ctx->offset.to ? ctx->offset.to : filesize;
1115  for (ut64 j = ctx->offset.from; j < to; j += bsize) {
1116  int read = rz_io_pread_at(io, j, block, to - j > bsize ? bsize : (to - j));
1117  rz_crypto_update(cry, block, read);
1118  }
1119 
1120  rz_crypto_final(cry, NULL, 0);
1121 
1122  int ciphertext_size = 0;
1123  const ut8 *ciphertext = rz_crypto_get_output(cry, &ciphertext_size);
1124 
1125  hash_print_crypto(ctx, ctx->algorithm, ciphertext, ciphertext_size, ctx->offset.from, to);
1126  result = true;
1127 
1128 calculate_encrypt_end:
1129  free(block);
1130  free(iv);
1131  rz_crypto_free(cry);
1132  return result;
1133 }
1134 
1135 static bool calculate_luhn(RzHashContext *ctx, RzIO *io, const char *filename) {
1136  char value[128];
1137  const char *input = ctx->input + 2;
1138  ut64 to = ctx->offset.to ? ctx->offset.to : strlen(input);
1139  ut64 from = ctx->offset.from;
1140  ut64 result = 0;
1141 
1142  if (!rz_calculate_luhn_value(input, &result)) {
1143  RZ_LOG_ERROR("rz-hash: error, input string is not a number\n");
1144  return false;
1145  }
1146 
1147  snprintf(value, sizeof(value), "%" PFMT64u, result);
1148  switch (ctx->mode) {
1149  case RZ_HASH_MODE_JSON:
1150  pj_o(ctx->pj);
1151  pj_kb(ctx->pj, "seed", false);
1152  pj_kb(ctx->pj, "hmac", false);
1153  pj_kn(ctx->pj, "from", from);
1154  pj_kn(ctx->pj, "to", to);
1155  pj_ks(ctx->pj, "name", ctx->algorithm);
1156  pj_ks(ctx->pj, "value", value);
1157  pj_end(ctx->pj);
1158  break;
1159  case RZ_HASH_MODE_STANDARD:
1160  printf("%s: 0x%08" PFMT64x "-0x%08" PFMT64x " %s: %s\n", filename, from, to, ctx->algorithm, value);
1161  break;
1163  case RZ_HASH_MODE_QUIET:
1164  printf("%s: %s: %s\n", filename, ctx->algorithm, value);
1165  break;
1167  puts(value);
1168  break;
1169  }
1170  return true;
1171 }
1172 
1173 static int lib_hash_cb(RzLibPlugin *pl, void *user, void *data) {
1174  RzHashPlugin *hand = (RzHashPlugin *)data;
1175  RzHashContext *ctx = (RzHashContext *)user;
1176  return rz_hash_plugin_add(ctx->rh, hand);
1177 }
1178 
1180  char *tmp = rz_sys_getenv("RZ_ASM_NOPLUGINS");
1181  if (tmp) {
1182  free(tmp);
1183  return;
1184  }
1185  RzLib *rl = rz_lib_new(NULL, NULL);
1186  rz_lib_add_handler(rl, RZ_LIB_TYPE_HASH, "hash plugins", &lib_hash_cb, NULL, ctx);
1187 
1188  char *path = rz_sys_getenv(RZ_LIB_ENV);
1189  if (!RZ_STR_ISEMPTY(path)) {
1190  rz_lib_opendir(rl, path, false);
1191  }
1192 
1193  char *homeplugindir = rz_path_home_prefix(RZ_PLUGINS);
1194  char *sysplugindir = rz_path_system(RZ_PLUGINS);
1195  rz_lib_opendir(rl, homeplugindir, false);
1196  rz_lib_opendir(rl, sysplugindir, false);
1197  free(homeplugindir);
1198  free(sysplugindir);
1199 
1200  free(path);
1201  rz_lib_free(rl);
1202  free(tmp);
1203 }
1204 
1205 RZ_API int rz_main_rz_hash(int argc, const char **argv) {
1206  int result = 1;
1207  RzHashContext ctx = { 0 };
1208  ctx.rh = rz_hash_new();
1210 
1211  hash_parse_cmdline(argc, argv, &ctx);
1212 
1213  switch (ctx.operation) {
1214  case RZ_HASH_OP_LIST_ALGO:
1216  break;
1217  case RZ_HASH_OP_LUHN:
1219  goto rz_main_rz_hash_end;
1220  }
1221  break;
1222  case RZ_HASH_OP_HASH:
1224  goto rz_main_rz_hash_end;
1225  }
1226  break;
1227  case RZ_HASH_OP_DECRYPT:
1229  goto rz_main_rz_hash_end;
1230  }
1231  break;
1232  case RZ_HASH_OP_ENCRYPT:
1234  goto rz_main_rz_hash_end;
1235  }
1236  break;
1237  case RZ_HASH_OP_VERSION:
1238  rz_main_version_print("rz-hash");
1239  break;
1240  case RZ_HASH_OP_USAGE:
1241  rz_hash_show_help(true);
1242  goto rz_main_rz_hash_end;
1243  case RZ_HASH_OP_ERROR:
1244  goto rz_main_rz_hash_end;
1245  case RZ_HASH_OP_HELP:
1246  result = 0;
1247  /* fall-thru */
1248  default:
1249  rz_hash_show_help(false);
1250  goto rz_main_rz_hash_end;
1251  }
1252 
1253  result = 0;
1254 
1255 rz_main_rz_hash_end:
1257  return result;
1258 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
const char * desc
Definition: bin_vsf.c:19
struct buffer buffer
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RZ_API int rz_crypto_update(RzCrypto *cry, const ut8 *buf, int len)
Definition: crypto.c:166
RZ_API bool rz_crypto_set_iv(RzCrypto *cry, const ut8 *iv, int ivlen)
Definition: crypto.c:161
RZ_API int rz_crypto_final(RzCrypto *cry, const ut8 *buf, int len)
Definition: crypto.c:170
RZ_API const ut8 * rz_crypto_get_output(RzCrypto *cry, int *size)
Definition: crypto.c:193
RZ_API bool rz_crypto_set_key(RzCrypto *cry, const ut8 *key, int keylen, int mode, int direction)
Definition: crypto.c:151
RZ_API void rz_crypto_free(RzCrypto *cry)
Definition: crypto.c:116
RZ_API RzCrypto * rz_crypto_new(void)
Definition: crypto.c:83
RZ_API const RzCryptoPlugin * rz_crypto_plugin_by_index(size_t index)
Definition: crypto.c:64
RZ_API bool rz_crypto_use(RzCrypto *cry, const char *algo)
Definition: crypto.c:130
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
static static fork write
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
static int is_string(const ut8 *buf, int size, int *len)
Definition: data.c:7
uint32_t ut32
RZ_API RZ_BORROW const ut8 * rz_hash_cfg_get_result(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const char *name, RZ_NONNULL ut32 *size)
Returns the digest value of the requested algorithm name.
Definition: hash.c:445
RZ_API RZ_OWN RzHashCfg * rz_hash_cfg_new(RZ_NONNULL RzHash *rh)
Definition: hash.c:134
RZ_API bool rz_hash_plugin_add(RZ_NONNULL RzHash *rh, RZ_NONNULL RZ_OWN const RzHashPlugin *plugin)
Add a new plugin to rh so that RzHashCfg can be created using specific algorithms.
Definition: hash.c:609
RZ_API void rz_hash_cfg_free(RZ_NONNULL RzHashCfg *md)
Definition: hash.c:186
RZ_API bool rz_hash_cfg_iterate(RZ_NONNULL RzHashCfg *md, size_t iterate)
Calculate the final hash by iterating its result N times.
Definition: hash.c:414
RZ_API void rz_hash_free(RzHash *rh)
Definition: hash.c:597
RZ_API RZ_BORROW const RzHashPlugin * rz_hash_plugin_by_index(RZ_NONNULL RzHash *rh, size_t index)
Definition: hash.c:104
RZ_API RzHash * rz_hash_new(void)
Definition: hash.c:585
RZ_API bool rz_hash_cfg_configure(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const char *name)
Allocates and configures the plugin message digest context.
Definition: hash.c:199
RZ_API bool rz_hash_cfg_hmac(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const ut8 *key, ut64 key_size)
Sets the key for the hmac algorithm.
Definition: hash.c:250
RZ_API bool rz_hash_cfg_init(RZ_NONNULL RzHashCfg *md)
Resets/initialize the message digest contextes.
Definition: hash.c:298
RZ_API bool rz_hash_cfg_update(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const ut8 *data, ut64 size)
Inserts data into each the message digest contextes.
Definition: hash.c:337
RZ_API bool rz_hash_cfg_final(RZ_NONNULL RzHashCfg *md)
Generates the final value of the message digest contextes.
Definition: hash.c:359
RZ_API RZ_OWN char * rz_hash_cfg_get_result_string(RZ_NONNULL RzHashCfg *md, RZ_NONNULL const char *name, RZ_NULLABLE ut32 *size, bool invert)
Returns the digest value of the requested algorithm name.
Definition: hash.c:469
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
const char * filename
Definition: ioapi.h:137
voidpf uLong offset
Definition: ioapi.h:144
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static int compare(const char *s1, const char *s2, int l1, int l2)
Definition: chmd.c:864
static void list(RzEgg *egg)
Definition: rz-gg.c:52
static void hash_context_fini(RzHashContext *ctx)
Definition: rz-hash.c:489
static RzList * parse_hash_algorithms(RzHashContext *ctx)
Definition: rz-hash.c:785
#define rz_hash_ctx_set_op(x, o)
Definition: rz-hash.c:219
RzHashMode
Definition: rz-hash.c:21
@ RZ_HASH_MODE_QUIET
Definition: rz-hash.c:25
@ RZ_HASH_MODE_VERY_QUIET
Definition: rz-hash.c:26
@ RZ_HASH_MODE_STANDARD
Definition: rz-hash.c:22
@ RZ_HASH_MODE_RANDOMART
Definition: rz-hash.c:24
@ RZ_HASH_MODE_JSON
Definition: rz-hash.c:23
static bool hash_context_run(RzHashContext *ctx, RzHashRun run)
Definition: rz-hash.c:585
static bool calculate_encrypt(RzHashContext *ctx, RzIO *io, const char *filename)
Definition: rz-hash.c:1053
#define rz_hash_ctx_set_mode(x, m)
Definition: rz-hash.c:218
RzHashOp
Definition: rz-hash.c:29
@ RZ_HASH_OP_HASH
Definition: rz-hash.c:36
@ RZ_HASH_OP_HELP
Definition: rz-hash.c:32
@ RZ_HASH_OP_USAGE
Definition: rz-hash.c:33
@ RZ_HASH_OP_VERSION
Definition: rz-hash.c:34
@ RZ_HASH_OP_UNKNOWN
Definition: rz-hash.c:30
@ RZ_HASH_OP_DECRYPT
Definition: rz-hash.c:37
@ RZ_HASH_OP_LIST_ALGO
Definition: rz-hash.c:35
@ RZ_HASH_OP_LUHN
Definition: rz-hash.c:39
@ RZ_HASH_OP_ENCRYPT
Definition: rz-hash.c:38
@ RZ_HASH_OP_ERROR
Definition: rz-hash.c:31
static void hash_load_plugins(RzHashContext *ctx)
Definition: rz-hash.c:1179
#define rz_hash_ctx_set_input(x, k, s, h)
Definition: rz-hash.c:207
#define rz_hash_error(x, o, f,...)
Definition: rz-hash.c:146
#define RZ_HASH_DEFAULT_BLOCK_SIZE
Definition: rz-hash.c:14
static RzIODesc * hash_context_create_desc_io_string(RzIO *io, const char *input)
Definition: rz-hash.c:536
#define rz_hash_ctx_set_signed(x, k, i)
Definition: rz-hash.c:191
static RzIODesc * hash_context_create_desc_io_stdin(RzIO *io)
Definition: rz-hash.c:500
static bool calculate_hash(RzHashContext *ctx, RzIO *io, const char *filename)
Definition: rz-hash.c:800
static void rz_hash_show_help(bool usage_only)
Definition: rz-hash.c:72
RZ_API int rz_main_rz_hash(int argc, const char **argv)
Definition: rz-hash.c:1205
static void hash_context_compare_hashes(RzHashContext *ctx, size_t filesize, bool result, const char *hname, const char *filename)
Definition: rz-hash.c:760
static void hash_print_digest(RzHashContext *ctx, RzHashCfg *md, const char *hname, ut64 from, ut64 to, const char *filename)
Definition: rz-hash.c:717
static void hash_print_crypto(RzHashContext *ctx, const char *hname, const ut8 *buffer, int len, ut64 from, ut64 to)
Definition: rz-hash.c:667
#define rz_hash_ctx_set_unsigned(x, k, i)
Definition: rz-hash.c:199
static void hash_parse_cmdline(int argc, const char **argv, RzHashContext *ctx)
Definition: rz-hash.c:318
#define rz_hash_bool_error(x, o, f,...)
Definition: rz-hash.c:141
static bool hash_parse_any(RzHashContext *ctx, const char *option, const char *arg, RzHashBuffer *hb)
Definition: rz-hash.c:290
bool(* RzHashRun)(RzHashContext *ctx, RzIO *io, const char *filename)
Definition: rz-hash.c:70
static int lib_hash_cb(RzLibPlugin *pl, void *user, void *data)
Definition: rz-hash.c:1173
static bool calculate_luhn(RzHashContext *ctx, RzIO *io, const char *filename)
Definition: rz-hash.c:1135
#define rz_hash_ctx_set_bool(x, k, i, t, f)
Definition: rz-hash.c:167
static bool hash_parse_string(const char *option, const char *string, ut8 **buffer, size_t *bufsize)
Definition: rz-hash.c:222
static bool hash_parse_hexadecimal(const char *option, const char *hexadecimal, ut8 **buffer, size_t *bufsize)
Definition: rz-hash.c:254
#define rz_hash_set_val(x, k, d, v)
Definition: rz-hash.c:151
#define rz_hash_ctx_set_quiet(x)
Definition: rz-hash.c:178
struct rz_hash_context RzHashContext
static bool calculate_decrypt(RzHashContext *ctx, RzIO *io, const char *filename)
Definition: rz-hash.c:977
static void rz_hash_show_algorithms(RzHashContext *ctx)
Definition: rz-hash.c:109
#define rz_hash_ctx_set_str(x, k, s)
Definition: rz-hash.c:220
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
RZ_API RZ_OWN char * rz_hash_cfg_randomart(RZ_NONNULL const ut8 *buffer, ut32 length, ut64 address)
Generates a randomart that is meant to be an easily validate buffers.
Definition: randomart.c:55
static int run(int i, const char *arg)
Definition: rz-bb.c:19
#define rz_warn_if_reached()
Definition: rz_assert.h:29
@ RZ_CRYPTO_DIR_DECRYPT
Definition: rz_crypto.h:24
@ RZ_CRYPTO_DIR_ENCRYPT
Definition: rz_crypto.h:23
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
RZ_API char * rz_stdin_slurp(int *sz)
Definition: file.c:408
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API void rz_getopt_init(RzGetopt *go, int argc, const char **argv, const char *ostr)
Definition: getopt.c:17
RZ_API int rz_getopt_next(RzGetopt *opt)
Definition: getopt.c:29
ut32 RzHashSize
Definition: rz_hash.h:24
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
RZ_API int rz_io_pwrite_at(RzIO *io, ut64 paddr, const ut8 *buf, int len)
Definition: io.c:277
RZ_API ut64 rz_io_desc_size(RzIODesc *desc)
Definition: io_desc.c:224
RZ_API void rz_io_free(RzIO *io)
Definition: io.c:126
RZ_API RzIODesc * rz_io_open_nomap(RzIO *io, const char *uri, int flags, int mode)
Definition: io.c:145
RZ_API int rz_io_pread_at(RzIO *io, ut64 paddr, ut8 *buf, int len)
Definition: io.c:269
RZ_API RzIO * rz_io_new(void)
Definition: io.c:110
RZ_API bool rz_io_desc_close(RzIODesc *desc)
Definition: io_desc.c:165
RZ_API void rz_lib_free(RzLib *lib)
Definition: lib.c:189
#define RZ_LIB_ENV
Definition: rz_lib.h:23
RZ_API RzLib * rz_lib_new(const char *symname, const char *symnamefunc)
Definition: lib.c:176
@ RZ_LIB_TYPE_HASH
Definition: rz_lib.h:82
RZ_API bool rz_lib_opendir(RzLib *lib, const char *path, bool force)
Open all the libraries in the given directory, if it wasn't already opened.
Definition: lib.c:417
RZ_API bool rz_lib_add_handler(RzLib *lib, int type, const char *desc, RzLibCallback ct, RzLibCallback dt, void *user)
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API bool rz_calculate_luhn_value(const char *data, ut64 *result)
Definition: luhn.c:6
RZ_API int rz_main_version_print(const char *program)
Definition: main.c:49
RZ_API RZ_OWN char * rz_path_home_prefix(RZ_NULLABLE const char *path)
Return path prefixed by the home prefix.
Definition: path.c:182
RZ_API RZ_OWN char * rz_path_system(RZ_NULLABLE const char *path)
Return the full system path of the given subpath path.
Definition: path.c:162
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
Definition: pj.c:177
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API RzList * rz_str_split_list(char *str, const char *c, int n)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3429
RZ_API int rz_str_unescape(char *buf)
Definition: str.c:1300
#define IS_NULLSTR(x)
Definition: rz_str_util.h:4
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define RZ_PERM_R
Definition: rz_types.h:93
#define PFMTSZu
Definition: rz_types.h:399
#define PFMT64u
Definition: rz_types.h:395
#define PFMT64x
Definition: rz_types.h:393
#define st64
Definition: rz_types_base.h:10
#define RZ_PLUGINS
Definition: rz_userconf.h:72
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
int ssize_t
Definition: sftypes.h:39
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
size_t len
Definition: rz-hash.c:18
ut8 * buf
Definition: rz-hash.c:17
ut64 from
Definition: rz-hash.c:43
ut64 to
Definition: rz-hash.c:44
Definition: buffer.h:15
Definition: getopt.h:84
Definition: rz_pj.h:12
const char * name
Definition: rz_crypto.h:41
const char * license
Definition: rz_crypto.h:42
const char * author
Definition: rz_crypto.h:43
const char * arg
Definition: rz_getopt.h:15
bool as_prefix
Definition: rz-hash.c:49
RzHashMode mode
Definition: rz-hash.c:60
RzHash * rh
Definition: rz-hash.c:48
RzHashBuffer key
Definition: rz-hash.c:58
RzHashOp operation
Definition: rz-hash.c:62
RzHashBuffer seed
Definition: rz-hash.c:59
char * input
Definition: rz-hash.c:55
bool little_endian
Definition: rz-hash.c:50
bool use_stdin
Definition: rz-hash.c:52
char * iv
Definition: rz-hash.c:56
const char ** files
Definition: rz-hash.c:57
char * algorithm
Definition: rz-hash.c:53
ut64 block_size
Definition: rz-hash.c:64
ut64 iterate
Definition: rz-hash.c:65
RzHashOffset offset
Definition: rz-hash.c:61
char * compare
Definition: rz-hash.c:54
bool show_blocks
Definition: rz-hash.c:51
const char * name
Definition: rz_hash.h:27
bool support_hmac
Definition: rz_hash.h:30
const char * author
Definition: rz_hash.h:29
const char * license
Definition: rz_hash.h:28
Definition: rz_io.h:59
struct rz_io_desc_t * desc
Definition: rz_io.h:60
#define bool
Definition: sysdefs.h:146
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115