agievich / bee2
1
/*
2
*******************************************************************************
3
\file pfok.c
4
\brief Draft of RD_RB: key establishment protocols in finite fields
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2014.07.01
8
\version 2016.09.07
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/prng.h"
18
#include "bee2/core/str.h"
19
#include "bee2/core/util.h"
20
#include "bee2/crypto/pfok.h"
21
#include "bee2/math/pri.h"
22
#include "bee2/math/zm.h"
23
#include "bee2/math/ww.h"
24
#include "bee2/math/zz.h"
25

26
/*
27
*******************************************************************************
28
При генерации параметров pfok требуется находить простые числа, битовая длина 
29
которых лежит в интервале (16, 32]. Для этого используется функция 
30
priNextPrimeVal(), которая находит гарантированно простое число из одного 
31
машинного слова. Функция не подходит, если длина машинного слова равняется 16.
32

33
\todo Поддержать B_PER_W == 16.
34
*******************************************************************************
35
*/
36

37
#if (B_PER_W == 16)
38
	#error "Can't construct small primes"
39
#endif
40

41
/*
42
*******************************************************************************
43
Стандартные размерности
44
*******************************************************************************
45
*/
46
static u32 const _ls[] = 
47
{
48
	638, 702, 766, 862, 958, 1022, 1118, 
49
	1214, 1310, 1438, 1534, 1662, 1790, 1918, 
50
	2046, 2174, 2334, 2462, 2622, 2782, 2942, 
51
};
52

53
static u32 const _rs[] = 
54
{
55
	130, 136, 141, 149, 154, 161, 168,
56
	175, 181, 188, 194, 201, 208, 214,
57
	221, 225, 234, 240, 246, 253, 259, 
58
};
59

60
/*
61
*******************************************************************************
62
Тестовые параметры: методика ИЛ НИИ ППМИ
63
*******************************************************************************
64
*/
65

66
static const u32 _test_params_n = 256;
67

68
static const u16 _test_params_z[] = {
69
	40046, 43788,  1706, 57707, 58664,  8036, 56277, 12802, 
70
	22211, 49982, 39997,  7717,  7896, 18474, 58455,  3341, 
71
	30740, 54550, 18656, 61919, 54929, 55271, 27359, 45417, 
72
	54224, 30379, 40508, 57601, 27245, 54721,  4700,
73
};
74

75
static const char _test_params_name[] = "test";
76

77
static const u32 _test_params_l = 638;
78

79
static const u32 _test_params_r = 130;
80

81
static const octet _test_params_p[] = {
82
	0xDF, 0x60, 0x3F, 0xB4, 0xB1, 0xCB, 0x6B, 0xEB, 
83
	0xBE, 0xB8, 0x47, 0xA8, 0x70, 0x61, 0x37, 0x93,
84
	0x16, 0xAE, 0x3C, 0x66, 0xFA, 0x82, 0x8A, 0x6F,
85
	0x90, 0x05, 0x8A, 0x59, 0xBA, 0xE3, 0xDC, 0x65,
86
	0x80, 0x56, 0xB4, 0x67, 0xAE, 0x55, 0x59, 0x77,
87
	0x11, 0x12, 0x33, 0x3B, 0x0B, 0x3C, 0xF8, 0xF9,
88
	0x77, 0xE9, 0x7F, 0x51, 0xDC, 0xAE, 0x1F, 0x3C,
89
	0x3E, 0x0E, 0x6C, 0xE0, 0xFB, 0xFA, 0xD8, 0x9D,
90
	0x75, 0xB7, 0xF2, 0x4B, 0x3B, 0xE7, 0x37, 0xE1,
91
	0x75, 0xAB, 0xAA, 0x86, 0xAB, 0x91, 0xF7, 0x2A,
92
};
93

94
static const octet _test_params_g[] = {
95
	0xEA, 0x36, 0x50, 0x71, 0xE2, 0x10, 0x2E, 0x77,
96
	0x59, 0xB7, 0x21, 0x16, 0x69, 0xBC, 0xD6, 0x11,
97
	0xF6, 0x80, 0x58, 0x9A, 0x2B, 0x0E, 0xF9, 0xDC,
98
	0x96, 0x51, 0xF0, 0x0E, 0x85, 0xB0, 0x21, 0x8E,
99
	0xBD, 0xC1, 0xB1, 0xCC, 0x43, 0xF5, 0xD1, 0x12,
100
	0x8E, 0xDD, 0xA8, 0x19, 0x8D, 0xE7, 0x21, 0x5E,
101
	0x01, 0xF0, 0x6D, 0x2E, 0x3C, 0x35, 0x3B, 0xBA,
102
	0x7C, 0x99, 0x27, 0x45, 0x2F, 0x7F, 0x47, 0x50,
103
	0x28, 0x73, 0x4F, 0x54, 0x0A, 0xE9, 0x24, 0xDF,
104
	0xB8, 0x81, 0x33, 0xC5, 0x97, 0xD3, 0x43, 0x2A,
105
};
106

107
static const u32 _test_params_lt[] = {
108
	637, 319, 160, 81, 41, 21,
109
};
110

111
/*
112
*******************************************************************************
113
Стандартные параметры: приложение В к СТБ П 34.101.50
114
*******************************************************************************
115
*/
116

117
// bdh-params (common)
118
static const u32 _bdh_params_n = 256;
119

120
static const u16 _bdh_params_z[] = {
121
	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 
122
	18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
123
};
124

125
// bdh-params3
126
static const char _bdh_params3_name[] = "1.2.112.0.2.0.1176.2.3.3.2";
127

128
static const u32 _bdh_params3_l = 1022;
129

130
static const u32 _bdh_params3_r = 161;
131

132
static const octet _bdh_params3_p[] = {
133
	0x6F, 0x5E, 0xBE, 0x31, 0xD7, 0x55, 0x76, 0x17,
134
	0x84, 0x3F, 0xC5, 0xAB, 0x4E, 0xC7, 0x67, 0xE0,
135
	0x6E, 0x42, 0xDE, 0xEA, 0x2C, 0x82, 0xBE, 0x7B,
136
	0x3F, 0xEA, 0xCB, 0xEC, 0xC4, 0x17, 0x07, 0x65,
137
	0x27, 0xB6, 0x04, 0xBF, 0xA6, 0x67, 0xE5, 0x2C,
138
	0x48, 0xD2, 0x19, 0xEC, 0xAB, 0x83, 0x16, 0x72,
139
	0x4F, 0x0B, 0xAB, 0x80, 0xD8, 0x10, 0x27, 0xB6,
140
	0x9C, 0x80, 0xB7, 0xE8, 0xA2, 0x14, 0xAB, 0x94,
141
	0x0E, 0x24, 0x0C, 0x05, 0x98, 0x9B, 0xC1, 0x4B,
142
	0xEE, 0x10, 0x05, 0x2B, 0xE7, 0xC2, 0x68, 0x78,
143
	0xAB, 0xE9, 0xEB, 0x51, 0x27, 0xCB, 0x9D, 0xA6,
144
	0x48, 0x6A, 0x7E, 0x5E, 0x5D, 0x1E, 0xFE, 0x77,
145
	0x66, 0xE5, 0x87, 0x6E, 0x34, 0x98, 0x66, 0x74,
146
	0x64, 0x3E, 0xB8, 0x42, 0x93, 0xE6, 0xE3, 0x4E,
147
	0x78, 0x9E, 0x50, 0x8B, 0x8C, 0x8C, 0xAF, 0x80,
148
	0xA4, 0x66, 0xF6, 0x38, 0xC5, 0x17, 0x96, 0x33,
149
};
150

151
static const octet _bdh_params3_g[] = {
152
	0x69, 0x4D, 0x08, 0xFB, 0x1D, 0x37, 0x1A, 0x1B,
153
	0x5C, 0xFB, 0x53, 0x95, 0xCD, 0x61, 0xCB, 0xE4,
154
	0x2E, 0x88, 0xFB, 0xA5, 0xEE, 0x3C, 0xC6, 0x03,
155
	0xFA, 0x45, 0x14, 0x99, 0x16, 0xB6, 0xCA, 0xD7,
156
	0xA6, 0xEC, 0x80, 0x2F, 0x64, 0x0A, 0x7D, 0x7A,
157
	0xEA, 0x41, 0x81, 0x6A, 0x02, 0x0C, 0x60, 0x9A,
158
	0xE7, 0x2B, 0xF0, 0xC3, 0xC3, 0xE1, 0x7D, 0xD4,
159
	0x13, 0x78, 0xEB, 0x85, 0xC2, 0xFF, 0xE6, 0xC7,
160
	0x39, 0x5F, 0x46, 0x80, 0xB5, 0x56, 0x98, 0xAC,
161
	0x25, 0xE7, 0xCE, 0x34, 0xA4, 0x49, 0x83, 0x54,
162
	0xF3, 0xE6, 0x72, 0xC2, 0x8B, 0xE4, 0x8C, 0xCD,
163
	0xD8, 0x4C, 0x82, 0x58, 0x1F, 0x54, 0x17, 0xFF,
164
	0x6C, 0x5E, 0x06, 0x18, 0xC4, 0x80, 0x58, 0x67,
165
	0x3B, 0xB5, 0x10, 0x0F, 0xA3, 0x11, 0x87, 0x69,
166
	0xD8, 0xD3, 0xEE, 0xA2, 0xA0, 0xBC, 0x0D, 0x69,
167
	0xC8, 0xFE, 0xDC, 0x50, 0xD3, 0x3A, 0x2A, 0x32,
168
};
169

170
static const u32 _bdh_params3_lt[] = {
171
	1021, 511, 256, 129, 65, 33, 17,
172
};
173

174
// bdh-params6
175
static const char _bdh_params6_name[] = "1.2.112.0.2.0.1176.2.3.6.2";
176

177
static const u32 _bdh_params6_l = 1534;
178

179
static const u32 _bdh_params6_r = 194;
180

181
static const octet _bdh_params6_p[] = {
182
	0xC7, 0x51, 0x14, 0x7B, 0xED, 0x69, 0xF4, 0x2D,
183
	0x32, 0x5F, 0xB1, 0x45, 0x0A, 0x66, 0xAF, 0xA5,
184
	0x34, 0xE1, 0xBF, 0x35, 0x42, 0xCB, 0xBF, 0x36,
185
	0xB5, 0x14, 0x2E, 0xF6, 0x64, 0x17, 0xF5, 0x2D,
186
	0x42, 0x2E, 0x3F, 0x7A, 0x35, 0x7E, 0xF2, 0xAC,
187
	0x1B, 0xBF, 0xB8, 0xAA, 0xA7, 0x69, 0xB1, 0xF0,
188
	0x49, 0x1B, 0x46, 0x61, 0xFA, 0x8F, 0xE0, 0xC7,
189
	0x0F, 0x40, 0x94, 0xF8, 0x28, 0x73, 0x19, 0xFA,
190
	0x2E, 0x95, 0x40, 0x05, 0x22, 0xC8, 0x85, 0xD9,
191
	0x3B, 0x70, 0x0F, 0x58, 0x1B, 0xBE, 0xC1, 0xDC,
192
	0x4C, 0xC7, 0xEC, 0xCF, 0xB4, 0x3C, 0x04, 0x79,
193
	0x3A, 0x25, 0x9A, 0x2E, 0x6F, 0xFA, 0x3E, 0x8C,
194
	0x1A, 0x06, 0xA8, 0x9F, 0x96, 0x88, 0x38, 0xBB,
195
	0x74, 0xA5, 0x77, 0xC3, 0x0D, 0x09, 0x57, 0x45,
196
	0x74, 0x08, 0x97, 0x44, 0xA1, 0xF4, 0x7C, 0xE0,
197
	0x98, 0x85, 0xD2, 0x46, 0x24, 0x82, 0x1D, 0xA0,
198
	0xAD, 0x39, 0xE6, 0x77, 0xF4, 0x5C, 0x00, 0xE0,
199
	0x9E, 0x92, 0x06, 0x6B, 0x2B, 0xAD, 0xE0, 0xCB,
200
	0x66, 0xD2, 0x02, 0xCC, 0xAD, 0x51, 0xEB, 0xE1,
201
	0x1F, 0xE9, 0x4D, 0xB1, 0x30, 0x65, 0xBF, 0xBB,
202
	0x94, 0x55, 0xE7, 0x58, 0x61, 0xAA, 0x78, 0x78,
203
	0x1C, 0x5E, 0x6C, 0xB5, 0x88, 0xCA, 0x4E, 0xD5,
204
	0x50, 0x3A, 0xDF, 0x8C, 0xD4, 0x4B, 0x05, 0x2D,
205
	0xA5, 0xF5, 0xA9, 0x6B, 0x50, 0x1F, 0x7C, 0x39,
206
};
207

208
static const octet _bdh_params6_g[] = {
209
	0xB2, 0x85, 0x48, 0xF3, 0x48, 0xEB, 0xE7, 0x5A,
210
	0xBD, 0x23, 0xCE, 0x48, 0xB7, 0x2E, 0x92, 0xC5,
211
	0x78, 0x0F, 0x74, 0xC2, 0xD7, 0xDF, 0x35, 0x1D,
212
	0x76, 0x31, 0x54, 0x3F, 0xEE, 0x2C, 0x40, 0xB4,
213
	0xE2, 0x9B, 0x5E, 0x7B, 0x94, 0xF9, 0x34, 0xD8,
214
	0xA1, 0xD8, 0x71, 0x5E, 0x25, 0xC5, 0x21, 0xE4,
215
	0xCE, 0xFC, 0xA4, 0x13, 0x22, 0xDF, 0x78, 0x8C,
216
	0x6A, 0x71, 0xFD, 0x64, 0x4E, 0xE5, 0x74, 0x60,
217
	0x1B, 0xCC, 0x01, 0xEC, 0x99, 0xF6, 0xCE, 0x18,
218
	0xE2, 0x53, 0x4D, 0xA0, 0xA6, 0x85, 0x4B, 0xF6,
219
	0xC8, 0xC6, 0xF9, 0xB0, 0x59, 0x3E, 0x31, 0x3A,
220
	0x1A, 0x20, 0x6D, 0xB7, 0xB7, 0xC6, 0x54, 0x45,
221
	0xA3, 0x00, 0xB1, 0x33, 0x06, 0x09, 0x2B, 0x97,
222
	0x0D, 0xD7, 0x98, 0xC7, 0x32, 0x15, 0xC5, 0x3A,
223
	0x97, 0xD3, 0xB4, 0xAF, 0xE1, 0xF9, 0x25, 0x08,
224
	0xD1, 0xE5, 0x22, 0x13, 0x56, 0xAD, 0x88, 0xD2,
225
	0xCD, 0xA0, 0xD7, 0x73, 0xD9, 0x62, 0x76, 0xC1,
226
	0x47, 0x50, 0xBF, 0x1E, 0xD8, 0x7D, 0x58, 0x8B,
227
	0xC7, 0xC5, 0x47, 0xEE, 0xB7, 0x57, 0xA9, 0xC3,
228
	0xAF, 0x25, 0xC8, 0x7B, 0x8F, 0x13, 0x3A, 0x3C,
229
	0xFD, 0x6F, 0x7D, 0xEE, 0x66, 0xF7, 0xD0, 0x9A,
230
	0xCC, 0xA7, 0xCB, 0xB3, 0x0B, 0x4D, 0xDA, 0x41,
231
	0xB4, 0x21, 0x84, 0xF9, 0xBD, 0xF4, 0xE3, 0x6B,
232
	0xEF, 0x90, 0x3E, 0x5E, 0xB6, 0xA8, 0xE7, 0x24,
233
};
234

235
static const u32 _bdh_params6_lt[] = {
236
	1533, 767, 384, 193, 97, 49, 25,
237
};
238

239
// bdh-params10
240
static const char _bdh_params10_name[] = "1.2.112.0.2.0.1176.2.3.10.2";
241

242
static const u32 _bdh_params10_l = 2462;
243

244
static const u32 _bdh_params10_r = 240;
245

246
static const octet _bdh_params10_p[] = {
247
	0xDB, 0x80, 0x4A, 0x65, 0x29, 0x2D, 0x15, 0x9C,
248
	0x56, 0xF9, 0x99, 0x47, 0x65, 0xAE, 0x74, 0xFC,
249
	0xE1, 0xE8, 0x0C, 0x12, 0x3E, 0x82, 0xBB, 0x75,
250
	0x20, 0xE2, 0x33, 0x17, 0xD8, 0x03, 0xA6, 0x6A,
251
	0x90, 0x8C, 0x5E, 0x94, 0x39, 0x65, 0x08, 0xA6,
252
	0x92, 0x7F, 0x4A, 0xC6, 0x38, 0x33, 0xDF, 0x8E,
253
	0xA6, 0x1A, 0x08, 0x23, 0xB8, 0x29, 0xFA, 0x3A,
254
	0x33, 0xC6, 0xC8, 0x27, 0x58, 0xA4, 0xFE, 0x4D,
255
	0xED, 0x1F, 0xDE, 0x37, 0x36, 0x84, 0x93, 0x68,
256
	0x0B, 0x68, 0xE6, 0xA9, 0x5E, 0x07, 0xBF, 0x1C,
257
	0xE0, 0x16, 0xAE, 0x73, 0xAE, 0x92, 0xAD, 0x2D,
258
	0x0D, 0xC4, 0xE0, 0xF5, 0x39, 0x7B, 0x41, 0xF1,
259
	0xFC, 0xBA, 0x14, 0x09, 0x8F, 0xA0, 0xFD, 0x21,
260
	0x05, 0xB0, 0xD3, 0x8E, 0x63, 0xB5, 0x2F, 0x3A,
261
	0xDE, 0x4B, 0x20, 0x36, 0xC3, 0xEC, 0xCD, 0x9A,
262
	0xEF, 0x52, 0xE4, 0xA8, 0x56, 0x13, 0x00, 0xC4,
263
	0xD5, 0x3C, 0x9A, 0x37, 0x08, 0x5B, 0xE9, 0xF8,
264
	0x52, 0xBF, 0x29, 0xF4, 0x97, 0x85, 0x64, 0x42,
265
	0x69, 0x45, 0x50, 0x41, 0xE6, 0x47, 0x56, 0xFF,
266
	0xA6, 0xA3, 0xB2, 0xD9, 0x75, 0x9B, 0x01, 0x0C,
267
	0x11, 0xDD, 0x63, 0xE1, 0x5F, 0x2E, 0x46, 0xA8,
268
	0xD1, 0xA1, 0x36, 0x39, 0xC1, 0xA3, 0x6F, 0x51,
269
	0xB4, 0xB9, 0xF6, 0x53, 0x26, 0x9F, 0xF9, 0xDC,
270
	0xF2, 0x11, 0x27, 0x4E, 0xC1, 0x70, 0xF4, 0x1F,
271
	0xEE, 0x33, 0x74, 0xAF, 0x40, 0xAE, 0x58, 0xA3,
272
	0x5B, 0xD0, 0xAB, 0x66, 0x7F, 0x26, 0x39, 0x51,
273
	0xDF, 0xB6, 0x8B, 0xB6, 0xF0, 0xAD, 0xB1, 0xE5,
274
	0x3B, 0x02, 0x72, 0xB7, 0x8E, 0xA4, 0xD7, 0xF6,
275
	0x2D, 0x05, 0x38, 0x3D, 0xE5, 0x34, 0x8D, 0x21,
276
	0x87, 0x23, 0x7D, 0xEB, 0xA1, 0x3D, 0xF3, 0x22,
277
	0xDA, 0xF1, 0xE4, 0x2D, 0xCF, 0x42, 0x69, 0x1C,
278
	0x96, 0x54, 0x10, 0x16, 0xB1, 0xF4, 0xEA, 0x94,
279
	0x9C, 0xED, 0x31, 0x46, 0x7F, 0x8F, 0x1F, 0x93,
280
	0x9B, 0x59, 0x4A, 0x69, 0xEC, 0x92, 0x92, 0x9B,
281
	0xA9, 0xB6, 0x0A, 0xD8, 0x3A, 0xED, 0x0F, 0x23,
282
	0x08, 0x8C, 0xDD, 0xA0, 0x12, 0xAD, 0xC0, 0x26,
283
	0xEE, 0x65, 0xC3, 0xD0, 0x38, 0x6B, 0x20, 0xAA,
284
	0xA0, 0x13, 0x8F, 0xAF, 0x6F, 0xC2, 0x81, 0xEA,
285
	0x85, 0xF4, 0xA8, 0x20,
286
};
287

288
static const octet _bdh_params10_g[] = {
289
	0x14, 0xE1, 0x96, 0x49, 0x7C, 0x27, 0xCD, 0x04, 
290
	0x2E, 0xF3, 0x32, 0x7B, 0x74, 0x12, 0x2C, 0xDE,
291
	0x04, 0xF8, 0xE6, 0x30, 0x2E, 0xB5, 0x25, 0x2A, 
292
	0x39, 0xBC, 0x4A, 0x90, 0xD7, 0xE0, 0x98, 0x97,
293
	0xF9, 0xF4, 0xFD, 0xFD, 0x97, 0x96, 0xBF, 0xD7, 
294
	0x50, 0xA9, 0x51, 0x74, 0x6D, 0x40, 0xA0, 0xD7,
295
	0x5F, 0x6A, 0xC6, 0x10, 0x3B, 0xAF, 0xB8, 0x51, 
296
	0xDA, 0xD5, 0x19, 0x0F, 0xD9, 0x66, 0xF4, 0x4E,
297
	0xA6, 0x96, 0x5C, 0x33, 0x38, 0x88, 0xA6, 0x9B, 
298
	0x80, 0xCE, 0x13, 0xAE, 0xBF, 0x87, 0x63, 0x44,
299
	0xF4, 0x6E, 0x44, 0x6D, 0x7C, 0x96, 0x32, 0x3B, 
300
	0xD9, 0xDD, 0x64, 0x84, 0xE2, 0x30, 0x5E, 0x94,
301
	0x19, 0x9C, 0x67, 0xC4, 0xFB, 0xB7, 0x53, 0x38, 
302
	0x57, 0x55, 0xD5, 0x94, 0x7A, 0x08, 0xD6, 0x48,
303
	0xA9, 0x7A, 0xF8, 0x74, 0xF4, 0x03, 0x6A, 0x01, 
304
	0x67, 0x2E, 0xEB, 0x54, 0x9F, 0x04, 0xF7, 0xB5,
305
	0x0A, 0xCF, 0x6D, 0xAA, 0x7C, 0x7E, 0x70, 0x96, 
306
	0x32, 0xBA, 0x20, 0x16, 0x65, 0xB4, 0x6A, 0xFC,
307
	0xB6, 0xDD, 0xC4, 0x58, 0x8A, 0xB0, 0x1B, 0x3A, 
308
	0x09, 0xC7, 0xD9, 0x7B, 0x67, 0x96, 0xEF, 0x0A,
309
	0x94, 0x38, 0x17, 0x4C, 0xF1, 0x11, 0x8F, 0x8C,
310
	0xCC, 0x6F, 0x27, 0x95, 0x9A, 0x7C, 0x9A, 0xC2,
311
	0xC0, 0x92, 0x3B, 0x87, 0x00, 0xB9, 0xAE, 0x1F,
312
	0x2B, 0xE6, 0xB3, 0xDD, 0xB5, 0xDB, 0xC8, 0x5A,
313
	0x6C, 0xD2, 0x3F, 0xE3, 0x69, 0x41, 0xCD, 0x1E,
314
	0x04, 0x6A, 0x6C, 0x48, 0x71, 0x22, 0x82, 0xAB,
315
	0xD4, 0x52, 0x55, 0x4F, 0x84, 0xF5, 0x96, 0x13,
316
	0x9F, 0xBA, 0xBB, 0x67, 0x8D, 0x39, 0x26, 0xE5,
317
	0x58, 0x4E, 0x4C, 0x28, 0x0C, 0x18, 0xB2, 0xC2,
318
	0x49, 0xF2, 0x35, 0x91, 0x03, 0x9E, 0x46, 0xA9,
319
	0x86, 0xA8, 0x29, 0x8D, 0x76, 0x52, 0x57, 0x97,
320
	0x7C, 0x54, 0x0F, 0x11, 0x23, 0x88, 0x3D, 0x87,
321
	0xC9, 0x2B, 0x34, 0x7E, 0xB9, 0x41, 0x02, 0xD9,
322
	0xA5, 0x0A, 0xE6, 0x0C, 0x10, 0x8D, 0x3E, 0x61,
323
	0x73, 0x3D, 0x41, 0x6D, 0x82, 0x8E, 0x8F, 0x84,
324
	0x96, 0xAD, 0x42, 0x9A, 0x75, 0xB6, 0xE2, 0x26,
325
	0x95, 0xF1, 0x79, 0xED, 0x94, 0x4B, 0x2E, 0x44,
326
	0x01, 0x06, 0x45, 0x62, 0x57, 0x39, 0xC2, 0xFA,
327
	0xE5, 0x64, 0x83, 0x03,
328
};
329

330
static const u32 _bdh_params10_lt[] = {
331
	2461, 1231, 616, 309, 155, 78, 40, 21,
332
};
333

334
/*
335
*******************************************************************************
336
Загрузка стандартных параметров
337
*******************************************************************************
338
*/
339

340 1
err_t pfokStdParams(pfok_params* params, pfok_seed* seed, const char* name)
341
{
342 1
	if (!memIsValid(params, sizeof(pfok_params)) ||
343 1
		!memIsNullOrValid(seed, sizeof(pfok_seed)))
344 0
		return ERR_BAD_INPUT;
345
	// подготовить params
346 1
	memSetZero(params, sizeof(pfok_params));
347
	// найти params
348 1
	if (strEq(name, _test_params_name))
349
	{
350 1
		params->l = _test_params_l;
351 1
		params->r = _test_params_r;
352 1
		params->n = _test_params_n;
353 1
		memCopy(params->p, _test_params_p, sizeof(_test_params_p));
354 1
		memCopy(params->g, _test_params_g, sizeof(_test_params_g));
355 1
		if (seed)
356
		{
357 1
			memCopy(seed->z, _test_params_z, sizeof(_test_params_z));
358 1
			memCopy(seed->lt, _test_params_lt, sizeof(_test_params_lt));
359
		}
360 1
		return ERR_OK;
361
	}
362 1
	if (strEq(name, _bdh_params3_name))
363
	{
364 1
		params->l = _bdh_params3_l;
365 1
		params->r = _bdh_params3_r;
366 1
		params->n = _bdh_params_n;
367 1
		memCopy(params->p, _bdh_params3_p, sizeof(_bdh_params3_p));
368 1
		memCopy(params->g, _bdh_params3_g, sizeof(_bdh_params3_g));
369 1
		if (seed)
370
		{
371 0
			memCopy(seed->z, _bdh_params_z, sizeof(_bdh_params_z));
372 0
			memCopy(seed->lt, _bdh_params3_lt, sizeof(_bdh_params3_lt));
373
		}
374 1
		return ERR_OK;
375
	}
376 1
	if (strEq(name, _bdh_params6_name))
377
	{
378 1
		params->l = _bdh_params6_l;
379 1
		params->r = _bdh_params6_r;
380 1
		params->n = _bdh_params_n;
381 1
		memCopy(params->p, _bdh_params6_p, sizeof(_bdh_params6_p));
382 1
		memCopy(params->g, _bdh_params6_g, sizeof(_bdh_params6_g));
383 1
		if (seed)
384
		{
385 0
			memCopy(seed->z, _bdh_params_z, sizeof(_bdh_params_z));
386 0
			memCopy(seed->lt, _bdh_params6_lt, sizeof(_bdh_params6_lt));
387
		}
388 1
		return ERR_OK;
389
	}
390 1
	if (strEq(name, _bdh_params10_name))
391
	{
392 1
		params->l = _bdh_params10_l;
393 1
		params->r = _bdh_params10_r;
394 1
		params->n = _bdh_params_n;
395 1
		memCopy(params->p, _bdh_params10_p, sizeof(_bdh_params10_p));
396 1
		memCopy(params->g, _bdh_params10_g, sizeof(_bdh_params10_g));
397 1
		if (seed)
398
		{
399 0
			memCopy(seed->z, _bdh_params_z, sizeof(_bdh_params_z));
400 0
			memCopy(seed->lt, _bdh_params10_lt, sizeof(_bdh_params10_lt));
401
		}
402 1
		return ERR_OK;
403
	}
404 0
	return ERR_FILE_NOT_FOUND;
405
}
406

407
/*
408
*******************************************************************************
409
Работоспособные параметры?
410

411
Не проверяется простота p и q и примитивность g. Проверяется только то, что
412
1)	битовая длина p равняется l;
413
2)	p \equiv 3 \mod 4;
414
3)	0 < g < p.
415
*******************************************************************************
416
*/
417

418 1
static bool_t pfokIsOperableParams(const pfok_params* params)
419
{
420
	size_t n;
421 1
	ASSERT(memIsValid(params, sizeof(pfok_params)));
422
	// проверить размерности
423 1
	for (n = 0; n < COUNT_OF(_ls); ++n)
424 1
		if (_ls[n] == params->l)
425 1
			break;
426 1
	if (n == COUNT_OF(_ls) || _rs[n] != params->r || params->n >= params->l)
427 0
		return FALSE;
428
	// проверить p (младшие два бита -- 11? старшие 3 бита -- 001?)
429 1
	ASSERT((params->l + 2) % 8 == 0);
430 1
	n = O_OF_B(params->l);
431 1
	if (params->p[0] % 4 != 3 || params->p[n - 1] / 32 != 1)
432 0
		return FALSE;
433
	// проверить g
434 1
	return !memIsZero(params->g, n) && memCmp(params->g, params->p, n) < 0;
435
}
436

437
/*
438
*******************************************************************************
439
Генерация параметров
440

441
Строится число q битовой длины l - 1, а затем проверяется, что p = 2q + 1
442
является простым. Если p составное, то строится новое q и так далее. 
443
Подходящее простое q называется простым Софи Жермен.
444

445
\remark Известна эвристика: имеется \approx 1.32 n / (\log n)^2 простых Жермен,
446
не превосходящих n. С другой стороны, имеется \approx n / \log n простых, 
447
не превосходящих n. Поэтому случайное простое q, не превосходящее n, 
448
окажется простым Жермен с вероятностью близкой к 1.32 / \log n. 
449
Отсюда среднее число кандидатов q:
450
\log n / 1.32 \approx 0.52 l. 
451

452
Статистика генерации стандартных параметров:
453
------------------------------------------------------------------
454
параметры                     | l    | число кандидатов  | оценка
455
------------------------------------------------------------------
456
"test"                        | 638  | 6                 | 332   
457
"1.2.112.0.2.0.1176.2.3.3.2"  | 1022 | 582               | 531
458
"1.2.112.0.2.0.1176.2.3.6.2"  | 1534 | 274               | 798  
459
"1.2.112.0.2.0.1176.2.3.10.2" | 2462 | 415               | 1280 
460
------------------------------------------------------------------
461

462
Проверка примитивности g:
463
g^(q) \neq e => g^(q) == - e
464
g^(2) \neq e => g == e или g == -e
465
*******************************************************************************
466
*/
467

468 1
err_t pfokGenParams(pfok_params* params, const pfok_seed* seed, 
469
	pfok_on_q_i on_q)
470
{
471 1
	size_t num = 0;
472
	size_t i;
473
	size_t no, n;
474
	size_t offset;
475
	const u32* lt;
476
	// состояние 
477
	void* state;
478
	octet* stb_state;
479
	word* qi;
480
	word* p;
481
	word* g;
482
	qr_o* qr;
483
	void* stack;
484
	// проверить указатели
485 1
	if (!memIsValid(params, sizeof(pfok_params)) ||
486 1
		!memIsValid(seed, sizeof(pfok_seed)))
487 0
		return ERR_BAD_INPUT;
488
	// подготовить params
489 1
	memSetZero(params, sizeof(pfok_params));
490
	// проверить числа z[i]
491 1
	for (i = 0; i < 31; ++i)
492 1
		if (seed->z[i] == 0 || seed->z[i] >= 65257)
493 0
			return ERR_BAD_PARAMS;
494
	// проверить цепочку lt[i] и одновременно зафиксировать размерности
495 1
	for (i = 0, lt = seed->lt; i < COUNT_OF(_ls); ++i)
496 1
		if (lt[0] == _ls[i] - 1)
497 1
			break;
498 1
	if (i == COUNT_OF(_ls))
499 0
		return ERR_BAD_PARAMS;
500 1
	params->l = _ls[i], params->r = _rs[i], params->n = 256;
501 1
	for (i = 1, offset = W_OF_B(lt[0]); lt[i] > 32; ++i)
502
	{
503 1
		if (lt[i - 1] > 2 * lt[i] || 5 * lt[i] + 16 >= 4 * lt[i - 1])
504 0
			return ERR_BAD_PARAMS;
505 1
		offset += W_OF_B(lt[i]);
506
	}
507 1
	ASSERT(lt[i] > 16);
508
	// размерности
509 1
	no = O_OF_B(params->l), n = W_OF_B(params->l);
510
	// создать состояние
511 1
	state = blobCreate(
512 1
		prngSTB_keep() + O_OF_W(offset) + O_OF_B(lt[i]) + 
513 1
		O_OF_W(n) +	zmMontCreate_keep(no) +
514 1
		utilMax(6,
515
			priNextPrimeW_deep(),
516 1
			priExtendPrime_deep(params->l, n, (lt[0] + 3) / 4),
517 1
			priIsSieved_deep((lt[0] + 3) / 4),
518
			priIsSGPrime_deep(n),
519
			zmMontCreate_deep(no), 
520
			qrPower_deep(n, n, zmMontCreate_deep(no))));
521 1
	if (state == 0)
522 0
		return ERR_OUTOFMEMORY;
523
	// раскладка состояния
524 1
	stb_state = (octet*)state;
525 1
	qi = (word*)(stb_state + prngSTB_keep());
526 1
	p = qi + offset + W_OF_B(lt[i]);
527 1
	qr = (qr_o*)(p + n);
528 1
	stack = (octet*)qr + zmMontCreate_keep(no);
529
	// запустить генератор
530 1
	prngSTBStart(stb_state, seed->z);
531
	// основной цикл
532
	while (1)
533
	{
534
		// первое (минимальное) простое?
535 1
		if (lt[i] <= 32)
536
		{
537
			do
538
			{
539 1
				prngSTBStepR(qi + offset, O_OF_B(lt[i]), stb_state);
540 1
				wwTrimHi(qi + offset, W_OF_B(lt[i]), lt[i] - 1);
541 1
				wwSetBit(qi + offset, lt[i] - 1, 1);
542
			}
543 1
			while (!priNextPrimeW(qi + offset, qi[offset], stack));
544
			// к следующему простому
545 1
			offset -= W_OF_B(lt[--i]);
546
		}
547
		// обычное простое
548
		else
549
		{
550 1
			size_t trials = (i == 0) ? 4 * lt[i] * lt[i] : 4 * lt[i];
551 1
			size_t base_count = (lt[i] + 3) / 4;
552
			// потенциальное отступление от Проекта, не влияющее на результат
553 1
			if (base_count > priBaseSize())
554 0
				base_count = priBaseSize();
555
			// не удается построить новое простое?
556 1
			if (!priExtendPrime(qi + offset, lt[i], 
557 1
					qi + offset + W_OF_B(lt[i]), W_OF_B(lt[i + 1]), 
558
					trials, base_count, prngSTBStepR, stb_state, stack))
559
			{
560
				// к предыдущему простому
561 0
				offset += W_OF_B(lt[i++]);
562 0
				continue;
563
			}
564
			// не последнее простое?
565 1
			if (i > 0)
566
			{
567
				// к следующему простому
568 1
				offset -= W_OF_B(lt[--i]);
569 1
				continue;
570
			}
571
			// обработать нового кандидата
572 1
			on_q ? on_q(qi, W_OF_B(lt[0]), ++num) : 0;
573
			// p <- 2q_0 + 1
574 1
			ASSERT(W_OF_B(lt[0]) == n);
575 1
			wwCopy(p, qi, n);
576 1
			wwShHi(p, n, 1);
577 1
			p[0] |= 1;
578
			// p -- простое?
579 1
			if (priIsSieved(p, n, base_count, stack) && 
580 1
				priIsSGPrime(qi, n, stack))
581 1
				break;
582
		}
583
	}
584
	// сохранить p
585 1
	wwTo(params->p, no, p);
586
	// построить кольцо Монтгомери
587 1
	zmMontCreate(qr, params->p, no, params->l + 2, stack);
588
	// сгенерировать g
589 1
	g = qi + W_OF_B(lt[0]);
590
	do
591
	{
592
		// g <- g + 1
593 1
		for (i = 0; i < no && ++params->g[i] == 0;);
594
		// p <- g^(q) [p == e или p == -e]
595 1
		qrFrom(g, params->g, qr, stack);
596 1
		qrPower(p, g, qi, W_OF_B(lt[0]), qr, stack);
597
	}
598 1
	while (qrIsUnity(p, qr) || qrIsUnity(g, qr) || qrCmp(p, g, qr) == 0);
599
	// все нормально
600 1
	blobClose(state);
601 1
	return ERR_OK;
602
}
603

604 1
err_t pfokValParams(const pfok_params* params)
605
{
606
	size_t no, n;
607
	// состояние 
608
	void* state;
609
	word* p;
610
	word* g;
611
	qr_o* qr;
612
	void* stack;
613
	// проверить указатели
614 1
	if (!memIsValid(params, sizeof(pfok_params)))
615 0
		return ERR_BAD_INPUT;
616
	// работоспособные параметры?
617 1
	if (!pfokIsOperableParams(params))
618 0
		return ERR_BAD_PARAMS;
619
	// размерности
620 1
	no = O_OF_B(params->l), n = W_OF_B(params->l);
621
	// создать состояние
622 1
	state = blobCreate(
623 1
		2 * O_OF_W(n) + zmMontCreate_keep(no) +  
624 1
		utilMax(3,
625
			priIsPrime_deep(n),
626
			zmMontCreate_deep(no),
627
			qrPower_deep(n, n, zmMontCreate_deep(no))));
628 1
	if (state == 0)
629 0
		return ERR_OUTOFMEMORY;
630
	// раскладка состояния
631 1
	p = (word*)state;
632 1
	g = p + n;
633 1
	qr = (qr_o*)(g + n);
634 1
	stack = (octet*)qr + zmMontCreate_keep(no);
635
	// p -- простое?
636 1
	wwFrom(p, params->p, no);
637 1
	if (!priIsPrime(p, n, stack))
638
	{
639 0
		blobClose(state);
640 0
		return ERR_BAD_PARAMS;
641
	}
642
	// q -- простое?
643 1
	wwShLo(p, n, 1);
644 1
	if (!priIsPrime(p, n, stack))
645
	{
646 0
		blobClose(state);
647 0
		return ERR_BAD_PARAMS;
648
	}
649
	// построить кольцо Монтгомери
650 1
	zmMontCreate(qr, params->p, no, params->l + 2, stack);
651
	// проверить g
652 1
	qrFrom(g, params->g, qr, stack);
653 1
	qrPower(p, g, p, W_OF_B(params->l - 1), qr, stack);
654 1
	if (qrIsUnity(p, qr) || qrIsUnity(g, qr) || qrCmp(p, g, qr) == 0)
655
	{
656 1
		blobClose(state);
657 1
		return ERR_BAD_PARAMS;
658
	}
659
	// все нормально
660 1
	blobClose(state);
661 1
	return ERR_OK;
662
}
663

664
/*
665
*******************************************************************************
666
Управление ключами
667
*******************************************************************************
668
*/
669

670 1
err_t pfokGenKeypair(octet privkey[], octet pubkey[], 
671
	const pfok_params* params, gen_i rng, void* rng_state)
672
{
673
	size_t no, n;
674
	size_t mo, m;
675
	// состояние
676
	void* state;
677
	word* x;				/* [m] личный ключ */
678
	word* y;				/* [n] открытый ключ */
679
	qr_o* qr;				/* описание кольца Монтгомери */
680
	void* stack;
681
	// проверить params
682 1
	if (!memIsValid(params, sizeof(pfok_params)))
683 0
		return ERR_BAD_INPUT;
684
	// работоспособные параметры?
685 1
	if (!pfokIsOperableParams(params))
686 0
		return ERR_BAD_PARAMS;
687
	// размерности
688 1
	no = O_OF_B(params->l), n = W_OF_B(params->l);
689 1
	mo = O_OF_B(params->r), m = W_OF_B(params->r);
690
	// проверить остальные входные данные
691 1
	if (!memIsValid(privkey, mo) || !memIsValid(pubkey, no) || rng == 0)
692 0
		return ERR_BAD_INPUT;
693
	// создать состояние
694 1
	state = blobCreate(
695 1
		O_OF_W(n) + O_OF_W(m) + zmMontCreate_keep(no) +  
696 1
		utilMax(2,
697
			zmMontCreate_deep(no),
698
			qrPower_deep(n, n, zmMontCreate_deep(no))));
699 1
	if (state == 0)
700 0
		return ERR_OUTOFMEMORY;
701
	// раскладка состояния
702 1
	x = (word*)state;
703 1
	y = x + m;
704 1
	qr = (qr_o*)(y + n);
705 1
	stack = (octet*)qr + zmMontCreate_keep(no);
706
	// построить кольцо Монтгомери
707 1
	zmMontCreate(qr, params->p, no, params->l + 2, stack);
708
	// x <-R {0, 1,..., 2^r - 1}
709 1
	rng(x, mo, rng_state);
710 1
	wwFrom(x, x, mo);
711 1
	wwTrimHi(x, m, params->r);
712
	// y <- g^(x)
713 1
	wwFrom(y, params->g, no);
714 1
	qrPower(y, y, x, m, qr, stack);
715
	// выгрузить ключи
716 1
	wwTo(privkey, mo, x);
717 1
	qrTo(pubkey, y, qr, stack);
718
	// все нормально
719 1
	blobClose(state);
720 1
	return ERR_OK;
721
}
722

723 1
err_t pfokValPubkey(const pfok_params* params, const octet pubkey[])
724
{
725
	size_t no;
726
	// проверить params
727 1
	if (!memIsValid(params, sizeof(pfok_params)))
728 0
		return ERR_BAD_INPUT;
729
	// работоспособные параметры?
730 1
	if (!pfokIsOperableParams(params))
731 0
		return ERR_BAD_PARAMS;
732
	// размерности
733 1
	no = O_OF_B(params->l);
734
	// проверить остальные входные данные
735 1
	if (!memIsValid(pubkey, no))
736 0
		return ERR_BAD_INPUT;
737
	// 0 < pubkey < p?
738 1
	if (memIsZero(pubkey, no) || memCmp(pubkey, params->p, no) >= 0)
739 0
		return ERR_BAD_PUBKEY;
740
	// все нормально
741 1
	return ERR_OK;
742
}
743

744 1
err_t pfokCalcPubkey(octet pubkey[], const pfok_params* params, 
745
	const octet privkey[])
746
{
747
	size_t no, n;
748
	size_t mo, m;
749
	// состояние
750
	void* state;
751
	word* x;				/* [m] личный ключ */
752
	word* y;				/* [n] открытый ключ */
753
	qr_o* qr;				/* описание кольца Монтгомери */
754
	void* stack;
755
	// проверить params
756 1
	if (!memIsValid(params, sizeof(pfok_params)))
757 0
		return ERR_BAD_INPUT;
758
	// работоспособные параметры?
759 1
	if (!pfokIsOperableParams(params))
760 0
		return ERR_BAD_PARAMS;
761
	// размерности
762 1
	no = O_OF_B(params->l), n = W_OF_B(params->l);
763 1
	mo = O_OF_B(params->r), m = W_OF_B(params->r);
764
	// проверить остальные входные данные
765 1
	if (!memIsValid(privkey, mo) || !memIsValid(pubkey, no))
766 0
		return ERR_BAD_INPUT;
767
	// создать состояние
768 1
	state = blobCreate(
769 1
		O_OF_W(n) + O_OF_W(m) + zmMontCreate_keep(no) +  
770 1
		utilMax(2,
771
			zmMontCreate_deep(no),
772
			qrPower_deep(n, n, zmMontCreate_deep(no))));
773 1
	if (state == 0)
774 0
		return ERR_OUTOFMEMORY;
775
	// раскладка состояния
776 1
	x = (word*)state;
777 1
	y = x + m;
778 1
	qr = (qr_o*)(y + n);
779 1
	stack = (octet*)qr + zmMontCreate_keep(no);
780
	// построить кольцо Монтгомери
781 1
	zmMontCreate(qr, params->p, no, params->l + 2, stack);
782
	// x <- privkey
783 1
	wwFrom(x, privkey, mo);
784 1
	if (wwGetBits(x, params->r, B_OF_W(m) - params->r) != 0)
785
	{
786 0
		blobClose(state);
787 0
		return ERR_BAD_PRIVKEY;
788
	}
789
	// y <- g^(x)
790 1
	wwFrom(y, params->g, no);
791 1
	qrPower(y, y, x, m, qr, stack);
792
	// выгрузить открытый ключ
793 1
	qrTo(pubkey, y, qr, stack);
794
	// все нормально
795 1
	blobClose(state);
796 1
	return ERR_OK;
797
}
798

799
/*
800
*******************************************************************************
801
Протоколы
802
*******************************************************************************
803
*/
804

805 1
err_t pfokDH(octet sharekey[], const pfok_params* params, 
806
	const octet privkey[], const octet pubkey[])
807
{
808
	size_t no, n;
809
	size_t mo, m;
810
	// состояние
811
	void* state;
812
	word* x;				/* [m] личный ключ */
813
	word* y;				/* [n] открытый ключ визави */
814
	qr_o* qr;				/* описание кольца Монтгомери */
815
	void* stack;
816
	// проверить params
817 1
	if (!memIsValid(params, sizeof(pfok_params)))
818 0
		return ERR_BAD_INPUT;
819
	// работоспособные параметры?
820 1
	if (!pfokIsOperableParams(params))
821 0
		return ERR_BAD_PARAMS;
822
	// размерности
823 1
	no = O_OF_B(params->l), n = W_OF_B(params->l);
824 1
	mo = O_OF_B(params->r), m = W_OF_B(params->r);
825
	// проверить остальные входные данные
826 1
	if (!memIsValid(privkey, mo) || 
827 1
		!memIsValid(pubkey, no) ||
828 1
		!memIsValid(sharekey, O_OF_B(params->n)))
829 0
		return ERR_BAD_INPUT;
830
	// создать состояние
831 1
	state = blobCreate(
832 1
		O_OF_W(n) + O_OF_W(m) + zmMontCreate_keep(no) +  
833 1
		utilMax(2,
834
			zmMontCreate_deep(no),
835
			qrPower_deep(n, n, zmMontCreate_deep(no))));
836 1
	if (state == 0)
837 0
		return ERR_OUTOFMEMORY;
838
	// раскладка состояния
839 1
	x = (word*)state;
840 1
	y = x + m;
841 1
	qr = (qr_o*)(y + n);
842 1
	stack = (octet*)qr + zmMontCreate_keep(no);
843
	// построить кольцо Монтгомери
844 1
	zmMontCreate(qr, params->p, no, params->l + 2, stack);
845
	// x <- privkey
846 1
	wwFrom(x, privkey, mo);
847 1
	if (wwGetBits(x, params->r, B_OF_W(m) - params->r) != 0)
848
	{
849 0
		blobClose(state);
850 0
		return ERR_BAD_PRIVKEY;
851
	}
852
	// y <- pubkey
853 1
	wwFrom(y, pubkey, no);
854 1
	if (wwIsZero(y, n) || wwCmp(y, qr->mod, n) >= 0)
855
	{
856 0
		blobClose(state);
857 0
		return ERR_BAD_PUBKEY;
858
	}
859 1
	qrPower(y, y, x, m, qr, stack);
860
	// выгрузить открытый ключ
861 1
	qrTo((octet*)y, y, qr, stack);
862 1
	memCopy(sharekey, y, O_OF_B(params->n));
863 1
	if (params->n % 8)
864 0
		sharekey[params->n / 8] &= (octet)255 >> (8 - params->n % 8);
865
	// все нормально
866 1
	blobClose(state);
867 1
	return ERR_OK;
868
}
869

870 1
err_t pfokMTI(octet sharekey[], const pfok_params* params, 
871
	const octet privkey[], const octet privkey1[], 
872
	const octet pubkey[], const octet pubkey1[])
873
{
874
	size_t no, n;
875
	size_t mo, m;
876
	// состояние
877
	void* state;
878
	word* x;				/* [m] личный ключ */
879
	word* u;				/* [m] одноразовый личный ключ */
880
	word* y;				/* [n] открытый ключ визави */
881
	word* v;				/* [n] одноразовый открытый ключ визави */
882
	qr_o* qr;				/* описание кольца Монтгомери */
883
	void* stack;
884
	// проверить params
885 1
	if (!memIsValid(params, sizeof(pfok_params)))
886 0
		return ERR_BAD_INPUT;
887
	// работоспособные параметры?
888 1
	if (!pfokIsOperableParams(params))
889 0
		return ERR_BAD_PARAMS;
890
	// размерности
891 1
	no = O_OF_B(params->l), n = W_OF_B(params->l);
892 1
	mo = O_OF_B(params->r), m = W_OF_B(params->r);
893
	// проверить остальные входные данные
894 1
	if (!memIsValid(privkey, mo) || 
895 1
		!memIsValid(privkey1, mo) || 
896 1
		!memIsValid(pubkey, no) ||
897 1
		!memIsValid(pubkey1, no) ||
898 1
		!memIsValid(sharekey, O_OF_B(params->n)))
899 0
		return ERR_BAD_INPUT;
900
	// создать состояние
901 1
	state = blobCreate(
902 1
		2 * O_OF_W(n) + 2 * O_OF_W(m) + zmMontCreate_keep(no) +  
903 1
		utilMax(2,
904
			zmMontCreate_deep(no),
905
			qrPower_deep(n, n, zmMontCreate_deep(no))));
906 1
	if (state == 0)
907 0
		return ERR_OUTOFMEMORY;
908
	// раскладка состояния
909 1
	x = (word*)state;
910 1
	u = x + m;
911 1
	y = u + m;
912 1
	v = y + n;
913 1
	qr = (qr_o*)(v + n);
914 1
	stack = (octet*)qr + zmMontCreate_keep(no);
915
	// построить кольцо Монтгомери
916 1
	zmMontCreate(qr, params->p, no, params->l + 2, stack);
917
	// x <- privkey, u <- privkey1
918 1
	wwFrom(x, privkey, mo);
919 1
	wwFrom(u, privkey1, mo);
920 1
	if (wwGetBits(x, params->r, B_OF_W(m) - params->r) != 0 ||
921 1
		wwGetBits(u, params->r, B_OF_W(m) - params->r) != 0)
922
	{
923 0
		blobClose(state);
924 0
		return ERR_BAD_PRIVKEY;
925
	}
926
	// y <- pubkey, v <- pubkey1
927 1
	wwFrom(y, pubkey, no);
928 1
	wwFrom(v, pubkey1, no);
929 1
	if (wwIsZero(y, n) || wwCmp(y, qr->mod, n) >= 0 ||
930 1
		wwIsZero(v, n) || wwCmp(v, qr->mod, n) >= 0)
931
	{
932 0
		blobClose(state);
933 0
		return ERR_BAD_PUBKEY;
934
	}
935
	// y <- y^u, v <- v^x
936 1
	qrPower(y, y, u, m, qr, stack);
937 1
	qrPower(v, v, x, m, qr, stack);
938
	// выгрузить открытый ключ
939 1
	qrTo((octet*)y, y, qr, stack);
940 1
	qrTo((octet*)v, v, qr, stack);
941 1
	memCopy(sharekey, y, O_OF_B(params->n));
942 1
	memXor2(sharekey, v, O_OF_B(params->n));
943 1
	if (params->n % 8)
944 0
		sharekey[params->n / 8] &= (octet)255 >> (8 - params->n % 8);
945
	// все нормально
946 1
	blobClose(state);
947 1
	return ERR_OK;
948
}

Read our documentation on viewing source code .

Loading