1
/*
2
*******************************************************************************
3
\file belt_dwp.c
4
\brief STB 34.101.31 (belt): DWP (datawrap = data encryption + 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/util.h"
18
#include "bee2/crypto/belt.h"
19
#include "bee2/math/ww.h"
20
#include "belt_lcl.h"
21

22
/*
23
*******************************************************************************
24
Шифрование и имитозащита данных (DWP)
25

26
\remark Режим get-then-continue реализован, но пока не рекомендован
27
(вплоть до завершения оценки надежности).
28
*******************************************************************************
29
*/
30

31
typedef struct
32
{
33
	belt_ctr_st ctr[1];		/*< состояние функций CTR */
34
	word r[W_OF_B(128)];	/*< переменная r */
35
	word t[W_OF_B(128)];	/*< переменная t */
36
	word t1[W_OF_B(128)];	/*< копия t/имитовставка */
37
	word len[W_OF_B(128)];	/*< обработано открытых || критических данных */
38
	octet block[16];		/*< блок данных */
39
	size_t filled;			/*< накоплено октетов в блоке */
40
	octet stack[];			/*< стек умножения */
41
} belt_dwp_st;
42

43 1
size_t beltDWP_keep()
44
{
45 1
	return sizeof(belt_dwp_st) + beltPolyMul_deep();
46
}
47

48 1
void beltDWPStart(void* state, const octet key[], size_t len, 
49
	const octet iv[16])
50
{
51 1
	belt_dwp_st* st = (belt_dwp_st*)state;
52 1
	ASSERT(memIsDisjoint2(iv, 16, state, beltDWP_keep()));
53
	// настроить CTR
54 1
	beltCTRStart(st->ctr, key, len, iv);
55
	// установить r, s
56 1
	beltBlockCopy(st->r, st->ctr->ctr);
57 1
	beltBlockEncr2((u32*)st->r, st->ctr->key);
58
#if (OCTET_ORDER == BIG_ENDIAN && B_PER_W != 32)
59
	beltBlockRevU32(st->r);
60
	beltBlockRevW(st->r);
61
#endif
62 1
	wwFrom(st->t, beltH(), 16);
63
	// обнулить счетчики
64 1
	memSetZero(st->len, sizeof(st->len));
65 1
	st->filled = 0;
66
}
67

68 1
void beltDWPStepE(void* buf, size_t count, void* state)
69
{
70 1
	beltCTRStepE(buf, count, state);
71
}
72

73 1
void beltDWPStepI(const void* buf, size_t count, void* state)
74
{
75 1
	belt_dwp_st* st = (belt_dwp_st*)state;
76 1
	ASSERT(memIsDisjoint2(buf, count, state, beltDWP_keep()));
77
	// критические данные не обрабатывались?
78 1
	ASSERT(count == 0 || beltHalfBlockIsZero(st->len + W_OF_B(64)));
79
	// обновить длину
80 1
	beltHalfBlockAddBitSizeW(st->len, count);
81
	// есть накопленные данные?
82 1
	if (st->filled)
83
	{
84 1
		if (count < 16 - st->filled)
85
		{
86 0
			memCopy(st->block + st->filled, buf, count);
87 0
			st->filled += count;
88 0
			return;
89
		}
90 1
		memCopy(st->block + st->filled, buf, 16 - st->filled);
91 1
		count -= 16 - st->filled;
92 1
		buf = (const octet*)buf + 16 - st->filled;
93
#if (OCTET_ORDER == BIG_ENDIAN)
94
		beltBlockRevW(st->block);
95
#endif
96 1
		beltBlockXor2(st->t, st->block);
97 1
		beltPolyMul(st->t, st->t, st->r, st->stack);
98 1
		st->filled = 0;
99
	}
100
	// цикл по полным блокам
101 1
	while (count >= 16)
102
	{
103 1
		beltBlockCopy(st->block, buf);
104
#if (OCTET_ORDER == BIG_ENDIAN)
105
		beltBlockRevW(st->block);
106
#endif
107 1
		beltBlockXor2(st->t, st->block);
108 1
		beltPolyMul(st->t, st->t, st->r, st->stack);
109 1
		buf = (const octet*)buf + 16;
110 1
		count -= 16;
111
	}
112
	// неполный блок?
113 1
	if (count)
114 1
		memCopy(st->block, buf, st->filled = count);
115
}
116

117 1
void beltDWPStepA(const void* buf, size_t count, void* state)
118
{
119 1
	belt_dwp_st* st = (belt_dwp_st*)state;
120 1
	ASSERT(memIsDisjoint2(buf, count, state, beltDWP_keep()));
121
	// первый непустой фрагмент критических данных?
122
	// есть необработанные открытые данные?
123 1
	if (count && beltHalfBlockIsZero(st->len + W_OF_B(64)) && st->filled)
124
	{
125 0
		memSetZero(st->block + st->filled, 16 - st->filled);
126
#if (OCTET_ORDER == BIG_ENDIAN)
127
		beltBlockRevW(st->block);
128
#endif
129 0
		beltBlockXor2(st->t, st->block);
130 0
		beltPolyMul(st->t, st->t, st->r, st->stack);
131 0
		st->filled = 0;
132
	}
133
	// обновить длину
134 1
	beltHalfBlockAddBitSizeW(st->len + W_OF_B(64), count);
135
	// есть накопленные данные?
136 1
	if (st->filled)
137
	{
138 1
		if (count < 16 - st->filled)
139
		{
140 0
			memCopy(st->block + st->filled, buf, count);
141 0
			st->filled += count;
142 0
			return;
143
		}
144 1
		memCopy(st->block + st->filled, buf, 16 - st->filled);
145 1
		count -= 16 - st->filled;
146 1
		buf = (const octet*)buf + 16 - st->filled;
147
#if (OCTET_ORDER == BIG_ENDIAN)
148
		beltBlockRevW(st->block);
149
#endif
150 1
		beltBlockXor2(st->t, st->block);
151 1
		beltPolyMul(st->t, st->t, st->r, st->stack);
152 1
		st->filled = 0;
153
	}
154
	// цикл по полным блокам
155 1
	while (count >= 16)
156
	{
157 1
		beltBlockCopy(st->block, buf);
158
#if (OCTET_ORDER == BIG_ENDIAN)
159
		beltBlockRevW(st->block);
160
#endif
161 1
		beltBlockXor2(st->t, st->block);
162 1
		beltPolyMul(st->t, st->t, st->r, st->stack);
163 1
		buf = (const octet*)buf + 16;
164 1
		count -= 16;
165
	}
166
	// неполный блок?
167 1
	if (count)
168 1
		memCopy(st->block, buf, st->filled = count);
169
}
170

171 1
void beltDWPStepD(void* buf, size_t count, void* state)
172
{
173 1
	beltCTRStepD(buf, count, state);
174
}
175

176 1
static void beltDWPStepG_internal(void* state)
177
{
178 1
	belt_dwp_st* st = (belt_dwp_st*)state;
179 1
	ASSERT(memIsValid(state, beltDWP_keep()));
180
	// создать копию t и завершить обработку данных
181 1
	if (st->filled)
182
	{
183 1
		memSetZero(st->block + st->filled, 16 - st->filled);
184 1
		wwFrom(st->t1, st->block, 16);
185 1
		beltBlockXor2(st->t1, st->t);
186 1
		beltPolyMul(st->t1, st->t1, st->r, st->stack);
187
	}
188
	else
189 1
		memCopy(st->t1, st->t, 16);
190
	// обработать блок длины
191 1
	beltBlockXor2(st->t1, st->len);
192 1
	beltPolyMul(st->t1, st->t1, st->r, st->stack);
193
#if (OCTET_ORDER == BIG_ENDIAN)
194
	beltBlockRevW(st->t1);
195
#endif
196 1
	beltBlockEncr((octet*)st->t1, st->ctr->key);
197
}
198

199 1
void beltDWPStepG(octet mac[8], void* state)
200
{
201 1
	belt_dwp_st* st = (belt_dwp_st*)state;
202 1
	ASSERT(memIsValid(mac, 8));
203 1
	beltDWPStepG_internal(state);
204 1
	memCopy(mac, st->t1, 8);
205
}
206

207 1
bool_t beltDWPStepV(const octet mac[8], void* state)
208
{
209 1
	belt_dwp_st* st = (belt_dwp_st*)state;
210 1
	ASSERT(memIsValid(mac, 8));
211 1
	beltDWPStepG_internal(state);
212 1
	return memEq(mac, st->t1, 8);
213
}
214

215 1
err_t beltDWPWrap(void* dest, octet mac[8], const void* src1, size_t count1,
216
	const void* src2, size_t count2, const octet key[], size_t len,
217
	const octet iv[16])
218
{
219
	void* state;
220
	// проверить входные данные
221 1
	if (len != 16 && len != 24 && len != 32 ||
222 1
		!memIsValid(src1, count1) ||
223 1
		!memIsValid(src2, count2) ||
224 1
		!memIsValid(key, len) ||
225 1
		!memIsValid(iv, 16) ||
226 1
		!memIsValid(dest, count1) ||
227 1
		!memIsValid(mac, 8))
228 0
		return ERR_BAD_INPUT;
229
	// создать состояние
230 1
	state = blobCreate(beltDWP_keep());
231 1
	if (state == 0)
232 0
		return ERR_OUTOFMEMORY;
233
	// установить защиту (I перед E из-за разрешенного пересечения src2 и dest)
234 1
	beltDWPStart(state, key, len, iv);
235 1
	beltDWPStepI(src2, count2, state);
236 1
	memMove(dest, src1, count1);
237 1
	beltDWPStepE(dest, count1, state);
238 1
	beltDWPStepA(dest, count1, state);
239 1
	beltDWPStepG(mac, state);
240
	// завершить
241 1
	blobClose(state);
242 1
	return ERR_OK;
243
}
244

245 1
err_t beltDWPUnwrap(void* dest, const void* src1, size_t count1,
246
	const void* src2, size_t count2, const octet mac[8], const octet key[],
247
	size_t len, const octet iv[16])
248
{
249
	void* state;
250
	// проверить входные данные
251 1
	if (len != 16 && len != 24 && len != 32 ||
252 1
		!memIsValid(src1, count1) ||
253 1
		!memIsValid(src2, count2) ||
254 1
		!memIsValid(mac, 8) ||
255 1
		!memIsValid(key, len) ||
256 1
		!memIsValid(iv, 16) ||
257 1
		!memIsValid(dest, count1))
258 0
		return ERR_BAD_INPUT;
259
	// создать состояние
260 1
	state = blobCreate(beltDWP_keep());
261 1
	if (state == 0)
262 0
		return ERR_OUTOFMEMORY;
263
	// снять защиту
264 1
	beltDWPStart(state, key, len, iv);
265 1
	beltDWPStepI(src2, count2, state);
266 1
	beltDWPStepA(src1, count1, state);
267 1
	if (!beltDWPStepV(mac, state))
268
	{
269 0
		blobClose(state);
270 0
		return ERR_BAD_MAC;
271
	}
272 1
	memMove(dest, src1, count1);
273 1
	beltDWPStepD(dest, count1, state);
274
	// завершить
275 1
	blobClose(state);
276 1
	return ERR_OK;
277
}

Read our documentation on viewing source code .

Loading