Botan 3.6.1
Crypto and TLS for C&
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
10#include <botan/hash.h>
11#include <botan/internal/stl_util.h>
12#include <unordered_map>
13
14#include <CommonCrypto/CommonCrypto.h>
15
16namespace Botan {
17
18namespace {
19
20template <class CTX>
21class CommonCrypto_HashFunction final : public HashFunction {
22 public:
23 struct digest_config_t {
24 std::string name;
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 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
39 std::string name() const override { return m_info.name; }
40
41 std::unique_ptr<HashFunction> new_object() const override {
42 return std::make_unique<CommonCrypto_HashFunction>(m_info);
43 }
44
45 std::unique_ptr<HashFunction> copy_state() const override {
46 return std::unique_ptr<CommonCrypto_HashFunction>(new CommonCrypto_HashFunction(m_info, m_ctx));
47 }
48
49 size_t output_length() const override { return m_info.digestLength; }
50
51 size_t hash_block_size() const override { return m_info.blockSize; }
52
53 CommonCrypto_HashFunction(const digest_config_t& info) : m_info(info) { clear(); }
54
55 CommonCrypto_HashFunction(const digest_config_t& info, const CTX& ctx) : m_ctx(ctx), m_info(info) {}
56
57 private:
58 void add_data(std::span<const uint8_t> input) override {
59 BufferSlicer in(input);
60
61 /* update len parameter is 32 bit unsigned integer, feed input in parts */
62 while(!in.empty()) {
63 CC_LONG update_len = (in.remaining() > 0xFFFFFFFFUL) ? 0xFFFFFFFFUL : static_cast<CC_LONG>(in.remaining());
64 const auto chunk = in.take(update_len);
65 m_info.update(&m_ctx, chunk.data(), static_cast<CC_LONG>(chunk.size()));
66 }
67 }
68
69 void final_result(std::span<uint8_t> output) override {
70 if(m_info.final(output.data(), &m_ctx) != 1)
71 throw CommonCrypto_Error("CC_" + m_info.name + "_Final");
72 clear();
73 }
74
75 CTX m_ctx;
76 digest_config_t m_info;
77};
78} // namespace
79
80std::unique_ptr<HashFunction> make_commoncrypto_hash(std::string_view name) {
81#define MAKE_COMMONCRYPTO_HASH_3(name, hash, ctx) \
82 std::unique_ptr<HashFunction>(new CommonCrypto_HashFunction<CC_##ctx##_CTX>({std::string(name), \
83 CC_##hash##_DIGEST_LENGTH, \
84 CC_##hash##_BLOCK_BYTES, \
85 CC_##hash##_Init, \
86 CC_##hash##_Update, \
87 CC_##hash##_Final}));
88
89#define MAKE_COMMONCRYPTO_HASH_2(name, id) MAKE_COMMONCRYPTO_HASH_3(name, id, id)
90
91#define MAKE_COMMONCRYPTO_HASH_1(id) MAKE_COMMONCRYPTO_HASH_2(#id, id)
92
93#if defined(BOTAN_HAS_SHA2_32)
94 if(name == "SHA-224")
95 return MAKE_COMMONCRYPTO_HASH_3(name, SHA224, SHA256);
96 if(name == "SHA-256")
97 return MAKE_COMMONCRYPTO_HASH_2(name, SHA256);
98#endif
99#if defined(BOTAN_HAS_SHA2_64)
100 if(name == "SHA-384")
101 return MAKE_COMMONCRYPTO_HASH_3(name, SHA384, SHA512);
102 if(name == "SHA-512")
103 return MAKE_COMMONCRYPTO_HASH_2(name, SHA512);
104#endif
105
106#if defined(BOTAN_HAS_SHA1)
107 if(name == "SHA-1")
108 return MAKE_COMMONCRYPTO_HASH_2(name, SHA1);
109#endif
110
111 return nullptr;
112}
113
114} // namespace Botan
#define MAKE_COMMONCRYPTO_HASH_2(name, id)
size_t digestLength
std::string name
size_t blockSize
#define MAKE_COMMONCRYPTO_HASH_3(name, hash, ctx)
int(* final)(unsigned char *, CTX *)
std::unique_ptr< HashFunction > make_commoncrypto_hash(std::string_view name)