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-94 signature algorithm *
8 * Requires OpenSSL 0.9.9 for compilation *
9 **********************************************************************/
11 #include <openssl/rand.h>
12 #include <openssl/bn.h>
13 #include <openssl/dsa.h>
14 #include <openssl/err.h>
15 #include <openssl/evp.h>
17 #include "gost_params.h"
19 #include "e_gost_err.h"
22 void dump_signature(const char *message
,const unsigned char *buffer
,size_t len
)
25 fprintf(stderr
,"signature %s Length=%d",message
,len
);
28 if (i
% 16 ==0) fputc('\n',stderr
);
29 fprintf (stderr
," %02x",buffer
[i
]);
31 fprintf(stderr
,"\nEnd of signature\n");
34 void dump_dsa_sig(const char *message
, DSA_SIG
*sig
)
36 fprintf(stderr
,"%s\nR=",message
);
37 BN_print_fp(stderr
,sig
->r
);
38 fprintf(stderr
,"\nS=");
39 BN_print_fp(stderr
,sig
->s
);
45 #define dump_signature(a,b,c)
46 #define dump_dsa_sig(a,b)
50 * Computes signature and returns it as DSA_SIG structure
52 DSA_SIG
*gost_do_sign(const unsigned char *dgst
,int dlen
, DSA
*dsa
)
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();
62 GOSTerr(GOST_F_GOST_DO_SIGN
,ERR_R_MALLOC_FAILURE
);
67 tmp2
= BN_CTX_get(ctx
);
68 BN_mod(tmp
,md
,dsa
->q
,ctx
);
77 /*Generate random number k less than q*/
78 BN_rand_range(k
,dsa
->q
);
79 /* generate r = (a^x mod p) mod q */
80 BN_mod_exp(tmp
,dsa
->g
, k
, dsa
->p
,ctx
);
81 if (!(newsig
->r
)) newsig
->r
=BN_new();
82 BN_mod(newsig
->r
,tmp
,dsa
->q
,ctx
);
84 while (BN_is_zero(newsig
->r
));
85 /* generate s = (xr + k(Hm)) mod q */
86 BN_mod_mul(tmp
,dsa
->priv_key
,newsig
->r
,dsa
->q
,ctx
);
87 BN_mod_mul(tmp2
,k
,md
,dsa
->q
,ctx
);
88 if (!newsig
->s
) newsig
->s
=BN_new();
89 BN_mod_add(newsig
->s
,tmp
,tmp2
,dsa
->q
,ctx
);
91 while (BN_is_zero(newsig
->s
));
101 * Packs signature according to Cryptocom rules
102 * and frees up DSA_SIG structure
105 int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
108 memset(sig,0,*siglen);
109 store_bignum(s->r, sig,order);
110 store_bignum(s->s, sig + order,order);
111 dump_signature("serialized",sig,*siglen);
117 * Packs signature according to Cryptopro rules
118 * and frees up DSA_SIG structure
120 int pack_sign_cp(DSA_SIG
*s
,int order
,unsigned char *sig
, size_t *siglen
)
123 memset(sig
,0,*siglen
);
124 store_bignum(s
->s
, sig
, order
);
125 store_bignum(s
->r
, sig
+order
,order
);
126 dump_signature("serialized",sig
,*siglen
);
132 * Verifies signature passed as DSA_SIG structure
136 int gost_do_verify(const unsigned char *dgst
, int dgst_len
,
137 DSA_SIG
*sig
, DSA
*dsa
)
139 BIGNUM
*md
, *tmp
=NULL
;
141 BIGNUM
*u
=NULL
,*v
=NULL
,*z1
=NULL
,*z2
=NULL
;
142 BIGNUM
*tmp2
=NULL
,*tmp3
=NULL
;
144 BN_CTX
*ctx
= BN_CTX_new();
147 if (BN_cmp(sig
->s
,dsa
->q
)>=1||
148 BN_cmp(sig
->r
,dsa
->q
)>=1)
150 GOSTerr(GOST_F_GOST_DO_VERIFY
,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q
);
160 tmp2
=BN_CTX_get(ctx
);
161 tmp3
=BN_CTX_get(ctx
);
164 BN_mod(tmp
,md
,dsa
->q
,ctx
);
171 BN_mod_exp(v
,md
,q2
,dsa
->q
,ctx
);
172 BN_mod_mul(z1
,sig
->s
,v
,dsa
->q
,ctx
);
173 BN_sub(tmp
,dsa
->q
,sig
->r
);
174 BN_mod_mul(z2
,tmp
,v
,dsa
->p
,ctx
);
175 BN_mod_exp(tmp
,dsa
->g
,z1
,dsa
->p
,ctx
);
176 BN_mod_exp(tmp2
,dsa
->pub_key
,z2
,dsa
->p
,ctx
);
177 BN_mod_mul(tmp3
,tmp
,tmp2
,dsa
->p
,ctx
);
178 BN_mod(u
,tmp3
,dsa
->q
,ctx
);
179 ok
= BN_cmp(u
,sig
->r
);
186 GOSTerr(GOST_F_GOST_DO_VERIFY
,GOST_R_SIGNATURE_MISMATCH
);
192 * Computes public keys for GOST R 34.10-94 algorithm
195 int gost94_compute_public(DSA
*dsa
)
197 /* Now fill algorithm parameters with correct values */
198 BN_CTX
*ctx
= BN_CTX_new();
201 GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC
,GOST_R_KEY_IS_NOT_INITALIZED
);
204 /* Compute public key y = a^x mod p */
205 dsa
->pub_key
=BN_new();
206 BN_mod_exp(dsa
->pub_key
, dsa
->g
,dsa
->priv_key
,dsa
->p
,ctx
);
212 * Fill GOST 94 params, searching them in R3410_paramset array
216 int fill_GOST94_params(DSA
*dsa
,int nid
)
218 R3410_params
*params
=R3410_paramset
;
219 while (params
->nid
!=NID_undef
&& params
->nid
!=nid
) params
++;
220 if (params
->nid
== NID_undef
)
222 GOSTerr(GOST_F_FILL_GOST94_PARAMS
,GOST_R_UNSUPPORTED_PARAMETER_SET
);
225 #define dump_signature(a,b,c)
226 if (dsa
->p
) { BN_free(dsa
->p
); }
228 BN_dec2bn(&(dsa
->p
),params
->p
);
229 if (dsa
->q
) { BN_free(dsa
->q
); }
231 BN_dec2bn(&(dsa
->q
),params
->q
);
232 if (dsa
->g
) { BN_free(dsa
->g
); }
234 BN_dec2bn(&(dsa
->g
),params
->a
);
239 * Generate GOST R 34.10-94 keypair
243 int gost_sign_keygen(DSA
*dsa
)
245 dsa
->priv_key
= BN_new();
246 BN_rand_range(dsa
->priv_key
,dsa
->q
);
247 return gost94_compute_public( dsa
);
250 /* Unpack signature according to cryptocom rules */
252 DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
258 GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,ERR_R_MALLOC_FAILURE);
261 s->r = getbnfrombuf(sig, siglen/2);
262 s->s = getbnfrombuf(sig + siglen/2, siglen/2);
266 /* Unpack signature according to cryptopro rules */
267 DSA_SIG
*unpack_cp_signature(const unsigned char *sig
,size_t siglen
)
274 GOSTerr(GOST_F_UNPACK_CP_SIGNATURE
,ERR_R_MALLOC_FAILURE
);
277 s
->s
= getbnfrombuf(sig
, siglen
/2);
278 s
->r
= getbnfrombuf(sig
+ siglen
/2, siglen
/2);
282 /* Convert little-endian byte array into bignum */
283 BIGNUM
*hashsum2bn(const unsigned char *dgst
)
285 unsigned char buf
[32];
291 return getbnfrombuf(buf
,32);
294 /* Convert byte buffer to bignum, skipping leading zeros*/
295 BIGNUM
*getbnfrombuf(const unsigned char *buf
,size_t len
)
297 while (*buf
==0&&len
>0)
303 return BN_bin2bn(buf
,len
,NULL
);
313 /* Pack bignum into byte buffer of given size, filling all leading bytes
315 int store_bignum(BIGNUM
*bn
, unsigned char *buf
,int len
)
317 int bytes
= BN_num_bytes(bn
);
318 if (bytes
>len
) return 0;
320 BN_bn2bin(bn
,buf
+len
-bytes
);