File: kmac_provider.hpp

package info (click to toggle)
rapmap 0.15.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,228 kB
  • sloc: cpp: 48,810; ansic: 4,686; sh: 215; python: 82; makefile: 15
file content (128 lines) | stat: -rw-r--r-- 2,483 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
This code is written by kerukuro and released into public domain.
*/

#ifndef DIGESTPP_PROVIDERS_KMAC_HPP
#define DIGESTPP_PROVIDERS_KMAC_HPP

#include "shake_provider.hpp"

namespace digestpp
{

namespace detail
{

namespace kmac_functions
{
	template<size_t B>
	inline std::string bytepad(const std::string& str)
	{
		const size_t pad = B == 128 ? 168 : 136;
		unsigned char buf[32];
		size_t len = shake_functions::left_encode(pad, buf);
		std::string res(reinterpret_cast<const char*>(buf), len);
		len = shake_functions::left_encode(str.length() * 8, buf);
		res.append(reinterpret_cast<const char*>(buf), len);
		res.append(str);
		size_t delta = pad - res.size() % pad;
		if (delta && delta != pad)
			res.append(delta, '\x00');
		return res;
	}

} // namespace kmac_functions


template<size_t B, bool XOF>
class kmac_provider
{
public:
	static const bool is_xof = XOF;

	template<bool xof=XOF, typename std::enable_if<!xof>::type* = nullptr>
	kmac_provider(size_t hashsize) : hs(hashsize)
	{
		static_assert(B == 128 || B == 256, "KMAC only supports 128 and 256 bits");
		validate_hash_size(hashsize, SIZE_MAX);
		set_key("");
	}

	template<bool xof=XOF, typename std::enable_if<xof>::type* = nullptr>
	kmac_provider() : hs(0)
	{
		static_assert(B == 128 || B == 256, "KMAC only supports 128 and 256 bits");
		set_key("");
	}

	~kmac_provider()
	{
		clear();
	}

	inline void set_key(const std::string& key)
	{
		K = kmac_functions::bytepad<B>(key);
	}

	inline void set_customization(const std::string& customization)
	{
		shake.set_customization(customization);
	}

	inline void init()
	{
		squeezing = false;
		shake.set_function_name("KMAC");
		shake.init();
		update(reinterpret_cast<const unsigned char*>(K.data()), K.length());
	}

	inline void update(const unsigned char* data, size_t len)
	{
		shake.update(data, len);
	}

	inline void squeeze(unsigned char* hash, size_t hs)
	{
		if (!squeezing)
		{
			unsigned char buf[32];
			size_t len = shake_functions::right_encode(!XOF ? hs * 8 : 0, buf, false);
			update(buf, len); 
			squeezing = true;
		}
		shake.squeeze(hash, hs);
	}

	inline void final(unsigned char* hash)
	{
		squeeze(hash, hs / 8);
	}

	inline void clear()
	{
		shake.clear();
		zero_memory(K);
		set_key("");
	}

	inline size_t hash_size() const
	{
		return hs;
	}

private:
	std::string K;
	size_t hs;
	bool squeezing;
	shake_provider<B, 24> shake;
};

} // namespace detail

} // namespace digestpp

#endif // DIGESTPP_PROVIDERS_KMAC_HPP