From a04549cc755408ff2dcab209fd87d3e46f7d662a Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sun, 17 Sep 2006 13:00:18 +0000 Subject: GOST public key algorithm ENGINE donated to the OpenSSL by Cryptocom. Very early version, doesn't do much yet, not even added to the build system. --- engines/ccgost/Makefile | 122 ++++++++ engines/ccgost/ameth.c | 671 ++++++++++++++++++++++++++++++++++++++++ engines/ccgost/crypt.h | 62 ++++ engines/ccgost/e_gost_err.c | 210 +++++++++++++ engines/ccgost/e_gost_err.h | 150 +++++++++ engines/ccgost/e_gost_err.proto | 61 ++++ engines/ccgost/engine.c | 230 ++++++++++++++ engines/ccgost/gost.ec | 5 + engines/ccgost/gost2001.c | 324 +++++++++++++++++++ engines/ccgost/gost2001_keyx.c | 385 +++++++++++++++++++++++ engines/ccgost/gost89.c | 383 +++++++++++++++++++++++ engines/ccgost/gost89.h | 96 ++++++ engines/ccgost/gost94_keyx.c | 420 +++++++++++++++++++++++++ engines/ccgost/gost_asn1.c | 55 ++++ engines/ccgost/gost_asn1.h | 57 ++++ engines/ccgost/gost_crypt.c | 579 ++++++++++++++++++++++++++++++++++ engines/ccgost/gost_sign.c | 302 ++++++++++++++++++ engines/ccgost/gosthash.c | 256 +++++++++++++++ engines/ccgost/gosthash.h | 39 +++ engines/ccgost/gostkeyx.h | 42 +++ engines/ccgost/gostsum.1 | 78 +++++ engines/ccgost/gostsum.c | 184 +++++++++++ engines/ccgost/keywrap.c | 97 ++++++ engines/ccgost/keywrap.h | 56 ++++ engines/ccgost/md.h | 41 +++ engines/ccgost/md_gost.c | 69 +++++ engines/ccgost/meth.h | 22 ++ engines/ccgost/params.c | 198 ++++++++++++ engines/ccgost/paramset.h | 34 ++ engines/ccgost/pmeth.c | 514 ++++++++++++++++++++++++++++++ engines/ccgost/pmeth.h | 26 ++ engines/ccgost/sign.h | 30 ++ engines/ccgost/tools.h | 38 +++ 33 files changed, 5836 insertions(+) create mode 100644 engines/ccgost/Makefile create mode 100644 engines/ccgost/ameth.c create mode 100644 engines/ccgost/crypt.h create mode 100644 engines/ccgost/e_gost_err.c create mode 100644 engines/ccgost/e_gost_err.h create mode 100644 engines/ccgost/e_gost_err.proto create mode 100644 engines/ccgost/engine.c create mode 100644 engines/ccgost/gost.ec create mode 100644 engines/ccgost/gost2001.c create mode 100644 engines/ccgost/gost2001_keyx.c create mode 100644 engines/ccgost/gost89.c create mode 100644 engines/ccgost/gost89.h create mode 100644 engines/ccgost/gost94_keyx.c create mode 100644 engines/ccgost/gost_asn1.c create mode 100644 engines/ccgost/gost_asn1.h create mode 100644 engines/ccgost/gost_crypt.c create mode 100644 engines/ccgost/gost_sign.c create mode 100644 engines/ccgost/gosthash.c create mode 100644 engines/ccgost/gosthash.h create mode 100644 engines/ccgost/gostkeyx.h create mode 100644 engines/ccgost/gostsum.1 create mode 100644 engines/ccgost/gostsum.c create mode 100644 engines/ccgost/keywrap.c create mode 100644 engines/ccgost/keywrap.h create mode 100644 engines/ccgost/md.h create mode 100644 engines/ccgost/md_gost.c create mode 100644 engines/ccgost/meth.h create mode 100644 engines/ccgost/params.c create mode 100644 engines/ccgost/paramset.h create mode 100644 engines/ccgost/pmeth.c create mode 100644 engines/ccgost/pmeth.h create mode 100644 engines/ccgost/sign.h create mode 100644 engines/ccgost/tools.h (limited to 'engines') diff --git a/engines/ccgost/Makefile b/engines/ccgost/Makefile new file mode 100644 index 0000000000..b4caacdb7e --- /dev/null +++ b/engines/ccgost/Makefile @@ -0,0 +1,122 @@ +# OPENSSL_DIR is a root directory of openssl sources +THISDIR?=$(shell perl -MCwd -e 'print getcwd') +OPENSSL_DIR?=$(THISDIR)/../openssl +ENGINE_ID?=gost +TESTSUITE_DIR?=$(THISDIR)/test-suite +FOR?=$(HOST) +CC=gcc +CFLAGS=-fPIC -g -Wall -I$(OPENSSL_DIR)/include +LDFLAGS=-g -L $(OPENSSL_DIR) -static-libgcc +ifeq "$(FOR)" "s64" +CFLAGS+=-m64 +LDFLAGS+=-m64 +endif +OS:=$(shell uname -s) +ifeq "$(OS)" "FreeBSD" +LIBDIR:=$(shell LD_LIBRARY_PATH=$(OPENSSL_DIR) $(OPENSSL_DIR)/apps/openssl version -d|sed -e 's/^[^"]*"//' -e 's/".*$$//')/lib +LDFLAGS+=-rpath $(LIBDIR) +endif + + +ifeq "$(FOR)" "w32" +ENGINE_LIB?=$(ENGINE_ID)$(DLLSUFFIX) +DLLSUFFIX=.dll +EXESUFFIX=.exe +CFLAGS+=-mno-cygwin +LDFLAGS+=-mno-cygwin +ifeq "$(OS)" "Linux" +CC=i586-mingw32msvc-gcc +endif +LIBS=-lcrypto.dll +else +ENGINE_LIB?=lib$(ENGINE_ID)$(DLLSUFFIX) +LIBS=-lcrypto +DLLSUFFIX=.so +endif +export DLLSUFFIX +export EXESUFFIX +ifneq "$(FOR)" "" +export FOR +endif +CFLAGS+=$(DEBUG_FLAGS) +export ENGINE_LIB +ENG_SOURCES=md_gost.c gost_crypt.c gost_asn1.c ameth.c pmeth.c\ + gost_crypt.c gost_sign.c gost2001.c md_gost.c gost_crypt.c\ + engine.c gost94_keyx.c keywrap.c gost2001_keyx.c +all: $(ENGINE_LIB) openssl.cnf +buildtests: +$(ENGINE_LIB): e_gost_err.o engine.o ameth.o pmeth.o params.o md_gost.o gosthash.o gost89.o gost_sign.o gost_crypt.o keywrap.o gost2001.o gost94_keyx.o gost2001_keyx.o gost_asn1.o + $(CC) $(LDFLAGS) -shared -o $@ $+ $(LIBS) $(LDFLAGS) +openssl.cnf: openssl.cnf.1 openssl.cnf.2 + cat $+ > $@ +openssl.cnf.1: + echo "openssl_conf = openssl_def" > $@ +openssl.cnf.2: + echo "[openssl_def]" > $@ + echo "engines = engine_section" >> $@ + echo "[engine_section]" >> $@ + echo "$(ENGINE_ID) = $(ENGINE_ID)_section" >> $@ + echo "[$(ENGINE_ID)_section]" >> $@ + echo "dynamic_path = $(THISDIR)/$(ENGINE_LIB)" >> $@ + echo "engine_id = $(ENGINE_ID)" >> $@ + echo "default_algorithms = ALL" >> $@ +gosthash1.o: gosthash.c + $(CC) -c $(CFLAGS) -o $@ -DOPENSSL_BUILD $+ +gostsum: gostsum.o gosthash.o gost89.o +inttests: gosttest$(EXESUFFIX) etalon wraptest$(EXESUFFIX) etalon.wrap ectest$(EXESUFFIX) etalon.ec + ./gosttest${EXESUFFIX} > gost_test + diff -uw gost_test etalon + ./wraptest$(EXESUFFIX) > wrap_test + diff -uw wrap_test etalon.wrap + ./ectest$(EXESUFFIX) > ec_test 2>&1 + diff -uw ec_test etalon.ec +ectest$(EXESUFFIX): ectest.o gost2001_dbg.o gost_sign_dbg.o params.o e_gost_err.o + $(CC) -o $@ $(LDFLAGS) $+ -lcrypto +%_dbg.o: %.c + $(CC) -c $(CFLAGS) -DDEBUG_SIGN -DDEBUG_KEYS -o $@ $+ +gosttest$(EXESUFFIX): gosttest.o gosthash.o gost89.o + $(CC) $(LDFLAGS) -o $@ $+ +wraptest$(EXESUFFIX): wraptest.c keywrap.c gost89.c + $(CC) -DDEBUG_DH $(LDFLAGS) -o $@ $+ +sign_ex: LOADLIBES=-lcrypto +sign_ex: sign_ex.o +clean: + rm -f core gosttest gostsum *.o gost_test openssl.cnf* $(ENGINE_LIB) + if [ -f t/Makefile ]; then $(MAKE) -C t clean; fi + if [ -f $(TESTSUITE_DIR)/Makefile ]; then $(MAKE) -C $(TESTSUITE_DIR) clean; fi +e_gost_err.c e_gost_err.h: $(ENG_SOURCES) gost.ec e_gost_err.proto + perl $(OPENSSL_DIR)/util/mkerr.pl -conf gost.ec -nostatic -debug -write $(ENG_SOURCES) + +tests: openssl.cnf.2 + OPENSSL_DIR=$(OPENSSL_DIR) $(MAKE) -C $(TESTSUITE_DIR) CONFADD=$(THISDIR)/openssl.cnf.2 + +# depedencies +# +# +gost_sign.o: gost_sign.c sign.h paramset.h tools.h e_gost_err.h + +pmeth.o: pmeth.c meth.h pmeth.h sign.h paramset.h e_gost_err.h + +ameth.o: ameth.c tools.h meth.h pmeth.h gost_asn1.h crypt.h e_gost_err.h paramset.h + +keywrap.o: keywrap.c gost89.h keywrap.h + +gost2001.o: gost2001.c tools.h sign.h paramset.h e_gost_err.h + +engine.o: engine.c md.h crypt.h meth.h e_gost_err.h + +gost89.o: gost89.c gost89.h + +gost_asn1.o: gost_asn1.c gost_asn1.h + +gost_crypt.o: gost_crypt.c crypt.h gost89.h e_gost_err.h gost_asn1.h + +gosthash.o: gosthash.c gost89.h gosthash.h + +md_gost.o: md_gost.c md.h gosthash.h e_gost_err.h + +params.o: params.c paramset.h + +gost94_keyx.o: gost94_keyx.c gost_asn1.h gost89.h gosthash.h crypt.h pmeth.h keywrap.h e_gost_err.h gostkeyx.h + +gost2001_keyx.o: gost2001_keyx.c gost89.h gost_asn1.h e_gost_err.h keywrap.h crypt.h sign.h gostkeyx.h pmeth.h gosthash.h tools.h diff --git a/engines/ccgost/ameth.c b/engines/ccgost/ameth.c new file mode 100644 index 0000000000..c64cd2d298 --- /dev/null +++ b/engines/ccgost/ameth.c @@ -0,0 +1,671 @@ +/********************************************************************** + * ameth.c * + * Copyright (c) 2005-2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Implementation of RFC 4490/4491 ASN1 method * + * for OpenSSL * + * Requires OpenSSL 0.9.9 for compilation * + **********************************************************************/ +#include +#include +#include +#include "meth.h" +#include "pmeth.h" +#include "paramset.h" +#include "gost_asn1.h" +#include "crypt.h" +#include "sign.h" +#include "tools.h" +#include "e_gost_err.h" + +int gost94_nid_by_params(DSA *p) +{ + R3410_params *gost_params; + BIGNUM *q=BN_new(); + for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++) { + BN_dec2bn(&q,gost_params->q); + if (!BN_cmp(q,p->q)) + { + BN_free(q); + return gost_params->nid; + } + } + BN_free(q); + return NID_undef; +} + +static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key) +{ + ASN1_STRING *params = ASN1_STRING_new(); + GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new(); + int pkey_param_nid = NID_undef; + int cipher_param_nid = NID_undef; + if (!params || !gkp) { + GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, + ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(params); + params = NULL; + goto err; + } + switch (EVP_PKEY_base_id(key)) { + case NID_id_GostR3410_2001_cc: + pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc; + cipher_param_nid = NID_id_Gost28147_89_cc; + break; + case NID_id_GostR3410_94_cc: + pkey_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet; + cipher_param_nid = NID_id_Gost28147_89_cc; + break; + case NID_id_GostR3410_2001: + pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key))); + cipher_param_nid = get_encryption_params(NULL)->nid; + break; + case NID_id_GostR3410_94: + pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key)); + if (pkey_param_nid == NID_undef) { + GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, + GOST_R_INVALID_GOST94_PARMSET); + ASN1_STRING_free(params); + params=NULL; + goto err; + } + cipher_param_nid = get_encryption_params(NULL)->nid; + break; + } + gkp->key_params = OBJ_nid2obj(pkey_param_nid); + gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet); + /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/ + params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data); + if (params->length <=0 ) + { + GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, + ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(params); + params = NULL; + goto err; + } + params ->type = V_ASN1_SEQUENCE; +err: + GOST_KEY_PARAMS_free(gkp); + return params; +} +/* Parses GOST algorithm parameters from X509_ALGOR and + * modifies pkey setting NID and parameters + */ +static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) +{ + ASN1_OBJECT *palg_obj =NULL; + int ptype = V_ASN1_UNDEF; + int pkey_nid = NID_undef,param_nid = NID_undef; + ASN1_STRING *pval = NULL; + const unsigned char *p; + GOST_KEY_PARAMS *gkp = NULL; + + X509_ALGOR_get0(&palg_obj, &ptype, (void **) (&pval), palg); + if (ptype != V_ASN1_SEQUENCE) { + GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, + GOST_R_BAD_KEY_PARAMETERS_FORMAT); + return 0; + } + p=pval->data; + pkey_nid = OBJ_obj2nid(palg_obj); + + gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length); + if (!gkp) { + GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, + GOST_R_BAD_PKEY_PARAMETERS_FORMAT); + } + param_nid = OBJ_obj2nid(gkp->key_params); + GOST_KEY_PARAMS_free(gkp); + EVP_PKEY_set_type(pkey,pkey_nid); + switch (pkey_nid) { + case NID_id_GostR3410_94: + case NID_id_GostR3410_94_cc: + { DSA *dsa= EVP_PKEY_get0(pkey); + if (!dsa) { + dsa = DSA_new(); + if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0; + } + if (!fill_GOST94_params(dsa,param_nid)) return 0; + break; + } + case NID_id_GostR3410_2001: + case NID_id_GostR3410_2001_cc: + { EC_KEY *ec = EVP_PKEY_get0(pkey); + if (!ec) { + ec = EC_KEY_new(); + if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0; + } + if (!fill_GOST2001_params(ec,param_nid)) return 0; + + } + + } + + return 1; +} + +static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) +{ + switch (EVP_PKEY_base_id(pkey)) { + case NID_id_GostR3410_94: + case NID_id_GostR3410_94_cc: + { DSA *dsa = EVP_PKEY_get0(pkey); + if (!dsa) { + dsa = DSA_new(); + EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa); + } + dsa->priv_key = BN_dup(priv); + if (!EVP_PKEY_missing_parameters(pkey)) + gost94_compute_public(dsa); + break; + } + case NID_id_GostR3410_2001: + case NID_id_GostR3410_2001_cc: + { EC_KEY *ec = EVP_PKEY_get0(pkey); + if (!ec) { + ec = EC_KEY_new(); + EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec); + } + if (!EC_KEY_set_private_key(ec,priv)) return 0; + if (!EVP_PKEY_missing_parameters(pkey)) + gost2001_compute_public(ec); + break; + } + + } + return 1; +} +BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) +{ + switch (EVP_PKEY_base_id(pkey)) { + case NID_id_GostR3410_94: + case NID_id_GostR3410_94_cc: + { DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey); + if (!dsa) { + return NULL; + } + if (!dsa->priv_key) return NULL; + return BN_dup(dsa->priv_key); + break; + } + case NID_id_GostR3410_2001: + case NID_id_GostR3410_2001_cc: + { EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey); + const BIGNUM* priv; + if (!ec) { + return NULL; + } + if (!(priv=EC_KEY_get0_private_key(ec))) return NULL; + return BN_dup(priv); + break; + } + + } + return NULL; +} +static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, + long arg1, void *arg2) +{ + switch (op) + { + case ASN1_PKEY_CTRL_PKCS7_SIGN: + if (arg1 == 0) { + X509_ALGOR *alg1 = NULL, *alg2 = NULL; + int nid = EVP_PKEY_base_id(pkey); + PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2, + NULL, &alg1, &alg2); + X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94), + V_ASN1_NULL, 0); + if (nid == NID_undef) { + return (-1); + } + X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0); + } + return 1; + case ASN1_PKEY_CTRL_PKCS7_ENCRYPT: + if (arg1 == 0) + { + X509_ALGOR *alg; + ASN1_STRING * params = encode_gost_algor_params(pkey); + if (!params) { + return -1; + } + PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg); + X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type), + V_ASN1_SEQUENCE, params); + } + return 1; + case ASN1_PKEY_CTRL_DEFAULT_MD_NID: + *(int *)arg2 = NID_id_GostR3411_94; + return 2; + } + + return -2; +} +/*----------------------- free functions * ------------------------------*/ +static void pkey_free_gost94(EVP_PKEY *key) { + if (key->pkey.dsa) { + DSA_free(key->pkey.dsa); + } +} +static void pkey_free_gost01(EVP_PKEY *key) { + if (key->pkey.ec) { + EC_KEY_free(key->pkey.ec); + } +} +/* ------------------ private key functions -----------------------------*/ +static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) +{ + const unsigned char *pkey_buf = NULL,*p=NULL; + int priv_len = 0; + BIGNUM *pk_num=NULL; + int ret =0; + X509_ALGOR *palg =NULL; + ASN1_OBJECT *palg_obj = NULL; + ASN1_INTEGER *priv_key=NULL; + + if (!PKCS8_pkey_get0(&palg_obj,&pkey_buf,&priv_len,&palg,p8inf)) + return 0; + p = pkey_buf; + if (!decode_gost_algor_params(pk,palg)) { + return 0; + } + priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len); + if (!priv_key) { + } + + if (!(pk_num = ASN1_INTEGER_to_BN(priv_key, NULL))) { + GOSTerr(GOST_F_PRIV_DECODE_GOST_94, + EVP_R_DECODE_ERROR); + } + + ret= gost_set_priv_key(pk,pk_num); + BN_free(pk_num); + return ret; +} +/* ----------------------------------------------------------------------*/ +static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) +{ + ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); + ASN1_STRING *params = encode_gost_algor_params(pk); + unsigned char *priv_buf = NULL; + int priv_len; + BIGNUM *key; + + ASN1_INTEGER *asn1key=NULL; + if (!params) { + return 0; + } + key = gost_get_priv_key(pk); + asn1key = BN_to_ASN1_INTEGER(key,NULL); + BN_free(key); + priv_len = i2d_ASN1_INTEGER(asn1key,&priv_buf); + ASN1_INTEGER_free(asn1key); + return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params, + priv_buf,priv_len); +} + +static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) +{ + BIGNUM *key; + if (!BIO_indent(out,indent,128)) return 0; + key = gost_get_priv_key(pkey); + if (!key) return 0; + BN_print(out,key); + BN_free(key); + return 1; +} +/* ---------------------------------------------------------------------*/ +static int param_missing_gost94(const EVP_PKEY *pk) +{ + const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk); + if (!dsa) return 1; + if (!dsa->q) return 1; + return 0; +} +static int param_missing_gost01(const EVP_PKEY *pk) +{ + const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk); + if (!ec) return 1; + if (!EC_KEY_get0_group(ec)) return 1; + return 0; +} + +static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from) +{ + const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from); + DSA *dto = EVP_PKEY_get0(to); + if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) + { + GOSTerr(GOST_F_PARAM_COPY_GOST94, + GOST_R_INCOMPATIBLE_ALGORITHMS); + return 0; + } + if (!dfrom) + { + GOSTerr(GOST_F_PARAM_COPY_GOST94, + GOST_R_KEY_PARAMETERS_MISSING); + return 0; + } + if (!dto) + { + dto = DSA_new(); + EVP_PKEY_assign(to,EVP_PKEY_base_id(from),dto); + } +#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x); + COPYBIGNUM(dto,dfrom,p) + COPYBIGNUM(dto,dfrom,q) + COPYBIGNUM(dto,dfrom,g) + + if (dto->priv_key) + gost94_compute_public(dto); + return 1; +} +static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) { + EC_KEY *eto = EVP_PKEY_get0(to); + const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from); + if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { + GOSTerr(GOST_F_PARAM_COPY_GOST01, + GOST_R_INCOMPATIBLE_ALGORITHMS); + return 0; + } + if (!efrom) { + GOSTerr(GOST_F_PARAM_COPY_GOST94, + GOST_R_KEY_PARAMETERS_MISSING); + return 0; + } + if (!eto) { + eto = EC_KEY_new(); + EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto); + } + EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom))); + if (EC_KEY_get0_private_key(eto)) { + gost2001_compute_public(eto); + } + return 1; + + + +} +static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) { + const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a); + const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b); + if (!BN_cmp(da->q,db->q)) return 1; + return 0; +} +static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) { + if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))== + EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b)))) { + return 1; + } + return 0; + +} +/* ---------- Public key functions * --------------------------------------*/ +static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub) +{ + X509_ALGOR *palg = NULL; + const unsigned char *pubkey_buf = NULL; + unsigned char *databuf; + ASN1_OBJECT *palgobj = NULL; + int pub_len,i,j; + DSA *dsa; + ASN1_OCTET_STRING *octet= NULL; + + if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len, + &palg, pub)) return 0; + EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL); + if (!decode_gost_algor_params(pk,palg)) return 0; + octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len); + if (!octet) + { + GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE); + return 0; + } + databuf = OPENSSL_malloc(octet->length); + for (i=0,j=octet->length-1;ilength;i++,j--) + { + databuf[j]=octet->data[i]; + } + dsa = EVP_PKEY_get0(pk); + dsa->pub_key=BN_bin2bn(databuf,octet->length,NULL); + ASN1_OCTET_STRING_free(octet); + OPENSSL_free(databuf); + return 1; + +} +static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk) +{ + ASN1_OBJECT *algobj = NULL; + ASN1_OCTET_STRING *octet = NULL; + void *pval = NULL; + unsigned char *buf=NULL,*databuf,*sptr; + int i,j,data_len,ret=0; + + int ptype; + DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk); + algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); + if (pk->save_parameters) { + ASN1_STRING *params = encode_gost_algor_params(pk); + pval = params; + ptype = V_ASN1_SEQUENCE; + } + data_len = BN_num_bytes(dsa->pub_key); + databuf = OPENSSL_malloc(data_len); + BN_bn2bin(dsa->pub_key,databuf); + octet = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(octet,NULL,data_len); + sptr = ASN1_STRING_data(octet); + for (i=0,j=data_len-1; i< data_len;i++,j--) + { + sptr[i]=databuf[j]; + } + OPENSSL_free(databuf); + ret = i2d_ASN1_OCTET_STRING(octet,&buf); + ASN1_BIT_STRING_free(octet); + if (ret <0) return 0; + return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret); +} +static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub) +{ + X509_ALGOR *palg = NULL; + const unsigned char *pubkey_buf = NULL; + unsigned char *databuf; + ASN1_OBJECT *palgobj = NULL; + int pub_len,i,j; + EC_POINT *pub_key; + BIGNUM *X,*Y; + ASN1_OCTET_STRING *octet= NULL; + const EC_GROUP *group; + + if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len, + &palg, pub)) return 0; + EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL); + if (!decode_gost_algor_params(pk,palg)) return 0; + group = EC_KEY_get0_group(EVP_PKEY_get0(pk)); + octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len); + if (!octet) + { + GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE); + return 0; + } + databuf = OPENSSL_malloc(octet->length); + for (i=0,j=octet->length-1;ilength;i++,j--) + { + databuf[j]=octet->data[i]; + } + if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) { + X= getbnfrombuf(databuf,octet->length/2); + Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2); + } else { + Y= getbnfrombuf(databuf,octet->length/2); + X= getbnfrombuf(databuf+(octet->length/2),octet->length/2); + } + OPENSSL_free(databuf); + pub_key = EC_POINT_new(group); + if (!EC_POINT_set_affine_coordinates_GFp(group + ,pub_key,X,Y,NULL)) + { + GOSTerr(GOST_F_PUB_DECODE_GOST01, + ERR_R_EC_LIB); + return 0; + } + BN_free(X); + BN_free(Y); + if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk),pub_key)) + { + GOSTerr(GOST_F_PUB_DECODE_GOST01, + ERR_R_EC_LIB); + return 0; + } + /*EC_POINT_free(pub_key);*/ + return 1; + +} +static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk) +{ + ASN1_OBJECT *algobj = NULL; + ASN1_OCTET_STRING *octet = NULL; + void *pval = NULL; + unsigned char *buf=NULL,*databuf,*sptr; + int i,j,data_len,ret=0; + const EC_POINT *pub_key; + BIGNUM *X,*Y,*order; + const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk); + int ptype; + + algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); + if (pk->save_parameters) { + ASN1_STRING *params = encode_gost_algor_params(pk); + pval = params; + ptype = V_ASN1_SEQUENCE; + } + order = BN_new(); + EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL); + pub_key=EC_KEY_get0_public_key(ec); + if (!pub_key) { + GOSTerr(GOST_F_PUB_ENCODE_GOST01, + GOST_R_PUBLIC_KEY_UNDEFINED); + return 0; + } + X=BN_new(); + Y=BN_new(); + EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec), + pub_key,X,Y,NULL); + data_len = 2*BN_num_bytes(order); + BN_free(order); + databuf = OPENSSL_malloc(data_len); + memset(databuf,0,data_len); + if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) { + store_bignum(X,databuf,data_len/2); + store_bignum(Y,databuf+data_len/2,data_len/2); + } else { + store_bignum(X,databuf+data_len/2,data_len/2); + store_bignum(Y,databuf,data_len/2); + } + BN_free(X); + BN_free(Y); + octet = ASN1_OCTET_STRING_new(); + ASN1_STRING_set(octet,NULL,data_len); + sptr=ASN1_STRING_data(octet); + for (i=0,j=data_len-1;ipub_key && db->pub_key + && !BN_cmp(da->pub_key,db->pub_key)) { + return 1; + } + return 0; +} +static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b) +{ + const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a); + const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b); + const EC_POINT *ka,*kb; + int ret=0; + if (!ea || !eb) return 0; + ka = EC_KEY_get0_public_key(ea); + kb = EC_KEY_get0_public_key(eb); + if (!ka || !kb) return 0; + ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ; + return ret; +} +static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) +{ + const BIGNUM *key; + if (!BIO_indent(out,indent,128)) return 0; + key = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key; + if (!key) return 0; + BN_print(out,key); + return 1; +} +static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx) +{ + return 0; +} +static int pkey_size_gost(const EVP_PKEY *pk) +{ + return 64; +} +static int pkey_bits_gost(const EVP_PKEY *pk) +{ + return 256; +} +/* ----------------------------------------------------------------------*/ +int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) { + *ameth = EVP_PKEY_asn1_new(nid, + ASN1_PKEY_SIGPARAM_NULL, pemstr, info); + if (!*ameth) return 0; + switch (nid) { + case NID_id_GostR3410_94_cc: + case NID_id_GostR3410_94: + EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94); + EVP_PKEY_asn1_set_private (*ameth, + priv_decode_gost, priv_encode_gost, + priv_print_gost); + + EVP_PKEY_asn1_set_param (*ameth, 0, 0, + param_missing_gost94, param_copy_gost94, + param_cmp_gost94,0 ); + EVP_PKEY_asn1_set_public (*ameth, + pub_decode_gost94, pub_encode_gost94, + pub_cmp_gost94, pub_print_gost94, + pkey_size_gost, pkey_bits_gost); + + EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost); + break; + case NID_id_GostR3410_2001_cc: + case NID_id_GostR3410_2001: + EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01); + EVP_PKEY_asn1_set_private (*ameth, + priv_decode_gost, priv_encode_gost, + priv_print_gost); + + EVP_PKEY_asn1_set_param (*ameth, 0, 0, + param_missing_gost01, param_copy_gost01, + param_cmp_gost01, 0); + EVP_PKEY_asn1_set_public (*ameth, + pub_decode_gost01, pub_encode_gost01, + pub_cmp_gost01, pub_print_gost01, + pkey_size_gost, pkey_bits_gost); + + EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost); + break; + } + return 1; +} diff --git a/engines/ccgost/crypt.h b/engines/ccgost/crypt.h new file mode 100644 index 0000000000..bdd3dc08a8 --- /dev/null +++ b/engines/ccgost/crypt.h @@ -0,0 +1,62 @@ +/********************************************************************** + * gost_crypt.h * + * Copyright (c) 2005-2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Declarations for GOST 28147-89 encryption algorithm * + * OpenSSL 0.9.9 libraries required * + **********************************************************************/ +#ifndef GOST_CRYPT_H +#define GOST_CRYPT_H +#include +#include +#include +#include "gost89.h" +#ifdef __cplusplus + extern "C" { +#endif +/* Cipher context used for EVP_CIPHER operation */ +struct ossl_gost_cipher_ctx { + int paramNID; + off_t count; + int key_meshing; + gost_ctx cctx; +}; +/* Structure to map parameter NID to S-block */ +struct gost_cipher_info { + int nid; + gost_subst_block *sblock; + int key_meshing; +}; +#ifdef USE_SSL +/* Context for MAC */ +struct ossl_gost_imit_ctx { + gost_ctx cctx; + unsigned char buffer[8]; + unsigned char partial_block[8]; + off_t count; + int key_meshing; + int bytes_left; + int key_set; +}; +#endif +/* Table which maps parameter NID to S-blocks */ +extern struct gost_cipher_info gost_cipher_list[]; +/* Find encryption params from ASN1_OBJECT */ +const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj); +/* Implementation of GOST 28147-89 cipher in CFB and CNT modes */ +extern EVP_CIPHER cipher_gost; +#ifdef USE_SSL +#define EVP_MD_FLAG_NEEDS_KEY 0x20 +#define EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH (EVP_MD_CTRL_ALG_CTRL+1) +#define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+2) +/* Ciphers and MACs specific for GOST TLS draft */ +extern EVP_CIPHER cipher_gost_vizircfb; +extern EVP_CIPHER cipher_gost_cpacnt; +extern EVP_MD imit_gost_vizir; +extern EVP_MD imit_gost_cpa; +#endif +#ifdef __cplusplus + }; +#endif +#endif diff --git a/engines/ccgost/e_gost_err.c b/engines/ccgost/e_gost_err.c new file mode 100644 index 0000000000..5ba09e885a --- /dev/null +++ b/engines/ccgost/e_gost_err.c @@ -0,0 +1,210 @@ +/* e_gost_err.c */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* NOTE: this file was auto generated by the mkerr.pl script: any changes + * made to it will be overwritten when the script next updates this file, + * only reason strings will be preserved. + */ + +#include +#include +#include "e_gost_err.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +#define ERR_FUNC(func) ERR_PACK(0,func,0) +#define ERR_REASON(reason) ERR_PACK(0,0,reason) + +static ERR_STRING_DATA GOST_str_functs[]= + { +{ERR_FUNC(GOST_F_DECODE_GOST_ALGOR_PARAMS), "DECODE_GOST_ALGOR_PARAMS"}, +{ERR_FUNC(GOST_F_DECRYPT_CRYPTOCOM_KEY), "decrypt_cryptocom_key"}, +{ERR_FUNC(GOST_F_ENCODE_GOST_ALGOR_PARAMS), "ENCODE_GOST_ALGOR_PARAMS"}, +{ERR_FUNC(GOST_F_FILL_GOST2001_PARAMS), "FILL_GOST2001_PARAMS"}, +{ERR_FUNC(GOST_F_FILL_GOST94_PARAMS), "FILL_GOST94_PARAMS"}, +{ERR_FUNC(GOST_F_GET_ENCRYPTION_PARAMS), "get_encryption_params"}, +{ERR_FUNC(GOST_F_GOST2001_COMPUTE_PUBLIC), "GOST2001_COMPUTE_PUBLIC"}, +{ERR_FUNC(GOST_F_GOST2001_DO_SIGN), "GOST2001_DO_SIGN"}, +{ERR_FUNC(GOST_F_GOST2001_DO_VERIFY), "GOST2001_DO_VERIFY"}, +{ERR_FUNC(GOST_F_GOST89_GET_ASN1_PARAMETERS), "gost89_get_asn1_parameters"}, +{ERR_FUNC(GOST_F_GOST89_SET_ASN1_PARAMETERS), "gost89_set_asn1_parameters"}, +{ERR_FUNC(GOST_F_GOST94_COPY_PARAMETERS), "GOST94_COPY_PARAMETERS"}, +{ERR_FUNC(GOST_F_GOST_CIPHER_CTL), "gost_cipher_ctl"}, +{ERR_FUNC(GOST_F_GOST_COMPUTE_PUBLIC), "GOST_COMPUTE_PUBLIC"}, +{ERR_FUNC(GOST_F_GOST_DO_SIGN), "GOST_DO_SIGN"}, +{ERR_FUNC(GOST_F_GOST_DO_VERIFY), "GOST_DO_VERIFY"}, +{ERR_FUNC(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001), "MAKE_RFC4490_KEYTRANSPORT_2001"}, +{ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"}, +{ERR_FUNC(GOST_F_PARAM_COPY_GOST94), "PARAM_COPY_GOST94"}, +{ERR_FUNC(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT), "PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT"}, +{ERR_FUNC(GOST_F_PKCS7_GOST94_KEY_TRANSPORT_DECRYPT), "PKCS7_GOST94_KEY_TRANSPORT_DECRYPT"}, +{ERR_FUNC(GOST_F_PKEY_GOST01CC_DECRYPT), "pkey_GOST01cc_decrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST01CC_ENCRYPT), "pkey_GOST01cc_encrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST01CP_ENCRYPT), "pkey_GOST01cp_encrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST01_KEYGEN), "PKEY_GOST01_KEYGEN"}, +{ERR_FUNC(GOST_F_PKEY_GOST94CC_DECRYPT), "pkey_GOST94cc_decrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST94CC_ENCRYPT), "pkey_GOST94cc_encrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST94CP_DECRYPT), "pkey_GOST94cp_decrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST94CP_ENCRYPT), "pkey_GOST94cp_encrypt"}, +{ERR_FUNC(GOST_F_PKEY_GOST94_KEYGEN), "PKEY_GOST94_KEYGEN"}, +{ERR_FUNC(GOST_F_PKEY_GOST_CTRL), "PKEY_GOST_CTRL"}, +{ERR_FUNC(GOST_F_PKEY_GOST_CTRL01_STR), "PKEY_GOST_CTRL01_STR"}, +{ERR_FUNC(GOST_F_PKEY_GOST_CTRL94_STR), "PKEY_GOST_CTRL94_STR"}, +{ERR_FUNC(GOST_F_PRIV_DECODE_GOST_94), "PRIV_DECODE_GOST_94"}, +{ERR_FUNC(GOST_F_PUB_DECODE_GOST01), "PUB_DECODE_GOST01"}, +{ERR_FUNC(GOST_F_PUB_DECODE_GOST94), "PUB_DECODE_GOST94"}, +{ERR_FUNC(GOST_F_PUB_ENCODE_GOST01), "PUB_ENCODE_GOST01"}, +{ERR_FUNC(GOST_F_UNPACK_CC_SIGNATURE), "UNPACK_CC_SIGNATURE"}, +{ERR_FUNC(GOST_F_UNPACK_CP_SIGNATURE), "UNPACK_CP_SIGNATURE"}, +{0,NULL} + }; + +static ERR_STRING_DATA GOST_str_reasons[]= + { +{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"}, +{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"}, +{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"}, +{ERR_REASON(GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT),"ctx not initialized for encrypt"}, +{ERR_REASON(GOST_R_ERROR_COMPUTING_MAC) ,"error computing mac"}, +{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"}, +{ERR_REASON(GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO),"error packing key transport info"}, +{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"}, +{ERR_REASON(GOST_R_ERROR_STORING_ENCRYPTED_KEY),"error storing encrypted key"}, +{ERR_REASON(GOST_R_ERROR_STORING_IV) ,"error storing iv"}, +{ERR_REASON(GOST_R_ERROR_STORING_MAC) ,"error storing mac"}, +{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"}, +{ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"}, +{ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"}, +{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"}, +{ERR_REASON(GOST_R_INVALID_ENCRYPTED_KEY_SIZE),"invalid encrypted key size"}, +{ERR_REASON(GOST_R_INVALID_GOST94_PARMSET),"invalid gost94 parmset"}, +{ERR_REASON(GOST_R_INVALID_IV_LENGTH) ,"invalid iv length"}, +{ERR_REASON(GOST_R_INVALID_PARAMSET) ,"invalid paramset"}, +{ERR_REASON(GOST_R_KEY_IS_NOT_INITALIZED),"key is not initalized"}, +{ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED),"key is not initialized"}, +{ERR_REASON(GOST_R_KEY_PARAMETERS_MISSING),"key parameters missing"}, +{ERR_REASON(GOST_R_MALLOC_FAILURE) ,"malloc failure"}, +{ERR_REASON(GOST_R_NOT_ENOUGH_SPACE_FOR_KEY),"not enough space for key"}, +{ERR_REASON(GOST_R_NO_MEMORY) ,"no memory"}, +{ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"}, +{ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"}, +{ERR_REASON(GOST_R_RANDOM_GENERATOR_ERROR),"random generator error"}, +{ERR_REASON(GOST_R_RANDOM_GENERATOR_FAILURE),"random generator failure"}, +{ERR_REASON(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED),"random number generator failed"}, +{ERR_REASON(GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH),"session key mac does not match"}, +{ERR_REASON(GOST_R_SIGNATURE_MISMATCH) ,"signature mismatch"}, +{ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"}, +{ERR_REASON(GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND),"unsupported cipher ctl command"}, +{ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"}, +{0,NULL} + }; + +#endif + +#ifdef GOST_LIB_NAME +static ERR_STRING_DATA GOST_lib_name[]= + { +{0 ,GOST_LIB_NAME}, +{0,NULL} + }; +#endif + + +static int GOST_lib_error_code=0; +static int GOST_error_init=1; + +void ERR_load_GOST_strings(void) + { + if (GOST_lib_error_code == 0) + GOST_lib_error_code=ERR_get_next_error_library(); + + if (GOST_error_init) + { + GOST_error_init=0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(GOST_lib_error_code,GOST_str_functs); + ERR_load_strings(GOST_lib_error_code,GOST_str_reasons); +#endif + +#ifdef GOST_LIB_NAME + GOST_lib_name->error = ERR_PACK(GOST_lib_error_code,0,0); + ERR_load_strings(0,GOST_lib_name); +#endif + } + } + +void ERR_unload_GOST_strings(void) + { + if (GOST_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(GOST_lib_error_code,GOST_str_functs); + ERR_unload_strings(GOST_lib_error_code,GOST_str_reasons); +#endif + +#ifdef GOST_LIB_NAME + ERR_unload_strings(0,GOST_lib_name); +#endif + GOST_error_init=1; + } + } + +void ERR_GOST_error(int function, int reason, char *file, int line) + { + if (GOST_lib_error_code == 0) + GOST_lib_error_code=ERR_get_next_error_library(); + ERR_PUT_error(GOST_lib_error_code,function,reason,file,line); + } diff --git a/engines/ccgost/e_gost_err.h b/engines/ccgost/e_gost_err.h new file mode 100644 index 0000000000..49f4cd5766 --- /dev/null +++ b/engines/ccgost/e_gost_err.h @@ -0,0 +1,150 @@ +/* ==================================================================== + * Copyright (c) 2001-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_GOST_ERR_H +#define HEADER_GOST_ERR_H + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ +void ERR_load_GOST_strings(void); +void ERR_unload_GOST_strings(void); +void ERR_GOST_error(int function, int reason, char *file, int line); +#define GOSTerr(f,r) ERR_GOST_error((f),(r),__FILE__,__LINE__) + +/* Error codes for the GOST functions. */ + +/* Function codes. */ +#define GOST_F_DECODE_GOST_ALGOR_PARAMS 131 +#define GOST_F_DECRYPT_CRYPTOCOM_KEY 120 +#define GOST_F_ENCODE_GOST_ALGOR_PARAMS 130 +#define GOST_F_FILL_GOST2001_PARAMS 99 +#define GOST_F_FILL_GOST94_PARAMS 100 +#define GOST_F_GET_ENCRYPTION_PARAMS 101 +#define GOST_F_GOST2001_COMPUTE_PUBLIC 102 +#define GOST_F_GOST2001_DO_SIGN 103 +#define GOST_F_GOST2001_DO_VERIFY 104 +#define GOST_F_GOST89_GET_ASN1_PARAMETERS 105 +#define GOST_F_GOST89_SET_ASN1_PARAMETERS 106 +#define GOST_F_GOST94_COPY_PARAMETERS 107 +#define GOST_F_GOST_CIPHER_CTL 108 +#define GOST_F_GOST_COMPUTE_PUBLIC 109 +#define GOST_F_GOST_DO_SIGN 110 +#define GOST_F_GOST_DO_VERIFY 111 +#define GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001 127 +#define GOST_F_PARAM_COPY_GOST01 132 +#define GOST_F_PARAM_COPY_GOST94 133 +#define GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT 121 +#define GOST_F_PKCS7_GOST94_KEY_TRANSPORT_DECRYPT 122 +#define GOST_F_PKEY_GOST01CC_DECRYPT 128 +#define GOST_F_PKEY_GOST01CC_ENCRYPT 129 +#define GOST_F_PKEY_GOST01CP_ENCRYPT 137 +#define GOST_F_PKEY_GOST01_KEYGEN 112 +#define GOST_F_PKEY_GOST94CC_DECRYPT 125 +#define GOST_F_PKEY_GOST94CC_ENCRYPT 123 +#define GOST_F_PKEY_GOST94CP_DECRYPT 126 +#define GOST_F_PKEY_GOST94CP_ENCRYPT 124 +#define GOST_F_PKEY_GOST94_KEYGEN 113 +#define GOST_F_PKEY_GOST_CTRL 114 +#define GOST_F_PKEY_GOST_CTRL01_STR 115 +#define GOST_F_PKEY_GOST_CTRL94_STR 116 +#define GOST_F_PRIV_DECODE_GOST_94 117 +#define GOST_F_PUB_DECODE_GOST01 136 +#define GOST_F_PUB_DECODE_GOST94 134 +#define GOST_F_PUB_ENCODE_GOST01 135 +#define GOST_F_UNPACK_CC_SIGNATURE 118 +#define GOST_F_UNPACK_CP_SIGNATURE 119 + +/* Reason codes. */ +#define GOST_R_BAD_KEY_PARAMETERS_FORMAT 128 +#define GOST_R_BAD_PKEY_PARAMETERS_FORMAT 129 +#define GOST_R_CANNOT_PACK_EPHEMERAL_KEY 114 +#define GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT 115 +#define GOST_R_ERROR_COMPUTING_MAC 116 +#define GOST_R_ERROR_COMPUTING_SHARED_KEY 117 +#define GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO 118 +#define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO 119 +#define GOST_R_ERROR_STORING_ENCRYPTED_KEY 120 +#define GOST_R_ERROR_STORING_IV 121 +#define GOST_R_ERROR_STORING_MAC 122 +#define GOST_R_INCOMPATIBLE_ALGORITHMS 130 +#define GOST_R_INVALID_CIPHER_PARAMS 99 +#define GOST_R_INVALID_CIPHER_PARAM_OID 100 +#define GOST_R_INVALID_DIGEST_TYPE 101 +#define GOST_R_INVALID_ENCRYPTED_KEY_SIZE 123 +#define GOST_R_INVALID_GOST94_PARMSET 127 +#define GOST_R_INVALID_IV_LENGTH 102 +#define GOST_R_INVALID_PARAMSET 103 +#define GOST_R_KEY_IS_NOT_INITALIZED 104 +#define GOST_R_KEY_IS_NOT_INITIALIZED 105 +#define GOST_R_KEY_PARAMETERS_MISSING 131 +#define GOST_R_MALLOC_FAILURE 124 +#define GOST_R_NOT_ENOUGH_SPACE_FOR_KEY 125 +#define GOST_R_NO_MEMORY 106 +#define GOST_R_NO_PARAMETERS_SET 107 +#define GOST_R_PUBLIC_KEY_UNDEFINED 132 +#define GOST_R_RANDOM_GENERATOR_ERROR 108 +#define GOST_R_RANDOM_GENERATOR_FAILURE 133 +#define GOST_R_RANDOM_NUMBER_GENERATOR_FAILED 109 +#define GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH 126 +#define GOST_R_SIGNATURE_MISMATCH 110 +#define GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q 111 +#define GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND 112 +#define GOST_R_UNSUPPORTED_PARAMETER_SET 113 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/engines/ccgost/e_gost_err.proto b/engines/ccgost/e_gost_err.proto new file mode 100644 index 0000000000..c57bd1bd8f --- /dev/null +++ b/engines/ccgost/e_gost_err.proto @@ -0,0 +1,61 @@ +/* ==================================================================== + * Copyright (c) 2001-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_GOST_ERR_H +#define HEADER_GOST_ERR_H + +#define GOST_LIB_NAME "GOST engine" +#ifdef __cplusplus + extern "C" { +#endif diff --git a/engines/ccgost/engine.c b/engines/ccgost/engine.c new file mode 100644 index 0000000000..757793b396 --- /dev/null +++ b/engines/ccgost/engine.c @@ -0,0 +1,230 @@ +/********************************************************************** + * engine.c * + * Copyright (c) 2005-2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Main file of GOST engine * + * for OpenSSL * + * Requires OpenSSL 0.9.9 for compilation * + **********************************************************************/ +#include +#include +#include +#include +#include "e_gost_err.h" +#include "md.h" +#include "crypt.h" +#include "meth.h" + +static const char *engine_gost_id = "gost"; +static const char *engine_gost_name = "Reference implementation of GOST engine"; + +/* Symmetric cipher and digest function registrar */ + +static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); + +static int gost_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int ind); + +static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth, + const int **nids, int nid); + +static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, + const int **nids, int nid); + +static int gost_cipher_nids[] = + {NID_id_Gost28147_89, 0}; + +static int gost_digest_nids[] = + {NID_id_GostR3411_94, 0}; + +static int gost_pkey_meth_nids[] = + {NID_id_GostR3410_94_cc, NID_id_GostR3410_94, NID_id_GostR3410_2001_cc, + NID_id_GostR3410_2001, 0}; + +static EVP_PKEY_METHOD *pmeth_GostR3410_94_cc = NULL, *pmeth_GostR3410_94 = NULL, + *pmeth_GostR3410_2001_cc = NULL, *pmeth_GostR3410_2001 = NULL; + +static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94_cc = NULL, *ameth_GostR3410_94 = NULL, + *ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL; + + +static int gost_engine_init(ENGINE *e) { + return 1; +} +static int gost_engine_finish(ENGINE *e) { + return 1; +} + +static int gost_engine_destroy(ENGINE *e) { + return 1; +} + +static int bind_gost (ENGINE *e,const char *id) { + int ret = 0; + if (id && strcmp(id, engine_gost_id)) return 0; + + if (!ENGINE_set_id(e, engine_gost_id)) { + printf("ENGINE_set_id failed\n"); + goto end; + } + if (!ENGINE_set_name(e, engine_gost_name)) { + printf("ENGINE_set_name failed\n"); + goto end; + } + if (!ENGINE_set_digests(e, gost_digests)) { + printf("ENGINE_set_digests failed\n"); + goto end; + } + if (! ENGINE_set_ciphers(e, gost_ciphers)) { + printf("ENGINE_set_ciphers failed\n"); + goto end; + } + if (! ENGINE_set_pkey_meths(e, gost_pkey_meths)) { + printf("ENGINE_set_pkey_meths failed\n"); + goto end; + } + if (! ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) { + printf("ENGINE_set_pkey_asn1_meths failed\n"); + goto end; + } + if ( ! ENGINE_set_destroy_function(e, gost_engine_destroy) + || ! ENGINE_set_init_function(e,gost_engine_init) + || ! ENGINE_set_finish_function(e,gost_engine_finish)) goto end; + + + + if (!register_ameth_gost(NID_id_GostR3410_94_cc, &ameth_GostR3410_94_cc, "GOST94CC", "GOST R 34.10-94, Cryptocom LTD implementation")) goto end; + if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end; + if (!register_ameth_gost(NID_id_GostR3410_2001_cc, &ameth_GostR3410_2001_cc, "GOST2001CC", "GOST R 34.10-2001, Cryptocom LTD implementation")) goto end; + if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end; + + if (!register_pmeth_gost(NID_id_GostR3410_94_cc, &pmeth_GostR3410_94_cc, 0)) goto end; + if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end; + if (!register_pmeth_gost(NID_id_GostR3410_2001_cc, &pmeth_GostR3410_2001_cc, 0)) goto end; + if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end; + if ( ! ENGINE_register_ciphers(e) + || ! ENGINE_register_digests(e) + || ! ENGINE_register_pkey_meths(e) + /* These two actually should go in LIST_ADD command */ + || ! EVP_add_cipher(&cipher_gost) + || ! EVP_add_digest(&digest_gost) + ) goto end; + + ERR_load_GOST_strings(); + ret = 1; +end: + return ret; +} + +#ifdef _WIN32 +extern __declspec( dllexport ) +#endif + +//#ifndef OPENSSL_NO_DYNAMIC_ENGINE +IMPLEMENT_DYNAMIC_BIND_FN(bind_gost); + +#ifdef _WIN32 +extern __declspec( dllexport ) +#endif + +IMPLEMENT_DYNAMIC_CHECK_FN(); +//#else +static ENGINE *engine_gost(void) + { + ENGINE *ret = ENGINE_new(); + if(!ret) + return NULL; + if(!bind_gost(ret, engine_gost_id)) + { + ENGINE_free(ret); + return NULL; + } + return ret; + } + +void ENGINE_load_gost(void) + { + /* Copied from eng_[openssl|dyn].c */ + ENGINE *toadd = engine_gost(); + if(!toadd) return; + ENGINE_add(toadd); + ENGINE_free(toadd); + ERR_clear_error(); + } +//#endif /* OPENSSL_NO_DYNAMIC_ENGINE */ + +static int gost_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) +{ + int ok =1 ; + if (!digest) { + *nids = gost_digest_nids; + return 1; + } + //printf("Digest no %d requested\n",nid); + if(nid == NID_id_GostR3411_94) { + *digest = &digest_gost; + } else { + ok =0; + *digest = NULL; + } + return ok; +} + +static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher, + const int **nids, int nid) { + int ok = 1; + if (!cipher) { + *nids = gost_cipher_nids; + return 1; /* Only one cipher supported */ + } + + if(nid == NID_id_Gost28147_89) { + *cipher = &cipher_gost; + } else { + ok = 0; + *cipher = NULL; + } + return ok; +} + +static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth, + const int **nids, int nid) +{ + if (!pmeth) { + *nids = gost_pkey_meth_nids; + return 4; + } + + switch (nid) { + case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1; + case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1; + case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1; + case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1; + default:; + } + + *pmeth = NULL; + return 0; +} + +static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, + const int **nids, int nid) +{ + if (!ameth) { + *nids = gost_pkey_meth_nids; + return 4; + } + switch (nid) { + case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1; + case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1; + case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1; + case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1; + default:; + } + + *ameth = NULL; + return 0; +} diff --git a/engines/ccgost/gost.ec b/engines/ccgost/gost.ec new file mode 100644 index 0000000000..6c2c85e57c --- /dev/null +++ b/engines/ccgost/gost.ec @@ -0,0 +1,5 @@ +L GOST e_gost_err.h e_gost_err.c +L NONE asymm.h NONE +L NONE md.h NONE +L NONE crypt.h NONE +L NONE gostkeyx.h NONE diff --git a/engines/ccgost/gost2001.c b/engines/ccgost/gost2001.c new file mode 100644 index 0000000000..c53bd6c7c5 --- /dev/null +++ b/engines/ccgost/gost2001.c @@ -0,0 +1,324 @@ +/********************************************************************** + * gost2001.c * + * Copyright (c) 2005-2006 Cryptocom LTD * + * This file is distributed under the same license as OpenSSL * + * * + * Implementation of GOST R 34.10-2001 * + * Requires OpenSSL 0.9.9 for compilation * + **********************************************************************/ +#include "tools.h" +#include "sign.h" +#include "paramset.h" +#include +#include +#include +#include +#include "e_gost_err.h" +#ifdef DEBUG_SIGN +extern +void dump_signature(const char *message,const unsigned char *buffer,size_t len); +void dump_dsa_sig(const char *message, DSA_SIG *sig); +#else + +#define dump_signature(a,b,c) +#define dump_dsa_sig(a,b) +#endif + +/* + * Fills EC_KEY structure hidden in the app_data field of DSA structure + * with parameter information, extracted from parameter array in + * params.c file. + * + * Also fils DSA->q field with copy of EC_GROUP order field to make + * DSA_size function work + */ +int fill_GOST2001_params(EC_KEY *eckey, int nid) { + R3410_2001_params *params = R3410_2001_paramset; + EC_GROUP *grp; + BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL; + EC_POINT *P=NULL; + BN_CTX *ctx=BN_CTX_new(); + int ok=0; + + BN_CTX_start(ctx); + p=BN_CTX_get(ctx); + a=BN_CTX_get(ctx); + b=BN_CTX_get(ctx); + x=BN_CTX_get(ctx); + y=BN_CTX_get(ctx); + q=BN_CTX_get(ctx); + while (params->nid!=NID_undef && params->nid != nid) params++; + if (params->nid == NID_undef) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET); + goto err; + } + BN_hex2bn(&p,params->p); + BN_hex2bn(&a,params->a); + BN_hex2bn(&b,params->b); + + grp = EC_GROUP_new_curve_GFp(p,a,b,ctx); + + P = EC_POINT_new(grp); + + BN_hex2bn(&x,params->x); + BN_hex2bn(&y,params->y); + EC_POINT_set_affine_coordinates_GFp(grp,P,x,y,ctx); + BN_hex2bn(&q,params->q); +#ifdef DEBUG_KEYS + fprintf(stderr,"Set params index %d oid %s\nq=", + (params-R3410_2001_paramset),OBJ_nid2sn(params->nid)); + BN_print_fp(stderr,q); + fprintf(stderr,"\n"); +#endif + + EC_GROUP_set_generator(grp,P,q,NULL); + EC_GROUP_set_curve_name(grp,params->nid); + + EC_KEY_set_group(eckey,grp); + ok=1; +err: + EC_POINT_free(P); + EC_GROUP_free(grp); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return ok; + +} + + +/* + * Computes gost2001 signature as DSA_SIG structure + * + * + */ +DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey) { + DSA_SIG *newsig = NULL; + BIGNUM *md = hashsum2bn(dgst); + BIGNUM *order = NULL; + const EC_GROUP *group; + const BIGNUM *priv_key; + BIGNUM *r=NULL,*s=NULL,*X=NULL,*tmp=NULL,*tmp2=NULL, *k=NULL,*e=NULL; + EC_POINT *C=NULL; + BN_CTX *ctx = BN_CTX_new(); + BN_CTX_start(ctx); + OPENSSL_assert(dlen==32); + newsig=DSA_SIG_new(); + if (!newsig) + { + GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY); + goto err; + } + group = EC_KEY_get0_group(eckey); + order=BN_CTX_get(ctx); + EC_GROUP_get_order(group,order,ctx); + priv_key = EC_KEY_get0_private_key(eckey); + e = BN_CTX_get(ctx); + BN_mod(e,md,order,ctx); +#ifdef DEBUG_SIGN + fprintf(stderr,"digest as bignum="); + BN_print_fp(stderr,md); + fprintf(stderr,"\ndigest mod q="); + BN_print_fp(stderr,e); + fprintf(stderr,"\n"); +#endif + if (BN_is_zero(e)) + { + BN_one(e); + } + k =BN_CTX_get(ctx); + C=EC_POINT_new(group); + do { + do { + if (!BN_rand_range(k,order)) + { + GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); + DSA_SIG_free(newsig); + goto err; + } + if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx)) { + GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB); + DSA_SIG_free(newsig); + goto err; + } + if (!X) X=BN_CTX_get(ctx); + if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) { + GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB); + DSA_SIG_free(newsig); + goto err; + } + if (!r) r=BN_CTX_get(ctx); + BN_nnmod(r,X,order,ctx); + } while (BN_is_zero(r)); + /* s = (r*priv_key+k*e) mod order */ + if (!tmp) tmp = BN_CTX_get(ctx); + BN_mod_mul(tmp,priv_key,r,order,ctx); + if (!tmp2) tmp2 = BN_CTX_get(ctx); + BN_mod_mul(tmp2,k,e,order,ctx); + if (!s) s=BN_CTX_get(ctx); + BN_mod_add(s,tmp,tmp2,order,ctx); + } while (BN_is_zero(s)); + + newsig->s=BN_dup(s); + newsig->r=BN_dup(r); +err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + EC_POINT_free(C); + BN_free(md); + return newsig; +} +/* + * Verifies gost 2001 signature + * + */ +int gost2001_do_verify(const unsigned char *dgst,int dgst_len, + DSA_SIG *sig, EC_KEY *ec) { + BN_CTX *ctx=BN_CTX_new(); + const EC_GROUP *group = EC_KEY_get0_group(ec); + BIGNUM *order; + BIGNUM *md = NULL,*e=NULL,*R=NULL,*v=NULL,*z1=NULL,*z2=NULL; + BIGNUM *X=NULL,*tmp=NULL; + EC_POINT *C = NULL; + const EC_POINT *pub_key=NULL; + int ok=0; + + BN_CTX_start(ctx); + order = BN_CTX_get(ctx); + e = BN_CTX_get(ctx); + z1 = BN_CTX_get(ctx); + z2 = BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + X= BN_CTX_get(ctx); + R=BN_CTX_get(ctx); + v=BN_CTX_get(ctx); + + EC_GROUP_get_order(group,order,ctx); + pub_key = EC_KEY_get0_public_key(ec); + if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || + (BN_cmp(sig->s,order)>=1) || (BN_cmp(sig->r,order)>=1)) + { + GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); + goto err; + + } + md = hashsum2bn(dgst); + + BN_mod(e,md,order,ctx); +#ifdef DEBUG_SIGN + fprintf(stderr,"digest as bignum: "); + BN_print_fp(stderr,md); + fprintf(stderr,"\ndigest mod q: "); + BN_print_fp(stderr,e); +#endif + if (BN_is_zero(e)) BN_one(e); + v=BN_mod_inverse(v,e,order,ctx); + BN_mod_mul(z1,sig->s,v,order,ctx); + BN_sub(tmp,order,sig->r); + BN_mod_mul(z2,tmp,v,order,ctx); +#ifdef DEBUG_SIGN + fprintf(stderr,"\nInverted digest value: "); + BN_print_fp(stderr,v); + fprintf(stderr,"\nz1: "); + BN_print_fp(stderr,z1); + fprintf(stderr,"\nz2: "); + BN_print_fp(stderr,z2); +#endif + C = EC_POINT_new(group); + if (!EC_POINT_mul(group,C,z1,pub_key,z2,ctx)) + { + GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) + { + GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB); + goto err; + } + BN_mod(R,X,order,ctx); +#ifdef DEBUG_SIGN + fprintf(stderr,"\nX="); + BN_print_fp(stderr,X); + fprintf(stderr,"\nX mod q="); + BN_print_fp(stderr,R); + fprintf(stderr,"\n"); +#endif + if (BN_cmp(R,sig->r)!=0) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH); + } else { + ok = 1; + } +err: + EC_POINT_free(C); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + BN_free(md); + return ok; +} +/* + * Computes GOST R 34.10-2001 public key + * + * + */ +int gost2001_compute_public(EC_KEY *ec) +{ + const EC_GROUP *group = EC_KEY_get0_group(ec); + EC_POINT *pub_key=NULL; + const BIGNUM *priv_key=NULL; + BN_CTX *ctx=NULL; + int ok=0; + + if (!group) { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITIALIZED); + return 0; + } + ctx=BN_CTX_new(); + BN_CTX_start(ctx); + if (!(priv_key=EC_KEY_get0_private_key(ec))) + { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); + goto err; + } + + pub_key = EC_POINT_new(group); + if (!EC_POINT_mul(group,pub_key,priv_key,NULL,NULL,ctx)) + { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); + goto err; + } + if (!EC_KEY_set_public_key(ec,pub_key)) { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); + goto err; + } + ok = 256; +err: + BN_CTX_end(ctx); + EC_POINT_free(pub_key); + BN_CTX_free(ctx); + return ok; +} +/* + * + * Generates GOST R 34.10-2001 keypair + * + * + */ +int gost2001_keygen(EC_KEY *ec) { + BIGNUM *order = BN_new(),*d=BN_new(); + const EC_GROUP *group = EC_KEY_get0_group(ec); + EC_GROUP_get_order(group,order,NULL); + + do { + if (!BN_rand_range(d,order)) + { + GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); + BN_free(d); + BN_free(order); + return 0; + } + } while (BN_is_zero(d)); + EC_KEY_set_private_key(ec,d); + BN_free(d); + BN_free(order); + return gost2001_compute_public(ec); +} + diff --git a/engines/ccgost/gost2001_keyx.c b/engines/ccgost/gost2001_keyx.c new file mode 100644 index 0000000000..120ec69d3c --- /dev/null +++ b/engines/ccgost/gost2001_keyx.c @@ -0,0 +1,385 @@ +/********************************************************************** + * gost_keyx.c * + * Copyright (c) 2005-2006 Cryptocom LTD