gost_sign.c revision 280304
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> 15238384Sjkim 16238384Sjkim#include "gost_params.h" 17238384Sjkim#include "gost_lcl.h" 18238384Sjkim#include "e_gost_err.h" 19238384Sjkim 20238384Sjkim#ifdef DEBUG_SIGN 21280304Sjkimvoid dump_signature(const char *message, const unsigned char *buffer, 22280304Sjkim size_t len) 23280304Sjkim{ 24280304Sjkim size_t i; 25280304Sjkim fprintf(stderr, "signature %s Length=%d", message, len); 26280304Sjkim for (i = 0; i < len; i++) { 27280304Sjkim if (i % 16 == 0) 28280304Sjkim fputc('\n', stderr); 29280304Sjkim fprintf(stderr, " %02x", buffer[i]); 30280304Sjkim } 31280304Sjkim fprintf(stderr, "\nEnd of signature\n"); 32280304Sjkim} 33238384Sjkim 34238384Sjkimvoid dump_dsa_sig(const char *message, DSA_SIG *sig) 35280304Sjkim{ 36280304Sjkim fprintf(stderr, "%s\nR=", message); 37280304Sjkim BN_print_fp(stderr, sig->r); 38280304Sjkim fprintf(stderr, "\nS="); 39280304Sjkim BN_print_fp(stderr, sig->s); 40280304Sjkim fprintf(stderr, "\n"); 41280304Sjkim} 42238384Sjkim 43238384Sjkim#else 44238384Sjkim 45280304Sjkim# define dump_signature(a,b,c) 46280304Sjkim# define dump_dsa_sig(a,b) 47238384Sjkim#endif 48238384Sjkim 49238384Sjkim/* 50238384Sjkim * Computes signature and returns it as DSA_SIG structure 51238384Sjkim */ 52280304SjkimDSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 53280304Sjkim{ 54280304Sjkim BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; 55280304Sjkim DSA_SIG *newsig = DSA_SIG_new(); 56280304Sjkim BIGNUM *md = hashsum2bn(dgst); 57280304Sjkim /* check if H(M) mod q is zero */ 58280304Sjkim BN_CTX *ctx = BN_CTX_new(); 59280304Sjkim BN_CTX_start(ctx); 60280304Sjkim if (!newsig) { 61280304Sjkim GOSTerr(GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); 62280304Sjkim goto err; 63280304Sjkim } 64280304Sjkim tmp = BN_CTX_get(ctx); 65280304Sjkim k = BN_CTX_get(ctx); 66280304Sjkim tmp2 = BN_CTX_get(ctx); 67280304Sjkim BN_mod(tmp, md, dsa->q, ctx); 68280304Sjkim if (BN_is_zero(tmp)) { 69280304Sjkim BN_one(md); 70280304Sjkim } 71280304Sjkim do { 72280304Sjkim do { 73280304Sjkim /* 74280304Sjkim * Generate random number k less than q 75280304Sjkim */ 76280304Sjkim BN_rand_range(k, dsa->q); 77280304Sjkim /* generate r = (a^x mod p) mod q */ 78280304Sjkim BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx); 79280304Sjkim if (!(newsig->r)) 80280304Sjkim newsig->r = BN_new(); 81280304Sjkim BN_mod(newsig->r, tmp, dsa->q, ctx); 82280304Sjkim } 83280304Sjkim while (BN_is_zero(newsig->r)); 84280304Sjkim /* generate s = (xr + k(Hm)) mod q */ 85280304Sjkim BN_mod_mul(tmp, dsa->priv_key, newsig->r, dsa->q, ctx); 86280304Sjkim BN_mod_mul(tmp2, k, md, dsa->q, ctx); 87280304Sjkim if (!newsig->s) 88280304Sjkim newsig->s = BN_new(); 89280304Sjkim BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx); 90280304Sjkim } 91280304Sjkim while (BN_is_zero(newsig->s)); 92280304Sjkim err: 93280304Sjkim BN_free(md); 94280304Sjkim BN_CTX_end(ctx); 95280304Sjkim BN_CTX_free(ctx); 96280304Sjkim return newsig; 97280304Sjkim} 98238384Sjkim 99238384Sjkim/* 100238384Sjkim * Packs signature according to Cryptocom rules 101238384Sjkim * and frees up DSA_SIG structure 102238384Sjkim */ 103280304Sjkim/*- 104238384Sjkimint pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen) 105280304Sjkim { 106280304Sjkim *siglen = 2*order; 107280304Sjkim memset(sig,0,*siglen); 108280304Sjkim store_bignum(s->r, sig,order); 109280304Sjkim store_bignum(s->s, sig + order,order); 110280304Sjkim dump_signature("serialized",sig,*siglen); 111280304Sjkim DSA_SIG_free(s); 112280304Sjkim return 1; 113280304Sjkim } 114238384Sjkim*/ 115238384Sjkim/* 116238384Sjkim * Packs signature according to Cryptopro rules 117238384Sjkim * and frees up DSA_SIG structure 118238384Sjkim */ 119280304Sjkimint pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen) 120280304Sjkim{ 121280304Sjkim *siglen = 2 * order; 122280304Sjkim memset(sig, 0, *siglen); 123280304Sjkim store_bignum(s->s, sig, order); 124280304Sjkim store_bignum(s->r, sig + order, order); 125280304Sjkim dump_signature("serialized", sig, *siglen); 126280304Sjkim DSA_SIG_free(s); 127280304Sjkim return 1; 128280304Sjkim} 129238384Sjkim 130238384Sjkim/* 131238384Sjkim * Verifies signature passed as DSA_SIG structure 132238384Sjkim * 133238384Sjkim */ 134238384Sjkim 135238384Sjkimint gost_do_verify(const unsigned char *dgst, int dgst_len, 136280304Sjkim DSA_SIG *sig, DSA *dsa) 137280304Sjkim{ 138280304Sjkim BIGNUM *md, *tmp = NULL; 139280304Sjkim BIGNUM *q2 = NULL; 140280304Sjkim BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; 141280304Sjkim BIGNUM *tmp2 = NULL, *tmp3 = NULL; 142280304Sjkim int ok; 143280304Sjkim BN_CTX *ctx = BN_CTX_new(); 144238384Sjkim 145280304Sjkim BN_CTX_start(ctx); 146280304Sjkim if (BN_cmp(sig->s, dsa->q) >= 1 || BN_cmp(sig->r, dsa->q) >= 1) { 147280304Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); 148280304Sjkim return 0; 149280304Sjkim } 150280304Sjkim md = hashsum2bn(dgst); 151238384Sjkim 152280304Sjkim tmp = BN_CTX_get(ctx); 153280304Sjkim v = BN_CTX_get(ctx); 154280304Sjkim q2 = BN_CTX_get(ctx); 155280304Sjkim z1 = BN_CTX_get(ctx); 156280304Sjkim z2 = BN_CTX_get(ctx); 157280304Sjkim tmp2 = BN_CTX_get(ctx); 158280304Sjkim tmp3 = BN_CTX_get(ctx); 159280304Sjkim u = BN_CTX_get(ctx); 160280304Sjkim 161280304Sjkim BN_mod(tmp, md, dsa->q, ctx); 162280304Sjkim if (BN_is_zero(tmp)) { 163280304Sjkim BN_one(md); 164280304Sjkim } 165280304Sjkim BN_copy(q2, dsa->q); 166280304Sjkim BN_sub_word(q2, 2); 167280304Sjkim BN_mod_exp(v, md, q2, dsa->q, ctx); 168280304Sjkim BN_mod_mul(z1, sig->s, v, dsa->q, ctx); 169280304Sjkim BN_sub(tmp, dsa->q, sig->r); 170280304Sjkim BN_mod_mul(z2, tmp, v, dsa->p, ctx); 171280304Sjkim BN_mod_exp(tmp, dsa->g, z1, dsa->p, ctx); 172280304Sjkim BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx); 173280304Sjkim BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx); 174280304Sjkim BN_mod(u, tmp3, dsa->q, ctx); 175280304Sjkim ok = BN_cmp(u, sig->r); 176280304Sjkim 177280304Sjkim BN_free(md); 178280304Sjkim BN_CTX_end(ctx); 179280304Sjkim BN_CTX_free(ctx); 180280304Sjkim if (ok != 0) { 181280304Sjkim GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); 182280304Sjkim } 183280304Sjkim return (ok == 0); 184280304Sjkim} 185280304Sjkim 186238384Sjkim/* 187238384Sjkim * Computes public keys for GOST R 34.10-94 algorithm 188238384Sjkim * 189238384Sjkim */ 190238384Sjkimint gost94_compute_public(DSA *dsa) 191280304Sjkim{ 192280304Sjkim /* Now fill algorithm parameters with correct values */ 193280304Sjkim BN_CTX *ctx = BN_CTX_new(); 194280304Sjkim if (!dsa->g) { 195280304Sjkim GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED); 196280304Sjkim return 0; 197280304Sjkim } 198280304Sjkim /* Compute public key y = a^x mod p */ 199280304Sjkim dsa->pub_key = BN_new(); 200280304Sjkim BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx); 201280304Sjkim BN_CTX_free(ctx); 202280304Sjkim return 1; 203280304Sjkim} 204238384Sjkim 205238384Sjkim/* 206238384Sjkim * Fill GOST 94 params, searching them in R3410_paramset array 207238384Sjkim * by nid of paramset 208238384Sjkim * 209238384Sjkim */ 210280304Sjkimint fill_GOST94_params(DSA *dsa, int nid) 211280304Sjkim{ 212280304Sjkim R3410_params *params = R3410_paramset; 213280304Sjkim while (params->nid != NID_undef && params->nid != nid) 214280304Sjkim params++; 215280304Sjkim if (params->nid == NID_undef) { 216280304Sjkim GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET); 217280304Sjkim return 0; 218280304Sjkim } 219238384Sjkim#define dump_signature(a,b,c) 220280304Sjkim if (dsa->p) { 221280304Sjkim BN_free(dsa->p); 222280304Sjkim } 223280304Sjkim dsa->p = NULL; 224280304Sjkim BN_dec2bn(&(dsa->p), params->p); 225280304Sjkim if (dsa->q) { 226280304Sjkim BN_free(dsa->q); 227280304Sjkim } 228280304Sjkim dsa->q = NULL; 229280304Sjkim BN_dec2bn(&(dsa->q), params->q); 230280304Sjkim if (dsa->g) { 231280304Sjkim BN_free(dsa->g); 232280304Sjkim } 233280304Sjkim dsa->g = NULL; 234280304Sjkim BN_dec2bn(&(dsa->g), params->a); 235280304Sjkim return 1; 236280304Sjkim} 237238384Sjkim 238238384Sjkim/* 239238384Sjkim * Generate GOST R 34.10-94 keypair 240238384Sjkim * 241238384Sjkim * 242238384Sjkim */ 243238384Sjkimint gost_sign_keygen(DSA *dsa) 244280304Sjkim{ 245280304Sjkim dsa->priv_key = BN_new(); 246280304Sjkim BN_rand_range(dsa->priv_key, dsa->q); 247280304Sjkim return gost94_compute_public(dsa); 248280304Sjkim} 249238384Sjkim 250238384Sjkim/* Unpack signature according to cryptocom rules */ 251280304Sjkim/*- 252238384SjkimDSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) 253280304Sjkim { 254280304Sjkim DSA_SIG *s; 255280304Sjkim s = DSA_SIG_new(); 256280304Sjkim if (s == NULL) 257280304Sjkim { 258280304Sjkim GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY); 259280304Sjkim return(NULL); 260280304Sjkim } 261280304Sjkim s->r = getbnfrombuf(sig, siglen/2); 262280304Sjkim s->s = getbnfrombuf(sig + siglen/2, siglen/2); 263280304Sjkim return s; 264280304Sjkim } 265238384Sjkim*/ 266238384Sjkim/* Unpack signature according to cryptopro rules */ 267280304SjkimDSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen) 268280304Sjkim{ 269280304Sjkim DSA_SIG *s; 270238384Sjkim 271280304Sjkim s = DSA_SIG_new(); 272280304Sjkim if (s == NULL) { 273280304Sjkim GOSTerr(GOST_F_UNPACK_CP_SIGNATURE, GOST_R_NO_MEMORY); 274280304Sjkim return NULL; 275280304Sjkim } 276280304Sjkim s->s = getbnfrombuf(sig, siglen / 2); 277280304Sjkim s->r = getbnfrombuf(sig + siglen / 2, siglen / 2); 278280304Sjkim return s; 279280304Sjkim} 280238384Sjkim 281238384Sjkim/* Convert little-endian byte array into bignum */ 282238384SjkimBIGNUM *hashsum2bn(const unsigned char *dgst) 283280304Sjkim{ 284280304Sjkim unsigned char buf[32]; 285280304Sjkim int i; 286280304Sjkim for (i = 0; i < 32; i++) { 287280304Sjkim buf[31 - i] = dgst[i]; 288280304Sjkim } 289280304Sjkim return getbnfrombuf(buf, 32); 290280304Sjkim} 291238384Sjkim 292238384Sjkim/* Convert byte buffer to bignum, skipping leading zeros*/ 293280304SjkimBIGNUM *getbnfrombuf(const unsigned char *buf, size_t len) 294280304Sjkim{ 295280304Sjkim while (*buf == 0 && len > 0) { 296280304Sjkim buf++; 297280304Sjkim len--; 298280304Sjkim } 299280304Sjkim if (len) { 300280304Sjkim return BN_bin2bn(buf, len, NULL); 301280304Sjkim } else { 302280304Sjkim BIGNUM *b = BN_new(); 303280304Sjkim BN_zero(b); 304280304Sjkim return b; 305280304Sjkim } 306280304Sjkim} 307238384Sjkim 308280304Sjkim/* 309280304Sjkim * Pack bignum into byte buffer of given size, filling all leading bytes by 310280304Sjkim * zeros 311280304Sjkim */ 312280304Sjkimint store_bignum(BIGNUM *bn, unsigned char *buf, int len) 313280304Sjkim{ 314280304Sjkim int bytes = BN_num_bytes(bn); 315280304Sjkim if (bytes > len) 316280304Sjkim return 0; 317280304Sjkim memset(buf, 0, len); 318280304Sjkim BN_bn2bin(bn, buf + len - bytes); 319280304Sjkim return 1; 320280304Sjkim} 321