agievich / bee2
1
/*
2
*******************************************************************************
3
\file belt_wbl.c
4
\brief STB 34.101.31 (belt): wide block encryption
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2017.11.03
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/util.h"
18
#include "bee2/crypto/belt.h"
19
#include "belt_lcl.h"
20

21
/*
22
*******************************************************************************
23
Шифрование широкого блока (WBL)
24

25
\remark Внутренняя реализация представлена бвзовыми (Base) и оптимизированными 
26
(Opt) функциями. Оптимизация включается, когда обрабатываемый широкий блок 
27
состоит из целого числа 128-битовых блоков и число блоков n не меньше 4 при 
28
зашифровании и не меньше 5 при расшифровании.
29

30
\remark Суть оптимизации:
31
- в beltWBLStepEOpt() сумма sum = r1 + ... + r_{n-1} сохраняется и учитывается 
32
  при расчете такой же суммы на следующем такте (требуется 2 сложения 
33
  128-битовых блоков вместо n - 2);
34
- в beltWBLStepD2() сумма sum = r2 + ... + r_{n-1} сохраняется и учитывается 
35
  при расчете такой же суммы на следующем такте (требуется 2 сложения блоков 
36
  вместо n - 3).
37
*******************************************************************************
38
*/
39

40 1
size_t beltWBL_keep()
41
{
42 1
	return sizeof(belt_wbl_st);
43
}
44

45 1
void beltWBLStart(void* state, const octet key[], size_t len)
46
{
47 1
	belt_wbl_st* st = (belt_wbl_st*)state;
48 1
	ASSERT(memIsValid(state, beltWBL_keep()));
49 1
	beltKeyExpand2(st->key, key, len);
50 1
	st->round = 0;
51
}
52

53 1
void beltWBLStepEBase(void* buf, size_t count, void* state)
54
{
55 1
	belt_wbl_st* st = (belt_wbl_st*)state;
56 1
	word n = ((word)count + 15) / 16;
57 1
	ASSERT(count >= 32);
58 1
	ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
59 1
	ASSERT(st->round % (2 * n) == 0);
60
	do
61
	{
62
		size_t i;
63
		// block <- r1 + ... + r_{n-1}
64 1
		beltBlockCopy(st->block, buf);
65 1
		for (i = 16; i + 16 < count; i += 16)
66 1
			beltBlockXor2(st->block, (octet*)buf + i);
67
		// r <- ShLo^128(r)
68 1
		memMove(buf, (octet*)buf + 16, count - 16);
69
		// r* <- block
70 1
		beltBlockCopy((octet*)buf + count - 16, st->block);
71
		// block <- beltBlockEncr(block) + <round>
72 1
		beltBlockEncr(st->block, st->key);
73 1
		st->round++;
74
#if (OCTET_ORDER == LITTLE_ENDIAN)
75 1
		memXor2(st->block, &st->round, O_PER_W);
76
#else // BIG_ENDIAN
77
		st->round = wordRev(st->round);
78
		memXor2(st->block, &st->round, O_PER_W);
79
		st->round = wordRev(st->round);
80
#endif // OCTET_ORDER
81
		// r*_до_сдвига <- r*_до_сдвига + block
82 1
		beltBlockXor2((octet*)buf + count - 32, st->block);
83
	}
84 1
	while (st->round % (2 * n));
85
}
86

87 1
void beltWBLStepEOpt(void* buf, size_t count, void* state)
88
{
89 1
	belt_wbl_st* st = (belt_wbl_st*)state;
90 1
	word n = ((word)count + 15) / 16;
91
	size_t i;
92 1
	ASSERT(count >= 32 && count % 16 == 0);
93 1
	ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
94
	// sum <- r1 + ... + r_{n-1}
95 1
	beltBlockCopy(st->sum, buf);
96 1
	for (i = 16; i + 16 < count; i += 16)
97 1
		beltBlockXor2(st->sum, (octet*)buf + i);
98
	// 2 * n итераций 
99 1
	ASSERT(st->round % (2 * n) == 0);
100
	// sum будет записываться по смещению i: 
101
	// это блок r1 в начале такта и блок r* в конце)
102 1
	i = 0; 
103
	do
104
	{
105
		// block <- beltBlockEncr(sum) + <round>
106 1
		beltBlockCopy(st->block, st->sum);
107 1
		beltBlockEncr(st->block, st->key);
108 1
		st->round++;
109
#if (OCTET_ORDER == LITTLE_ENDIAN)
110 1
		memXor2(st->block, &st->round, O_PER_W);
111
#else // BIG_ENDIAN
112
		st->round = wordRev(st->round);
113
		memXor2(st->block, &st->round, O_PER_W);
114
		st->round = wordRev(st->round);
115
#endif // OCTET_ORDER
116
		// r* <- r* + block
117 1
		beltBlockXor2((octet*)buf + (i + count - 16) % count, st->block);
118
		// запомнить sum
119 1
		beltBlockCopy(st->block, st->sum);
120
		// пересчитать sum: добавить новое слагаемое
121 1
		beltBlockXor2(st->sum, (octet*)buf + (i + count - 16) % count);
122
		// пересчитать sum: исключить старое слагаемое
123 1
		beltBlockXor2(st->sum, (octet*)buf + i);
124
		// сохранить sum
125 1
		beltBlockCopy((octet*)buf + i, st->block);
126
		// вперед
127 1
		i = (i + 16) % count;
128
	}
129 1
	while (st->round % (2 * n));
130
}
131

132 1
void beltWBLStepDBase(void* buf, size_t count, void* state)
133
{
134 1
	belt_wbl_st* st = (belt_wbl_st*)state;
135 1
	word n = ((word)count + 15) / 16;
136 1
	ASSERT(count >= 32);
137 1
	ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
138 1
	for (st->round = 2 * n; st->round; --st->round)
139
	{
140
		size_t i;
141
		// block <- r*
142 1
		beltBlockCopy(st->block, (octet*)buf + count - 16);
143
		// r <- ShHi^128(r)
144 1
		memMove((octet*)buf + 16, buf, count - 16);
145
		// r1 <- block
146 1
		beltBlockCopy(buf, st->block);
147
		// block <- beltBlockEncr(block) + <round>
148 1
		beltBlockEncr(st->block, st->key);
149
#if (OCTET_ORDER == LITTLE_ENDIAN)
150 1
		memXor2(st->block, &st->round, O_PER_W);
151
#else // BIG_ENDIAN
152
		st->round = wordRev(st->round);
153
		memXor2(st->block, &st->round, O_PER_W);
154
		st->round = wordRev(st->round);
155
#endif // OCTET_ORDER
156
		// r* <- r* + block
157 1
		beltBlockXor2((octet*)buf + count - 16, st->block);
158
		// r1 <- r1 + r2 + ... + r_{n-1}
159 1
		for (i = 16; i + 16 < count; i += 16)
160 1
			beltBlockXor2(buf, (octet*)buf + i);
161
	}
162
}
163

164 1
void beltWBLStepDOpt(void* buf, size_t count, void* state)
165
{
166 1
	belt_wbl_st* st = (belt_wbl_st*)state;
167 1
	word n = ((word)count + 15) / 16;
168
	size_t i;
169 1
	ASSERT(count >= 32 && count % 16 == 0);
170 1
	ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
171
	// sum <- r1 + ... + r_{n-2} (будущая сумма r2 + ... + r_{n-1})
172 1
	beltBlockCopy(st->sum, (octet*)buf);
173 1
	for (i = 16; i + 32 < count; i += 16)
174 1
		beltBlockXor2(st->sum, (octet*)buf + i);
175
	// 2 * n итераций (sum будет записываться по смещению i: 
176
	// это блок r* в начале такта и блок r1 в конце)
177 1
	for (st->round = 2 * n, i = count - 16; st->round; --st->round)
178
	{
179
		// block <- beltBlockEncr(r*) + <round>
180 1
		beltBlockCopy(st->block, (octet*)buf + i);
181 1
		beltBlockEncr(st->block, st->key);
182
#if (OCTET_ORDER == LITTLE_ENDIAN)
183 1
		memXor2(st->block, &st->round, O_PER_W);
184
#else // BIG_ENDIAN
185
		st->round = wordRev(st->round);
186
		memXor2(st->block, &st->round, O_PER_W);
187
		st->round = wordRev(st->round);
188
#endif // OCTET_ORDER
189
		// r* <- r* + block
190 1
		beltBlockXor2((octet*)buf + (i + count - 16) % count, st->block);
191
		// r1 <- pre r* + sum
192 1
		beltBlockXor2((octet*)buf + i, st->sum);
193
		// пересчитать sum: исключить старое слагаемое
194 1
		beltBlockXor2(st->sum, (octet*)buf + (i + count - 32) % count);
195
		// пересчитать sum: добавить новое слагаемое
196 1
		beltBlockXor2(st->sum, (octet*)buf + i);
197
		// назад
198 1
		i = (i + count - 16) % count;
199
	}
200
}
201

202 1
void beltWBLStepE(void* buf, size_t count, void* state)
203
{
204 1
	belt_wbl_st* st = (belt_wbl_st*)state;
205 1
	ASSERT(memIsValid(state, beltWBL_keep()));
206 1
	st->round = 0;
207 1
	(count % 16 || count < 64) ? 
208 1
		beltWBLStepEBase(buf, count, state) :
209 1
		beltWBLStepEOpt(buf, count, state);
210
}
211

212 1
void beltWBLStepD(void* buf, size_t count, void* state)
213
{
214 1
	(count % 16 || count < 80) ? 
215 1
		beltWBLStepDBase(buf, count, state) :
216 1
		beltWBLStepDOpt(buf, count, state);
217
}
218

219 1
void beltWBLStepD2(void* buf1, void* buf2, size_t count, void* state)
220
{
221 1
	belt_wbl_st* st = (belt_wbl_st*)state;
222 1
	word n = ((word)count + 15) / 16;
223
	// pre
224 1
	ASSERT(count >= 32);
225 1
	ASSERT(memIsDisjoint3(buf1, count - 16, buf2, 16, state, beltWBL_keep()));
226 1
	for (st->round = 2 * n; st->round; --st->round)
227
	{
228
		size_t i;
229
		// block <- r*
230 1
		beltBlockCopy(st->block, buf2);
231
		// r <- ShHi^128(r)
232 1
		memCopy(buf2, (octet*)buf1 + count - 32, 16);
233 1
		memMove((octet*)buf1 + 16, buf1, count - 32);
234
		// r1 <- block
235 1
		beltBlockCopy(buf1, st->block);
236
		// block <- beltBlockEncr(block) + <round>
237 1
		beltBlockEncr(st->block, st->key);
238
#if (OCTET_ORDER == LITTLE_ENDIAN)
239 1
		memXor2(st->block, &st->round, O_PER_W);
240
#else // BIG_ENDIAN
241
		st->round = wordRev(st->round);
242
		memXor2(st->block, &st->round, O_PER_W);
243
		st->round = wordRev(st->round);
244
#endif // OCTET_ORDER
245
		// r* <- r* + block
246 1
		beltBlockXor2(buf2, st->block);
247
		// r1 <- r1 + r2 + ... + r_{n-1}
248 1
		for (i = 16; i + 32 < count; i += 16)
249 1
			beltBlockXor2(buf1, (octet*)buf1 + i);
250 1
		ASSERT(i + 16 <= count && i + 32 >= count);
251 1
		if (i + 16 < count)
252
		{
253 1
			memXor2(buf1, (octet*)buf1 + i, count - 16 - i);
254 1
			memXor2((octet*)buf1 + count - 16 - i, buf2, 32 + i - count);
255
		}
256
	}
257
}
258

259 0
void beltWBLStepR(void* buf, size_t count, void* state)
260
{
261 0
	(count % 16 || count < 64) ? 
262 0
		beltWBLStepEBase(buf, count, state) :
263 0
		beltWBLStepEOpt(buf, count, state);
264
}

Read our documentation on viewing source code .

Loading