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> 15284283Sjkim#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 22280297Sjkimvoid dump_signature(const char *message, const unsigned char *buffer, 23280297Sjkim size_t len) 24280297Sjkim{ 25280297Sjkim size_t i; 26280297Sjkim fprintf(stderr, "signature %s Length=%d", message, len); 27280297Sjkim for (i = 0; i < len; i++) { 28280297Sjkim if (i % 16 == 0) 29280297Sjkim fputc('\n', stderr); 30280297Sjkim fprintf(stderr, " %02x", buffer[i]); 31280297Sjkim } 32280297Sjkim fprintf(stderr, "\nEnd of signature\n"); 33280297Sjkim} 34238384Sjkim 35238384Sjkimvoid dump_dsa_sig(const char *message, DSA_SIG *sig) 36280297Sjkim{ 37280297Sjkim fprintf(stderr, "%s\nR=", message); 38280297Sjkim BN_print_fp(stderr, sig->r); 39280297Sjkim fprintf(stderr, "\nS="); 40280297Sjkim BN_print_fp(stderr, sig->s); 41280297Sjkim fprintf(stderr, "\n"); 42280297Sjkim} 43238384Sjkim 44238384Sjkim#else 45238384Sjkim 46280297Sjkim# define dump_signature(a,b,c) 47280297Sjkim# define dump_dsa_sig(a,b) 48238384Sjkim#endif 49238384Sjkim 50238384Sjkim/* 51238384Sjkim * Computes signature and returns it as DSA_SIG structure 52238384Sjkim */ 53280297SjkimDSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 54280297Sjkim{ 55280297Sjkim BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; 56284283Sjkim DSA_SIG *newsig = NULL, *ret = NULL; 57280297Sjkim BIGNUM *md = hashsum2bn(dgst); 58280297Sjkim /* check if H(M) mod q is zero */ 59280297Sjkim BN_CTX *ctx = BN_CTX_new(); 60284283Sjkim if(!ctx) { 61284283Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 62284283Sjkim goto err; 63284283Sjkim } 64280297Sjkim BN_CTX_start(ctx); 65284283Sjkim newsig = DSA_SIG_new(); 66280297Sjkim if (!newsig) { 67280297Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); 68280297Sjkim goto err; 69280297Sjkim } 70280297Sjkim tmp = BN_CTX_get(ctx); 71280297Sjkim k = BN_CTX_get(ctx); 72280297Sjkim tmp2 = BN_CTX_get(ctx); 73284283Sjkim if(!tmp || !k || !tmp2) { 74284283Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 75284283Sjkim goto err; 76284283Sjkim } 77280297Sjkim BN_mod(tmp, md, dsa->q, ctx); 78280297Sjkim if (BN_is_zero(tmp)) { 79280297Sjkim BN_one(md); 80280297Sjkim } 81280297Sjkim do { 82280297Sjkim do { 83280297Sjkim /* 84280297Sjkim * Generate random number k less than q 85280297Sjkim */ 86280297Sjkim BN_rand_range(k, dsa->q); 87280297Sjkim /* generate r = (a^x mod p) mod q */ 88280297Sjkim BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx); 89284283Sjkim if (!(newsig->r)) { 90280297Sjkim newsig->r = BN_new(); 91284283Sjkim if(!newsig->r) { 92284283Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 93284283Sjkim goto err; 94284283Sjkim } 95284283Sjkim } 96280297Sjkim BN_mod(newsig->r, tmp, dsa->q, ctx); 97280297Sjkim } 98280297Sjkim while (BN_is_zero(newsig->r)); 99280297Sjkim /* generate s = (xr + k(Hm)) mod q */ 100280297Sjkim BN_mod_mul(tmp, dsa->priv_key, newsig->r, dsa->q, ctx); 101280297Sjkim BN_mod_mul(tmp2, k, md, dsa->q, ctx); 102284283Sjkim if (!newsig->s) { 103280297Sjkim newsig->s = BN_new(); 104284283Sjkim if(!newsig->s) { 105284283Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); 106284283Sjkim goto err; 107284283Sjkim } 108284283Sjkim } 109280297Sjkim BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx); 110280297Sjkim } 111280297Sjkim while (BN_is_zero(newsig->s)); 112284283Sjkim 113284283Sjkim ret = newsig; 114280297Sjkim err: 115280297Sjkim BN_free(md); 116284283Sjkim if(ctx) { 117284283Sjkim BN_CTX_end(ctx); 118284283Sjkim BN_CTX_free(ctx); 119284283Sjkim } 120284283Sjkim if(!ret && newsig) { 121284283Sjkim DSA_SIG_free(newsig); 122284283Sjkim } 123284283Sjkim return ret; 124280297Sjkim} 125238384Sjkim 126238384Sjkim/* 127238384Sjkim * Packs signature according to Cryptocom rules 128238384Sjkim * and frees up DSA_SIG structure 129238384Sjkim */ 130280297Sjkim/*- 131238384Sjkimint pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen) 132280297Sjkim { 133280297Sjkim *siglen = 2*order; 134280297Sjkim memset(sig,0,*siglen); 135280297Sjkim store_bignum(s->r, sig,order); 136280297Sjkim store_bignum(s->s, sig + order,order); 137280297Sjkim dump_signature("serialized",sig,*siglen); 138280297Sjkim DSA_SIG_free(s); 139280297Sjkim return 1; 140280297Sjkim } 141238384Sjkim*/ 142238384Sjkim/* 143238384Sjkim * Packs signature according to Cryptopro rules 144238384Sjkim * and frees up DSA_SIG structure 145238384Sjkim */ 146280297Sjkimint pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen) 147280297Sjkim{ 148280297Sjkim *siglen = 2 * order; 149280297Sjkim memset(sig, 0, *siglen); 150280297Sjkim store_bignum(s->s, sig, order); 151280297Sjkim store_bignum(s->r, sig + order, order); 152280297Sjkim dump_signature("serialized", sig, *siglen); 153280297Sjkim DSA_SIG_free(s); 154280297Sjkim return 1; 155280297Sjkim} 156238384Sjkim 157238384Sjkim/* 158238384Sjkim * Verifies signature passed as DSA_SIG structure 159238384Sjkim * 160238384Sjkim */ 161238384Sjkim 162238384Sjkimint gost_do_verify(const unsigned char *dgst, int dgst_len, 163280297Sjkim DSA_SIG *sig, DSA *dsa) 164280297Sjkim{ 165284283Sjkim BIGNUM *md = NULL, *tmp = NULL; 166280297Sjkim BIGNUM *q2 = NULL; 167280297Sjkim BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; 168280297Sjkim BIGNUM *tmp2 = NULL, *tmp3 = NULL; 169284283Sjkim int ok = 0; 170280297Sjkim BN_CTX *ctx = BN_CTX_new(); 171284283Sjkim if(!ctx) { 172284283Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); 173284283Sjkim goto err; 174284283Sjkim } 175238384Sjkim 176280297Sjkim BN_CTX_start(ctx); 177280297Sjkim if (BN_cmp(sig->s, dsa->q) >= 1 || BN_cmp(sig->r, dsa->q) >= 1) { 178280297Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 179284283Sjkim goto err; 180280297Sjkim } 181280297Sjkim md = hashsum2bn(dgst); 182238384Sjkim 183280297Sjkim tmp = BN_CTX_get(ctx); 184280297Sjkim v = BN_CTX_get(ctx); 185280297Sjkim q2 = BN_CTX_get(ctx); 186280297Sjkim z1 = BN_CTX_get(ctx); 187280297Sjkim z2 = BN_CTX_get(ctx); 188280297Sjkim tmp2 = BN_CTX_get(ctx); 189280297Sjkim tmp3 = BN_CTX_get(ctx); 190280297Sjkim u = BN_CTX_get(ctx); 191284283Sjkim if(!tmp || !v || !q2 || !z1 || !z2 || !tmp2 || !tmp3 || !u) { 192284283Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); 193284283Sjkim goto err; 194284283Sjkim } 195280297Sjkim 196280297Sjkim BN_mod(tmp, md, dsa->q, ctx); 197280297Sjkim if (BN_is_zero(tmp)) { 198280297Sjkim BN_one(md); 199280297Sjkim } 200280297Sjkim BN_copy(q2, dsa->q); 201280297Sjkim BN_sub_word(q2, 2); 202280297Sjkim BN_mod_exp(v, md, q2, dsa->q, ctx); 203280297Sjkim BN_mod_mul(z1, sig->s, v, dsa->q, ctx); 204280297Sjkim BN_sub(tmp, dsa->q, sig->r); 205280297Sjkim BN_mod_mul(z2, tmp, v, dsa->p, ctx); 206280297Sjkim BN_mod_exp(tmp, dsa->g, z1, dsa->p, ctx); 207280297Sjkim BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx); 208280297Sjkim BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx); 209280297Sjkim BN_mod(u, tmp3, dsa->q, ctx); 210284283Sjkim ok = (BN_cmp(u, sig->r) == 0); 211280297Sjkim 212284283Sjkim if (!ok) { 213280297Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 214280297Sjkim } 215284283Sjkimerr: 216284283Sjkim if(md) BN_free(md); 217284283Sjkim if(ctx) { 218284283Sjkim BN_CTX_end(ctx); 219284283Sjkim BN_CTX_free(ctx); 220284283Sjkim } 221284283Sjkim return ok; 222280297Sjkim} 223280297Sjkim 224238384Sjkim/* 225238384Sjkim * Computes public keys for GOST R 34.10-94 algorithm 226238384Sjkim * 227238384Sjkim */ 228238384Sjkimint gost94_compute_public(DSA *dsa) 229280297Sjkim{ 230280297Sjkim /* Now fill algorithm parameters with correct values */ 231284283Sjkim BN_CTX *ctx; 232280297Sjkim if (!dsa->g) { 233280297Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED); 234280297Sjkim return 0; 235280297Sjkim } 236284283Sjkim ctx = BN_CTX_new(); 237284283Sjkim if(!ctx) { 238284283Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 239284283Sjkim return 0; 240284283Sjkim } 241284283Sjkim 242284283Sjkim dsa->pub_key = BN_new(); 243284283Sjkim if(!dsa->pub_key) { 244284283Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); 245284283Sjkim BN_CTX_free(ctx); 246284283Sjkim return 0; 247284283Sjkim } 248280297Sjkim /* Compute public key y = a^x mod p */ 249280297Sjkim BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx); 250280297Sjkim BN_CTX_free(ctx); 251280297Sjkim return 1; 252280297Sjkim} 253238384Sjkim 254238384Sjkim/* 255238384Sjkim * Fill GOST 94 params, searching them in R3410_paramset array 256238384Sjkim * by nid of paramset 257238384Sjkim * 258238384Sjkim */ 259280297Sjkimint fill_GOST94_params(DSA *dsa, int nid) 260280297Sjkim{ 261280297Sjkim R3410_params *params = R3410_paramset; 262280297Sjkim while (params->nid != NID_undef && params->nid != nid) 263280297Sjkim params++; 264280297Sjkim if (params->nid == NID_undef) { 265280297Sjkim GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); 266280297Sjkim return 0; 267280297Sjkim } 268238384Sjkim#define dump_signature(a,b,c) 269280297Sjkim if (dsa->p) { 270280297Sjkim BN_free(dsa->p); 271280297Sjkim } 272280297Sjkim dsa->p = NULL; 273280297Sjkim BN_dec2bn(&(dsa->p), params->p); 274280297Sjkim if (dsa->q) { 275280297Sjkim BN_free(dsa->q); 276280297Sjkim } 277280297Sjkim dsa->q = NULL; 278280297Sjkim BN_dec2bn(&(dsa->q), params->q); 279280297Sjkim if (dsa->g) { 280280297Sjkim BN_free(dsa->g); 281280297Sjkim } 282280297Sjkim dsa->g = NULL; 283280297Sjkim BN_dec2bn(&(dsa->g), params->a); 284280297Sjkim return 1; 285280297Sjkim} 286238384Sjkim 287238384Sjkim/* 288238384Sjkim * Generate GOST R 34.10-94 keypair 289238384Sjkim * 290238384Sjkim * 291238384Sjkim */ 292238384Sjkimint gost_sign_keygen(DSA *dsa) 293280297Sjkim{ 294280297Sjkim dsa->priv_key = BN_new(); 295284283Sjkim if(!dsa->priv_key) { 296284283Sjkim GOSTerr(GOST_F_GOST_SIGN_KEYGEN, ERR_R_MALLOC_FAILURE); 297284283Sjkim return 0; 298284283Sjkim } 299280297Sjkim BN_rand_range(dsa->priv_key, dsa->q); 300280297Sjkim return gost94_compute_public(dsa); 301280297Sjkim} 302238384Sjkim 303238384Sjkim/* Unpack signature according to cryptocom rules */ 304280297Sjkim/*- 305238384SjkimDSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) 306280297Sjkim { 307280297Sjkim DSA_SIG *s; 308280297Sjkim s = DSA_SIG_new(); 309280297Sjkim if (s == NULL) 310280297Sjkim { 311280297Sjkim GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY); 312280297Sjkim return(NULL); 313280297Sjkim } 314280297Sjkim s->r = getbnfrombuf(sig, siglen/2); 315280297Sjkim s->s = getbnfrombuf(sig + siglen/2, siglen/2); 316280297Sjkim return s; 317280297Sjkim } 318238384Sjkim*/ 319238384Sjkim/* Unpack signature according to cryptopro rules */ 320280297SjkimDSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen) 321280297Sjkim{ 322280297Sjkim DSA_SIG *s; 323238384Sjkim 324280297Sjkim s = DSA_SIG_new(); 325280297Sjkim if (s == NULL) { 326280297Sjkim GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, GOST_R_NO_MEMORY); 327280297Sjkim return NULL; 328280297Sjkim } 329280297Sjkim s->s = getbnfrombuf(sig, siglen / 2); 330280297Sjkim s->r = getbnfrombuf(sig + siglen / 2, siglen / 2); 331280297Sjkim return s; 332280297Sjkim} 333238384Sjkim 334238384Sjkim/* Convert little-endian byte array into bignum */ 335238384SjkimBIGNUM *hashsum2bn(const unsigned char *dgst) 336280297Sjkim{ 337280297Sjkim unsigned char buf[32]; 338280297Sjkim int i; 339280297Sjkim for (i = 0; i < 32; i++) { 340280297Sjkim buf[31 - i] = dgst[i]; 341280297Sjkim } 342280297Sjkim return getbnfrombuf(buf, 32); 343280297Sjkim} 344238384Sjkim 345238384Sjkim/* Convert byte buffer to bignum, skipping leading zeros*/ 346280297SjkimBIGNUM *getbnfrombuf(const unsigned char *buf, size_t len) 347280297Sjkim{ 348280297Sjkim while (*buf == 0 && len > 0) { 349280297Sjkim buf++; 350280297Sjkim len--; 351280297Sjkim } 352280297Sjkim if (len) { 353280297Sjkim return BN_bin2bn(buf, len, NULL); 354280297Sjkim } else { 355280297Sjkim BIGNUM *b = BN_new(); 356280297Sjkim BN_zero(b); 357280297Sjkim return b; 358280297Sjkim } 359280297Sjkim} 360238384Sjkim 361280297Sjkim/* 362280297Sjkim * Pack bignum into byte buffer of given size, filling all leading bytes by 363280297Sjkim * zeros 364280297Sjkim */ 365280297Sjkimint store_bignum(BIGNUM *bn, unsigned char *buf, int len) 366280297Sjkim{ 367280297Sjkim int bytes = BN_num_bytes(bn); 368280297Sjkim if (bytes > len) 369280297Sjkim return 0; 370280297Sjkim memset(buf, 0, len); 371280297Sjkim BN_bn2bin(bn, buf + len - bytes); 372280297Sjkim return 1; 373280297Sjkim} 374