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
,size_t len
);
19 void dump_dsa_sig(const char *message
, DSA_SIG
*sig
);
22 #define dump_signature(a,b,c)
23 #define dump_dsa_sig(a,b)
27 * Fills EC_KEY structure hidden in the app_data field of DSA structure
28 * with parameter information, extracted from parameter array in
31 * Also fils DSA->q field with copy of EC_GROUP order field to make
32 * DSA_size function work
34 int fill_GOST2001_params(EC_KEY
*eckey
, int nid
)
36 R3410_2001_params
*params
= R3410_2001_paramset
;
38 BIGNUM
*p
=NULL
,*q
=NULL
,*a
=NULL
,*b
=NULL
,*x
=NULL
,*y
=NULL
;
40 BN_CTX
*ctx
=BN_CTX_new();
50 while (params
->nid
!=NID_undef
&& params
->nid
!= nid
) params
++;
51 if (params
->nid
== NID_undef
)
53 GOSTerr(GOST_F_FILL_GOST2001_PARAMS
,GOST_R_UNSUPPORTED_PARAMETER_SET
);
56 BN_hex2bn(&p
,params
->p
);
57 BN_hex2bn(&a
,params
->a
);
58 BN_hex2bn(&b
,params
->b
);
60 grp
= EC_GROUP_new_curve_GFp(p
,a
,b
,ctx
);
62 P
= EC_POINT_new(grp
);
64 BN_hex2bn(&x
,params
->x
);
65 BN_hex2bn(&y
,params
->y
);
66 EC_POINT_set_affine_coordinates_GFp(grp
,P
,x
,y
,ctx
);
67 BN_hex2bn(&q
,params
->q
);
69 fprintf(stderr
,"Set params index %d oid %s\nq=",
70 (params
-R3410_2001_paramset
),OBJ_nid2sn(params
->nid
));
71 BN_print_fp(stderr
,q
);
75 EC_GROUP_set_generator(grp
,P
,q
,NULL
);
76 EC_GROUP_set_curve_name(grp
,params
->nid
);
78 EC_KEY_set_group(eckey
,grp
);
90 * Computes gost2001 signature as DSA_SIG structure
94 DSA_SIG
*gost2001_do_sign(const unsigned char *dgst
,int dlen
, EC_KEY
*eckey
)
96 DSA_SIG
*newsig
= NULL
;
97 BIGNUM
*md
= hashsum2bn(dgst
);
99 const EC_GROUP
*group
;
100 const BIGNUM
*priv_key
;
101 BIGNUM
*r
=NULL
,*s
=NULL
,*X
=NULL
,*tmp
=NULL
,*tmp2
=NULL
, *k
=NULL
,*e
=NULL
;
103 BN_CTX
*ctx
= BN_CTX_new();
105 OPENSSL_assert(dlen
==32);
106 newsig
=DSA_SIG_new();
109 GOSTerr(GOST_F_GOST2001_DO_SIGN
,GOST_R_NO_MEMORY
);
112 group
= EC_KEY_get0_group(eckey
);
113 order
=BN_CTX_get(ctx
);
114 EC_GROUP_get_order(group
,order
,ctx
);
115 priv_key
= EC_KEY_get0_private_key(eckey
);
117 BN_mod(e
,md
,order
,ctx
);
119 fprintf(stderr
,"digest as bignum=");
120 BN_print_fp(stderr
,md
);
121 fprintf(stderr
,"\ndigest mod q=");
122 BN_print_fp(stderr
,e
);
123 fprintf(stderr
,"\n");
130 C
=EC_POINT_new(group
);
135 if (!BN_rand_range(k
,order
))
137 GOSTerr(GOST_F_GOST2001_DO_SIGN
,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED
);
138 DSA_SIG_free(newsig
);
141 if (!EC_POINT_mul(group
,C
,k
,NULL
,NULL
,ctx
))
143 GOSTerr(GOST_F_GOST2001_DO_SIGN
,ERR_R_EC_LIB
);
144 DSA_SIG_free(newsig
);
147 if (!X
) X
=BN_CTX_get(ctx
);
148 if (!EC_POINT_get_affine_coordinates_GFp(group
,C
,X
,NULL
,ctx
))
150 GOSTerr(GOST_F_GOST2001_DO_SIGN
,ERR_R_EC_LIB
);
151 DSA_SIG_free(newsig
);
154 if (!r
) r
=BN_CTX_get(ctx
);
155 BN_nnmod(r
,X
,order
,ctx
);
157 while (BN_is_zero(r
));
158 /* s = (r*priv_key+k*e) mod order */
159 if (!tmp
) tmp
= BN_CTX_get(ctx
);
160 BN_mod_mul(tmp
,priv_key
,r
,order
,ctx
);
161 if (!tmp2
) tmp2
= BN_CTX_get(ctx
);
162 BN_mod_mul(tmp2
,k
,e
,order
,ctx
);
163 if (!s
) s
=BN_CTX_get(ctx
);
164 BN_mod_add(s
,tmp
,tmp2
,order
,ctx
);
166 while (BN_is_zero(s
));
178 * Verifies gost 2001 signature
181 int gost2001_do_verify(const unsigned char *dgst
,int dgst_len
,
182 DSA_SIG
*sig
, EC_KEY
*ec
)
184 BN_CTX
*ctx
=BN_CTX_new();
185 const EC_GROUP
*group
= EC_KEY_get0_group(ec
);
187 BIGNUM
*md
= NULL
,*e
=NULL
,*R
=NULL
,*v
=NULL
,*z1
=NULL
,*z2
=NULL
;
188 BIGNUM
*X
=NULL
,*tmp
=NULL
;
190 const EC_POINT
*pub_key
=NULL
;
194 order
= BN_CTX_get(ctx
);
196 z1
= BN_CTX_get(ctx
);
197 z2
= BN_CTX_get(ctx
);
198 tmp
= BN_CTX_get(ctx
);
203 EC_GROUP_get_order(group
,order
,ctx
);
204 pub_key
= EC_KEY_get0_public_key(ec
);
205 if (BN_is_zero(sig
->s
) || BN_is_zero(sig
->r
) ||
206 (BN_cmp(sig
->s
,order
)>=1) || (BN_cmp(sig
->r
,order
)>=1))
208 GOSTerr(GOST_F_GOST2001_DO_VERIFY
,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q
);
212 md
= hashsum2bn(dgst
);
214 BN_mod(e
,md
,order
,ctx
);
216 fprintf(stderr
,"digest as bignum: ");
217 BN_print_fp(stderr
,md
);
218 fprintf(stderr
,"\ndigest mod q: ");
219 BN_print_fp(stderr
,e
);
221 if (BN_is_zero(e
)) BN_one(e
);
222 v
=BN_mod_inverse(v
,e
,order
,ctx
);
223 BN_mod_mul(z1
,sig
->s
,v
,order
,ctx
);
224 BN_sub(tmp
,order
,sig
->r
);
225 BN_mod_mul(z2
,tmp
,v
,order
,ctx
);
227 fprintf(stderr
,"\nInverted digest value: ");
228 BN_print_fp(stderr
,v
);
229 fprintf(stderr
,"\nz1: ");
230 BN_print_fp(stderr
,z1
);
231 fprintf(stderr
,"\nz2: ");
232 BN_print_fp(stderr
,z2
);
234 C
= EC_POINT_new(group
);
235 if (!EC_POINT_mul(group
,C
,z1
,pub_key
,z2
,ctx
))
237 GOSTerr(GOST_F_GOST2001_DO_VERIFY
,ERR_R_EC_LIB
);
240 if (!EC_POINT_get_affine_coordinates_GFp(group
,C
,X
,NULL
,ctx
))
242 GOSTerr(GOST_F_GOST2001_DO_VERIFY
,ERR_R_EC_LIB
);
245 BN_mod(R
,X
,order
,ctx
);
247 fprintf(stderr
,"\nX=");
248 BN_print_fp(stderr
,X
);
249 fprintf(stderr
,"\nX mod q=");
250 BN_print_fp(stderr
,R
);
251 fprintf(stderr
,"\n");
253 if (BN_cmp(R
,sig
->r
)!=0)
255 GOSTerr(GOST_F_GOST2001_DO_VERIFY
,GOST_R_SIGNATURE_MISMATCH
);
269 * Computes GOST R 34.10-2001 public key
273 int gost2001_compute_public(EC_KEY
*ec
)
275 const EC_GROUP
*group
= EC_KEY_get0_group(ec
);
276 EC_POINT
*pub_key
=NULL
;
277 const BIGNUM
*priv_key
=NULL
;
283 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,GOST_R_KEY_IS_NOT_INITIALIZED
);
288 if (!(priv_key
=EC_KEY_get0_private_key(ec
)))
290 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,ERR_R_EC_LIB
);
294 pub_key
= EC_POINT_new(group
);
295 if (!EC_POINT_mul(group
,pub_key
,priv_key
,NULL
,NULL
,ctx
))
297 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,ERR_R_EC_LIB
);
300 if (!EC_KEY_set_public_key(ec
,pub_key
))
302 GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC
,ERR_R_EC_LIB
);
308 EC_POINT_free(pub_key
);
314 * Generates GOST R 34.10-2001 keypair
318 int gost2001_keygen(EC_KEY
*ec
)
320 BIGNUM
*order
= BN_new(),*d
=BN_new();
321 const EC_GROUP
*group
= EC_KEY_get0_group(ec
);
322 EC_GROUP_get_order(group
,order
,NULL
);
326 if (!BN_rand_range(d
,order
))
328 GOSTerr(GOST_F_GOST2001_KEYGEN
,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED
);
334 while (BN_is_zero(d
));
335 EC_KEY_set_private_key(ec
,d
);
338 return gost2001_compute_public(ec
);