agievich / bee2
1
/*
2
*******************************************************************************
3
\file bash_f64.c
4
\brief STB 34.101.77 (bash): bash-f
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\author (C) Vlad Semenov [semenov.vlad.by@gmail.com]
8
\created 2014.07.15
9
\version 2019.07.16
10
\license This program is released under the GNU General Public License 
11
version 3. See Copyright Notices in bee2/info.h.
12
*******************************************************************************
13
*/
14

15
#include "bee2/core/blob.h"
16
#include "bee2/core/err.h"
17
#include "bee2/core/mem.h"
18
#include "bee2/core/u64.h"
19
#include "bee2/core/util.h"
20
#include "bee2/crypto/bash.h"
21

22
/*
23
*******************************************************************************
24
Алгоритм bash-s
25

26
\remark На платформе x64 компилятор распознает циклические сдвиги u64RotHi 
27
и задействует команды rol / ror.
28

29
\remark На платформе x64 скорость работы зависит от числа пересылок через 
30
команду mov. Макрос bashS реализован так, чтобы уменьшить число пересылок.
31
Дальнейшие оптимизации связаны с использованием дополнительных 
32
вспомогательных переменных.
33
*******************************************************************************
34
*/
35

36
#define bashS(w0, w1, w2, m1, n1, m2, n2, t0, t1, t2)\
37
	t2 = u64RotHi(w0, m1),\
38
	w0 ^= w1 ^ w2,\
39
	t1 = w1 ^ u64RotHi(w0, n1),\
40
	w1 = t1 ^ t2,\
41
	w2 ^= u64RotHi(w2, m2) ^ u64RotHi(t1, n2),\
42
	t1 = w0 | w2,\
43
	t2 = w0 & w1,\
44
	t0 = ~w2,\
45
	t0 |= w1,\
46
	w0 ^= t0,\
47
	w1 ^= t1,\
48
	w2 ^= t2\
49

50
/*
51
*******************************************************************************
52
Тактовые константы
53

54
Рассчитаны с помощью следующей программы:
55
\code
56
	const u64 A = 0xDC2BE1997FE0D8AE;
57
	u64 C[24];
58
	C[0] = 0x3BF5080AC8BA94B1;
59
	for (size_t t = 1; t < 24; ++t)
60
		C[t] = (C[t - 1] >> 1) ^ (A & 0 - (C[t - 1] & 1));
61
\endcode
62
*******************************************************************************
63
*/
64

65
#define c1  0x3BF5080AC8BA94B1ull
66
#define c2  0xC1D1659C1BBD92F6ull
67
#define c3  0x60E8B2CE0DDEC97Bull
68
#define c4  0xEC5FB8FE790FBC13ull
69
#define c5  0xAA043DE6436706A7ull
70
#define c6  0x8929FF6A5E535BFDull
71
#define c7  0x98BF1E2C50C97550ull
72
#define c8  0x4C5F8F162864BAA8ull
73
#define c9  0x262FC78B14325D54ull
74
#define c10 0x1317E3C58A192EAAull
75
#define c11 0x098BF1E2C50C9755ull
76
#define c12 0xD8EE19681D669304ull
77
#define c13 0x6C770CB40EB34982ull
78
#define c14 0x363B865A0759A4C1ull
79
#define c15 0xC73622B47C4C0ACEull
80
#define c16 0x639B115A3E260567ull
81
#define c17 0xEDE6693460F3DA1Dull
82
#define c18 0xAAD8D5034F9935A0ull
83
#define c19 0x556C6A81A7CC9AD0ull
84
#define c20 0x2AB63540D3E64D68ull
85
#define c21 0x155B1AA069F326B4ull
86
#define c22 0x0AAD8D5034F9935Aull
87
#define c23 0x0556C6A81A7CC9ADull
88
#define c24 0xDE8082CD72DEBC78ull
89

90
/*
91
*******************************************************************************
92
Перестановка P
93

94
Перестановка P переносит слово из позиции P(x) в позицию x.
95

96
Макросы Pi задают действие перестановки P^i. Значение Pi(x) указывает, 
97
какое первоначальное слово будет в позиции x после i тактов.
98

99
\warning Рекурсия P_i(x) = P_1(P_{i - 1}(x)) в VS09 работает только 
100
до глубины 4. Дальше препроцессор не справляется.
101
*******************************************************************************
102
*/
103

104
#define P0(x) x
105

106
#define P1(x)\
107
	((x < 8) ? 8 + (x + 2 * (x & 1) + 7) % 8 :\
108
		((x < 16) ? 8 + (x ^ 1) : (5 * x + 6) % 8))
109

110
#define P2(x) P1(P1(x))
111

112
#define P3(x)\
113
	(8 * (x / 8) + ( x % 8 + 4) % 8)
114

115
#define P4(x) P1(P3(x))
116
#define P5(x) P2(P3(x))
117

118
/*
119
*******************************************************************************
120
Такт
121

122
Макрос p задает расположение входных слов в ячейках массива s перед выполнением 
123
такта i: в ячейке s[x] размещается первоначальное слово номер p(x).
124

125
Макрос p_next задает расположение входных слов перед выполнением такта i + 1.
126
*******************************************************************************
127
*/
128

129
#define bashR(s, p, p_next, i, t0, t1, t2)\
130
	bashS(s[p( 0)], s[p( 8)], s[p(16)],  8, 53, 14,  1, t0, t1, t2);\
131
	bashS(s[p( 1)], s[p( 9)], s[p(17)], 56, 51, 34,  7, t0, t1, t2);\
132
	bashS(s[p( 2)], s[p(10)], s[p(18)],  8, 37, 46, 49, t0, t1, t2);\
133
	bashS(s[p( 3)], s[p(11)], s[p(19)], 56,  3,  2, 23, t0, t1, t2);\
134
	bashS(s[p( 4)], s[p(12)], s[p(20)],  8, 21, 14, 33, t0, t1, t2);\
135
	bashS(s[p( 5)], s[p(13)], s[p(21)], 56, 19, 34, 39, t0, t1, t2);\
136
	bashS(s[p( 6)], s[p(14)], s[p(22)],  8,  5, 46, 17, t0, t1, t2);\
137
	bashS(s[p( 7)], s[p(15)], s[p(23)], 56, 35,  2, 55, t0, t1, t2);\
138
	s[p_next(23)] ^= c##i
139

140
/*
141
*******************************************************************************
142
Bash-f (sponge-функция)
143
*******************************************************************************
144
*/
145

146 1
static void bashF0(u64 s[24])
147
{
148
	register u64 t0;
149
	register u64 t1;
150
	register u64 t2;
151 1
	bashR(s, P0, P1,  1, t0, t1, t2);
152 1
	bashR(s, P1, P2,  2, t0, t1, t2);
153 1
	bashR(s, P2, P3,  3, t0, t1, t2);
154 1
	bashR(s, P3, P4,  4, t0, t1, t2);
155 1
	bashR(s, P4, P5,  5, t0, t1, t2);
156 1
	bashR(s, P5, P0,  6, t0, t1, t2);
157 1
	bashR(s, P0, P1,  7, t0, t1, t2);
158 1
	bashR(s, P1, P2,  8, t0, t1, t2);
159 1
	bashR(s, P2, P3,  9, t0, t1, t2);
160 1
	bashR(s, P3, P4, 10, t0, t1, t2);
161 1
	bashR(s, P4, P5, 11, t0, t1, t2);
162 1
	bashR(s, P5, P0, 12, t0, t1, t2);
163 1
	bashR(s, P0, P1, 13, t0, t1, t2);
164 1
	bashR(s, P1, P2, 14, t0, t1, t2);
165 1
	bashR(s, P2, P3, 15, t0, t1, t2);
166 1
	bashR(s, P3, P4, 16, t0, t1, t2);
167 1
	bashR(s, P4, P5, 17, t0, t1, t2);
168 1
	bashR(s, P5, P0, 18, t0, t1, t2);
169 1
	bashR(s, P0, P1, 19, t0, t1, t2);
170 1
	bashR(s, P1, P2, 20, t0, t1, t2);
171 1
	bashR(s, P2, P3, 21, t0, t1, t2);
172 1
	bashR(s, P3, P4, 22, t0, t1, t2);
173 1
	bashR(s, P4, P5, 23, t0, t1, t2);
174 1
	bashR(s, P5, P0, 24, t0, t1, t2);
175 1
	t0 = t1 = t2 = 0;
176
}
177

178 1
void bashF(octet block[192], void* stack)
179
{
180 1
	u64* s = (u64*)block;
181 1
	ASSERT(memIsDisjoint2(block, 192, stack, bashF_deep()));
182
#if (OCTET_ORDER == BIG_ENDIAN)
183
	u64Rev2(s, 24);
184
#endif
185 1
	bashF0(s);
186
#if (OCTET_ORDER == BIG_ENDIAN)
187
	u64Rev2(s, 24);
188
#endif
189
}
190

191 1
size_t bashF_deep()
192
{
193 1
	return 0;
194
}

Read our documentation on viewing source code .

Loading