DSL
hash.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #include <drift/dslcore.h>
12 #include <drift/GenLib.h>
13 #include <drift/hash.h>
14 #include <drift/Mutex.h>
15 
16 typedef vector<const HASH_PROVIDER*> hashProviderList;
17 hashProviderList * dslHashProviders() {
18  AutoMutexPtr(dslMutex());
19  static hashProviderList hash_providers { &dsl_native_hashers };
20  return &hash_providers;
21 }
22 
23 extern DSL_Mutex * dslMutex();
24 void DSL_CC dsl_add_hash_provider(const HASH_PROVIDER * p) {
25  AutoMutexPtr(dslMutex());
26  //dslHashProviders()->push_back(p);
27  /* 3rd party providers will probably be more optimized than our generic native ones, so put them 1st */
28  hashProviderList* hash_providers = dslHashProviders();
29  hash_providers->insert(hash_providers->begin(), p);
30 }
31 void DSL_CC dsl_remove_hash_provider(const HASH_PROVIDER * p) {
32  AutoMutexPtr(dslMutex());
33  hashProviderList * hash_providers = dslHashProviders();
34  for (auto x = hash_providers->begin(); x != hash_providers->end(); x++) {
35  if (*x == p) {
36  hash_providers->erase(x);
37 #ifdef DEBUG
38  printf("Removed hash provider %s -> %zu\n", p->name, hash_providers->size());
39 #endif
40  break;
41  }
42  }
43 }
44 void DSL_CC dsl_get_hash_providers(vector<const HASH_PROVIDER *>& p) {
45  AutoMutexPtr(dslMutex());
46  p = *dslHashProviders();
47 }
48 
49 HASH_CTX * DSL_CC hash_init(const char * name) {
50  //AutoMutexPtr(dslMutex());
51  hashProviderList* hash_providers = dslHashProviders();
52  for (auto x = hash_providers->begin(); x != hash_providers->end(); x++) {
53  HASH_CTX * ret = (*x)->hash_init(name);
54  if (ret != NULL) {
55  ret->provider = *x;
56  return ret;
57  }
58  }
59  return NULL;
60 }
61 
62 void DSL_CC hash_update(HASH_CTX *ctx, const uint8 *data, size_t len) {
63  if (ctx == NULL || data == NULL) {
64  return;
65  }
66  ctx->provider->hash_update(ctx, data, len);
67 }
68 bool DSL_CC hash_finish(HASH_CTX *ctx, uint8 * out, size_t outlen) {
69  if (ctx == NULL || out == NULL) {
70  return false;
71  }
72  if (outlen < ctx->hashSize) {
73  printf("DSL: Output buffer too small in hash_finish()!\n");
74  uint8 * tmp = (uint8 *)dsl_malloc(ctx->hashSize);
75  bool ret = ctx->provider->hash_finish(ctx, tmp, ctx->hashSize);
76  memcpy(out, tmp, outlen);
77  dsl_free(tmp);
78  return ret;
79  }
80  return ctx->provider->hash_finish(ctx, out, outlen);
81 }
82 
83 DSL_API bool DSL_CC hashdata(const char * name, const uint8 *data, size_t datalen, char * out, size_t outlen, bool raw_output) {
84  HASH_CTX * ctx = hash_init(name);
85  if (ctx == NULL) {
86  return false;
87  }
88  if (raw_output && outlen < ctx->hashSize) {
89  return false;
90  } else if (!raw_output && outlen < ((ctx->hashSize * 2) + 1)) {
91  return false;
92  }
93 
94  hash_update(ctx,data,datalen);
95 
96  bool ret;
97  if (raw_output) {
98  ret = hash_finish(ctx, (uint8 *)out, outlen);
99  } else {
100  uint8 * hashtmp = (uint8 *)dsl_malloc(ctx->hashSize);
101  size_t hsize = ctx->hashSize;
102  ret = hash_finish(ctx, hashtmp, ctx->hashSize);
103  if (ret) {
104  ret = (bin2hex(hashtmp, hsize, out, outlen) != NULL);
105  }
106  dsl_free(hashtmp);
107  }
108  return ret;
109 }
110 
111 DSL_API bool DSL_CC hashfile(const char * name, const char * fn, char * out, size_t outlen, bool raw_output) {
112  DSL_FILE * fp = RW_OpenFile(fn, "rb");
113  if (fp) {
114  bool ret = hashfile_rw(name, fp, out, outlen, raw_output);
115  fp->close(fp);
116  return ret;
117  }
118  return false;
119 }
120 
121 DSL_API bool DSL_CC hashfile_fp(const char * name, FILE * fpp, char * out, size_t outlen, bool raw_output) {
122  if (fpp == NULL) { return false; }
123 
124  DSL_FILE * fp = RW_ConvertFile(fpp, false);
125  if (fp) {
126  bool ret = hashfile_rw(name, fp, out, outlen, raw_output);
127  fp->close(fp);
128  return ret;
129  }
130  return false;
131 }
132 
133 DSL_API bool DSL_CC hashfile_rw(const char * name, DSL_FILE * fp, char * out, size_t outlen, bool raw_output) {
134  HASH_CTX * ctx = hash_init(name);
135  if (ctx == NULL) {
136  return false;
137  }
138  if (raw_output && outlen < ctx->hashSize) {
139  return false;
140  } else if (!raw_output && outlen < ((ctx->hashSize * 2) + 1)) {
141  return false;
142  }
143 
144  char buf[32768];
145 
146  fp->seek(fp, 0, SEEK_END);
147  int64 left = fp->tell(fp);
148  fp->seek(fp, 0, SEEK_SET);
149 
150  bool ret = true;
151  while (left) {
152  int64 toRead = (left >= sizeof(buf)) ? sizeof(buf):left;
153  if (fp->read(buf, toRead, fp) == toRead) {
154  hash_update(ctx,(uint8 *)&buf, (size_t)toRead);
155  left -= toRead;
156  } else {
157  ret = false;
158  break;
159  }
160  }
161 
162  bool ret2;
163  if (raw_output) {
164  ret2 = hash_finish(ctx, (uint8 *)out, outlen);
165  } else {
166  size_t hsize = ctx->hashSize;
167  unsigned char * hashtmp = (unsigned char *)dsl_malloc(ctx->hashSize);
168  ret2 = hash_finish(ctx, hashtmp, ctx->hashSize);
169  if (ret2) {
170  ret2 = (bin2hex(hashtmp, hsize, out, outlen) != NULL);
171  }
172  dsl_free(hashtmp);
173  }
174  return (ret && ret2);
175 }
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
DSL_API_CLASS char *DSL_CC bin2hex(const uint8_t *data, size_t datalen, char *out, size_t outsize)
Definition: GenLib.cpp:129
DSL_API bool DSL_CC hashdata(const char *name, const uint8 *data, size_t datalen, char *out, size_t outlen, bool raw_output)
Wrapper around hash_init()/hash_update()/hash_finish(). If raw_output == true out will contain binary...
Definition: hash.cpp:83
DSL_API bool DSL_CC hashfile_rw(const char *name, DSL_FILE *fp, char *out, size_t outlen, bool raw_output)
Wrapper around hash_init()/hash_update()/hash_finish(). If raw_output == true out will contain binary...
Definition: hash.cpp:133
void DSL_CC hash_update(HASH_CTX *ctx, const uint8 *data, size_t len)
Call with the data you want to hash, can be called multiple times to hash a large file in chunks for ...
Definition: hash.cpp:62
DSL_API bool DSL_CC hashfile(const char *name, const char *fn, char *out, size_t outlen, bool raw_output)
Wrapper around hash_init()/hash_update()/hash_finish(). If raw_output == true out will contain binary...
Definition: hash.cpp:111
HASH_CTX *DSL_CC hash_init(const char *name)
Definition: hash.cpp:49
DSL_API bool DSL_CC hashfile_fp(const char *name, FILE *fpp, char *out, size_t outlen, bool raw_output)
Wrapper around hash_init()/hash_update()/hash_finish(). If raw_output == true out will contain binary...
Definition: hash.cpp:121
bool DSL_CC hash_finish(HASH_CTX *ctx, uint8 *out, size_t outlen)
Finalize hash and store in out. outlen should be >= hashSize in the HASH_CTX struct....
Definition: hash.cpp:68
DSL_API DSL_FILE *DSL_CC RW_ConvertFile(FILE *fp, bool autoclose)
Definition: rwops.cpp:68
DSL_API DSL_FILE *DSL_CC RW_OpenFile(const char *fn, const char *mode)
Definition: rwops.cpp:50
Definition: rwops.h:24
void(* close)(DSL_FILE *fp)
Definition: rwops.h:54
bool(* seek)(DSL_FILE *fp, int64 pos, int mode)
Definition: rwops.h:31
int64(* read)(void *buf, int64 size, DSL_FILE *fp)
Definition: rwops.h:36
int64(* tell)(DSL_FILE *fp)
Definition: rwops.h:45
Definition: hash.h:26