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 algoritgthm *
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/evp.h>
19 #include "e_gost_err.h"
22 void dump_signature(const char *message,const unsigned char *buffer,size_t len) {
24 fprintf(stderr,"signature %s Length=%d",message,len);
25 for (i=0; i<len; i++) {
26 if (i% 16 ==0) fputc('\n',stderr);
27 fprintf (stderr," %02x",buffer[i]);
29 fprintf(stderr,"\nEnd of signature\n");
32 void dump_dsa_sig(const char *message, DSA_SIG *sig) {
33 fprintf(stderr,"%s\nR=",message);
34 BN_print_fp(stderr,sig->r);
35 fprintf(stderr,"\nS=");
36 BN_print_fp(stderr,sig->s);
42 #define dump_signature(a,b,c)
43 #define dump_dsa_sig(a,b)
47 * Computes signature and returns it as DSA_SIG structure
49 DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
51 BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
52 DSA_SIG *newsig = DSA_SIG_new();
53 BIGNUM *md = hashsum2bn(dgst);
54 /* check if H(M) mod q is zero */
55 BN_CTX *ctx=BN_CTX_new();
59 GOSTerr(GOST_F_GOST_DO_SIGN,GOST_R_NO_MEMORY);
64 tmp2 = BN_CTX_get(ctx);
65 BN_mod(tmp,md,dsa->q,ctx);
72 /*Generate random number k less than q*/
73 BN_rand_range(k,dsa->q);
74 /* generate r = (a^x mod p) mod q */
75 BN_mod_exp(tmp,dsa->g, k, dsa->p,ctx);
76 if (!(newsig->r)) newsig->r=BN_new();
77 BN_mod(newsig->r,tmp,dsa->q,ctx);
78 } while (BN_is_zero(newsig->r));
79 /* generate s = (xr + k(Hm)) mod q */
80 BN_mod_mul(tmp,dsa->priv_key,newsig->r,dsa->q,ctx);
81 BN_mod_mul(tmp2,k,md,dsa->q,ctx);
82 if (!newsig->s) newsig->s=BN_new();
83 BN_mod_add(newsig->s,tmp,tmp2,dsa->q,ctx);
84 } while (BN_is_zero(newsig->s));
94 * Packs signature according to Cryptocom rules
95 * and frees up DSA_SIG structure
98 int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen)
102 memset(sig,0,*siglen);
103 store_bignum(s->r, sig,order);
104 store_bignum(s->s, sig + order,order);
105 dump_signature("serialized",sig,*siglen);
110 * Packs signature according to Cryptopro rules
111 * and frees up DSA_SIG structure
113 int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen)
117 memset(sig,0,*siglen);
118 store_bignum(s->s, sig, order);
119 store_bignum(s->r, sig+order,order);
120 dump_signature("serialized",sig,*siglen);
129 * Verifies signature passed as DSA_SIG structure
133 int gost_do_verify(const unsigned char *dgst, int dgst_len,
134 DSA_SIG *sig, DSA *dsa)
136 BIGNUM *md, *tmp=NULL;
138 BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL;
139 BIGNUM *tmp2=NULL,*tmp3=NULL;
141 BN_CTX *ctx = BN_CTX_new();
144 if (BN_cmp(sig->s,dsa->q)>=1||
145 BN_cmp(sig->r,dsa->q)>=1)
147 GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
157 tmp2=BN_CTX_get(ctx);
158 tmp3=BN_CTX_get(ctx);
161 BN_mod(tmp,md,dsa->q,ctx);
162 if (BN_is_zero(tmp)) {
167 BN_mod_exp(v,md,q2,dsa->q,ctx);
168 BN_mod_mul(z1,sig->s,v,dsa->q,ctx);
169 BN_sub(tmp,dsa->q,sig->r);
170 BN_mod_mul(z2,tmp,v,dsa->p,ctx);
171 BN_mod_exp(tmp,dsa->g,z1,dsa->p,ctx);
172 BN_mod_exp(tmp2,dsa->pub_key,z2,dsa->p,ctx);
173 BN_mod_mul(tmp3,tmp,tmp2,dsa->p,ctx);
174 BN_mod(u,tmp3,dsa->q,ctx);
175 ok= BN_cmp(u,sig->r);
181 GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
187 * Computes public keys for GOST R 34.10-94 algorithm
190 int gost94_compute_public(DSA *dsa)
192 /* Now fill algorithm parameters with correct values */
193 BN_CTX *ctx = BN_CTX_new();
195 GOSTerr(GOST_F_GOST_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED);
198 /* Compute public key y = a^x mod p */
199 dsa->pub_key=BN_new();
200 BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx);
206 * Fill GOST 94 params, searching them in R3410_paramset array
210 int fill_GOST94_params(DSA *dsa,int nid) {
211 R3410_params *params=R3410_paramset;
212 while (params->nid!=NID_undef && params->nid !=nid) params++;
213 if (params->nid == NID_undef)
215 GOSTerr(GOST_F_FILL_GOST94_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
218 #define dump_signature(a,b,c)
219 if (dsa->p) { BN_free(dsa->p); }
221 BN_dec2bn(&(dsa->p),params->p);
222 if (dsa->q) { BN_free(dsa->q); }
224 BN_dec2bn(&(dsa->q),params->q);
225 if (dsa->g) { BN_free(dsa->g); }
227 BN_dec2bn(&(dsa->g),params->a);
232 * Generate GOST R 34.10-94 keypair
236 int gost_sign_keygen(DSA *dsa)
238 dsa->priv_key = BN_new();
239 BN_rand_range(dsa->priv_key,dsa->q);
240 return gost94_compute_public( dsa);
242 /* Unpack signature according to cryptocom rules */
244 DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
249 GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY);
252 s->r = getbnfrombuf(sig, siglen/2);
253 s->s = getbnfrombuf(sig + siglen/2, siglen/2);
256 /* Unpack signature according to cryptopro rules */
257 DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
263 GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY);
266 s->s = getbnfrombuf(sig , siglen/2);
267 s->r = getbnfrombuf(sig + siglen/2, siglen/2);
270 /* Convert little-endian byte array into bignum */
271 BIGNUM *hashsum2bn(const unsigned char *dgst)
272 { unsigned char buf[32];
277 return getbnfrombuf(buf,32);
280 /* Convert byte buffer to bignum, skipping leading zeros*/
281 BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len) {
282 while (*buf==0&&len>0) {
286 return BN_bin2bn(buf,len,NULL);
293 /* Pack bignum into byte buffer of given size, filling all leading bytes
295 int store_bignum(BIGNUM *bn, unsigned char *buf,int len) {
296 int bytes = BN_num_bytes(bn);
297 if (bytes>len) return 0;
299 BN_bn2bin(bn,buf+len-bytes);