1238384Sjkim/********************************************************************** 2238384Sjkim * gost2001.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6280304Sjkim * Implementation of GOST R 34.10-2001 * 7238384Sjkim * Requires OpenSSL 0.9.9 for compilation * 8238384Sjkim **********************************************************************/ 9238384Sjkim#include "gost_lcl.h" 10238384Sjkim#include "gost_params.h" 11238384Sjkim#include <string.h> 12238384Sjkim#include <openssl/rand.h> 13238384Sjkim#include <openssl/ecdsa.h> 14238384Sjkim#include <openssl/err.h> 15238384Sjkim#include "e_gost_err.h" 16238384Sjkim#ifdef DEBUG_SIGN 17280304Sjkimextern 18280304Sjkimvoid dump_signature(const char *message, const unsigned char *buffer, 19280304Sjkim size_t len); 20238384Sjkimvoid dump_dsa_sig(const char *message, DSA_SIG *sig); 21238384Sjkim#else 22238384Sjkim 23280304Sjkim# define dump_signature(a,b,c) 24280304Sjkim# define dump_dsa_sig(a,b) 25238384Sjkim#endif 26238384Sjkim 27238384Sjkim/* 28238384Sjkim * Fills EC_KEY structure hidden in the app_data field of DSA structure 29238384Sjkim * with parameter information, extracted from parameter array in 30238384Sjkim * params.c file. 31238384Sjkim * 32238384Sjkim * Also fils DSA->q field with copy of EC_GROUP order field to make 33238384Sjkim * DSA_size function work 34280304Sjkim */ 35238384Sjkimint fill_GOST2001_params(EC_KEY *eckey, int nid) 36280304Sjkim{ 37280304Sjkim R3410_2001_params *params = R3410_2001_paramset; 38280304Sjkim EC_GROUP *grp = NULL; 39280304Sjkim BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; 40280304Sjkim EC_POINT *P = NULL; 41280304Sjkim BN_CTX *ctx = BN_CTX_new(); 42280304Sjkim int ok = 0; 43238384Sjkim 44284285Sjkim if(!ctx) { 45284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 46284285Sjkim goto err; 47284285Sjkim } 48284285Sjkim 49280304Sjkim BN_CTX_start(ctx); 50280304Sjkim p = BN_CTX_get(ctx); 51280304Sjkim a = BN_CTX_get(ctx); 52280304Sjkim b = BN_CTX_get(ctx); 53280304Sjkim x = BN_CTX_get(ctx); 54280304Sjkim y = BN_CTX_get(ctx); 55280304Sjkim q = BN_CTX_get(ctx); 56284285Sjkim if(!p || !a || !b || !x || !y || !q) { 57284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 58284285Sjkim goto err; 59284285Sjkim } 60280304Sjkim while (params->nid != NID_undef && params->nid != nid) 61280304Sjkim params++; 62280304Sjkim if (params->nid == NID_undef) { 63280304Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 64280304Sjkim GOST_R_UNSUPPORTED_PARAMETER_SET); 65280304Sjkim goto err; 66280304Sjkim } 67284285Sjkim if(!BN_hex2bn(&p, params->p) 68284285Sjkim || !BN_hex2bn(&a, params->a) 69284285Sjkim || !BN_hex2bn(&b, params->b)) { 70284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 71284285Sjkim ERR_R_INTERNAL_ERROR); 72284285Sjkim goto err; 73284285Sjkim } 74238384Sjkim 75280304Sjkim grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); 76284285Sjkim if(!grp) { 77284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 78284285Sjkim goto err; 79284285Sjkim } 80280304Sjkim 81280304Sjkim P = EC_POINT_new(grp); 82284285Sjkim if(!P) { 83284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 84284285Sjkim goto err; 85284285Sjkim } 86280304Sjkim 87284285Sjkim if(!BN_hex2bn(&x, params->x) 88284285Sjkim || !BN_hex2bn(&y, params->y) 89284285Sjkim || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx) 90284285Sjkim || !BN_hex2bn(&q, params->q)) { 91284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 92284285Sjkim goto err; 93284285Sjkim } 94238384Sjkim#ifdef DEBUG_KEYS 95280304Sjkim fprintf(stderr, "Set params index %d oid %s\nq=", 96280304Sjkim (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); 97280304Sjkim BN_print_fp(stderr, q); 98280304Sjkim fprintf(stderr, "\n"); 99280304Sjkim#endif 100238384Sjkim 101284285Sjkim if(!EC_GROUP_set_generator(grp, P, q, NULL)) { 102284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 103284285Sjkim goto err; 104284285Sjkim } 105280304Sjkim EC_GROUP_set_curve_name(grp, params->nid); 106284285Sjkim if(!EC_KEY_set_group(eckey, grp)) { 107284285Sjkim GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 108284285Sjkim goto err; 109284285Sjkim } 110280304Sjkim ok = 1; 111280304Sjkim err: 112284285Sjkim if (P) EC_POINT_free(P); 113284285Sjkim if (grp) EC_GROUP_free(grp); 114284285Sjkim if (ctx) { 115284285Sjkim BN_CTX_end(ctx); 116284285Sjkim BN_CTX_free(ctx); 117284285Sjkim } 118280304Sjkim return ok; 119280304Sjkim} 120238384Sjkim 121238384Sjkim/* 122280304Sjkim * Computes gost2001 signature as DSA_SIG structure 123238384Sjkim * 124238384Sjkim * 125280304Sjkim */ 126280304SjkimDSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) 127280304Sjkim{ 128284285Sjkim DSA_SIG *newsig = NULL, *ret = NULL; 129280304Sjkim BIGNUM *md = hashsum2bn(dgst); 130280304Sjkim BIGNUM *order = NULL; 131280304Sjkim const EC_GROUP *group; 132280304Sjkim const BIGNUM *priv_key; 133280304Sjkim BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = 134280304Sjkim NULL, *e = NULL; 135280304Sjkim EC_POINT *C = NULL; 136280304Sjkim BN_CTX *ctx = BN_CTX_new(); 137284285Sjkim if(!ctx || !md) { 138284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 139284285Sjkim goto err; 140284285Sjkim } 141280304Sjkim BN_CTX_start(ctx); 142280304Sjkim OPENSSL_assert(dlen == 32); 143280304Sjkim newsig = DSA_SIG_new(); 144280304Sjkim if (!newsig) { 145280304Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_NO_MEMORY); 146280304Sjkim goto err; 147280304Sjkim } 148280304Sjkim group = EC_KEY_get0_group(eckey); 149284285Sjkim if(!group) { 150284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 151284285Sjkim goto err; 152284285Sjkim } 153280304Sjkim order = BN_CTX_get(ctx); 154284285Sjkim if(!order || !EC_GROUP_get_order(group, order, ctx)) { 155284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 156284285Sjkim goto err; 157284285Sjkim } 158280304Sjkim priv_key = EC_KEY_get0_private_key(eckey); 159284285Sjkim if(!priv_key) { 160284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 161284285Sjkim goto err; 162284285Sjkim } 163280304Sjkim e = BN_CTX_get(ctx); 164284285Sjkim if(!e || !BN_mod(e, md, order, ctx)) { 165284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 166284285Sjkim goto err; 167284285Sjkim } 168238384Sjkim#ifdef DEBUG_SIGN 169280304Sjkim fprintf(stderr, "digest as bignum="); 170280304Sjkim BN_print_fp(stderr, md); 171280304Sjkim fprintf(stderr, "\ndigest mod q="); 172280304Sjkim BN_print_fp(stderr, e); 173280304Sjkim fprintf(stderr, "\n"); 174280304Sjkim#endif 175280304Sjkim if (BN_is_zero(e)) { 176280304Sjkim BN_one(e); 177280304Sjkim } 178280304Sjkim k = BN_CTX_get(ctx); 179280304Sjkim C = EC_POINT_new(group); 180284285Sjkim if(!k || !C) { 181284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 182284285Sjkim goto err; 183284285Sjkim } 184280304Sjkim do { 185280304Sjkim do { 186280304Sjkim if (!BN_rand_range(k, order)) { 187280304Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, 188280304Sjkim GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 189280304Sjkim goto err; 190280304Sjkim } 191280304Sjkim if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { 192280304Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 193280304Sjkim goto err; 194280304Sjkim } 195280304Sjkim if (!X) 196280304Sjkim X = BN_CTX_get(ctx); 197284285Sjkim if (!r) 198284285Sjkim r = BN_CTX_get(ctx); 199284285Sjkim if (!X || !r) { 200284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 201284285Sjkim goto err; 202284285Sjkim } 203280304Sjkim if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 204280304Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 205280304Sjkim goto err; 206280304Sjkim } 207284285Sjkim 208284285Sjkim if(!BN_nnmod(r, X, order, ctx)) { 209284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 210284285Sjkim goto err; 211284285Sjkim } 212280304Sjkim } 213280304Sjkim while (BN_is_zero(r)); 214280304Sjkim /* s = (r*priv_key+k*e) mod order */ 215280304Sjkim if (!tmp) 216280304Sjkim tmp = BN_CTX_get(ctx); 217280304Sjkim if (!tmp2) 218280304Sjkim tmp2 = BN_CTX_get(ctx); 219280304Sjkim if (!s) 220280304Sjkim s = BN_CTX_get(ctx); 221284285Sjkim if (!tmp || !tmp2 || !s) { 222284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 223284285Sjkim goto err; 224284285Sjkim } 225284285Sjkim 226284285Sjkim if(!BN_mod_mul(tmp, priv_key, r, order, ctx) 227284285Sjkim || !BN_mod_mul(tmp2, k, e, order, ctx) 228284285Sjkim || !BN_mod_add(s, tmp, tmp2, order, ctx)) { 229284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 230284285Sjkim goto err; 231284285Sjkim } 232280304Sjkim } 233280304Sjkim while (BN_is_zero(s)); 234238384Sjkim 235280304Sjkim newsig->s = BN_dup(s); 236280304Sjkim newsig->r = BN_dup(r); 237284285Sjkim if(!newsig->s || !newsig->r) { 238284285Sjkim GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 239284285Sjkim goto err; 240284285Sjkim } 241284285Sjkim 242284285Sjkim ret = newsig; 243280304Sjkim err: 244284285Sjkim if(ctx) { 245284285Sjkim BN_CTX_end(ctx); 246284285Sjkim BN_CTX_free(ctx); 247284285Sjkim } 248284285Sjkim if (C) EC_POINT_free(C); 249284285Sjkim if (md) BN_free(md); 250284285Sjkim if (!ret && newsig) { 251284285Sjkim DSA_SIG_free(newsig); 252284285Sjkim } 253284285Sjkim return ret; 254280304Sjkim} 255280304Sjkim 256238384Sjkim/* 257238384Sjkim * Verifies gost 2001 signature 258238384Sjkim * 259280304Sjkim */ 260280304Sjkimint gost2001_do_verify(const unsigned char *dgst, int dgst_len, 261280304Sjkim DSA_SIG *sig, EC_KEY *ec) 262280304Sjkim{ 263280304Sjkim BN_CTX *ctx = BN_CTX_new(); 264280304Sjkim const EC_GROUP *group = EC_KEY_get0_group(ec); 265280304Sjkim BIGNUM *order; 266280304Sjkim BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = 267280304Sjkim NULL; 268280304Sjkim BIGNUM *X = NULL, *tmp = NULL; 269280304Sjkim EC_POINT *C = NULL; 270280304Sjkim const EC_POINT *pub_key = NULL; 271280304Sjkim int ok = 0; 272238384Sjkim 273284285Sjkim if(!ctx || !group) { 274284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 275284285Sjkim goto err; 276284285Sjkim } 277284285Sjkim 278280304Sjkim BN_CTX_start(ctx); 279280304Sjkim order = BN_CTX_get(ctx); 280280304Sjkim e = BN_CTX_get(ctx); 281280304Sjkim z1 = BN_CTX_get(ctx); 282280304Sjkim z2 = BN_CTX_get(ctx); 283280304Sjkim tmp = BN_CTX_get(ctx); 284280304Sjkim X = BN_CTX_get(ctx); 285280304Sjkim R = BN_CTX_get(ctx); 286280304Sjkim v = BN_CTX_get(ctx); 287284285Sjkim if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) { 288284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); 289284285Sjkim goto err; 290284285Sjkim } 291238384Sjkim 292280304Sjkim pub_key = EC_KEY_get0_public_key(ec); 293284285Sjkim if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) { 294284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 295284285Sjkim goto err; 296284285Sjkim } 297284285Sjkim 298280304Sjkim if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || 299280304Sjkim (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { 300280304Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, 301280304Sjkim GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 302280304Sjkim goto err; 303238384Sjkim 304280304Sjkim } 305280304Sjkim md = hashsum2bn(dgst); 306280304Sjkim 307284285Sjkim if(!md || !BN_mod(e, md, order, ctx)) { 308284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 309284285Sjkim goto err; 310284285Sjkim } 311238384Sjkim#ifdef DEBUG_SIGN 312280304Sjkim fprintf(stderr, "digest as bignum: "); 313280304Sjkim BN_print_fp(stderr, md); 314280304Sjkim fprintf(stderr, "\ndigest mod q: "); 315280304Sjkim BN_print_fp(stderr, e); 316280304Sjkim#endif 317284285Sjkim if (BN_is_zero(e) && !BN_one(e)) { 318284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 319284285Sjkim goto err; 320284285Sjkim } 321280304Sjkim v = BN_mod_inverse(v, e, order, ctx); 322284285Sjkim if(!v 323284285Sjkim || !BN_mod_mul(z1, sig->s, v, order, ctx) 324284285Sjkim || !BN_sub(tmp, order, sig->r) 325284285Sjkim || !BN_mod_mul(z2, tmp, v, order, ctx)) { 326284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 327284285Sjkim goto err; 328284285Sjkim } 329238384Sjkim#ifdef DEBUG_SIGN 330280304Sjkim fprintf(stderr, "\nInverted digest value: "); 331280304Sjkim BN_print_fp(stderr, v); 332280304Sjkim fprintf(stderr, "\nz1: "); 333280304Sjkim BN_print_fp(stderr, z1); 334280304Sjkim fprintf(stderr, "\nz2: "); 335280304Sjkim BN_print_fp(stderr, z2); 336280304Sjkim#endif 337280304Sjkim C = EC_POINT_new(group); 338284285Sjkim if (!C) { 339284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); 340284285Sjkim goto err; 341284285Sjkim } 342280304Sjkim if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { 343280304Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 344280304Sjkim goto err; 345280304Sjkim } 346280304Sjkim if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 347280304Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 348280304Sjkim goto err; 349280304Sjkim } 350284285Sjkim if(!BN_mod(R, X, order, ctx)) { 351284285Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 352284285Sjkim goto err; 353284285Sjkim } 354238384Sjkim#ifdef DEBUG_SIGN 355280304Sjkim fprintf(stderr, "\nX="); 356280304Sjkim BN_print_fp(stderr, X); 357280304Sjkim fprintf(stderr, "\nX mod q="); 358280304Sjkim BN_print_fp(stderr, R); 359280304Sjkim fprintf(stderr, "\n"); 360280304Sjkim#endif 361280304Sjkim if (BN_cmp(R, sig->r) != 0) { 362280304Sjkim GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 363280304Sjkim } else { 364280304Sjkim ok = 1; 365280304Sjkim } 366280304Sjkim err: 367284285Sjkim if (C) EC_POINT_free(C); 368284285Sjkim if (ctx) { 369284285Sjkim BN_CTX_end(ctx); 370284285Sjkim BN_CTX_free(ctx); 371284285Sjkim } 372284285Sjkim if (md) BN_free(md); 373280304Sjkim return ok; 374280304Sjkim} 375280304Sjkim 376238384Sjkim/* 377238384Sjkim * Computes GOST R 34.10-2001 public key 378238384Sjkim * 379238384Sjkim * 380280304Sjkim */ 381280304Sjkimint gost2001_compute_public(EC_KEY *ec) 382280304Sjkim{ 383280304Sjkim const EC_GROUP *group = EC_KEY_get0_group(ec); 384280304Sjkim EC_POINT *pub_key = NULL; 385280304Sjkim const BIGNUM *priv_key = NULL; 386280304Sjkim BN_CTX *ctx = NULL; 387280304Sjkim int ok = 0; 388238384Sjkim 389280304Sjkim if (!group) { 390280304Sjkim GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, 391280304Sjkim GOST_R_KEY_IS_NOT_INITIALIZED); 392280304Sjkim return 0; 393280304Sjkim } 394280304Sjkim ctx = BN_CTX_new(); 395284285Sjkim if(!ctx) { 396284285Sjkim GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 397284285Sjkim goto err; 398284285Sjkim } 399280304Sjkim BN_CTX_start(ctx); 400280304Sjkim if (!(priv_key = EC_KEY_get0_private_key(ec))) { 401280304Sjkim GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 402280304Sjkim goto err; 403280304Sjkim } 404238384Sjkim 405280304Sjkim pub_key = EC_POINT_new(group); 406284285Sjkim if(!pub_key) { 407284285Sjkim GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 408284285Sjkim goto err; 409284285Sjkim } 410280304Sjkim if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { 411280304Sjkim GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 412280304Sjkim goto err; 413280304Sjkim } 414280304Sjkim if (!EC_KEY_set_public_key(ec, pub_key)) { 415280304Sjkim GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 416280304Sjkim goto err; 417280304Sjkim } 418280304Sjkim ok = 256; 419280304Sjkim err: 420284285Sjkim if (pub_key) EC_POINT_free(pub_key); 421284285Sjkim if (ctx) { 422284285Sjkim BN_CTX_end(ctx); 423284285Sjkim BN_CTX_free(ctx); 424284285Sjkim } 425280304Sjkim return ok; 426280304Sjkim} 427280304Sjkim 428238384Sjkim/* 429280304Sjkim * 430238384Sjkim * Generates GOST R 34.10-2001 keypair 431238384Sjkim * 432238384Sjkim * 433280304Sjkim */ 434238384Sjkimint gost2001_keygen(EC_KEY *ec) 435280304Sjkim{ 436280304Sjkim BIGNUM *order = BN_new(), *d = BN_new(); 437280304Sjkim const EC_GROUP *group = EC_KEY_get0_group(ec); 438238384Sjkim 439284285Sjkim if(!group || !EC_GROUP_get_order(group, order, NULL)) { 440284285Sjkim GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); 441284285Sjkim BN_free(d); 442284285Sjkim BN_free(order); 443284285Sjkim return 0; 444284285Sjkim } 445284285Sjkim 446280304Sjkim do { 447280304Sjkim if (!BN_rand_range(d, order)) { 448280304Sjkim GOSTerr(GOST_F_GOST2001_KEYGEN, 449280304Sjkim GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 450280304Sjkim BN_free(d); 451280304Sjkim BN_free(order); 452280304Sjkim return 0; 453280304Sjkim } 454280304Sjkim } 455280304Sjkim while (BN_is_zero(d)); 456284285Sjkim 457284285Sjkim if(!EC_KEY_set_private_key(ec, d)) { 458284285Sjkim GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); 459284285Sjkim BN_free(d); 460284285Sjkim BN_free(order); 461284285Sjkim return 0; 462284285Sjkim } 463280304Sjkim BN_free(d); 464280304Sjkim BN_free(order); 465280304Sjkim return gost2001_compute_public(ec); 466280304Sjkim} 467