gost_sign.c revision 284285
1238384Sjkim/********************************************************************** 2238384Sjkim * gost_sign.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6238384Sjkim * Implementation of GOST R 34.10-94 signature algorithm * 7238384Sjkim * for OpenSSL * 8238384Sjkim * Requires OpenSSL 0.9.9 for compilation * 9238384Sjkim **********************************************************************/ 10238384Sjkim#include <string.h> 11238384Sjkim#include <openssl/rand.h> 12238384Sjkim#include <openssl/bn.h> 13238384Sjkim#include <openssl/dsa.h> 14238384Sjkim#include <openssl/evp.h> 15284285Sjkim#include <openssl/err.h> 16238384Sjkim 17238384Sjkim#include "gost_params.h" 18238384Sjkim#include "gost_lcl.h" 19238384Sjkim#include "e_gost_err.h" 20238384Sjkim 21238384Sjkim#ifdef DEBUG_SIGN 22280304Sjkimvoid dump_signature(const char *message, const unsigned char *buffer, 23280304Sjkim size_t len) 24280304Sjkim{ 25280304Sjkim size_t i; 26280304Sjkim fprintf(stderr, "signature %s Length=%d", message, len); 27280304Sjkim for (i = 0; i < len; i++) { 28280304Sjkim if (i % 16 == 0) 29280304Sjkim fputc('\n', stderr); 30280304Sjkim fprintf(stderr, " %02x", buffer[i]); 31280304Sjkim } 32280304Sjkim fprintf(stderr, "\nEnd of signature\n"); 33280304Sjkim} 34238384Sjkim 35238384Sjkimvoid dump_dsa_sig(const char *message, DSA_SIG *sig) 36280304Sjkim{ 37280304Sjkim fprintf(stderr, "%s\nR=", message); 38280304Sjkim BN_print_fp(stderr, sig->r); 39280304Sjkim fprintf(stderr, "\nS="); 40280304Sjkim BN_print_fp(stderr, sig->s); 41280304Sjkim fprintf(stderr, "\n"); 42280304Sjkim} 43238384Sjkim 44238384Sjkim#else 45238384Sjkim 46280304Sjkim# define dump_signature(a,b,c) 47280304Sjkim# define dump_dsa_sig(a,b) 48238384Sjkim#endif 49238384Sjkim 50238384Sjkim/* 51238384Sjkim * Computes signature and returns it as DSA_SIG structure 52238384Sjkim */ 53280304SjkimDSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 54280304Sjkim{ 55280304Sjkim BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; 56284285Sjkim DSA_SIG *newsig = NULL, *ret = NULL; 57280304Sjkim BIGNUM *md = hashsum2bn(dgst); 58280304Sjkim /* check if H(M) mod q is zero */ 59280304Sjkim BN_CTX *ctx = BN_CTX_new(); 60284285Sjkim if(!ctx) { 61284285Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 62284285Sjkim goto err; 63284285Sjkim } 64280304Sjkim BN_CTX_start(ctx); 65284285Sjkim newsig = DSA_SIG_new(); 66280304Sjkim if (!newsig) { 67280304Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); 68280304Sjkim goto err; 69280304Sjkim } 70280304Sjkim tmp = BN_CTX_get(ctx); 71280304Sjkim k = BN_CTX_get(ctx); 72280304Sjkim tmp2 = BN_CTX_get(ctx); 73284285Sjkim if(!tmp || !k || !tmp2) { 74284285Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 75284285Sjkim goto err; 76284285Sjkim } 77280304Sjkim BN_mod(tmp, md, dsa->q, ctx); 78280304Sjkim if (BN_is_zero(tmp)) { 79280304Sjkim BN_one(md); 80280304Sjkim } 81280304Sjkim do { 82280304Sjkim do { 83280304Sjkim /* 84280304Sjkim * Generate random number k less than q 85280304Sjkim */ 86280304Sjkim BN_rand_range(k, dsa->q); 87280304Sjkim /* generate r = (a^x mod p) mod q */ 88280304Sjkim BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx); 89284285Sjkim if (!(newsig->r)) { 90280304Sjkim newsig->r = BN_new(); 91284285Sjkim if(!newsig->r) { 92284285Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 93284285Sjkim goto err; 94284285Sjkim } 95284285Sjkim } 96280304Sjkim BN_mod(newsig->r, tmp, dsa->q, ctx); 97280304Sjkim } 98280304Sjkim while (BN_is_zero(newsig->r)); 99280304Sjkim /* generate s = (xr + k(Hm)) mod q */ 100280304Sjkim BN_mod_mul(tmp, dsa->priv_key, newsig->r, dsa->q, ctx); 101280304Sjkim BN_mod_mul(tmp2, k, md, dsa->q, ctx); 102284285Sjkim if (!newsig->s) { 103280304Sjkim newsig->s = BN_new(); 104284285Sjkim if(!newsig->s) { 105284285Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 106284285Sjkim goto err; 107284285Sjkim } 108284285Sjkim } 109280304Sjkim BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx); 110280304Sjkim } 111280304Sjkim while (BN_is_zero(newsig->s)); 112284285Sjkim 113284285Sjkim ret = newsig; 114280304Sjkim err: 115280304Sjkim BN_free(md); 116284285Sjkim if(ctx) { 117284285Sjkim BN_CTX_end(ctx); 118284285Sjkim BN_CTX_free(ctx); 119284285Sjkim } 120284285Sjkim if(!ret && newsig) { 121284285Sjkim DSA_SIG_free(newsig); 122284285Sjkim } 123284285Sjkim return ret; 124280304Sjkim} 125238384Sjkim 126238384Sjkim/* 127238384Sjkim * Packs signature according to Cryptocom rules 128238384Sjkim * and frees up DSA_SIG structure 129238384Sjkim */ 130280304Sjkim/*- 131238384Sjkimint pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen) 132280304Sjkim { 133280304Sjkim *siglen = 2*order; 134280304Sjkim memset(sig,0,*siglen); 135280304Sjkim store_bignum(s->r, sig,order); 136280304Sjkim store_bignum(s->s, sig + order,order); 137280304Sjkim dump_signature("serialized",sig,*siglen); 138280304Sjkim DSA_SIG_free(s); 139280304Sjkim return 1; 140280304Sjkim } 141238384Sjkim*/ 142238384Sjkim/* 143238384Sjkim * Packs signature according to Cryptopro rules 144238384Sjkim * and frees up DSA_SIG structure 145238384Sjkim */ 146280304Sjkimint pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen) 147280304Sjkim{ 148280304Sjkim *siglen = 2 * order; 149280304Sjkim memset(sig, 0, *siglen); 150280304Sjkim store_bignum(s->s, sig, order); 151280304Sjkim store_bignum(s->r, sig + order, order); 152280304Sjkim dump_signature("serialized", sig, *siglen); 153280304Sjkim DSA_SIG_free(s); 154280304Sjkim return 1; 155280304Sjkim} 156238384Sjkim 157238384Sjkim/* 158238384Sjkim * Verifies signature passed as DSA_SIG structure 159238384Sjkim * 160238384Sjkim */ 161238384Sjkim 162238384Sjkimint gost_do_verify(const unsigned char *dgst, int dgst_len, 163280304Sjkim DSA_SIG *sig, DSA *dsa) 164280304Sjkim{ 165284285Sjkim BIGNUM *md = NULL, *tmp = NULL; 166280304Sjkim BIGNUM *q2 = NULL; 167280304Sjkim BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; 168280304Sjkim BIGNUM *tmp2 = NULL, *tmp3 = NULL; 169284285Sjkim int ok = 0; 170280304Sjkim BN_CTX *ctx = BN_CTX_new(); 171284285Sjkim if(!ctx) { 172284285Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); 173284285Sjkim goto err; 174284285Sjkim } 175238384Sjkim 176280304Sjkim BN_CTX_start(ctx); 177280304Sjkim if (BN_cmp(sig->s, dsa->q) >= 1 || BN_cmp(sig->r, dsa->q) >= 1) { 178280304Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 179284285Sjkim goto err; 180280304Sjkim } 181280304Sjkim md = hashsum2bn(dgst); 182238384Sjkim 183280304Sjkim tmp = BN_CTX_get(ctx); 184280304Sjkim v = BN_CTX_get(ctx); 185280304Sjkim q2 = BN_CTX_get(ctx); 186280304Sjkim z1 = BN_CTX_get(ctx); 187280304Sjkim z2 = BN_CTX_get(ctx); 188280304Sjkim tmp2 = BN_CTX_get(ctx); 189280304Sjkim tmp3 = BN_CTX_get(ctx); 190280304Sjkim u = BN_CTX_get(ctx); 191284285Sjkim if(!tmp || !v || !q2 || !z1 || !z2 || !tmp2 || !tmp3 || !u) { 192284285Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); 193284285Sjkim goto err; 194284285Sjkim } 195280304Sjkim 196280304Sjkim BN_mod(tmp, md, dsa->q, ctx); 197280304Sjkim if (BN_is_zero(tmp)) { 198280304Sjkim BN_one(md); 199280304Sjkim } 200280304Sjkim BN_copy(q2, dsa->q); 201280304Sjkim BN_sub_word(q2, 2); 202280304Sjkim BN_mod_exp(v, md, q2, dsa->q, ctx); 203280304Sjkim BN_mod_mul(z1, sig->s, v, dsa->q, ctx); 204280304Sjkim BN_sub(tmp, dsa->q, sig->r); 205280304Sjkim BN_mod_mul(z2, tmp, v, dsa->p, ctx); 206280304Sjkim BN_mod_exp(tmp, dsa->g, z1, dsa->p, ctx); 207280304Sjkim BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx); 208280304Sjkim BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx); 209280304Sjkim BN_mod(u, tmp3, dsa->q, ctx); 210284285Sjkim ok = (BN_cmp(u, sig->r) == 0); 211280304Sjkim 212284285Sjkim if (!ok) { 213280304Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 214280304Sjkim } 215284285Sjkimerr: 216284285Sjkim if(md) BN_free(md); 217284285Sjkim if(ctx) { 218284285Sjkim BN_CTX_end(ctx); 219284285Sjkim BN_CTX_free(ctx); 220284285Sjkim } 221284285Sjkim return ok; 222280304Sjkim} 223280304Sjkim 224238384Sjkim/* 225238384Sjkim * Computes public keys for GOST R 34.10-94 algorithm 226238384Sjkim * 227238384Sjkim */ 228238384Sjkimint gost94_compute_public(DSA *dsa) 229280304Sjkim{ 230280304Sjkim /* Now fill algorithm parameters with correct values */ 231284285Sjkim BN_CTX *ctx; 232280304Sjkim if (!dsa->g) { 233280304Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED); 234280304Sjkim return 0; 235280304Sjkim } 236284285Sjkim ctx = BN_CTX_new(); 237284285Sjkim if(!ctx) { 238284285Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 239284285Sjkim return 0; 240284285Sjkim } 241284285Sjkim 242284285Sjkim dsa->pub_key = BN_new(); 243284285Sjkim if(!dsa->pub_key) { 244284285Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 245284285Sjkim BN_CTX_free(ctx); 246284285Sjkim return 0; 247284285Sjkim } 248280304Sjkim /* Compute public key y = a^x mod p */ 249280304Sjkim BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx); 250280304Sjkim BN_CTX_free(ctx); 251280304Sjkim return 1; 252280304Sjkim} 253238384Sjkim 254238384Sjkim/* 255238384Sjkim * Fill GOST 94 params, searching them in R3410_paramset array 256238384Sjkim * by nid of paramset 257238384Sjkim * 258238384Sjkim */ 259280304Sjkimint fill_GOST94_params(DSA *dsa, int nid) 260280304Sjkim{ 261280304Sjkim R3410_params *params = R3410_paramset; 262280304Sjkim while (params->nid != NID_undef && params->nid != nid) 263280304Sjkim params++; 264280304Sjkim if (params->nid == NID_undef) { 265280304Sjkim GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); 266280304Sjkim return 0; 267280304Sjkim } 268238384Sjkim#define dump_signature(a,b,c) 269280304Sjkim if (dsa->p) { 270280304Sjkim BN_free(dsa->p); 271280304Sjkim } 272280304Sjkim dsa->p = NULL; 273280304Sjkim BN_dec2bn(&(dsa->p), params->p); 274280304Sjkim if (dsa->q) { 275280304Sjkim BN_free(dsa->q); 276280304Sjkim } 277280304Sjkim dsa->q = NULL; 278280304Sjkim BN_dec2bn(&(dsa->q), params->q); 279280304Sjkim if (dsa->g) { 280280304Sjkim BN_free(dsa->g); 281280304Sjkim } 282280304Sjkim dsa->g = NULL; 283280304Sjkim BN_dec2bn(&(dsa->g), params->a); 284280304Sjkim return 1; 285280304Sjkim} 286238384Sjkim 287238384Sjkim/* 288238384Sjkim * Generate GOST R 34.10-94 keypair 289238384Sjkim * 290238384Sjkim * 291238384Sjkim */ 292238384Sjkimint gost_sign_keygen(DSA *dsa) 293280304Sjkim{ 294280304Sjkim dsa->priv_key = BN_new(); 295284285Sjkim if(!dsa->priv_key) { 296284285Sjkim GOSTerr(GOST_F_GOST_SIGN_KEYGEN, ERR_R_MALLOC_FAILURE); 297284285Sjkim return 0; 298284285Sjkim } 299280304Sjkim BN_rand_range(dsa->priv_key, dsa->q); 300280304Sjkim return gost94_compute_public(dsa); 301280304Sjkim} 302238384Sjkim 303238384Sjkim/* Unpack signature according to cryptocom rules */ 304280304Sjkim/*- 305238384SjkimDSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) 306280304Sjkim { 307280304Sjkim DSA_SIG *s; 308280304Sjkim s = DSA_SIG_new(); 309280304Sjkim if (s == NULL) 310280304Sjkim { 311280304Sjkim GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY); 312280304Sjkim return(NULL); 313280304Sjkim } 314280304Sjkim s->r = getbnfrombuf(sig, siglen/2); 315280304Sjkim s->s = getbnfrombuf(sig + siglen/2, siglen/2); 316280304Sjkim return s; 317280304Sjkim } 318238384Sjkim*/ 319238384Sjkim/* Unpack signature according to cryptopro rules */ 320280304SjkimDSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen) 321280304Sjkim{ 322280304Sjkim DSA_SIG *s; 323238384Sjkim 324280304Sjkim s = DSA_SIG_new(); 325280304Sjkim if (s == NULL) { 326280304Sjkim GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, GOST_R_NO_MEMORY); 327280304Sjkim return NULL; 328280304Sjkim } 329280304Sjkim s->s = getbnfrombuf(sig, siglen / 2); 330280304Sjkim s->r = getbnfrombuf(sig + siglen / 2, siglen / 2); 331280304Sjkim return s; 332280304Sjkim} 333238384Sjkim 334238384Sjkim/* Convert little-endian byte array into bignum */ 335238384SjkimBIGNUM *hashsum2bn(const unsigned char *dgst) 336280304Sjkim{ 337280304Sjkim unsigned char buf[32]; 338280304Sjkim int i; 339280304Sjkim for (i = 0; i < 32; i++) { 340280304Sjkim buf[31 - i] = dgst[i]; 341280304Sjkim } 342280304Sjkim return getbnfrombuf(buf, 32); 343280304Sjkim} 344238384Sjkim 345238384Sjkim/* Convert byte buffer to bignum, skipping leading zeros*/ 346280304SjkimBIGNUM *getbnfrombuf(const unsigned char *buf, size_t len) 347280304Sjkim{ 348280304Sjkim while (*buf == 0 && len > 0) { 349280304Sjkim buf++; 350280304Sjkim len--; 351280304Sjkim } 352280304Sjkim if (len) { 353280304Sjkim return BN_bin2bn(buf, len, NULL); 354280304Sjkim } else { 355280304Sjkim BIGNUM *b = BN_new(); 356280304Sjkim BN_zero(b); 357280304Sjkim return b; 358280304Sjkim } 359280304Sjkim} 360238384Sjkim 361280304Sjkim/* 362280304Sjkim * Pack bignum into byte buffer of given size, filling all leading bytes by 363280304Sjkim * zeros 364280304Sjkim */ 365280304Sjkimint store_bignum(BIGNUM *bn, unsigned char *buf, int len) 366280304Sjkim{ 367280304Sjkim int bytes = BN_num_bytes(bn); 368280304Sjkim if (bytes > len) 369280304Sjkim return 0; 370280304Sjkim memset(buf, 0, len); 371280304Sjkim BN_bn2bin(bn, buf + len - bytes); 372280304Sjkim return 1; 373280304Sjkim} 374