agievich / bee2
1
/*
2
*******************************************************************************
3
\file brng.c
4
\brief STB 34.101.47 (brng): algorithms of pseudorandom number generation
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2013.01.31
8
\version 2018.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/core/word.h"
19
#include "bee2/crypto/belt.h"
20
#include "bee2/crypto/brng.h"
21

22
/*
23
*******************************************************************************
24
Ускорители: быстрые операции над блоками brng
25
*******************************************************************************
26
*/
27

28 1
static void brngBlockNeg(octet dest[32], const octet src[32])
29
{
30 1
	register size_t i = W_OF_O(32);
31 1
	while (i--)
32 1
		((word*)dest)[i] = ~((const word*)src)[i];
33
}
34

35 1
static void brngBlockXor2(octet dest[32], const octet src[32])
36
{
37 1
	register size_t i = W_OF_O(32);
38 1
	while (i--)
39 1
		((word*)dest)[i] ^= ((const word*)src)[i];
40
}
41

42 1
static void brngBlockInc(octet block[32])
43
{
44 1
	register size_t i = 0;
45 1
	word* w = (word*)block;
46
	do
47
	{
48
#if (OCTET_ORDER == BIG_ENDIAN)
49
		w[i] = wordRev(w[i]);
50
		++w[i];
51
		w[i] = wordRev(w[i]);
52
#else
53 1
		++w[i];
54
#endif
55
	}
56 1
	while (w[i] == 0 && i++ < W_OF_O(32));
57 1
	i = 0;
58
}
59

60
/*
61
*******************************************************************************
62
Генерация в режиме CTR
63

64
В brng_ctr_st::state_ex размещаются два beltHash-состояния:
65
-	вспомогательное состояние;
66
-	состояние beltHash(key ||....).
67
*******************************************************************************
68
*/
69
typedef struct
70
{
71
	octet s[32];		/*< переменная s */
72
	octet r[32];		/*< переменная r */
73
	octet block[32];	/*< блок выходных данных */
74
	size_t reserved;	/*< резерв выходных октетов */
75
	octet state_ex[];	/*< [2 beltHash_keep()] хэш-состояния */
76
} brng_ctr_st;
77

78 1
size_t brngCTR_keep()
79
{
80 1
	return sizeof(brng_ctr_st) + 2 * beltHash_keep();
81
}
82

83 1
void brngCTRStart(void* state, const octet key[32], const octet iv[32])
84
{
85 1
	brng_ctr_st* s = (brng_ctr_st*)state;
86 1
	ASSERT(memIsDisjoint2(s, brngCTR_keep(), key, 32));
87 1
	ASSERT(iv == 0 || memIsDisjoint2(s, brngCTR_keep(), iv, 32));
88
	// обработать key
89 1
	beltHashStart(s->state_ex + beltHash_keep());
90 1
	beltHashStepH(key, 32, s->state_ex + beltHash_keep());
91
	//	сохранить iv
92 1
	if (iv)
93 1
		memCopy(s->s, iv, 32);
94
	else
95 1
		memSetZero(s->s, 32);
96
	//	r <- ~s
97 1
	brngBlockNeg(s->r, s->s);
98
	// нет выходных данных
99 1
	s->reserved = 0;
100
}
101

102 1
void brngCTRStepR(void* buf, size_t count, void* state)
103
{
104 1
	brng_ctr_st* s = (brng_ctr_st*)state;
105 1
	ASSERT(memIsDisjoint2(buf, count, s, brngCTR_keep()));
106
	// есть резерв данных?
107 1
	if (s->reserved)
108
	{
109 1
		if (s->reserved >= count)
110
		{
111 0
			memCopy(buf, s->block + 32 - s->reserved, count);
112 0
			s->reserved -= count;
113 0
			return;
114
		}
115 1
		memCopy(buf, s->block + 32 - s->reserved, s->reserved);
116 1
		count -= s->reserved;
117 1
		buf = (octet*)buf + s->reserved;
118 1
		s->reserved = 0;
119
	}
120
	// цикл по полным блокам
121 1
	while (count >= 32)
122
	{
123
		// Y_t <- belt-hash(key || s || X_t || r)
124 1
		memCopy(s->state_ex, s->state_ex + beltHash_keep(), beltHash_keep());
125 1
		beltHashStepH(s->s, 32, s->state_ex);
126 1
		beltHashStepH(buf, 32, s->state_ex);
127 1
		beltHashStepH(s->r, 32, s->state_ex);
128 1
		beltHashStepG(buf, s->state_ex);
129
		// next
130 1
		brngBlockInc(s->s);
131 1
		brngBlockXor2(s->r, buf);
132 1
		buf = (octet*)buf + 32;
133 1
		count -= 32;
134
	}
135
	// неполный блок?
136 1
	if (count)
137
	{
138
		// block <- beltHash(key || s || zero_pad(X_t) || r)
139 1
		memSetZero(s->block + count, 32 - count);
140 1
		memCopy(s->state_ex, s->state_ex + beltHash_keep(), beltHash_keep());
141 1
		beltHashStepH(s->s, 32, s->state_ex);
142 1
		beltHashStepH(buf, count, s->state_ex);
143 1
		beltHashStepH(s->block + count, 32 - count, s->state_ex);
144 1
		beltHashStepH(s->r, 32, s->state_ex);
145 1
		beltHashStepG(s->block, s->state_ex);
146
		// Y_t <- left(block)
147 1
		memCopy(buf, s->block, count);
148
		// next
149 1
		brngBlockInc(s->s);
150 1
		brngBlockXor2(s->r, s->block);
151 1
		s->reserved = 32 - count;
152
	}
153
}
154

155 1
void brngCTRStepG(octet iv[32], void* state)
156
{
157 1
	brng_ctr_st* s = (brng_ctr_st*)state;
158 1
	ASSERT(memIsDisjoint2(s, brngCTR_keep(), iv, 32));
159 1
	memCopy(iv, s->s, 32);
160
}
161

162 1
err_t brngCTRRand(void* buf, size_t count, const octet key[32], octet iv[32])
163
{
164
	void* state;
165
	// проверить входные данные
166 1
	if (!memIsValid(key, 32) ||
167 1
		!memIsValid(iv, 32) ||
168 1
		!memIsValid(buf, count))
169 0
		return ERR_BAD_INPUT;
170
	// создать состояние
171 1
	state = blobCreate(brngCTR_keep());
172 1
	if (state == 0)
173 0
		return ERR_OUTOFMEMORY;
174
	// сгенерировать данные
175 1
	brngCTRStart(state, key, iv);
176 1
	brngCTRStepR(buf, count, state);
177 1
	brngCTRStepG(iv, state);
178
	// завершить
179 1
	blobClose(state);
180 1
	return ERR_OK;
181
}
182

183
/*
184
*******************************************************************************
185
Генерация в режиме HMAC
186

187
В brng_hmac_st::state_ex размещаются два beltHMAC-состояния:
188
-	вспомогательное состояние;
189
-	состояние beltHMAC(key, ...).
190

191
\remark Учитывается инкрементальность beltHMAC
192
*******************************************************************************
193
*/
194
typedef struct
195
{
196
	const octet* iv;			/*< указатель на синхропосылку */
197
	octet iv_buf[64];			/*< синхропосылка (если укладывается) */
198
	size_t iv_len;				/*< длина синхропосылки в октетах */
199
	octet r[32];				/*< переменная r */
200
	octet block[32];			/*< блок выходных данных */
201
	size_t reserved;			/*< резерв выходных октетов */
202
	octet state_ex[];			/*< [2 * beltHMAC_keep()] hmac-состояния */
203
} brng_hmac_st;
204

205 1
size_t brngHMAC_keep()
206
{
207 1
	return sizeof(brng_hmac_st) + 2 * beltHMAC_keep();
208
}
209

210 1
void brngHMACStart(void* state, const octet key[], size_t key_len, 
211
	const octet iv[], size_t iv_len)
212
{
213 1
	brng_hmac_st* s = (brng_hmac_st*)state;
214 1
	ASSERT(memIsDisjoint2(s, brngHMAC_keep(), key, key_len));
215 1
	ASSERT(memIsDisjoint2(s, brngHMAC_keep(), iv, iv_len));
216
	// запомнить iv
217 1
	if ((s->iv_len = iv_len) <= 64) 
218
	{
219 1
		memCopy(s->iv_buf, iv, iv_len);
220 1
		s->iv = s->iv_buf;
221
	}
222
	else
223 1
		s->iv = iv;
224
	// обработать key
225 1
	beltHMACStart(s->state_ex + beltHMAC_keep(), key, key_len);
226
	// r <- beltHMAC(key, iv)
227 1
	memCopy(s->state_ex, s->state_ex + beltHMAC_keep(), beltHMAC_keep());
228 1
	beltHMACStepA(iv, iv_len, s->state_ex);
229 1
	beltHMACStepG(s->r, s->state_ex);
230
	// нет выходных данных
231 1
	s->reserved = 0;
232
}
233

234 1
void brngHMACStepR(void* buf, size_t count, void* state)
235
{
236 1
	brng_hmac_st* s = (brng_hmac_st*)state;
237 1
	ASSERT(memIsDisjoint2(buf, count, s, brngHMAC_keep()));
238
	// есть резерв данных?
239 1
	if (s->reserved)
240
	{
241 1
		if (s->reserved >= count)
242
		{
243 1
			memCopy(buf, s->block + 32 - s->reserved, count);
244 1
			s->reserved -= count;
245 1
			return;
246
		}
247 0
		memCopy(buf, s->block + 32 - s->reserved, s->reserved);
248 0
		count -= s->reserved;
249 0
		buf = (octet*)buf + s->reserved;
250 0
		s->reserved = 0;
251
	}
252
	// цикл по полным блокам
253 1
	while (count >= 32)
254
	{
255
		// r <- beltHMAC(key, r) 
256 1
		memCopy(s->state_ex, s->state_ex + beltHMAC_keep(), beltHMAC_keep());
257 1
		beltHMACStepA(s->r, 32, s->state_ex);
258 1
		beltHMACStepG(s->r, s->state_ex);
259
		// Y_t <- beltHMAC(key, r || iv)
260 1
		beltHMACStepA(s->iv, s->iv_len, s->state_ex);
261 1
		beltHMACStepG(buf, s->state_ex);
262
		// next
263 1
		buf = (octet*)buf + 32;
264 1
		count -= 32;
265
	}
266
	// неполный блок?
267 1
	if (count)
268
	{
269
		// r <- beltHMAC(key, r) 
270 1
		memCopy(s->state_ex, s->state_ex + beltHMAC_keep(), beltHMAC_keep());
271 1
		beltHMACStepA(s->r, 32, s->state_ex);
272 1
		beltHMACStepG(s->r, s->state_ex);
273
		// Y_t <- left(beltHMAC(key, r || iv))
274 1
		beltHMACStepA(s->iv, s->iv_len, s->state_ex);
275 1
		beltHMACStepG(s->block, s->state_ex);
276 1
		memCopy(buf, s->block, count);
277
		// next
278 1
		s->reserved = 32 - count;
279
	}
280
}
281

282 1
err_t brngHMACRand(void* buf, size_t count, const octet key[], size_t key_len,
283
	const octet iv[], size_t iv_len)
284
{
285
	void* state;
286
	// проверить входные данные
287 1
	if (!memIsValid(key, key_len) ||
288 1
		!memIsValid(iv, iv_len) ||
289 1
		!memIsValid(buf, count) ||
290 1
		!memIsDisjoint2(buf, count, iv, iv_len))
291 0
		return ERR_BAD_INPUT;
292
	// создать состояние
293 1
	state = blobCreate(brngHMAC_keep());
294 1
	if (state == 0)
295 0
		return ERR_OUTOFMEMORY;
296
	// сгенерировать данные
297 1
	brngHMACStart(state, key, key_len, iv, iv_len);
298 1
	brngHMACStepR(buf, count, state);
299
	// завершить
300 1
	blobClose(state);
301 1
	return ERR_OK;
302
}

Read our documentation on viewing source code .

Loading