/src/openssl/engines/ccgost/gost2001.c
Line | Count | Source (jump to first uncovered line) |
1 | | /********************************************************************** |
2 | | * gost2001.c * |
3 | | * Copyright (c) 2005-2006 Cryptocom LTD * |
4 | | * This file is distributed under the same license as OpenSSL * |
5 | | * * |
6 | | * Implementation of GOST R 34.10-2001 * |
7 | | * Requires OpenSSL 0.9.9 for compilation * |
8 | | **********************************************************************/ |
9 | | #include "gost_lcl.h" |
10 | | #include "gost_params.h" |
11 | | #include <string.h> |
12 | | #include <openssl/rand.h> |
13 | | #include <openssl/ecdsa.h> |
14 | | #include <openssl/err.h> |
15 | | #include "e_gost_err.h" |
16 | | #ifdef DEBUG_SIGN |
17 | | extern |
18 | | void dump_signature(const char *message, const unsigned char *buffer, |
19 | | size_t len); |
20 | | void dump_dsa_sig(const char *message, DSA_SIG *sig); |
21 | | #else |
22 | | |
23 | | # define dump_signature(a,b,c) |
24 | | # define dump_dsa_sig(a,b) |
25 | | #endif |
26 | | |
27 | | /* |
28 | | * Fills EC_KEY structure hidden in the app_data field of DSA structure |
29 | | * with parameter information, extracted from parameter array in |
30 | | * params.c file. |
31 | | * |
32 | | * Also fils DSA->q field with copy of EC_GROUP order field to make |
33 | | * DSA_size function work |
34 | | */ |
35 | | int fill_GOST2001_params(EC_KEY *eckey, int nid) |
36 | 0 | { |
37 | 0 | R3410_2001_params *params = R3410_2001_paramset; |
38 | 0 | EC_GROUP *grp = NULL; |
39 | 0 | BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; |
40 | 0 | EC_POINT *P = NULL; |
41 | 0 | BN_CTX *ctx = BN_CTX_new(); |
42 | 0 | int ok = 0; |
43 | |
|
44 | 0 | if(!ctx) { |
45 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); |
46 | 0 | goto err; |
47 | 0 | } |
48 | | |
49 | 0 | BN_CTX_start(ctx); |
50 | 0 | p = BN_CTX_get(ctx); |
51 | 0 | a = BN_CTX_get(ctx); |
52 | 0 | b = BN_CTX_get(ctx); |
53 | 0 | x = BN_CTX_get(ctx); |
54 | 0 | y = BN_CTX_get(ctx); |
55 | 0 | q = BN_CTX_get(ctx); |
56 | 0 | if(!p || !a || !b || !x || !y || !q) { |
57 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); |
58 | 0 | goto err; |
59 | 0 | } |
60 | 0 | while (params->nid != NID_undef && params->nid != nid) |
61 | 0 | params++; |
62 | 0 | if (params->nid == NID_undef) { |
63 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, |
64 | 0 | GOST_R_UNSUPPORTED_PARAMETER_SET); |
65 | 0 | goto err; |
66 | 0 | } |
67 | 0 | if(!BN_hex2bn(&p, params->p) |
68 | 0 | || !BN_hex2bn(&a, params->a) |
69 | 0 | || !BN_hex2bn(&b, params->b)) { |
70 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, |
71 | 0 | ERR_R_INTERNAL_ERROR); |
72 | 0 | goto err; |
73 | 0 | } |
74 | | |
75 | 0 | grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); |
76 | 0 | if(!grp) { |
77 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); |
78 | 0 | goto err; |
79 | 0 | } |
80 | | |
81 | 0 | P = EC_POINT_new(grp); |
82 | 0 | if(!P) { |
83 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); |
84 | 0 | goto err; |
85 | 0 | } |
86 | | |
87 | 0 | if(!BN_hex2bn(&x, params->x) |
88 | 0 | || !BN_hex2bn(&y, params->y) |
89 | 0 | || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx) |
90 | 0 | || !BN_hex2bn(&q, params->q)) { |
91 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); |
92 | 0 | goto err; |
93 | 0 | } |
94 | | #ifdef DEBUG_KEYS |
95 | | fprintf(stderr, "Set params index %d oid %s\nq=", |
96 | | (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); |
97 | | BN_print_fp(stderr, q); |
98 | | fprintf(stderr, "\n"); |
99 | | #endif |
100 | | |
101 | 0 | if(!EC_GROUP_set_generator(grp, P, q, NULL)) { |
102 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); |
103 | 0 | goto err; |
104 | 0 | } |
105 | 0 | EC_GROUP_set_curve_name(grp, params->nid); |
106 | 0 | if(!EC_KEY_set_group(eckey, grp)) { |
107 | 0 | GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); |
108 | 0 | goto err; |
109 | 0 | } |
110 | 0 | ok = 1; |
111 | 0 | err: |
112 | 0 | if (P) EC_POINT_free(P); |
113 | 0 | if (grp) EC_GROUP_free(grp); |
114 | 0 | if (ctx) { |
115 | 0 | BN_CTX_end(ctx); |
116 | 0 | BN_CTX_free(ctx); |
117 | 0 | } |
118 | 0 | return ok; |
119 | 0 | } |
120 | | |
121 | | /* |
122 | | * Computes gost2001 signature as DSA_SIG structure |
123 | | * |
124 | | * |
125 | | */ |
126 | | DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) |
127 | 0 | { |
128 | 0 | DSA_SIG *newsig = NULL, *ret = NULL; |
129 | 0 | BIGNUM *md = hashsum2bn(dgst); |
130 | 0 | BIGNUM *order = NULL; |
131 | 0 | const EC_GROUP *group; |
132 | 0 | const BIGNUM *priv_key; |
133 | 0 | BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = |
134 | 0 | NULL, *e = NULL; |
135 | 0 | EC_POINT *C = NULL; |
136 | 0 | BN_CTX *ctx = BN_CTX_new(); |
137 | 0 | if(!ctx || !md) { |
138 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); |
139 | 0 | goto err; |
140 | 0 | } |
141 | 0 | BN_CTX_start(ctx); |
142 | 0 | OPENSSL_assert(dlen == 32); |
143 | 0 | newsig = DSA_SIG_new(); |
144 | 0 | if (!newsig) { |
145 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_NO_MEMORY); |
146 | 0 | goto err; |
147 | 0 | } |
148 | 0 | group = EC_KEY_get0_group(eckey); |
149 | 0 | if(!group) { |
150 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); |
151 | 0 | goto err; |
152 | 0 | } |
153 | 0 | order = BN_CTX_get(ctx); |
154 | 0 | if(!order || !EC_GROUP_get_order(group, order, ctx)) { |
155 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); |
156 | 0 | goto err; |
157 | 0 | } |
158 | 0 | priv_key = EC_KEY_get0_private_key(eckey); |
159 | 0 | if(!priv_key) { |
160 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); |
161 | 0 | goto err; |
162 | 0 | } |
163 | 0 | e = BN_CTX_get(ctx); |
164 | 0 | if(!e || !BN_mod(e, md, order, ctx)) { |
165 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); |
166 | 0 | goto err; |
167 | 0 | } |
168 | | #ifdef DEBUG_SIGN |
169 | | fprintf(stderr, "digest as bignum="); |
170 | | BN_print_fp(stderr, md); |
171 | | fprintf(stderr, "\ndigest mod q="); |
172 | | BN_print_fp(stderr, e); |
173 | | fprintf(stderr, "\n"); |
174 | | #endif |
175 | 0 | if (BN_is_zero(e)) { |
176 | 0 | BN_one(e); |
177 | 0 | } |
178 | 0 | k = BN_CTX_get(ctx); |
179 | 0 | C = EC_POINT_new(group); |
180 | 0 | if(!k || !C) { |
181 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); |
182 | 0 | goto err; |
183 | 0 | } |
184 | 0 | do { |
185 | 0 | do { |
186 | 0 | if (!BN_rand_range(k, order)) { |
187 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, |
188 | 0 | GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); |
189 | 0 | goto err; |
190 | 0 | } |
191 | 0 | if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { |
192 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); |
193 | 0 | goto err; |
194 | 0 | } |
195 | 0 | if (!X) |
196 | 0 | X = BN_CTX_get(ctx); |
197 | 0 | if (!r) |
198 | 0 | r = BN_CTX_get(ctx); |
199 | 0 | if (!X || !r) { |
200 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); |
201 | 0 | goto err; |
202 | 0 | } |
203 | 0 | if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { |
204 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); |
205 | 0 | goto err; |
206 | 0 | } |
207 | | |
208 | 0 | if(!BN_nnmod(r, X, order, ctx)) { |
209 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); |
210 | 0 | goto err; |
211 | 0 | } |
212 | 0 | } |
213 | 0 | while (BN_is_zero(r)); |
214 | | /* s = (r*priv_key+k*e) mod order */ |
215 | 0 | if (!tmp) |
216 | 0 | tmp = BN_CTX_get(ctx); |
217 | 0 | if (!tmp2) |
218 | 0 | tmp2 = BN_CTX_get(ctx); |
219 | 0 | if (!s) |
220 | 0 | s = BN_CTX_get(ctx); |
221 | 0 | if (!tmp || !tmp2 || !s) { |
222 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); |
223 | 0 | goto err; |
224 | 0 | } |
225 | | |
226 | 0 | if(!BN_mod_mul(tmp, priv_key, r, order, ctx) |
227 | 0 | || !BN_mod_mul(tmp2, k, e, order, ctx) |
228 | 0 | || !BN_mod_add(s, tmp, tmp2, order, ctx)) { |
229 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); |
230 | 0 | goto err; |
231 | 0 | } |
232 | 0 | } |
233 | 0 | while (BN_is_zero(s)); |
234 | | |
235 | 0 | newsig->s = BN_dup(s); |
236 | 0 | newsig->r = BN_dup(r); |
237 | 0 | if(!newsig->s || !newsig->r) { |
238 | 0 | GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); |
239 | 0 | goto err; |
240 | 0 | } |
241 | | |
242 | 0 | ret = newsig; |
243 | 0 | err: |
244 | 0 | if(ctx) { |
245 | 0 | BN_CTX_end(ctx); |
246 | 0 | BN_CTX_free(ctx); |
247 | 0 | } |
248 | 0 | if (C) EC_POINT_free(C); |
249 | 0 | if (md) BN_free(md); |
250 | 0 | if (!ret && newsig) { |
251 | 0 | DSA_SIG_free(newsig); |
252 | 0 | } |
253 | 0 | return ret; |
254 | 0 | } |
255 | | |
256 | | /* |
257 | | * Verifies gost 2001 signature |
258 | | * |
259 | | */ |
260 | | int gost2001_do_verify(const unsigned char *dgst, int dgst_len, |
261 | | DSA_SIG *sig, EC_KEY *ec) |
262 | 0 | { |
263 | 0 | BN_CTX *ctx = BN_CTX_new(); |
264 | 0 | const EC_GROUP *group = EC_KEY_get0_group(ec); |
265 | 0 | BIGNUM *order; |
266 | 0 | BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = |
267 | 0 | NULL; |
268 | 0 | BIGNUM *X = NULL, *tmp = NULL; |
269 | 0 | EC_POINT *C = NULL; |
270 | 0 | const EC_POINT *pub_key = NULL; |
271 | 0 | int ok = 0; |
272 | |
|
273 | 0 | if(!ctx || !group) { |
274 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); |
275 | 0 | goto err; |
276 | 0 | } |
277 | | |
278 | 0 | BN_CTX_start(ctx); |
279 | 0 | order = BN_CTX_get(ctx); |
280 | 0 | e = BN_CTX_get(ctx); |
281 | 0 | z1 = BN_CTX_get(ctx); |
282 | 0 | z2 = BN_CTX_get(ctx); |
283 | 0 | tmp = BN_CTX_get(ctx); |
284 | 0 | X = BN_CTX_get(ctx); |
285 | 0 | R = BN_CTX_get(ctx); |
286 | 0 | v = BN_CTX_get(ctx); |
287 | 0 | if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) { |
288 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); |
289 | 0 | goto err; |
290 | 0 | } |
291 | | |
292 | 0 | pub_key = EC_KEY_get0_public_key(ec); |
293 | 0 | if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) { |
294 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); |
295 | 0 | goto err; |
296 | 0 | } |
297 | | |
298 | 0 | if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || |
299 | 0 | (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { |
300 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, |
301 | 0 | GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); |
302 | 0 | goto err; |
303 | |
|
304 | 0 | } |
305 | 0 | md = hashsum2bn(dgst); |
306 | |
|
307 | 0 | if(!md || !BN_mod(e, md, order, ctx)) { |
308 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); |
309 | 0 | goto err; |
310 | 0 | } |
311 | | #ifdef DEBUG_SIGN |
312 | | fprintf(stderr, "digest as bignum: "); |
313 | | BN_print_fp(stderr, md); |
314 | | fprintf(stderr, "\ndigest mod q: "); |
315 | | BN_print_fp(stderr, e); |
316 | | #endif |
317 | 0 | if (BN_is_zero(e) && !BN_one(e)) { |
318 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); |
319 | 0 | goto err; |
320 | 0 | } |
321 | 0 | v = BN_mod_inverse(v, e, order, ctx); |
322 | 0 | if(!v |
323 | 0 | || !BN_mod_mul(z1, sig->s, v, order, ctx) |
324 | 0 | || !BN_sub(tmp, order, sig->r) |
325 | 0 | || !BN_mod_mul(z2, tmp, v, order, ctx)) { |
326 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); |
327 | 0 | goto err; |
328 | 0 | } |
329 | | #ifdef DEBUG_SIGN |
330 | | fprintf(stderr, "\nInverted digest value: "); |
331 | | BN_print_fp(stderr, v); |
332 | | fprintf(stderr, "\nz1: "); |
333 | | BN_print_fp(stderr, z1); |
334 | | fprintf(stderr, "\nz2: "); |
335 | | BN_print_fp(stderr, z2); |
336 | | #endif |
337 | 0 | C = EC_POINT_new(group); |
338 | 0 | if (!C) { |
339 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); |
340 | 0 | goto err; |
341 | 0 | } |
342 | 0 | if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { |
343 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); |
344 | 0 | goto err; |
345 | 0 | } |
346 | 0 | if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { |
347 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); |
348 | 0 | goto err; |
349 | 0 | } |
350 | 0 | if(!BN_mod(R, X, order, ctx)) { |
351 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); |
352 | 0 | goto err; |
353 | 0 | } |
354 | | #ifdef DEBUG_SIGN |
355 | | fprintf(stderr, "\nX="); |
356 | | BN_print_fp(stderr, X); |
357 | | fprintf(stderr, "\nX mod q="); |
358 | | BN_print_fp(stderr, R); |
359 | | fprintf(stderr, "\n"); |
360 | | #endif |
361 | 0 | if (BN_cmp(R, sig->r) != 0) { |
362 | 0 | GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); |
363 | 0 | } else { |
364 | 0 | ok = 1; |
365 | 0 | } |
366 | 0 | err: |
367 | 0 | if (C) EC_POINT_free(C); |
368 | 0 | if (ctx) { |
369 | 0 | BN_CTX_end(ctx); |
370 | 0 | BN_CTX_free(ctx); |
371 | 0 | } |
372 | 0 | if (md) BN_free(md); |
373 | 0 | return ok; |
374 | 0 | } |
375 | | |
376 | | /* |
377 | | * Computes GOST R 34.10-2001 public key |
378 | | * |
379 | | * |
380 | | */ |
381 | | int gost2001_compute_public(EC_KEY *ec) |
382 | 0 | { |
383 | 0 | const EC_GROUP *group = EC_KEY_get0_group(ec); |
384 | 0 | EC_POINT *pub_key = NULL; |
385 | 0 | const BIGNUM *priv_key = NULL; |
386 | 0 | BN_CTX *ctx = NULL; |
387 | 0 | int ok = 0; |
388 | |
|
389 | 0 | if (!group) { |
390 | 0 | GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, |
391 | 0 | GOST_R_KEY_IS_NOT_INITIALIZED); |
392 | 0 | return 0; |
393 | 0 | } |
394 | 0 | ctx = BN_CTX_new(); |
395 | 0 | if(!ctx) { |
396 | 0 | GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); |
397 | 0 | goto err; |
398 | 0 | } |
399 | 0 | BN_CTX_start(ctx); |
400 | 0 | if (!(priv_key = EC_KEY_get0_private_key(ec))) { |
401 | 0 | GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); |
402 | 0 | goto err; |
403 | 0 | } |
404 | | |
405 | 0 | pub_key = EC_POINT_new(group); |
406 | 0 | if(!pub_key) { |
407 | 0 | GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); |
408 | 0 | goto err; |
409 | 0 | } |
410 | 0 | if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { |
411 | 0 | GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); |
412 | 0 | goto err; |
413 | 0 | } |
414 | 0 | if (!EC_KEY_set_public_key(ec, pub_key)) { |
415 | 0 | GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); |
416 | 0 | goto err; |
417 | 0 | } |
418 | 0 | ok = 256; |
419 | 0 | err: |
420 | 0 | if (pub_key) EC_POINT_free(pub_key); |
421 | 0 | if (ctx) { |
422 | 0 | BN_CTX_end(ctx); |
423 | 0 | BN_CTX_free(ctx); |
424 | 0 | } |
425 | 0 | return ok; |
426 | 0 | } |
427 | | |
428 | | /* |
429 | | * |
430 | | * Generates GOST R 34.10-2001 keypair |
431 | | * |
432 | | * |
433 | | */ |
434 | | int gost2001_keygen(EC_KEY *ec) |
435 | 0 | { |
436 | 0 | BIGNUM *order = BN_new(), *d = BN_new(); |
437 | 0 | const EC_GROUP *group = NULL; |
438 | |
|
439 | 0 | if (order == NULL || d == NULL) { |
440 | 0 | GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_MALLOC_FAILURE); |
441 | 0 | BN_free(d); |
442 | 0 | BN_free(order); |
443 | 0 | return 0; |
444 | 0 | } |
445 | | |
446 | 0 | group = EC_KEY_get0_group(ec); |
447 | 0 | if(!group || !EC_GROUP_get_order(group, order, NULL)) { |
448 | 0 | GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); |
449 | 0 | BN_free(d); |
450 | 0 | BN_free(order); |
451 | 0 | return 0; |
452 | 0 | } |
453 | | |
454 | 0 | do { |
455 | 0 | if (!BN_rand_range(d, order)) { |
456 | 0 | GOSTerr(GOST_F_GOST2001_KEYGEN, |
457 | 0 | GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); |
458 | 0 | BN_free(d); |
459 | 0 | BN_free(order); |
460 | 0 | return 0; |
461 | 0 | } |
462 | 0 | } |
463 | 0 | while (BN_is_zero(d)); |
464 | | |
465 | 0 | if(!EC_KEY_set_private_key(ec, d)) { |
466 | 0 | GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); |
467 | 0 | BN_free(d); |
468 | 0 | BN_free(order); |
469 | 0 | return 0; |
470 | 0 | } |
471 | 0 | BN_free(d); |
472 | 0 | BN_free(order); |
473 | 0 | return gost2001_compute_public(ec); |
474 | 0 | } |