5bcc296475cf16e864cdceefb6bf5f104ce64392
[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,
23                     size_t len)
24 {
25     size_t i;
26     fprintf(stderr, "signature %s Length=%d", message, len);
27     for (i = 0; i < len; i++) {
28         if (i % 16 == 0)
29             fputc('\n', stderr);
30         fprintf(stderr, " %02x", buffer[i]);
31     }
32     fprintf(stderr, "\nEnd of signature\n");
33 }
34
35 void dump_dsa_sig(const char *message, DSA_SIG *sig)
36 {
37     fprintf(stderr, "%s\nR=", message);
38     BN_print_fp(stderr, sig->r);
39     fprintf(stderr, "\nS=");
40     BN_print_fp(stderr, sig->s);
41     fprintf(stderr, "\n");
42 }
43
44 #else
45
46 # define dump_signature(a,b,c)
47 # define dump_dsa_sig(a,b)
48 #endif
49
50 /*
51  * Computes signature and returns it as DSA_SIG structure
52  */
53 DSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
54 {
55     BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL;
56     DSA_SIG *newsig = DSA_SIG_new();
57     BIGNUM *md = hashsum2bn(dgst);
58     /* check if H(M) mod q is zero */
59     BN_CTX *ctx = BN_CTX_new();
60     BN_CTX_start(ctx);
61     if (!newsig) {
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         BN_one(md);
71     }
72     do {
73         do {
74             /*
75              * Generate random number k less than q
76              */
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))
81                 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)
89             newsig->s = BN_new();
90         BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx);
91     }
92     while (BN_is_zero(newsig->s));
93  err:
94     BN_free(md);
95     BN_CTX_end(ctx);
96     BN_CTX_free(ctx);
97     return newsig;
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 || BN_cmp(sig->r, dsa->q) >= 1) {
148         GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
149         return 0;
150     }
151     md = hashsum2bn(dgst);
152
153     tmp = BN_CTX_get(ctx);
154     v = BN_CTX_get(ctx);
155     q2 = BN_CTX_get(ctx);
156     z1 = BN_CTX_get(ctx);
157     z2 = BN_CTX_get(ctx);
158     tmp2 = BN_CTX_get(ctx);
159     tmp3 = BN_CTX_get(ctx);
160     u = BN_CTX_get(ctx);
161
162     BN_mod(tmp, md, dsa->q, ctx);
163     if (BN_is_zero(tmp)) {
164         BN_one(md);
165     }
166     BN_copy(q2, dsa->q);
167     BN_sub_word(q2, 2);
168     BN_mod_exp(v, md, q2, dsa->q, ctx);
169     BN_mod_mul(z1, sig->s, v, dsa->q, ctx);
170     BN_sub(tmp, dsa->q, sig->r);
171     BN_mod_mul(z2, tmp, v, dsa->p, ctx);
172     BN_mod_exp(tmp, dsa->g, z1, dsa->p, ctx);
173     BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx);
174     BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx);
175     BN_mod(u, tmp3, dsa->q, ctx);
176     ok = BN_cmp(u, sig->r);
177
178     BN_free(md);
179     BN_CTX_end(ctx);
180     BN_CTX_free(ctx);
181     if (ok != 0) {
182         GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH);
183     }
184     return (ok == 0);
185 }
186
187 /*
188  * Computes public keys for GOST R 34.10-94 algorithm
189  *
190  */
191 int gost94_compute_public(DSA *dsa)
192 {
193     /* Now fill algorithm parameters with correct values */
194     BN_CTX *ctx = BN_CTX_new();
195     if (!dsa->g) {
196         GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED);
197         return 0;
198     }
199     /* Compute public key  y = a^x mod p */
200     dsa->pub_key = BN_new();
201     BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx);
202     BN_CTX_free(ctx);
203     return 1;
204 }
205
206 /*
207  * Fill GOST 94 params, searching them in R3410_paramset array
208  * by nid of paramset
209  *
210  */
211 int fill_GOST94_params(DSA *dsa, int nid)
212 {
213     R3410_params *params = R3410_paramset;
214     while (params->nid != NID_undef && params->nid != nid)
215         params++;
216     if (params->nid == NID_undef) {
217         GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET);
218         return 0;
219     }
220 #define dump_signature(a,b,c)
221     if (dsa->p) {
222         BN_free(dsa->p);
223     }
224     dsa->p = NULL;
225     BN_dec2bn(&(dsa->p), params->p);
226     if (dsa->q) {
227         BN_free(dsa->q);
228     }
229     dsa->q = NULL;
230     BN_dec2bn(&(dsa->q), params->q);
231     if (dsa->g) {
232         BN_free(dsa->g);
233     }
234     dsa->g = NULL;
235     BN_dec2bn(&(dsa->g), params->a);
236     return 1;
237 }
238
239 /*
240  *  Generate GOST R 34.10-94 keypair
241  *
242  *
243  */
244 int gost_sign_keygen(DSA *dsa)
245 {
246     dsa->priv_key = BN_new();
247     BN_rand_range(dsa->priv_key, dsa->q);
248     return gost94_compute_public(dsa);
249 }
250
251 /* Unpack signature according to cryptocom rules  */
252 /*-
253 DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
254         {
255         DSA_SIG *s;
256         s = DSA_SIG_new();
257         if (s == NULL)
258                 {
259                 GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,ERR_R_MALLOC_FAILURE);
260                 return(NULL);
261                 }
262         s->r = getbnfrombuf(sig, siglen/2);
263         s->s = getbnfrombuf(sig + siglen/2, siglen/2);
264         return s;
265         }
266 */
267 /* Unpack signature according to cryptopro rules  */
268 DSA_SIG *unpack_cp_signature(const unsigned char *sig, size_t siglen)
269 {
270     DSA_SIG *s;
271
272     s = DSA_SIG_new();
273     if (s == NULL) {
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         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         buf++;
298         len--;
299     }
300     if (len) {
301         return BN_bin2bn(buf, len, NULL);
302     } else {
303         BIGNUM *b = BN_new();
304         BN_zero(b);
305         return b;
306     }
307 }
308
309 /*
310  * Pack bignum into byte buffer of given size, filling all leading bytes by
311  * zeros
312  */
313 int store_bignum(BIGNUM *bn, unsigned char *buf, int len)
314 {
315     int bytes = BN_num_bytes(bn);
316     if (bytes > len)
317         return 0;
318     memset(buf, 0, len);
319     BN_bn2bin(bn, buf + len - bytes);
320     return 1;
321 }