gost_sign.c revision 284285
1/********************************************************************** 2 * gost_sign.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-94 signature algorithm * 7 * for OpenSSL * 8 * Requires OpenSSL 0.9.9 for compilation * 9 **********************************************************************/ 10#include <string.h> 11#include <openssl/rand.h> 12#include <openssl/bn.h> 13#include <openssl/dsa.h> 14#include <openssl/evp.h> 15#include <openssl/err.h> 16 17#include "gost_params.h" 18#include "gost_lcl.h" 19#include "e_gost_err.h" 20 21#ifdef DEBUG_SIGN 22void dump_signature(const char *message, const unsigned char *buffer, 23 size_t len) 24{ 25 size_t i; 26 fprintf(stderr, "signature %s Length=%d", message, len); 27 for (i = 0; i < len; i++) { 28 if (i % 16 == 0) 29 fputc('\n', stderr); 30 fprintf(stderr, " %02x", buffer[i]); 31 } 32 fprintf(stderr, "\nEnd of signature\n"); 33} 34 35void dump_dsa_sig(const char *message, DSA_SIG *sig) 36{ 37 fprintf(stderr, "%s\nR=", message); 38 BN_print_fp(stderr, sig->r); 39 fprintf(stderr, "\nS="); 40 BN_print_fp(stderr, sig->s); 41 fprintf(stderr, "\n"); 42} 43 44#else 45 46# define dump_signature(a,b,c) 47# define dump_dsa_sig(a,b) 48#endif 49 50/* 51 * Computes signature and returns it as DSA_SIG structure 52 */ 53DSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 54{ 55 BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; 56 DSA_SIG *newsig = NULL, *ret = NULL; 57 BIGNUM *md = hashsum2bn(dgst); 58 /* check if H(M) mod q is zero */ 59 BN_CTX *ctx = BN_CTX_new(); 60 if(!ctx) { 61 GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 62 goto err; 63 } 64 BN_CTX_start(ctx); 65 newsig = DSA_SIG_new(); 66 if (!newsig) { 67 GOSTerr(GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); 68 goto err; 69 } 70 tmp = BN_CTX_get(ctx); 71 k = BN_CTX_get(ctx); 72 tmp2 = BN_CTX_get(ctx); 73 if(!tmp || !k || !tmp2) { 74 GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 75 goto err; 76 } 77 BN_mod(tmp, md, dsa->q, ctx); 78 if (BN_is_zero(tmp)) { 79 BN_one(md); 80 } 81 do { 82 do { 83 /* 84 * Generate random number k less than q 85 */ 86 BN_rand_range(k, dsa->q); 87 /* generate r = (a^x mod p) mod q */ 88 BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx); 89 if (!(newsig->r)) { 90 newsig->r = BN_new(); 91 if(!newsig->r) { 92 GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 93 goto err; 94 } 95 } 96 BN_mod(newsig->r, tmp, dsa->q, ctx); 97 } 98 while (BN_is_zero(newsig->r)); 99 /* generate s = (xr + k(Hm)) mod q */ 100 BN_mod_mul(tmp, dsa->priv_key, newsig->r, dsa->q, ctx); 101 BN_mod_mul(tmp2, k, md, dsa->q, ctx); 102 if (!newsig->s) { 103 newsig->s = BN_new(); 104 if(!newsig->s) { 105 GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 106 goto err; 107 } 108 } 109 BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx); 110 } 111 while (BN_is_zero(newsig->s)); 112 113 ret = newsig; 114 err: 115 BN_free(md); 116 if(ctx) { 117 BN_CTX_end(ctx); 118 BN_CTX_free(ctx); 119 } 120 if(!ret && newsig) { 121 DSA_SIG_free(newsig); 122 } 123 return ret; 124} 125 126/* 127 * Packs signature according to Cryptocom rules 128 * and frees up DSA_SIG structure 129 */ 130/*- 131int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen) 132 { 133 *siglen = 2*order; 134 memset(sig,0,*siglen); 135 store_bignum(s->r, sig,order); 136 store_bignum(s->s, sig + order,order); 137 dump_signature("serialized",sig,*siglen); 138 DSA_SIG_free(s); 139 return 1; 140 } 141*/ 142/* 143 * Packs signature according to Cryptopro rules 144 * and frees up DSA_SIG structure 145 */ 146int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen) 147{ 148 *siglen = 2 * order; 149 memset(sig, 0, *siglen); 150 store_bignum(s->s, sig, order); 151 store_bignum(s->r, sig + order, order); 152 dump_signature("serialized", sig, *siglen); 153 DSA_SIG_free(s); 154 return 1; 155} 156 157/* 158 * Verifies signature passed as DSA_SIG structure 159 * 160 */ 161 162int gost_do_verify(const unsigned char *dgst, int dgst_len, 163 DSA_SIG *sig, DSA *dsa) 164{ 165 BIGNUM *md = NULL, *tmp = NULL; 166 BIGNUM *q2 = NULL; 167 BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; 168 BIGNUM *tmp2 = NULL, *tmp3 = NULL; 169 int ok = 0; 170 BN_CTX *ctx = BN_CTX_new(); 171 if(!ctx) { 172 GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); 173 goto err; 174 } 175 176 BN_CTX_start(ctx); 177 if (BN_cmp(sig->s, dsa->q) >= 1 || BN_cmp(sig->r, dsa->q) >= 1) { 178 GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 179 goto err; 180 } 181 md = hashsum2bn(dgst); 182 183 tmp = BN_CTX_get(ctx); 184 v = BN_CTX_get(ctx); 185 q2 = BN_CTX_get(ctx); 186 z1 = BN_CTX_get(ctx); 187 z2 = BN_CTX_get(ctx); 188 tmp2 = BN_CTX_get(ctx); 189 tmp3 = BN_CTX_get(ctx); 190 u = BN_CTX_get(ctx); 191 if(!tmp || !v || !q2 || !z1 || !z2 || !tmp2 || !tmp3 || !u) { 192 GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); 193 goto err; 194 } 195 196 BN_mod(tmp, md, dsa->q, ctx); 197 if (BN_is_zero(tmp)) { 198 BN_one(md); 199 } 200 BN_copy(q2, dsa->q); 201 BN_sub_word(q2, 2); 202 BN_mod_exp(v, md, q2, dsa->q, ctx); 203 BN_mod_mul(z1, sig->s, v, dsa->q, ctx); 204 BN_sub(tmp, dsa->q, sig->r); 205 BN_mod_mul(z2, tmp, v, dsa->p, ctx); 206 BN_mod_exp(tmp, dsa->g, z1, dsa->p, ctx); 207 BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx); 208 BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx); 209 BN_mod(u, tmp3, dsa->q, ctx); 210 ok = (BN_cmp(u, sig->r) == 0); 211 212 if (!ok) { 213 GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 214 } 215err: 216 if(md) BN_free(md); 217 if(ctx) { 218 BN_CTX_end(ctx); 219 BN_CTX_free(ctx); 220 } 221 return ok; 222} 223 224/* 225 * Computes public keys for GOST R 34.10-94 algorithm 226 * 227 */ 228int gost94_compute_public(DSA *dsa) 229{ 230 /* Now fill algorithm parameters with correct values */ 231 BN_CTX *ctx; 232 if (!dsa->g) { 233 GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED); 234 return 0; 235 } 236 ctx = BN_CTX_new(); 237 if(!ctx) { 238 GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 239 return 0; 240 } 241 242 dsa->pub_key = BN_new(); 243 if(!dsa->pub_key) { 244 GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 245 BN_CTX_free(ctx); 246 return 0; 247 } 248 /* Compute public key y = a^x mod p */ 249 BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx); 250 BN_CTX_free(ctx); 251 return 1; 252} 253 254/* 255 * Fill GOST 94 params, searching them in R3410_paramset array 256 * by nid of paramset 257 * 258 */ 259int fill_GOST94_params(DSA *dsa, int nid) 260{ 261 R3410_params *params = R3410_paramset; 262 while (params->nid != NID_undef && params->nid != nid) 263 params++; 264 if (params->nid == NID_undef) { 265 GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); 266 return 0; 267 } 268#define dump_signature(a,b,c) 269 if (dsa->p) { 270 BN_free(dsa->p); 271 } 272 dsa->p = NULL; 273 BN_dec2bn(&(dsa->p), params->p); 274 if (dsa->q) { 275 BN_free(dsa->q); 276 } 277 dsa->q = NULL; 278 BN_dec2bn(&(dsa->q), params->q); 279 if (dsa->g) { 280 BN_free(dsa->g); 281 } 282 dsa->g = NULL; 283 BN_dec2bn(&(dsa->g), params->a); 284 return 1; 285} 286 287/* 288 * Generate GOST R 34.10-94 keypair 289 * 290 * 291 */ 292int gost_sign_keygen(DSA *dsa) 293{ 294 dsa->priv_key = BN_new(); 295 if(!dsa->priv_key) { 296 GOSTerr(GOST_F_GOST_SIGN_KEYGEN, ERR_R_MALLOC_FAILURE); 297 return 0; 298 } 299 BN_rand_range(dsa->priv_key, dsa->q); 300 return gost94_compute_public(dsa); 301} 302 303/* Unpack signature according to cryptocom rules */ 304/*- 305DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) 306 { 307 DSA_SIG *s; 308 s = DSA_SIG_new(); 309 if (s == NULL) 310 { 311 GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY); 312 return(NULL); 313 } 314 s->r = getbnfrombuf(sig, siglen/2); 315 s->s = getbnfrombuf(sig + siglen/2, siglen/2); 316 return s; 317 } 318*/ 319/* Unpack signature according to cryptopro rules */ 320DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen) 321{ 322 DSA_SIG *s; 323 324 s = DSA_SIG_new(); 325 if (s == NULL) { 326 GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, GOST_R_NO_MEMORY); 327 return NULL; 328 } 329 s->s = getbnfrombuf(sig, siglen / 2); 330 s->r = getbnfrombuf(sig + siglen / 2, siglen / 2); 331 return s; 332} 333 334/* Convert little-endian byte array into bignum */ 335BIGNUM *hashsum2bn(const unsigned char *dgst) 336{ 337 unsigned char buf[32]; 338 int i; 339 for (i = 0; i < 32; i++) { 340 buf[31 - i] = dgst[i]; 341 } 342 return getbnfrombuf(buf, 32); 343} 344 345/* Convert byte buffer to bignum, skipping leading zeros*/ 346BIGNUM *getbnfrombuf(const unsigned char *buf, size_t len) 347{ 348 while (*buf == 0 && len > 0) { 349 buf++; 350 len--; 351 } 352 if (len) { 353 return BN_bin2bn(buf, len, NULL); 354 } else { 355 BIGNUM *b = BN_new(); 356 BN_zero(b); 357 return b; 358 } 359} 360 361/* 362 * Pack bignum into byte buffer of given size, filling all leading bytes by 363 * zeros 364 */ 365int store_bignum(BIGNUM *bn, unsigned char *buf, int len) 366{ 367 int bytes = BN_num_bytes(bn); 368 if (bytes > len) 369 return 0; 370 memset(buf, 0, len); 371 BN_bn2bin(bn, buf + len - bytes); 372 return 1; 373} 374