Botan  2.18.1
Crypto and TLS for C++11
commoncrypto_hash.cpp
Go to the documentation of this file.
1 /*
2 * CommonCrypto Hash Functions
3 * (C) 2018 Jose Pereira
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/internal/commoncrypto.h>
9 #include <botan/hash.h>
10 #include <unordered_map>
11 
12 #include <CommonCrypto/CommonCrypto.h>
13 
14 namespace Botan {
15 
16 namespace {
17 
18 template <class CTX>
19 class CommonCrypto_HashFunction final : public HashFunction
20  {
21  public:
22 
23  struct digest_config_t {
24  std::string name;
25  size_t digestLength;
26  size_t blockSize;
27  int (*init)(CTX *);
28  int (*update)(CTX *, const void *, CC_LONG len);
29  int (*final)(unsigned char *, CTX*);
30  };
31 
32  void clear() override
33  {
34  if(m_info.init(&m_ctx) != 1)
35  throw CommonCrypto_Error("CC_" + m_info.name + "_Init");
36  }
37 
38  std::string provider() const override { return "commoncrypto"; }
39  std::string name() const override { return m_info.name; }
40 
41  HashFunction* clone() const override
42  {
43  return new CommonCrypto_HashFunction(m_info);
44  }
45 
46  std::unique_ptr<HashFunction> copy_state() const override
47  {
48  return std::unique_ptr<CommonCrypto_HashFunction>(
49  new CommonCrypto_HashFunction(m_info, m_ctx));
50  }
51 
52  size_t output_length() const override
53  {
54  return m_info.digestLength;
55  }
56 
57  size_t hash_block_size() const override
58  {
59  return m_info.blockSize;
60  }
61 
62  CommonCrypto_HashFunction(const digest_config_t& info) :
63  m_info(info)
64  {
65  clear();
66  }
67 
68  CommonCrypto_HashFunction(const digest_config_t& info, const CTX &ctx) :
69  m_ctx(ctx), m_info(info) {}
70 
71  private:
72  void add_data(const uint8_t input[], size_t length) override
73  {
74  /* update len parameter is 32 bit unsigned integer, feed input in parts */
75  while (length > 0)
76  {
77  CC_LONG update_len = (length > 0xFFFFFFFFUL) ? 0xFFFFFFFFUL : static_cast<CC_LONG>(length);
78  m_info.update(&m_ctx, input, update_len);
79  input += update_len;
80  length -= update_len;
81  }
82  }
83 
84  void final_result(uint8_t output[]) override
85  {
86  if(m_info.final(output, &m_ctx) != 1)
87  throw CommonCrypto_Error("CC_" + m_info.name + "_Final");
88  clear();
89  }
90 
91  CTX m_ctx;
92  digest_config_t m_info;
93  };
94 }
95 
96 std::unique_ptr<HashFunction>
97 make_commoncrypto_hash(const std::string& name)
98  {
99 #define MAKE_COMMONCRYPTO_HASH_3(name, hash, ctx) \
100  std::unique_ptr<HashFunction>( \
101  new CommonCrypto_HashFunction<CC_ ## ctx ## _CTX >({ \
102  name, \
103  CC_ ## hash ## _DIGEST_LENGTH, \
104  CC_ ## hash ## _BLOCK_BYTES, \
105  CC_ ## hash ## _Init, \
106  CC_ ## hash ## _Update, \
107  CC_ ## hash ## _Final \
108  }));
109 
110 #define MAKE_COMMONCRYPTO_HASH_2(name, id) \
111  MAKE_COMMONCRYPTO_HASH_3(name, id, id)
112 
113 #define MAKE_COMMONCRYPTO_HASH_1(id) \
114  MAKE_COMMONCRYPTO_HASH_2(#id, id)
115 
116 #if defined(BOTAN_HAS_SHA2_32)
117  if(name == "SHA-224")
118  return MAKE_COMMONCRYPTO_HASH_3(name, SHA224, SHA256);
119  if(name == "SHA-256")
120  return MAKE_COMMONCRYPTO_HASH_2(name, SHA256);
121 #endif
122 #if defined(BOTAN_HAS_SHA2_64)
123  if(name == "SHA-384")
124  return MAKE_COMMONCRYPTO_HASH_3(name, SHA384, SHA512);
125  if(name == "SHA-512")
126  return MAKE_COMMONCRYPTO_HASH_2(name, SHA512);
127 #endif
128 
129 #if defined(BOTAN_HAS_SHA1)
130  if(name == "SHA-160" || name == "SHA-1" || name == "SHA1")
131  return MAKE_COMMONCRYPTO_HASH_2(name, SHA1);
132 #endif
133 
134 #if defined(BOTAN_HAS_MD5)
135  if(name == "MD5")
137 #endif
138 
139 #if defined(BOTAN_HAS_MD4)
140  if(name == "MD4")
142 #endif
143  return nullptr;
144  }
145 
146 }
#define MAKE_COMMONCRYPTO_HASH_1(id)
Definition: md4.h:20
int(* final)(unsigned char *, CTX *)
std::string name
size_t blockSize
Definition: md5.h:20
size_t digestLength
Definition: alg_id.cpp:13
std::unique_ptr< HashFunction > make_commoncrypto_hash(const std::string &name)
#define MAKE_COMMONCRYPTO_HASH_2(name, id)
#define MAKE_COMMONCRYPTO_HASH_3(name, hash, ctx)
int(* update)(CTX *, const void *, CC_LONG len)
int(* init)(CTX *)