Commit a04549cc authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

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.
parent bc7535bc
Loading
Loading
Loading
Loading
+122 −0
Original line number Diff line number Diff line
# 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

engines/ccgost/ameth.c

0 → 100644
+671 −0
Original line number Diff line number Diff line
/**********************************************************************
 *                          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, &params->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;
}

engines/ccgost/crypt.h

0 → 100644
+62 −0
Original line number Diff line number Diff line
/**********************************************************************
 *                        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 <unistd.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#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
+210 −0

File added.

Preview size limit exceeded, changes collapsed.

+150 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading