gost2001.c revision 306195
1/**********************************************************************
2 *                          gost2001.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-2001                                   *
7 *          Requires OpenSSL 0.9.9 for compilation                    *
8 **********************************************************************/
9#include "gost_lcl.h"
10#include "gost_params.h"
11#include <string.h>
12#include <openssl/rand.h>
13#include <openssl/ecdsa.h>
14#include <openssl/err.h>
15#include "e_gost_err.h"
16#ifdef DEBUG_SIGN
17extern
18void dump_signature(const char *message, const unsigned char *buffer,
19                    size_t len);
20void dump_dsa_sig(const char *message, DSA_SIG *sig);
21#else
22
23# define dump_signature(a,b,c)
24# define dump_dsa_sig(a,b)
25#endif
26
27/*
28 * Fills EC_KEY structure hidden in the app_data field of DSA structure
29 * with parameter information, extracted from parameter array in
30 * params.c file.
31 *
32 * Also fils DSA->q field with copy of EC_GROUP order field to make
33 * DSA_size function work
34 */
35int fill_GOST2001_params(EC_KEY *eckey, int nid)
36{
37    R3410_2001_params *params = R3410_2001_paramset;
38    EC_GROUP *grp = NULL;
39    BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
40    EC_POINT *P = NULL;
41    BN_CTX *ctx = BN_CTX_new();
42    int ok = 0;
43
44    if(!ctx) {
45        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
46        goto err;
47    }
48
49    BN_CTX_start(ctx);
50    p = BN_CTX_get(ctx);
51    a = BN_CTX_get(ctx);
52    b = BN_CTX_get(ctx);
53    x = BN_CTX_get(ctx);
54    y = BN_CTX_get(ctx);
55    q = BN_CTX_get(ctx);
56    if(!p || !a || !b || !x || !y || !q) {
57        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
58        goto err;
59    }
60    while (params->nid != NID_undef && params->nid != nid)
61        params++;
62    if (params->nid == NID_undef) {
63        GOSTerr(GOST_F_FILL_GOST2001_PARAMS,
64                GOST_R_UNSUPPORTED_PARAMETER_SET);
65        goto err;
66    }
67    if(!BN_hex2bn(&p, params->p)
68        || !BN_hex2bn(&a, params->a)
69        || !BN_hex2bn(&b, params->b)) {
70        GOSTerr(GOST_F_FILL_GOST2001_PARAMS,
71                ERR_R_INTERNAL_ERROR);
72        goto err;
73    }
74
75    grp = EC_GROUP_new_curve_GFp(p, a, b, ctx);
76    if(!grp)  {
77        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
78        goto err;
79    }
80
81    P = EC_POINT_new(grp);
82    if(!P)  {
83        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
84        goto err;
85    }
86
87    if(!BN_hex2bn(&x, params->x)
88        || !BN_hex2bn(&y, params->y)
89        || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx)
90        || !BN_hex2bn(&q, params->q))  {
91        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
92        goto err;
93    }
94#ifdef DEBUG_KEYS
95    fprintf(stderr, "Set params index %d oid %s\nq=",
96            (params - R3410_2001_paramset), OBJ_nid2sn(params->nid));
97    BN_print_fp(stderr, q);
98    fprintf(stderr, "\n");
99#endif
100
101    if(!EC_GROUP_set_generator(grp, P, q, NULL)) {
102        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
103        goto err;
104    }
105    EC_GROUP_set_curve_name(grp, params->nid);
106    if(!EC_KEY_set_group(eckey, grp)) {
107        GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
108        goto err;
109    }
110    ok = 1;
111 err:
112    if (P) EC_POINT_free(P);
113    if (grp) EC_GROUP_free(grp);
114    if (ctx) {
115        BN_CTX_end(ctx);
116        BN_CTX_free(ctx);
117    }
118    return ok;
119}
120
121/*
122 * Computes gost2001 signature as DSA_SIG structure
123 *
124 *
125 */
126DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
127{
128    DSA_SIG *newsig = NULL, *ret = NULL;
129    BIGNUM *md = hashsum2bn(dgst);
130    BIGNUM *order = NULL;
131    const EC_GROUP *group;
132    const BIGNUM *priv_key;
133    BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k =
134        NULL, *e = NULL;
135    EC_POINT *C = NULL;
136    BN_CTX *ctx = BN_CTX_new();
137    if(!ctx || !md) {
138        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
139        goto err;
140    }
141    BN_CTX_start(ctx);
142    OPENSSL_assert(dlen == 32);
143    newsig = DSA_SIG_new();
144    if (!newsig) {
145        GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_NO_MEMORY);
146        goto err;
147    }
148    group = EC_KEY_get0_group(eckey);
149    if(!group) {
150        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
151        goto err;
152    }
153    order = BN_CTX_get(ctx);
154    if(!order || !EC_GROUP_get_order(group, order, ctx)) {
155        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
156        goto err;
157    }
158    priv_key = EC_KEY_get0_private_key(eckey);
159    if(!priv_key) {
160        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
161        goto err;
162    }
163    e = BN_CTX_get(ctx);
164    if(!e || !BN_mod(e, md, order, ctx)) {
165        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
166        goto err;
167    }
168#ifdef DEBUG_SIGN
169    fprintf(stderr, "digest as bignum=");
170    BN_print_fp(stderr, md);
171    fprintf(stderr, "\ndigest mod q=");
172    BN_print_fp(stderr, e);
173    fprintf(stderr, "\n");
174#endif
175    if (BN_is_zero(e)) {
176        BN_one(e);
177    }
178    k = BN_CTX_get(ctx);
179    C = EC_POINT_new(group);
180    if(!k || !C) {
181        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
182        goto err;
183    }
184    do {
185        do {
186            if (!BN_rand_range(k, order)) {
187                GOSTerr(GOST_F_GOST2001_DO_SIGN,
188                        GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
189                goto err;
190            }
191            if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) {
192                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
193                goto err;
194            }
195            if (!X)
196                X = BN_CTX_get(ctx);
197            if (!r)
198                r = BN_CTX_get(ctx);
199            if (!X || !r) {
200                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
201                goto err;
202            }
203            if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
204                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
205                goto err;
206            }
207
208            if(!BN_nnmod(r, X, order, ctx)) {
209                GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
210                goto err;
211            }
212        }
213        while (BN_is_zero(r));
214        /* s =  (r*priv_key+k*e) mod order */
215        if (!tmp)
216            tmp = BN_CTX_get(ctx);
217        if (!tmp2)
218            tmp2 = BN_CTX_get(ctx);
219        if (!s)
220            s = BN_CTX_get(ctx);
221        if (!tmp || !tmp2 || !s) {
222            GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
223            goto err;
224        }
225
226        if(!BN_mod_mul(tmp, priv_key, r, order, ctx)
227            || !BN_mod_mul(tmp2, k, e, order, ctx)
228            || !BN_mod_add(s, tmp, tmp2, order, ctx)) {
229            GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
230            goto err;
231        }
232    }
233    while (BN_is_zero(s));
234
235    newsig->s = BN_dup(s);
236    newsig->r = BN_dup(r);
237    if(!newsig->s || !newsig->r) {
238        GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
239        goto err;
240    }
241
242    ret = newsig;
243 err:
244    if(ctx) {
245        BN_CTX_end(ctx);
246        BN_CTX_free(ctx);
247    }
248    if (C) EC_POINT_free(C);
249    if (md) BN_free(md);
250    if (!ret && newsig) {
251        DSA_SIG_free(newsig);
252    }
253    return ret;
254}
255
256/*
257 * Verifies gost 2001 signature
258 *
259 */
260int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
261                       DSA_SIG *sig, EC_KEY *ec)
262{
263    BN_CTX *ctx = BN_CTX_new();
264    const EC_GROUP *group = EC_KEY_get0_group(ec);
265    BIGNUM *order;
266    BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 =
267        NULL;
268    BIGNUM *X = NULL, *tmp = NULL;
269    EC_POINT *C = NULL;
270    const EC_POINT *pub_key = NULL;
271    int ok = 0;
272
273    if(!ctx || !group) {
274        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
275        goto err;
276    }
277
278    BN_CTX_start(ctx);
279    order = BN_CTX_get(ctx);
280    e = BN_CTX_get(ctx);
281    z1 = BN_CTX_get(ctx);
282    z2 = BN_CTX_get(ctx);
283    tmp = BN_CTX_get(ctx);
284    X = BN_CTX_get(ctx);
285    R = BN_CTX_get(ctx);
286    v = BN_CTX_get(ctx);
287    if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) {
288        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE);
289        goto err;
290    }
291
292    pub_key = EC_KEY_get0_public_key(ec);
293    if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) {
294        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
295        goto err;
296    }
297
298    if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
299        (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) {
300        GOSTerr(GOST_F_GOST2001_DO_VERIFY,
301                GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
302        goto err;
303
304    }
305    md = hashsum2bn(dgst);
306
307    if(!md || !BN_mod(e, md, order, ctx)) {
308        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
309        goto err;
310    }
311#ifdef DEBUG_SIGN
312    fprintf(stderr, "digest as bignum: ");
313    BN_print_fp(stderr, md);
314    fprintf(stderr, "\ndigest mod q: ");
315    BN_print_fp(stderr, e);
316#endif
317    if (BN_is_zero(e) && !BN_one(e)) {
318        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
319        goto err;
320    }
321    v = BN_mod_inverse(v, e, order, ctx);
322    if(!v
323        || !BN_mod_mul(z1, sig->s, v, order, ctx)
324        || !BN_sub(tmp, order, sig->r)
325        || !BN_mod_mul(z2, tmp, v, order, ctx)) {
326        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
327        goto err;
328    }
329#ifdef DEBUG_SIGN
330    fprintf(stderr, "\nInverted digest value: ");
331    BN_print_fp(stderr, v);
332    fprintf(stderr, "\nz1: ");
333    BN_print_fp(stderr, z1);
334    fprintf(stderr, "\nz2: ");
335    BN_print_fp(stderr, z2);
336#endif
337    C = EC_POINT_new(group);
338    if (!C) {
339        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE);
340        goto err;
341    }
342    if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) {
343        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
344        goto err;
345    }
346    if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
347        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
348        goto err;
349    }
350    if(!BN_mod(R, X, order, ctx)) {
351        GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
352        goto err;
353    }
354#ifdef DEBUG_SIGN
355    fprintf(stderr, "\nX=");
356    BN_print_fp(stderr, X);
357    fprintf(stderr, "\nX mod q=");
358    BN_print_fp(stderr, R);
359    fprintf(stderr, "\n");
360#endif
361    if (BN_cmp(R, sig->r) != 0) {
362        GOSTerr(GOST_F_GOST2001_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH);
363    } else {
364        ok = 1;
365    }
366 err:
367    if (C) EC_POINT_free(C);
368    if (ctx) {
369        BN_CTX_end(ctx);
370        BN_CTX_free(ctx);
371    }
372    if (md) BN_free(md);
373    return ok;
374}
375
376/*
377 * Computes GOST R 34.10-2001 public key
378 *
379 *
380 */
381int gost2001_compute_public(EC_KEY *ec)
382{
383    const EC_GROUP *group = EC_KEY_get0_group(ec);
384    EC_POINT *pub_key = NULL;
385    const BIGNUM *priv_key = NULL;
386    BN_CTX *ctx = NULL;
387    int ok = 0;
388
389    if (!group) {
390        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,
391                GOST_R_KEY_IS_NOT_INITIALIZED);
392        return 0;
393    }
394    ctx = BN_CTX_new();
395    if(!ctx) {
396        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE);
397        goto err;
398    }
399    BN_CTX_start(ctx);
400    if (!(priv_key = EC_KEY_get0_private_key(ec))) {
401        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
402        goto err;
403    }
404
405    pub_key = EC_POINT_new(group);
406    if(!pub_key) {
407        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE);
408        goto err;
409    }
410    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) {
411        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
412        goto err;
413    }
414    if (!EC_KEY_set_public_key(ec, pub_key)) {
415        GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB);
416        goto err;
417    }
418    ok = 256;
419 err:
420    if (pub_key) EC_POINT_free(pub_key);
421    if (ctx) {
422        BN_CTX_end(ctx);
423        BN_CTX_free(ctx);
424    }
425    return ok;
426}
427
428/*
429 *
430 * Generates GOST R 34.10-2001 keypair
431 *
432 *
433 */
434int gost2001_keygen(EC_KEY *ec)
435{
436    BIGNUM *order = BN_new(), *d = BN_new();
437    const EC_GROUP *group = NULL;
438
439    if (order == NULL || d == NULL) {
440        GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_MALLOC_FAILURE);
441        BN_free(d);
442        BN_free(order);
443        return 0;
444    }
445
446    group = EC_KEY_get0_group(ec);
447    if(!group || !EC_GROUP_get_order(group, order, NULL)) {
448        GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR);
449        BN_free(d);
450        BN_free(order);
451        return 0;
452    }
453
454    do {
455        if (!BN_rand_range(d, order)) {
456            GOSTerr(GOST_F_GOST2001_KEYGEN,
457                    GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
458            BN_free(d);
459            BN_free(order);
460            return 0;
461        }
462    }
463    while (BN_is_zero(d));
464
465    if(!EC_KEY_set_private_key(ec, d)) {
466        GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR);
467        BN_free(d);
468        BN_free(order);
469        return 0;
470    }
471    BN_free(d);
472    BN_free(order);
473    return gost2001_compute_public(ec);
474}
475