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