tcpflow  1.6.1
About: tcpflow is a TCP/IP packet demultiplexer that captures data transmitted as part of TCP connections (flows), and stores the data in a way that is convenient for protocol analysis and debugging.
  Fossies Dox: tcpflow-1.6.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

hash_t.h
Go to the documentation of this file.
1 /*
2  * C++ covers for md5, sha1, and sha256 (and sha512 if present)
3  *
4  * hash representation classes: md5_t, sha1_t, sha256_t (sha512_t)
5  * has generators: md5_generator(), sha1_generator(), sha256_generator()
6  *
7  * Generating a hash:
8  * sha1_t val = sha1_generator::hash_buf(buf,bufsize)
9  * sha1_t generator hasher;
10  * hasher.update(buf,bufsize)
11  * hasher.update(buf,bufsize)
12  * hasher.update(buf,bufsize)
13  * sha1_t val = hasher.final()
14  *
15  * Using the values:
16  * string val.hexdigest() --- return a hext digest
17  * val.size() --- the size of the hash in bytes
18  * uint8_t val.digest[SIZE] --- the buffer of the raw bytes
19  * uint8_t val.final() --- synonym for md.digest
20  *
21  * This can be updated in the future for Mac so that the hash__ class
22  * is then subclassed by a hash__openssl or a hash__commonCrypto class.
23  *
24  *
25  * Revision History:
26  * 2012 - Simson L. Garfinkel - Created for bulk_extractor.
27  *
28  * This file is public domain
29  */
30 
31 #ifndef HASH_T_H
32 #define HASH_T_H
33 
34 #include <cstring>
35 #include <cstdlib>
36 
37 /**
38  * For reasons that defy explanation (at the moment), this is required.
39  */
40 
41 
42 #ifdef __APPLE__
43 #include <AvailabilityMacros.h>
44 #undef DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
45 #define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
46 #endif
47 
48 #include <stdint.h>
49 #include <assert.h>
50 #include <fcntl.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <iostream>
54 #include <unistd.h>
55 
56 #if defined(HAVE_OPENSSL_HMAC_H) && defined(HAVE_OPENSSL_EVP_H)
57 #include <openssl/hmac.h>
58 #include <openssl/evp.h>
59 #else
60 #error OpenSSL required for hash_t.h
61 #endif
62 
63 #ifdef HAVE_SYS_MMAN_H
64 #include <sys/mman.h>
65 #endif
66 
67 #ifdef HAVE_SYS_MMAP_H
68 #include <sys/mmap.h>
69 #endif
70 
71 template<const EVP_MD *md(),size_t SIZE>
72 class hash__
73 {
74 public:
75  uint8_t digest[SIZE];
76  static size_t size() {
77  return(SIZE);
78  }
79  hash__(){
80  }
81  hash__(const uint8_t *provided){
82  memcpy(this->digest,provided,size());
83  }
84  const uint8_t *final() const {
85  return this->digest;
86  }
87  /* python like interface for hexdigest */
88  static unsigned int hex2int(char ch){
89  if(ch>='0' && ch<='9') return ch-'0';
90  if(ch>='a' && ch<='f') return ch-'a'+10;
91  if(ch>='A' && ch<='F') return ch-'A'+10;
92  return 0;
93  }
94  static unsigned int hex2int(char ch0,char ch1){
95  return (hex2int(ch0)<<4) | hex2int(ch1);
96  }
97  static hash__ fromhex(const std::string &hexbuf) {
98  hash__ res;
99  assert(hexbuf.size()==SIZE*2);
100  for(unsigned int i=0;i+1<hexbuf.size() && (i/2)<size();i+=2){
101  res.digest[i/2] = hex2int(hexbuf[i],hexbuf[i+1]);
102  }
103  return res;
104  }
105  const char *hexdigest(char *hexbuf,size_t bufsize) const {
106  const char *hexbuf_start = hexbuf;
107  for(unsigned int i=0;i<SIZE && bufsize>=3;i++){
108  snprintf(hexbuf,bufsize,"%02x",this->digest[i]);
109  hexbuf += 2;
110  bufsize -= 2;
111  }
112  return hexbuf_start;
113  }
114  std::string hexdigest() const {
115  std::string ret;
116  char buf[SIZE*2+1];
117  return std::string(hexdigest(buf,sizeof(buf)));
118  }
119  /**
120  * Convert a hex representation to binary, and return
121  * the number of bits converted.
122  * @param binbuf output buffer
123  * @param binbuf_size size of output buffer in bytes.
124  * @param hex input buffer (in hex)
125  * @return the number of converted bits.
126  */
127  static int hex2bin(uint8_t *binbuf,size_t binbuf_size,const char *hex)
128  {
129  int bits = 0;
130  while(hex[0] && hex[1] && binbuf_size>0){
131  *binbuf++ = hex2int(hex[0],hex[1]);
132  hex += 2;
133  bits += 8;
134  binbuf_size -= 1;
135  }
136  return bits;
137  }
138  static const hash__ *new_from_hex(const char *hex) {
139  hash__ *val = new hash__();
140  if(hex2bin(val->digest,sizeof(val->digest),hex)!=SIZE*8){
141  std::cerr << "invalid input " << hex << "(" << SIZE*8 << ")\n";
142  exit(1);
143  }
144  return val;
145  }
146  bool operator<(const hash__ &s2) const {
147  /* Check the first byte manually as a performance hack */
148  if(this->digest[0] < s2.digest[0]) return true;
149  if(this->digest[0] > s2.digest[0]) return false;
150  return memcmp(this->digest,s2.digest, SIZE) < 0;
151  }
152  bool operator==(const hash__ &s2) const {
153  if(this->digest[0] != s2.digest[0]) return false;
154  return memcmp(this->digest,s2.digest, SIZE) == 0;
155  }
156  friend std::ostream& operator<<(std::ostream& os,const hash__ &s2) {
157  os << s2.hexdigest();
158  return os;
159  }
160 };
161 
165 #ifdef HAVE_EVP_SHA512
166 typedef hash__<EVP_sha512,64> sha512_t;
167 #endif
168 
169 template<typename T>
170 inline std::string digest_name();
171 template<>
172 inline std::string digest_name<md5_t>() {
173  return "MD5";
174 }
175 template<>
176 inline std::string digest_name<sha1_t>() {
177  return "SHA1";
178 }
179 template<>
180 inline std::string digest_name<sha256_t>() {
181  return "SHA256";
182 }
183 #ifdef HAVE_EVP_SHA512
184 template<>
185 inline std::string digest_name<sha512_t>() {
186  return "SHA512";
187 }
188 #endif
189 
190 template<const EVP_MD *md(),size_t SIZE>
191 class hash_generator__ { /* generates the hash */
192  private:
193  EVP_MD_CTX* mdctx; /* the context for computing the value */
194  bool initialized; /* has the context been initialized? */
195  bool finalized;
196  /* Static function to determine if something is zero */
197  static bool iszero(const uint8_t *buf,size_t bufsize){
198  for(unsigned int i=0;i<bufsize;i++){
199  if(buf[i]!=0) return false;
200  }
201  return true;
202  }
203  /* Not allowed to copy; these are prototyped but not defined, so any attempt to use them will fail, but we won't get the -Weffc++ warnings */
206 public:
207  int64_t hashed_bytes;
208  /* This function takes advantage of the fact that different hash functions produce residues with different sizes */
211  release();
212  }
213  void release(){ /* free allocated memory */
214  if(initialized){
215 #ifdef HAVE_EVP_MD_CTX_FREE
216  EVP_MD_CTX_free(mdctx);
217 #else
218  EVP_MD_CTX_destroy(mdctx);
219 #endif
220  initialized = false;
221  hashed_bytes = 0;
222  }
223  }
224  void init(){
225  if(initialized==false){
226 #ifdef HAVE_EVP_MD_CTX_NEW
227  mdctx = EVP_MD_CTX_new();
228 #else
229  mdctx = EVP_MD_CTX_create();
230 #endif
231  if (!mdctx) throw std::bad_alloc();
232  EVP_DigestInit_ex(mdctx, md(), NULL);
233  initialized = true;
234  finalized = false;
235  hashed_bytes = 0;
236  }
237  }
238  void update(const uint8_t *buf,size_t bufsize){
239  if(!initialized) init();
240  if(finalized){
241  std::cerr << "hashgen_t::update called after finalized\n";
242  exit(1);
243  }
244  EVP_DigestUpdate(mdctx,buf,bufsize);
245  hashed_bytes += bufsize;
246  }
247  hash__<md,SIZE> final() {
248  if(finalized){
249  std::cerr << "currently friendly_geneator does not cache the final value\n";
250  assert(0);
251  exit(1); // in case compiled with assertions disabled
252  }
253  if(!initialized){
254  init(); /* do it now! */
255  }
256  hash__<md,SIZE> val;
257  unsigned int len = sizeof(val.digest);
258  EVP_DigestFinal(mdctx,val.digest,&len);
259  finalized = true;
260  return val;
261  }
262 
263  /** Compute a sha1 from a buffer and return the hash */
264  static hash__<md,SIZE> hash_buf(const uint8_t *buf,size_t bufsize){
265  /* First time through find the SHA1 of 512 NULLs */
267  g.update(buf,bufsize);
268  return g.final();
269  }
270 
271 #ifdef HAVE_MMAP
272  /** Static method allocateor */
273  static hash__<md,SIZE> hash_file(const char *fname){
274  int fd = open(fname,O_RDONLY
275 #ifdef O_BINARY
276  |O_BINARY
277 #endif
278  );
279  if(fd<0) throw fname;
280  struct stat st;
281  if(fstat(fd,&st)<0){
282  close(fd);
283  throw fname;
284  }
285  const uint8_t *buf = (const uint8_t *)mmap(0,st.st_size,PROT_READ,MAP_FILE|MAP_SHARED,fd,0);
286  if(buf==0){
287  close(fd);
288  throw fname;
289  }
290  hash__<md,SIZE> s = hash_buf(buf,st.st_size);
291  munmap((void *)buf,st.st_size);
292  close(fd);
293  return s;
294  }
295 #endif
296 };
297 
301 
302 #ifdef HAVE_EVP_SHA512
303 typedef hash_generator__<EVP_sha512,64> sha512_generator;
304 #define HAVE_SHA512_T
305 #endif
306 
307 #endif
Definition: hash_t.h:73
bool operator==(const hash__ &s2) const
Definition: hash_t.h:152
std::string hexdigest() const
Definition: hash_t.h:114
bool operator<(const hash__ &s2) const
Definition: hash_t.h:146
static size_t size()
Definition: hash_t.h:76
static hash__ fromhex(const std::string &hexbuf)
Definition: hash_t.h:97
friend std::ostream & operator<<(std::ostream &os, const hash__ &s2)
Definition: hash_t.h:156
static int hex2bin(uint8_t *binbuf, size_t binbuf_size, const char *hex)
Definition: hash_t.h:127
hash__(const uint8_t *provided)
Definition: hash_t.h:81
static unsigned int hex2int(char ch)
Definition: hash_t.h:88
hash__()
Definition: hash_t.h:79
static const hash__ * new_from_hex(const char *hex)
Definition: hash_t.h:138
const char * hexdigest(char *hexbuf, size_t bufsize) const
Definition: hash_t.h:105
uint8_t digest[SIZE]
Definition: hash_t.h:75
static unsigned int hex2int(char ch0, char ch1)
Definition: hash_t.h:94
bool initialized
Definition: hash_t.h:194
hash__< md, SIZE > final()
Definition: hash_t.h:247
hash_generator__ & operator=(const hash_generator__ &)
void update(const uint8_t *buf, size_t bufsize)
Definition: hash_t.h:238
void release()
Definition: hash_t.h:213
int64_t hashed_bytes
Definition: hash_t.h:207
static bool iszero(const uint8_t *buf, size_t bufsize)
Definition: hash_t.h:197
void init()
Definition: hash_t.h:224
EVP_MD_CTX * mdctx
Definition: hash_t.h:193
hash_generator__(const hash_generator__ &)
static hash__< md, SIZE > hash_buf(const uint8_t *buf, size_t bufsize)
Definition: hash_t.h:264
bool finalized
Definition: hash_t.h:195
#define O_BINARY
std::string digest_name< md5_t >()
Definition: hash_t.h:172
hash__< EVP_sha256, 32 > sha256_t
Definition: hash_t.h:164
std::string digest_name< sha1_t >()
Definition: hash_t.h:176
hash__< EVP_sha1, 20 > sha1_t
Definition: hash_t.h:163
hash_generator__< EVP_sha1, 20 > sha1_generator
Definition: hash_t.h:299
std::string digest_name()
hash__< EVP_md5, 16 > md5_t
Definition: hash_t.h:162
std::string digest_name< sha256_t >()
Definition: hash_t.h:180
hash_generator__< EVP_md5, 16 > md5_generator
Definition: hash_t.h:298
hash_generator__< EVP_sha256, 32 > sha256_generator
Definition: hash_t.h:300
static const char * hexbuf(char *dst, int dst_len, const unsigned char *bin, int bytes, int flag)
Definition: sbuf.cpp:206
#define PROT_READ
Definition: util.cpp:227
#define MAP_FILE
Definition: util.cpp:228
#define MAP_SHARED
Definition: util.cpp:229
void * mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
Definition: util.cpp:230
void munmap(void *buf, size_t size)
Definition: util.cpp:238
unsigned char uint8_t
Definition: util.h:6