File: k12m14_provider.hpp

package info (click to toggle)
salmon 1.10.2%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 35,580 kB
  • sloc: cpp: 199,285; ansic: 171,082; sh: 859; python: 792; makefile: 235
file content (138 lines) | stat: -rw-r--r-- 2,666 bytes parent folder | download | duplicates (8)
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
129
130
131
132
133
134
135
136
137
138
/*
This code is written by kerukuro and released into public domain.
*/

#ifndef DIGESTPP_PROVIDERS_K12M14_HPP
#define DIGESTPP_PROVIDERS_K12M14_HPP

#include "../../detail/functions.hpp"
#include "../../detail/absorb_data.hpp"
#include "shake_provider.hpp"
#include <array>

namespace digestpp
{

namespace detail
{

template<size_t B>
class k12m14_provider
{
public:
	static const bool is_xof = true;

	k12m14_provider()
	{
		static_assert(B == 128 || B == 256, "K12M14 only supports 128 and 256 bits");
	}

	~k12m14_provider()
	{
		clear();
	}

	inline void set_customization(const std::string& customization)
	{
		S = customization;
	}

	inline void init()
	{
		main.init();
		pos = 0;
		chunk = 0;
		squeezing = false;
	}

	inline void update(const unsigned char* data, size_t len)
	{
		detail::absorb_bytes(data, len, m.size(), m.size(), m.data(), pos, total, 
			[this](const unsigned char* data, size_t len) { transform(data, len, len * 8192); });
	}

	inline void squeeze(unsigned char* hash, size_t hs)
	{
		if (!squeezing)
		{
			unsigned char buf[B / 4];
			size_t len = shake_functions::right_encode(S.length(), buf, true);
			if (!S.empty())
				update(reinterpret_cast<const unsigned char*>(S.data()), S.length());
			update(buf, len); 
			if (pos)
			{
				if (!chunk)
				{
					main.update(m.data(), pos);
					main.set_suffix(0x07);
				}
				else
				{
					child.update(m.data(), pos);
					child.squeeze(buf, B / 4);
					main.update(buf, B / 4);
					main.set_suffix(0x06);
					len = shake_functions::right_encode(chunk, buf, true);
					main.update(buf, len);
					main.update(reinterpret_cast<const unsigned char*>("\xFF\xFF"), 2);
				}
			}
			squeezing = true;
		}
		main.squeeze(hash, hs);
	}

	inline void transform(const unsigned char* data, uint64_t num_blks, size_t reallen)
	{
		for (uint64_t blk = 0; blk < num_blks; blk++)
		{
			if (!chunk)
			{
				main.update(data, 8192);
				main.update(reinterpret_cast<const unsigned char*>("\x03\x00\x00\x00\x00\x00\x00\x00"), 8);
			}
			else
			{
				child.update(data, 8192);
				unsigned char buf[B / 4];
				child.squeeze(buf, B / 4);
				main.update(buf, B / 4);
			}

			child.init();
			child.set_suffix(0x0b);
			++chunk;
			data += 8192;
		}
	}


	inline void clear()
	{
		main.clear();
		child.clear();
		zero_memory(m);
		zero_memory(S);
		S.clear();
	}

private:
	constexpr static size_t R = B == 128 ? 12 : 14;
	shake_provider<B, R> main;
	shake_provider<B, R> child;
	std::array<unsigned char, 8192> m;
	std::string S;
	size_t pos;
	size_t total;
	size_t chunk;
	bool squeezing;
};

} // namespace detail

} // namespace digestpp

#endif // DIGESTPP_PROVIDERS_K12M14_HPP