1238384Sjkim/********************************************************************** 2238384Sjkim * gost2001.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6296341Sdelphij * 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 17296341Sdelphijextern 18296341Sdelphijvoid dump_signature(const char *message, const unsigned char *buffer, 19296341Sdelphij size_t len); 20238384Sjkimvoid dump_dsa_sig(const char *message, DSA_SIG *sig); 21238384Sjkim#else 22238384Sjkim 23296341Sdelphij# define dump_signature(a,b,c) 24296341Sdelphij# 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 34296341Sdelphij */ 35238384Sjkimint fill_GOST2001_params(EC_KEY *eckey, int nid) 36296341Sdelphij{ 37296341Sdelphij R3410_2001_params *params = R3410_2001_paramset; 38296341Sdelphij EC_GROUP *grp = NULL; 39296341Sdelphij BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; 40296341Sdelphij EC_POINT *P = NULL; 41296341Sdelphij BN_CTX *ctx = BN_CTX_new(); 42296341Sdelphij int ok = 0; 43238384Sjkim 44296341Sdelphij if(!ctx) { 45296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 46296341Sdelphij goto err; 47296341Sdelphij } 48238384Sjkim 49296341Sdelphij BN_CTX_start(ctx); 50296341Sdelphij p = BN_CTX_get(ctx); 51296341Sdelphij a = BN_CTX_get(ctx); 52296341Sdelphij b = BN_CTX_get(ctx); 53296341Sdelphij x = BN_CTX_get(ctx); 54296341Sdelphij y = BN_CTX_get(ctx); 55296341Sdelphij q = BN_CTX_get(ctx); 56296341Sdelphij if(!p || !a || !b || !x || !y || !q) { 57296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 58296341Sdelphij goto err; 59296341Sdelphij } 60296341Sdelphij while (params->nid != NID_undef && params->nid != nid) 61296341Sdelphij params++; 62296341Sdelphij if (params->nid == NID_undef) { 63296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 64296341Sdelphij GOST_R_UNSUPPORTED_PARAMETER_SET); 65296341Sdelphij goto err; 66296341Sdelphij } 67296341Sdelphij if(!BN_hex2bn(&p, params->p) 68296341Sdelphij || !BN_hex2bn(&a, params->a) 69296341Sdelphij || !BN_hex2bn(&b, params->b)) { 70296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 71296341Sdelphij ERR_R_INTERNAL_ERROR); 72296341Sdelphij goto err; 73296341Sdelphij } 74238384Sjkim 75296341Sdelphij grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); 76296341Sdelphij if(!grp) { 77296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 78296341Sdelphij goto err; 79296341Sdelphij } 80238384Sjkim 81296341Sdelphij P = EC_POINT_new(grp); 82296341Sdelphij if(!P) { 83296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 84296341Sdelphij goto err; 85296341Sdelphij } 86238384Sjkim 87296341Sdelphij if(!BN_hex2bn(&x, params->x) 88296341Sdelphij || !BN_hex2bn(&y, params->y) 89296341Sdelphij || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx) 90296341Sdelphij || !BN_hex2bn(&q, params->q)) { 91296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 92296341Sdelphij goto err; 93296341Sdelphij } 94296341Sdelphij#ifdef DEBUG_KEYS 95296341Sdelphij fprintf(stderr, "Set params index %d oid %s\nq=", 96296341Sdelphij (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); 97296341Sdelphij BN_print_fp(stderr, q); 98296341Sdelphij fprintf(stderr, "\n"); 99296341Sdelphij#endif 100238384Sjkim 101296341Sdelphij if(!EC_GROUP_set_generator(grp, P, q, NULL)) { 102296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 103296341Sdelphij goto err; 104296341Sdelphij } 105296341Sdelphij EC_GROUP_set_curve_name(grp, params->nid); 106296341Sdelphij if(!EC_KEY_set_group(eckey, grp)) { 107296341Sdelphij GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 108296341Sdelphij goto err; 109296341Sdelphij } 110296341Sdelphij ok = 1; 111296341Sdelphij err: 112296341Sdelphij if (P) EC_POINT_free(P); 113296341Sdelphij if (grp) EC_GROUP_free(grp); 114296341Sdelphij if (ctx) { 115296341Sdelphij BN_CTX_end(ctx); 116296341Sdelphij BN_CTX_free(ctx); 117296341Sdelphij } 118296341Sdelphij return ok; 119296341Sdelphij} 120296341Sdelphij 121238384Sjkim/* 122296341Sdelphij * Computes gost2001 signature as DSA_SIG structure 123238384Sjkim * 124238384Sjkim * 125296341Sdelphij */ 126296341SdelphijDSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) 127296341Sdelphij{ 128296341Sdelphij DSA_SIG *newsig = NULL, *ret = NULL; 129296341Sdelphij BIGNUM *md = hashsum2bn(dgst); 130296341Sdelphij BIGNUM *order = NULL; 131296341Sdelphij const EC_GROUP *group; 132296341Sdelphij const BIGNUM *priv_key; 133296341Sdelphij BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = 134296341Sdelphij NULL, *e = NULL; 135296341Sdelphij EC_POINT *C = NULL; 136296341Sdelphij BN_CTX *ctx = BN_CTX_new(); 137296341Sdelphij if(!ctx || !md) { 138296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 139296341Sdelphij goto err; 140296341Sdelphij } 141296341Sdelphij BN_CTX_start(ctx); 142296341Sdelphij OPENSSL_assert(dlen == 32); 143296341Sdelphij newsig = DSA_SIG_new(); 144296341Sdelphij if (!newsig) { 145296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_NO_MEMORY); 146296341Sdelphij goto err; 147296341Sdelphij } 148296341Sdelphij group = EC_KEY_get0_group(eckey); 149296341Sdelphij if(!group) { 150296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 151296341Sdelphij goto err; 152296341Sdelphij } 153296341Sdelphij order = BN_CTX_get(ctx); 154296341Sdelphij if(!order || !EC_GROUP_get_order(group, order, ctx)) { 155296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 156296341Sdelphij goto err; 157296341Sdelphij } 158296341Sdelphij priv_key = EC_KEY_get0_private_key(eckey); 159296341Sdelphij if(!priv_key) { 160296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 161296341Sdelphij goto err; 162296341Sdelphij } 163296341Sdelphij e = BN_CTX_get(ctx); 164296341Sdelphij if(!e || !BN_mod(e, md, order, ctx)) { 165296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 166296341Sdelphij goto err; 167296341Sdelphij } 168238384Sjkim#ifdef DEBUG_SIGN 169296341Sdelphij fprintf(stderr, "digest as bignum="); 170296341Sdelphij BN_print_fp(stderr, md); 171296341Sdelphij fprintf(stderr, "\ndigest mod q="); 172296341Sdelphij BN_print_fp(stderr, e); 173296341Sdelphij fprintf(stderr, "\n"); 174296341Sdelphij#endif 175296341Sdelphij if (BN_is_zero(e)) { 176296341Sdelphij BN_one(e); 177296341Sdelphij } 178296341Sdelphij k = BN_CTX_get(ctx); 179296341Sdelphij C = EC_POINT_new(group); 180296341Sdelphij if(!k || !C) { 181296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 182296341Sdelphij goto err; 183296341Sdelphij } 184296341Sdelphij do { 185296341Sdelphij do { 186296341Sdelphij if (!BN_rand_range(k, order)) { 187296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, 188296341Sdelphij GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 189296341Sdelphij goto err; 190296341Sdelphij } 191296341Sdelphij if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { 192296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 193296341Sdelphij goto err; 194296341Sdelphij } 195296341Sdelphij if (!X) 196296341Sdelphij X = BN_CTX_get(ctx); 197296341Sdelphij if (!r) 198296341Sdelphij r = BN_CTX_get(ctx); 199296341Sdelphij if (!X || !r) { 200296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 201296341Sdelphij goto err; 202296341Sdelphij } 203296341Sdelphij if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 204296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 205296341Sdelphij goto err; 206296341Sdelphij } 207238384Sjkim 208296341Sdelphij if(!BN_nnmod(r, X, order, ctx)) { 209296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 210296341Sdelphij goto err; 211296341Sdelphij } 212296341Sdelphij } 213296341Sdelphij while (BN_is_zero(r)); 214296341Sdelphij /* s = (r*priv_key+k*e) mod order */ 215296341Sdelphij if (!tmp) 216296341Sdelphij tmp = BN_CTX_get(ctx); 217296341Sdelphij if (!tmp2) 218296341Sdelphij tmp2 = BN_CTX_get(ctx); 219296341Sdelphij if (!s) 220296341Sdelphij s = BN_CTX_get(ctx); 221296341Sdelphij if (!tmp || !tmp2 || !s) { 222296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 223296341Sdelphij goto err; 224296341Sdelphij } 225296341Sdelphij 226296341Sdelphij if(!BN_mod_mul(tmp, priv_key, r, order, ctx) 227296341Sdelphij || !BN_mod_mul(tmp2, k, e, order, ctx) 228296341Sdelphij || !BN_mod_add(s, tmp, tmp2, order, ctx)) { 229296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 230296341Sdelphij goto err; 231296341Sdelphij } 232296341Sdelphij } 233296341Sdelphij while (BN_is_zero(s)); 234296341Sdelphij 235296341Sdelphij newsig->s = BN_dup(s); 236296341Sdelphij newsig->r = BN_dup(r); 237296341Sdelphij if(!newsig->s || !newsig->r) { 238296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 239296341Sdelphij goto err; 240296341Sdelphij } 241296341Sdelphij 242296341Sdelphij ret = newsig; 243296341Sdelphij err: 244296341Sdelphij if(ctx) { 245296341Sdelphij BN_CTX_end(ctx); 246296341Sdelphij BN_CTX_free(ctx); 247296341Sdelphij } 248296341Sdelphij if (C) EC_POINT_free(C); 249296341Sdelphij if (md) BN_free(md); 250296341Sdelphij if (!ret && newsig) { 251296341Sdelphij DSA_SIG_free(newsig); 252296341Sdelphij } 253296341Sdelphij return ret; 254296341Sdelphij} 255296341Sdelphij 256238384Sjkim/* 257238384Sjkim * Verifies gost 2001 signature 258238384Sjkim * 259296341Sdelphij */ 260296341Sdelphijint gost2001_do_verify(const unsigned char *dgst, int dgst_len, 261296341Sdelphij DSA_SIG *sig, EC_KEY *ec) 262296341Sdelphij{ 263296341Sdelphij BN_CTX *ctx = BN_CTX_new(); 264296341Sdelphij const EC_GROUP *group = EC_KEY_get0_group(ec); 265296341Sdelphij BIGNUM *order; 266296341Sdelphij BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = 267296341Sdelphij NULL; 268296341Sdelphij BIGNUM *X = NULL, *tmp = NULL; 269296341Sdelphij EC_POINT *C = NULL; 270296341Sdelphij const EC_POINT *pub_key = NULL; 271296341Sdelphij int ok = 0; 272238384Sjkim 273296341Sdelphij if(!ctx || !group) { 274296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 275296341Sdelphij goto err; 276296341Sdelphij } 277238384Sjkim 278296341Sdelphij BN_CTX_start(ctx); 279296341Sdelphij order = BN_CTX_get(ctx); 280296341Sdelphij e = BN_CTX_get(ctx); 281296341Sdelphij z1 = BN_CTX_get(ctx); 282296341Sdelphij z2 = BN_CTX_get(ctx); 283296341Sdelphij tmp = BN_CTX_get(ctx); 284296341Sdelphij X = BN_CTX_get(ctx); 285296341Sdelphij R = BN_CTX_get(ctx); 286296341Sdelphij v = BN_CTX_get(ctx); 287296341Sdelphij if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) { 288296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); 289296341Sdelphij goto err; 290296341Sdelphij } 291238384Sjkim 292296341Sdelphij pub_key = EC_KEY_get0_public_key(ec); 293296341Sdelphij if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) { 294296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 295296341Sdelphij goto err; 296296341Sdelphij } 297296341Sdelphij 298296341Sdelphij if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || 299296341Sdelphij (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { 300296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, 301296341Sdelphij GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 302296341Sdelphij goto err; 303296341Sdelphij 304296341Sdelphij } 305296341Sdelphij md = hashsum2bn(dgst); 306296341Sdelphij 307296341Sdelphij if(!md || !BN_mod(e, md, order, ctx)) { 308296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 309296341Sdelphij goto err; 310296341Sdelphij } 311238384Sjkim#ifdef DEBUG_SIGN 312296341Sdelphij fprintf(stderr, "digest as bignum: "); 313296341Sdelphij BN_print_fp(stderr, md); 314296341Sdelphij fprintf(stderr, "\ndigest mod q: "); 315296341Sdelphij BN_print_fp(stderr, e); 316296341Sdelphij#endif 317296341Sdelphij if (BN_is_zero(e) && !BN_one(e)) { 318296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 319296341Sdelphij goto err; 320296341Sdelphij } 321296341Sdelphij v = BN_mod_inverse(v, e, order, ctx); 322296341Sdelphij if(!v 323296341Sdelphij || !BN_mod_mul(z1, sig->s, v, order, ctx) 324296341Sdelphij || !BN_sub(tmp, order, sig->r) 325296341Sdelphij || !BN_mod_mul(z2, tmp, v, order, ctx)) { 326296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 327296341Sdelphij goto err; 328296341Sdelphij } 329238384Sjkim#ifdef DEBUG_SIGN 330296341Sdelphij fprintf(stderr, "\nInverted digest value: "); 331296341Sdelphij BN_print_fp(stderr, v); 332296341Sdelphij fprintf(stderr, "\nz1: "); 333296341Sdelphij BN_print_fp(stderr, z1); 334296341Sdelphij fprintf(stderr, "\nz2: "); 335296341Sdelphij BN_print_fp(stderr, z2); 336296341Sdelphij#endif 337296341Sdelphij C = EC_POINT_new(group); 338296341Sdelphij if (!C) { 339296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); 340296341Sdelphij goto err; 341296341Sdelphij } 342296341Sdelphij if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { 343296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 344296341Sdelphij goto err; 345296341Sdelphij } 346296341Sdelphij if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 347296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 348296341Sdelphij goto err; 349296341Sdelphij } 350296341Sdelphij if(!BN_mod(R, X, order, ctx)) { 351296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 352296341Sdelphij goto err; 353296341Sdelphij } 354238384Sjkim#ifdef DEBUG_SIGN 355296341Sdelphij fprintf(stderr, "\nX="); 356296341Sdelphij BN_print_fp(stderr, X); 357296341Sdelphij fprintf(stderr, "\nX mod q="); 358296341Sdelphij BN_print_fp(stderr, R); 359296341Sdelphij fprintf(stderr, "\n"); 360296341Sdelphij#endif 361296341Sdelphij if (BN_cmp(R, sig->r) != 0) { 362296341Sdelphij GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 363296341Sdelphij } else { 364296341Sdelphij ok = 1; 365296341Sdelphij } 366296341Sdelphij err: 367296341Sdelphij if (C) EC_POINT_free(C); 368296341Sdelphij if (ctx) { 369296341Sdelphij BN_CTX_end(ctx); 370296341Sdelphij BN_CTX_free(ctx); 371296341Sdelphij } 372296341Sdelphij if (md) BN_free(md); 373296341Sdelphij return ok; 374296341Sdelphij} 375296341Sdelphij 376238384Sjkim/* 377238384Sjkim * Computes GOST R 34.10-2001 public key 378238384Sjkim * 379238384Sjkim * 380296341Sdelphij */ 381296341Sdelphijint gost2001_compute_public(EC_KEY *ec) 382296341Sdelphij{ 383296341Sdelphij const EC_GROUP *group = EC_KEY_get0_group(ec); 384296341Sdelphij EC_POINT *pub_key = NULL; 385296341Sdelphij const BIGNUM *priv_key = NULL; 386296341Sdelphij BN_CTX *ctx = NULL; 387296341Sdelphij int ok = 0; 388238384Sjkim 389296341Sdelphij if (!group) { 390296341Sdelphij GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, 391296341Sdelphij GOST_R_KEY_IS_NOT_INITIALIZED); 392296341Sdelphij return 0; 393296341Sdelphij } 394296341Sdelphij ctx = BN_CTX_new(); 395296341Sdelphij if(!ctx) { 396296341Sdelphij GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 397296341Sdelphij goto err; 398296341Sdelphij } 399296341Sdelphij BN_CTX_start(ctx); 400296341Sdelphij if (!(priv_key = EC_KEY_get0_private_key(ec))) { 401296341Sdelphij GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 402296341Sdelphij goto err; 403296341Sdelphij } 404238384Sjkim 405296341Sdelphij pub_key = EC_POINT_new(group); 406296341Sdelphij if(!pub_key) { 407296341Sdelphij GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 408296341Sdelphij goto err; 409296341Sdelphij } 410296341Sdelphij if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { 411296341Sdelphij GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 412296341Sdelphij goto err; 413296341Sdelphij } 414296341Sdelphij if (!EC_KEY_set_public_key(ec, pub_key)) { 415296341Sdelphij GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 416296341Sdelphij goto err; 417296341Sdelphij } 418296341Sdelphij ok = 256; 419296341Sdelphij err: 420296341Sdelphij if (pub_key) EC_POINT_free(pub_key); 421296341Sdelphij if (ctx) { 422296341Sdelphij BN_CTX_end(ctx); 423296341Sdelphij BN_CTX_free(ctx); 424296341Sdelphij } 425296341Sdelphij return ok; 426296341Sdelphij} 427296341Sdelphij 428238384Sjkim/* 429296341Sdelphij * 430238384Sjkim * Generates GOST R 34.10-2001 keypair 431238384Sjkim * 432238384Sjkim * 433296341Sdelphij */ 434238384Sjkimint gost2001_keygen(EC_KEY *ec) 435296341Sdelphij{ 436296341Sdelphij BIGNUM *order = BN_new(), *d = BN_new(); 437296341Sdelphij const EC_GROUP *group = EC_KEY_get0_group(ec); 438238384Sjkim 439296341Sdelphij if(!group || !EC_GROUP_get_order(group, order, NULL)) { 440296341Sdelphij GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); 441296341Sdelphij BN_free(d); 442296341Sdelphij BN_free(order); 443296341Sdelphij return 0; 444296341Sdelphij } 445296341Sdelphij 446296341Sdelphij do { 447296341Sdelphij if (!BN_rand_range(d, order)) { 448296341Sdelphij GOSTerr(GOST_F_GOST2001_KEYGEN, 449296341Sdelphij GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 450296341Sdelphij BN_free(d); 451296341Sdelphij BN_free(order); 452296341Sdelphij return 0; 453296341Sdelphij } 454296341Sdelphij } 455296341Sdelphij while (BN_is_zero(d)); 456296341Sdelphij 457296341Sdelphij if(!EC_KEY_set_private_key(ec, d)) { 458296341Sdelphij GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); 459296341Sdelphij BN_free(d); 460296341Sdelphij BN_free(order); 461296341Sdelphij return 0; 462296341Sdelphij } 463296341Sdelphij BN_free(d); 464296341Sdelphij BN_free(order); 465296341Sdelphij return gost2001_compute_public(ec); 466296341Sdelphij} 467