Coverage Report

Created: 2022-11-30 06:20

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