1
/*
2
*******************************************************************************
3
\file bash_prg.c
4
\brief STB 34.101.77 (bash): programmable algorithms
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2018.10.30
8
\version 2020.06.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/mem.h"
16
#include "bee2/core/util.h"
17
#include "bee2/crypto/bash.h"
18

19
/*
20
*******************************************************************************
21
Программируемые алгоритмы
22

23
\remark В bash_prg_st::s хранится состояние автомата. Состояние как строка 
24
октетов состоит из двух частей:
25
1) буфер (первые buf_len октетов);
26
2) память (все остальное).
27

28
Данные загружаются в буфер и выгружаются из буфера блоками по buf_len октетов.
29

30
В бесключевом режиме память содержит 2dl битов, в ключевом -- (l + dl/2) битов.
31
Эти факты используются в функции bashPrgIsKeymode() для проверки того, что
32
автомат находится в ключевом режиме.
33

34
Первый бит памяти является контрольным -- он инвертируется в bashPrgCommit().
35

36
Длина buf_len в зависимости от параметров и режима:
37

38
 l  | d | key | keyless
39
-----------------------
40
128 | 1 | 168 | 160
41
128 | 2 | 160 | 128
42
192 | 1 | 156 | 144
43
192 | 2 | 144 |  96 
44
256 | 1 | 144 | 128
45
256 | 2 | 128 |  64
46

47
6-битовые коды NULL, KEY, DATA, TEXT, OUT дополнены (справа) парой битов 01
48
и объявлены как BASH_PRG_XXX.
49
*******************************************************************************
50
*/
51

52
#define BASH_PRG_NULL		0x01	/* 000000 01 */
53
#define BASH_PRG_KEY		0x05	/* 000001 01 */
54
#define BASH_PRG_DATA		0x09	/* 000010 01 */
55
#define BASH_PRG_TEXT		0x0D	/* 000011 01 */
56
#define BASH_PRG_OUT		0x11	/* 000100 01 */
57

58
typedef struct {
59
	size_t l;			/*< уровень стойкости */
60
	size_t d;			/*< емкость */
61
	octet s[192];		/*< состояние */
62
	size_t buf_len;		/*< длина буфера */
63
	size_t pos;			/*< позиция в буфере */
64
	octet t[192];		/*< копия состояния (для ratchet) */
65
	octet stack[];		/*< [bashF_deep()] стек bashF */
66
} bash_prg_st;
67

68 1
size_t bashPrg_keep()
69
{
70 1
	return sizeof(bash_prg_st) + bashF_deep();
71
}
72

73
/*
74
*******************************************************************************
75
Вспомогательные функции
76
*******************************************************************************
77
*/
78

79 1
static bool_t bashPrgIsKeymode(const void* state)
80
{
81 1
	const bash_prg_st* st = (const bash_prg_st*)state;
82 1
	ASSERT(memIsValid(st, bashPrg_keep()));
83
	// (192 - buf_len) ==? (l + d * l / 2) / 8
84 1
	return 16 * (192 - st->buf_len) == st->l * (2 + st->d);
85
}
86

87
/*
88
*******************************************************************************
89
Commit: завершить предыдущую команду и начать новую с кодом code
90
*******************************************************************************
91
*/
92

93 1
static void bashPrgCommit(octet code, void* state)
94
{
95 1
	bash_prg_st* st = (bash_prg_st*)state;
96 1
	ASSERT(memIsValid(st, bashPrg_keep()));
97 1
	ASSERT(st->pos < st->buf_len);
98
	// учесть code
99 1
	st->s[st->pos] ^= code;
100
	// инвертировать контрольный бит
101 1
	st->s[st->buf_len] ^= 0x80;
102
	// применить sponge-функцию
103 1
	bashF(st->s, st->stack);
104
	// сбросить pos
105 1
	st->pos = 0;
106
}
107

108
/*
109
*******************************************************************************
110
Start: инициализировать
111
*******************************************************************************
112
*/
113

114 1
void bashPrgStart(void* state, size_t l, size_t d, const octet ann[],
115
	size_t ann_len, const octet key[], size_t key_len)
116
{
117 1
	bash_prg_st* st = (bash_prg_st*)state;
118 1
	ASSERT(memIsValid(st, bashPrg_keep()));
119 1
	ASSERT(l == 128 || l == 192 || l == 256);
120 1
	ASSERT(d == 1 || d == 2);
121 1
	ASSERT(ann_len % 4 == 0 && ann_len <= 60);
122 1
	ASSERT(key_len % 4 == 0 && key_len <= 60);
123 1
	ASSERT(key_len == 0 || key_len >= l / 8);
124 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), ann, ann_len));
125 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), key, key_len));
126
	// pos <- 8 + |ann| + |key|
127 1
	st->pos = 1 + ann_len + key_len;
128
	// s[0..pos) <- <|ann|/2 + |key|/32>_8 || ann || key
129 1
	st->s[0] = (octet)(ann_len * 4 + key_len / 4);
130 1
	memCopy(st->s + 1, ann, ann_len); 
131 1
	memCopy(st->s + 1 + ann_len, key, key_len);
132
	// s[pos..) <- 0
133 1
	memSetZero(st->s + st->pos, 192 - st->pos);
134
	// s[1472..) <- <l / 4 + d>_{64}
135 1
	st->s[192 - 8] = (octet)(l / 4  + d);
136
	// длина буфера
137 1
	st->buf_len = key_len ? (192 - l * (2 + d) / 16) : (192 - d * l / 4);
138
	// сохранить параметры
139 1
	st->l = l, st->d = d;
140
}
141

142
/*
143
*******************************************************************************
144
Restart: повторно инициализировать
145
*******************************************************************************
146
*/
147

148 1
void bashPrgRestart(const octet ann[], size_t ann_len, 
149
	const octet key[], size_t key_len, void* state)
150
{
151 1
	bash_prg_st* st = (bash_prg_st*)state;
152 1
	ASSERT(memIsValid(st, bashPrg_keep()));
153 1
	ASSERT(ann_len % 4 == 0 && ann_len <= 60);
154 1
	ASSERT(key_len % 4 == 0 && key_len <= 60);
155 1
	ASSERT(key_len == 0 || key_len >= st->l / 8);
156 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), ann, ann_len));
157 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), key, key_len));
158
	// вводится ключ?
159 1
	if (key_len)
160
	{
161 0
		bashPrgCommit(BASH_PRG_KEY, state);
162
		// перейти в ключевой режим (если еще не в нем)
163 0
		st->buf_len = 192 - st->l * (2 + st->d) / 16;
164
	}
165
	else
166 1
		bashPrgCommit(BASH_PRG_NULL, state);
167
	// pos <- 8 + |ann| + |key|
168 1
	st->pos = 1 + ann_len + key_len;
169
	// s[0..pos) <- s[0..pos) ^ <|ann|/2 + |key|/32>_8  || ann || key
170 1
	st->s[0] ^= (octet)(ann_len * 4 + key_len / 4);
171 1
	memXor2(st->s + 1, ann, ann_len); 
172 1
	memXor2(st->s + 1 + ann_len, key, key_len);
173
}
174

175
/*
176
*******************************************************************************
177
Absorb: загрузить
178
*******************************************************************************
179
*/
180

181 1
void bashPrgAbsorbStart(void* state)
182
{
183 1
	bashPrgCommit(BASH_PRG_DATA, state);
184
}
185

186 1
void bashPrgAbsorbStep(const void* buf, size_t count, void* state)
187
{
188 1
	bash_prg_st* st = (bash_prg_st*)state;
189 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), buf, count));
190
	// не накопился полный буфер?
191 1
	if (count < st->buf_len - st->pos)
192
	{
193 1
		memXor2(st->s + st->pos, buf, count);
194 1
		st->pos += count;
195 1
		return;
196
	}
197
	// новый полный буфер
198 1
	memXor2(st->s + st->pos, buf, st->buf_len - st->pos);
199 1
	buf = (const octet*)buf + st->buf_len - st->pos;
200 1
	count -= st->buf_len - st->pos;
201 1
	bashF(st->s, st->stack);
202
	// цикл по полным блокам
203 1
	while (count >= st->buf_len)
204
	{
205 1
		memXor2(st->s, buf, st->buf_len);
206 1
		buf = (const octet*)buf + st->buf_len;
207 1
		count -= st->buf_len;
208 1
		bashF(st->s, st->stack);
209
	}
210
	// неполный блок?
211 1
	if (st->pos = count)
212 1
		memXor2(st->s, buf, count);
213
}
214

215 1
void bashPrgAbsorb(const void* buf, size_t count, void* state)
216
{
217 1
	bashPrgAbsorbStart(state);
218 1
	bashPrgAbsorbStep(buf, count, state);
219
}
220

221
/*
222
*******************************************************************************
223
Squeeze: выгрузить
224
*******************************************************************************
225
*/
226

227 1
void bashPrgSqueezeStart(void* state)
228
{
229 1
	bashPrgCommit(BASH_PRG_OUT, state);
230
}
231

232 1
void bashPrgSqueezeStep(void* buf, size_t count, void* state)
233
{
234 1
	bash_prg_st* st = (bash_prg_st*)state;
235 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), buf, count));
236
	// остатка буфера достаточно?
237 1
	if (count < st->buf_len - st->pos)
238
	{
239 1
		memCopy(buf, st->s + st->pos, count);
240 1
		st->pos += count;
241 1
		return;
242
	}
243
	// новый буфер
244 1
	memCopy(buf, st->s + st->pos, st->buf_len - st->pos);
245 1
	buf = (octet*)buf + st->buf_len - st->pos;
246 1
	count -= st->buf_len - st->pos;
247 1
	bashF(st->s, st->stack);
248
	// цикл по полным блокам
249 1
	while (count >= st->buf_len)
250
	{
251 0
		memCopy(buf, st->s, st->buf_len);
252 0
		buf = (octet*)buf + st->buf_len;
253 0
		count -= st->buf_len;
254 0
		bashF(st->s, st->stack);
255
	}
256
	// неполный блок
257 1
	if (st->pos = count)
258 0
		memCopy(buf, st->s, count);
259
}
260

261 1
void bashPrgSqueeze(void* buf, size_t count, void* state)
262
{
263 1
	bashPrgSqueezeStart(state);
264 1
	bashPrgSqueezeStep(buf, count, state);
265
}
266

267
/*
268
*******************************************************************************
269
Encr: зашифровать
270
*******************************************************************************
271
*/
272

273 1
void bashPrgEncrStart(void* state)
274
{
275 1
	ASSERT(bashPrgIsKeymode(state));
276 1
	bashPrgCommit(BASH_PRG_TEXT, state);
277
}
278

279 1
void bashPrgEncrStep(void* buf, size_t count, void* state)
280
{
281 1
	bash_prg_st* st = (bash_prg_st*)state;
282 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), buf, count));
283
	// остатка буфера достаточно?
284 1
	if (count < st->buf_len - st->pos)
285
	{
286 1
		memXor2(st->s + st->pos, buf, count);
287 1
		memCopy(buf, st->s + st->pos, count);
288 1
		st->pos += count;
289 1
		return;
290
	}
291
	// новый буфер
292 1
	memXor2(st->s + st->pos, buf, st->buf_len - st->pos);
293 1
	memCopy(buf, st->s + st->pos, st->buf_len - st->pos);
294 1
	buf = (octet*)buf + st->buf_len - st->pos;
295 1
	count -= st->buf_len - st->pos;
296 1
	bashF(st->s, st->stack);
297
	// цикл по полным блокам
298 1
	while (count >= st->buf_len)
299
	{
300 1
		memXor2(st->s, buf, st->buf_len);
301 1
		memCopy(buf, st->s, st->buf_len);
302 1
		buf = (octet*)buf + st->buf_len;
303 1
		count -= st->buf_len;
304 1
		bashF(st->s, st->stack);
305
	}
306
	// неполный блок
307 1
	if (st->pos = count)
308
	{
309 1
		memXor2(st->s, buf, count);
310 1
		memCopy(buf, st->s, count);
311
	}
312
}
313

314 1
void bashPrgEncr(void* buf, size_t count, void* state)
315
{
316 1
	bashPrgEncrStart(state);
317 1
	bashPrgEncrStep(buf, count, state);
318
}
319

320
/*
321
*******************************************************************************
322
Decr: расшифровать
323
*******************************************************************************
324
*/
325

326 1
void bashPrgDecrStart(void* state)
327
{
328 1
	ASSERT(bashPrgIsKeymode(state));
329 1
	bashPrgCommit(BASH_PRG_TEXT, state);
330
}
331

332 1
void bashPrgDecrStep(void* buf, size_t count, void* state)
333
{
334 1
	bash_prg_st* st = (bash_prg_st*)state;
335 1
	ASSERT(memIsDisjoint2(st, bashPrg_keep(), buf, count));
336
	// остатка буфера достаточно?
337 1
	if (count < st->buf_len - st->pos)
338
	{
339 1
		memXor2(buf, st->s + st->pos, count);
340 1
		memXor2(st->s + st->pos, buf, count);
341 1
		st->pos += count;
342 1
		return;
343
	}
344
	// новый буфер
345 1
	memXor2(buf, st->s + st->pos, st->buf_len - st->pos);
346 1
	memXor2(st->s + st->pos, buf, st->buf_len - st->pos);
347 1
	buf = (octet*)buf + st->buf_len - st->pos;
348 1
	count -= st->buf_len - st->pos;
349 1
	bashF(st->s, st->stack);
350
	// цикл по полным блокам
351 1
	while (count >= st->buf_len)
352
	{
353 1
		memXor2(buf, st->s, st->buf_len);
354 1
		memXor2(st->s, buf, st->buf_len);
355 1
		buf = (octet*)buf + st->buf_len;
356 1
		count -= st->buf_len;
357 1
		bashF(st->s, st->stack);
358
	}
359
	// неполный блок
360 1
	if (st->pos = count)
361
	{
362 1
		memXor2(buf, st->s, count);
363 1
		memXor2(st->s, buf, count);
364
	}
365
}
366

367 1
void bashPrgDecr(void* buf, size_t count, void* state)
368
{
369 1
	bashPrgDecrStart(state);
370 1
	bashPrgDecrStep(buf, count, state);
371
}
372

373
/*
374
*******************************************************************************
375
Ratchet: необратимо изменить
376
*******************************************************************************
377
*/
378

379 1
void bashPrgRatchet(void* state)
380
{
381 1
	bash_prg_st* st = (bash_prg_st*)state;
382 1
	ASSERT(memIsValid(st, bashPrg_keep()));
383
	// завершить предыдущую команду
384 1
	bashPrgCommit(BASH_PRG_NULL, state);
385
	// необратимо изменить
386 1
	memCopy(st->t, st->s, 192);
387 1
	bashF(st->s, st->stack);
388 1
	memXor2(st->s, st->t, 192);
389
}

Read our documentation on viewing source code .

Loading