1
/*
2
*******************************************************************************
3
\file g12s.c
4
\brief GOST R 34.10-94 (Russia): digital signature algorithms
5
\project bee2 [cryptographic library]
6
\author (C) Sergey Agievich [agievich@{bsu.by|gmail.com}]
7
\created 2012.07.09
8
\version 2016.04.22
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/str.h"
18
#include "bee2/core/util.h"
19
#include "bee2/crypto/g12s.h"
20
#include "bee2/math/ecp.h"
21
#include "bee2/math/gfp.h"
22
#include "bee2/math/ww.h"
23
#include "bee2/math/zz.h"
24

25
/*
26
*******************************************************************************
27
Глубина стека
28

29
Высокоуровневые функции сообщают о потребностях в стековой памяти через 
30
функции интерфейса g12s_deep_i. Потребности не должны учитывать память для 
31
размещения описаний базового поля и эллиптической кривой.
32
*******************************************************************************
33
*/
34

35
typedef size_t (*g12s_deep_i)(
36
	size_t n,					/* размерность (в машинных словах) */
37
	size_t f_deep,				/* глубина стека базового поля */
38
	size_t ec_d,				/* число проективных координат */
39
	size_t ec_deep				/* глубина стека эллиптической кривой */
40
);
41

42
/*
43
*******************************************************************************
44
Стандартные параметры: проверочный пример A.1 из ГОСТ Р 34.10-2012
45
*******************************************************************************
46
*/
47

48
static const char _a1_name[] = "1.2.643.2.2.35.0";
49

50
static const u32 _a1_l = 256;
51

52
static const octet _a1_p[] = {
53
	0x31, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
57
};
58

59
static const octet _a1_a[] = {
60
	0x07,
61
};
62

63
static const octet _a1_b[] = {
64
	0x7E, 0x3B, 0xE2, 0xDA, 0xE9, 0x0C, 0x4C, 0x51,
65
	0x2A, 0xFC, 0x72, 0x34, 0x6A, 0x6E, 0x3F, 0x56,
66
	0x40, 0xEF, 0xAF, 0xFB, 0x22, 0xE0, 0xB8, 0x39,
67
	0xE7, 0x8C, 0x93, 0xAA, 0x98, 0xF4, 0xBF, 0x5F,
68
};
69

70
static const octet _a1_q[] = {
71
	0xB3, 0xF5, 0xCC, 0x3A, 0x19, 0xFC, 0x9C, 0xC5,
72
	0x54, 0x61, 0x97, 0x92, 0x18, 0x8A, 0xFE, 0x50,
73
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
75
};
76

77
static const octet _a1_n = 1;
78

79
static const octet _a1_xP[] = {
80
	0x02,
81
};
82

83
static const octet _a1_yP[] = {
84
	0xC8, 0x8F, 0x7E, 0xEA, 0xBC, 0xAB, 0x96, 0x2B,
85
	0x12, 0x67, 0xA2, 0x9C, 0x0A, 0x7F, 0xC9, 0x85,
86
	0x9C, 0xD1, 0x16, 0x0E, 0x03, 0x16, 0x63, 0xBD,
87
	0xD4, 0x47, 0x51, 0xE6, 0xA0, 0xA8, 0xE2, 0x08,
88
};
89

90
/*
91
*******************************************************************************
92
Параметры КриптоПро,  набор A (1.2.643.2.2.35.1)
93
*******************************************************************************
94
*/
95

96
static const char _cryptoproA_name[] = "1.2.643.2.2.35.1";
97

98
static const u32 _cryptoproA_l = 256;
99

100
static const octet _cryptoproA_p[] = {
101
	0x97, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
102
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
103
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
105
};
106

107
static const octet _cryptoproA_a[] = {
108
	0x94, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112
};
113

114
static const octet _cryptoproA_b[] = {
115
	0xA6,
116
};
117

118
static const octet _cryptoproA_q[] = {
119
	0x93, 0xB8, 0x61, 0xB7, 0x09, 0x1B, 0x84, 0x45,
120
	0x00, 0xD1, 0x5A, 0x99, 0x70, 0x10, 0x61, 0x6C,
121
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
122
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
123
};
124

125
static const octet _cryptoproA_n = 1;
126

127
static const octet _cryptoproA_xP[] = {
128
	0x01,
129
};
130

131
static const octet _cryptoproA_yP[] = {
132
	0x14, 0x1E, 0x9F, 0x9E, 0x9C, 0xC9, 0xAC, 0x22,
133
	0xB1, 0xE3, 0x23, 0xDF, 0x2D, 0x4F, 0x29, 0x35,
134
	0x76, 0x2B, 0x3F, 0x45, 0x5A, 0x50, 0xDF, 0x27,
135
	0xDA, 0x9C, 0x98, 0xE0, 0x71, 0xE4, 0x91, 0x8D,
136
};
137

138
/*
139
*******************************************************************************
140
Параметры КриптоПро,  набор B (1.2.643.2.2.35.2)
141
*******************************************************************************
142
*/
143

144
static const char _cryptoproB_name[] = "1.2.643.2.2.35.2";
145

146
static const u32 _cryptoproB_l = 256;
147

148
static const octet _cryptoproB_p[] = {
149
	0x99, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
153
};
154

155
static const octet _cryptoproB_a[] = {
156
	0x96, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
160
};
161

162
static const octet _cryptoproB_b[] = {
163
	0x8B, 0xBC, 0x1B, 0x7E, 0xCE, 0xD4, 0x49, 0x2F,
164
	0x18, 0x2B, 0xFF, 0x73, 0x93, 0x25, 0x79, 0xE9,
165
	0x0A, 0xF8, 0x3D, 0x5C, 0xC2, 0xD3, 0xA7, 0x66,
166
	0xF8, 0xA5, 0x69, 0xA2, 0x19, 0xF4, 0x1A, 0x3E,
167
};
168

169
static const octet _cryptoproB_q[] = {
170
	0x8F, 0x19, 0x8A, 0xCC, 0x1B, 0x16, 0x97, 0xE4, 
171
	0xE5, 0x24, 0xA6, 0xF1, 0xFF, 0x0C, 0x70, 0x5F, 
172
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
173
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
174
};
175

176
static const octet _cryptoproB_n = 1;
177

178
static const octet _cryptoproB_xP[] = {
179
	0x01,
180
};
181

182
static const octet _cryptoproB_yP[] = {
183
	0xFC, 0x7E, 0x71, 0x17, 0xD7, 0xF8, 0x4B, 0x74,
184
	0xFB, 0xEC, 0x03, 0x8D, 0x85, 0xC9, 0x45, 0xC5,
185
	0xE5, 0x70, 0xC0, 0xB2, 0x3E, 0x1C, 0x3D, 0xB8,
186
	0x80, 0x66, 0xF9, 0x59, 0x43, 0x12, 0xA8, 0x3F,
187
};
188

189
/*
190
*******************************************************************************
191
Параметры КриптоПро,  набор C (1.2.643.2.2.35.3)
192
*******************************************************************************
193
*/
194

195
static const char _cryptoproC_name[] = "1.2.643.2.2.35.3";
196

197
static const u32 _cryptoproC_l = 256;
198

199
static const octet _cryptoproC_p[] = {
200
	0x9B, 0x75, 0x2D, 0x02, 0xB9, 0xF7, 0x98, 0x79,
201
	0xD3, 0x51, 0x90, 0x78, 0x86, 0x6E, 0x84, 0xCF,
202
	0xAA, 0xC8, 0x41, 0x6B, 0x5E, 0xC8, 0x1E, 0xAB,
203
	0x07, 0x81, 0x85, 0x5A, 0x5F, 0x60, 0x9F, 0x9B,
204
};
205

206
static const octet _cryptoproC_a[] = {
207
	0x98, 0x75, 0x2D, 0x02, 0xB9, 0xF7, 0x98, 0x79,
208
	0xD3, 0x51, 0x90, 0x78, 0x86, 0x6E, 0x84, 0xCF,
209
	0xAA, 0xC8, 0x41, 0x6B, 0x5E, 0xC8, 0x1E, 0xAB,
210
	0x07, 0x81, 0x85, 0x5A, 0x5F, 0x60, 0x9F, 0x9B,
211
};
212

213
static const octet _cryptoproC_b[] = {
214
	0x5A, 0x80,
215
};
216

217
static const octet _cryptoproC_q[] = {
218
	0xB9, 0x0B, 0x98, 0x98, 0x65, 0x3A, 0x2F, 0xF0,
219
	0x74, 0xFB, 0xDD, 0x1E, 0x51, 0xA3, 0x2C, 0x58,
220
	0xAA, 0xC8, 0x41, 0x6B, 0x5E, 0xC8, 0x1E, 0xAB,
221
	0x07, 0x81, 0x85, 0x5A, 0x5F, 0x60, 0x9F, 0x9B,
222
};
223

224
static const octet _cryptoproC_n = 1;
225

226
static const octet _cryptoproC_xP[] = {
227
	0x00,
228
};
229

230
static const octet _cryptoproC_yP[] = {
231
	0x67, 0xBB, 0xB3, 0xFD, 0x0D, 0x55, 0x6E, 0x36,
232
	0x8F, 0x1A, 0x64, 0xD4, 0x40, 0xC4, 0x4D, 0x4D,
233
	0xEE, 0xC0, 0x08, 0xCD, 0x83, 0x37, 0xBF, 0x3C,
234
	0x8C, 0x1A, 0x71, 0x43, 0x57, 0xE5, 0xEC, 0x41,
235
};
236

237
/*
238
*******************************************************************************
239
Параметры CryptoCom (1.2.643.2.9.1.8.1)
240
*******************************************************************************
241
*/
242

243
static const char _cryptocom_name[] = "1.2.643.2.9.1.8.1";
244

245
static const u32 _cryptocom_l = 256;
246

247
static const octet _cryptocom_p[] = {
248
	0xC7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
252
};
253

254
static const octet _cryptocom_a[] = {
255
	0xC4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
259
};
260

261
static const octet _cryptocom_b[] = {
262
	0x0C, 0x08, 0x55, 0xE9, 0x07, 0xE4, 0xD5, 0x87,
263
	0x77, 0x4B, 0xD4, 0x8F, 0x08, 0xE9, 0x32, 0x16,
264
	0xE8, 0x32, 0x82, 0xF8, 0xF1, 0xF1, 0xD0, 0xF7,
265
	0x9F, 0x74, 0xBC, 0x5E, 0x26, 0xB4, 0x06, 0x2D,
266
};
267

268
static const octet _cryptocom_q[] = {
269
	0x85, 0x7B, 0xE8, 0xB6, 0x54, 0x8A, 0x45, 0xB7,
270
	0x28, 0xE4, 0xBD, 0xF4, 0xA2, 0x17, 0x61, 0x60,
271
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
272
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F,
273
};
274

275
static const octet _cryptocom_n = 2;
276

277
static const octet _cryptocom_xP[] = {
278
	0x02,
279
};
280

281
static const octet _cryptocom_yP[] = {
282
	0x2C, 0xB2, 0xB6, 0xCC, 0xC8, 0xED, 0x0B, 0x44,
283
	0x6F, 0x70, 0xE9, 0x4A, 0x26, 0x8B, 0x24, 0xEB,
284
	0x17, 0x6A, 0x72, 0x5E, 0x10, 0x01, 0x8D, 0xC1,
285
	0xF5, 0x3E, 0x81, 0xF8, 0x4B, 0x03, 0x0E, 0xA2,
286
};
287

288
/*
289
*******************************************************************************
290
Стандартные параметры: проверочный пример A.2 из ГОСТ Р 34.10-2012
291
*******************************************************************************
292
*/
293

294
static const char _a2_name[] = "1.2.643.7.1.2.1.2.0";
295

296
static const u32 _a2_l = 512;
297

298
static const octet _a2_p[] = {
299
	0x73, 0x63, 0xBE, 0x28, 0xF5, 0xBB, 0x64, 0x16, 
300
	0xD8, 0x4D, 0x22, 0xAC, 0x6F, 0x33, 0xB8, 0x35, 
301
	0x6D, 0x54, 0xE4, 0x80, 0x7E, 0x04, 0x58, 0x04, 
302
	0x4A, 0x70, 0xF4, 0x1A, 0x74, 0x52, 0xD8, 0xF1, 
303
	0x5D, 0xD1, 0xD2, 0xB5, 0x09, 0x7C, 0xEB, 0xD4, 
304
	0x04, 0x0F, 0xB9, 0xFF, 0xB2, 0x14, 0x2B, 0x92, 
305
	0x80, 0xEE, 0x2F, 0x6B, 0x7B, 0x26, 0x0D, 0x55, 
306
	0xC7, 0x23, 0x00, 0xFE, 0xD1, 0xAC, 0x31, 0x45, 
307
};
308

309
static const octet _a2_a[] = {
310
	0x07, 
311
};
312

313
static const octet _a2_b[] = {
314
	0xDC, 0x2A, 0x30, 0x4F, 0x08, 0xA3, 0xD0, 0xFA, 
315
	0x97, 0x68, 0xDD, 0x2A, 0x0C, 0x54, 0x9E, 0xBC, 
316
	0x74, 0xCF, 0xE0, 0x58, 0xCA, 0x89, 0x0A, 0x48, 
317
	0x22, 0x73, 0xAD, 0xB2, 0x13, 0x40, 0x83, 0x61, 
318
	0x43, 0xAC, 0xA1, 0xEC, 0x49, 0xB6, 0x88, 0xD7, 
319
	0xFD, 0x00, 0x94, 0xE4, 0x77, 0xF3, 0xC5, 0x8B, 
320
	0x74, 0xEB, 0x57, 0x4E, 0xA5, 0xCF, 0xD8, 0x29, 
321
	0xDA, 0x16, 0x11, 0xA3, 0x06, 0x08, 0xFF, 0x1C, 
322
};
323

324
static const octet _a2_q[] = {
325
	0xDF, 0xE6, 0xE6, 0x87, 0xF1, 0xAA, 0x44, 0xD6, 
326
	0x95, 0xC5, 0x23, 0xBE, 0xED, 0x25, 0x6E, 0xD8, 
327
	0xF1, 0x23, 0xC4, 0xEC, 0x5E, 0x5C, 0x90, 0x19, 
328
	0xC7, 0xBA, 0x1D, 0xCB, 0x7E, 0x2D, 0x2F, 0xA8, 
329
	0x5D, 0xD1, 0xD2, 0xB5, 0x09, 0x7C, 0xEB, 0xD4, 
330
	0x04, 0x0F, 0xB9, 0xFF, 0xB2, 0x14, 0x2B, 0x92, 
331
	0x80, 0xEE, 0x2F, 0x6B, 0x7B, 0x26, 0x0D, 0x55, 
332
	0xC7, 0x23, 0x00, 0xFE, 0xD1, 0xAC, 0x31, 0x45, 
333
};
334

335
static const octet _a2_n = 1;
336

337
static const octet _a2_xP[] = {
338
	0x9A, 0x8A, 0x24, 0x20, 0xB1, 0xF1, 0x30, 0xB5, 
339
	0xB4, 0x33, 0xAC, 0x7F, 0x97, 0x49, 0xC8, 0x8B, 
340
	0xE2, 0x04, 0xE8, 0xEE, 0xA7, 0x0A, 0xB6, 0xC6, 
341
	0x8D, 0x83, 0xCD, 0x62, 0x12, 0x61, 0x60, 0xFD, 
342
	0x62, 0xD7, 0x8C, 0xA6, 0x93, 0x10, 0xF9, 0x25, 
343
	0xC8, 0x7C, 0x05, 0xD7, 0xB3, 0xB3, 0x13, 0x52, 
344
	0x6C, 0x7A, 0xFD, 0xBB, 0x6E, 0xBF, 0x96, 0xF3, 
345
	0x30, 0xEE, 0x72, 0x45, 0xC6, 0x9C, 0xD1, 0x24, 
346
};
347

348
static const octet _a2_yP[] = {
349
	0x1E, 0x37, 0xDD, 0x1A, 0xCB, 0x92, 0xBB, 0x6D, 
350
	0x0B, 0x64, 0x24, 0x1B, 0xB9, 0x18, 0x1A, 0xDC, 
351
	0x43, 0x4E, 0xEE, 0xE1, 0x51, 0x33, 0xEB, 0xF7, 
352
	0x6B, 0x49, 0xF1, 0x77, 0x6D, 0x15, 0xAB, 0x83, 
353
	0x2C, 0x9B, 0xF3, 0x59, 0xC2, 0x47, 0x24, 0xF3, 
354
	0xC3, 0xF2, 0xE5, 0x91, 0x1E, 0x06, 0xBF, 0xCF, 
355
	0xDD, 0xAC, 0x57, 0xC8, 0x13, 0x06, 0x02, 0x0D, 
356
	0x6E, 0xCE, 0xD2, 0x3B, 0xA4, 0x12, 0xB3, 0x2B, 
357
};
358

359
/*
360
*******************************************************************************
361
Стандартные параметры: набор iD-tC26-gost-3410-12-512-pArAmSEtA 
362
из Методических рекомендаций
363
*******************************************************************************
364
*/
365

366
static const char _paramsetA512_name[] = "1.2.643.7.1.2.1.2.1";
367

368
static const u32 _paramsetA512_l = 512;
369

370
static const octet _paramsetA512_p[] = {
371
	0xC7, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
372
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
373
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
374
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
375
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
376
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
377
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
378
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
379
};
380

381
static const octet _paramsetA512_a[] = {
382
	0xC4, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
383
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
384
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
385
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
386
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
387
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
388
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
389
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
390
};
391

392
static const octet _paramsetA512_b[] = {
393
	0x60, 0xC7, 0x71, 0x5A, 0x78, 0x90, 0x31, 0x50,
394
	0x61, 0x47, 0xEE, 0xEB, 0xD4, 0xF9, 0x2E, 0x86,
395
	0xDD, 0x90, 0xDA, 0x10, 0x40, 0x57, 0xB4, 0x4C,
396
	0x61, 0x27, 0x0D, 0xF3, 0x90, 0xB0, 0x3C, 0xEE,
397
	0x65, 0x62, 0x0B, 0xFD, 0x1C, 0x08, 0xBD, 0x79,
398
	0xE8, 0xB0, 0x1C, 0x76, 0x74, 0x25, 0xB8, 0x34,
399
	0xDA, 0xF1, 0x67, 0x66, 0x2B, 0x0B, 0xBD, 0xC1,
400
	0xDD, 0x86, 0xFC, 0xED, 0x5D, 0x50, 0xC2, 0xE8,
401
};
402

403
static const octet _paramsetA512_q[] = {
404
	0x75, 0xB2, 0x10, 0x1F, 0x41, 0xB1, 0xCD, 0xCA,
405
	0x5D, 0xB8, 0xD2, 0xFA, 0xAB, 0x38, 0x4B, 0x9B,
406
	0x60, 0x60, 0x05, 0x4E, 0x8D, 0x2B, 0xF2, 0x6F,
407
	0x11, 0x89, 0x8D, 0xF4, 0x32, 0x95, 0xE6, 0x27,
408
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
409
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
410
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
411
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
412
};
413

414
static const octet _paramsetA512_n = 1;
415

416
static const octet _paramsetA512_xP[] = {
417
	0x03,
418
};
419

420
static const octet _paramsetA512_yP[] = {
421
	0xA4, 0xF2, 0x15, 0x52, 0xCB, 0x89, 0xA5, 0x89,
422
	0xB8, 0xF5, 0x35, 0xC2, 0x5F, 0xFE, 0x28, 0x80,
423
	0xE9, 0x41, 0x3A, 0x0E, 0xA5, 0xE6, 0x75, 0x3D,
424
	0xE9, 0x36, 0xD0, 0x4F, 0xBE, 0x26, 0x16, 0xDF,
425
	0x21, 0xA9, 0xEF, 0xCB, 0xFD, 0x64, 0x80, 0x77,
426
	0xC1, 0xAB, 0xF1, 0xAC, 0x93, 0x1C, 0x5E, 0xCE,
427
	0xE6, 0x50, 0x54, 0xE2, 0x16, 0x88, 0x1B, 0xA6,
428
	0xE3, 0x6A, 0x83, 0x7A, 0xE8, 0xCF, 0x03, 0x75,
429
};
430

431
/*
432
*******************************************************************************
433
Стандартные параметры: набор id-tC26-gost-3410-12-512-paramsetB 
434
из Методических рекомендаций
435
*******************************************************************************
436
*/
437

438
static const char _paramsetB512_name[] = "1.2.643.7.1.2.1.2.2";
439

440
static const u32 _paramsetB512_l = 512;
441

442
static const octet _paramsetB512_p[] = {
443
	0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
451
};
452

453
static const octet _paramsetB512_a[] = {
454
	0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
461
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
462
};
463

464
static const octet _paramsetB512_b[] = {
465
	0x16, 0x01, 0x14, 0xC5, 0xC7, 0xCB, 0x8C, 0xFB,
466
	0x6E, 0x10, 0xA3, 0x1F, 0xEE, 0x8B, 0xF7, 0x50,
467
	0x9C, 0xB6, 0x1A, 0xAD, 0x6F, 0x27, 0x8B, 0x7F,
468
	0x21, 0x6D, 0x41, 0xB1, 0x2D, 0x5D, 0x96, 0x3E,
469
	0x9F, 0x28, 0x4B, 0x6C, 0x80, 0xDC, 0x85, 0xBF,
470
	0xBC, 0x38, 0xF1, 0x4A, 0x61, 0x7D, 0x7C, 0xB9,
471
	0x17, 0x25, 0x5E, 0x6F, 0xCF, 0x06, 0x3E, 0x7E,
472
	0x45, 0x41, 0xC8, 0x9D, 0x45, 0x1B, 0x7D, 0x68,
473
};
474

475
static const octet _paramsetB512_q[] = {
476
	0xBD, 0x25, 0x4F, 0x37, 0x54, 0x6C, 0x34, 0xC6,
477
	0x0E, 0xEA, 0x1B, 0x10, 0x12, 0x67, 0x99, 0x8B,
478
	0xFA, 0x0C, 0xD4, 0xD9, 0x7B, 0xB7, 0xFD, 0xAC,
479
	0x45, 0xA5, 0x65, 0x25, 0x14, 0xEC, 0xA1, 0x49,
480
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
481
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
483
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
484
};
485

486
static const octet _paramsetB512_n = 1;
487

488
static const octet _paramsetB512_xP[] = {
489
	0x02, 
490
};
491

492
static const octet _paramsetB512_yP[] = {
493
	0xBD, 0x41, 0xFE, 0x80, 0x07, 0x34, 0x21, 0x7E,
494
	0xEC, 0xEE, 0x4C, 0xF9, 0x55, 0x10, 0x04, 0x28,
495
	0x88, 0x39, 0xC0, 0xF8, 0xAA, 0xBC, 0x2C, 0x15,
496
	0x39, 0x4A, 0xDF, 0x1E, 0xFD, 0x28, 0xB2, 0xDC,
497
	0x35, 0x73, 0xEC, 0xC8, 0xE6, 0xD9, 0x6D, 0xBE,
498
	0x13, 0xC2, 0x78, 0x75, 0x69, 0x3B, 0x12, 0x3C,
499
	0x0F, 0x94, 0xA8, 0x47, 0x36, 0x1E, 0x07, 0x2C,
500
	0x4C, 0x09, 0x9B, 0x38, 0xDA, 0x7E, 0x8F, 0x1A,
501
};
502

503
/*
504
*******************************************************************************
505
Загрузить стандартные параметры
506
*******************************************************************************
507
*/
508

509
#define _LOAD_NAMED_PARAMS(params, name)\
510
	(params)->l = _##name##_l;\
511
	memCopy((params)->p, _##name##_p, sizeof(_##name##_p));\
512
	memCopy((params)->a, _##name##_a, sizeof(_##name##_a));\
513
	memCopy((params)->b, _##name##_b, sizeof(_##name##_b));\
514
	memCopy((params)->q, _##name##_q, sizeof(_##name##_q));\
515
	(params)->n = _##name##_n;\
516
	memCopy((params)->xP, _##name##_xP, sizeof(_##name##_xP));\
517
	memCopy((params)->yP, _##name##_yP, sizeof(_##name##_yP))\
518

519 1
err_t g12sStdParams(g12s_params* params, const char* name)
520
{
521 1
	if (!memIsValid(params, sizeof(g12s_params)))
522 0
		return ERR_BAD_INPUT;
523 1
	memSetZero(params, sizeof(g12s_params));
524 1
	if (strEq(name, _a1_name))
525
	{
526 1
		_LOAD_NAMED_PARAMS(params, a1);
527 1
		return ERR_OK;
528
	}
529 1
	if (strEq(name, _cryptoproA_name))
530
	{
531 1
		_LOAD_NAMED_PARAMS(params, cryptoproA);
532 1
		return ERR_OK;
533
	}
534 1
	if (strEq(name, _cryptoproB_name))
535
	{
536 1
		_LOAD_NAMED_PARAMS(params, cryptoproB);
537 1
		return ERR_OK;
538
	}
539 1
	if (strEq(name, _cryptoproC_name))
540
	{
541 1
		_LOAD_NAMED_PARAMS(params, cryptoproC);
542 1
		return ERR_OK;
543
	}
544 1
	if (strEq(name, _cryptocom_name))
545
	{
546 1
		_LOAD_NAMED_PARAMS(params, cryptocom);
547 1
		return ERR_OK;
548
	}
549 1
	if (strEq(name, _a2_name))
550
	{
551 1
		_LOAD_NAMED_PARAMS(params, a2);
552 1
		return ERR_OK;
553
	}
554 1
	if (strEq(name, _paramsetA512_name))
555
	{
556 1
		_LOAD_NAMED_PARAMS(params, paramsetA512);
557 1
		return ERR_OK;
558
	}
559 1
	if (strEq(name, _paramsetB512_name))
560
	{
561 1
		_LOAD_NAMED_PARAMS(params, paramsetB512);
562 1
		return ERR_OK;
563
	}
564 0
	return ERR_FILE_NOT_FOUND;
565
}
566

567
/*
568
*******************************************************************************
569
Создание описания эллиптической кривой
570

571
По долговременным параметрам params формируется описание pec эллиптической
572
кривой. Указатель *pec является одновременно началом фрагмента памяти, 
573
в котором размещается состояние и стек. Длина фрагмента определяется с учетом 
574
потребностей deep и размерностей dims.
575
\pre Указатель pec корректен.
576
\return ERR_OK, если описание успешно создано, и код ошибки в противном 
577
случае.
578
\remark Запрошенная память начинается по адресу objEnd(*pec, void).
579
\remark Проводится минимальная проверка параметров, обеспечивающая 
580
работоспособность высокоуровневых функций.
581
\remark Диапазоны для q:
582
-	2^254 \leq q \leq 2^256 (l == 256);
583
-	2^508 \leq q \leq 2^512 (l == 512).
584
.
585
\post Диапазоны для p:
586
	|nq - (p + 1)| \leq 2\sqrt{p} =>
587
		(\sqrt{nq} - 1)^2 \leq p \leq (\sqrt{nq} + 1)^2 =>
588
			p \geq (\sqrt{q} - 1)^2 =>
589
				p > 2^253 (l == 256)
590
				p > 2^507 (l == 512)
591
В частности, длина p (в октетах, в словах) не меньше длины q. 
592
*******************************************************************************
593
*/
594

595 1
static err_t g12sCreateEc(
596
	ec_o** pec,						/* [out] описание эллиптической кривой */
597
	const g12s_params* params,		/* [in] долговременные параметры */
598
	g12s_deep_i deep				/* [in] потребности в стековой памяти */
599
)
600
{
601
	// размерности
602
	size_t n, no, nb;
603
	size_t f_keep;
604
	size_t f_deep;
605
	size_t ec_d;
606
	size_t ec_keep;
607
	size_t ec_deep;
608
	// состояние
609
	void* state;	
610
	qr_o* f;			/* базовое поле */
611
	ec_o* ec;			/* кривая */
612
	void* stack;
613
	// pre
614 1
	ASSERT(memIsValid(pec, sizeof(*pec)));
615
	// минимальная проверка входных данных
616 1
	if (!memIsValid(params, sizeof(g12s_params)) ||
617 1
		params->l != 256 && params->l != 512)
618 0
		return ERR_BAD_PARAMS;
619
	// определить размерности
620 1
	no = memNonZeroSize(params->p, sizeof(params->p) * params->l / 512);
621 1
	n = W_OF_O(no);
622 1
	f_keep = gfpCreate_keep(no);
623 1
	f_deep = gfpCreate_deep(no);
624 1
	ec_d = 3;
625 1
	ec_keep = ecpCreateJ_keep(no);
626 1
	ec_deep = ecpCreateJ_deep(no, f_deep);
627
	// создать состояние
628 1
	state = blobCreate(
629 1
		f_keep + ec_keep +
630 1
		utilMax(3,
631
			ec_deep,
632
			ecCreateGroup_deep(f_deep),
633
			deep(n, f_deep, ec_d, ec_deep)));
634 1
	if (state == 0)
635 0
		return ERR_OUTOFMEMORY;
636
	// создать поле
637 1
	f = (qr_o*)((octet*)state + ec_keep);
638 1
	stack = (octet*)f + f_keep;
639 1
	if (!gfpCreate(f, params->p, no, stack))
640
	{
641 0
		blobClose(state);
642 0
		return ERR_BAD_PARAMS;
643
	}
644
	// проверить длину p
645 1
	nb = wwBitSize(f->mod, n);
646 1
	if (params->l == 256 && nb <= 253 ||
647 1
		params->l == 512 && nb <= 507)
648
	{
649 0
		blobClose(state);
650 0
		return ERR_BAD_PARAMS;
651
	}
652
	// создать кривую и группу
653 1
	ec = (ec_o*)state;
654 1
	if (!ecpCreateJ(ec, f, params->a, params->b, stack) ||
655 1
		!ecCreateGroup(ec, params->xP, params->yP, params->q, 
656 1
			params->l / 8, params->n, stack))
657
	{
658 0
		blobClose(state);
659 0
		return ERR_BAD_PARAMS;
660
	}
661
	// проверить q
662 1
	n = W_OF_B(params->l);
663 1
	nb = wwBitSize(ec->order, n);
664 1
	if (params->l == 256 && nb <= 254 ||
665 1
		params->l == 512 && nb <= 508 ||
666 1
		zzIsEven(ec->order, n))
667
	{
668 0
		blobClose(state);
669 0
		return ERR_BAD_PARAMS;
670
	}
671
	// присоединить f к ec
672 1
	objAppend(ec, f, 0);
673
	// все нормально
674 1
	*pec = ec;
675 1
	return ERR_OK;
676
}
677

678
/*
679
*******************************************************************************
680
Закрытие описания эллиптической кривой
681
*******************************************************************************
682
*/
683

684 1
void g12sCloseEc(ec_o* ec)
685
{
686 1
	blobClose(ec);
687
}
688

689
/*
690
*******************************************************************************
691
Проверка параметров
692

693
-#	l \in {256, 512} (g12sCreateEc)
694
-#	2^254 < q < 2^256 или 2^508 < q < 2^512 (bignCreateEc)
695
-#	p -- простое (ecpIsValid)
696
-#	q -- простое (ecpIsSafeGroup)
697
-#	q != p (ecpIsSafeGroup)
698
-#	p^m \not\equiv 1 (mod q), m = 1, 2,..., 31 или 131 (ecpIsSafeGroup)
699
-#	a, b < p (ecpCreateJ in g12sCreateEc)
700
-#	J(E) \notin {0, 1728} <=> a, b != 0 (g12sValParams)
701
-#	4a^3 + 27b^2 \not\equiv 0 (\mod p) (ecpIsValid)
702
-#	P \in E (ecpSeemsValidGroup)
703
-#	|n * q - (p + 1)| \leq 2\sqrt{p} (ecpSeemsValidGroup)
704
-#	qP = O (ecpHasOrder)
705

706
*******************************************************************************
707
*/
708

709 1
static size_t g12sValParams_deep(size_t n, size_t f_deep, size_t ec_d, 
710
	size_t ec_deep)
711
{
712 1
	return utilMax(4,
713
			ecpIsValid_deep(n, f_deep),
714
			ecpSeemsValidGroup_deep(n, f_deep),
715
			ecpIsSafeGroup_deep(n),
716
			ecHasOrderA_deep(n, ec_d, ec_deep, n));
717
}
718

719 1
err_t g12sValParams(const g12s_params* params)
720
{
721
	err_t code;
722
	// состояние
723
	ec_o* ec;
724
	void* stack;
725
	// старт
726 1
	code = g12sCreateEc(&ec, params, g12sValParams_deep);
727 1
	ERR_CALL_CHECK(code);
728 1
	stack = objEnd(ec, void);
729
	// проверить кривую, проверить J(E)
730 1
	if (!ecpIsValid(ec, stack) ||
731 1
		!ecpSeemsValidGroup(ec, stack) ||
732 1
		!ecpIsSafeGroup(ec, params->l == 256 ? 31 : 131, stack) ||
733 1
		!ecHasOrderA(ec->base, ec, ec->order, ec->f->n, stack) ||
734 1
		qrIsZero(ec->A, ec->f) || 
735 1
		qrIsZero(ec->B, ec->f))
736 0
		code = ERR_BAD_PARAMS;
737
	// завершение
738 1
	g12sCloseEc(ec);
739 1
	return code;
740
}
741

742
/*
743
*******************************************************************************
744
Управление ключами
745
*******************************************************************************
746
*/
747

748 1
static size_t g12sGenKeypair_deep(size_t n, size_t f_deep, size_t ec_d, 
749
	size_t ec_deep)
750
{
751 1
	const size_t m = n;
752 1
	return O_OF_W(m + 2 * n) + 
753 1
		ecMulA_deep(n, ec_d, ec_deep, n);
754
}
755

756 1
err_t g12sGenKeypair(octet privkey[], octet pubkey[],
757
	const g12s_params* params, gen_i rng, void* rng_stack)
758
{
759
	err_t code;
760
	size_t m, mo;
761
	// состояние
762
	ec_o* ec;
763
	word* d;				/* [m] личный ключ */
764
	word* Q;				/* [2n] открытый ключ */	
765
	void* stack;
766
	// проверить rng
767 1
	if (rng == 0)
768 0
		return ERR_BAD_RNG;
769
	// старт
770 1
	code = g12sCreateEc(&ec, params, g12sGenKeypair_deep);
771 1
	ERR_CALL_CHECK(code);
772
	// размерности order
773 1
	m = W_OF_B(params->l);
774 1
	mo = O_OF_B(params->l);
775
	// проверить входные указатели
776 1
	if (!memIsValid(privkey, mo) || 
777 1
		!memIsValid(pubkey, 2 * ec->f->no))
778
	{
779 0
		g12sCloseEc(ec);
780 0
		return ERR_BAD_INPUT;
781
	}
782
	// раскладка состояния
783 1
	d = objEnd(ec, word);
784 1
	Q = d + m;
785 1
	stack = Q + 2 * ec->f->n;
786
	// d <-R {1,2,..., q - 1}
787 1
	if (!zzRandNZMod(d, ec->order, m, rng, rng_stack))
788
	{
789 0
		g12sCloseEc(ec);
790 0
		return ERR_BAD_RNG;
791
	}
792
	// Q <- d P
793 1
	if (!ecMulA(Q, ec->base, ec, d, m, stack))
794
	{
795 0
		g12sCloseEc(ec);
796 0
		return ERR_BAD_PARAMS;
797
	}
798
	// выгрузить ключи
799 1
	wwTo(privkey, mo, d);
800 1
	qrTo(pubkey, ecX(Q), ec->f, stack);
801 1
	qrTo(pubkey + ec->f->no, ecY(Q, ec->f->n), ec->f, stack);
802
	// все нормально
803 1
	g12sCloseEc(ec);
804 1
	return ERR_OK;
805
}
806

807
/*
808
*******************************************************************************
809
Выработка ЭЦП
810
*******************************************************************************
811
*/
812

813 1
static size_t g12sSign_deep(size_t n, size_t f_deep, size_t ec_d, 
814
	size_t ec_deep)
815
{
816 1
	const size_t m = n;
817 1
	return 	O_OF_W(3 * m + 2 * n) +
818 1
		utilMax(3,
819
			zzMod_deep(m, m),
820
			ecMulA_deep(n, ec_d, ec_deep, n),
821
			zzMulMod_deep(m));
822
}
823

824 1
err_t g12sSign(octet sig[], const g12s_params* params, const octet hash[],
825
	const octet privkey[], gen_i rng, void* rng_stack)
826
{
827
	err_t code;
828
	size_t m, mo;
829
	// состояние
830
	ec_o* ec;
831
	word* d;		/* [m] личный ключ */
832
	word* e;		/* [m] обработанное хэш-значение */
833
	word* k;		/* [m] одноразовый ключ */
834
	word* C;		/* [2n] вспомогательная точка */
835
	word* r;		/* [m] первая (старшая) часть подписи */
836
	word* s;		/* [m] вторая часть подписи */
837
	void* stack;
838
	// проверить rng
839 1
	if (rng == 0)
840 0
		return ERR_BAD_RNG;
841
	// старт
842 1
	code = g12sCreateEc(&ec, params, g12sSign_deep);
843 1
	ERR_CALL_CHECK(code);
844
	// размерности order
845 1
	m = W_OF_B(params->l);
846 1
	mo = O_OF_B(params->l);
847
	// проверить входные указатели
848 1
	if (!memIsValid(hash, mo) ||
849 1
		!memIsValid(privkey, mo) ||
850 1
		!memIsValid(sig, 2 * mo))
851
	{
852 0
		g12sCloseEc(ec);
853 0
		return ERR_BAD_INPUT;
854
	}
855
	// раскладка состояния
856 1
	d = objEnd(ec, word);
857 1
	e = d + m;
858 1
	k = e + m;
859 1
	C = k + m;
860 1
	r = C + 2 * ec->f->n;
861 1
	s = r + m;
862 1
	stack = s + m;
863
	// загрузить d
864 1
	wwFrom(d, privkey, mo);
865 1
	if (wwIsZero(d, m) || 
866 1
		wwCmp(d, ec->order, m) >= 0)
867
	{
868 0
		g12sCloseEc(ec);
869 0
		return ERR_BAD_PRIVKEY;
870
	}
871
	// e <- hash \mod q
872 1
	memCopy(e, hash, mo);
873 1
	memRev(e, mo);
874 1
	wwFrom(e, e, mo);
875 1
	zzMod(e, e, m, ec->order, m, stack);
876
	// e == 0 => e <- 1
877 1
	if (wwIsZero(e, m))
878 0
		e[0] = 1;
879
	// k <-R {1,2,..., q - 1}
880
gen_k:
881 1
	if (!zzRandNZMod(k, ec->order, m, rng, rng_stack))
882
	{
883 0
		g12sCloseEc(ec);
884 0
		return ERR_BAD_RNG;
885
	}
886
	// C <- k P
887 1
	if (!ecMulA(C, ec->base, ec, k, m, stack))
888
	{
889
		// если params корректны, то этого быть не должно
890 0
		g12sCloseEc(ec);
891 0
		return ERR_BAD_INPUT;
892
	}
893
	// r <- x_C \mod q
894 1
	qrTo((octet*)C, ecX(C), ec->f, stack);
895 1
	wwFrom(r, C, ec->f->no);
896 1
	zzMod(r, r, ec->f->n, ec->order, m, stack);
897
	// r == 0 => повторить генерацию k
898 1
	if (wwIsZero(r, m))
899 0
		goto gen_k;
900
	// s <- (rd + ke) \mod q
901 1
	zzMulMod(k, k, e, ec->order, m, stack);
902 1
	zzMulMod(s, r, d, ec->order, m, stack);
903 1
	zzAddMod(s, s, k, ec->order, m);
904
	// выгрузить ЭЦП
905 1
	wwTo(sig, mo, s);
906 1
	wwTo(sig + mo, mo, r);
907 1
	memRev(sig, 2 * mo);
908
	// все нормально
909 1
	g12sCloseEc(ec);
910 1
	return ERR_OK;
911
}
912

913
/*
914
*******************************************************************************
915
Проверка ЭЦП
916
*******************************************************************************
917
*/
918

919 1
static size_t g12sVerify_deep(size_t n, size_t f_deep, size_t ec_d, 
920
	size_t ec_deep)
921
{
922 1
	const size_t m = n;
923 1
	return O_OF_W(5 * m + 2 * n) +
924 1
		utilMax(4,
925
			zzMod_deep(m, m),
926
			zzMulMod_deep(m),
927
			zzInvMod_deep(m),
928
			ecAddMulA_deep(n, ec_d, ec_deep, 2, m, m));
929
}
930

931 1
err_t g12sVerify(const g12s_params* params, const octet hash[], 
932
	const octet sig[], const octet pubkey[])
933
{
934
	err_t code;
935
	size_t m, mo;
936
	// состояние
937
	ec_o* ec;
938
	word* Q;		/* [2n] открытый ключ / точка R */
939
	word* r;		/* [m] первая (старшая) часть подписи */
940
	word* s;		/* [m] вторая часть подписи */
941
	word* e;		/* [m] обработанное хэш-значение, v */
942
	void* stack;
943
	// старт
944 1
	code = g12sCreateEc(&ec, params, g12sVerify_deep);
945 1
	ERR_CALL_CHECK(code);
946
	// размерности order
947 1
	m = W_OF_B(params->l);
948 1
	mo = O_OF_B(params->l);
949
	// проверить входные указатели
950 1
	if (!memIsValid(hash, mo) ||
951 1
		!memIsValid(sig, 2 * mo) ||
952 1
		!memIsValid(pubkey, 2 * ec->f->no))
953
	{
954 0
		g12sCloseEc(ec);
955 0
		return ERR_BAD_INPUT;
956
	}
957
	// раскладка состояния
958 1
	Q = objEnd(ec, word);
959 1
	r = Q + 2 * ec->f->n;
960 1
	s = r + m;
961 1
	e = s + m;
962 1
	stack = e + m;
963
	// загрузить Q
964 1
	if (!qrFrom(ecX(Q), pubkey, ec->f, stack) ||
965 1
		!qrFrom(ecY(Q, ec->f->n), pubkey + ec->f->no, ec->f, stack))
966
	{
967 0
		g12sCloseEc(ec);
968 0
		return ERR_BAD_PUBKEY;
969
	}
970
	// загрузить r и s
971 1
	memCopy(s, sig + mo, mo);
972 1
	memRev(s, mo);
973 1
	wwFrom(s, s, mo);
974 1
	memCopy(r, sig, mo);
975 1
	memRev(r, mo);
976 1
	wwFrom(r, r, mo);
977 1
	if (wwIsZero(s, m) || 
978 1
		wwIsZero(r, m) || 
979 1
		wwCmp(s, ec->order, m) >= 0 ||
980 1
		wwCmp(r, ec->order, m) >= 0)
981
	{
982 0
		g12sCloseEc(ec);
983 0
		return ERR_BAD_SIG;
984
	}
985
	// e <- hash \mod q
986 1
	memCopy(e, hash, mo);
987 1
	memRev(e, mo);
988 1
	wwFrom(e, e, mo);
989 1
	zzMod(e, e, m, ec->order, m, stack);
990
	// e == 0 => e <- 1
991 1
	if (wwIsZero(e, m))
992 0
		e[0] = 1;
993
	// e <- e^{-1} \mod q [v]
994 1
	zzInvMod(e, e, ec->order, m, stack);
995
	// s <- s e \mod q [z1]
996 1
	zzMulMod(s, s, e, ec->order, m, stack);
997
	// e <- - e r \mod q [z2]
998 1
	zzMulMod(e, e, r, ec->order, m, stack);
999 1
	zzNegMod(e, e, ec->order, m);
1000
	// Q <- s P + e Q [z1 P + z2 Q = R]
1001 1
	if (!ecAddMulA(Q, ec, stack, 2, ec->base, s, m, Q, e, m))
1002
	{
1003 0
		g12sCloseEc(ec);
1004 0
		return ERR_BAD_PARAMS;
1005
	}
1006
	// s <- x_Q \mod q [x_R \mod q]
1007 1
	qrTo((octet*)Q, ecX(Q), ec->f, stack);
1008 1
	wwFrom(Q, Q, ec->f->no);
1009 1
	zzMod(s, Q, ec->f->n, ec->order, m, stack);
1010
	// s == r?
1011 1
	code = wwEq(r, s, m) ? ERR_OK : ERR_BAD_SIG;
1012
	// завершение
1013 1
	g12sCloseEc(ec);
1014 1
	return code;
1015
}

Read our documentation on viewing source code .

Loading