agievich / bee2
1
/*
2
*******************************************************************************
3
\file belt_mac.c
4
\brief STB 34.101.31 (belt): MAC (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
Имитозащита (MAC)
25

26
Для ускорения работы текущая имитовставка s хранится в виде [4]u32.
27
Это позволяет зашифровывать s с помощью функции beltBlockEncr2(),
28
в которой не используется реверс октетов даже на платформах BIG_ENDIAN.
29
Реверс применяется только перед сложением накопленного блока данных
30
с текущей имитовставкой.
31
*******************************************************************************
32
*/
33
typedef struct
34
{
35
	u32 key[8];			/*< форматированный ключ */
36
	u32 s[4];			/*< переменная s */
37
	u32 r[4];			/*< переменная r */
38
	u32 mac[4];			/*< окончательная имитовставка */
39
	octet block[16];	/*< блок данных */
40
	size_t filled;		/*< накоплено октетов в блоке */
41
} belt_mac_st;
42

43 1
size_t beltMAC_keep()
44
{
45 1
	return sizeof(belt_mac_st);
46
}
47

48 1
void beltMACStart(void* state, const octet key[], size_t len)
49
{
50 1
	belt_mac_st* st = (belt_mac_st*)state;
51 1
	ASSERT(memIsValid(state, beltMAC_keep()));
52 1
	beltKeyExpand2(st->key, key, len);
53 1
	beltBlockSetZero(st->s);
54 1
	beltBlockSetZero(st->r);
55 1
	beltBlockEncr2(st->r, st->key);
56 1
	st->filled = 0;
57
}
58

59 1
void beltMACStepA(const void* buf, size_t count, void* state)
60
{
61 1
	belt_mac_st* st = (belt_mac_st*)state;
62 1
	ASSERT(memIsDisjoint2(buf, count, state, beltMAC_keep()));
63
	// накопить полный блок
64 1
	if (st->filled < 16)
65
	{
66 1
		if (count <= 16 - st->filled)
67
		{
68 1
			memCopy(st->block + st->filled, buf, count);
69 1
			st->filled += count;
70 1
			return;
71
		}
72 1
		memCopy(st->block + st->filled, buf, 16 - st->filled);
73 1
		count -= 16 - st->filled;
74 1
		buf = (const octet*)buf + 16 - st->filled;
75 1
		st->filled = 16;
76
	}
77
	// цикл по полным блокам
78 1
	while (count >= 16)
79
	{
80
#if (OCTET_ORDER == BIG_ENDIAN)
81
		beltBlockRevU32(st->block);
82
#endif
83 1
		beltBlockXor2(st->s, st->block);
84 1
		beltBlockEncr2(st->s, st->key);
85 1
		beltBlockCopy(st->block, buf);
86 1
		buf = (const octet*)buf + 16;
87 1
		count -= 16;
88
	}
89
	// неполный блок?
90 1
	if (count)
91
	{
92
#if (OCTET_ORDER == BIG_ENDIAN)
93
		beltBlockRevU32(st->block);
94
#endif
95 1
		beltBlockXor2(st->s, st->block);
96 1
		beltBlockEncr2(st->s, st->key);
97 1
		memCopy(st->block, buf, count);
98 1
		st->filled = count;
99
	}
100
}
101

102 1
static void beltMACStepG_internal(void* state)
103
{
104 1
	belt_mac_st* st = (belt_mac_st*)state;
105 1
	ASSERT(memIsValid(state, beltMAC_keep()));
106
	// полный блок?
107 1
	if (st->filled == 16)
108
	{
109
#if (OCTET_ORDER == BIG_ENDIAN)
110
		beltBlockRevU32(st->block);
111
#endif
112 1
		beltBlockXor(st->mac, st->s, st->block);
113 1
		st->mac[0] ^= st->r[1];
114 1
		st->mac[1] ^= st->r[2];
115 1
		st->mac[2] ^= st->r[3];
116 1
		st->mac[3] ^= st->r[0] ^ st->r[1];
117
#if (OCTET_ORDER == BIG_ENDIAN)
118
		beltBlockRevU32(st->block);
119
#endif
120
	}
121
	// неполный (в т.ч. пустой) блок?
122
	else
123
	{
124 1
		st->block[st->filled] = 0x80;
125 1
		memSetZero(st->block + st->filled + 1, 16 - st->filled - 1);
126
#if (OCTET_ORDER == BIG_ENDIAN)
127
		beltBlockRevU32(st->block);
128
#endif
129 1
		beltBlockXor(st->mac, st->s, st->block);
130 1
		st->mac[0] ^= st->r[0] ^ st->r[3];
131 1
		st->mac[1] ^= st->r[0];
132 1
		st->mac[2] ^= st->r[1];
133 1
		st->mac[3] ^= st->r[2];
134
#if (OCTET_ORDER == BIG_ENDIAN)
135
		beltBlockRevU32(st->block);
136
#endif
137
	}
138 1
	beltBlockEncr2(st->mac, st->key);
139
}
140

141 1
void beltMACStepG(octet mac[8], void* state)
142
{
143 1
	belt_mac_st* st = (belt_mac_st*)state;
144 1
	ASSERT(memIsValid(mac, 8));
145 1
	beltMACStepG_internal(state);
146 1
	u32To(mac, 8, st->mac);
147
}
148

149 1
void beltMACStepG2(octet mac[], size_t mac_len, void* state)
150
{
151 1
	belt_mac_st* st = (belt_mac_st*)state;
152 1
	ASSERT(mac_len <= 8);
153 1
	ASSERT(memIsValid(mac, mac_len));
154 1
	beltMACStepG_internal(state);
155 1
	u32To(mac, mac_len, st->mac);
156
}
157

158 1
bool_t beltMACStepV(const octet mac[8], void* state)
159
{
160 1
	belt_mac_st* st = (belt_mac_st*)state;
161 1
	ASSERT(memIsValid(mac, 8));
162 1
	beltMACStepG_internal(state);
163
#if (OCTET_ORDER == BIG_ENDIAN)
164
	st->mac[0] = u32Rev(st->mac[0]);
165
	st->mac[1] = u32Rev(st->mac[1]);
166
#endif
167 1
	return memEq(mac, st->mac, 8);
168
}
169

170 1
bool_t beltMACStepV2(const octet mac[], size_t mac_len, void* state)
171
{
172 1
	belt_mac_st* st = (belt_mac_st*)state;
173 1
	ASSERT(mac_len <= 8);
174 1
	ASSERT(memIsValid(mac, mac_len));
175 1
	beltMACStepG_internal(st);
176
#if (OCTET_ORDER == BIG_ENDIAN)
177
	st->mac[0] = u32Rev(st->mac[0]);
178
	st->mac[1] = u32Rev(st->mac[1]);
179
#endif
180 1
	return memEq(mac, st->mac, mac_len);
181
}
182

183 1
err_t beltMAC(octet mac[8], const void* src, size_t count,
184
	const octet key[], size_t len)
185
{
186
	void* state;
187
	// проверить входные данные
188 1
	if (len != 16 && len != 24 && len != 32 ||
189 1
		!memIsValid(src, count) ||
190 1
		!memIsValid(key, len) ||
191 1
		!memIsValid(mac, 8))
192 0
		return ERR_BAD_INPUT;
193
	// создать состояние
194 1
	state = blobCreate(beltMAC_keep());
195 1
	if (state == 0)
196 0
		return ERR_OUTOFMEMORY;
197
	// выработать имитовставку
198 1
	beltMACStart(state, key, len);
199 1
	beltMACStepA(src, count, state);
200 1
	beltMACStepG(mac, state);
201
	// завершить
202 1
	blobClose(state);
203 1
	return ERR_OK;
204
}

Read our documentation on viewing source code .

Loading