Import OpenSSL 1.0.1m.
[dragonfly.git] / crypto / openssl / 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/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,
22                     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         if (i % 16 == 0)
28             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         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         BN_one(md);
70     }
71     do {
72         do {
73             /*
74              * Generate random number k less than q
75              */
76             BN_rand_range(k, dsa->q);
77             /* generate r = (a^x mod p) mod q */
78             BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx);
79             if (!(newsig->r))
80                 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)
88             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  * 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 int 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
135 int 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 || BN_cmp(sig->r, dsa->q) >= 1) {
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_GOST94_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 {
212     R3410_params *params = R3410_paramset;
213     while (params->nid != NID_undef && params->nid != nid)
214         params++;
215     if (params->nid == NID_undef) {
216         GOSTerr(GOST_F_FILL_GOST94_PARAMS, GOST_R_UNSUPPORTED_PARAMETER_SET);
217         return 0;
218     }
219 #define dump_signature(a,b,c)
220     if (dsa->p) {
221         BN_free(dsa->p);
222     }
223     dsa->p = NULL;
224     BN_dec2bn(&(dsa->p), params->p);
225     if (dsa->q) {
226         BN_free(dsa->q);
227     }
228     dsa->q = NULL;
229     BN_dec2bn(&(dsa->q), params->q);
230     if (dsa->g) {
231         BN_free(dsa->g);
232     }
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,GOST_R_NO_MEMORY);
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         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 */
282 BIGNUM *hashsum2bn(const unsigned char *dgst)
283 {
284     unsigned char buf[32];
285     int i;
286     for (i = 0; i < 32; i++) {
287         buf[31 - i] = dgst[i];
288     }
289     return getbnfrombuf(buf, 32);
290 }
291
292 /* Convert byte buffer to bignum, skipping leading zeros*/
293 BIGNUM *getbnfrombuf(const unsigned char *buf, size_t len)
294 {
295     while (*buf == 0 && len > 0) {
296         buf++;
297         len--;
298     }
299     if (len) {
300         return BN_bin2bn(buf, len, NULL);
301     } else {
302         BIGNUM *b = BN_new();
303         BN_zero(b);
304         return b;
305     }
306 }
307
308 /*
309  * Pack bignum into byte buffer of given size, filling all leading bytes by
310  * zeros
311  */
312 int store_bignum(BIGNUM *bn, unsigned char *buf, int len)
313 {
314     int bytes = BN_num_bytes(bn);
315     if (bytes > len)
316         return 0;
317     memset(buf, 0, len);
318     BN_bn2bin(bn, buf + len - bytes);
319     return 1;
320 }