agievich / bee2
1
/*
2
*******************************************************************************
3
\file bash_ae.c
4
\brief STB 34.101.77 (bash): authenticated encryption
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2018.10.30
8
\version 2019.07.09
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/bash.h"
19

20
/*
21
*******************************************************************************
22
Аутентифицированное шифрование
23

24
\remark В bash_ae_st::s хранится состояние автомата. Состояние как строка 
25
октетов состоит из трех последовательных частей:
26
1) буфер (block_len = 192 - l / 4 октетов);
27
2) октет управление (смещение block_len);
28
3) память (все остальное).
29

30
\remark Макросы bashAECtrlX управляют частями октета управления. Эти части:
31
A) признак полного (1) / неполного (0) блока (1 бит);
32
B) признак промежуточного (1) / завершающего (0) блока (1 бит);
33
C) тип текущего блока (3 бита);
34
D) тип следующего блока (3 бита).
35
Обработка блока отложенная, поэтому тип следующего блока будет известен 
36
в момент обработки.
37

38
\remark В bashAEStart() состояние заполнено так, как будто сделаны вызовы
39
	bashAECtrlA(s, 0), bashAECtrlB(s, 0), bashAECtrlC(s, BASH_KEY);
40
*******************************************************************************
41
*/
42

43
typedef struct {
44
	octet s[192];		/*< состояние */
45
	size_t block_len;	/*< длина блока */
46
	size_t filled;		/*< загружено/выгружено октетов в блок/из блока */
47
	octet code;			/*< код текущего типа данных */
48
	octet stack[];		/*< [[bashF_deep()] стек bashF */
49
} bash_ae_st;
50

51 1
static void bashAECtrl(bash_ae_st* s, octet mask, octet val)
52
{
53 1
	s->s[s->block_len] &= mask;
54 1
	s->s[s->block_len] |= val;
55
}
56

57
#define bashAECtrlA(s, a) bashAECtrl(s, 0x7F, (a) << 7)
58
#define bashAECtrlB(s, b) bashAECtrl(s, 0xBF, (b) << 6)
59
#define bashAECtrlC(s, c) bashAECtrl(s, 0xC7, (c) << 3)
60
#define bashAECtrlD(s, d) bashAECtrl(s, 0xF8, (d) << 0)
61

62 1
size_t bashAE_keep()
63
{
64 1
	return sizeof(bash_ae_st) + bashF_deep();
65
}
66

67 1
void bashAEStart(void* state, const octet key[], size_t key_len, 
68
	const octet iv[], size_t iv_len)
69
{
70 1
	bash_ae_st* s = (bash_ae_st*)state;
71 1
	ASSERT(key_len == 16 || key_len == 24 || key_len == 32);
72 1
	ASSERT(iv_len <= key_len * 2);
73 1
	ASSERT(memIsDisjoint2(s, bashAE_keep(), key, key_len));
74 1
	ASSERT(memIsDisjoint2(s, bashAE_keep(), iv, iv_len));
75
	// s[0..1472 = 184 * 8) <- key || iv || 10...0
76 1
	memCopy(s->s, key, key_len); 
77 1
	memCopy(s->s + key_len, iv, iv_len);
78 1
	memSetZero(s->s + key_len + iv_len, 192 - key_len - iv_len);
79 1
	s->s[key_len + iv_len] = 0x80;
80
	// s[1472..) <- <l / 4 + 1>_{64}
81 1
	s->s[192 - 8] = (octet)(key_len * 2 + 1);
82
	// длина блока
83 1
	s->block_len = 192 - key_len * 2;
84
	// накопленные данные 
85 1
	s->filled = key_len + iv_len;
86
	// запомнить код
87 1
	s->code = BASH_AE_KEY;
88
}
89

90
/*
91
*******************************************************************************
92
Absorb (Загрузка)
93
*******************************************************************************
94
*/
95

96 1
void bashAEAbsorbStart(octet code, void* state)
97
{
98 1
	bash_ae_st* s = (bash_ae_st*)state;
99 1
	ASSERT(code == BASH_AE_KEY || code == BASH_AE_DATA);
100 1
	ASSERT(memIsValid(s, bashAE_keep()));
101
	// обработать отложенный блок
102 1
	bashAECtrlA(s, s->filled == s->block_len); /* полный? */
103 1
	bashAECtrlB(s, 0); /* заключительный */
104 1
	bashAECtrlC(s, s->code);
105 1
	bashAECtrlD(s, code);
106 1
	bashF(s->s, s->stack);
107 1
	s->filled = 0;
108
	// запомнить код
109 1
	s->code = code;
110
}
111

112 1
void bashAEAbsorbStep(const void* buf, size_t count, void* state)
113
{
114 1
	bash_ae_st* s = (bash_ae_st*)state;
115 1
	ASSERT(memIsDisjoint2(buf, count, s, bashAE_keep()));
116
	// не накопится на полный блок?
117 1
	if (count < s->block_len - s->filled)
118
	{
119 1
		memCopy(s->s + s->filled, buf, count);
120 1
		s->filled += count;
121 1
		return;
122
	}
123
	// новый полный блок
124 0
	memCopy(s->s + s->filled, buf, s->block_len - s->filled);
125 0
	buf = (const octet*)buf + s->block_len - s->filled;
126 0
	count -= s->block_len - s->filled;
127 0
	s->filled = s->block_len;
128
	// цикл по полным блокам
129 0
	while (count >= s->block_len)
130
	{
131
		// обработать отложенный блок
132 0
		bashAECtrlA(s, 1); /* полный */
133 0
		bashAECtrlB(s, 1); /* промежуточный */
134 0
		bashAECtrlC(s, s->code);
135 0
		bashAECtrlD(s, s->code);
136 0
		bashF(s->s, s->stack);
137
		// новый полный блок
138 0
		memCopy(s->s, buf, s->block_len);
139 0
		buf = (const octet*)buf + s->block_len;
140 0
		count -= s->block_len;
141
	}
142
	// неполный блок?
143 0
	if (count)
144 0
		memCopy(s->s, buf, s->filled = count);
145
}
146

147 1
void bashAEAbsorbStop(void* state)
148
{
149 1
	bash_ae_st* s = (bash_ae_st*)state;
150 1
	ASSERT(memIsValid(s, bashAE_keep()));
151
	// подготовить отложенный блок к завершению текущей операции
152 1
	memSetZero(s->s + s->filled, s->block_len - s->filled);
153
	// можем попасть в октет управления, но это не важно
154 1
	s->s[s->filled] = 0x80;
155
}
156

157 1
void bashAEAbsorb(octet code, const void* buf, size_t count, void* state)
158
{
159 1
	bashAEAbsorbStart(code, state);
160 1
	bashAEAbsorbStep(buf, count, state);
161 1
	bashAEAbsorbStop(state);
162
}
163

164
/*
165
*******************************************************************************
166
Squeeze (Выгрузка)
167
*******************************************************************************
168
*/
169

170 1
void bashAESqueezeStart(octet code, void* state)
171
{
172 1
	bash_ae_st* s = (bash_ae_st*)state;
173 1
	ASSERT(code == BASH_AE_PRN || code == BASH_AE_MAC);
174 1
	ASSERT(memIsValid(s, bashAE_keep()));
175
	// обработать отложенный блок
176 1
	bashAECtrlA(s, s->filled == s->block_len); /* полный? */
177 1
	bashAECtrlB(s, 0); /* заключительный */ 
178 1
	bashAECtrlC(s, s->code);
179 1
	bashAECtrlD(s, code);
180 1
	bashF(s->s, s->stack);
181 1
	s->filled = 0;
182
	// запомнить код
183 1
	s->code = code;
184
}
185

186 1
void bashAESqueezeStep(void* buf, size_t count, void* state)
187
{
188 1
	bash_ae_st* s = (bash_ae_st*)state;
189 1
	ASSERT(memIsDisjoint2(buf, count, s, bashAE_keep()));
190
	// есть остаток в буфере?
191 1
	if (s->filled < s->block_len)
192
	{
193 1
		if (count <= s->block_len - s->filled)
194
		{
195 1
			memCopy(buf, s->s + s->filled, count);
196 1
			s->filled += count;
197 1
			return;
198
		}
199
		// новый входной полный блок
200 0
		memCopy(buf, s->s + s->filled, s->block_len - s->filled);
201 0
		buf = (octet*)buf + s->block_len - s->filled;
202 0
		count -= s->block_len - s->filled;
203 0
		s->filled = s->block_len;
204
	}
205
	// цикл по полным блокам
206 0
	while (count >= s->block_len)
207
	{
208
		// обработать отложенный блок
209 0
		bashAECtrlA(s, 0); /* всегда 0 */
210 0
		bashAECtrlB(s, 1); /* промежуточный */
211 0
		bashAECtrlC(s, s->code);
212 0
		bashAECtrlD(s, s->code);
213 0
		bashF(s->s, s->stack);
214
		// новый полный блок
215 0
		memCopy(buf, s->s, s->block_len);
216 0
		buf = (octet*)buf + s->block_len;
217 0
		count -= s->block_len;
218
	}
219
	// еще?
220 0
	if (count)
221
	{
222
		// обработать отложенный блок
223 0
		bashAECtrlA(s, 0); /* всегда 0 */
224 0
		bashAECtrlB(s, 1); /* промежуточный */
225 0
		bashAECtrlC(s, s->code);
226 0
		bashAECtrlD(s, s->code);
227 0
		bashF(s->s, s->stack);
228
		// новый полный блок
229 0
		memCopy(buf, s->s, s->filled = count);
230
	}
231
}
232

233 1
void bashAESqueezeStop(void* state)
234
{
235 1
	bash_ae_st* s = (bash_ae_st*)state;
236 1
	ASSERT(memIsValid(s, bashAE_keep()));
237
	// чтобы считали, что был неполный блок
238 1
	s->filled = 0;
239
}
240

241 1
void bashAESqueeze(octet code, void* buf, size_t count, void* state)
242
{
243 1
	bashAESqueezeStart(code, state);
244 1
	bashAESqueezeStep(buf, count, state);
245 1
	bashAESqueezeStop(state);
246
}
247

248
/*
249
*******************************************************************************
250
Encr (Зашифрование)
251
*******************************************************************************
252
*/
253

254 1
void bashAEEncrStart(void* state)
255
{
256 1
	bash_ae_st* s = (bash_ae_st*)state;
257 1
	ASSERT(memIsValid(s, bashAE_keep()));
258
	// обработать отложенный блок
259 1
	bashAECtrlA(s, s->filled == s->block_len); /* полный? */
260 1
	bashAECtrlB(s, 0); /* заключительный */
261 1
	bashAECtrlC(s, s->code);
262 1
	bashAECtrlD(s, BASH_AE_TEXT);
263 1
	bashF(s->s, s->stack);
264 1
	s->filled = 0;
265
	// запомнить код
266 1
	s->code = BASH_AE_TEXT;
267
}
268

269 1
void bashAEEncrStep(void* buf, size_t count, void* state)
270
{
271 1
	bash_ae_st* s = (bash_ae_st*)state;
272 1
	ASSERT(memIsDisjoint2(buf, count, s, bashAE_keep()));
273
	// есть остаток в буфере?
274 1
	if (s->filled < s->block_len)
275
	{
276 1
		if (count <= s->block_len - s->filled)
277
		{
278 1
			memXor2(buf, s->s + s->filled, count);
279 1
			memXor2(s->s + s->filled, buf, count);
280 1
			s->filled += count;
281 1
			return;
282
		}
283 1
		memXor2(buf, s->s + s->filled, s->block_len - s->filled);
284 1
		memXor2(s->s + s->filled, buf, s->block_len - s->filled);
285 1
		buf = (octet*)buf + s->block_len - s->filled;
286 1
		count -= s->block_len - s->filled;
287 1
		s->filled = s->block_len;
288
	}
289
	// цикл по полным блокам
290 1
	while (count >= s->block_len)
291
	{
292
		// обработать отложенный блок
293 1
		bashAECtrlA(s, 1); /* полный */
294 1
		bashAECtrlB(s, 1); /* промежуточный */
295 1
		bashAECtrlC(s, s->code);
296 1
		bashAECtrlD(s, s->code);
297 1
		bashF(s->s, s->stack);
298
		// новый полный блок
299 1
		memXor2(buf, s->s, s->block_len);
300 1
		memXor2(s->s, buf, s->block_len);
301 1
		buf = (octet*)buf + s->block_len;
302 1
		count -= s->block_len;
303
	}
304
	// еще?
305 1
	if (count)
306
	{
307
		// обработать отложенный блок
308 1
		bashAECtrlA(s, 1); /* полный */
309 1
		bashAECtrlB(s, 1); /* промежуточный */
310 1
		bashAECtrlC(s, s->code);
311 1
		bashAECtrlD(s, s->code);
312 1
		bashF(s->s, s->stack);
313
		// новый полный блок
314 1
		memXor2(buf, s->s, count);
315 1
		memXor2(s->s, buf, s->filled = count);
316
	}
317
}
318

319 1
void bashAEEncrStop(void* state)
320
{
321 1
	bash_ae_st* s = (bash_ae_st*)state;
322 1
	ASSERT(memIsValid(s, bashAE_keep()));
323
	// подготовить отложенный блок к завершению текущей операции
324 1
	memSetZero(s->s + s->filled, s->block_len - s->filled);
325
	// можем попасть в октет управления, но это не важно
326 1
	s->s[s->filled] = 0x80;
327
}
328

329 1
void bashAEEncr(void* buf, size_t count, void* state)
330
{
331 1
	bashAEEncrStart(state);
332 1
	bashAEEncrStep(buf, count, state);
333 1
	bashAEEncrStop(state);
334
}
335

336
/*
337
*******************************************************************************
338
Decr (Расшифрование)
339
*******************************************************************************
340
*/
341

342 1
void bashAEDecrStart(void* state)
343
{
344 1
	bash_ae_st* s = (bash_ae_st*)state;
345 1
	ASSERT(memIsValid(s, bashAE_keep()));
346
	// обработать отложенный блок
347 1
	bashAECtrlA(s, s->filled == s->block_len); /* полный? */
348 1
	bashAECtrlB(s, 0); /* заключительный */
349 1
	bashAECtrlC(s, s->code);
350 1
	bashAECtrlD(s, BASH_AE_TEXT);
351 1
	bashF(s->s, s->stack);
352 1
	s->filled = 0;
353
	// запомнить код
354 1
	s->code = BASH_AE_TEXT;
355
}
356

357 1
void bashAEDecrStep(void* buf, size_t count, void* state)
358
{
359 1
	bash_ae_st* s = (bash_ae_st*)state;
360 1
	ASSERT(memIsDisjoint2(buf, count, s, bashAE_keep()));
361
	// есть остаток в буфере?
362 1
	if (s->filled < s->block_len)
363
	{
364 1
		if (count <= s->block_len - s->filled)
365
		{
366 1
			memXor2(buf, s->s + s->filled, count);
367 1
			memCopy(s->s + s->filled, buf, count);
368 1
			s->filled += count;
369 1
			return;
370
		}
371 1
		memXor2(buf, s->s + s->filled, s->block_len - s->filled);
372 1
		memCopy(s->s + s->filled, buf, s->block_len - s->filled);
373 1
		buf = (octet*)buf + s->block_len - s->filled;
374 1
		count -= s->block_len - s->filled;
375 1
		s->filled = s->block_len;
376
	}
377
	// цикл по полным блокам
378 1
	while (count >= s->block_len)
379
	{
380
		// обработать отложенный блок
381 1
		bashAECtrlA(s, 1); /* полный */
382 1
		bashAECtrlB(s, 1); /* промежуточный */
383 1
		bashAECtrlC(s, s->code);
384 1
		bashAECtrlD(s, s->code);
385 1
		bashF(s->s, s->stack);
386
		// новый полный блок
387 1
		memXor2(buf, s->s, s->block_len);
388 1
		memCopy(s->s, buf, s->block_len);
389 1
		buf = (octet*)buf + s->block_len;
390 1
		count -= s->block_len;
391
	}
392
	// еще?
393 1
	if (count)
394
	{
395
		// обработать отложенный блок
396 1
		bashAECtrlA(s, 1); /* полный */
397 1
		bashAECtrlB(s, 1); /* промежуточный */
398 1
		bashAECtrlC(s, s->code);
399 1
		bashAECtrlD(s, s->code);
400 1
		bashF(s->s, s->stack);
401
		// новый полный блок
402 1
		memXor2(buf, s->s, count);
403 1
		memCopy(s->s, buf, s->filled = count);
404
	}
405
}
406

407 1
void bashAEDecrStop(void* state)
408
{
409 1
	bash_ae_st* s = (bash_ae_st*)state;
410 1
	ASSERT(memIsValid(s, bashAE_keep()));
411
	// подготовить отложенный блок к завершению текущей операции
412 1
	memSetZero(s->s + s->filled, s->block_len - s->filled);
413
	// можем попасть в октет управления, но это не важно
414 1
	s->s[s->filled] = 0x80;
415
}
416

417 1
void bashAEDecr(void* buf, size_t count, void* state)
418
{
419 1
	bashAEDecrStart(state);
420 1
	bashAEDecrStep(buf, count, state);
421 1
	bashAEDecrStop(state);
422
}

Read our documentation on viewing source code .

Loading