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
21void 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
33void 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 */
51DSA_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		{
61		GOSTerr(GOST_F_GOST_DO_SIGN,GOST_R_NO_MEMORY);
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/*
104int 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 */
119int 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
135int 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		{
149		GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
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		{
185		GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
186		}
187	return (ok==0);
188	}
189
190/*
191 * Computes public keys for GOST R 34.10-94 algorithm
192 *
193 */
194int gost94_compute_public(DSA *dsa)
195	{
196	/* Now fill algorithm parameters with correct values */
197	BN_CTX *ctx = BN_CTX_new();
198	if (!dsa->g)
199		{
200		GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED);
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 */
215int fill_GOST94_params(DSA *dsa,int nid)
216	{
217	R3410_params *params=R3410_paramset;
218	while (params->nid!=NID_undef && params->nid !=nid) params++;
219	if (params->nid == NID_undef)
220		{
221		GOSTerr(GOST_F_FILL_GOST94_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
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 */
242int gost_sign_keygen(DSA *dsa)
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/*
251DSA_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  */
266DSA_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		{
273		GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY);
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 */
282BIGNUM *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*/
294BIGNUM *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 */
314int 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	}
322