1
/*
2
*******************************************************************************
3
\file belt_hmac.c
4
\brief STB 34.101.31 (belt): HMAC message authentication
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2012.12.18
8
\version 2020.03.24
9
\license This program is released under the GNU General Public License 
10
version 3. See Copyright Notices in bee2/info.h.
11
*******************************************************************************
12
*/
13

14
#include "bee2/core/blob.h"
15
#include "bee2/core/err.h"
16
#include "bee2/core/mem.h"
17
#include "bee2/core/u32.h"
18
#include "bee2/core/util.h"
19
#include "bee2/crypto/belt.h"
20
#include "belt_lcl.h"
21

22
/*
23
*******************************************************************************
24
Ключезависимое хэширование (HMAC)
25
*******************************************************************************
26
*/
27
typedef struct
28
{
29
	u32 ls_in[8];		/*< блок [4]len || [4]s внутреннего хэширования */
30
	u32 h_in[8];		/*< переменная h внутреннего хэширования */
31
	u32 h1_in[8];		/*< копия переменной h внутреннего хэширования */
32
	u32 ls_out[8];		/*< блок [4]len || [4]s внешнего хэширования */
33
	u32 h_out[8];		/*< переменная h внешнего хэширования */
34
	u32 h1_out[8];		/*< копия переменной h внешнего хэширования */
35
	u32 s1[4];			/*< копия переменной s */
36
	octet block[32];	/*< блок данных */
37
	size_t filled;		/*< накоплено октетов в блоке */
38
	octet stack[];		/*< [beltCompr_deep()] стек beltCompr */
39
} belt_hmac_st;
40

41 1
size_t beltHMAC_keep()
42
{
43 1
	return sizeof(belt_hmac_st) + beltCompr_deep();
44
}
45

46 1
void beltHMACStart(void* state, const octet key[], size_t len)
47
{
48 1
	belt_hmac_st* st = (belt_hmac_st*)state;
49 1
	ASSERT(memIsDisjoint2(key, len, state, beltHMAC_keep()));
50
	// key <- key || 0
51 1
	if (len <= 32)
52
	{
53 1
		memCopy(st->block, key, len);
54 1
		memSetZero(st->block + len, 32 - len);
55
#if (OCTET_ORDER == BIG_ENDIAN)
56
		beltBlockRevU32(st->block);
57
		beltBlockRevU32(st->block + 16);
58
#endif
59
	}
60
	// key <- beltHash(key)
61
	else
62
	{
63 1
		beltBlockSetZero(st->ls_in);
64 1
		beltBlockAddBitSizeU32(st->ls_in, len);
65 1
		beltBlockSetZero(st->ls_in + 4);
66 1
		u32From(st->h_in, beltH(), 32);
67 1
		while (len >= 32)
68
		{
69 1
			beltBlockCopy(st->block, key);
70 1
			beltBlockCopy(st->block + 16, key + 16);
71
#if (OCTET_ORDER == BIG_ENDIAN)
72
			beltBlockRevU32(st->block);
73
			beltBlockRevU32(st->block + 16);
74
#endif
75 1
			beltCompr2(st->ls_in + 4, st->h_in, (u32*)st->block, st->stack);
76 1
			key += 32;
77 1
			len -= 32;
78
		}
79 1
		if (len)
80
		{
81 1
			memCopy(st->block, key, len);
82 1
			memSetZero(st->block + len, 32 - len);
83
#if (OCTET_ORDER == BIG_ENDIAN)
84
			beltBlockRevU32(st->block);
85
			beltBlockRevU32(st->block + 16);
86
#endif
87 1
			beltCompr2(st->ls_in + 4, st->h_in, (u32*)st->block, st->stack);
88
		}
89 1
		beltCompr(st->h_in, st->ls_in, st->stack);
90 1
		beltBlockCopy(st->block, st->h_in);
91 1
		beltBlockCopy(st->block + 16, st->h_in + 4);
92
	}
93
	// сформировать key ^ ipad
94 1
	for (len = 0; len < 32; ++len)
95 1
		st->block[len] ^= 0x36;
96
	// начать внутреннее хэширование
97 1
	beltBlockSetZero(st->ls_in);
98 1
	beltBlockAddBitSizeU32(st->ls_in, 32);
99 1
	beltBlockSetZero(st->ls_in + 4);
100 1
	u32From(st->h_in, beltH(), 32);
101 1
	beltCompr2(st->ls_in + 4, st->h_in, (u32*)st->block, st->stack);
102 1
	st->filled = 0;
103
	// сформировать key ^ opad [0x36 ^ 0x5C == 0x6A]
104 1
	for (; len--; )
105 1
		st->block[len] ^= 0x6A;
106
	// начать внешнее хэширование [будет хэшироваться ровно два блока]
107 1
	beltBlockSetZero(st->ls_out);
108 1
	beltBlockAddBitSizeU32(st->ls_out, 32 * 2);
109 1
	beltBlockSetZero(st->ls_out + 4);
110 1
	u32From(st->h_out, beltH(), 32);
111 1
	beltCompr2(st->ls_out + 4, st->h_out, (u32*)st->block, st->stack);
112
}
113

114 1
void beltHMACStepA(const void* buf, size_t count, void* state)
115
{
116 1
	belt_hmac_st* st = (belt_hmac_st*)state;
117 1
	ASSERT(memIsDisjoint2(buf, count, state, beltHMAC_keep()));
118
	// обновить длину
119 1
	beltBlockAddBitSizeU32(st->ls_in, count);
120
	// есть накопленные данные?
121 1
	if (st->filled)
122
	{
123 1
		if (count < 32 - st->filled)
124
		{
125 1
			memCopy(st->block + st->filled, buf, count);
126 1
			st->filled += count;
127 1
			return;
128
		}
129 1
		memCopy(st->block + st->filled, buf, 32 - st->filled);
130 1
		count -= 32 - st->filled;
131 1
		buf = (const octet*)buf + 32 - st->filled;
132
#if (OCTET_ORDER == BIG_ENDIAN)
133
		beltBlockRevU32(st->block);
134
		beltBlockRevU32(st->block + 16);
135
#endif
136 1
		beltCompr2(st->ls_in + 4, st->h_in, (u32*)st->block, st->stack);
137 1
		st->filled = 0;
138
	}
139
	// цикл по полным блокам
140 1
	while (count >= 32)
141
	{
142 1
		beltBlockCopy(st->block, buf);
143 1
		beltBlockCopy(st->block + 16, (const octet*)buf + 16);
144
#if (OCTET_ORDER == BIG_ENDIAN)
145
		beltBlockRevU32(st->block);
146
		beltBlockRevU32(st->block + 16);
147
#endif
148 1
		beltCompr2(st->ls_in + 4, st->h_in, (u32*)st->block, st->stack);
149 1
		buf = (const octet*)buf + 32;
150 1
		count -= 32;
151
	}
152
	// неполный блок?
153 1
	if (count)
154 1
		memCopy(st->block, buf, st->filled = count);
155
}
156

157 1
static void beltHMACStepG_internal(void* state)
158
{
159 1
	belt_hmac_st* st = (belt_hmac_st*)state;
160
	// pre
161 1
	ASSERT(memIsValid(state, beltHash_keep()));
162
	// создать копии второй части st->ls_in и st->h_in
163 1
	beltBlockCopy(st->s1, st->ls_in + 4);
164 1
	beltBlockCopy(st->h1_in, st->h_in);
165 1
	beltBlockCopy(st->h1_in + 4, st->h_in + 4);
166
	// есть необработанные данные?
167 1
	if (st->filled)
168
	{
169 1
		memSetZero(st->block + st->filled, 32 - st->filled);
170
#if (OCTET_ORDER == BIG_ENDIAN)
171
		beltBlockRevU32(st->block);
172
		beltBlockRevU32(st->block + 16);
173
#endif
174 1
		beltCompr2(st->ls_in + 4, st->h1_in, (u32*)st->block, st->stack);
175
#if (OCTET_ORDER == BIG_ENDIAN)
176
		beltBlockRevU32(st->block + 16);
177
		beltBlockRevU32(st->block);
178
#endif
179
	}
180
	// последний блок внутреннего хэширования
181 1
	beltCompr(st->h1_in, st->ls_in, st->stack);
182
	// восстановить сохраненную часть st->ls_in
183 1
	beltBlockCopy(st->ls_in + 4, st->s1);
184
	// создать копии второй части st->ls_out и st->h_out
185 1
	beltBlockCopy(st->s1, st->ls_out + 4);
186 1
	beltBlockCopy(st->h1_out, st->h_out);
187 1
	beltBlockCopy(st->h1_out + 4, st->h_out + 4);
188
	// обработать блок st->h1_in
189 1
	beltCompr2(st->ls_out + 4, st->h1_out, st->h1_in, st->stack);
190
	// последний блок внешнего хэширования
191 1
	beltCompr(st->h1_out, st->ls_out, st->stack);
192
	// восстановить сохраненную часть st->ls_out
193 1
	beltBlockCopy(st->ls_out + 4, st->s1);
194
}
195

196 1
void beltHMACStepG(octet mac[32], void* state)
197
{
198 1
	belt_hmac_st* st = (belt_hmac_st*)state;
199 1
	ASSERT(memIsValid(mac, 32));
200 1
	beltHMACStepG_internal(state);
201 1
	u32To(mac, 32, st->h1_out);
202
}
203

204 1
void beltHMACStepG2(octet mac[], size_t mac_len, void* state)
205
{
206 1
	belt_hmac_st* st = (belt_hmac_st*)state;
207 1
	ASSERT(mac_len <= 32);
208 1
	ASSERT(memIsValid(mac, mac_len));
209 1
	beltHMACStepG_internal(state);
210 1
	u32To(mac, mac_len, st->h1_out);
211
}
212

213 1
bool_t beltHMACStepV(const octet mac[32], void* state)
214
{
215 1
	belt_hmac_st* st = (belt_hmac_st*)state;
216 1
	ASSERT(memIsValid(mac, 32));
217 1
	beltHMACStepG_internal(state);
218
#if (OCTET_ORDER == BIG_ENDIAN)
219
	beltBlockRevU32(st->h1_out);
220
	beltBlockRevU32(st->h1_out + 4);
221
#endif
222 1
	return memEq(mac, st->h1_out, 32);
223
}
224

225 1
bool_t beltHMACStepV2(const octet mac[], size_t mac_len, void* state)
226
{
227 1
	belt_hmac_st* st = (belt_hmac_st*)state;
228 1
	ASSERT(mac_len <= 32);
229 1
	ASSERT(memIsValid(mac, mac_len));
230 1
	beltHMACStepG_internal(state);
231
#if (OCTET_ORDER == BIG_ENDIAN)
232
	beltBlockRevU32(st->h1_out);
233
	beltBlockRevU32(st->h1_out + 4);
234
#endif
235 1
	return memEq(mac, st->h1_out, mac_len);
236
}
237

238 1
err_t beltHMAC(octet mac[32], const void* src, size_t count,
239
	const octet key[], size_t len)
240
{
241
	void* state;
242
	// проверить входные данные
243 1
	if (!memIsValid(src, count) ||
244 1
		!memIsValid(key, len) ||
245 1
		!memIsValid(mac, 32))
246 0
		return ERR_BAD_INPUT;
247
	// создать состояние
248 1
	state = blobCreate(beltHMAC_keep());
249 1
	if (state == 0)
250 0
		return ERR_OUTOFMEMORY;
251
	// выработать имитовставку
252 1
	beltHMACStart(state, key, len);
253 1
	beltHMACStepA(src, count, state);
254 1
	beltHMACStepG(mac, state);
255
	// завершить
256 1
	blobClose(state);
257 1
	return ERR_OK;
258
}

Read our documentation on viewing source code .

Loading