Index: openssl/engines/ccgost/gost_sign.c |
=================================================================== |
--- openssl/engines/ccgost/gost_sign.c (revision 0) |
+++ openssl/engines/ccgost/gost_sign.c (revision 0) |
@@ -0,0 +1,321 @@ |
+/********************************************************************** |
+ * gost_sign.c * |
+ * Copyright (c) 2005-2006 Cryptocom LTD * |
+ * This file is distributed under the same license as OpenSSL * |
+ * * |
+ * Implementation of GOST R 34.10-94 signature algorithm * |
+ * for OpenSSL * |
+ * Requires OpenSSL 0.9.9 for compilation * |
+ **********************************************************************/ |
+#include <string.h> |
+#include <openssl/rand.h> |
+#include <openssl/bn.h> |
+#include <openssl/dsa.h> |
+#include <openssl/evp.h> |
+ |
+#include "gost_params.h" |
+#include "gost_lcl.h" |
+#include "e_gost_err.h" |
+ |
+#ifdef DEBUG_SIGN |
+void dump_signature(const char *message,const unsigned char *buffer,size_t len) |
+ { |
+ size_t i; |
+ fprintf(stderr,"signature %s Length=%d",message,len); |
+ for (i=0; i<len; i++) |
+ { |
+ if (i% 16 ==0) fputc('\n',stderr); |
+ fprintf (stderr," %02x",buffer[i]); |
+ } |
+ fprintf(stderr,"\nEnd of signature\n"); |
+ } |
+ |
+void dump_dsa_sig(const char *message, DSA_SIG *sig) |
+ { |
+ fprintf(stderr,"%s\nR=",message); |
+ BN_print_fp(stderr,sig->r); |
+ fprintf(stderr,"\nS="); |
+ BN_print_fp(stderr,sig->s); |
+ fprintf(stderr,"\n"); |
+ } |
+ |
+#else |
+ |
+#define dump_signature(a,b,c) |
+#define dump_dsa_sig(a,b) |
+#endif |
+ |
+/* |
+ * Computes signature and returns it as DSA_SIG structure |
+ */ |
+DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa) |
+ { |
+ BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL; |
+ DSA_SIG *newsig = DSA_SIG_new(); |
+ BIGNUM *md = hashsum2bn(dgst); |
+ /* check if H(M) mod q is zero */ |
+ BN_CTX *ctx=BN_CTX_new(); |
+ BN_CTX_start(ctx); |
+ if (!newsig) |
+ { |
+ GOSTerr(GOST_F_GOST_DO_SIGN,GOST_R_NO_MEMORY); |
+ goto err; |
+ } |
+ tmp=BN_CTX_get(ctx); |
+ k = BN_CTX_get(ctx); |
+ tmp2 = BN_CTX_get(ctx); |
+ BN_mod(tmp,md,dsa->q,ctx); |
+ if (BN_is_zero(tmp)) |
+ { |
+ BN_one(md); |
+ } |
+ do |
+ { |
+ do |
+ { |
+ /*Generate random number k less than q*/ |
+ BN_rand_range(k,dsa->q); |
+ /* generate r = (a^x mod p) mod q */ |
+ BN_mod_exp(tmp,dsa->g, k, dsa->p,ctx); |
+ if (!(newsig->r)) newsig->r=BN_new(); |
+ BN_mod(newsig->r,tmp,dsa->q,ctx); |
+ } |
+ while (BN_is_zero(newsig->r)); |
+ /* generate s = (xr + k(Hm)) mod q */ |
+ BN_mod_mul(tmp,dsa->priv_key,newsig->r,dsa->q,ctx); |
+ BN_mod_mul(tmp2,k,md,dsa->q,ctx); |
+ if (!newsig->s) newsig->s=BN_new(); |
+ BN_mod_add(newsig->s,tmp,tmp2,dsa->q,ctx); |
+ } |
+ while (BN_is_zero(newsig->s)); |
+ err: |
+ BN_free(md); |
+ BN_CTX_end(ctx); |
+ BN_CTX_free(ctx); |
+ return newsig; |
+ } |
+ |
+ |
+/* |
+ * Packs signature according to Cryptocom rules |
+ * and frees up DSA_SIG structure |
+ */ |
+/* |
+int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen) |
+ { |
+ *siglen = 2*order; |
+ memset(sig,0,*siglen); |
+ store_bignum(s->r, sig,order); |
+ store_bignum(s->s, sig + order,order); |
+ dump_signature("serialized",sig,*siglen); |
+ DSA_SIG_free(s); |
+ return 1; |
+ } |
+*/ |
+/* |
+ * Packs signature according to Cryptopro rules |
+ * and frees up DSA_SIG structure |
+ */ |
+int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen) |
+ { |
+ *siglen = 2*order; |
+ memset(sig,0,*siglen); |
+ store_bignum(s->s, sig, order); |
+ store_bignum(s->r, sig+order,order); |
+ dump_signature("serialized",sig,*siglen); |
+ DSA_SIG_free(s); |
+ return 1; |
+ } |
+ |
+/* |
+ * Verifies signature passed as DSA_SIG structure |
+ * |
+ */ |
+ |
+int gost_do_verify(const unsigned char *dgst, int dgst_len, |
+ DSA_SIG *sig, DSA *dsa) |
+ { |
+ BIGNUM *md, *tmp=NULL; |
+ BIGNUM *q2=NULL; |
+ BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL; |
+ BIGNUM *tmp2=NULL,*tmp3=NULL; |
+ int ok; |
+ BN_CTX *ctx = BN_CTX_new(); |
+ |
+ BN_CTX_start(ctx); |
+ if (BN_cmp(sig->s,dsa->q)>=1|| |
+ BN_cmp(sig->r,dsa->q)>=1) |
+ { |
+ GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); |
+ return 0; |
+ } |
+ md=hashsum2bn(dgst); |
+ |
+ tmp=BN_CTX_get(ctx); |
+ v=BN_CTX_get(ctx); |
+ q2=BN_CTX_get(ctx); |
+ z1=BN_CTX_get(ctx); |
+ z2=BN_CTX_get(ctx); |
+ tmp2=BN_CTX_get(ctx); |
+ tmp3=BN_CTX_get(ctx); |
+ u = BN_CTX_get(ctx); |
+ |
+ BN_mod(tmp,md,dsa->q,ctx); |
+ if (BN_is_zero(tmp)) |
+ { |
+ BN_one(md); |
+ } |
+ BN_copy(q2,dsa->q); |
+ BN_sub_word(q2,2); |
+ BN_mod_exp(v,md,q2,dsa->q,ctx); |
+ BN_mod_mul(z1,sig->s,v,dsa->q,ctx); |
+ BN_sub(tmp,dsa->q,sig->r); |
+ BN_mod_mul(z2,tmp,v,dsa->p,ctx); |
+ BN_mod_exp(tmp,dsa->g,z1,dsa->p,ctx); |
+ BN_mod_exp(tmp2,dsa->pub_key,z2,dsa->p,ctx); |
+ BN_mod_mul(tmp3,tmp,tmp2,dsa->p,ctx); |
+ BN_mod(u,tmp3,dsa->q,ctx); |
+ ok= BN_cmp(u,sig->r); |
+ |
+ BN_free(md); |
+ BN_CTX_end(ctx); |
+ BN_CTX_free(ctx); |
+ if (ok!=0) |
+ { |
+ GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH); |
+ } |
+ return (ok==0); |
+ } |
+ |
+/* |
+ * Computes public keys for GOST R 34.10-94 algorithm |
+ * |
+ */ |
+int gost94_compute_public(DSA *dsa) |
+ { |
+ /* Now fill algorithm parameters with correct values */ |
+ BN_CTX *ctx = BN_CTX_new(); |
+ if (!dsa->g) |
+ { |
+ GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED); |
+ return 0; |
+ } |
+ /* Compute public key y = a^x mod p */ |
+ dsa->pub_key=BN_new(); |
+ BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx); |
+ BN_CTX_free(ctx); |
+ return 1; |
+ } |
+ |
+/* |
+ * Fill GOST 94 params, searching them in R3410_paramset array |
+ * by nid of paramset |
+ * |
+ */ |
+int fill_GOST94_params(DSA *dsa,int nid) |
+ { |
+ R3410_params *params=R3410_paramset; |
+ while (params->nid!=NID_undef && params->nid !=nid) params++; |
+ if (params->nid == NID_undef) |
+ { |
+ GOSTerr(GOST_F_FILL_GOST94_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET); |
+ return 0; |
+ } |
+#define dump_signature(a,b,c) |
+ if (dsa->p) { BN_free(dsa->p); } |
+ dsa->p=NULL; |
+ BN_dec2bn(&(dsa->p),params->p); |
+ if (dsa->q) { BN_free(dsa->q); } |
+ dsa->q=NULL; |
+ BN_dec2bn(&(dsa->q),params->q); |
+ if (dsa->g) { BN_free(dsa->g); } |
+ dsa->g=NULL; |
+ BN_dec2bn(&(dsa->g),params->a); |
+ return 1; |
+ } |
+ |
+/* |
+ * Generate GOST R 34.10-94 keypair |
+ * |
+ * |
+ */ |
+int gost_sign_keygen(DSA *dsa) |
+ { |
+ dsa->priv_key = BN_new(); |
+ BN_rand_range(dsa->priv_key,dsa->q); |
+ return gost94_compute_public( dsa); |
+ } |
+ |
+/* Unpack signature according to cryptocom rules */ |
+/* |
+DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) |
+ { |
+ DSA_SIG *s; |
+ s = DSA_SIG_new(); |
+ if (s == NULL) |
+ { |
+ GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY); |
+ return(NULL); |
+ } |
+ s->r = getbnfrombuf(sig, siglen/2); |
+ s->s = getbnfrombuf(sig + siglen/2, siglen/2); |
+ return s; |
+ } |
+*/ |
+/* Unpack signature according to cryptopro rules */ |
+DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) |
+ { |
+ DSA_SIG *s; |
+ |
+ s = DSA_SIG_new(); |
+ if (s == NULL) |
+ { |
+ GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY); |
+ return NULL; |
+ } |
+ s->s = getbnfrombuf(sig , siglen/2); |
+ s->r = getbnfrombuf(sig + siglen/2, siglen/2); |
+ return s; |
+ } |
+ |
+/* Convert little-endian byte array into bignum */ |
+BIGNUM *hashsum2bn(const unsigned char *dgst) |
+ { |
+ unsigned char buf[32]; |
+ int i; |
+ for (i=0;i<32;i++) |
+ { |
+ buf[31-i]=dgst[i]; |
+ } |
+ return getbnfrombuf(buf,32); |
+ } |
+ |
+/* Convert byte buffer to bignum, skipping leading zeros*/ |
+BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len) |
+ { |
+ while (*buf==0&&len>0) |
+ { |
+ buf++; len--; |
+ } |
+ if (len) |
+ { |
+ return BN_bin2bn(buf,len,NULL); |
+ } |
+ else |
+ { |
+ BIGNUM *b=BN_new(); |
+ BN_zero(b); |
+ return b; |
+ } |
+ } |
+ |
+/* Pack bignum into byte buffer of given size, filling all leading bytes |
+ * by zeros */ |
+int store_bignum(BIGNUM *bn, unsigned char *buf,int len) |
+ { |
+ int bytes = BN_num_bytes(bn); |
+ if (bytes>len) return 0; |
+ memset(buf,0,len); |
+ BN_bn2bin(bn,buf+len-bytes); |
+ return 1; |
+ } |