OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
gost_sign.c
Go to the documentation of this file.
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 
16 #include "gost_params.h"
17 #include "gost_lcl.h"
18 #include "e_gost_err.h"
19 
20 #ifdef DEBUG_SIGN
21 void dump_signature(const char *message,const unsigned char *buffer,size_t len)
22  {
23  size_t i;
24  fprintf(stderr,"signature %s Length=%d",message,len);
25  for (i=0; i<len; i++)
26  {
27  if (i% 16 ==0) fputc('\n',stderr);
28  fprintf (stderr," %02x",buffer[i]);
29  }
30  fprintf(stderr,"\nEnd of signature\n");
31  }
32 
33 void dump_dsa_sig(const char *message, DSA_SIG *sig)
34  {
35  fprintf(stderr,"%s\nR=",message);
36  BN_print_fp(stderr,sig->r);
37  fprintf(stderr,"\nS=");
38  BN_print_fp(stderr,sig->s);
39  fprintf(stderr,"\n");
40  }
41 
42 #else
43 
44 #define dump_signature(a,b,c)
45 #define dump_dsa_sig(a,b)
46 #endif
47 
48 /*
49  * Computes signature and returns it as DSA_SIG structure
50  */
51 DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
52  {
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();
58  BN_CTX_start(ctx);
59  if (!newsig)
60  {
62  goto err;
63  }
64  tmp=BN_CTX_get(ctx);
65  k = BN_CTX_get(ctx);
66  tmp2 = BN_CTX_get(ctx);
67  BN_mod(tmp,md,dsa->q,ctx);
68  if (BN_is_zero(tmp))
69  {
70  BN_one(md);
71  }
72  do
73  {
74  do
75  {
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);
82  }
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);
89  }
90  while (BN_is_zero(newsig->s));
91  err:
92  BN_free(md);
93  BN_CTX_end(ctx);
94  BN_CTX_free(ctx);
95  return newsig;
96  }
97 
98 
99 /*
100  * Packs signature according to Cryptocom rules
101  * and frees up DSA_SIG structure
102  */
103 /*
104 int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
105  {
106  *siglen = 2*order;
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);
111  DSA_SIG_free(s);
112  return 1;
113  }
114 */
115 /*
116  * Packs signature according to Cryptopro rules
117  * and frees up DSA_SIG structure
118  */
119 int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
120  {
121  *siglen = 2*order;
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);
126  DSA_SIG_free(s);
127  return 1;
128  }
129 
130 /*
131  * Verifies signature passed as DSA_SIG structure
132  *
133  */
134 
135 int gost_do_verify(const unsigned char *dgst, int dgst_len,
136  DSA_SIG *sig, DSA *dsa)
137  {
138  BIGNUM *md, *tmp=NULL;
139  BIGNUM *q2=NULL;
140  BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL;
141  BIGNUM *tmp2=NULL,*tmp3=NULL;
142  int ok;
143  BN_CTX *ctx = BN_CTX_new();
144 
145  BN_CTX_start(ctx);
146  if (BN_cmp(sig->s,dsa->q)>=1||
147  BN_cmp(sig->r,dsa->q)>=1)
148  {
150  return 0;
151  }
152  md=hashsum2bn(dgst);
153 
154  tmp=BN_CTX_get(ctx);
155  v=BN_CTX_get(ctx);
156  q2=BN_CTX_get(ctx);
157  z1=BN_CTX_get(ctx);
158  z2=BN_CTX_get(ctx);
159  tmp2=BN_CTX_get(ctx);
160  tmp3=BN_CTX_get(ctx);
161  u = BN_CTX_get(ctx);
162 
163  BN_mod(tmp,md,dsa->q,ctx);
164  if (BN_is_zero(tmp))
165  {
166  BN_one(md);
167  }
168  BN_copy(q2,dsa->q);
169  BN_sub_word(q2,2);
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);
179 
180  BN_free(md);
181  BN_CTX_end(ctx);
182  BN_CTX_free(ctx);
183  if (ok!=0)
184  {
186  }
187  return (ok==0);
188  }
189 
190 /*
191  * Computes public keys for GOST R 34.10-94 algorithm
192  *
193  */
195  {
196  /* Now fill algorithm parameters with correct values */
197  BN_CTX *ctx = BN_CTX_new();
198  if (!dsa->g)
199  {
201  return 0;
202  }
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);
206  BN_CTX_free(ctx);
207  return 1;
208  }
209 
210 /*
211  * Fill GOST 94 params, searching them in R3410_paramset array
212  * by nid of paramset
213  *
214  */
216  {
218  while (params->nid!=NID_undef && params->nid !=nid) params++;
219  if (params->nid == NID_undef)
220  {
222  return 0;
223  }
224 #define dump_signature(a,b,c)
225  if (dsa->p) { BN_free(dsa->p); }
226  dsa->p=NULL;
227  BN_dec2bn(&(dsa->p),params->p);
228  if (dsa->q) { BN_free(dsa->q); }
229  dsa->q=NULL;
230  BN_dec2bn(&(dsa->q),params->q);
231  if (dsa->g) { BN_free(dsa->g); }
232  dsa->g=NULL;
233  BN_dec2bn(&(dsa->g),params->a);
234  return 1;
235  }
236 
237 /*
238  * Generate GOST R 34.10-94 keypair
239  *
240  *
241  */
243  {
244  dsa->priv_key = BN_new();
245  BN_rand_range(dsa->priv_key,dsa->q);
246  return gost94_compute_public( dsa);
247  }
248 
249 /* Unpack signature according to cryptocom rules */
250 /*
251 DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
252  {
253  DSA_SIG *s;
254  s = DSA_SIG_new();
255  if (s == NULL)
256  {
257  GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY);
258  return(NULL);
259  }
260  s->r = getbnfrombuf(sig, siglen/2);
261  s->s = getbnfrombuf(sig + siglen/2, siglen/2);
262  return s;
263  }
264 */
265 /* Unpack signature according to cryptopro rules */
266 DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
267  {
268  DSA_SIG *s;
269 
270  s = DSA_SIG_new();
271  if (s == NULL)
272  {
274  return NULL;
275  }
276  s->s = getbnfrombuf(sig , siglen/2);
277  s->r = getbnfrombuf(sig + siglen/2, siglen/2);
278  return s;
279  }
280 
281 /* Convert little-endian byte array into bignum */
282 BIGNUM *hashsum2bn(const unsigned char *dgst)
283  {
284  unsigned char buf[32];
285  int i;
286  for (i=0;i<32;i++)
287  {
288  buf[31-i]=dgst[i];
289  }
290  return getbnfrombuf(buf,32);
291  }
292 
293 /* Convert byte buffer to bignum, skipping leading zeros*/
294 BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len)
295  {
296  while (*buf==0&&len>0)
297  {
298  buf++; len--;
299  }
300  if (len)
301  {
302  return BN_bin2bn(buf,len,NULL);
303  }
304  else
305  {
306  BIGNUM *b=BN_new();
307  BN_zero(b);
308  return b;
309  }
310  }
311 
312 /* Pack bignum into byte buffer of given size, filling all leading bytes
313  * by zeros */
314 int store_bignum(BIGNUM *bn, unsigned char *buf,int len)
315  {
316  int bytes = BN_num_bytes(bn);
317  if (bytes>len) return 0;
318  memset(buf,0,len);
319  BN_bn2bin(bn,buf+len-bytes);
320  return 1;
321  }