diff options
Diffstat (limited to 'engines')
33 files changed, 5836 insertions, 0 deletions
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 <openssl/engine.h> +#include <openssl/evp.h> +#include <string.h> +#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;i<octet->length;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;i<octet->length;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;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_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 (da && db && da->pub_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 |