1
/**********************************************************************
3
* Copyright (c) 2005-2006 Cryptocom LTD *
4
* This file is distributed under the same license as OpenSSL *
6
* Implementation of GOST R 34.10-94 signature algorithm *
8
* Requires OpenSSL 0.9.9 for compilation *
9
**********************************************************************/
11
#include <openssl/rand.h>
12
#include <openssl/bn.h>
13
#include <openssl/dsa.h>
14
#include <openssl/evp.h>
16
#include "gost_params.h"
18
#include "e_gost_err.h"
21
void dump_signature(const char *message,const unsigned char *buffer,size_t len)
24
fprintf(stderr,"signature %s Length=%d",message,len);
27
if (i% 16 ==0) fputc('\n',stderr);
28
fprintf (stderr," %02x",buffer[i]);
30
fprintf(stderr,"\nEnd of signature\n");
33
void dump_dsa_sig(const char *message, DSA_SIG *sig)
35
fprintf(stderr,"%s\nR=",message);
36
BN_print_fp(stderr,sig->r);
37
fprintf(stderr,"\nS=");
38
BN_print_fp(stderr,sig->s);
44
#define dump_signature(a,b,c)
45
#define dump_dsa_sig(a,b)
49
* Computes signature and returns it as DSA_SIG structure
51
DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
53
BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
54
DSA_SIG *newsig = DSA_SIG_new();
55
BIGNUM *md = hashsum2bn(dgst);
56
/* check if H(M) mod q is zero */
57
BN_CTX *ctx=BN_CTX_new();
61
GOSTerr(GOST_F_GOST_DO_SIGN,GOST_R_NO_MEMORY);
66
tmp2 = BN_CTX_get(ctx);
67
BN_mod(tmp,md,dsa->q,ctx);
76
/*Generate random number k less than q*/
77
BN_rand_range(k,dsa->q);
78
/* generate r = (a^x mod p) mod q */
79
BN_mod_exp(tmp,dsa->g, k, dsa->p,ctx);
80
if (!(newsig->r)) newsig->r=BN_new();
81
BN_mod(newsig->r,tmp,dsa->q,ctx);
83
while (BN_is_zero(newsig->r));
84
/* generate s = (xr + k(Hm)) mod q */
85
BN_mod_mul(tmp,dsa->priv_key,newsig->r,dsa->q,ctx);
86
BN_mod_mul(tmp2,k,md,dsa->q,ctx);
87
if (!newsig->s) newsig->s=BN_new();
88
BN_mod_add(newsig->s,tmp,tmp2,dsa->q,ctx);
90
while (BN_is_zero(newsig->s));
100
* Packs signature according to Cryptocom rules
101
* and frees up DSA_SIG structure
104
int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
107
memset(sig,0,*siglen);
108
store_bignum(s->r, sig,order);
109
store_bignum(s->s, sig + order,order);
110
dump_signature("serialized",sig,*siglen);
116
* Packs signature according to Cryptopro rules
117
* and frees up DSA_SIG structure
119
int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
122
memset(sig,0,*siglen);
123
store_bignum(s->s, sig, order);
124
store_bignum(s->r, sig+order,order);
125
dump_signature("serialized",sig,*siglen);
131
* Verifies signature passed as DSA_SIG structure
135
int gost_do_verify(const unsigned char *dgst, int dgst_len,
136
DSA_SIG *sig, DSA *dsa)
138
BIGNUM *md, *tmp=NULL;
140
BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL;
141
BIGNUM *tmp2=NULL,*tmp3=NULL;
143
BN_CTX *ctx = BN_CTX_new();
146
if (BN_cmp(sig->s,dsa->q)>=1||
147
BN_cmp(sig->r,dsa->q)>=1)
149
GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
159
tmp2=BN_CTX_get(ctx);
160
tmp3=BN_CTX_get(ctx);
163
BN_mod(tmp,md,dsa->q,ctx);
170
BN_mod_exp(v,md,q2,dsa->q,ctx);
171
BN_mod_mul(z1,sig->s,v,dsa->q,ctx);
172
BN_sub(tmp,dsa->q,sig->r);
173
BN_mod_mul(z2,tmp,v,dsa->p,ctx);
174
BN_mod_exp(tmp,dsa->g,z1,dsa->p,ctx);
175
BN_mod_exp(tmp2,dsa->pub_key,z2,dsa->p,ctx);
176
BN_mod_mul(tmp3,tmp,tmp2,dsa->p,ctx);
177
BN_mod(u,tmp3,dsa->q,ctx);
178
ok= BN_cmp(u,sig->r);
185
GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
191
* Computes public keys for GOST R 34.10-94 algorithm
194
int gost94_compute_public(DSA *dsa)
196
/* Now fill algorithm parameters with correct values */
197
BN_CTX *ctx = BN_CTX_new();
200
GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED);
203
/* Compute public key y = a^x mod p */
204
dsa->pub_key=BN_new();
205
BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx);
211
* Fill GOST 94 params, searching them in R3410_paramset array
215
int fill_GOST94_params(DSA *dsa,int nid)
217
R3410_params *params=R3410_paramset;
218
while (params->nid!=NID_undef && params->nid !=nid) params++;
219
if (params->nid == NID_undef)
221
GOSTerr(GOST_F_FILL_GOST94_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
224
#define dump_signature(a,b,c)
225
if (dsa->p) { BN_free(dsa->p); }
227
BN_dec2bn(&(dsa->p),params->p);
228
if (dsa->q) { BN_free(dsa->q); }
230
BN_dec2bn(&(dsa->q),params->q);
231
if (dsa->g) { BN_free(dsa->g); }
233
BN_dec2bn(&(dsa->g),params->a);
238
* Generate GOST R 34.10-94 keypair
242
int gost_sign_keygen(DSA *dsa)
244
dsa->priv_key = BN_new();
245
BN_rand_range(dsa->priv_key,dsa->q);
246
return gost94_compute_public( dsa);
249
/* Unpack signature according to cryptocom rules */
251
DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
257
GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY);
260
s->r = getbnfrombuf(sig, siglen/2);
261
s->s = getbnfrombuf(sig + siglen/2, siglen/2);
265
/* Unpack signature according to cryptopro rules */
266
DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
273
GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY);
276
s->s = getbnfrombuf(sig , siglen/2);
277
s->r = getbnfrombuf(sig + siglen/2, siglen/2);
281
/* Convert little-endian byte array into bignum */
282
BIGNUM *hashsum2bn(const unsigned char *dgst)
284
unsigned char buf[32];
290
return getbnfrombuf(buf,32);
293
/* Convert byte buffer to bignum, skipping leading zeros*/
294
BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len)
296
while (*buf==0&&len>0)
302
return BN_bin2bn(buf,len,NULL);
312
/* Pack bignum into byte buffer of given size, filling all leading bytes
314
int store_bignum(BIGNUM *bn, unsigned char *buf,int len)
316
int bytes = BN_num_bytes(bn);
317
if (bytes>len) return 0;
319
BN_bn2bin(bn,buf+len-bytes);