Botan 2.19.1
Crypto and TLS for C&
openssl_hash.cpp
Go to the documentation of this file.
1/*
2* OpenSSL Hash Functions
3* (C) 1999-2007,2015 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/hash.h>
9#include <botan/internal/openssl.h>
10#include <openssl/evp.h>
11#include <unordered_map>
12
13namespace Botan {
14
15namespace {
16
17class OpenSSL_HashFunction final : public HashFunction
18 {
19 public:
20 void clear() override
21 {
22 const EVP_MD* algo = EVP_MD_CTX_md(m_md);
23 if(!EVP_DigestInit_ex(m_md, algo, nullptr))
24 throw OpenSSL_Error("EVP_DigestInit_ex", ERR_get_error());
25 }
26
27 std::string provider() const override { return "openssl"; }
28 std::string name() const override { return m_name; }
29
30 HashFunction* clone() const override
31 {
32 const EVP_MD* algo = EVP_MD_CTX_md(m_md);
33 return new OpenSSL_HashFunction(name(), algo);
34 }
35
36 std::unique_ptr<HashFunction> copy_state() const override
37 {
38 std::unique_ptr<OpenSSL_HashFunction> copy(new OpenSSL_HashFunction(m_name, nullptr));
39 EVP_MD_CTX_copy(copy->m_md, m_md);
40 return std::unique_ptr<HashFunction>(copy.release());
41 }
42
43 size_t output_length() const override
44 {
45 return EVP_MD_size(EVP_MD_CTX_md(m_md));
46 }
47
48 size_t hash_block_size() const override
49 {
50 return EVP_MD_block_size(EVP_MD_CTX_md(m_md));
51 }
52
53 OpenSSL_HashFunction(const std::string& name, const EVP_MD* md) : m_name(name)
54 {
55#if OPENSSL_VERSION_NUMBER < 0x10100000L
56 m_md = EVP_MD_CTX_create();
57#else
58 m_md = EVP_MD_CTX_new();
59#endif
60
61 if(m_md == nullptr)
62 throw OpenSSL_Error("Can't allocate new context", ERR_get_error());
63 EVP_MD_CTX_init(m_md);
64 if(md && !EVP_DigestInit_ex(m_md, md, nullptr))
65 throw OpenSSL_Error("EVP_DigestInit_ex", ERR_get_error());
66 }
67
68 OpenSSL_HashFunction(EVP_MD_CTX* ctx) : m_md(ctx)
69 {
70 }
71
72 ~OpenSSL_HashFunction()
73 {
74#if OPENSSL_VERSION_NUMBER < 0x10100000L
75 EVP_MD_CTX_destroy(m_md);
76#else
77 EVP_MD_CTX_free(m_md);
78#endif
79 }
80
81 private:
82 void add_data(const uint8_t input[], size_t length) override
83 {
84 if(!EVP_DigestUpdate(m_md, input, length))
85 throw OpenSSL_Error("EVP_DigestUpdate", ERR_get_error());
86 }
87
88 void final_result(uint8_t output[]) override
89 {
90 if(!EVP_DigestFinal_ex(m_md, output, nullptr))
91 throw OpenSSL_Error("EVP_DigestFinal_ex", ERR_get_error());
92 const EVP_MD* algo = EVP_MD_CTX_md(m_md);
93 if(!EVP_DigestInit_ex(m_md, algo, nullptr))
94 throw OpenSSL_Error("EVP_DigestInit_ex", ERR_get_error());
95 }
96
97 std::string m_name;
98 EVP_MD_CTX* m_md;
99 };
100
101}
102
103std::unique_ptr<HashFunction>
104make_openssl_hash(const std::string& name)
105 {
106#define MAKE_OPENSSL_HASH(fn) \
107 std::unique_ptr<HashFunction>(new OpenSSL_HashFunction(name, fn ()))
108
109#if defined(BOTAN_HAS_SHA2_32) && !defined(OPENSSL_NO_SHA256)
110 if(name == "SHA-224")
111 return MAKE_OPENSSL_HASH(EVP_sha224);
112 if(name == "SHA-256")
113 return MAKE_OPENSSL_HASH(EVP_sha256);
114#endif
115
116#if defined(BOTAN_HAS_SHA2_64) && !defined(OPENSSL_NO_SHA512)
117 if(name == "SHA-384")
118 return MAKE_OPENSSL_HASH(EVP_sha384);
119 if(name == "SHA-512")
120 return MAKE_OPENSSL_HASH(EVP_sha512);
121#endif
122
123#if defined(BOTAN_HAS_SHA1) && !defined(OPENSSL_NO_SHA)
124 if(name == "SHA-160" || name == "SHA-1" || name == "SHA1")
125 return MAKE_OPENSSL_HASH(EVP_sha1);
126#endif
127
128#if defined(BOTAN_HAS_MD5) && !defined(OPENSSL_NO_MD5)
129 if(name == "MD5")
130 return MAKE_OPENSSL_HASH(EVP_md5);
131 #endif
132
133 return nullptr;
134 }
135
136}
std::string name
int(* final)(unsigned char *, CTX *)
Definition: alg_id.cpp:13
std::unique_ptr< HashFunction > make_openssl_hash(const std::string &name)
#define MAKE_OPENSSL_HASH(fn)