1 #ifndef PICHI_CRYPTO_HASH_HPP
2 #define PICHI_CRYPTO_HASH_HPP
3 
4 #include <mbedtls/md5.h>
5 #include <mbedtls/sha1.h>
6 #include <mbedtls/sha256.h>
7 #include <mbedtls/sha512.h>
8 #include <pichi/common/buffer.hpp>
9 #include <pichi/common/enumerations.hpp>
10 
11 #if MBEDTLS_VERSION_MAJOR >= 3
12 #define mbedtls_md5_starts_ret mbedtls_md5_starts
13 #define mbedtls_sha1_starts_ret mbedtls_sha1_starts
14 #define mbedtls_sha256_starts_ret mbedtls_sha256_starts
15 #define mbedtls_sha512_starts_ret mbedtls_sha512_starts
16 #define mbedtls_md5_update_ret mbedtls_md5_update
17 #define mbedtls_sha1_update_ret mbedtls_sha1_update
18 #define mbedtls_sha256_update_ret mbedtls_sha256_update
19 #define mbedtls_sha512_update_ret mbedtls_sha512_update
20 #define mbedtls_md5_finish_ret mbedtls_md5_finish
21 #define mbedtls_sha1_finish_ret mbedtls_sha1_finish
22 #define mbedtls_sha256_finish_ret mbedtls_sha256_finish
23 #define mbedtls_sha512_finish_ret mbedtls_sha512_finish
24 #endif  // MBEDTLS_VERSION_MAJOR >= 3
25 
26 namespace pichi::crypto {
27 
28 // TODO use lambda if compiler supports
29 struct StartFunctions {
sha224pichi::crypto::StartFunctions30   inline static int sha224(mbedtls_sha256_context* ctx)
31   {
32     return mbedtls_sha256_starts_ret(ctx, 1);
33   }
sha256pichi::crypto::StartFunctions34   inline static int sha256(mbedtls_sha256_context* ctx)
35   {
36     return mbedtls_sha256_starts_ret(ctx, 0);
37   }
sha384pichi::crypto::StartFunctions38   inline static int sha384(mbedtls_sha512_context* ctx)
39   {
40     return mbedtls_sha512_starts_ret(ctx, 1);
41   }
sha512pichi::crypto::StartFunctions42   inline static int sha512(mbedtls_sha512_context* ctx)
43   {
44     return mbedtls_sha512_starts_ret(ctx, 0);
45   }
46 };
47 
48 template <HashAlgorithm algorithm> struct HashTraits {
49 };
50 
51 template <> struct HashTraits<HashAlgorithm::MD5> {
52   using Context = mbedtls_md5_context;
53   static constexpr auto initialize = mbedtls_md5_init;
54   static constexpr auto start = mbedtls_md5_starts_ret;
55   static constexpr auto clone = mbedtls_md5_clone;
56   static constexpr auto release = mbedtls_md5_free;
57   static constexpr auto update = mbedtls_md5_update_ret;
58   static constexpr auto finish = mbedtls_md5_finish_ret;
59   static size_t const length = 16;
60   static size_t const block_size = 64;
61 };
62 
63 template <> struct HashTraits<HashAlgorithm::SHA1> {
64   using Context = mbedtls_sha1_context;
65   static constexpr auto initialize = mbedtls_sha1_init;
66   static constexpr auto start = mbedtls_sha1_starts_ret;
67   static constexpr auto clone = mbedtls_sha1_clone;
68   static constexpr auto release = mbedtls_sha1_free;
69   static constexpr auto update = mbedtls_sha1_update_ret;
70   static constexpr auto finish = mbedtls_sha1_finish_ret;
71   static size_t const length = 20;
72   static size_t const block_size = 64;
73 };
74 
75 template <> struct HashTraits<HashAlgorithm::SHA224> {
76   using Context = mbedtls_sha256_context;
77   static constexpr auto initialize = mbedtls_sha256_init;
78   static constexpr auto start = StartFunctions::sha224;
79   static constexpr auto clone = mbedtls_sha256_clone;
80   static constexpr auto release = mbedtls_sha256_free;
81   static constexpr auto update = mbedtls_sha256_update_ret;
82   static constexpr auto finish = mbedtls_sha256_finish_ret;
83   static size_t const length = 28;
84   static size_t const block_size = 64;
85 };
86 
87 template <> struct HashTraits<HashAlgorithm::SHA256> {
88   using Context = mbedtls_sha256_context;
89   static constexpr auto initialize = mbedtls_sha256_init;
90   static constexpr auto start = StartFunctions::sha256;
91   static constexpr auto clone = mbedtls_sha256_clone;
92   static constexpr auto release = mbedtls_sha256_free;
93   static constexpr auto update = mbedtls_sha256_update_ret;
94   static constexpr auto finish = mbedtls_sha256_finish_ret;
95   static size_t const length = 32;
96   static size_t const block_size = 64;
97 };
98 
99 template <> struct HashTraits<HashAlgorithm::SHA384> {
100   using Context = mbedtls_sha512_context;
101   static constexpr auto initialize = mbedtls_sha512_init;
102   static constexpr auto start = StartFunctions::sha384;
103   static constexpr auto clone = mbedtls_sha512_clone;
104   static constexpr auto release = mbedtls_sha512_free;
105   static constexpr auto update = mbedtls_sha512_update_ret;
106   static constexpr auto finish = mbedtls_sha512_finish_ret;
107   static size_t const length = 48;
108   static size_t const block_size = 128;
109 };
110 
111 template <> struct HashTraits<HashAlgorithm::SHA512> {
112   using Context = mbedtls_sha512_context;
113   static constexpr auto initialize = mbedtls_sha512_init;
114   static constexpr auto start = StartFunctions::sha512;
115   static constexpr auto clone = mbedtls_sha512_clone;
116   static constexpr auto release = mbedtls_sha512_free;
117   static constexpr auto update = mbedtls_sha512_update_ret;
118   static constexpr auto finish = mbedtls_sha512_finish_ret;
119   static size_t const length = 64;
120   static size_t const block_size = 128;
121 };
122 
123 template <HashAlgorithm algorithm> class Hash {
124 private:
125   using Traits = HashTraits<algorithm>;
126   using Context = typename Traits::Context;
127 
128 public:
129   Hash& operator=(Hash const&) = delete;
130   Hash& operator=(Hash&&) = delete;
131 
132   Hash(Hash const&);
133   Hash(Hash&&);
134 
135 public:
136   Hash();
137   ~Hash();
138 
139   void append(ConstBuffer<uint8_t>);
140   size_t hash(MutableBuffer<uint8_t>);
141   size_t hash(ConstBuffer<uint8_t>, MutableBuffer<uint8_t>);
142 
143 private:
144   Context ctx_;
145 };
146 
147 template <HashAlgorithm algorithm> class Hmac {
148 private:
149   using H = Hash<algorithm>;
150   using Traits = HashTraits<algorithm>;
151 
152 public:
153   Hmac& operator=(Hmac const&) = delete;
154   Hmac& operator=(Hmac&&) = delete;
155 
156   Hmac(Hmac const&) = default;
157   Hmac(Hmac&&) = default;
158 
159 public:
160   Hmac(ConstBuffer<uint8_t> key);
161   void append(ConstBuffer<uint8_t>);
162   size_t hash(MutableBuffer<uint8_t>);
163   size_t hash(ConstBuffer<uint8_t>, MutableBuffer<uint8_t>);
164 
165 private:
166   H i_;
167   H o_;
168 };
169 
170 template <HashAlgorithm algorithm>
171 void hkdf(MutableBuffer<uint8_t> okm, ConstBuffer<uint8_t> ikm, ConstBuffer<uint8_t> salt,
172           ConstBuffer<uint8_t> info = {(uint8_t const*)"ss-subkey", 9});
173 
174 std::string bin2hex(ConstBuffer<uint8_t> bin);
175 
176 }  // namespace pichi::crypto
177 
178 #endif  // PICHI_CRYPTO_HASH_HPP
179