Branch data Line data Source code
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 : 0 : DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
52 : : {
53 : 0 : BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
54 : 0 : DSA_SIG *newsig = DSA_SIG_new();
55 : 0 : BIGNUM *md = hashsum2bn(dgst);
56 : : /* check if H(M) mod q is zero */
57 : 0 : BN_CTX *ctx=BN_CTX_new();
58 : 0 : BN_CTX_start(ctx);
59 [ # # ]: 0 : if (!newsig)
60 : : {
61 : 0 : GOSTerr(GOST_F_GOST_DO_SIGN,GOST_R_NO_MEMORY);
62 : 0 : goto err;
63 : : }
64 : 0 : tmp=BN_CTX_get(ctx);
65 : 0 : k = BN_CTX_get(ctx);
66 : 0 : tmp2 = BN_CTX_get(ctx);
67 : 0 : BN_mod(tmp,md,dsa->q,ctx);
68 [ # # ]: 0 : if (BN_is_zero(tmp))
69 : : {
70 : 0 : BN_one(md);
71 : : }
72 : : do
73 : : {
74 : : do
75 : : {
76 : : /*Generate random number k less than q*/
77 : 0 : BN_rand_range(k,dsa->q);
78 : : /* generate r = (a^x mod p) mod q */
79 : 0 : BN_mod_exp(tmp,dsa->g, k, dsa->p,ctx);
80 [ # # ]: 0 : if (!(newsig->r)) newsig->r=BN_new();
81 : 0 : BN_mod(newsig->r,tmp,dsa->q,ctx);
82 : : }
83 [ # # ]: 0 : while (BN_is_zero(newsig->r));
84 : : /* generate s = (xr + k(Hm)) mod q */
85 : 0 : BN_mod_mul(tmp,dsa->priv_key,newsig->r,dsa->q,ctx);
86 : 0 : BN_mod_mul(tmp2,k,md,dsa->q,ctx);
87 [ # # ]: 0 : if (!newsig->s) newsig->s=BN_new();
88 : 0 : BN_mod_add(newsig->s,tmp,tmp2,dsa->q,ctx);
89 : : }
90 [ # # ]: 0 : while (BN_is_zero(newsig->s));
91 : : err:
92 : 0 : BN_free(md);
93 : 0 : BN_CTX_end(ctx);
94 : 0 : BN_CTX_free(ctx);
95 : 0 : 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 : 0 : int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
120 : : {
121 : 0 : *siglen = 2*order;
122 : 0 : memset(sig,0,*siglen);
123 : 0 : store_bignum(s->s, sig, order);
124 : 0 : store_bignum(s->r, sig+order,order);
125 : : dump_signature("serialized",sig,*siglen);
126 : 0 : DSA_SIG_free(s);
127 : 0 : return 1;
128 : : }
129 : :
130 : : /*
131 : : * Verifies signature passed as DSA_SIG structure
132 : : *
133 : : */
134 : :
135 : 0 : int gost_do_verify(const unsigned char *dgst, int dgst_len,
136 : : DSA_SIG *sig, DSA *dsa)
137 : : {
138 : 0 : BIGNUM *md, *tmp=NULL;
139 : 0 : BIGNUM *q2=NULL;
140 : 0 : BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL;
141 : 0 : BIGNUM *tmp2=NULL,*tmp3=NULL;
142 : : int ok;
143 : 0 : BN_CTX *ctx = BN_CTX_new();
144 : :
145 : 0 : BN_CTX_start(ctx);
146 [ # # # # ]: 0 : if (BN_cmp(sig->s,dsa->q)>=1||
147 : 0 : BN_cmp(sig->r,dsa->q)>=1)
148 : : {
149 : 0 : GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
150 : 0 : return 0;
151 : : }
152 : 0 : md=hashsum2bn(dgst);
153 : :
154 : 0 : tmp=BN_CTX_get(ctx);
155 : 0 : v=BN_CTX_get(ctx);
156 : 0 : q2=BN_CTX_get(ctx);
157 : 0 : z1=BN_CTX_get(ctx);
158 : 0 : z2=BN_CTX_get(ctx);
159 : 0 : tmp2=BN_CTX_get(ctx);
160 : 0 : tmp3=BN_CTX_get(ctx);
161 : 0 : u = BN_CTX_get(ctx);
162 : :
163 : 0 : BN_mod(tmp,md,dsa->q,ctx);
164 [ # # ]: 0 : if (BN_is_zero(tmp))
165 : : {
166 : 0 : BN_one(md);
167 : : }
168 : 0 : BN_copy(q2,dsa->q);
169 : 0 : BN_sub_word(q2,2);
170 : 0 : BN_mod_exp(v,md,q2,dsa->q,ctx);
171 : 0 : BN_mod_mul(z1,sig->s,v,dsa->q,ctx);
172 : 0 : BN_sub(tmp,dsa->q,sig->r);
173 : 0 : BN_mod_mul(z2,tmp,v,dsa->p,ctx);
174 : 0 : BN_mod_exp(tmp,dsa->g,z1,dsa->p,ctx);
175 : 0 : BN_mod_exp(tmp2,dsa->pub_key,z2,dsa->p,ctx);
176 : 0 : BN_mod_mul(tmp3,tmp,tmp2,dsa->p,ctx);
177 : 0 : BN_mod(u,tmp3,dsa->q,ctx);
178 : 0 : ok= BN_cmp(u,sig->r);
179 : :
180 : 0 : BN_free(md);
181 : 0 : BN_CTX_end(ctx);
182 : 0 : BN_CTX_free(ctx);
183 [ # # ]: 0 : if (ok!=0)
184 : : {
185 : 0 : GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
186 : : }
187 : 0 : return (ok==0);
188 : : }
189 : :
190 : : /*
191 : : * Computes public keys for GOST R 34.10-94 algorithm
192 : : *
193 : : */
194 : 0 : int gost94_compute_public(DSA *dsa)
195 : : {
196 : : /* Now fill algorithm parameters with correct values */
197 : 0 : BN_CTX *ctx = BN_CTX_new();
198 [ # # ]: 0 : if (!dsa->g)
199 : : {
200 : 0 : GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED);
201 : 0 : return 0;
202 : : }
203 : : /* Compute public key y = a^x mod p */
204 : 0 : dsa->pub_key=BN_new();
205 : 0 : BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx);
206 : 0 : BN_CTX_free(ctx);
207 : 0 : return 1;
208 : : }
209 : :
210 : : /*
211 : : * Fill GOST 94 params, searching them in R3410_paramset array
212 : : * by nid of paramset
213 : : *
214 : : */
215 : 0 : int fill_GOST94_params(DSA *dsa,int nid)
216 : : {
217 : 0 : R3410_params *params=R3410_paramset;
218 [ # # ][ # # ]: 0 : while (params->nid!=NID_undef && params->nid !=nid) params++;
219 [ # # ]: 0 : if (params->nid == NID_undef)
220 : : {
221 : 0 : GOSTerr(GOST_F_FILL_GOST94_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
222 : 0 : return 0;
223 : : }
224 : : #define dump_signature(a,b,c)
225 [ # # ]: 0 : if (dsa->p) { BN_free(dsa->p); }
226 : 0 : dsa->p=NULL;
227 : 0 : BN_dec2bn(&(dsa->p),params->p);
228 [ # # ]: 0 : if (dsa->q) { BN_free(dsa->q); }
229 : 0 : dsa->q=NULL;
230 : 0 : BN_dec2bn(&(dsa->q),params->q);
231 [ # # ]: 0 : if (dsa->g) { BN_free(dsa->g); }
232 : 0 : dsa->g=NULL;
233 : 0 : BN_dec2bn(&(dsa->g),params->a);
234 : 0 : return 1;
235 : : }
236 : :
237 : : /*
238 : : * Generate GOST R 34.10-94 keypair
239 : : *
240 : : *
241 : : */
242 : 0 : int gost_sign_keygen(DSA *dsa)
243 : : {
244 : 0 : dsa->priv_key = BN_new();
245 : 0 : BN_rand_range(dsa->priv_key,dsa->q);
246 : 0 : 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 : 0 : DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
267 : : {
268 : : DSA_SIG *s;
269 : :
270 : 0 : s = DSA_SIG_new();
271 [ # # ]: 0 : if (s == NULL)
272 : : {
273 : 0 : GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY);
274 : 0 : return NULL;
275 : : }
276 : 0 : s->s = getbnfrombuf(sig , siglen/2);
277 : 0 : s->r = getbnfrombuf(sig + siglen/2, siglen/2);
278 : 0 : return s;
279 : : }
280 : :
281 : : /* Convert little-endian byte array into bignum */
282 : 0 : BIGNUM *hashsum2bn(const unsigned char *dgst)
283 : : {
284 : : unsigned char buf[32];
285 : : int i;
286 [ # # ]: 0 : for (i=0;i<32;i++)
287 : : {
288 : 0 : buf[31-i]=dgst[i];
289 : : }
290 : 0 : return getbnfrombuf(buf,32);
291 : : }
292 : :
293 : : /* Convert byte buffer to bignum, skipping leading zeros*/
294 : 0 : BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len)
295 : : {
296 [ # # ][ # # ]: 0 : while (*buf==0&&len>0)
297 : : {
298 : 0 : buf++; len--;
299 : : }
300 [ # # ]: 0 : if (len)
301 : : {
302 : 0 : return BN_bin2bn(buf,len,NULL);
303 : : }
304 : : else
305 : : {
306 : 0 : BIGNUM *b=BN_new();
307 : 0 : BN_zero(b);
308 : 0 : return b;
309 : : }
310 : : }
311 : :
312 : : /* Pack bignum into byte buffer of given size, filling all leading bytes
313 : : * by zeros */
314 : 0 : int store_bignum(BIGNUM *bn, unsigned char *buf,int len)
315 : : {
316 : 0 : int bytes = BN_num_bytes(bn);
317 [ # # ]: 0 : if (bytes>len) return 0;
318 : 0 : memset(buf,0,len);
319 : 0 : BN_bn2bin(bn,buf+len-bytes);
320 : 0 : return 1;
321 : : }
|