gost2001.c revision 280304
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 BN_CTX_start(ctx); 45 p = BN_CTX_get(ctx); 46 a = BN_CTX_get(ctx); 47 b = BN_CTX_get(ctx); 48 x = BN_CTX_get(ctx); 49 y = BN_CTX_get(ctx); 50 q = BN_CTX_get(ctx); 51 while (params->nid != NID_undef && params->nid != nid) 52 params++; 53 if (params->nid == NID_undef) { 54 GOSTerr(GOST_F_FILL_GOST2001_PARAMS, 55 GOST_R_UNSUPPORTED_PARAMETER_SET); 56 goto err; 57 } 58 BN_hex2bn(&p, params->p); 59 BN_hex2bn(&a, params->a); 60 BN_hex2bn(&b, params->b); 61 62 grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); 63 64 P = EC_POINT_new(grp); 65 66 BN_hex2bn(&x, params->x); 67 BN_hex2bn(&y, params->y); 68 EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx); 69 BN_hex2bn(&q, params->q); 70#ifdef DEBUG_KEYS 71 fprintf(stderr, "Set params index %d oid %s\nq=", 72 (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); 73 BN_print_fp(stderr, q); 74 fprintf(stderr, "\n"); 75#endif 76 77 EC_GROUP_set_generator(grp, P, q, NULL); 78 EC_GROUP_set_curve_name(grp, params->nid); 79 80 EC_KEY_set_group(eckey, grp); 81 ok = 1; 82 err: 83 EC_POINT_free(P); 84 EC_GROUP_free(grp); 85 BN_CTX_end(ctx); 86 BN_CTX_free(ctx); 87 return ok; 88} 89 90/* 91 * Computes gost2001 signature as DSA_SIG structure 92 * 93 * 94 */ 95DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) 96{ 97 DSA_SIG *newsig = NULL; 98 BIGNUM *md = hashsum2bn(dgst); 99 BIGNUM *order = NULL; 100 const EC_GROUP *group; 101 const BIGNUM *priv_key; 102 BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k = 103 NULL, *e = NULL; 104 EC_POINT *C = NULL; 105 BN_CTX *ctx = BN_CTX_new(); 106 BN_CTX_start(ctx); 107 OPENSSL_assert(dlen == 32); 108 newsig = DSA_SIG_new(); 109 if (!newsig) { 110 GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_NO_MEMORY); 111 goto err; 112 } 113 group = EC_KEY_get0_group(eckey); 114 order = BN_CTX_get(ctx); 115 EC_GROUP_get_order(group, order, ctx); 116 priv_key = EC_KEY_get0_private_key(eckey); 117 e = BN_CTX_get(ctx); 118 BN_mod(e, md, order, ctx); 119#ifdef DEBUG_SIGN 120 fprintf(stderr, "digest as bignum="); 121 BN_print_fp(stderr, md); 122 fprintf(stderr, "\ndigest mod q="); 123 BN_print_fp(stderr, e); 124 fprintf(stderr, "\n"); 125#endif 126 if (BN_is_zero(e)) { 127 BN_one(e); 128 } 129 k = BN_CTX_get(ctx); 130 C = EC_POINT_new(group); 131 do { 132 do { 133 if (!BN_rand_range(k, order)) { 134 GOSTerr(GOST_F_GOST2001_DO_SIGN, 135 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 136 DSA_SIG_free(newsig); 137 newsig = NULL; 138 goto err; 139 } 140 if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { 141 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 142 DSA_SIG_free(newsig); 143 newsig = NULL; 144 goto err; 145 } 146 if (!X) 147 X = BN_CTX_get(ctx); 148 if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 149 GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); 150 DSA_SIG_free(newsig); 151 newsig = NULL; 152 goto err; 153 } 154 if (!r) 155 r = BN_CTX_get(ctx); 156 BN_nnmod(r, X, order, ctx); 157 } 158 while (BN_is_zero(r)); 159 /* s = (r*priv_key+k*e) mod order */ 160 if (!tmp) 161 tmp = BN_CTX_get(ctx); 162 BN_mod_mul(tmp, priv_key, r, order, ctx); 163 if (!tmp2) 164 tmp2 = BN_CTX_get(ctx); 165 BN_mod_mul(tmp2, k, e, order, ctx); 166 if (!s) 167 s = BN_CTX_get(ctx); 168 BN_mod_add(s, tmp, tmp2, order, ctx); 169 } 170 while (BN_is_zero(s)); 171 172 newsig->s = BN_dup(s); 173 newsig->r = BN_dup(r); 174 err: 175 BN_CTX_end(ctx); 176 BN_CTX_free(ctx); 177 EC_POINT_free(C); 178 BN_free(md); 179 return newsig; 180} 181 182/* 183 * Verifies gost 2001 signature 184 * 185 */ 186int gost2001_do_verify(const unsigned char *dgst, int dgst_len, 187 DSA_SIG *sig, EC_KEY *ec) 188{ 189 BN_CTX *ctx = BN_CTX_new(); 190 const EC_GROUP *group = EC_KEY_get0_group(ec); 191 BIGNUM *order; 192 BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = 193 NULL; 194 BIGNUM *X = NULL, *tmp = NULL; 195 EC_POINT *C = NULL; 196 const EC_POINT *pub_key = NULL; 197 int ok = 0; 198 199 BN_CTX_start(ctx); 200 order = BN_CTX_get(ctx); 201 e = BN_CTX_get(ctx); 202 z1 = BN_CTX_get(ctx); 203 z2 = BN_CTX_get(ctx); 204 tmp = BN_CTX_get(ctx); 205 X = BN_CTX_get(ctx); 206 R = BN_CTX_get(ctx); 207 v = BN_CTX_get(ctx); 208 209 EC_GROUP_get_order(group, order, ctx); 210 pub_key = EC_KEY_get0_public_key(ec); 211 if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || 212 (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { 213 GOSTerr(GOST_F_GOST2001_DO_VERIFY, 214 GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 215 goto err; 216 217 } 218 md = hashsum2bn(dgst); 219 220 BN_mod(e, md, order, ctx); 221#ifdef DEBUG_SIGN 222 fprintf(stderr, "digest as bignum: "); 223 BN_print_fp(stderr, md); 224 fprintf(stderr, "\ndigest mod q: "); 225 BN_print_fp(stderr, e); 226#endif 227 if (BN_is_zero(e)) 228 BN_one(e); 229 v = BN_mod_inverse(v, e, order, ctx); 230 BN_mod_mul(z1, sig->s, v, order, ctx); 231 BN_sub(tmp, order, sig->r); 232 BN_mod_mul(z2, tmp, v, order, ctx); 233#ifdef DEBUG_SIGN 234 fprintf(stderr, "\nInverted digest value: "); 235 BN_print_fp(stderr, v); 236 fprintf(stderr, "\nz1: "); 237 BN_print_fp(stderr, z1); 238 fprintf(stderr, "\nz2: "); 239 BN_print_fp(stderr, z2); 240#endif 241 C = EC_POINT_new(group); 242 if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { 243 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 244 goto err; 245 } 246 if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { 247 GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); 248 goto err; 249 } 250 BN_mod(R, X, order, ctx); 251#ifdef DEBUG_SIGN 252 fprintf(stderr, "\nX="); 253 BN_print_fp(stderr, X); 254 fprintf(stderr, "\nX mod q="); 255 BN_print_fp(stderr, R); 256 fprintf(stderr, "\n"); 257#endif 258 if (BN_cmp(R, sig->r) != 0) { 259 GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 260 } else { 261 ok = 1; 262 } 263 err: 264 EC_POINT_free(C); 265 BN_CTX_end(ctx); 266 BN_CTX_free(ctx); 267 BN_free(md); 268 return ok; 269} 270 271/* 272 * Computes GOST R 34.10-2001 public key 273 * 274 * 275 */ 276int gost2001_compute_public(EC_KEY *ec) 277{ 278 const EC_GROUP *group = EC_KEY_get0_group(ec); 279 EC_POINT *pub_key = NULL; 280 const BIGNUM *priv_key = NULL; 281 BN_CTX *ctx = NULL; 282 int ok = 0; 283 284 if (!group) { 285 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, 286 GOST_R_KEY_IS_NOT_INITIALIZED); 287 return 0; 288 } 289 ctx = BN_CTX_new(); 290 BN_CTX_start(ctx); 291 if (!(priv_key = EC_KEY_get0_private_key(ec))) { 292 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 293 goto err; 294 } 295 296 pub_key = EC_POINT_new(group); 297 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { 298 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 299 goto err; 300 } 301 if (!EC_KEY_set_public_key(ec, pub_key)) { 302 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); 303 goto err; 304 } 305 ok = 256; 306 err: 307 BN_CTX_end(ctx); 308 EC_POINT_free(pub_key); 309 BN_CTX_free(ctx); 310 return ok; 311} 312 313/* 314 * 315 * Generates GOST R 34.10-2001 keypair 316 * 317 * 318 */ 319int gost2001_keygen(EC_KEY *ec) 320{ 321 BIGNUM *order = BN_new(), *d = BN_new(); 322 const EC_GROUP *group = EC_KEY_get0_group(ec); 323 EC_GROUP_get_order(group, order, NULL); 324 325 do { 326 if (!BN_rand_range(d, order)) { 327 GOSTerr(GOST_F_GOST2001_KEYGEN, 328 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); 329 BN_free(d); 330 BN_free(order); 331 return 0; 332 } 333 } 334 while (BN_is_zero(d)); 335 EC_KEY_set_private_key(ec, d); 336 BN_free(d); 337 BN_free(order); 338 return gost2001_compute_public(ec); 339} 340