gost2001.c revision 284285
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 17extern 18void dump_signature(const char *message, const unsigned char *buffer, 19 size_t len); 20void 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 */ 35int fill_GOST2001_params(EC_KEY *eckey, int nid) 36{ 37 R3410_2001_params *params = R3410_2001_paramset; 38 EC_GROUP *grp = NULL; 39 BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL; 40 EC_POINT *P = NULL; 41 BN_CTX *ctx = BN_CTX_new(); 42 int ok = 0; 43 44 if(!ctx) { 45 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 46 goto err; 47 } 48 49 BN_CTX_start(ctx); 50 p = BN_CTX_get(ctx); 51 a = BN_CTX_get(ctx); 52 b = BN_CTX_get(ctx); 53 x = BN_CTX_get(ctx); 54 y = BN_CTX_get(ctx); 55 q = BN_CTX_get(ctx); 56 if(!p || !a || !b || !x || !y || !q) { 57 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 58 goto err; 59 } 60 while (params->nid != NID_undef && params->nid != nid) 61 params++; 62 if (params->nid == NID_undef) { 63 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 64 GOST_R_UNSUPPORTED_PARAMETER_SET); 65 goto err; 66 } 67 if(!BN_hex2bn(&p, params->p) 68 || !BN_hex2bn(&a, params->a) 69 || !BN_hex2bn(&b, params->b)) { 70 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 71 ERR_R_INTERNAL_ERROR); 72 goto err; 73 } 74 75 grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); 76 if(!grp) { 77 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 78 goto err; 79 } 80 81 P = EC_POINT_new(grp); 82 if(!P) { 83 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); 84 goto err; 85 } 86 87 if(!BN_hex2bn(&x, params->x) 88 || !BN_hex2bn(&y, params->y) 89 || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx) 90 || !BN_hex2bn(&q, params->q)) { 91 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 92 goto err; 93 } 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 if(!EC_GROUP_set_generator(grp, P, q, NULL)) { 102 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 103 goto err; 104 } 105 EC_GROUP_set_curve_name(grp, params->nid); 106 if(!EC_KEY_set_group(eckey, grp)) { 107 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); 108 goto err; 109 } 110 ok = 1; 111 err: 112 if (P) EC_POINT_free(P); 113 if (grp) EC_GROUP_free(grp); 114 if (ctx) { 115 BN_CTX_end(ctx); 116 BN_CTX_free(ctx); 117 } 118 return ok; 119} 120 121/* 122 * Computes gost2001 signature as DSA_SIG structure 123 * 124 * 125 */ 126DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) 127{ 128 DSA_SIG *newsig = NULL, *ret = NULL; 129 BIGNUM *md = hashsum2bn(dgst); 130 BIGNUM *order = NULL; 131 const EC_GROUP *group; 132 const BIGNUM *priv_key; 133 BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = 134 NULL, *e = NULL; 135 EC_POINT *C = NULL; 136 BN_CTX *ctx = BN_CTX_new(); 137 if(!ctx || !md) { 138 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 139 goto err; 140 } 141 BN_CTX_start(ctx); 142 OPENSSL_assert(dlen == 32); 143 newsig = DSA_SIG_new(); 144 if (!newsig) { 145 GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_NO_MEMORY); 146 goto err; 147 } 148 group = EC_KEY_get0_group(eckey); 149 if(!group) { 150 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 151 goto err; 152 } 153 order = BN_CTX_get(ctx); 154 if(!order || !EC_GROUP_get_order(group, order, ctx)) { 155 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 156 goto err; 157 } 158 priv_key = EC_KEY_get0_private_key(eckey); 159 if(!priv_key) { 160 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 161 goto err; 162 } 163 e = BN_CTX_get(ctx); 164 if(!e || !BN_mod(e, md, order, ctx)) { 165 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 166 goto err; 167 } 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 if (BN_is_zero(e)) { 176 BN_one(e); 177 } 178 k = BN_CTX_get(ctx); 179 C = EC_POINT_new(group); 180 if(!k || !C) { 181 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 182 goto err; 183 } 184 do { 185 do { 186 if (!BN_rand_range(k, order)) { 187 GOSTerr(GOST_F_GOST2001_DO_SIGN, 188 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 189 goto err; 190 } 191 if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { 192 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 193 goto err; 194 } 195 if (!X) 196 X = BN_CTX_get(ctx); 197 if (!r) 198 r = BN_CTX_get(ctx); 199 if (!X || !r) { 200 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 201 goto err; 202 } 203 if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 204 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 205 goto err; 206 } 207 208 if(!BN_nnmod(r, X, order, ctx)) { 209 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 210 goto err; 211 } 212 } 213 while (BN_is_zero(r)); 214 /* s = (r*priv_key+k*e) mod order */ 215 if (!tmp) 216 tmp = BN_CTX_get(ctx); 217 if (!tmp2) 218 tmp2 = BN_CTX_get(ctx); 219 if (!s) 220 s = BN_CTX_get(ctx); 221 if (!tmp || !tmp2 || !s) { 222 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 223 goto err; 224 } 225 226 if(!BN_mod_mul(tmp, priv_key, r, order, ctx) 227 || !BN_mod_mul(tmp2, k, e, order, ctx) 228 || !BN_mod_add(s, tmp, tmp2, order, ctx)) { 229 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); 230 goto err; 231 } 232 } 233 while (BN_is_zero(s)); 234 235 newsig->s = BN_dup(s); 236 newsig->r = BN_dup(r); 237 if(!newsig->s || !newsig->r) { 238 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); 239 goto err; 240 } 241 242 ret = newsig; 243 err: 244 if(ctx) { 245 BN_CTX_end(ctx); 246 BN_CTX_free(ctx); 247 } 248 if (C) EC_POINT_free(C); 249 if (md) BN_free(md); 250 if (!ret && newsig) { 251 DSA_SIG_free(newsig); 252 } 253 return ret; 254} 255 256/* 257 * Verifies gost 2001 signature 258 * 259 */ 260int gost2001_do_verify(const unsigned char *dgst, int dgst_len, 261 DSA_SIG *sig, EC_KEY *ec) 262{ 263 BN_CTX *ctx = BN_CTX_new(); 264 const EC_GROUP *group = EC_KEY_get0_group(ec); 265 BIGNUM *order; 266 BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = 267 NULL; 268 BIGNUM *X = NULL, *tmp = NULL; 269 EC_POINT *C = NULL; 270 const EC_POINT *pub_key = NULL; 271 int ok = 0; 272 273 if(!ctx || !group) { 274 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 275 goto err; 276 } 277 278 BN_CTX_start(ctx); 279 order = BN_CTX_get(ctx); 280 e = BN_CTX_get(ctx); 281 z1 = BN_CTX_get(ctx); 282 z2 = BN_CTX_get(ctx); 283 tmp = BN_CTX_get(ctx); 284 X = BN_CTX_get(ctx); 285 R = BN_CTX_get(ctx); 286 v = BN_CTX_get(ctx); 287 if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) { 288 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); 289 goto err; 290 } 291 292 pub_key = EC_KEY_get0_public_key(ec); 293 if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) { 294 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 295 goto err; 296 } 297 298 if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || 299 (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { 300 GOSTerr(GOST_F_GOST2001_DO_VERIFY, 301 GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 302 goto err; 303 304 } 305 md = hashsum2bn(dgst); 306 307 if(!md || !BN_mod(e, md, order, ctx)) { 308 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 309 goto err; 310 } 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 if (BN_is_zero(e) && !BN_one(e)) { 318 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 319 goto err; 320 } 321 v = BN_mod_inverse(v, e, order, ctx); 322 if(!v 323 || !BN_mod_mul(z1, sig->s, v, order, ctx) 324 || !BN_sub(tmp, order, sig->r) 325 || !BN_mod_mul(z2, tmp, v, order, ctx)) { 326 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 327 goto err; 328 } 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 C = EC_POINT_new(group); 338 if (!C) { 339 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); 340 goto err; 341 } 342 if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { 343 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 344 goto err; 345 } 346 if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 347 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 348 goto err; 349 } 350 if(!BN_mod(R, X, order, ctx)) { 351 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); 352 goto err; 353 } 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 if (BN_cmp(R, sig->r) != 0) { 362 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 363 } else { 364 ok = 1; 365 } 366 err: 367 if (C) EC_POINT_free(C); 368 if (ctx) { 369 BN_CTX_end(ctx); 370 BN_CTX_free(ctx); 371 } 372 if (md) BN_free(md); 373 return ok; 374} 375 376/* 377 * Computes GOST R 34.10-2001 public key 378 * 379 * 380 */ 381int gost2001_compute_public(EC_KEY *ec) 382{ 383 const EC_GROUP *group = EC_KEY_get0_group(ec); 384 EC_POINT *pub_key = NULL; 385 const BIGNUM *priv_key = NULL; 386 BN_CTX *ctx = NULL; 387 int ok = 0; 388 389 if (!group) { 390 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, 391 GOST_R_KEY_IS_NOT_INITIALIZED); 392 return 0; 393 } 394 ctx = BN_CTX_new(); 395 if(!ctx) { 396 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 397 goto err; 398 } 399 BN_CTX_start(ctx); 400 if (!(priv_key = EC_KEY_get0_private_key(ec))) { 401 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 402 goto err; 403 } 404 405 pub_key = EC_POINT_new(group); 406 if(!pub_key) { 407 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 408 goto err; 409 } 410 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { 411 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 412 goto err; 413 } 414 if (!EC_KEY_set_public_key(ec, pub_key)) { 415 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 416 goto err; 417 } 418 ok = 256; 419 err: 420 if (pub_key) EC_POINT_free(pub_key); 421 if (ctx) { 422 BN_CTX_end(ctx); 423 BN_CTX_free(ctx); 424 } 425 return ok; 426} 427 428/* 429 * 430 * Generates GOST R 34.10-2001 keypair 431 * 432 * 433 */ 434int gost2001_keygen(EC_KEY *ec) 435{ 436 BIGNUM *order = BN_new(), *d = BN_new(); 437 const EC_GROUP *group = EC_KEY_get0_group(ec); 438 439 if(!group || !EC_GROUP_get_order(group, order, NULL)) { 440 GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); 441 BN_free(d); 442 BN_free(order); 443 return 0; 444 } 445 446 do { 447 if (!BN_rand_range(d, order)) { 448 GOSTerr(GOST_F_GOST2001_KEYGEN, 449 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 450 BN_free(d); 451 BN_free(order); 452 return 0; 453 } 454 } 455 while (BN_is_zero(d)); 456 457 if(!EC_KEY_set_private_key(ec, d)) { 458 GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); 459 BN_free(d); 460 BN_free(order); 461 return 0; 462 } 463 BN_free(d); 464 BN_free(order); 465 return gost2001_compute_public(ec); 466} 467