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