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