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