Botan 3.13.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 security_level() const override {
51 if(m_info.name == "SHA-1") {
52 // Collision attacks with cost ~2^61 are known (Leurent and Peyrin, 2020)
53 return 61;
54 } else {
56 }
57 }
58
59 size_t hash_block_size() const override { return m_info.blockSize; }
60
61 CommonCrypto_HashFunction(const digest_config_t& info) : m_info(info) { clear(); }
62
63 CommonCrypto_HashFunction(const digest_config_t& info, const CTX& ctx) : m_ctx(ctx), m_info(info) {}
64
65 private:
66 void add_data(std::span<const uint8_t> input) override {
67 BufferSlicer in(input);
68
69 /* update len parameter is 32 bit unsigned integer, feed input in parts */
70 while(!in.empty()) {
71 CC_LONG update_len = (in.remaining() > 0xFFFFFFFFUL) ? 0xFFFFFFFFUL : static_cast<CC_LONG>(in.remaining());
72 const auto chunk = in.take(update_len);
73 m_info.update(&m_ctx, chunk.data(), static_cast<CC_LONG>(chunk.size()));
74 }
75 }
76
77 void final_result(std::span<uint8_t> output) override {
78 if(m_info.final(output.data(), &m_ctx) != 1)
79 throw CommonCrypto_Error("CC_" + m_info.name + "_Final");
80 clear();
81 }
82
83 CTX m_ctx;
84 digest_config_t m_info;
85};
86} // namespace
87
88std::unique_ptr<HashFunction> make_commoncrypto_hash(std::string_view name) {
89#define MAKE_COMMONCRYPTO_HASH_3(name, hash, ctx) \
90 std::unique_ptr<HashFunction>(new CommonCrypto_HashFunction<CC_##ctx##_CTX>({std::string(name), \
91 CC_##hash##_DIGEST_LENGTH, \
92 CC_##hash##_BLOCK_BYTES, \
93 CC_##hash##_Init, \
94 CC_##hash##_Update, \
95 CC_##hash##_Final}));
96
97#define MAKE_COMMONCRYPTO_HASH_2(name, id) MAKE_COMMONCRYPTO_HASH_3(name, id, id)
98
99#define MAKE_COMMONCRYPTO_HASH_1(id) MAKE_COMMONCRYPTO_HASH_2(#id, id)
100
101#if defined(BOTAN_HAS_SHA2_32)
102 if(name == "SHA-224")
103 return MAKE_COMMONCRYPTO_HASH_3(name, SHA224, SHA256);
104 if(name == "SHA-256")
105 return MAKE_COMMONCRYPTO_HASH_2(name, SHA256);
106#endif
107#if defined(BOTAN_HAS_SHA2_64)
108 if(name == "SHA-384")
109 return MAKE_COMMONCRYPTO_HASH_3(name, SHA384, SHA512);
110 if(name == "SHA-512")
111 return MAKE_COMMONCRYPTO_HASH_2(name, SHA512);
112#endif
113
114#if defined(BOTAN_HAS_SHA1)
115 if(name == "SHA-1")
116 return MAKE_COMMONCRYPTO_HASH_2(name, SHA1);
117#endif
118
119 return nullptr;
120}
121
122} // namespace Botan
virtual size_t security_level() const
Definition hash.h:77
#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)