1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Implementation of GOST R 34.10-2001 *
7 * Requires OpenSSL 0.9.9 for compilation *
8 **********************************************************************/
10 #include "gost_params.h"
12 #include <openssl/rand.h>
13 #include <openssl/ecdsa.h>
14 #include <openssl/err.h>
15 #include "e_gost_err.h"
18 void dump_signature(const char *message
, const unsigned char *buffer
,
20 void dump_dsa_sig(const char *message
, DSA_SIG
*sig
);
23 # define dump_signature(a,b,c)
24 # define dump_dsa_sig(a,b)
28 * Fills EC_KEY structure hidden in the app_data field of DSA structure
29 * with parameter information, extracted from parameter array in
32 * Also fils DSA->q field with copy of EC_GROUP order field to make
33 * DSA_size function work
35 int fill_GOST2001_params(EC_KEY
*eckey
, int nid
)
37 R3410_2001_params
*params
= R3410_2001_paramset
;
39 BIGNUM
*p
= NULL
, *q
= NULL
, *a
= NULL
, *b
= NULL
, *x
= NULL
, *y
= NULL
;
41 BN_CTX
*ctx
= BN_CTX_new();
45 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
, ERR_R_MALLOC_FAILURE
);
56 if(!p
|| !a
|| !b
|| !x
|| !y
|| !q
) {
57 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
, ERR_R_MALLOC_FAILURE
);
60 while (params
->nid
!= NID_undef
&& params
->nid
!= nid
)
62 if (params
->nid
== NID_undef
) {
63 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
,
64 GOST_R_UNSUPPORTED_PARAMETER_SET
);
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
);
75 grp
= EC_GROUP_new_curve_GFp(p
, a
, b
, ctx
);
77 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
, ERR_R_MALLOC_FAILURE
);
81 P
= EC_POINT_new(grp
);
83 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
, ERR_R_MALLOC_FAILURE
);
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
);
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");
101 if(!EC_GROUP_set_generator(grp
, P
, q
, NULL
)) {
102 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
, ERR_R_INTERNAL_ERROR
);
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
);
112 if (P
) EC_POINT_free(P
);
113 if (grp
) EC_GROUP_free(grp
);
122 * Computes gost2001 signature as DSA_SIG structure
126 DSA_SIG
*gost2001_do_sign(const unsigned char *dgst
, int dlen
, EC_KEY
*eckey
)
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
=
136 BN_CTX
*ctx
= BN_CTX_new();
138 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
142 OPENSSL_assert(dlen
== 32);
143 newsig
= DSA_SIG_new();
145 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
148 group
= EC_KEY_get0_group(eckey
);
150 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_INTERNAL_ERROR
);
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
);
158 priv_key
= EC_KEY_get0_private_key(eckey
);
160 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_INTERNAL_ERROR
);
164 if(!e
|| !BN_mod(e
, md
, order
, ctx
)) {
165 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_INTERNAL_ERROR
);
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");
179 C
= EC_POINT_new(group
);
181 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
186 if (!BN_rand_range(k
, order
)) {
187 GOSTerr(GOST_F_GOST2001_DO_SIGN
,
188 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED
);
191 if (!EC_POINT_mul(group
, C
, k
, NULL
, NULL
, ctx
)) {
192 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_EC_LIB
);
200 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
203 if (!EC_POINT_get_affine_coordinates_GFp(group
, C
, X
, NULL
, ctx
)) {
204 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_EC_LIB
);
208 if(!BN_nnmod(r
, X
, order
, ctx
)) {
209 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_INTERNAL_ERROR
);
213 while (BN_is_zero(r
));
214 /* s = (r*priv_key+k*e) mod order */
216 tmp
= BN_CTX_get(ctx
);
218 tmp2
= BN_CTX_get(ctx
);
221 if (!tmp
|| !tmp2
|| !s
) {
222 GOSTerr(GOST_F_GOST2001_DO_SIGN
, ERR_R_MALLOC_FAILURE
);
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
);
233 while (BN_is_zero(s
));
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
);
248 if (C
) EC_POINT_free(C
);
250 if (!ret
&& newsig
) {
251 DSA_SIG_free(newsig
);
257 * Verifies gost 2001 signature
260 int gost2001_do_verify(const unsigned char *dgst
, int dgst_len
,
261 DSA_SIG
*sig
, EC_KEY
*ec
)
263 BN_CTX
*ctx
= BN_CTX_new();
264 const EC_GROUP
*group
= EC_KEY_get0_group(ec
);
266 BIGNUM
*md
= NULL
, *e
= NULL
, *R
= NULL
, *v
= NULL
, *z1
= NULL
, *z2
=
268 BIGNUM
*X
= NULL
, *tmp
= NULL
;
270 const EC_POINT
*pub_key
= NULL
;
274 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_INTERNAL_ERROR
);
279 order
= BN_CTX_get(ctx
);
281 z1
= BN_CTX_get(ctx
);
282 z2
= BN_CTX_get(ctx
);
283 tmp
= 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
);
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
);
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
);
305 md
= hashsum2bn(dgst
);
307 if(!md
|| !BN_mod(e
, md
, order
, ctx
)) {
308 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_INTERNAL_ERROR
);
312 fprintf(stderr
, "digest as bignum: ");
313 BN_print_fp(stderr
, md
);
314 fprintf(stderr
, "\ndigest mod q: ");
315 BN_print_fp(stderr
, e
);
317 if (BN_is_zero(e
) && !BN_one(e
)) {
318 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_INTERNAL_ERROR
);
321 v
= BN_mod_inverse(v
, e
, order
, ctx
);
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
);
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
);
337 C
= EC_POINT_new(group
);
339 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_MALLOC_FAILURE
);
342 if (!EC_POINT_mul(group
, C
, z1
, pub_key
, z2
, ctx
)) {
343 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_EC_LIB
);
346 if (!EC_POINT_get_affine_coordinates_GFp(group
, C
, X
, NULL
, ctx
)) {
347 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_EC_LIB
);
350 if(!BN_mod(R
, X
, order
, ctx
)) {
351 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, ERR_R_INTERNAL_ERROR
);
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");
361 if (BN_cmp(R
, sig
->r
) != 0) {
362 GOSTerr(GOST_F_GOST2001_DO_VERIFY
, GOST_R_SIGNATURE_MISMATCH
);
367 if (C
) EC_POINT_free(C
);
377 * Computes GOST R 34.10-2001 public key
381 int gost2001_compute_public(EC_KEY
*ec
)
383 const EC_GROUP
*group
= EC_KEY_get0_group(ec
);
384 EC_POINT
*pub_key
= NULL
;
385 const BIGNUM
*priv_key
= NULL
;
390 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,
391 GOST_R_KEY_IS_NOT_INITIALIZED
);
396 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
, ERR_R_MALLOC_FAILURE
);
400 if (!(priv_key
= EC_KEY_get0_private_key(ec
))) {
401 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
, ERR_R_EC_LIB
);
405 pub_key
= EC_POINT_new(group
);
407 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
, ERR_R_MALLOC_FAILURE
);
410 if (!EC_POINT_mul(group
, pub_key
, priv_key
, NULL
, NULL
, ctx
)) {
411 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
, ERR_R_EC_LIB
);
414 if (!EC_KEY_set_public_key(ec
, pub_key
)) {
415 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
, ERR_R_EC_LIB
);
420 if (pub_key
) EC_POINT_free(pub_key
);
430 * Generates GOST R 34.10-2001 keypair
434 int gost2001_keygen(EC_KEY
*ec
)
436 BIGNUM
*order
= BN_new(), *d
= BN_new();
437 const EC_GROUP
*group
= EC_KEY_get0_group(ec
);
439 if(!group
|| !EC_GROUP_get_order(group
, order
, NULL
)) {
440 GOSTerr(GOST_F_GOST2001_KEYGEN
, ERR_R_INTERNAL_ERROR
);
447 if (!BN_rand_range(d
, order
)) {
448 GOSTerr(GOST_F_GOST2001_KEYGEN
,
449 GOST_R_RANDOM_NUMBER_GENERATOR_FAILED
);
455 while (BN_is_zero(d
));
457 if(!EC_KEY_set_private_key(ec
, d
)) {
458 GOSTerr(GOST_F_GOST2001_KEYGEN
, ERR_R_INTERNAL_ERROR
);
465 return gost2001_compute_public(ec
);