agievich / bee2
1
/*
2
*******************************************************************************
3
\file bake.c
4
\brief STB 34.101.66 (bake): key establishment protocols
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2014.04.14
8
\version 2017.11.03
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/obj.h"
18
#include "bee2/core/util.h"
19
#include "bee2/crypto/bake.h"
20
#include "bee2/crypto/belt.h"
21
#include "crypto/bign_lcl.h"
22
#include "bee2/math/gfp.h"
23
#include "bee2/math/ecp.h"
24
#include "bee2/math/ww.h"
25
#include "bee2/math/zz.h"
26

27
/*
28
*******************************************************************************
29
\todo Контроль последовательности выполнения шагов протоколов?
30
*******************************************************************************
31
*/
32

33
/*
34
*******************************************************************************
35
Алгоритм bakeKDF
36
*******************************************************************************
37
*/
38

39 1
err_t bakeKDF(octet key[32], const octet secret[], size_t secret_len, 
40
	const octet iv[], size_t iv_len, size_t num)
41
{
42
	void* state;
43
	octet* block;
44
	// проверить входные данные
45 1
	if (!memIsValid(secret, secret_len) ||
46 1
		!memIsValid(iv, iv_len) ||
47 1
		!memIsValid(key, 32))
48 0
		return ERR_BAD_INPUT;
49
	// создать состояние
50 1
	state = blobCreate(utilMax(2, beltHash_keep(), beltKRP_keep() + 16));
51 1
	if (state == 0)
52 0
		return ERR_OUTOFMEMORY;
53 1
	block = (octet*)state + beltKRP_keep();
54
	// key <- beltHash(secret || iv)
55 1
	beltHashStart(state);
56 1
	beltHashStepH(secret, secret_len, state);
57 1
	beltHashStepH(iv, iv_len, state);
58 1
	beltHashStepG(key, state);
59
	// key <- beltKRP(Y, 1^96, num)
60 1
	memSet(block, 0xFF, 12);
61 1
	beltKRPStart(state, key, 32, block);
62
	CASSERT(B_PER_S <= 128);
63 1
	memCopy(block, &num, sizeof(size_t));
64
#if (OCTET_ORDER == BIG_ENDIAN)
65
	memRev(block, sizeof(size_t));
66
#endif
67 1
	memSetZero(block + sizeof(size_t), 16 - sizeof(size_t));
68 1
	beltKRPStepG(key, 32, block, state);
69
	// завершить
70 1
	blobClose(state);
71 1
	return ERR_OK;
72
}
73

74
/*
75
*******************************************************************************
76
Алгоритм bakeSWU
77
*******************************************************************************
78
*/
79

80 1
static void bakeSWU2(word W[], const ec_o* ec, const octet X[], void* stack)
81
{
82
	octet* H;	/* [no + 16] */
83
	word* s;	/* [n + W_OF_O(16)] (совпадает с H) */
84
	// pre
85 1
	ASSERT(ecIsOperable(ec));
86 1
	ASSERT(memIsValid(X, ec->f->no));
87 1
	ASSERT(wwIsValid(W, 2 * ec->f->n));
88
	// раскладка stack
89 1
	H = (octet*)stack;
90 1
	s = (word*)stack;
91 1
	stack = H + ec->f->no + 16;
92
	// H <- beltWBL(X, 0, 0)
93 1
	memSetZero(H + ec->f->no, 16);
94 1
	beltWBLStart(stack, H + ec->f->no, 16);
95 1
	memCopy(H, X, ec->f->no);
96 1
	beltWBLStepE(H, ec->f->no + 16, stack);
97
	// s <- \bar H mod p
98 1
	wwFrom(s, H, ec->f->no + 16);
99 1
	zzMod(s, s, ec->f->n + W_OF_O(16), ec->f->mod, ec->f->n, stack);
100
	// W <- ecpSWU(s)
101 1
	wwTo(H, ec->f->no, s);
102 1
	qrFrom(s, H, ec->f, stack);
103 1
	ecpSWU(W, s, ec, stack);
104
}
105

106 1
static size_t bakeSWU2_deep(size_t n, size_t f_deep, size_t ec_d,
107
	size_t ec_deep)
108
{
109 1
	return O_OF_W(n) + 16 +
110 1
		utilMax(3,
111
			zzMod_deep(n + W_OF_O(16), n),
112
			f_deep,
113
			ecpSWU_deep(n, f_deep));
114
}
115

116 1
err_t bakeSWU(octet pt[], const bign_params* params, const octet msg[])
117
{
118
	err_t code;
119
	void* state;
120
	word* W;
121
	// проверить входные данные
122 1
	if (!memIsValid(params, sizeof(bign_params)))
123 0
		return ERR_BAD_INPUT;
124 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
125 0
		return ERR_BAD_PARAMS;
126 1
	if (!memIsValid(msg, params->l / 4) ||
127 1
		!memIsValid(pt, params->l / 2))
128 0
		return ERR_BAD_INPUT;
129
	// создать состояние
130 1
	state = blobCreate(bignStart_keep(params->l, bakeSWU2_deep));
131 1
	if (state == 0)
132 0
		return ERR_OUTOFMEMORY;
133
	// старт
134 1
	code = bignStart(state, params);
135 1
	ERR_CALL_HANDLE(code, blobClose(state));
136
	// основные действия
137 1
	W = (word*)pt;
138 1
	bakeSWU2(W, (const ec_o*)state, msg, objEnd(state, void));
139 1
	wwTo(pt, params->l / 2, W);
140
	// завершение
141 1
	blobClose(state);
142 1
	return ERR_OK;
143
}
144

145
/*
146
*******************************************************************************
147
Шаги протокола BMQV
148

149
\todo Оптимизировать вычисление s(V - (2^l + t)Q):
150
	--	вычислить проективную кратную точку (2^l + t)Q и вычесть из нее 
151
		аффинную (пока нет функции вычисления проективной кратной точки);
152
	--	находить сумму кратных точек sV + (- s(2^l + t))Q (ecAddMulAA).
153
[В последнем случае теряется малость t].
154
*******************************************************************************
155
*/
156

157
typedef struct
158
{
159
	obj_hdr_t hdr;				/*< заголовок */
160
// ptr_table {
161
	ec_o* ec;					/*< описание эллиптической кривой */
162
	word* d;					/*< [ec->f->n] долговременный личный ключ */
163
	word* u;					/*< [ec->f->n] одноразовый личный ключ */
164
	octet* Vb;					/*< [ec->f->no] ecX(Vb) */
165
// }
166
	bign_params params[1];		/*< параметры */
167
	bake_settings settings[1];	/*< настройки */
168
	bake_cert cert[1];			/*< сертификат */
169
	octet K0[32];				/*< ключ K0 */
170
	octet K1[32];				/*< ключ K1 */
171
	octet data[];				/*< данные */
172
} bake_bmqv_o;
173

174
static size_t bakeBMQV_deep(size_t n, size_t f_deep, size_t ec_d, size_t ec_deep);
175

176 1
size_t bakeBMQV_keep(size_t l)
177
{
178 1
	const size_t n = W_OF_B(2 * l);
179 1
	const size_t no = O_OF_B(2 * l);
180 1
	return sizeof(bake_bmqv_o) +
181 1
		bignStart_keep(l, bakeBMQV_deep) +
182 1
		O_OF_W(2 * n) + no;
183
}
184

185 1
err_t bakeBMQVStart(void* state, const bign_params* params,
186
	const bake_settings* settings, const octet privkey[],
187
	const bake_cert* cert)
188
{
189
	err_t code;
190 1
	bake_bmqv_o* s = (bake_bmqv_o*)state;
191
	size_t n, no;
192
	// стек
193
	word* Q;
194
	void* stack;
195
	// проверить входные данные
196 1
	if (!memIsValid(params, sizeof(bign_params)) ||
197 1
		!memIsValid(settings, sizeof(bake_settings)) ||
198 1
		!memIsNullOrValid(settings->helloa, settings->helloa_len) ||
199 1
		!memIsNullOrValid(settings->hellob, settings->hellob_len))
200 0
		return ERR_BAD_INPUT;
201 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
202 0
		return ERR_BAD_PARAMS;
203 1
	if (settings->rng == 0)
204 0
		return ERR_BAD_RNG;
205 1
	if (!memIsValid(privkey, params->l / 4) ||
206 1
		!memIsValid(cert, sizeof(bake_cert)) ||
207 1
		!memIsValid(cert->data, cert->len) ||
208 1
		cert->val == 0)
209 0
		return ERR_BAD_INPUT;
210
	// загрузить параметры
211 1
	code = bignStart(s->data, params);
212 1
	ERR_CALL_CHECK(code);
213 1
	s->ec = (ec_o*)s->data;
214 1
	n = s->ec->f->n, no = s->ec->f->no;
215
	// сохранить параметры
216 1
	memCopy(s->params, params, sizeof(bign_params));
217
	// сохранить настройки
218 1
	memCopy(s->settings, settings, sizeof(bake_settings));
219
	// настроить указатели
220 1
	s->d = objEnd(s->ec, word);
221 1
	s->u = s->d + n;
222 1
	s->Vb = (octet*)(s->u + n);
223
	// настроить заголовок
224 1
	s->hdr.keep = sizeof(bake_bmqv_o) + objKeep(s->ec) + O_OF_W(2 * n) + no;
225 1
	s->hdr.p_count = 4;
226 1
	s->hdr.o_count = 1;
227
	// загрузить личный ключ
228 1
	wwFrom(s->d, privkey, no);
229
	// раскладка стека
230 1
	Q = objEnd(s, word);
231 1
	stack = Q + 2 * n;
232
	// проверить сертификат и его открытый ключ
233 1
	code = cert->val((octet*)Q, params, cert->data, cert->len);
234 1
	ERR_CALL_CHECK(code);
235 1
	if (!qrFrom(ecX(Q), (octet*)Q, s->ec->f, stack) ||
236 1
		!qrFrom(ecY(Q, n), (octet*)Q + no, s->ec->f, stack) ||
237 1
		!ecpIsOnA(Q, s->ec, stack))
238 0
		return ERR_BAD_CERT;
239
	// сохранить сертификат
240 1
	memCopy(s->cert, cert, sizeof(bake_cert));
241
	// все нормально
242 1
	return code;
243
}
244

245 1
static size_t bakeBMQVStart_deep(size_t n, size_t f_deep, size_t ec_d,
246
	size_t ec_deep)
247
{
248 1
	return O_OF_W(2 * n) +
249 1
		utilMax(2,
250
			f_deep,
251
			ecpIsOnA_deep(n, f_deep));
252
}
253

254 1
err_t bakeBMQVStep2(octet out[], void* state)
255
{
256 1
	bake_bmqv_o* s = (bake_bmqv_o*)state;
257
	size_t n, no;
258
	// стек
259
	word* Vb;		/* [2 * n] */
260
	void* stack;
261
	// обработать входные данные
262 1
	if (!objIsOperable(s))
263 0
		return ERR_BAD_INPUT;
264 1
	n = s->ec->f->n, no = s->ec->f->no;
265 1
	if (!memIsValid(out, 2 * no))
266 0
		return ERR_BAD_INPUT;
267 1
	ASSERT(memIsDisjoint2(out, 2 * no, s, objKeep(s)));
268
	// раскладка стека
269 1
	Vb = objEnd(s, word);
270 1
	stack = Vb + 2 * n;
271
	// ub <-R {1, 2, ..., q - 1}
272 1
	if (!zzRandNZMod(s->u, s->ec->order, n, s->settings->rng,
273
		s->settings->rng_state))
274 0
		return ERR_BAD_RNG;
275
	// Vb <- ub G
276 1
	if (!ecMulA(Vb, s->ec->base, s->ec, s->u, n, stack))
277 0
		return ERR_BAD_PARAMS;
278
	// out <- <Vb>
279 1
	qrTo(out, ecX(Vb), s->ec->f, stack);
280 1
	qrTo(out + no, ecY(Vb, n), s->ec->f, stack);
281
	// сохранить ecX(Vb)
282 1
	memCopy(s->Vb, out, no);
283
	// все нормально
284 1
	return ERR_OK;
285
}
286

287 1
static size_t bakeBMQVStep2_deep(size_t n, size_t f_deep, size_t ec_d,
288
	size_t ec_deep)
289
{
290 1
	return O_OF_W(2 * n) +
291 1
		utilMax(2,
292
			f_deep,
293
			ecMulA_deep(n, ec_d, ec_deep, n));
294
}
295

296 1
err_t bakeBMQVStep3(octet out[], const octet in[], const bake_cert* certb,
297
	void* state)
298
{
299
	err_t code;
300 1
	bake_bmqv_o* s = (bake_bmqv_o*)state;
301
	size_t n, no;
302
	// стек
303
	word* Qb;			/* [2 * n] */
304
	word* Va;			/* [2 * n] */
305
	word* Vb;			/* [2 * n] */
306
	word* t;			/* [n / 2 + 1] */
307
	word* sa;			/* [n + n / 2 + 1] */
308
	octet* K;			/* [no] (совпадает с Qb) */
309
	octet* block0;		/* [16] (совпадает с t) */
310
	octet* block1;		/* [16] (следует за block0) */
311
	void* stack;
312
	// проверить входные данные
313 1
	if (!objIsOperable(s))
314 0
		return ERR_BAD_INPUT;
315 1
	n = s->ec->f->n, no = s->ec->f->no;
316 1
	if (!memIsValid(in, 2 * no) ||
317 1
		!memIsValid(out, 2 * no + (s->settings->kca ? 8u : 0)) ||
318 1
		!memIsValid(certb, sizeof(bake_cert)) ||
319 1
		!memIsValid(certb->data, certb->len) ||
320 1
		certb->val == 0)
321 0
		return ERR_BAD_INPUT;
322 1
	ASSERT(memIsDisjoint2(out, 2 * no + (s->settings->kca ? 8u : 0),
323
		s, objKeep(s)));
324
	// раскладка стека
325 1
	Qb = objEnd(s, word);
326 1
	Va = Qb + 2 * n;
327 1
	Vb = Va + 2 * n;
328 1
	t = Vb + 2 * n;
329 1
	sa = t + n / 2 + 1;
330 1
	stack = sa + n + n / 2 + 1;
331 1
	K = (octet*)Qb;
332 1
	block0 = (octet*)t;
333 1
	block1 = block0 + 16;
334 1
	ASSERT(block1 + 16 <= (octet*)stack);
335
	// проверить certb
336 1
	code = certb->val((octet*)Qb, s->params, certb->data, certb->len);
337 1
	ERR_CALL_CHECK(code);
338 1
	if (!qrFrom(ecX(Qb), (octet*)Qb, s->ec->f, stack) ||
339 1
		!qrFrom(ecY(Qb, n), (octet*)Qb + no, s->ec->f, stack) ||
340 1
		!ecpIsOnA(Qb, s->ec, stack))
341 0
		return ERR_BAD_CERT;
342
	// Vb <- in, Vb \in E*?
343 1
	if (!qrFrom(ecX(Vb), in, s->ec->f, stack) ||
344 1
		!qrFrom(ecY(Vb, n), in + no, s->ec->f, stack) ||
345 1
		!ecpIsOnA(Vb, s->ec, stack))
346 0
		return ERR_BAD_POINT;
347
	// ua <-R {1, 2, ..., q - 1}
348 1
	if (!zzRandNZMod(s->u, s->ec->order, n, s->settings->rng,
349
		s->settings->rng_state))
350 0
		return ERR_BAD_RNG;
351
	// Va <- ua G
352 1
	if (!ecMulA(Va, s->ec->base, s->ec, s->u, n, stack))
353 0
		return ERR_BAD_PARAMS;
354 1
	qrTo((octet*)Va, ecX(Va), s->ec->f, stack);
355 1
	qrTo((octet*)Va + no, ecY(Va, n), s->ec->f, stack);
356
	// t <- <beltHash(<Va>_2l || <Vb>_2l)>_l
357 1
	beltHashStart(stack);
358 1
	beltHashStepH(Va, no, stack);
359 1
	beltHashStepH(in, no, stack);
360 1
	beltHashStepG2((octet*)t, no / 2, stack);
361 1
	wwFrom(t, t, no / 2);
362
	// out <- <Va>_4l
363 1
	memCopy(out, Va, 2 * no);
364
	// sa <- (ua - (2^l + t)da) \mod q
365 1
	zzMul(sa, t, n / 2, s->d, n, stack);
366 1
	sa[n + n / 2] = zzAdd2(sa + n / 2, s->d, n);
367 1
	zzMod(sa, sa, n + n / 2 + 1, s->ec->order, n, stack);
368 1
	zzSubMod(sa, s->u, sa, s->ec->order, n);
369
	// K <- sa(Vb - (2^l + t)Qb), K == O => K <- G
370 1
	t[n / 2] = 1;
371 1
	if (!ecMulA(Qb, Qb, s->ec, t, n / 2 + 1, stack))
372 0
		return ERR_BAD_PARAMS;
373 1
	if (!ecpSubAA(Vb, Vb, Qb, s->ec, stack))
374 0
		qrTo(K, s->ec->base, s->ec->f, stack);
375
	else
376
	{
377 1
		if (!ecMulA(Vb, Vb, s->ec, sa, n, stack))
378 0
			return ERR_BAD_PARAMS;
379 1
		qrTo(K, ecX(Vb), s->ec->f, stack);
380
	}
381
	// K <- beltHash(<K>_2l || certa || certb || helloa || hellob)
382 1
	beltHashStart(stack);
383 1
	beltHashStepH(K, no, stack);
384 1
	beltHashStepH(s->cert->data, s->cert->len, stack);
385 1
	beltHashStepH(certb->data, certb->len, stack);
386 1
	if (s->settings->helloa)
387 0
		beltHashStepH(s->settings->helloa, s->settings->helloa_len, stack);
388 1
	if (s->settings->hellob)
389 0
		beltHashStepH(s->settings->hellob, s->settings->hellob_len, stack);
390 1
	beltHashStepG(K, stack);
391
	// K0 <- beltKRP(K, 1^96, 0)
392 1
	memSetZero(block0, 16);
393 1
	memSet(block1, 0xFF, 16);
394 1
	beltKRPStart(stack, K, 32, block1);
395 1
	beltKRPStepG(s->K0, 32, block0, stack);
396
	// K1 <- beltKRP(K, 1^96, 1)
397 1
	if (s->settings->kca || s->settings->kcb)
398
	{
399 1
		block0[0] = 1;
400 1
		beltKRPStepG(s->K1, 32, block0, stack);
401
	}
402
	// Ta <- beltMAC(0^128, K1), ...|| out <- Ta
403 1
	if (s->settings->kca)
404
	{
405 1
		block0[0] = 0;
406 1
		beltMACStart(stack, s->K1, 32);
407 1
		beltMACStepA(block0, 16, stack);
408 1
		beltMACStepG(out + 2 * no, stack);
409
	}
410
	// все нормально
411 1
	return ERR_OK;
412
}
413

414 1
static size_t bakeBMQVStep3_deep(size_t n, size_t f_deep, size_t ec_d,
415
	size_t ec_deep)
416
{
417 1
	return O_OF_W(8 * n + 2) +
418 1
		utilMax(9,
419
			f_deep,
420
			ecpIsOnA_deep(n, f_deep),
421
			ecMulA_deep(n, ec_d, ec_deep, n),
422
			beltHash_keep(),
423
			zzMul_deep(n / 2, n),
424 1
			zzMod_deep(n + n / 2 + 1, n),
425
			ecpSubAA_deep(n, f_deep),
426
			beltKRP_keep(),
427
			beltMAC_keep());
428
}
429

430 1
err_t bakeBMQVStep4(octet out[], const octet in[], const bake_cert* certa,
431
	void* state)
432
{
433
	err_t code;
434 1
	bake_bmqv_o* s = (bake_bmqv_o*)state;
435
	size_t n, no;
436
	// стек
437
	word* Qa;			/* [2 * n] */
438
	word* Va;			/* [2 * n] */
439
	word* t;			/* [n / 2 + 1] */
440
	word* sb;			/* [n + n / 2 + 1] */
441
	octet* K;			/* [no] (совпадает с Qa) */
442
	octet* block0;		/* [16] (совпадает с t) */
443
	octet* block1;		/* [16] (следует за block0) */
444
	void* stack;
445
	// проверить входные данные
446 1
	if (!objIsOperable(s))
447 0
		return ERR_BAD_INPUT;
448 1
	n = s->ec->f->n, no = s->ec->f->no;
449 1
	if (!memIsValid(in, 2 * no + (s->settings->kca ? 8u : 0)) ||
450 1
		!memIsValid(out, s->settings->kcb ? 8u : 0) ||
451 1
		!memIsValid(certa, sizeof(bake_cert)) ||
452 1
		!memIsValid(certa->data, certa->len) ||
453 1
		certa->val == 0)
454 0
		return ERR_BAD_INPUT;
455 1
	ASSERT(memIsDisjoint2(out, s->settings->kcb ? 8u : 0, s, objKeep(s)));
456
	// раскладка стека
457 1
	Qa = objEnd(s, word);
458 1
	Va = Qa + 2 * n;
459 1
	t = Va + 2 * n;
460 1
	sb = t + n / 2 + 1;
461 1
	stack = sb + n + n / 2 + 1;
462 1
	K = (octet*)Qa;
463 1
	block0 = (octet*)t;
464 1
	block1 = block0 + 16;
465 1
	ASSERT(block1 + 16 <= (octet*)stack);
466
	// проверить certa
467 1
	code = certa->val((octet*)Qa, s->params, certa->data, certa->len);
468 1
	ERR_CALL_CHECK(code);
469 1
	if (!qrFrom(ecX(Qa), (octet*)Qa, s->ec->f, stack) ||
470 1
		!qrFrom(ecY(Qa, n), (octet*)Qa + no, s->ec->f, stack) ||
471 1
		!ecpIsOnA(Qa, s->ec, stack))
472 0
		return ERR_BAD_CERT;
473
	// Va <- in, Va \in E*?
474 1
	if (!qrFrom(ecX(Va), in, s->ec->f, stack) ||
475 1
		!qrFrom(ecY(Va, n), in + no, s->ec->f, stack) ||
476 1
		!ecpIsOnA(Va, s->ec, stack))
477 0
		return ERR_BAD_POINT;
478
	// t <- <beltHash(<Va>_2l || <Vb>_2l)>_l
479 1
	beltHashStart(stack);
480 1
	beltHashStepH(in, no, stack);
481 1
	beltHashStepH(s->Vb, no, stack);
482 1
	beltHashStepG2((octet*)t, no / 2, stack);
483 1
	wwFrom(t, t, no / 2);
484
	// sb <- (ub - (2^l + t)db) \mod q
485 1
	zzMul(sb, t, n / 2, s->d, n, stack);
486 1
	sb[n + n / 2] = zzAdd2(sb + n / 2, s->d, n);
487 1
	zzMod(sb, sb, n + n / 2 + 1, s->ec->order, n, stack);
488 1
	zzSubMod(sb, s->u, sb, s->ec->order, n);
489
	// K <- sb(Va - (2^l + t)Qa), K == O => K <- G
490 1
	t[n / 2] = 1;
491 1
	if (!ecMulA(Qa, Qa, s->ec, t, n / 2 + 1, stack))
492 0
		return ERR_BAD_PARAMS;
493 1
	if (!ecpSubAA(Va, Va, Qa, s->ec, stack))
494 0
		qrTo(K, s->ec->base, s->ec->f, stack);
495
	else
496
	{
497 1
		if (!ecMulA(Va, Va, s->ec, sb, n, stack))
498 0
			return ERR_BAD_PARAMS;
499 1
		qrTo(K, ecX(Va), s->ec->f, stack);
500
	}
501
	// K <- beltHash(<K>_2l || certa || certb || helloa || hellob)
502 1
	beltHashStart(stack);
503 1
	beltHashStepH(K, no, stack);
504 1
	beltHashStepH(certa->data, certa->len, stack);
505 1
	beltHashStepH(s->cert->data, s->cert->len, stack);
506 1
	if (s->settings->helloa)
507 0
		beltHashStepH(s->settings->helloa, s->settings->helloa_len, stack);
508 1
	if (s->settings->hellob)
509 0
		beltHashStepH(s->settings->hellob, s->settings->hellob_len, stack);
510 1
	beltHashStepG(K, stack);
511
	// K0 <- beltKRP(K, 1^96, 0)
512 1
	memSetZero(block0, 16);
513 1
	memSet(block1, 0xFF, 16);
514 1
	beltKRPStart(stack, K, 32, block1);
515 1
	beltKRPStepG(s->K0, 32, block0, stack);
516
	// K1 <- beltKRP(K, 1^96, 1)
517 1
	if (s->settings->kca || s->settings->kcb)
518
	{
519 1
		block0[0] = 1;
520 1
		beltKRPStepG(s->K1, 32, block0, stack);
521
	}
522
	// Ta == beltMAC(0^128, K1)?
523 1
	if (s->settings->kca)
524
	{
525 1
		block0[0] = 0;
526 1
		beltMACStart(stack, s->K1, 32);
527 1
		beltMACStepA(block0, 16, stack);
528 1
		if (!beltMACStepV(in + 2 * no, stack))
529 0
			return ERR_BAD_AUTH;
530
	}
531
	// Tb <- beltMAC(1^128, K1)?
532 1
	if (s->settings->kcb)
533
	{
534 1
		beltMACStart(stack, s->K1, 32);
535 1
		beltMACStepA(block1, 16, stack);
536 1
		beltMACStepG(out, stack);
537
	}
538
	// все нормально
539 1
	return ERR_OK;
540
}
541

542 1
static size_t bakeBMQVStep4_deep(size_t n, size_t f_deep, size_t ec_d,
543
	size_t ec_deep)
544
{
545 1
	return O_OF_W(6 * n + 2) +
546 1
		utilMax(9,
547
			f_deep,
548
			ecpIsOnA_deep(n, f_deep),
549
			ecMulA_deep(n, ec_d, ec_deep, n),
550
			beltHash_keep(),
551
			zzMul_deep(n / 2, n),
552 1
			zzMod_deep(n + n / 2 + 1, n),
553
			ecpSubAA_deep(n, f_deep),
554
			beltKRP_keep(),
555
			beltMAC_keep());
556
}
557

558 1
err_t bakeBMQVStep5(const octet in[8], void* state)
559
{
560 1
	bake_bmqv_o* s = (bake_bmqv_o*)state;
561
	// стек
562
	octet* block1;	/* [16] */
563
	void* stack;
564
	// проверить входные данные
565 1
	if (!objIsOperable(s))
566 0
		return ERR_BAD_INPUT;
567 1
	if (!s->settings->kcb)
568 0
		return ERR_BAD_LOGIC;
569 1
	if (!memIsValid(in, 8))
570 0
		return ERR_BAD_INPUT;
571
	// раскладка стека
572 1
	block1 = objEnd(s, octet);
573 1
	stack = block1 + 16;
574
	// Tb == beltMAC(1^128, K1)?
575 1
	memSet(block1, 0xFF, 16);
576 1
	beltMACStart(stack, s->K1, 32);
577 1
	beltMACStepA(block1, 16, stack);
578 1
	if (!beltMACStepV(in, stack))
579 0
		return ERR_BAD_AUTH;
580
	// все нормально
581 1
	return ERR_OK;
582
}
583

584 1
static size_t bakeBMQVStep5_deep(size_t n, size_t f_deep, size_t ec_d,
585
	size_t ec_deep)
586
{
587 1
	return 16 + beltMAC_keep();
588
}
589

590 1
err_t bakeBMQVStepG(octet key[32], void* state)
591
{
592 1
	bake_bmqv_o* s = (bake_bmqv_o*)state;
593
	// проверить входные данные
594 1
	if (!objIsOperable(s) ||
595 1
		!memIsValid(key, 32))
596 0
		return ERR_BAD_INPUT;
597
	// key <- K0
598 1
	memCopy(key, s->K0, 32);
599
	// все нормально
600 1
	return ERR_OK;
601
}
602

603 1
static size_t bakeBMQV_deep(size_t n, size_t f_deep, size_t ec_d, 
604
	size_t ec_deep)
605
{
606 1
	return utilMax(5,
607
		bakeBMQVStart_deep(n, f_deep, ec_d, ec_deep),
608
		bakeBMQVStep2_deep(n, f_deep, ec_d, ec_deep),
609
		bakeBMQVStep3_deep(n, f_deep, ec_d, ec_deep),
610
		bakeBMQVStep4_deep(n, f_deep, ec_d, ec_deep),
611
		bakeBMQVStep5_deep(n, f_deep, ec_d, ec_deep));
612
}
613

614
/*
615
*******************************************************************************
616
Выполнение BMQV
617
*******************************************************************************
618
*/
619

620 1
err_t bakeBMQVRunB(octet key[32], const bign_params* params,
621
	const bake_settings* settings, const octet privkeyb[],
622
	const bake_cert* certb, const bake_cert* certa,
623
	read_i read, write_i write, void* file)
624
{
625
	err_t code;
626
	size_t len;
627
	// блоб
628
	blob_t blob;
629
	octet* in;			/* [l / 2 + 8] */
630
	octet* out;			/* [l / 2] */
631
	void* state;		/* [bakeBMQV_keep()] */
632
	// проверить key
633 1
	if (!memIsValid(key, 32))
634 0
		return ERR_BAD_INPUT;
635
	// создать блоб
636 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
637 0
		return ERR_BAD_PARAMS;
638 1
	blob = blobCreate(params->l + 8 + bakeBMQV_keep(params->l));
639 1
	if (blob == 0)
640 0
		return ERR_OUTOFMEMORY;
641
	// раскладка блоба
642 1
	in = (octet*)blob;
643 1
	out = in + params->l / 2 + 8;
644 1
	state = out + params->l / 2;
645
	// старт
646 1
	code = bakeBMQVStart(state, params, settings, privkeyb, certb);
647 1
	ERR_CALL_HANDLE(code, blobClose(blob));
648
	// шаг 2
649 1
	code = bakeBMQVStep2(out, state);
650 1
	ERR_CALL_HANDLE(code, blobClose(blob));
651 1
	code = write(&len, out, params->l / 2, file);
652 1
	ERR_CALL_HANDLE(code, blobClose(blob));
653
	// шаг 4
654 1
	code = read(&len, in, params->l / 2 + (settings->kca ? 8u : 0), file);
655 1
	ERR_CALL_HANDLE(code, blobClose(blob));
656 1
	code = bakeBMQVStep4(out, in, certa, state);
657 1
	ERR_CALL_HANDLE(code, blobClose(blob));
658 1
	if (settings->kcb)
659
	{
660 1
		code = write(&len, out, 8, file);
661 1
		ERR_CALL_HANDLE(code, blobClose(blob));
662
	}
663
	// завершение
664 1
	code = bakeBMQVStepG(key, state);
665 1
	blobClose(blob);
666 1
	return code;
667
}
668

669 1
err_t bakeBMQVRunA(octet key[32], const bign_params* params,
670
	const bake_settings* settings, const octet privkeya[],
671
	const bake_cert* certa, const bake_cert* certb,
672
	read_i read, write_i write, void* file)
673
{
674
	err_t code;
675
	size_t len;
676
	// блоб
677
	blob_t blob;
678
	octet* in;			/* [l / 2] */
679
	octet* out;			/* [l / 2 + 8] */
680
	void* state;		/* [bakeBMQV_keep()] */
681
	// проверить key
682 1
	if (!memIsValid(key, 32))
683 0
		return ERR_BAD_INPUT;
684
	// создать блоб
685 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
686 0
		return ERR_BAD_PARAMS;
687 1
	blob = blobCreate(params->l + 8 + bakeBMQV_keep(params->l));
688 1
	if (blob == 0)
689 0
		return ERR_OUTOFMEMORY;
690
	// раскладка блоба
691 1
	in = (octet*)blob;
692 1
	out = in + params->l / 2;
693 1
	state = out + params->l / 2 + 8;
694
	// старт
695 1
	code = bakeBMQVStart(state, params, settings, privkeya, certa);
696 1
	ERR_CALL_HANDLE(code, blobClose(blob));
697
	// шаг 3
698 1
	code = read(&len, in, params->l / 2, file);
699 1
	ERR_CALL_HANDLE(code, blobClose(blob));
700 1
	code = bakeBMQVStep3(out, in, certb, state);
701 1
	ERR_CALL_HANDLE(code, blobClose(blob));
702 1
	code = write(&len, out, params->l / 2 + (settings->kca ? 8u : 0), file);
703 1
	ERR_CALL_HANDLE(code, blobClose(blob));
704
	// шаг 5
705 1
	if (settings->kcb)
706
	{
707 1
		code = read(&len, in, 8, file);
708 1
		ERR_CALL_HANDLE(code, blobClose(blob));
709 1
		code = bakeBMQVStep5(in, state);
710 1
		ERR_CALL_HANDLE(code, blobClose(blob));
711
	}
712
	// завершение
713 1
	code = bakeBMQVStepG(key, state);
714 1
	blobClose(blob);
715 1
	return code;
716
}
717

718
/*
719
*******************************************************************************
720
Шаги протокола BSTS
721
*******************************************************************************
722
*/
723

724
typedef struct
725
{
726
	obj_hdr_t hdr;				/*< заголовок */
727
// ptr_table {
728
	ec_o* ec;					/*< описание эллиптической кривой */
729
	word* d;					/*< [ec->f->n] долговременный личный ключ */
730
	word* u;					/*< [ec->f->n] одноразовый личный ключ */
731
	word* t;					/*< [ec->f->n / 2 + 1] t (совпадает с u) */
732
	word* Vb;					/*< [2 * ec->f->n] Vb */
733
// }
734
	bign_params params[1];		/*< параметры */
735
	bake_settings settings[1];	/*< настройки */
736
	bake_cert cert[1];			/*< сертификат */
737
	octet K0[32];				/*< ключ K0 */
738
	octet K1[32];				/*< ключ K1 */
739
	octet K2[32];				/*< ключ K2 */
740
	octet data[];				/*< данные */
741
} bake_bsts_o;
742

743
static size_t bakeBSTS_deep(size_t n, size_t f_deep, size_t ec_d, size_t ec_deep);
744

745 1
size_t bakeBSTS_keep(size_t l)
746
{
747 1
	const size_t n = W_OF_B(2 * l);
748 1
	return sizeof(bake_bsts_o) +
749 1
		bignStart_keep(l, bakeBSTS_deep) +
750 1
		O_OF_W(4 * n);
751
}
752

753 1
err_t bakeBSTSStart(void* state, const bign_params* params,
754
	const bake_settings* settings, const octet privkey[],
755
	const bake_cert* cert)
756
{
757
	err_t code;
758 1
	bake_bsts_o* s = (bake_bsts_o*)state;
759
	size_t n, no;
760
	word* Q;
761
	// стек
762
	void* stack;
763
	// проверить входные данные
764 1
	if (!memIsValid(params, sizeof(bign_params)) ||
765 1
		!memIsValid(settings, sizeof(bake_settings)) ||
766 1
		!memIsNullOrValid(settings->helloa, settings->helloa_len) ||
767 1
		!memIsNullOrValid(settings->hellob, settings->hellob_len))
768 0
		return ERR_BAD_INPUT;
769 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
770 0
		return ERR_BAD_PARAMS;
771 1
	if (settings->rng == 0)
772 0
		return ERR_BAD_RNG;
773 1
	if (!memIsValid(privkey, params->l / 4) ||
774 1
		!memIsValid(cert, sizeof(bake_cert)) ||
775 1
		!memIsValid(cert->data, cert->len) ||
776 1
		cert->val == 0)
777 0
		return ERR_BAD_INPUT;
778
	// загрузить параметры
779 1
	code = bignStart(s->data, params);
780 1
	ERR_CALL_CHECK(code);
781 1
	s->ec = (ec_o*)s->data;
782 1
	n = s->ec->f->n, no = s->ec->f->no;
783
	// сохранить параметры
784 1
	memCopy(s->params, params, sizeof(bign_params));
785
	// сохранить настройки
786 1
	memCopy(s->settings, settings, sizeof(bake_settings));
787
	// настроить указатели
788 1
	s->d = objEnd(s->ec, word);
789 1
	s->u = s->d + n;
790 1
	s->t = s->u;
791 1
	s->Vb = s->u + n;
792
	// настроить заголовок
793 1
	s->hdr.keep = sizeof(bake_bsts_o) + objKeep(s->ec) + O_OF_W(4 * n);
794 1
	s->hdr.p_count = 5;
795 1
	s->hdr.o_count = 1;
796
	// загрузить личный ключ
797 1
	wwFrom(s->d, privkey, no);
798
	// раскладка стека
799 1
	stack = objEnd(s, void);
800
	// проверить сертификат и его открытый ключ
801 1
	Q = s->Vb;
802 1
	code = cert->val((octet*)Q, params, cert->data, cert->len);
803 1
	ERR_CALL_CHECK(code);
804 1
	if (!qrFrom(ecX(Q), (octet*)Q, s->ec->f, stack) ||
805 1
		!qrFrom(ecY(Q, n), (octet*)Q + no, s->ec->f, stack) ||
806 1
		!ecpIsOnA(Q, s->ec, stack))
807 0
		return ERR_BAD_CERT;
808
	// сохранить сертификат
809 1
	memCopy(s->cert, cert, sizeof(bake_cert));
810
	// все нормально
811 1
	return code;
812
}
813

814 1
static size_t bakeBSTSStart_deep(size_t n, size_t f_deep, size_t ec_d,
815
	size_t ec_deep)
816
{
817 1
	return utilMax(2,
818
			f_deep,
819
			ecpIsOnA_deep(n, f_deep));
820
}
821

822 1
err_t bakeBSTSStep2(octet out[], void* state)
823
{
824 1
	bake_bsts_o* s = (bake_bsts_o*)state;
825
	size_t n, no;
826
	// стек
827
	void* stack;
828
	// обработать входные данные
829 1
	if (!objIsOperable(s))
830 0
		return ERR_BAD_INPUT;
831 1
	n = s->ec->f->n, no = s->ec->f->no;
832 1
	if (!memIsValid(out, 2 * no))
833 0
		return ERR_BAD_INPUT;
834
	// раскладка стека
835 1
	stack = objEnd(s, void);
836
	// ub <-R {1, 2, ..., q - 1}
837 1
	if (!zzRandNZMod(s->u, s->ec->order, n, s->settings->rng,
838
		s->settings->rng_state))
839 0
		return ERR_BAD_RNG;
840
	// Vb <- ub G
841 1
	if (!ecMulA(s->Vb, s->ec->base, s->ec, s->u, n, stack))
842 0
		return ERR_BAD_PARAMS;
843
	// out <- <Vb>
844 1
	qrTo(out, ecX(s->Vb), s->ec->f, stack);
845 1
	qrTo(out + no, ecY(s->Vb, n), s->ec->f, stack);
846
	// все нормально
847 1
	return ERR_OK;
848
}
849

850 1
static size_t bakeBSTSStep2_deep(size_t n, size_t f_deep, size_t ec_d,
851
	size_t ec_deep)
852
{
853 1
	return utilMax(2,
854
			f_deep,
855
			ecMulA_deep(n, ec_d, ec_deep, n));
856
}
857

858 1
err_t bakeBSTSStep3(octet out[], const octet in[], void* state)
859
{
860 1
	bake_bsts_o* s = (bake_bsts_o*)state;
861
	size_t n, no;
862
	// стек
863
	word* Va;			/* [2 * n] */
864
	word* t;			/* [n / 2 + 1] */
865
	word* sa;			/* [n + n / 2 + 1] */
866
	octet* K;			/* [no] (совпадает с Va) */
867
	octet* block0;		/* [16] (следует за sa) */
868
	octet* block1;		/* [16] (следует за block0) */
869
	void* stack;
870
	// проверить входные данные
871 1
	if (!objIsOperable(s))
872 0
		return ERR_BAD_INPUT;
873 1
	n = s->ec->f->n, no = s->ec->f->no;
874 1
	if (!memIsValid(in, 2 * no) ||
875 1
		!memIsValid(out, 3 * no + s->cert->len + 8))
876 0
		return ERR_BAD_INPUT;
877 1
	ASSERT(memIsDisjoint2(out, 3 * no + s->cert->len + 8, s, objKeep(s)));
878
	// раскладка стека
879 1
	Va = objEnd(s, word);
880 1
	t = Va + 2 * n;
881 1
	sa = t + n / 2 + 1;
882 1
	K = (octet*)Va;
883 1
	block0 = (octet*)(sa + n + n / 2 + 1);
884 1
	block1 = block0 + 16;
885 1
	stack = block1 + 16;
886
	// Vb <- in, Vb \in E*?
887 1
	if (!qrFrom(ecX(s->Vb), in, s->ec->f, stack) ||
888 1
		!qrFrom(ecY(s->Vb, n), in + no, s->ec->f, stack) ||
889 1
		!ecpIsOnA(s->Vb, s->ec, stack))
890 0
		return ERR_BAD_POINT;
891
	// ua <-R {1, 2, ..., q - 1}
892 1
	if (!zzRandNZMod(s->u, s->ec->order, n, s->settings->rng,
893
		s->settings->rng_state))
894 0
		return ERR_BAD_RNG;
895
	// Va <- ua G
896 1
	if (!ecMulA(Va, s->ec->base, s->ec, s->u, n, stack))
897 0
		return ERR_BAD_PARAMS;
898 1
	qrTo((octet*)Va, ecX(Va), s->ec->f, stack);
899 1
	qrTo((octet*)Va + no, ecY(Va, n), s->ec->f, stack);
900
	// t <- <beltHash(<Va>_2l || <Vb>_2l)>_l
901 1
	beltHashStart(stack);
902 1
	beltHashStepH(Va, no, stack);
903 1
	beltHashStepH(in, no, stack);
904 1
	beltHashStepG2((octet*)t, no / 2, stack);
905 1
	wwFrom(t, t, no / 2);
906
	// out ||.. <- <Va>_4l
907 1
	memCopy(out, Va, 2 * no);
908
	// sa <- (ua - (2^l + t)da) \mod q
909 1
	zzMul(sa, t, n / 2, s->d, n, stack);
910 1
	sa[n + n / 2] = zzAdd2(sa + n / 2, s->d, n);
911 1
	zzMod(sa, sa, n + n / 2 + 1, s->ec->order, n, stack);
912 1
	zzSubMod(sa, s->u, sa, s->ec->order, n);
913
	// ..|| out ||.. <- sa || certa
914 1
	wwTo(out + 2 * no, no, sa);
915 1
	memCopy(out + 3 * no, s->cert->data, s->cert->len);
916
	// K <- beltHash(<ua Vb>_2l || helloa || hellob)
917 1
	if (!ecMulA(Va, s->Vb, s->ec, s->u, n, stack))
918 0
		return ERR_BAD_PARAMS;
919 1
	qrTo(K, ecX(Va), s->ec->f, stack);
920 1
	beltHashStart(stack);
921 1
	beltHashStepH(K, no, stack);
922 1
	if (s->settings->helloa)
923 0
		beltHashStepH(s->settings->helloa, s->settings->helloa_len, stack);
924 1
	if (s->settings->hellob)
925 0
		beltHashStepH(s->settings->hellob, s->settings->hellob_len, stack);
926 1
	beltHashStepG(K, stack);
927
	// K0 <- beltKRP(K, 1^96, 0)
928 1
	memSetZero(block0, 16);
929 1
	memSet(block1, 0xFF, 16);
930 1
	beltKRPStart(stack, K, 32, block1);
931 1
	beltKRPStepG(s->K0, 32, block0, stack);
932
	// K1 <- beltKRP(K, 1^96, 1)
933 1
	block0[0] = 1;
934 1
	beltKRPStepG(s->K1, 32, block0, stack);
935
	// K2 <- beltKRP(K, 1^96, 2)
936 1
	block0[0] = 2;
937 1
	beltKRPStepG(s->K2, 32, block0, stack);
938
	// ..|| out ||.. <- beltCFBEncr(sa || certa)
939 1
	block0[0] = 0;
940 1
	beltCFBStart(stack, s->K2, 32, block0);
941 1
	beltCFBStepE(out + 2 * no, no + s->cert->len, stack);
942
	// ..|| out <- beltMAC(beltCFBEncr(sa || certa) || 0^128)
943 1
	beltMACStart(stack, s->K1, 32);
944 1
	beltMACStepA(out + 2 * no, no + s->cert->len, stack);
945 1
	beltMACStepA(block0, 16, stack);
946 1
	beltMACStepG(out + 3 * no + s->cert->len, stack);
947
	// сохранить t
948 1
	wwCopy(s->t, t, n / 2);
949 1
	s->t[n / 2] = 1;
950
	// все нормально
951 1
	return ERR_OK;
952
}
953

954 1
static size_t bakeBSTSStep3_deep(size_t n, size_t f_deep, size_t ec_d,
955
	size_t ec_deep)
956
{
957 1
	return O_OF_W(4 * n + 2) + 32 +
958 1
		utilMax(9,
959
			f_deep,
960
			ecpIsOnA_deep(n, f_deep),
961
			ecMulA_deep(n, ec_d, ec_deep, n),
962
			beltHash_keep(),
963
			zzMul_deep(n / 2, n),
964 1
			zzMod_deep(n + n / 2 + 1, n),
965
			beltKRP_keep(),
966
			beltCFB_keep(),
967
			beltMAC_keep());
968
}
969

970 1
err_t bakeBSTSStep4(octet out[], const octet in[], size_t in_len,
971
	bake_certval_i vala, void* state)
972
{
973
	err_t code;
974 1
	bake_bsts_o* s = (bake_bsts_o*)state;
975
	size_t n, no;
976
	// стек
977
	word* Va;			/* [2 * n] */
978
	word* Qa;			/* [2 * n] */
979
	word* t;			/* [n / 2 + 1] */
980
	word* sa;			/* [n] */
981
	word* sb;			/* [n + n / 2 + 1] (совпадает с sa) */
982
	octet* K;			/* [no] (совпадает с Qa) */
983
	octet* block0;		/* [16] (следует за sb) */
984
	octet* block1;		/* [16] (следует за block0) */
985
	void* stack;
986
	// проверить входные данные
987 1
	if (!objIsOperable(s))
988 0
		return ERR_BAD_INPUT;
989 1
	n = s->ec->f->n, no = s->ec->f->no;
990 1
	if (in_len <= 3 * no + 8 ||
991 1
		!memIsValid(in, in_len) ||
992 1
		vala == 0 ||
993 1
		!memIsValid(out, no + s->cert->len + 8))
994 0
		return ERR_BAD_INPUT;
995 1
	ASSERT(memIsDisjoint2(out, no + s->cert->len + 8, s, objKeep(s)));
996
	// раскладка стека
997 1
	Va = objEnd(s, word);
998 1
	Qa = Va + 2 * n;
999 1
	t = Qa + 2 * n;
1000 1
	sa = sb = t + n / 2 + 1;
1001 1
	K = (octet*)Qa;
1002 1
	block0 = (octet*)(sb + n + n / 2 + 1);
1003 1
	block1 = block0 + 16;
1004 1
	stack = block1 + 16;
1005
	// Va <- in, Va \in E*?
1006 1
	if (!qrFrom(ecX(Va), in, s->ec->f, stack) ||
1007 1
		!qrFrom(ecY(Va, n), in + no, s->ec->f, stack) ||
1008 1
		!ecpIsOnA(Va, s->ec, stack))
1009 0
		return ERR_BAD_POINT;
1010
	// K <- beltHash(<ub Va>_2l || helloa || hellob)
1011 1
	if (!ecMulA(Qa, Va, s->ec, s->u, n, stack))
1012 0
		return ERR_BAD_PARAMS;
1013 1
	qrTo(K, ecX(Qa), s->ec->f, stack);
1014 1
	beltHashStart(stack);
1015 1
	beltHashStepH(K, no, stack);
1016 1
	if (s->settings->helloa)
1017 0
		beltHashStepH(s->settings->helloa, s->settings->helloa_len, stack);
1018 1
	if (s->settings->hellob)
1019 0
		beltHashStepH(s->settings->hellob, s->settings->hellob_len, stack);
1020 1
	beltHashStepG(K, stack);
1021
	// K0 <- beltKRP(K, 1^96, 0)
1022 1
	memSetZero(block0, 16);
1023 1
	memSet(block1, 0xFF, 16);
1024 1
	beltKRPStart(stack, K, 32, block1);
1025 1
	beltKRPStepG(s->K0, 32, block0, stack);
1026
	// K1 <- beltKRP(K, 1^96, 1)
1027 1
	block0[0] = 1;
1028 1
	beltKRPStepG(s->K1, 32, block0, stack);
1029
	// K2 <- beltKRP(K, 1^96, 2)
1030 1
	block0[0] = 2;
1031 1
	beltKRPStepG(s->K2, 32, block0, stack);
1032
	// Ta == beltMAC(Ya || 0^128, K1)?
1033 1
	block0[0] = 0;
1034 1
	beltMACStart(stack, s->K1, 32);
1035 1
	beltMACStepA(in + 2 * no, in_len - 2 * no - 8, stack);
1036 1
	beltMACStepA(block0, 16, stack);
1037 1
	if (!beltMACStepV(in + in_len - 8, stack))
1038 0
		return ERR_BAD_AUTH;
1039
	// обработать Ya = [in_len - 2 * no - 8]in
1040 1
	in_len -= 2 * no + 8;
1041
	{
1042
		blob_t Ya;
1043
		// sa || certa <- beltCFBDecr(Ya, K2, 0^128)
1044 1
		if ((Ya = blobCreate(in_len)) == 0)
1045 0
			return ERR_OUTOFMEMORY;
1046 1
		memCopy(Ya, in + 2 * no, in_len);
1047 1
		beltCFBStart(stack, s->K2, 32, block0);
1048 1
		beltCFBStepD(Ya, in_len, stack);
1049
		// sa \in {0, 1,..., q - 1}?
1050 1
		wwFrom(sa, Ya, no);
1051 1
		if (wwCmp(sa, s->ec->order, n) >= 0)
1052
		{
1053 0
			blobClose(Ya);
1054 0
			return ERR_BAD_AUTH;
1055
		}
1056
		// проверить certa
1057 1
		code = vala((octet*)Qa, s->params, (octet*)Ya + no, in_len - no);
1058 1
		ERR_CALL_HANDLE(code, blobClose(Ya));
1059 1
		if (!qrFrom(ecX(Qa), (octet*)Qa, s->ec->f, stack) ||
1060 1
			!qrFrom(ecY(Qa, n), (octet*)Qa + no, s->ec->f, stack) ||
1061 1
			!ecpIsOnA(Qa, s->ec, stack))
1062 0
			code = ERR_BAD_CERT;
1063 1
		blobClose(Ya);
1064 1
		ERR_CALL_CHECK(code);
1065
	}
1066
	// t <- <beltHash(<Va>_2l || <Vb>_2l)>_l
1067 1
	beltHashStart(stack);
1068 1
	beltHashStepH(in, no, stack);
1069 1
	qrTo((octet*)s->Vb, s->Vb, s->ec->f, stack);
1070 1
	beltHashStepH(s->Vb, no, stack);
1071 1
	beltHashStepG2((octet*)t, no / 2, stack);
1072 1
	wwFrom(t, t, no / 2);
1073
	// sa G + (2^l + t)Qa == Va?
1074 1
	t[n / 2] = 1;
1075 1
	if (!ecAddMulA(Qa, s->ec, stack, 2, s->ec->base, sa, n, Qa, t, n / 2 + 1))
1076 0
		return ERR_BAD_PARAMS;
1077 1
	if (!wwEq(Qa, Va, 2 * n))
1078 0
		return ERR_BAD_AUTH;
1079
	// sb <- (ub - (2^l + t)db) \mod q
1080 1
	zzMul(sb, t, n / 2, s->d, n, stack);
1081 1
	sb[n + n / 2] = zzAdd2(sb + n / 2, s->d, n);
1082 1
	zzMod(sb, sb, n + n / 2 + 1, s->ec->order, n, stack);
1083 1
	zzSubMod(sb, s->u, sb, s->ec->order, n);
1084
	// out ||.. <- beltCFBEncr(sb || certb)
1085 1
	wwTo(out, no, sb);
1086 1
	memCopy(out + no, s->cert->data, s->cert->len);
1087 1
	beltCFBStart(stack, s->K2, 32, block1);
1088 1
	beltCFBStepE(out, no + s->cert->len, stack);
1089
	// .. || out <- beltMAC(beltCFBEncr(sb || certb) || 1^128)
1090 1
	beltMACStart(stack, s->K1, 32);
1091 1
	beltMACStepA(out, no + s->cert->len, stack);
1092 1
	beltMACStepA(block1, 16, stack);
1093 1
	beltMACStepG(out + no + s->cert->len, stack);
1094
	// все нормально
1095 1
	return ERR_OK;
1096
}
1097

1098 1
static size_t bakeBSTSStep4_deep(size_t n, size_t f_deep, size_t ec_d,
1099
	size_t ec_deep)
1100
{
1101 1
	return O_OF_W(6 * n + 2) + 32 +
1102 1
		utilMax(10,
1103
			f_deep,
1104
			ecpIsOnA_deep(n, f_deep),
1105
			ecMulA_deep(n, ec_d, ec_deep, n),
1106
			beltHash_keep(),
1107
			zzMul_deep(n / 2, n),
1108 1
			zzMod_deep(n + n / 2 + 1, n),
1109 1
			ecAddMulA_deep(n, ec_d, ec_deep, 2, n, n / 2 + 1),
1110
			beltKRP_keep(),
1111
			beltCFB_keep(),
1112
			beltMAC_keep());
1113
}
1114

1115 1
err_t bakeBSTSStep5(const octet in[], size_t in_len, bake_certval_i valb,
1116
	void* state)
1117
{
1118
	err_t code;
1119 1
	bake_bsts_o* s = (bake_bsts_o*)state;
1120
	size_t n, no;
1121
	// стек
1122
	word* Qb;			/* [2 * n] */
1123
	word* sb;			/* [n] */
1124
	octet* block1;		/* [16] (совпадает с Qb) */
1125
	octet* Tb;			/* [8] (следует за block1) */
1126
	void* stack;
1127
	// проверить входные данные
1128 1
	if (!objIsOperable(s))
1129 0
		return ERR_BAD_INPUT;
1130 1
	n = s->ec->f->n, no = s->ec->f->no;
1131 1
	if (in_len <= no + 8 ||
1132 1
		!memIsValid(in, in_len) ||
1133
		valb == 0)
1134 0
		return ERR_BAD_INPUT;
1135
	// раскладка стека
1136 1
	Qb = objEnd(s, word);
1137 1
	sb = Qb + 2 * n;
1138 1
	stack = sb + n;
1139 1
	block1 = (octet*)Qb;
1140 1
	Tb = block1 + 16;
1141 1
	ASSERT(Tb + 8 <= (octet*)stack);
1142
	// Tb == beltMAC(Yb || 1^128, K1)?
1143 1
	memSet(block1, 0xFF, 16);
1144 1
	beltMACStart(stack, s->K1, 32);
1145 1
	beltMACStepA(in, in_len - 8, stack);
1146 1
	beltMACStepA(block1, 16, stack);
1147 1
	if (!beltMACStepV(in + in_len - 8, stack))
1148 0
		return ERR_BAD_AUTH;
1149
	// обработать Yb = [in_len - 8]in
1150 1
	in_len -= 8;
1151
	{
1152
		blob_t Yb;
1153
		// sb || certb <- beltCFBDecr(Yb, K2, 1^128)
1154 1
		if ((Yb = blobCreate(in_len)) == 0)
1155 0
			return ERR_OUTOFMEMORY;
1156 1
		memCopy(Yb, in, in_len);
1157 1
		beltCFBStart(stack, s->K2, 32, block1);
1158 1
		beltCFBStepD(Yb, in_len, stack);
1159
		// sb \in {0, 1,..., q - 1}?
1160 1
		wwFrom(sb, Yb, no);
1161 1
		if (wwCmp(sb, s->ec->order, n) >= 0)
1162
		{
1163 0
			blobClose(Yb);
1164 0
			return ERR_BAD_AUTH;
1165
		}
1166
		// проверить certa
1167 1
		code = valb((octet*)Qb, s->params, (octet*)Yb + no, in_len - no);
1168 1
		ERR_CALL_HANDLE(code, blobClose(Yb));
1169 1
		if (!qrFrom(ecX(Qb), (octet*)Qb, s->ec->f, stack) ||
1170 1
			!qrFrom(ecY(Qb, n), (octet*)Qb + no, s->ec->f, stack) ||
1171 1
			!ecpIsOnA(Qb, s->ec, stack))
1172 0
			code = ERR_BAD_CERT;
1173 1
		blobClose(Yb);
1174 1
		ERR_CALL_CHECK(code);
1175
	}
1176
	// sb G + (2^l + t)Qa == Vb?
1177 1
	if (!ecAddMulA(Qb, s->ec, stack, 2, s->ec->base, sb, n,
1178 1
		Qb, s->t, n / 2 + 1))
1179 0
		return ERR_BAD_PARAMS;
1180 1
	if (!wwEq(Qb, s->Vb, 2 * n))
1181 0
		return ERR_BAD_AUTH;
1182
	// все нормально
1183 1
	return ERR_OK;
1184
}
1185

1186 1
static size_t bakeBSTSStep5_deep(size_t n, size_t f_deep, size_t ec_d,
1187
	size_t ec_deep)
1188
{
1189 1
	return O_OF_W(3 * n) +
1190 1
		utilMax(5,
1191
			beltMAC_keep(),
1192
			beltCFB_keep(),
1193
			f_deep,
1194
			ecpIsOnA_deep(n, f_deep),
1195 1
			ecAddMulA_deep(n, ec_d, ec_deep, 2, n, n / 2 + 1));
1196
}
1197

1198 1
err_t bakeBSTSStepG(octet key[32], void* state)
1199
{
1200 1
	bake_bsts_o* s = (bake_bsts_o*)state;
1201
	// проверить входные данные
1202 1
	if (!objIsOperable(s) ||
1203 1
		!memIsValid(key, 32))
1204 0
		return ERR_BAD_INPUT;
1205
	// key <- K0
1206 1
	memCopy(key, s->K0, 32);
1207
	// все нормально
1208 1
	return ERR_OK;
1209
}
1210

1211 1
static size_t bakeBSTS_deep(size_t n, size_t f_deep, size_t ec_d,
1212
	size_t ec_deep)
1213
{
1214 1
	return utilMax(5,
1215
		bakeBSTSStart_deep(n, f_deep, ec_d, ec_deep),
1216
		bakeBSTSStep2_deep(n, f_deep, ec_d, ec_deep),
1217
		bakeBSTSStep3_deep(n, f_deep, ec_d, ec_deep),
1218
		bakeBSTSStep4_deep(n, f_deep, ec_d, ec_deep),
1219
		bakeBSTSStep5_deep(n, f_deep, ec_d, ec_deep));
1220
}
1221

1222
/*
1223
*******************************************************************************
1224
Выполнение BSTS
1225
*******************************************************************************
1226
*/
1227

1228 1
err_t bakeBSTSRunB(octet key[32], const bign_params* params,
1229
	const bake_settings* settings, const octet privkeyb[],
1230
	const bake_cert* certb, bake_certval_i vala,
1231
	read_i read, write_i write, void* file)
1232
{
1233
	err_t code;
1234
	size_t len;
1235
	// блоб
1236
	blob_t blob;
1237
	octet* in;			/* [512] */
1238
	octet* out;			/* [MAX2(l / 2, l / 4 + certb->len + 8)] */
1239
	void* state;		/* [bakeBSTS_keep()] */
1240
	// проверить входные данные
1241 1
	if (!memIsValid(key, 32) ||
1242 1
		!memIsValid(certb, sizeof(bake_cert)))
1243 0
		return ERR_BAD_INPUT;
1244
	// создать блоб
1245 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
1246 0
		return ERR_BAD_PARAMS;
1247 1
	blob = blobCreate(512 +
1248 1
		MAX2(params->l / 2, params->l / 4 + certb->len + 8) +
1249 1
		bakeBSTS_keep(params->l));
1250 1
	if (blob == 0)
1251 0
		return ERR_OUTOFMEMORY;
1252
	// раскладка блоба
1253 1
	in = (octet*)blob;
1254 1
	out = in + 512;
1255 1
	state = out + MAX2(params->l / 2, params->l / 4 + certb->len + 8);
1256
	// старт
1257 1
	code = bakeBSTSStart(state, params, settings, privkeyb, certb);
1258 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1259
	// шаг 2
1260 1
	code = bakeBSTSStep2(out, state);
1261 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1262 1
	code = write(&len, out, params->l / 2, file);
1263 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1264
	// шаг 4: прочитать блок M2
1265 1
	code = read(&len, in, 512, file);
1266
	// шаг 4: M2 из одного блока?
1267 1
	if (code == ERR_MAX)
1268
	{
1269 1
		code = bakeBSTSStep4(out, in, len, vala, state);
1270 1
		ERR_CALL_HANDLE(code, blobClose(blob));
1271 1
		code = write(&len, out, params->l / 4 + certb->len + 8, file);
1272 1
		ERR_CALL_HANDLE(code, blobClose(blob));
1273
	}
1274
	// шаг 4: ошибка при чтении
1275 1
	else if (code != ERR_OK)
1276
	{
1277 1
		blobClose(blob);
1278 1
		return code;
1279
	}
1280
	// шаг 4: обработать M2 из нескольких блоков
1281
	else
1282
	{
1283 0
		blob_t M2 = 0;
1284 0
		while (code == ERR_OK)
1285
		{
1286 0
			if ((M2 = blobResize(M2, blobSize(M2) + len)) == 0)
1287
			{
1288 0
				blobClose(blob);
1289 0
				return ERR_OUTOFMEMORY;
1290
			}
1291 0
			memCopy((octet*)M2 + blobSize(M2) - len, in, len);
1292 0
			code = read(&len, in, 512, file);
1293
		}
1294 0
		if (code != ERR_MAX)
1295
		{
1296 0
			blobClose(M2);
1297 0
			blobClose(blob);
1298 0
			return code;
1299
		}
1300 0
		if ((M2 = blobResize(M2, blobSize(M2) + len)) == 0)
1301
		{
1302 0
			blobClose(blob);
1303 0
			return ERR_OUTOFMEMORY;
1304
		}
1305 0
		memCopy((octet*)M2 + blobSize(M2) - len, in, len);
1306 0
		code = bakeBSTSStep4(out, M2, blobSize(M2), vala, state);
1307 0
		blobClose(M2);
1308 0
		ERR_CALL_HANDLE(code, blobClose(blob));
1309 0
		code = write(&len, out, params->l / 4 + certb->len + 8, file);
1310 0
		ERR_CALL_HANDLE(code, blobClose(blob));
1311
	}
1312
	// завершение
1313 1
	code = bakeBSTSStepG(key, state);
1314 1
	blobClose(blob);
1315 1
	return code;
1316
}
1317

1318 1
err_t bakeBSTSRunA(octet key[32], const bign_params* params,
1319
	const bake_settings* settings, const octet privkeya[],
1320
	const bake_cert* certa, bake_certval_i valb,
1321
	read_i read, write_i write, void* file)
1322
{
1323
	err_t code;
1324
	size_t len;
1325
	// блоб
1326
	blob_t blob;
1327
	octet* in;			/* [MAX2(512, l / 2)] */
1328
	octet* out;			/* [3 * l / 4 + certa->len + 8] */
1329
	void* state;		/* [bakeBSTS_keep()] */
1330
	// проверить входные данные
1331 1
	if (!memIsValid(key, 32) ||
1332 1
		!memIsValid(certa, sizeof(bake_cert)))
1333 0
		return ERR_BAD_INPUT;
1334
	// создать блоб
1335 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
1336 0
		return ERR_BAD_PARAMS;
1337 1
	blob = blobCreate(MAX2(512, params->l / 2) +
1338 1
		3 * params->l / 4 + certa->len + 8 +
1339 1
		bakeBSTS_keep(params->l));
1340 1
	if (blob == 0)
1341 0
		return ERR_OUTOFMEMORY;
1342
	// раскладка блоба
1343 1
	in = (octet*)blob;
1344 1
	out = in + MAX2(512, params->l / 2);
1345 1
	state = out + 3 * params->l / 4 + certa->len + 8;
1346
	// старт
1347 1
	code = bakeBSTSStart(state, params, settings, privkeya, certa);
1348 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1349
	// шаг 3
1350 1
	code = read(&len, in, params->l / 2, file);
1351 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1352 1
	code = bakeBSTSStep3(out, in, state);
1353 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1354 1
	code = write(&len, out, 3 * params->l / 4 + certa->len + 8, file);
1355 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1356
	// шаг 5: прочитать блок M3
1357 1
	code = read(&len, in, 512, file);
1358
	// шаг 5: M3 из одного блока?
1359 1
	if (code == ERR_MAX)
1360
	{
1361 1
		code = bakeBSTSStep5(in, len, valb, state);
1362 1
		ERR_CALL_HANDLE(code, blobClose(blob));
1363
	}
1364
	// шаг 5: ошибка при чтении
1365 1
	else if (code != ERR_OK)
1366
	{
1367 1
		blobClose(blob);
1368 1
		return code;
1369
	}
1370
	// шаг 5: обработать M3 из нескольких блоков
1371
	else
1372
	{
1373 0
		blob_t M3 = 0;
1374 0
		while (code == ERR_OK)
1375
		{
1376 0
			if ((M3 = blobResize(M3, blobSize(M3) + len)) == 0)
1377
			{
1378 0
				blobClose(blob);
1379 0
				return ERR_OUTOFMEMORY;
1380
			}
1381 0
			memCopy((octet*)M3 + blobSize(M3) - len, in, len);
1382 0
			code = read(&len, in, 512, file);
1383
		}
1384 0
		if (code != ERR_MAX)
1385
		{
1386 0
			blobClose(M3);
1387 0
			blobClose(blob);
1388 0
			return code;
1389
		}
1390 0
		if ((M3 = blobResize(M3, blobSize(M3) + len)) == 0)
1391
		{
1392 0
			blobClose(blob);
1393 0
			return ERR_OUTOFMEMORY;
1394
		}
1395 0
		memCopy((octet*)M3 + blobSize(M3) - len, in, len);
1396 0
		code = bakeBSTSStep5(M3, blobSize(M3), valb, state);
1397 0
		blobClose(M3);
1398 0
		ERR_CALL_HANDLE(code, blobClose(blob));
1399
	}
1400
	// завершение
1401 1
	code = bakeBSTSStepG(key, state);
1402 1
	blobClose(blob);
1403 1
	return code;
1404
}
1405

1406
/*
1407
*******************************************************************************
1408
Шаги протокола BPACE
1409
*******************************************************************************
1410
*/
1411

1412
typedef struct
1413
{
1414
	obj_hdr_t hdr;				/*< заголовок */
1415
// ptr_table {
1416
	ec_o* ec;					/*< описание эллиптической кривой */
1417
	octet* R;					/*< [ec->f->no](Ra || Rb или ecX(Va)) */
1418
	word* W;					/*< [2 * ec->f->n] точка W */
1419
	word* u;					/*< [ec->f->n] ua или ub */
1420
// }
1421
	bake_settings settings[1];	/*< настройки */
1422
	octet K0[32];				/*< ключ K0 */
1423
	octet K1[32];				/*< ключ K1 */
1424
	octet K2[32];				/*< ключ K2 */
1425
	octet data[];				/*< данные */
1426
} bake_bpace_o;
1427

1428
static size_t bakeBPACE_deep(size_t n, size_t f_deep, size_t ec_d, size_t ec_deep);
1429

1430 1
size_t bakeBPACE_keep(size_t l)
1431
{
1432 1
	const size_t n = W_OF_B(2 * l);
1433 1
	const size_t no = O_OF_B(2 * l);
1434 1
	return sizeof(bake_bpace_o) +
1435 1
		bignStart_keep(l, bakeBPACE_deep) +
1436 1
		no + O_OF_W(3 * n);
1437
}
1438

1439 1
err_t bakeBPACEStart(void* state, const bign_params* params,
1440
	const bake_settings* settings, const octet pwd[], size_t pwd_len)
1441
{
1442
	err_t code;
1443 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1444
	size_t n, no;
1445
	// проверить входные данные
1446 1
	if (!memIsValid(params, sizeof(bign_params)) ||
1447 1
		!memIsValid(settings, sizeof(bake_settings)) ||
1448 1
		!memIsNullOrValid(settings->helloa, settings->helloa_len) ||
1449 1
		!memIsNullOrValid(settings->hellob, settings->hellob_len) ||
1450 1
		!memIsValid(pwd, pwd_len))
1451 0
		return ERR_BAD_INPUT;
1452 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
1453 0
		return ERR_BAD_PARAMS;
1454 1
	if (settings->rng == 0)
1455 0
		return ERR_BAD_RNG;
1456
	// загрузить параметры
1457 1
	code = bignStart(s->data, params);
1458 1
	ERR_CALL_CHECK(code);
1459 1
	s->ec = (ec_o*)s->data;
1460 1
	n = s->ec->f->n, no = s->ec->f->no;
1461
	// загрузить настройки
1462 1
	memCopy(s->settings, settings, sizeof(bake_settings));
1463
	// настроить указатели
1464 1
	s->R = objEnd(s->ec, octet);
1465 1
	s->W = (word*)(s->R + no);
1466 1
	s->u = s->W + 2 * n;
1467
	// настроить заголовок
1468 1
	s->hdr.keep = sizeof(bake_bpace_o) + objKeep(s->ec) + no + O_OF_W(3 * n);
1469 1
	s->hdr.p_count = 4;
1470 1
	s->hdr.o_count = 1;
1471
	// K2 <- beltHash(pwd)
1472 1
	beltHashStart(objEnd(s, void));
1473 1
	beltHashStepH(pwd, pwd_len, objEnd(s, void));
1474 1
	beltHashStepG(s->K2, objEnd(s, void));
1475
	// все нормально
1476 1
	return code;
1477
}
1478

1479 1
static size_t bakeBPACEStart_deep(size_t n, size_t f_deep, size_t ec_d,
1480
	size_t ec_deep)
1481
{
1482 1
	return beltHash_keep();
1483
}
1484

1485 1
err_t bakeBPACEStep2(octet out[], void* state)
1486
{
1487 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1488
	size_t no;
1489
	// стек
1490
	void* stack;
1491
	// обработать входные данные
1492 1
	if (!objIsOperable(s))
1493 0
		return ERR_BAD_INPUT;
1494 1
	no = s->ec->f->no;
1495 1
	if (!memIsValid(out, no / 2))
1496 0
		return ERR_BAD_INPUT;
1497
	// раскладка стека
1498 1
	stack = objEnd(s, void);
1499
	// Rb <-R {0, 1}^l
1500 1
	s->settings->rng(out, no / 2, s->settings->rng_state);
1501 1
	memCopy(s->R + no / 2, out, no / 2);
1502
	// out <- beltECB(Rb, K2)
1503 1
	beltECBStart(stack, s->K2, 32);
1504 1
	beltECBStepE(out, no / 2, stack);
1505
	// все нормально
1506 1
	return ERR_OK;
1507
}
1508

1509 1
static size_t bakeBPACEStep2_deep(size_t n, size_t f_deep, size_t ec_d,
1510
	size_t ec_deep)
1511
{
1512 1
	return beltECB_keep();
1513
}
1514

1515 1
err_t bakeBPACEStep3(octet out[], const octet in[], void* state)
1516
{
1517 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1518
	size_t n, no;
1519
	// стек
1520
	word* Va;			/* [2 * n] */
1521
	void* stack;
1522
	// проверить входные данные
1523 1
	if (!objIsOperable(s))
1524 0
		return ERR_BAD_INPUT;
1525 1
	n = s->ec->f->n, no = s->ec->f->no;
1526 1
	if (!memIsValid(in, no / 2) ||
1527 1
		!memIsValid(out, 5 * no / 2))
1528 0
		return ERR_BAD_INPUT;
1529 1
	ASSERT(memIsDisjoint2(out, 5 * no / 2, s, objKeep(s)));
1530
	// раскладка стека
1531 1
	Va = objEnd(s, word);
1532 1
	stack = Va + 2 * n;
1533
	// Rb <- beltECBDecr(Yb, K2)
1534 1
	memCopy(s->R + no / 2, in, no / 2);
1535 1
	beltECBStart(stack, s->K2, 32);
1536 1
	beltECBStepD(s->R + no / 2, no / 2, stack);
1537
	// Ra <-R {0, 1}^l
1538 1
	s->settings->rng(out, no / 2, s->settings->rng_state);
1539 1
	memCopy(s->R, out, no / 2);
1540
	// out ||... <- beltECBEncr(Ra, K2)
1541 1
	beltECBStart(stack, s->K2, 32);
1542 1
	beltECBStepE(out, no / 2, stack);
1543
	// W <- bakeSWU(Ra || Rb)
1544 1
	bakeSWU2(s->W, s->ec, s->R, stack);
1545
	// ua <-R {1, 2, ..., q - 1}
1546 1
	if (!zzRandNZMod(s->u, s->ec->order, n, s->settings->rng,
1547
		s->settings->rng_state))
1548 0
		return ERR_BAD_RNG;
1549
	// Va <- ua W
1550 1
	if (!ecMulA(Va, s->W, s->ec, s->u, n, stack))
1551 0
		return ERR_BAD_PARAMS;
1552
	// ...|| out <- <Va>
1553 1
	qrTo(out + no / 2, ecX(Va), s->ec->f, stack);
1554 1
	qrTo(out + 3 * no / 2, ecY(Va, n), s->ec->f, stack);
1555
	// сохранить x-координату Va
1556 1
	memCopy(s->R, out + no / 2, no);
1557
	// все нормально
1558 1
	return ERR_OK;
1559
}
1560

1561 1
static size_t bakeBPACEStep3_deep(size_t n, size_t f_deep, size_t ec_d,
1562
	size_t ec_deep)
1563
{
1564 1
	return O_OF_W(2 * n) +
1565 1
		utilMax(4,
1566
			beltECB_keep(),
1567
			bakeSWU2_deep(n, f_deep, ec_d, ec_deep),
1568
			ecMulA_deep(n, ec_d, ec_deep, n),
1569
			f_deep);
1570
}
1571

1572 1
err_t bakeBPACEStep4(octet out[], const octet in[], void* state)
1573
{
1574 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1575
	size_t n, no;
1576
	// стек
1577
	word* Va;		/* [2 * n] */
1578
	word* K;		/* [2 * n] (совпадает c Va) */
1579
	octet* Y;		/* [32] (совпадает c K) */
1580
	word* Vb;		/* [2 * n] (смещен на n относительно Va) */
1581
	octet* block0;	/* [16] (совпадает с Vb) */
1582
	octet* block1;	/* [16] (следует за block1) */
1583
	void* stack;
1584
	// проверить входные данные
1585 1
	if (!objIsOperable(s))
1586 0
		return ERR_BAD_INPUT;
1587 1
	n = s->ec->f->n, no = s->ec->f->no;
1588 1
	if (!memIsValid(in, 5 * no / 2) ||
1589 1
		!memIsValid(out, 2 * no + (s->settings->kcb ? 8u : 0)))
1590 0
		return ERR_BAD_INPUT;
1591 1
	ASSERT(memIsDisjoint2(out, 2 * no + (s->settings->kcb ? 8u : 0),
1592
		s, objKeep(s)));
1593
	// раскладка стека [Y должен умещаться в no октетов]
1594 1
	Va = K = objEnd(s, word);
1595 1
	Y = (octet*)K;
1596 1
	Vb = K + n;
1597 1
	block0 = (octet*)Vb;
1598 1
	block1 = block0 + 16;
1599 1
	stack = Vb + 2 * n;
1600 1
	ASSERT(32 <= no);
1601
	// Va <- ... || in, Va \in E*?
1602 1
	if (!qrFrom(ecX(Va), in + no / 2, s->ec->f, stack) ||
1603 1
		!qrFrom(ecY(Va, n), in + no / 2 + no, s->ec->f, stack) ||
1604 1
		!ecpIsOnA(Va, s->ec, stack))
1605 0
		return ERR_BAD_POINT;
1606
	// Ra <- beltECBDecr(in ||..., K2)
1607 1
	memCopy(s->R, in, no / 2);
1608 1
	beltECBStart(stack, s->K2, 32);
1609 1
	beltECBStepD(s->R, no / 2, stack);
1610
	// W <- bakeSWU(Ra || Rb)
1611 1
	bakeSWU2(s->W, s->ec, s->R, stack);
1612
	// ub <-R {1, 2, ..., q - 1}
1613 1
	if (!zzRandNZMod(s->u, s->ec->order, n, s->settings->rng,
1614
		s->settings->rng_state))
1615 0
		return ERR_BAD_RNG;
1616
	// K <- ub Va
1617 1
	if (!ecMulA(K, Va, s->ec, s->u, n, stack))
1618 0
		return ERR_BAD_PARAMS;
1619 1
	qrTo((octet*)K, ecX(K), s->ec->f, stack);
1620
	// Vb <- ub W
1621 1
	if (!ecMulA(Vb, s->W, s->ec, s->u, n, stack))
1622 0
		return ERR_BAD_PARAMS;
1623 1
	qrTo((octet*)ecX(Vb), ecX(Vb), s->ec->f, stack);
1624 1
	qrTo((octet*)ecY(Vb, n), ecY(Vb, n), s->ec->f, stack);
1625
	// Y <- beltHash(<K>_2l || <Va>_2l || <Vb>_2l || helloa || hellob)
1626 1
	beltHashStart(stack);
1627 1
	beltHashStepH(K, no, stack);
1628 1
	beltHashStepH(in + no / 2, no, stack);
1629 1
	beltHashStepH(Vb, no, stack);
1630 1
	if (s->settings->helloa)
1631 0
		beltHashStepH(s->settings->helloa, s->settings->helloa_len, stack);
1632 1
	if (s->settings->hellob)
1633 0
		beltHashStepH(s->settings->hellob, s->settings->hellob_len, stack);
1634 1
	beltHashStepG(Y, stack);
1635
	// out ||... <- <Vb>
1636 1
	memCopy(out, ecX(Vb), no);
1637 1
	memCopy(out + no, ecY(Vb, n), no);
1638
	// K0 <- beltKRP(Y, 1^96, 0)
1639 1
	memSetZero(block0, 16);
1640 1
	memSet(block1, 0xFF, 16);
1641 1
	beltKRPStart(stack, Y, 32, block1);
1642 1
	beltKRPStepG(s->K0, 32, block0, stack);
1643
	// K1 <- beltKRP(Y, 1^96, 1)
1644 1
	if (s->settings->kca || s->settings->kcb)
1645
	{
1646 1
		block0[0] = 1;
1647 1
		beltKRPStepG(s->K1, 32, block0, stack);
1648
	}
1649
	// Tb <- beltMAC(1^128, K1), ...|| out <- Tb
1650 1
	if (s->settings->kcb)
1651
	{
1652 1
		beltMACStart(stack, s->K1, 32);
1653 1
		beltMACStepA(block1, 16, stack);
1654 1
		beltMACStepG(out + 2 * no, stack);
1655
	}
1656
	// все нормально
1657 1
	return ERR_OK;
1658
}
1659

1660 1
static size_t bakeBPACEStep4_deep(size_t n, size_t f_deep, size_t ec_d,
1661
	size_t ec_deep)
1662
{
1663 1
	return O_OF_W(3 * n) +
1664 1
		utilMax(7,
1665
			f_deep,
1666
			beltECB_keep(),
1667
			bakeSWU2_deep(n, f_deep, ec_d, ec_deep),
1668
			ecMulA_deep(n, ec_d, ec_deep, n),
1669
			beltHash_keep(),
1670
			beltKRP_keep(),
1671
			beltMAC_keep());
1672
}
1673

1674 1
err_t bakeBPACEStep5(octet out[], const octet in[], void* state)
1675
{
1676 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1677
	size_t n, no;
1678
	// стек
1679
	word* Vb;		/* [2 * n] */
1680
	word* K;		/* [2 * n] (смещен на n относительно Vb) */
1681
	octet* Y;		/* [32] (совпадает c Vb) */
1682
	octet* block0;	/* [16] (следует за Y) */
1683
	octet* block1;	/* [16] (следует за block0) */
1684
	void* stack;
1685
	// проверить входные данные
1686 1
	if (!objIsOperable(s))
1687 0
		return ERR_BAD_INPUT;
1688 1
	n = s->ec->f->n, no = s->ec->f->no;
1689 1
	if (!memIsValid(in, 2 * no + (s->settings->kcb ? 8u : 0)) ||
1690 1
		!memIsValid(out, s->settings->kca ? 8u : 0))
1691 0
		return ERR_BAD_INPUT;
1692 1
	ASSERT(memIsDisjoint2(out, s->settings->kca ? 8u : 0, s, objKeep(s)));
1693
	// раскладка стека [Y || block0 || block1 должны умещаться в 3 * n слов]
1694 1
	Vb = objEnd(s, word);
1695 1
	K = Vb + n;
1696 1
	Y = (octet*)Vb;
1697 1
	block0 = Y + 32;
1698 1
	block1 = block0 + 16;
1699 1
	stack = K + 2 * n;
1700 1
	ASSERT(32 + 16 + 16 <= 3 * no);
1701
	// Vb <- in ||..., Vb \in E*?
1702 1
	if (!qrFrom(ecX(Vb), in, s->ec->f, stack) ||
1703 1
		!qrFrom(ecY(Vb, n), in + no, s->ec->f, stack) ||
1704 1
		!ecpIsOnA(Vb, s->ec, stack))
1705 0
		return ERR_BAD_POINT;
1706
	// K <- ua Vb
1707 1
	if (!ecMulA(K, Vb, s->ec, s->u, n, stack))
1708 0
		return ERR_BAD_PARAMS;
1709 1
	qrTo((octet*)K, ecX(K), s->ec->f, stack);
1710 1
	qrTo((octet*)Vb, ecX(Vb), s->ec->f, stack);
1711
	// Y <- beltHash(<K>_2l || <Va>_2l || <Vb>_2l || helloa || hellob)
1712 1
	beltHashStart(stack);
1713 1
	beltHashStepH(K, no, stack);
1714 1
	beltHashStepH(s->R, no, stack);
1715 1
	beltHashStepH(Vb, no, stack);
1716 1
	if (s->settings->helloa)
1717 0
		beltHashStepH(s->settings->helloa, s->settings->helloa_len, stack);
1718 1
	if (s->settings->hellob)
1719 0
		beltHashStepH(s->settings->hellob, s->settings->hellob_len, stack);
1720 1
	ASSERT(no >= 32);
1721 1
	beltHashStepG(Y, stack);
1722
	// K0 <- beltKRP(Y, 1^96, 0)
1723 1
	memSetZero(block0, 16);
1724 1
	memSet(block1, 0xFF, 16);
1725 1
	beltKRPStart(stack, Y, 32, block1);
1726 1
	beltKRPStepG(s->K0, 32, block0, stack);
1727
	// K1 <- beltKRP(Y, 1^96, 1)
1728 1
	if (s->settings->kca || s->settings->kcb)
1729
	{
1730 1
		block0[0] = 1;
1731 1
		beltKRPStepG(s->K1, 32, block0, stack);
1732
	}
1733
	// Tb == beltMAC(1^128, K1)?
1734 1
	if (s->settings->kcb)
1735
	{
1736 1
		beltMACStart(stack, s->K1, 32);
1737 1
		beltMACStepA(block1, 16, stack);
1738 1
		if (!beltMACStepV(in + 2 * no, stack))
1739 0
			return ERR_BAD_AUTH;
1740
	}
1741
	// Ta <- beltMAC(0^128, K1)
1742 1
	if (s->settings->kca)
1743
	{
1744 1
		block0[0] = 0;
1745 1
		beltMACStart(stack, s->K1, 32);
1746 1
		beltMACStepA(block0, 16, stack);
1747 1
		beltMACStepG(out, stack);
1748
	}
1749
	// все нормально
1750 1
	return ERR_OK;
1751
}
1752

1753 1
static size_t bakeBPACEStep5_deep(size_t n, size_t f_deep, size_t ec_d,
1754
	size_t ec_deep)
1755
{
1756 1
	return O_OF_W(3 * n) +
1757 1
		utilMax(5,
1758
			f_deep,
1759
			ecMulA_deep(n, ec_d, ec_deep, n),
1760
			beltHash_keep(),
1761
			beltKRP_keep(),
1762
			beltMAC_keep());
1763
}
1764

1765 1
err_t bakeBPACEStep6(const octet in[8], void* state)
1766
{
1767 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1768
	// стек
1769
	octet* block0;	/* [16] */
1770
	void* stack;
1771
	// проверить входные данные
1772 1
	if (!objIsOperable(s))
1773 0
		return ERR_BAD_INPUT;
1774 1
	if (!s->settings->kca)
1775 0
		return ERR_BAD_LOGIC;
1776 1
	if (!memIsValid(in, 8))
1777 0
		return ERR_BAD_INPUT;
1778
	// раскладка стека
1779 1
	block0 = objEnd(s, octet);
1780 1
	stack = block0 + 16;
1781
	// Ta == beltMAC(0^128, K1)?
1782 1
	memSetZero(block0, 16);
1783 1
	beltMACStart(stack, s->K1, 32);
1784 1
	beltMACStepA(block0, 16, stack);
1785 1
	if (!beltMACStepV(in, stack))
1786 0
		return ERR_BAD_AUTH;
1787
	// все нормально
1788 1
	return ERR_OK;
1789
}
1790

1791 1
static size_t bakeBPACEStep6_deep(size_t n, size_t f_deep, size_t ec_d,
1792
	size_t ec_deep)
1793
{
1794 1
	return 16 + beltMAC_keep();
1795
}
1796

1797 1
err_t bakeBPACEStepG(octet key[32], void* state)
1798
{
1799 1
	bake_bpace_o* s = (bake_bpace_o*)state;
1800
	// проверить входные данные
1801 1
	if (!objIsOperable(s) ||
1802 1
		!memIsValid(key, 32))
1803 0
		return ERR_BAD_INPUT;
1804
	// key <- K0
1805 1
	memCopy(key, s->K0, 32);
1806
	// все нормально
1807 1
	return ERR_OK;
1808
}
1809

1810 1
static size_t bakeBPACE_deep(size_t n, size_t f_deep, size_t ec_d,
1811
	size_t ec_deep)
1812
{
1813 1
	return utilMax(6,
1814
		bakeBPACEStart_deep(n, f_deep, ec_d, ec_deep),
1815
		bakeBPACEStep2_deep(n, f_deep, ec_d, ec_deep),
1816
		bakeBPACEStep3_deep(n, f_deep, ec_d, ec_deep),
1817
		bakeBPACEStep4_deep(n, f_deep, ec_d, ec_deep),
1818
		bakeBPACEStep5_deep(n, f_deep, ec_d, ec_deep),
1819
		bakeBPACEStep6_deep(n, f_deep, ec_d, ec_deep));
1820
}
1821

1822
/*
1823
*******************************************************************************
1824
Выполнение BPACE
1825
*******************************************************************************
1826
*/
1827

1828 1
err_t bakeBPACERunB(octet key[32], const bign_params* params,
1829
	const bake_settings* settings, const octet pwd[], size_t pwd_len,
1830
	read_i read, write_i write, void* file)
1831
{
1832
	err_t code;
1833
	size_t len;
1834
	// блоб
1835
	blob_t blob;
1836
	octet* in;			/* [5 * l / 8] */
1837
	octet* out;			/* [l / 2 + 8] */
1838
	void* state;		/* [bakeBPACE_keep()] */
1839
	// проверить key
1840 1
	if (!memIsValid(key, 32))
1841 0
		return ERR_BAD_INPUT;
1842
	// создать блоб
1843 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
1844 0
		return ERR_BAD_PARAMS;
1845 1
	blob = blobCreate(9 * params->l / 8 + 8 + bakeBPACE_keep(params->l));
1846 1
	if (blob == 0)
1847 0
		return ERR_OUTOFMEMORY;
1848
	// раскладка блоба
1849 1
	in = (octet*)blob;
1850 1
	out = in + 5 * params->l / 8;
1851 1
	state = out + params->l / 2 + 8;
1852
	// старт
1853 1
	code = bakeBPACEStart(state, params, settings, pwd, pwd_len);
1854 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1855
	// шаг 2
1856 1
	code = bakeBPACEStep2(out, state);
1857 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1858 1
	code = write(&len, out, params->l / 8, file);
1859 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1860
	// шаг 4
1861 1
	code = read(&len, in, 5 * params->l / 8, file);
1862 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1863 1
	code = bakeBPACEStep4(out, in, state);
1864 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1865 1
	code = write(&len, out, params->l / 2 + (settings->kcb ? 8u : 0), file);
1866 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1867
	// шаг 6
1868 1
	if (settings->kca)
1869
	{
1870 1
		code = read(&len, in, 8, file);
1871 1
		ERR_CALL_HANDLE(code, blobClose(blob));
1872 1
		code = bakeBPACEStep6(in, state);
1873 1
		ERR_CALL_HANDLE(code, blobClose(blob));
1874
	}
1875
	// завершение
1876 1
	code = bakeBPACEStepG(key, state);
1877 1
	blobClose(blob);
1878 1
	return code;
1879
}
1880

1881 1
err_t bakeBPACERunA(octet key[32], const bign_params* params,
1882
	const bake_settings* settings, const octet pwd[], size_t pwd_len,
1883
	read_i read, write_i write, void* file)
1884
{
1885
	err_t code;
1886
	size_t len;
1887
	// блоб
1888
	blob_t blob;
1889
	octet* in;			/* [l / 2 + 8] */
1890
	octet* out;			/* [5 * l / 8] */
1891
	void* state;		/* [bakeBPACE_keep()] */
1892
	// проверить key
1893 1
	if (!memIsValid(key, 32))
1894 0
		return ERR_BAD_INPUT;
1895
	// создать блоб
1896 1
	if (params->l != 128 && params->l != 192 && params->l != 256)
1897 0
		return ERR_BAD_PARAMS;
1898 1
	blob = blobCreate(9 * params->l / 8 + 8 + bakeBPACE_keep(params->l));
1899 1
	if (blob == 0)
1900 0
		return ERR_OUTOFMEMORY;
1901
	// раскладка блоба
1902 1
	in = (octet*)blob;
1903 1
	out = in + params->l / 2 + 8;
1904 1
	state = out + 5 * params->l / 8;
1905
	// старт
1906 1
	code = bakeBPACEStart(state, params, settings, pwd, pwd_len);
1907 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1908
	// шаг 3
1909 1
	code = read(&len, in, params->l / 8, file);
1910 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1911 1
	code = bakeBPACEStep3(out, in, state);
1912 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1913 1
	code = write(&len, out, 5 * params->l / 8, file);
1914 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1915
	// шаг 5
1916 1
	code = read(&len, in, params->l / 2 + (settings->kcb ? 8u : 0), file);
1917 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1918 1
	code = bakeBPACEStep5(out, in, state);
1919 1
	ERR_CALL_HANDLE(code, blobClose(blob));
1920 1
	if (settings->kca)
1921
	{
1922 1
		code = write(&len, out, 8, file);
1923 1
		ERR_CALL_HANDLE(code, blobClose(blob));
1924
	}
1925
	// завершение
1926 1
	code = bakeBPACEStepG(key, state);
1927 1
	blobClose(blob);
1928 1
	return code;
1929
}

Read our documentation on viewing source code .

Loading