Updated version of gost engine.

This commit is contained in:
Dr. Stephen Henson 2006-09-21 13:04:43 +00:00
parent 1182301ca7
commit 926c41bd29
31 changed files with 2729 additions and 2322 deletions

View File

@ -1,122 +1,269 @@
# OPENSSL_DIR is a root directory of openssl sources DIR=ccgost
THISDIR?=$(shell perl -MCwd -e 'print getcwd') TOP=../..
OPENSSL_DIR?=$(THISDIR)/../openssl CC=cc
ENGINE_ID?=gost INCLUDES= -I../../include
TESTSUITE_DIR?=$(THISDIR)/test-suite CFLAG=-g
FOR?=$(HOST) MAKEFILE= Makefile
CC=gcc AR= ar r
CFLAGS=-fPIC -g -Wall -I$(OPENSSL_DIR)/include CFLAGS= $(INCLUDES) $(CFLAG)
LDFLAGS=-g -L $(OPENSSL_DIR) -static-libgcc LIB=$(TOP)/libcrypto.a
ifeq "$(FOR)" "s64"
CFLAGS+=-m64 LIBSRC= gost2001.c gost2001_keyx.c gost89.c gost94_keyx.c gost_ameth.c gost_asn1.c gost_crypt.c gost_ctl.c gost_eng.c gosthash.c gost_keywrap.c gost_md.c gost_params.c gost_pmeth.c gost_sign.c
LDFLAGS+=-m64
endif LIBOBJ= e_gost_err.o gost2001_keyx.o gost2001.o gost89.o gost94_keyx.o gost_ameth.o gost_asn1.o gost_crypt.o gost_ctl.o gost_eng.o gosthash.o gost_keywrap.o gost_md.o gost_params.o gost_pmeth.o gost_sign.o
OS:=$(shell uname -s)
ifeq "$(OS)" "FreeBSD" SRC=$(LIBSRC)
LIBDIR:=$(shell LD_LIBRARY_PATH=$(OPENSSL_DIR) $(OPENSSL_DIR)/apps/openssl version -d|sed -e 's/^[^"]*"//' -e 's/".*$$//')/lib
LDFLAGS+=-rpath $(LIBDIR) LIBNAME=gost
endif
top:
(cd $(TOP); $(MAKE) DIRS=engines EDIRS=$(DIR) sub_all)
all: lib
tags:
ctags $(SRC)
errors:
$(PERL) ../../util/mkerr.pl -conf gost.ec -nostatic -debug -write $(SRC)
lib: $(LIBOBJ)
if [ -n "$(SHARED_LIBS)" ]; then \
$(MAKE) -f $(TOP)/Makefile.shared -e \
LIBNAME=$(LIBNAME) \
LIBEXTRAS='$(LIBOBJ)' \
LIBDEPS='-L$(TOP) -lcrypto' \
link_o.$(SHLIB_TARGET); \
else \
$(AR) $(LIB) $(LIBOBJ); \
fi
install:
[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
if [ -n "$(SHARED_LIBS)" ]; then \
set -e; \
echo installing $(LIBNAME); \
if [ "$(PLATFORM)" != "Cygwin" ]; then \
case "$(CFLAGS)" in \
*DSO_BEOS*) sfx="so";; \
*DSO_DLFCN*) sfx="so";; \
*DSO_DL*) sfx="sl";; \
*) sfx="bad";; \
esac; \
cp lib$(LIBNAME).$$sfx $(INSTALL_PREFIX)$(INSTALLTOP)/lib/engines/lib$(LIBNAME).$$sfx.new; \
else \
sfx="so"; \
cp cyg$(LIBNAME).dll $(INSTALL_PREFIX)$(INSTALLTOP)/lib/engines/lib$(LIBNAME).$$sfx.new; \
fi; \
chmod 555 $(INSTALL_PREFIX)$(INSTALLTOP)/lib/engines/lib$(LIBNAME).$$sfx.new; \
mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/lib/engines/lib$(LIBNAME).$$sfx.new $(INSTALL_PREFIX)$(INSTALLTOP)/lib/engines/lib$(LIBNAME).$$sfx; \
fi
links:
tests:
depend:
@if [ -z "$(THIS)" ]; then \
$(MAKE) -f $(TOP)/Makefile reflect THIS=$@; \
else \
$(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC); \
fi
files:
ifeq "$(FOR)" "w32"
ENGINE_LIB?=$(ENGINE_ID)$(DLLSUFFIX) lint:
DLLSUFFIX=.dll lint -DLINT $(INCLUDES) $(SRC)>fluff
EXESUFFIX=.exe
CFLAGS+=-mno-cygwin dclean:
LDFLAGS+=-mno-cygwin $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
ifeq "$(OS)" "Linux" mv -f Makefile.new $(MAKEFILE)
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: clean:
rm -f core gosttest gostsum *.o gost_test openssl.cnf* $(ENGINE_LIB) rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff *.so *.sl *.dll
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 # DO NOT DELETE THIS LINE -- make depend depends on it.
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
gost2001.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost2001.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost2001.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost2001.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost2001.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost2001.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost2001.o: ../../include/openssl/err.h ../../include/openssl/evp.h
gost2001.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
gost2001.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
gost2001.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost2001.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
gost2001.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
gost2001.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
gost2001.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
gost2001.o: e_gost_err.h gost2001.c gost89.h gost_lcl.h gost_params.h
gost2001.o: gosthash.h
gost2001_keyx.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost2001_keyx.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost2001_keyx.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost2001_keyx.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost2001_keyx.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost2001_keyx.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost2001_keyx.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost2001_keyx.o: ../../include/openssl/obj_mac.h
gost2001_keyx.o: ../../include/openssl/objects.h
gost2001_keyx.o: ../../include/openssl/opensslconf.h
gost2001_keyx.o: ../../include/openssl/opensslv.h
gost2001_keyx.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
gost2001_keyx.o: ../../include/openssl/rand.h ../../include/openssl/safestack.h
gost2001_keyx.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost2001_keyx.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost2001_keyx.o: ../../include/openssl/x509_vfy.h e_gost_err.h gost2001_keyx.c
gost2001_keyx.o: gost89.h gost_keywrap.h gost_lcl.h gosthash.h
gost89.o: gost89.c gost89.h gost89.o: gost89.c gost89.h
gost94_keyx.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_asn1.o: gost_asn1.c gost_asn1.h gost94_keyx.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost94_keyx.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_crypt.o: gost_crypt.c crypt.h gost89.h e_gost_err.h gost_asn1.h gost94_keyx.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
gost94_keyx.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
gosthash.o: gosthash.c gost89.h gosthash.h gost94_keyx.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
gost94_keyx.o: ../../include/openssl/engine.h ../../include/openssl/evp.h
md_gost.o: md_gost.c md.h gosthash.h e_gost_err.h gost94_keyx.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
gost94_keyx.o: ../../include/openssl/objects.h
params.o: params.c paramset.h gost94_keyx.o: ../../include/openssl/opensslconf.h
gost94_keyx.o: ../../include/openssl/opensslv.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 gost94_keyx.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
gost94_keyx.o: ../../include/openssl/rand.h ../../include/openssl/safestack.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 gost94_keyx.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost94_keyx.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost94_keyx.o: ../../include/openssl/x509_vfy.h e_gost_err.h gost89.h
gost94_keyx.o: gost94_keyx.c gost_keywrap.h gost_lcl.h gosthash.h
gost_ameth.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_ameth.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_ameth.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_ameth.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_ameth.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_ameth.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_ameth.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_ameth.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_ameth.o: ../../include/openssl/opensslconf.h
gost_ameth.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_ameth.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
gost_ameth.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost_ameth.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost_ameth.o: ../../include/openssl/x509_vfy.h e_gost_err.h gost89.h
gost_ameth.o: gost_ameth.c gost_lcl.h gost_params.h gosthash.h
gost_asn1.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_asn1.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_asn1.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_asn1.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_asn1.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_asn1.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_asn1.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_asn1.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_asn1.o: ../../include/openssl/opensslconf.h
gost_asn1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_asn1.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
gost_asn1.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost_asn1.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost_asn1.o: ../../include/openssl/x509_vfy.h gost89.h gost_asn1.c gost_lcl.h
gost_asn1.o: gosthash.h
gost_crypt.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_crypt.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_crypt.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_crypt.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_crypt.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_crypt.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_crypt.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_crypt.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_crypt.o: ../../include/openssl/opensslconf.h
gost_crypt.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_crypt.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
gost_crypt.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
gost_crypt.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
gost_crypt.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
gost_crypt.o: e_gost_err.h gost89.h gost_crypt.c gost_lcl.h gosthash.h
gost_ctl.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_ctl.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_ctl.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_ctl.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_ctl.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_ctl.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_ctl.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_ctl.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_ctl.o: ../../include/openssl/opensslconf.h
gost_ctl.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_ctl.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
gost_ctl.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost_ctl.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost_ctl.o: ../../include/openssl/x509_vfy.h gost89.h gost_ctl.c gost_lcl.h
gost_ctl.o: gosthash.h
gost_eng.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_eng.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_eng.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_eng.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_eng.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_eng.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_eng.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_eng.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_eng.o: ../../include/openssl/opensslconf.h
gost_eng.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_eng.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
gost_eng.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost_eng.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost_eng.o: ../../include/openssl/x509_vfy.h e_gost_err.h gost89.h gost_eng.c
gost_eng.o: gost_lcl.h gosthash.h
gost_keywrap.o: gost89.h gost_keywrap.c gost_keywrap.h
gost_md.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_md.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_md.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_md.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_md.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_md.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_md.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_md.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_md.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
gost_md.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
gost_md.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
gost_md.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
gost_md.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
gost_md.o: e_gost_err.h gost89.h gost_lcl.h gost_md.c gosthash.h
gost_params.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
gost_params.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
gost_params.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_params.o: ../../include/openssl/opensslconf.h
gost_params.o: ../../include/openssl/opensslv.h
gost_params.o: ../../include/openssl/ossl_typ.h
gost_params.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
gost_params.o: ../../include/openssl/symhacks.h gost_params.c gost_params.h
gost_pmeth.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_pmeth.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_pmeth.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_pmeth.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_pmeth.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_pmeth.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_pmeth.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_pmeth.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_pmeth.o: ../../include/openssl/opensslconf.h
gost_pmeth.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_pmeth.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
gost_pmeth.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
gost_pmeth.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
gost_pmeth.o: ../../include/openssl/x509_vfy.h e_gost_err.h gost89.h gost_lcl.h
gost_pmeth.o: gost_params.h gost_pmeth.c gosthash.h
gost_sign.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost_sign.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost_sign.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost_sign.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
gost_sign.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
gost_sign.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
gost_sign.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
gost_sign.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
gost_sign.o: ../../include/openssl/opensslconf.h
gost_sign.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gost_sign.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
gost_sign.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
gost_sign.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
gost_sign.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
gost_sign.o: e_gost_err.h gost89.h gost_lcl.h gost_params.h gost_sign.c
gost_sign.o: gosthash.h
gosthash.o: gost89.h gosthash.c gosthash.h

View File

@ -1,62 +0,0 @@
/**********************************************************************
* 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

View File

@ -70,86 +70,86 @@
static ERR_STRING_DATA GOST_str_functs[]= static ERR_STRING_DATA GOST_str_functs[]=
{ {
{ERR_FUNC(GOST_F_DECODE_GOST_ALGOR_PARAMS), "DECODE_GOST_ALGOR_PARAMS"}, {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_DECRYPT_CRYPTOCOM_KEY), "decrypt_cryptocom_key"},
{ERR_FUNC(GOST_F_ENCODE_GOST_ALGOR_PARAMS), "ENCODE_GOST_ALGOR_PARAMS"}, {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_GOST2001_PARAMS), "FILL_GOST2001_PARAMS"},
{ERR_FUNC(GOST_F_FILL_GOST94_PARAMS), "FILL_GOST94_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_GET_ENCRYPTION_PARAMS), "get_encryption_params"},
{ERR_FUNC(GOST_F_GOST2001_COMPUTE_PUBLIC), "GOST2001_COMPUTE_PUBLIC"}, {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_SIGN), "GOST2001_DO_SIGN"},
{ERR_FUNC(GOST_F_GOST2001_DO_VERIFY), "GOST2001_DO_VERIFY"}, {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_GET_ASN1_PARAMETERS), "gost89_get_asn1_parameters"},
{ERR_FUNC(GOST_F_GOST89_SET_ASN1_PARAMETERS), "gost89_set_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_GOST94_COPY_PARAMETERS), "GOST94_COPY_PARAMETERS"},
{ERR_FUNC(GOST_F_GOST_CIPHER_CTL), "gost_cipher_ctl"}, {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_COMPUTE_PUBLIC), "GOST_COMPUTE_PUBLIC"},
{ERR_FUNC(GOST_F_GOST_DO_SIGN), "GOST_DO_SIGN"}, {ERR_FUNC(GOST_F_GOST_DO_SIGN), "GOST_DO_SIGN"},
{ERR_FUNC(GOST_F_GOST_DO_VERIFY), "GOST_DO_VERIFY"}, {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_MAKE_RFC4490_KEYTRANSPORT_2001), "MAKE_RFC4490_KEYTRANSPORT_2001"},
{ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"}, {ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"},
{ERR_FUNC(GOST_F_PARAM_COPY_GOST94), "PARAM_COPY_GOST94"}, {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_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_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_DECRYPT), "pkey_GOST01cc_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01CC_ENCRYPT), "pkey_GOST01cc_encrypt"}, {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_GOST01CP_ENCRYPT), "pkey_GOST01cp_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01_KEYGEN), "PKEY_GOST01_KEYGEN"}, {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_DECRYPT), "pkey_GOST94cc_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CC_ENCRYPT), "pkey_GOST94cc_encrypt"}, {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_DECRYPT), "pkey_GOST94cp_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CP_ENCRYPT), "pkey_GOST94cp_encrypt"}, {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_GOST94_KEYGEN), "PKEY_GOST94_KEYGEN"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL), "PKEY_GOST_CTRL"}, {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_CTRL01_STR), "PKEY_GOST_CTRL01_STR"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL94_STR), "PKEY_GOST_CTRL94_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_PRIV_DECODE_GOST_94), "PRIV_DECODE_GOST_94"},
{ERR_FUNC(GOST_F_PUB_DECODE_GOST01), "PUB_DECODE_GOST01"}, {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_DECODE_GOST94), "PUB_DECODE_GOST94"},
{ERR_FUNC(GOST_F_PUB_ENCODE_GOST01), "PUB_ENCODE_GOST01"}, {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_CC_SIGNATURE), "UNPACK_CC_SIGNATURE"},
{ERR_FUNC(GOST_F_UNPACK_CP_SIGNATURE), "UNPACK_CP_SIGNATURE"}, {ERR_FUNC(GOST_F_UNPACK_CP_SIGNATURE), "UNPACK_CP_SIGNATURE"},
{0,NULL} {0,NULL}
}; };
static ERR_STRING_DATA GOST_str_reasons[]= static ERR_STRING_DATA GOST_str_reasons[]=
{ {
{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"}, {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_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"}, {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_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_MAC) ,"error computing mac"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"}, {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_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_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_ENCRYPTED_KEY),"error storing encrypted key"},
{ERR_REASON(GOST_R_ERROR_STORING_IV) ,"error storing iv"}, {ERR_REASON(GOST_R_ERROR_STORING_IV) ,"error storing iv"},
{ERR_REASON(GOST_R_ERROR_STORING_MAC) ,"error storing mac"}, {ERR_REASON(GOST_R_ERROR_STORING_MAC) ,"error storing mac"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"}, {ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"}, {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_CIPHER_PARAM_OID),"invalid cipher param oid"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"}, {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_ENCRYPTED_KEY_SIZE),"invalid encrypted key size"},
{ERR_REASON(GOST_R_INVALID_GOST94_PARMSET),"invalid gost94 parmset"}, {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_IV_LENGTH) ,"invalid iv length"},
{ERR_REASON(GOST_R_INVALID_PARAMSET) ,"invalid paramset"}, {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_INITALIZED),"key is not initalized"},
{ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED),"key is not initialized"}, {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_KEY_PARAMETERS_MISSING),"key parameters missing"},
{ERR_REASON(GOST_R_MALLOC_FAILURE) ,"malloc failure"}, {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_NOT_ENOUGH_SPACE_FOR_KEY),"not enough space for key"},
{ERR_REASON(GOST_R_NO_MEMORY) ,"no memory"}, {ERR_REASON(GOST_R_NO_MEMORY) ,"no memory"},
{ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"}, {ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"},
{ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"}, {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_ERROR),"random generator error"},
{ERR_REASON(GOST_R_RANDOM_GENERATOR_FAILURE),"random generator failure"}, {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_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_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_MISMATCH) ,"signature mismatch"},
{ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"}, {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_CIPHER_CTL_COMMAND),"unsupported cipher ctl command"},
{ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"}, {ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"},
{0,NULL} {0,NULL}
}; };
#endif #endif
@ -157,8 +157,8 @@ static ERR_STRING_DATA GOST_str_reasons[]=
#ifdef GOST_LIB_NAME #ifdef GOST_LIB_NAME
static ERR_STRING_DATA GOST_lib_name[]= static ERR_STRING_DATA GOST_lib_name[]=
{ {
{0 ,GOST_LIB_NAME}, {0 ,GOST_LIB_NAME},
{0,NULL} {0,NULL}
}; };
#endif #endif

View File

@ -6,9 +6,8 @@
* Implementation of GOST R 34.10-2001 * * Implementation of GOST R 34.10-2001 *
* Requires OpenSSL 0.9.9 for compilation * * Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/ **********************************************************************/
#include "tools.h" #include "gost_lcl.h"
#include "sign.h" #include "gost_params.h"
#include "paramset.h"
#include <string.h> #include <string.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/ecdsa.h> #include <openssl/ecdsa.h>
@ -32,9 +31,10 @@ void dump_dsa_sig(const char *message, DSA_SIG *sig);
* Also fils DSA->q field with copy of EC_GROUP order field to make * Also fils DSA->q field with copy of EC_GROUP order field to make
* DSA_size function work * DSA_size function work
*/ */
int fill_GOST2001_params(EC_KEY *eckey, int nid) { int fill_GOST2001_params(EC_KEY *eckey, int nid)
{
R3410_2001_params *params = R3410_2001_paramset; R3410_2001_params *params = R3410_2001_paramset;
EC_GROUP *grp; EC_GROUP *grp=NULL;
BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL; BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL;
EC_POINT *P=NULL; EC_POINT *P=NULL;
BN_CTX *ctx=BN_CTX_new(); BN_CTX *ctx=BN_CTX_new();
@ -48,7 +48,8 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) {
y=BN_CTX_get(ctx); y=BN_CTX_get(ctx);
q=BN_CTX_get(ctx); q=BN_CTX_get(ctx);
while (params->nid!=NID_undef && params->nid != nid) params++; while (params->nid!=NID_undef && params->nid != nid) params++;
if (params->nid == NID_undef) { if (params->nid == NID_undef)
{
GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET); GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
goto err; goto err;
} }
@ -76,14 +77,13 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) {
EC_KEY_set_group(eckey,grp); EC_KEY_set_group(eckey,grp);
ok=1; ok=1;
err: err:
EC_POINT_free(P); EC_POINT_free(P);
EC_GROUP_free(grp); EC_GROUP_free(grp);
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return ok; return ok;
}
}
/* /*
@ -91,7 +91,8 @@ err:
* *
* *
*/ */
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey) { DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
{
DSA_SIG *newsig = NULL; DSA_SIG *newsig = NULL;
BIGNUM *md = hashsum2bn(dgst); BIGNUM *md = hashsum2bn(dgst);
BIGNUM *order = NULL; BIGNUM *order = NULL;
@ -127,28 +128,33 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey) {
} }
k =BN_CTX_get(ctx); k =BN_CTX_get(ctx);
C=EC_POINT_new(group); C=EC_POINT_new(group);
do { do
do { {
do
{
if (!BN_rand_range(k,order)) if (!BN_rand_range(k,order))
{ {
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
DSA_SIG_free(newsig); DSA_SIG_free(newsig);
goto err; goto err;
} }
if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx)) { if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx))
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB); GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
DSA_SIG_free(newsig); DSA_SIG_free(newsig);
goto err; goto err;
} }
if (!X) X=BN_CTX_get(ctx); if (!X) X=BN_CTX_get(ctx);
if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) { if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx))
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB); GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
DSA_SIG_free(newsig); DSA_SIG_free(newsig);
goto err; goto err;
} }
if (!r) r=BN_CTX_get(ctx); if (!r) r=BN_CTX_get(ctx);
BN_nnmod(r,X,order,ctx); BN_nnmod(r,X,order,ctx);
} while (BN_is_zero(r)); }
while (BN_is_zero(r));
/* s = (r*priv_key+k*e) mod order */ /* s = (r*priv_key+k*e) mod order */
if (!tmp) tmp = BN_CTX_get(ctx); if (!tmp) tmp = BN_CTX_get(ctx);
BN_mod_mul(tmp,priv_key,r,order,ctx); BN_mod_mul(tmp,priv_key,r,order,ctx);
@ -156,23 +162,25 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey) {
BN_mod_mul(tmp2,k,e,order,ctx); BN_mod_mul(tmp2,k,e,order,ctx);
if (!s) s=BN_CTX_get(ctx); if (!s) s=BN_CTX_get(ctx);
BN_mod_add(s,tmp,tmp2,order,ctx); BN_mod_add(s,tmp,tmp2,order,ctx);
} while (BN_is_zero(s)); }
while (BN_is_zero(s));
newsig->s=BN_dup(s); newsig->s=BN_dup(s);
newsig->r=BN_dup(r); newsig->r=BN_dup(r);
err: err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
EC_POINT_free(C); EC_POINT_free(C);
BN_free(md); BN_free(md);
return newsig; return newsig;
} }
/* /*
* Verifies gost 2001 signature * Verifies gost 2001 signature
* *
*/ */
int gost2001_do_verify(const unsigned char *dgst,int dgst_len, int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
DSA_SIG *sig, EC_KEY *ec) { DSA_SIG *sig, EC_KEY *ec)
{
BN_CTX *ctx=BN_CTX_new(); BN_CTX *ctx=BN_CTX_new();
const EC_GROUP *group = EC_KEY_get0_group(ec); const EC_GROUP *group = EC_KEY_get0_group(ec);
BIGNUM *order; BIGNUM *order;
@ -242,32 +250,36 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
BN_print_fp(stderr,R); BN_print_fp(stderr,R);
fprintf(stderr,"\n"); fprintf(stderr,"\n");
#endif #endif
if (BN_cmp(R,sig->r)!=0) { if (BN_cmp(R,sig->r)!=0)
{
GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH); GOSTerr(GOST_F_GOST2001_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
} else { }
else
{
ok = 1; ok = 1;
} }
err: err:
EC_POINT_free(C); EC_POINT_free(C);
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
BN_free(md); BN_free(md);
return ok; return ok;
} }
/* /*
* Computes GOST R 34.10-2001 public key * Computes GOST R 34.10-2001 public key
* *
* *
*/ */
int gost2001_compute_public(EC_KEY *ec) int gost2001_compute_public(EC_KEY *ec)
{ {
const EC_GROUP *group = EC_KEY_get0_group(ec); const EC_GROUP *group = EC_KEY_get0_group(ec);
EC_POINT *pub_key=NULL; EC_POINT *pub_key=NULL;
const BIGNUM *priv_key=NULL; const BIGNUM *priv_key=NULL;
BN_CTX *ctx=NULL; BN_CTX *ctx=NULL;
int ok=0; int ok=0;
if (!group) { if (!group)
{
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITIALIZED); GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITIALIZED);
return 0; return 0;
} }
@ -285,29 +297,32 @@ int gost2001_compute_public(EC_KEY *ec)
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB);
goto err; goto err;
} }
if (!EC_KEY_set_public_key(ec,pub_key)) { if (!EC_KEY_set_public_key(ec,pub_key))
{
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB); GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB);
goto err; goto err;
} }
ok = 256; ok = 256;
err: err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
EC_POINT_free(pub_key); EC_POINT_free(pub_key);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return ok; return ok;
} }
/* /*
* *
* Generates GOST R 34.10-2001 keypair * Generates GOST R 34.10-2001 keypair
* *
* *
*/ */
int gost2001_keygen(EC_KEY *ec) { int gost2001_keygen(EC_KEY *ec)
{
BIGNUM *order = BN_new(),*d=BN_new(); BIGNUM *order = BN_new(),*d=BN_new();
const EC_GROUP *group = EC_KEY_get0_group(ec); const EC_GROUP *group = EC_KEY_get0_group(ec);
EC_GROUP_get_order(group,order,NULL); EC_GROUP_get_order(group,order,NULL);
do { do
{
if (!BN_rand_range(d,order)) if (!BN_rand_range(d,order))
{ {
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
@ -315,10 +330,11 @@ int gost2001_keygen(EC_KEY *ec) {
BN_free(order); BN_free(order);
return 0; return 0;
} }
} while (BN_is_zero(d)); }
while (BN_is_zero(d));
EC_KEY_set_private_key(ec,d); EC_KEY_set_private_key(ec,d);
BN_free(d); BN_free(d);
BN_free(order); BN_free(order);
return gost2001_compute_public(ec); return gost2001_compute_public(ec);
} }

View File

@ -13,49 +13,48 @@
#include <openssl/objects.h> #include <openssl/objects.h>
#include "gost89.h" #include "gost89.h"
#include "gosthash.h" #include "gosthash.h"
#include "gost_asn1.h"
#include "e_gost_err.h" #include "e_gost_err.h"
#include "keywrap.h" #include "gost_keywrap.h"
#include "crypt.h" #include "gost_lcl.h"
#include "sign.h"
#include "pmeth.h"
#include "tools.h"
#include "gostkeyx.h"
/* Transform ECDH shared key into little endian as required by Cryptocom /* Transform ECDH shared key into little endian as required by Cryptocom
* key exchange */ * key exchange */
static void *make_key_le(const void *in, size_t inlen, void *out, size_t *outlen) { static void *make_key_le(const void *in, size_t inlen, void *out, size_t *outlen)
{
const char* inbuf= in; const char* inbuf= in;
char* outbuf= out; char* outbuf= out;
int i; int i;
if (*outlen < inlen) { if (*outlen < inlen)
{
return NULL; return NULL;
} }
for (i=0;i<inlen;i++) { for (i=0;i<inlen;i++)
{
outbuf[inlen-1-i]=inbuf[i]; outbuf[inlen-1-i]=inbuf[i];
} }
*outlen = inlen; *outlen = inlen;
return out; return out;
} }
/* Create gost 2001 ephemeral key with same parameters as peer key */ /* Create gost 2001 ephemeral key with same parameters as peer key */
static EC_KEY *make_ec_ephemeral_key(EC_KEY *peer_key,BIGNUM *seckey) { static EC_KEY *make_ec_ephemeral_key(EC_KEY *peer_key,BIGNUM *seckey)
{
EC_KEY *out = EC_KEY_new(); EC_KEY *out = EC_KEY_new();
EC_KEY_copy(out,peer_key); EC_KEY_copy(out,peer_key);
EC_KEY_set_private_key(out,seckey); EC_KEY_set_private_key(out,seckey);
gost2001_compute_public(out); gost2001_compute_public(out);
return out; return out;
} }
/* Packs GOST elliptic curve key into EVP_PKEY setting same parameters /* Packs GOST elliptic curve key into EVP_PKEY setting same parameters
* as in passed pubkey * as in passed pubkey
*/ */
static EVP_PKEY *ec_ephemeral_key_to_EVP(EVP_PKEY *pubk,int type,EC_KEY *ephemeral) static EVP_PKEY *ec_ephemeral_key_to_EVP(EVP_PKEY *pubk,int type,EC_KEY *ephemeral)
{ {
EVP_PKEY *newkey; EVP_PKEY *newkey;
newkey = EVP_PKEY_new(); newkey = EVP_PKEY_new();
EVP_PKEY_assign(newkey,type,ephemeral); EVP_PKEY_assign(newkey,type,ephemeral);
return newkey; return newkey;
} }
/* /*
* EVP_PKEY_METHOD callback encrypt * EVP_PKEY_METHOD callback encrypt
@ -64,7 +63,7 @@ static EVP_PKEY *ec_ephemeral_key_to_EVP(EVP_PKEY *pubk,int type,EC_KEY *ephemer
int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out, int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out,
size_t *out_len, const unsigned char *key,size_t key_len) size_t *out_len, const unsigned char *key,size_t key_len)
{ {
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
GOST_KEY_TRANSPORT *gkt = NULL; GOST_KEY_TRANSPORT *gkt = NULL;
@ -116,7 +115,8 @@ int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out,
goto err; goto err;
} }
if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey)) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey))
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
goto err; goto err;
} }
@ -124,15 +124,16 @@ int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out,
gkt->key_agreement_info->cipher = OBJ_nid2obj(NID_id_Gost28147_89_cc); gkt->key_agreement_info->cipher = OBJ_nid2obj(NID_id_Gost28147_89_cc);
if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret = 1; if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret = 1;
; ;
err: err:
if (gkt) GOST_KEY_TRANSPORT_free(gkt); if (gkt) GOST_KEY_TRANSPORT_free(gkt);
return ret; return ret;
} }
/* /*
* EVP_PKEY_METHOD callback decrypt * EVP_PKEY_METHOD callback decrypt
* Implementation of GOST2001 key transport, cryptocom variation * Implementation of GOST2001 key transport, cryptocom variation
*/ */
int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len) { int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len)
{
/* Form DH params from compute shared key */ /* Form DH params from compute shared key */
EVP_PKEY *priv=EVP_PKEY_CTX_get0_pkey(pctx); EVP_PKEY *priv=EVP_PKEY_CTX_get0_pkey(pctx);
GOST_KEY_TRANSPORT *gkt = NULL; GOST_KEY_TRANSPORT *gkt = NULL;
@ -145,14 +146,16 @@ int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
const EC_POINT *pub_key_point; const EC_POINT *pub_key_point;
EVP_PKEY *eph_key; EVP_PKEY *eph_key;
if (!key) { if (!key)
{
*key_len = 32; *key_len = 32;
return 1; return 1;
} }
/* Parse passed octet string and find out public key, iv and HMAC*/ /* Parse passed octet string and find out public key, iv and HMAC*/
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len); in_len);
if (!gkt) { if (!gkt)
{
GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return 0; return 0;
} }
@ -185,20 +188,23 @@ int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
} }
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
/* check HMAC of session key*/ /* check HMAC of session key*/
if (!gost_mac(&ctx,32,key,32,hmac_comp)) { if (!gost_mac(&ctx,32,key,32,hmac_comp))
{
GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC); GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC);
return 0; return 0;
} }
/* HMAC of session key is not correct */ /* HMAC of session key is not correct */
if (memcmp(hmac,hmac_comp,4)!=0) { if (memcmp(hmac,hmac_comp,4)!=0)
{
GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH); GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH);
return 0; return 0;
} }
return 1; return 1;
} }
/* Implementation of CryptoPro VKO 34.10-2001 algorithm */ /* Implementation of CryptoPro VKO 34.10-2001 algorithm */
static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,const EC_POINT *pub_key,EC_KEY *priv_key,const unsigned char *ukm) { static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,const EC_POINT *pub_key,EC_KEY *priv_key,const unsigned char *ukm)
{
unsigned char ukm_be[8],databuf[64],hashbuf[64]; unsigned char ukm_be[8],databuf[64],hashbuf[64];
BIGNUM *UKM=NULL,*p=NULL,*order=NULL,*X=NULL,*Y=NULL; BIGNUM *UKM=NULL,*p=NULL,*order=NULL,*X=NULL,*Y=NULL;
const BIGNUM* key=EC_KEY_get0_private_key(priv_key); const BIGNUM* key=EC_KEY_get0_private_key(priv_key);
@ -207,7 +213,8 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
gost_hash_ctx hash_ctx; gost_hash_ctx hash_ctx;
BN_CTX *ctx = BN_CTX_new(); BN_CTX *ctx = BN_CTX_new();
for (i=0;i<8;i++) { for (i=0;i<8;i++)
{
ukm_be[7-i]=ukm[i]; ukm_be[7-i]=ukm[i];
} }
BN_CTX_start(ctx); BN_CTX_start(ctx);
@ -226,7 +233,8 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
store_bignum(Y,databuf,32); store_bignum(Y,databuf,32);
store_bignum(X,databuf+32,32); store_bignum(X,databuf+32,32);
/* And reverse byte order of whole buffer */ /* And reverse byte order of whole buffer */
for (i=0;i<64;i++) { for (i=0;i<64;i++)
{
hashbuf[63-i]=databuf[i]; hashbuf[63-i]=databuf[i];
} }
init_gost_hash_ctx(&hash_ctx,&GostR3411_94_CryptoProParamSet); init_gost_hash_ctx(&hash_ctx,&GostR3411_94_CryptoProParamSet);
@ -239,7 +247,7 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
BN_CTX_free(ctx); BN_CTX_free(ctx);
EC_POINT_free(pnt); EC_POINT_free(pnt);
return 32; return 32;
} }
/* Generates ephemeral key based on pubk algorithm /* Generates ephemeral key based on pubk algorithm
* computes shared key using VKO and returns filled up * computes shared key using VKO and returns filled up
@ -249,7 +257,7 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_key, GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_key,
const unsigned char *key,size_t keylen, unsigned char *ukm, const unsigned char *key,size_t keylen, unsigned char *ukm,
size_t ukm_len) size_t ukm_len)
{ {
const struct gost_cipher_info *param=get_encryption_params(NULL); const struct gost_cipher_info *param=get_encryption_params(NULL);
EC_KEY *ephemeral = NULL; EC_KEY *ephemeral = NULL;
@ -260,7 +268,8 @@ GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_ke
EVP_PKEY *newkey=NULL; EVP_PKEY *newkey=NULL;
/* Do not use vizir cipher parameters with cryptopro */ /* Do not use vizir cipher parameters with cryptopro */
if (!getenv("CRYPT_PARAMS") && param == gost_cipher_list) { if (!get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS) && param == gost_cipher_list)
{
param= gost_cipher_list+1; param= gost_cipher_list+1;
} }
ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk),eph_key); ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk),eph_key);
@ -268,21 +277,26 @@ GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_ke
gost_init(&ctx,param->sblock); gost_init(&ctx,param->sblock);
keyWrapCryptoPro(&ctx,shared_key,ukm,key,crypted_key); keyWrapCryptoPro(&ctx,shared_key,ukm,key,crypted_key);
gkt = GOST_KEY_TRANSPORT_new(); gkt = GOST_KEY_TRANSPORT_new();
if (!gkt) { if (!gkt)
{
goto memerr; goto memerr;
} }
if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,
ukm,8)) { ukm,8))
{
goto memerr; goto memerr;
} }
if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4))
{
goto memerr; goto memerr;
} }
if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32))
{
goto memerr; goto memerr;
} }
newkey = ec_ephemeral_key_to_EVP(pubk,NID_id_GostR3410_2001,ephemeral); newkey = ec_ephemeral_key_to_EVP(pubk,NID_id_GostR3410_2001,ephemeral);
if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,newkey)) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,newkey))
{
GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
goto err; goto err;
} }
@ -290,13 +304,13 @@ GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_ke
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
EVP_PKEY_free(newkey); EVP_PKEY_free(newkey);
return gkt; return gkt;
memerr: memerr:
GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001, GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,
GOST_R_MALLOC_FAILURE); GOST_R_MALLOC_FAILURE);
err: err:
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
return NULL; return NULL;
} }
/* /*
* EVP_PKEY_METHOD callback encrypt * EVP_PKEY_METHOD callback encrypt
@ -304,32 +318,34 @@ err:
*/ */
int pkey_GOST01cp_encrypt (EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key,size_t key_len) int pkey_GOST01cp_encrypt (EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len, const unsigned char *key,size_t key_len)
{ {
GOST_KEY_TRANSPORT *gkt=NULL; GOST_KEY_TRANSPORT *gkt=NULL;
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
unsigned char ukm[8]; unsigned char ukm[8];
int ret=0; int ret=0;
if (RAND_bytes(ukm,8)<=0) { if (RAND_bytes(ukm,8)<=0)
{
GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT, GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
GOST_R_RANDOM_GENERATOR_FAILURE); GOST_R_RANDOM_GENERATOR_FAILURE);
return 0; return 0;
} }
if (!(gkt=make_rfc4490_keytransport_2001(pubk,gost_get_priv_key(data->eph_seckey),key, key_len,ukm,8))) { if (!(gkt=make_rfc4490_keytransport_2001(pubk,gost_get_priv_key(data->eph_seckey),key, key_len,ukm,8)))
{
goto err; goto err;
} }
if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret =1; if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret =1;
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
return ret; return ret;
err: err:
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
return -1; return -1;
} }
/* Public, because it would be needed in SSL implementation */ /* Public, because it would be needed in SSL implementation */
int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt, int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
unsigned char *key_buf,int key_buf_len) unsigned char *key_buf,int key_buf_len)
{ {
unsigned char wrappedKey[44]; unsigned char wrappedKey[44];
unsigned char sharedKey[32]; unsigned char sharedKey[32];
gost_ctx ctx; gost_ctx ctx;
@ -347,7 +363,8 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
memcpy(wrappedKey+40,gkt->key_info->imit->data,4); memcpy(wrappedKey+40,gkt->key_info->imit->data,4);
VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)), VKO_compute_key(sharedKey,32,EC_KEY_get0_public_key(EVP_PKEY_get0(eph_key)),
EVP_PKEY_get0(priv),wrappedKey); EVP_PKEY_get0(priv),wrappedKey);
if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key_buf)) { if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key_buf))
{
GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT, GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,
GOST_R_ERROR_COMPUTING_SHARED_KEY); GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err; goto err;
@ -355,31 +372,34 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
EVP_PKEY_free(eph_key); EVP_PKEY_free(eph_key);
return 32; return 32;
err: err:
EVP_PKEY_free(eph_key); EVP_PKEY_free(eph_key);
return -1; return -1;
} }
/* /*
* EVP_PKEY_METHOD callback decrypt * EVP_PKEY_METHOD callback decrypt
* Implementation of GOST2001 key transport, cryptopo variation * Implementation of GOST2001 key transport, cryptopo variation
*/ */
int pkey_GOST01cp_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_len, const unsigned char *in, size_t in_len) { int pkey_GOST01cp_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_len, const unsigned char *in, size_t in_len)
{
const unsigned char *p = in; const unsigned char *p = in;
EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx); EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
GOST_KEY_TRANSPORT *gkt = NULL; GOST_KEY_TRANSPORT *gkt = NULL;
int ret=0; int ret=0;
if (!key) { if (!key)
{
*key_len = 32; *key_len = 32;
return 1; return 1;
} }
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len); in_len);
if (!gkt) { if (!gkt)
{
GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return -1; return -1;
} }
ret = decrypt_rfc4490_shared_key_2001(priv,gkt,key,*key_len); ret = decrypt_rfc4490_shared_key_2001(priv,gkt,key,*key_len);
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
return ret; return ret;
} }

View File

@ -28,7 +28,7 @@ gost_subst_block GostR3411_94_TestParamSet = {
{0X5,0X8,0X1,0XD,0XA,0X3,0X4,0X2,0XE,0XF,0XC,0X7,0X6,0X0,0X9,0XB}, {0X5,0X8,0X1,0XD,0XA,0X3,0X4,0X2,0XE,0XF,0XC,0X7,0X6,0X0,0X9,0XB},
{0XE,0XB,0X4,0XC,0X6,0XD,0XF,0XA,0X2,0X3,0X8,0X1,0X0,0X7,0X5,0X9}, {0XE,0XB,0X4,0XC,0X6,0XD,0XF,0XA,0X2,0X3,0X8,0X1,0X0,0X7,0X5,0X9},
{0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3} {0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3}
}; };
/* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */ /* Substitution blocks for hash function 1.2.643.2.9.1.6.1 */
gost_subst_block GostR3411_94_CryptoProParamSet= { gost_subst_block GostR3411_94_CryptoProParamSet= {
{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC}, {0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
@ -39,11 +39,11 @@ gost_subst_block GostR3411_94_CryptoProParamSet= {
{0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD}, {0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
{0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8}, {0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF} {0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
} ; } ;
/* Test paramset from GOST 28147 */ /* Test paramset from GOST 28147 */
gost_subst_block Gost28147_TestParamSet = gost_subst_block Gost28147_TestParamSet =
{ {
{0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8}, {0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8},
{0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD}, {0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD},
{0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4}, {0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4},
@ -52,7 +52,7 @@ gost_subst_block Gost28147_TestParamSet =
{0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB}, {0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB},
{0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5}, {0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5},
{0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6} {0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6}
}; };
@ -67,10 +67,10 @@ gost_subst_block Gost28147_CryptoProParamSetA= {
{0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9}, {0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9},
{0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1}, {0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1},
{0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5} {0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5}
}; };
/* 1.2.643.2.2.31.2 */ /* 1.2.643.2.2.31.2 */
gost_subst_block Gost28147_CryptoProParamSetB= gost_subst_block Gost28147_CryptoProParamSetB=
{ {
{0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC}, {0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC},
{0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE}, {0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE},
{0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5}, {0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5},
@ -79,10 +79,10 @@ gost_subst_block Gost28147_CryptoProParamSetB=
{0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4}, {0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4},
{0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE}, {0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE},
{0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF} {0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF}
}; };
/* 1.2.643.2.2.31.3 */ /* 1.2.643.2.2.31.3 */
gost_subst_block Gost28147_CryptoProParamSetC= gost_subst_block Gost28147_CryptoProParamSetC=
{ {
{0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8}, {0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8},
{0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7}, {0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7},
{0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD}, {0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD},
@ -91,11 +91,11 @@ gost_subst_block Gost28147_CryptoProParamSetC=
{0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB}, {0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB},
{0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3}, {0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3},
{0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3} {0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3}
}; };
/* 1.2.643.2.2.31.4 */ /* 1.2.643.2.2.31.4 */
gost_subst_block Gost28147_CryptoProParamSetD= gost_subst_block Gost28147_CryptoProParamSetD=
{ {
{0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE}, {0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE},
{0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7}, {0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7},
{0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6}, {0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6},
@ -104,7 +104,7 @@ gost_subst_block Gost28147_CryptoProParamSetD=
{0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2}, {0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2},
{0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1}, {0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1},
{0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3} {0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3}
}; };
const byte CryptoProKeyMeshingKey[]={ const byte CryptoProKeyMeshingKey[]={
@ -112,31 +112,33 @@ const byte CryptoProKeyMeshingKey[]={
0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
}; };
/* Initialization of gost_ctx subst blocks*/ /* Initialization of gost_ctx subst blocks*/
void kboxinit(gost_ctx *c, const gost_subst_block *b) { void kboxinit(gost_ctx *c, const gost_subst_block *b)
{
int i; int i;
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++)
{
c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24; c->k87[i] = (b->k8[i>>4] <<4 | b->k7 [i &15])<<24;
c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16; c->k65[i] = (b->k6[i>>4] << 4 | b->k5 [i &15])<<16;
c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8; c->k43[i] = (b->k4[i>>4] <<4 | b->k3 [i &15])<<8;
c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15]; c->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15];
} }
} }
/* Part of GOST 28147 algorithm moved into separate function */ /* Part of GOST 28147 algorithm moved into separate function */
static word32 static word32 f(gost_ctx *c,word32 x)
f(gost_ctx *c,word32 x) {
{ x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]| x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
c->k43[x>> 8 & 255] | c->k21[x & 255]; c->k43[x>> 8 & 255] | c->k21[x & 255];
/* Rotate left 11 bits */ /* Rotate left 11 bits */
return x<<11 | x>>(32-11); return x<<11 | x>>(32-11);
} }
/* Low-level encryption routine - encrypts one 64 bit block*/ /* Low-level encryption routine - encrypts one 64 bit block*/
void gostcrypt(gost_ctx *c, const byte *in, byte *out) void gostcrypt(gost_ctx *c, const byte *in, byte *out)
{ {
register word32 n1, n2; /* As named in the GOST */ register word32 n1, n2; /* As named in the GOST */
n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
@ -164,10 +166,10 @@ void gostcrypt(gost_ctx *c, const byte *in, byte *out)
out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24; out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24; out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
} }
/* Low-level decryption routine. Decrypts one 64-bit block */ /* Low-level decryption routine. Decrypts one 64-bit block */
void gostdecrypt(gost_ctx *c, const byte *in,byte *out) void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
{ {
register word32 n1, n2; /* As named in the GOST */ register word32 n1, n2; /* As named in the GOST */
n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24); n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24); n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
@ -193,102 +195,113 @@ void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]); n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24; out[0] = (n2&0xff); out[1] = (n2>>8)&0xff; out[2]=(n2>>16)&0xff; out[3]=n2>>24;
out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24; out[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>24;
} }
/* Encrypts several blocks in ECB mode */ /* Encrypts several blocks in ECB mode */
void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks) void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
{ {
int i; int i;
for(i=0;i<blocks;i++){ for(i=0;i<blocks;i++)
{
gostcrypt(c,clear,cipher); gostcrypt(c,clear,cipher);
clear+=8; clear+=8;
cipher+=8; cipher+=8;
} }
} }
/* Decrypts several blocks in ECB mode */ /* Decrypts several blocks in ECB mode */
void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks) void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
{ {
int i; int i;
for(i=0;i<blocks;i++) { for(i=0;i<blocks;i++)
{
gostdecrypt(c,cipher,clear); gostdecrypt(c,cipher,clear);
clear+=8; clear+=8;
cipher+=8; cipher+=8;
} }
}
}
/* Encrypts several full blocks in CFB mode using 8byte IV */ /* Encrypts several full blocks in CFB mode using 8byte IV */
void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks) { void gost_enc_cfb(gost_ctx *ctx,const byte *iv,const byte *clear,byte *cipher, int blocks)
{
byte cur_iv[8]; byte cur_iv[8];
byte gamma[8]; byte gamma[8];
int i,j; int i,j;
const byte *in; const byte *in;
byte *out; byte *out;
memcpy(cur_iv,iv,8); memcpy(cur_iv,iv,8);
for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8) { for(i=0,in=clear,out=cipher;i<blocks;i++,in+=8,out+=8)
{
gostcrypt(ctx,cur_iv,gamma); gostcrypt(ctx,cur_iv,gamma);
for (j=0;j<8;j++) { for (j=0;j<8;j++)
{
cur_iv[j]=out[j]=in[j]^gamma[j]; cur_iv[j]=out[j]=in[j]^gamma[j];
} }
} }
}
}
/* Decrypts several full blocks in CFB mode using 8byte IV */ /* Decrypts several full blocks in CFB mode using 8byte IV */
void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks) { void gost_dec_cfb(gost_ctx *ctx,const byte *iv,const byte *cipher,byte *clear, int blocks)
{
byte cur_iv[8]; byte cur_iv[8];
byte gamma[8]; byte gamma[8];
int i,j; int i,j;
const byte *in; const byte *in;
byte *out; byte *out;
memcpy(cur_iv,iv,8); memcpy(cur_iv,iv,8);
for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8) { for(i=0,in=cipher,out=clear;i<blocks;i++,in+=8,out+=8)
{
gostcrypt(ctx,cur_iv,gamma); gostcrypt(ctx,cur_iv,gamma);
for (j=0;j<8;j++) { for (j=0;j<8;j++)
{
out[j]=(cur_iv[j]=in[j])^gamma[j]; out[j]=(cur_iv[j]=in[j])^gamma[j];
} }
} }
} }
/* Encrypts one block using specified key */ /* Encrypts one block using specified key */
void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock) void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock)
{ {
gost_key(c,key); gost_key(c,key);
gostcrypt(c,inblock,outblock); gostcrypt(c,inblock,outblock);
}
}
/* Set 256 bit key into context */ /* Set 256 bit key into context */
void gost_key(gost_ctx *c, const byte *k) void gost_key(gost_ctx *c, const byte *k)
{ {
int i,j; int i,j;
for(i=0,j=0;i<8;i++,j+=4) { for(i=0,j=0;i<8;i++,j+=4)
{
c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24); c->k[i]=k[j]|(k[j+1]<<8)|(k[j+2]<<16)|(k[j+3]<<24);
} }
} }
/* Retrieve 256-bit key from context */ /* Retrieve 256-bit key from context */
void gost_get_key(gost_ctx *c, byte *k) void gost_get_key(gost_ctx *c, byte *k)
{ {
int i,j; int i,j;
for(i=0,j=0;i<8;i++,j+=4) { for(i=0,j=0;i<8;i++,j+=4)
{
k[j]=c->k[i]& 0xFF; k[j]=c->k[i]& 0xFF;
k[j+1]=(c->k[i]>>8 )&0xFF; k[j+1]=(c->k[i]>>8 )&0xFF;
k[j+2]=(c->k[i]>>16) &0xFF; k[j+2]=(c->k[i]>>16) &0xFF;
k[j+3]=(c->k[i]>>24) &0xFF; k[j+3]=(c->k[i]>>24) &0xFF;
} }
}
}
/* Initalize context. Provides default value for subst_block */ /* Initalize context. Provides default value for subst_block */
void gost_init(gost_ctx *c, const gost_subst_block *b) void gost_init(gost_ctx *c, const gost_subst_block *b)
{ {
if(!b) { if(!b)
{
b=&GostR3411_94_TestParamSet; b=&GostR3411_94_TestParamSet;
} }
kboxinit(c,b); kboxinit(c,b);
} }
/* Cleans up key from context */ /* Cleans up key from context */
void gost_destroy(gost_ctx *c) void gost_destroy(gost_ctx *c)
{ {
int i; for(i=0;i<8;i++) c->k[i]=0; int i; for(i=0;i<8;i++) c->k[i]=0;
} }
/* Compute GOST 28147 mac block /* Compute GOST 28147 mac block
* *
@ -297,11 +310,12 @@ void gost_destroy(gost_ctx *c)
* buffer - 8-byte mac state buffer * buffer - 8-byte mac state buffer
* block 8-byte block to process. * block 8-byte block to process.
* */ * */
void mac_block(gost_ctx *c,byte *buffer,const byte *block) { void mac_block(gost_ctx *c,byte *buffer,const byte *block)
{
register word32 n1, n2; /* As named in the GOST */ register word32 n1, n2; /* As named in the GOST */
int i; int i;
for (i=0; i<8; i++) { for (i=0; i<8; i++)
{
buffer[i]^=block[i]; buffer[i]^=block[i];
} }
n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24); n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24);
@ -320,57 +334,62 @@ void mac_block(gost_ctx *c,byte *buffer,const byte *block) {
buffer[0] = (n1&0xff); buffer[1] = (n1>>8)&0xff; buffer[2]=(n1>>16)&0xff; buffer[3]=n1>>24; buffer[0] = (n1&0xff); buffer[1] = (n1>>8)&0xff; buffer[2]=(n1>>16)&0xff; buffer[3]=n1>>24;
buffer[4] = (n2&0xff); buffer[5] = (n2>>8)&0xff; buffer[6]=(n2>>16)&0xff; buffer[7]=n2>>24; buffer[4] = (n2&0xff); buffer[5] = (n2>>8)&0xff; buffer[6]=(n2>>16)&0xff; buffer[7]=n2>>24;
} }
/* Get mac with specified number of bits from MAC state buffer */ /* Get mac with specified number of bits from MAC state buffer */
void get_mac(byte *buffer,int nbits,byte *out) { void get_mac(byte *buffer,int nbits,byte *out)
{
int nbytes= nbits >> 3; int nbytes= nbits >> 3;
int rembits = nbits & 7; int rembits = nbits & 7;
int mask =rembits?((1<rembits)-1):0; int mask =rembits?((1<rembits)-1):0;
int i; int i;
for (i=0;i<nbytes;i++) out[i]=buffer[i]; for (i=0;i<nbytes;i++) out[i]=buffer[i];
if (rembits) out[i]=buffer[i]&mask; if (rembits) out[i]=buffer[i]&mask;
} }
/* Compute mac of specified length (in bits) from data. /* Compute mac of specified length (in bits) from data.
* Context should be initialized with key and subst blocks */ * Context should be initialized with key and subst blocks */
int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data, int gost_mac(gost_ctx *ctx,int mac_len,const unsigned char *data,
unsigned int data_len,unsigned char *mac) unsigned int data_len,unsigned char *mac)
{ {
byte buffer[8]={0,0,0,0,0,0,0,0}; byte buffer[8]={0,0,0,0,0,0,0,0};
byte buf2[8]; byte buf2[8];
int i; int i;
for (i=0;i+8<=data_len;i+=8) for (i=0;i+8<=data_len;i+=8)
mac_block(ctx,buffer,data+i); mac_block(ctx,buffer,data+i);
if (i<data_len) { if (i<data_len)
{
memset(buf2,0,8); memset(buf2,0,8);
memcpy(buf2,data+i,data_len-i); memcpy(buf2,data+i,data_len-i);
mac_block(ctx,buffer,buf2); mac_block(ctx,buffer,buf2);
} }
get_mac(buffer,mac_len,mac); get_mac(buffer,mac_len,mac);
return 1; return 1;
} }
/* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */ /* Compute MAC with non-zero IV. Used in some RFC 4357 algorithms */
int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data, int gost_mac_iv(gost_ctx *ctx,int mac_len,const unsigned char *iv,const unsigned char *data,
unsigned int data_len,unsigned char *mac) unsigned int data_len,unsigned char *mac)
{ {
byte buffer[8]; byte buffer[8];
byte buf2[8]; byte buf2[8];
int i; int i;
memcpy (buffer,iv,8); memcpy (buffer,iv,8);
for (i=0;i+8<=data_len;i+=8) for (i=0;i+8<=data_len;i+=8)
mac_block(ctx,buffer,data+i); mac_block(ctx,buffer,data+i);
if (i<data_len) { if (i<data_len)
{
memset(buf2,0,8); memset(buf2,0,8);
memcpy(buf2,data+i,data_len-i); memcpy(buf2,data+i,data_len-i);
mac_block(ctx,buffer,buf2); mac_block(ctx,buffer,buf2);
} }
get_mac(buffer,mac_len,mac); get_mac(buffer,mac_len,mac);
return 1; return 1;
} }
/* Implements key meshing algorithm by modifing ctx and IV in place */ /* Implements key meshing algorithm by modifing ctx and IV in place */
void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) { void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv)
{
unsigned char newkey[32],newiv[8]; unsigned char newkey[32],newiv[8];
/* Set static keymeshing key */ /* Set static keymeshing key */
/* "Decrypt" key with keymeshing key */ /* "Decrypt" key with keymeshing key */
@ -380,4 +399,4 @@ void cryptopro_key_meshing(gost_ctx *ctx, unsigned char *iv) {
/* Encrypt iv with new key */ /* Encrypt iv with new key */
gostcrypt(ctx,iv,newiv); gostcrypt(ctx,iv,newiv);
memcpy(iv,newiv,8); memcpy(iv,newiv,8);
} }

View File

@ -14,24 +14,21 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/objects.h> #include <openssl/objects.h>
#include "gostkeyx.h"
#include "gost_asn1.h"
#include "gost89.h" #include "gost89.h"
#include "gosthash.h" #include "gosthash.h"
#include "crypt.h"
#include "e_gost_err.h" #include "e_gost_err.h"
#include "pmeth.h" #include "gost_keywrap.h"
#include "keywrap.h" #include "gost_lcl.h"
#include "tools.h"
/* Common functions for both 94 and 2001 key exchange schemes */ /* Common functions for both 94 and 2001 key exchange schemes */
int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len, int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len,
const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx) const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx)
{ {
int i; int i;
int j; int j;
int blocks = crypted_key_len >>3; int blocks = crypted_key_len >>3;
unsigned char gamma[8]; unsigned char gamma[8];
if (max_key_len <crypted_key_len) { if (max_key_len <crypted_key_len)
{
GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_NOT_ENOUGH_SPACE_FOR_KEY); GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_NOT_ENOUGH_SPACE_FOR_KEY);
return 0; return 0;
} }
@ -54,10 +51,10 @@ int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len,
sess_key[j]=gamma[j]^crypted_key[j]; sess_key[j]=gamma[j]^crypted_key[j];
} }
return 1; return 1;
} }
int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len, int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
unsigned char *crypted_key, gost_ctx *ctx) unsigned char *crypted_key, gost_ctx *ctx)
{ {
int i; int i;
int j; int j;
unsigned char gamma[8]; unsigned char gamma[8];
@ -69,7 +66,7 @@ int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
gamma[j]=crypted_key[i+j]=sess_key[i+j]^gamma[j]; gamma[j]=crypted_key[i+j]=sess_key[i+j]^gamma[j];
} }
return 1; return 1;
} }
/* Implementation of the Diffi-Hellman key agreement scheme based on /* Implementation of the Diffi-Hellman key agreement scheme based on
* GOST-94 keys */ * GOST-94 keys */
@ -78,23 +75,24 @@ int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
* algorigthm * algorigthm
*/ */
static int compute_pair_key_le(unsigned char *pair_key,BIGNUM *pub_key,DH *dh) static int compute_pair_key_le(unsigned char *pair_key,BIGNUM *pub_key,DH *dh)
{ {
unsigned char be_key[128]; unsigned char be_key[128];
int i,key_size; int i,key_size;
key_size=DH_compute_key(be_key,pub_key,dh); key_size=DH_compute_key(be_key,pub_key,dh);
if (!key_size) return 0; if (!key_size) return 0;
memset(pair_key,0,128); memset(pair_key,0,128);
for (i=0;i<key_size;i++) { for (i=0;i<key_size;i++)
{
pair_key[i]=be_key[key_size-1-i]; pair_key[i]=be_key[key_size-1-i];
} }
return key_size; return key_size;
} }
/* /*
* Computes 256 bit key exchange key for CryptoCom variation of GOST 94 * Computes 256 bit key exchange key for CryptoCom variation of GOST 94
* algorithm * algorithm
*/ */
static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key) static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key)
{ {
unsigned char dh_key [128]; unsigned char dh_key [128];
int i; int i;
/* Compute key */ /* Compute key */
@ -106,33 +104,38 @@ static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key)
*/ */
if (DH_size(dh)==128) if (DH_size(dh)==128)
for (i=0;i<64;i++) { {
for (i=0;i<64;i++)
{
dh_key[i]^=dh_key[64+i]; dh_key[i]^=dh_key[64+i];
} }
for (i=0;i<32;i++) { }
for (i=0;i<32;i++)
{
shared_key[i]=dh_key[i]^dh_key[32+i]; shared_key[i]=dh_key[i]^dh_key[32+i];
} }
return 1; return 1;
} }
static DH *make_ephemeral_key(EVP_PKEY *pubk,BIGNUM *ephemeral_key) static DH *make_ephemeral_key(EVP_PKEY *pubk,BIGNUM *ephemeral_key)
{ {
DH *dh = DH_new(); DH *dh = DH_new();
dh->g = BN_dup(pubk->pkey.dsa->g); dh->g = BN_dup(pubk->pkey.dsa->g);
dh->p = BN_dup(pubk->pkey.dsa->p); dh->p = BN_dup(pubk->pkey.dsa->p);
dh->priv_key = BN_dup(ephemeral_key); dh->priv_key = BN_dup(ephemeral_key);
/* Generate ephemeral key pair */ /* Generate ephemeral key pair */
if (!DH_generate_key(dh)) { if (!DH_generate_key(dh))
{
DH_free(dh); DH_free(dh);
return NULL; return NULL;
} }
return dh; return dh;
} }
/* /*
* Computes 256 bit Key exchange key as specified in RFC 4357 * Computes 256 bit Key exchange key as specified in RFC 4357
*/ */
static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key) static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key)
{ {
unsigned char dh_key [128]; unsigned char dh_key [128];
gost_hash_ctx hash_ctx; gost_hash_ctx hash_ctx;
memset(dh_key,0,128); memset(dh_key,0,128);
@ -143,13 +146,14 @@ static int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key
finish_hash(&hash_ctx,shared_key); finish_hash(&hash_ctx,shared_key);
done_gost_hash_ctx(&hash_ctx); done_gost_hash_ctx(&hash_ctx);
return 1; return 1;
} }
/* EVP_PKEY_METHOD callback encrypt for /* EVP_PKEY_METHOD callback encrypt for
* GOST R 34.10-94 cryptopro modification * GOST R 34.10-94 cryptopro modification
*/ */
int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len ) int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len )
{ {
GOST_KEY_TRANSPORT *gkt=NULL; GOST_KEY_TRANSPORT *gkt=NULL;
DH *dh = NULL; DH *dh = NULL;
unsigned char shared_key[32], ukm[8],crypted_key[44]; unsigned char shared_key[32], ukm[8],crypted_key[44];
@ -159,8 +163,8 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
int size=-1; int size=-1;
gost_ctx cctx; gost_ctx cctx;
if (!(data->eph_seckey))
if (!(data->eph_seckey)) { {
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT); GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
return -1; return -1;
@ -169,54 +173,62 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey)); dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey));
gost_init(&cctx,param->sblock); gost_init(&cctx,param->sblock);
make_cp_exchange_key(dh,pubk,shared_key); make_cp_exchange_key(dh,pubk,shared_key);
if (RAND_bytes(ukm,8)<=0) { if (RAND_bytes(ukm,8)<=0)
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_RANDOM_GENERATOR_FAILURE); GOST_R_RANDOM_GENERATOR_FAILURE);
return -1; return -1;
} }
keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key); keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key);
gkt = GOST_KEY_TRANSPORT_new(); gkt = GOST_KEY_TRANSPORT_new();
if (!gkt) { if (!gkt)
{
goto memerr; goto memerr;
} }
if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,
ukm,8)) { ukm,8))
{
goto memerr; goto memerr;
} }
if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4)) { if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,crypted_key+40,4))
{
goto memerr; goto memerr;
} }
if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32)) { if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,crypted_key+8,32))
{
goto memerr; goto memerr;
} }
if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey)) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey))
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
goto err; goto err;
} }
ASN1_OBJECT_free(gkt->key_agreement_info->cipher); ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
*outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out);
if (!size) { if (!size)
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO);
size=-1; size=-1;
} }
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh); DH_free(dh);
return 1; return 1;
memerr: memerr:
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_MALLOC_FAILURE); GOST_R_MALLOC_FAILURE);
err: err:
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh); DH_free(dh);
return -1; return -1;
} }
/* EVP_PKEY_METHOD callback encrypt for /* EVP_PKEY_METHOD callback encrypt for
* GOST R 34.10-94 cryptocom modification * GOST R 34.10-94 cryptocom modification
*/ */
int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len) int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len)
{ {
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
/* create DH structure filling parameters from passed pub_key */ /* create DH structure filling parameters from passed pub_key */
@ -227,7 +239,8 @@ int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen
unsigned char shared_key[32],encrypted_key[32],hmac[4], unsigned char shared_key[32],encrypted_key[32],hmac[4],
iv[8]={0,0,0,0,0,0,0,0}; iv[8]={0,0,0,0,0,0,0,0};
if (! data->eph_seckey) { if (! data->eph_seckey)
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT); GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
return -1; return -1;
@ -274,19 +287,20 @@ int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY); GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY);
goto err; goto err;
} }
if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey)) { if (!X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,data->eph_seckey))
{
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY); GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
goto err; goto err;
} }
ASN1_OBJECT_free(gkt->key_agreement_info->cipher); ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(NID_id_Gost28147_89_cc); gkt->key_agreement_info->cipher = OBJ_nid2obj(NID_id_Gost28147_89_cc);
*outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out); *outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out);
err: err:
if (gkt) GOST_KEY_TRANSPORT_free(gkt); if (gkt) GOST_KEY_TRANSPORT_free(gkt);
if (dh) DH_free(dh); if (dh) DH_free(dh);
if (newkey) EVP_PKEY_free(newkey); if (newkey) EVP_PKEY_free(newkey);
return 1; return 1;
} }
/* EVP_PLEY_METHOD callback decrypt for /* EVP_PLEY_METHOD callback decrypt for
* GOST R 34.10-94 cryptopro modification * GOST R 34.10-94 cryptopro modification
@ -302,7 +316,8 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
EVP_PKEY *eph_key=NULL; EVP_PKEY *eph_key=NULL;
EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx);
if (!key) { if (!key)
{
*key_len = 32; *key_len = 32;
return 1; return 1;
} }
@ -312,7 +327,8 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
dh->priv_key = BN_dup(priv->pkey.dsa->priv_key); dh->priv_key = BN_dup(priv->pkey.dsa->priv_key);
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len); in_len);
if (!gkt) { if (!gkt)
{
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
DH_free(dh); DH_free(dh);
return 0; return 0;
@ -327,7 +343,8 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
OPENSSL_assert(gkt->key_info->imit->length==4); OPENSSL_assert(gkt->key_info->imit->length==4);
memcpy(wrappedKey+40,gkt->key_info->imit->data,4); memcpy(wrappedKey+40,gkt->key_info->imit->data,4);
make_cp_exchange_key(dh,eph_key,sharedKey); make_cp_exchange_key(dh,eph_key,sharedKey);
if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key)) { if (!keyUnwrapCryptoPro(&cctx,sharedKey,wrappedKey,key))
{
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT, GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,
GOST_R_ERROR_COMPUTING_SHARED_KEY); GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err; goto err;
@ -342,14 +359,14 @@ err:
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh); DH_free(dh);
return -1; return -1;
}
}
/* EVP_PKEY_METHOD callback decrypt for /* EVP_PKEY_METHOD callback decrypt for
* GOST R 34.10-94 cryptocom modification * GOST R 34.10-94 cryptocom modification
*/ */
int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len) int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len, const unsigned char *in, size_t in_len)
{ {
/* Form DH params from compute shared key */ /* Form DH params from compute shared key */
GOST_KEY_TRANSPORT *gkt = NULL; GOST_KEY_TRANSPORT *gkt = NULL;
const unsigned char *p=in; const unsigned char *p=in;
@ -362,7 +379,8 @@ int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
EVP_PKEY *eph_key; EVP_PKEY *eph_key;
EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx); EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
if (!key) { if (!key)
{
*key_len = 32; *key_len = 32;
return 1; return 1;
} }
@ -373,7 +391,8 @@ int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
/* Parse passed octet string and find out public key, iv and HMAC*/ /* Parse passed octet string and find out public key, iv and HMAC*/
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p, gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len); in_len);
if (!gkt) { if (!gkt)
{
GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO); GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
DH_free(dh); DH_free(dh);
return 0; return 0;
@ -407,14 +426,16 @@ int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
} }
GOST_KEY_TRANSPORT_free(gkt); GOST_KEY_TRANSPORT_free(gkt);
/* check HMAC of session key*/ /* check HMAC of session key*/
if (!gost_mac(&ctx,32,key,32,hmac_comp)) { if (!gost_mac(&ctx,32,key,32,hmac_comp))
{
GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC); GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_MAC);
return 0; return 0;
} }
/* HMAC of session key is not correct */ /* HMAC of session key is not correct */
if (memcmp(hmac,hmac_comp,4)!=0) { if (memcmp(hmac,hmac_comp,4)!=0)
{
GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH); GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH);
return 0; return 0;
} }
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
/********************************************************************** /**********************************************************************
* ameth.c * * gost_ameth.c *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *
@ -10,20 +10,16 @@
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <string.h> #include <string.h>
#include "meth.h" #include "gost_params.h"
#include "pmeth.h" #include "gost_lcl.h"
#include "paramset.h"
#include "gost_asn1.h"
#include "crypt.h"
#include "sign.h"
#include "tools.h"
#include "e_gost_err.h" #include "e_gost_err.h"
int gost94_nid_by_params(DSA *p) int gost94_nid_by_params(DSA *p)
{ {
R3410_params *gost_params; R3410_params *gost_params;
BIGNUM *q=BN_new(); BIGNUM *q=BN_new();
for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++) { for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++)
{
BN_dec2bn(&q,gost_params->q); BN_dec2bn(&q,gost_params->q);
if (!BN_cmp(q,p->q)) if (!BN_cmp(q,p->q))
{ {
@ -33,22 +29,24 @@ int gost94_nid_by_params(DSA *p)
} }
BN_free(q); BN_free(q);
return NID_undef; return NID_undef;
} }
static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key) static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
{ {
ASN1_STRING *params = ASN1_STRING_new(); ASN1_STRING *params = ASN1_STRING_new();
GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new(); GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
int pkey_param_nid = NID_undef; int pkey_param_nid = NID_undef;
int cipher_param_nid = NID_undef; int cipher_param_nid = NID_undef;
if (!params || !gkp) { if (!params || !gkp)
{
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
ERR_R_MALLOC_FAILURE); ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params); ASN1_STRING_free(params);
params = NULL; params = NULL;
goto err; goto err;
} }
switch (EVP_PKEY_base_id(key)) { switch (EVP_PKEY_base_id(key))
{
case NID_id_GostR3410_2001_cc: case NID_id_GostR3410_2001_cc:
pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc; pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
cipher_param_nid = NID_id_Gost28147_89_cc; cipher_param_nid = NID_id_Gost28147_89_cc;
@ -63,7 +61,8 @@ static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
break; break;
case NID_id_GostR3410_94: case NID_id_GostR3410_94:
pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key)); pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
if (pkey_param_nid == NID_undef) { if (pkey_param_nid == NID_undef)
{
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS, GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
GOST_R_INVALID_GOST94_PARMSET); GOST_R_INVALID_GOST94_PARMSET);
ASN1_STRING_free(params); ASN1_STRING_free(params);
@ -86,15 +85,16 @@ static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
goto err; goto err;
} }
params ->type = V_ASN1_SEQUENCE; params ->type = V_ASN1_SEQUENCE;
err: err:
GOST_KEY_PARAMS_free(gkp); GOST_KEY_PARAMS_free(gkp);
return params; return params;
} }
/* Parses GOST algorithm parameters from X509_ALGOR and /* Parses GOST algorithm parameters from X509_ALGOR and
* modifies pkey setting NID and parameters * modifies pkey setting NID and parameters
*/ */
static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
{ {
ASN1_OBJECT *palg_obj =NULL; ASN1_OBJECT *palg_obj =NULL;
int ptype = V_ASN1_UNDEF; int ptype = V_ASN1_UNDEF;
int pkey_nid = NID_undef,param_nid = NID_undef; int pkey_nid = NID_undef,param_nid = NID_undef;
@ -103,7 +103,8 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
GOST_KEY_PARAMS *gkp = NULL; GOST_KEY_PARAMS *gkp = NULL;
X509_ALGOR_get0(&palg_obj, &ptype, (void **) (&pval), palg); X509_ALGOR_get0(&palg_obj, &ptype, (void **) (&pval), palg);
if (ptype != V_ASN1_SEQUENCE) { if (ptype != V_ASN1_SEQUENCE)
{
GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
GOST_R_BAD_KEY_PARAMETERS_FORMAT); GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0; return 0;
@ -112,18 +113,22 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
pkey_nid = OBJ_obj2nid(palg_obj); pkey_nid = OBJ_obj2nid(palg_obj);
gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length); gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length);
if (!gkp) { if (!gkp)
{
GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS,
GOST_R_BAD_PKEY_PARAMETERS_FORMAT); GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
} }
param_nid = OBJ_obj2nid(gkp->key_params); param_nid = OBJ_obj2nid(gkp->key_params);
GOST_KEY_PARAMS_free(gkp); GOST_KEY_PARAMS_free(gkp);
EVP_PKEY_set_type(pkey,pkey_nid); EVP_PKEY_set_type(pkey,pkey_nid);
switch (pkey_nid) { switch (pkey_nid)
{
case NID_id_GostR3410_94: case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc: case NID_id_GostR3410_94_cc:
{ DSA *dsa= EVP_PKEY_get0(pkey); {
if (!dsa) { DSA *dsa= EVP_PKEY_get0(pkey);
if (!dsa)
{
dsa = DSA_new(); dsa = DSA_new();
if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0; if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0;
} }
@ -132,27 +137,30 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
} }
case NID_id_GostR3410_2001: case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc: case NID_id_GostR3410_2001_cc:
{ EC_KEY *ec = EVP_PKEY_get0(pkey); {
if (!ec) { EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
{
ec = EC_KEY_new(); ec = EC_KEY_new();
if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0; if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
} }
if (!fill_GOST2001_params(ec,param_nid)) return 0; if (!fill_GOST2001_params(ec,param_nid)) return 0;
} }
} }
return 1; return 1;
} }
static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv) static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
{ {
switch (EVP_PKEY_base_id(pkey)) { switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94: case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc: case NID_id_GostR3410_94_cc:
{ DSA *dsa = EVP_PKEY_get0(pkey); {
if (!dsa) { DSA *dsa = EVP_PKEY_get0(pkey);
if (!dsa)
{
dsa = DSA_new(); dsa = DSA_new();
EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa); EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa);
} }
@ -163,8 +171,10 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
} }
case NID_id_GostR3410_2001: case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc: case NID_id_GostR3410_2001_cc:
{ EC_KEY *ec = EVP_PKEY_get0(pkey); {
if (!ec) { EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
{
ec = EC_KEY_new(); ec = EC_KEY_new();
EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec); EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec);
} }
@ -173,17 +183,19 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
gost2001_compute_public(ec); gost2001_compute_public(ec);
break; break;
} }
} }
return 1; return 1;
} }
BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
{ {
switch (EVP_PKEY_base_id(pkey)) { switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94: case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc: case NID_id_GostR3410_94_cc:
{ DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey); {
if (!dsa) { DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
if (!dsa)
{
return NULL; return NULL;
} }
if (!dsa->priv_key) return NULL; if (!dsa->priv_key) return NULL;
@ -192,33 +204,37 @@ BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
} }
case NID_id_GostR3410_2001: case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc: case NID_id_GostR3410_2001_cc:
{ EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey); {
EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
const BIGNUM* priv; const BIGNUM* priv;
if (!ec) { if (!ec)
{
return NULL; return NULL;
} }
if (!(priv=EC_KEY_get0_private_key(ec))) return NULL; if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
return BN_dup(priv); return BN_dup(priv);
break; break;
} }
} }
return NULL; return NULL;
} }
static int pkey_ctrl_gost(EVP_PKEY *pkey, int op, static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
long arg1, void *arg2) long arg1, void *arg2)
{ {
switch (op) switch (op)
{ {
case ASN1_PKEY_CTRL_PKCS7_SIGN: case ASN1_PKEY_CTRL_PKCS7_SIGN:
if (arg1 == 0) { if (arg1 == 0)
{
X509_ALGOR *alg1 = NULL, *alg2 = NULL; X509_ALGOR *alg1 = NULL, *alg2 = NULL;
int nid = EVP_PKEY_base_id(pkey); int nid = EVP_PKEY_base_id(pkey);
PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2, PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2,
NULL, &alg1, &alg2); NULL, &alg1, &alg2);
X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94), X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
V_ASN1_NULL, 0); V_ASN1_NULL, 0);
if (nid == NID_undef) { if (nid == NID_undef)
{
return (-1); return (-1);
} }
X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0); X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
@ -229,7 +245,8 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
{ {
X509_ALGOR *alg; X509_ALGOR *alg;
ASN1_STRING * params = encode_gost_algor_params(pkey); ASN1_STRING * params = encode_gost_algor_params(pkey);
if (!params) { if (!params)
{
return -1; return -1;
} }
PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg); PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg);
@ -243,21 +260,27 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
} }
return -2; return -2;
} }
/*----------------------- free functions * ------------------------------*/ /*----------------------- free functions * ------------------------------*/
static void pkey_free_gost94(EVP_PKEY *key) { static void pkey_free_gost94(EVP_PKEY *key)
if (key->pkey.dsa) { {
if (key->pkey.dsa)
{
DSA_free(key->pkey.dsa); DSA_free(key->pkey.dsa);
} }
} }
static void pkey_free_gost01(EVP_PKEY *key) {
if (key->pkey.ec) { static void pkey_free_gost01(EVP_PKEY *key)
{
if (key->pkey.ec)
{
EC_KEY_free(key->pkey.ec); EC_KEY_free(key->pkey.ec);
} }
} }
/* ------------------ private key functions -----------------------------*/ /* ------------------ private key functions -----------------------------*/
static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
{ {
const unsigned char *pkey_buf = NULL,*p=NULL; const unsigned char *pkey_buf = NULL,*p=NULL;
int priv_len = 0; int priv_len = 0;
BIGNUM *pk_num=NULL; BIGNUM *pk_num=NULL;
@ -269,25 +292,48 @@ static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
if (!PKCS8_pkey_get0(&palg_obj,&pkey_buf,&priv_len,&palg,p8inf)) if (!PKCS8_pkey_get0(&palg_obj,&pkey_buf,&priv_len,&palg,p8inf))
return 0; return 0;
p = pkey_buf; p = pkey_buf;
if (!decode_gost_algor_params(pk,palg)) { if (!decode_gost_algor_params(pk,palg))
{
return 0; return 0;
} }
priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len); if (V_ASN1_OCTET_STRING == *p)
if (!priv_key) { {
} /* New format - Little endian octet string */
unsigned char rev_buf[32];
if (!(pk_num = ASN1_INTEGER_to_BN(priv_key, NULL))) { int i;
ASN1_OCTET_STRING *s = d2i_ASN1_OCTET_STRING(NULL,&p,priv_len);
if (!s||s->length !=32)
{
GOSTerr(GOST_F_PRIV_DECODE_GOST_94, GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
EVP_R_DECODE_ERROR); EVP_R_DECODE_ERROR);
return 0;
}
for (i=0;i<32;i++)
{
rev_buf[31-i]=s->data[i];
}
ASN1_STRING_free(s);
pk_num = getbnfrombuf(rev_buf,32);
}
else
{
priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
if (!priv_key || !(pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)))
{
GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
EVP_R_DECODE_ERROR);
return 0;
}
} }
ret= gost_set_priv_key(pk,pk_num); ret= gost_set_priv_key(pk,pk_num);
BN_free(pk_num); BN_free(pk_num);
return ret; return ret;
} }
/* ----------------------------------------------------------------------*/ /* ----------------------------------------------------------------------*/
static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) 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_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
ASN1_STRING *params = encode_gost_algor_params(pk); ASN1_STRING *params = encode_gost_algor_params(pk);
unsigned char *priv_buf = NULL; unsigned char *priv_buf = NULL;
@ -295,7 +341,8 @@ static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
BIGNUM *key; BIGNUM *key;
ASN1_INTEGER *asn1key=NULL; ASN1_INTEGER *asn1key=NULL;
if (!params) { if (!params)
{
return 0; return 0;
} }
key = gost_get_priv_key(pk); key = gost_get_priv_key(pk);
@ -305,11 +352,11 @@ static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
ASN1_INTEGER_free(asn1key); ASN1_INTEGER_free(asn1key);
return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params, return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
priv_buf,priv_len); priv_buf,priv_len);
} }
static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent, static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx) ASN1_PCTX *pctx)
{ {
BIGNUM *key; BIGNUM *key;
if (!BIO_indent(out,indent,128)) return 0; if (!BIO_indent(out,indent,128)) return 0;
key = gost_get_priv_key(pkey); key = gost_get_priv_key(pkey);
@ -317,25 +364,27 @@ static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
BN_print(out,key); BN_print(out,key);
BN_free(key); BN_free(key);
return 1; return 1;
} }
/* ---------------------------------------------------------------------*/ /* ---------------------------------------------------------------------*/
static int param_missing_gost94(const EVP_PKEY *pk) static int param_missing_gost94(const EVP_PKEY *pk)
{ {
const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk); const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
if (!dsa) return 1; if (!dsa) return 1;
if (!dsa->q) return 1; if (!dsa->q) return 1;
return 0; return 0;
} }
static int param_missing_gost01(const EVP_PKEY *pk) static int param_missing_gost01(const EVP_PKEY *pk)
{ {
const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk); const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
if (!ec) return 1; if (!ec) return 1;
if (!EC_KEY_get0_group(ec)) return 1; if (!EC_KEY_get0_group(ec)) return 1;
return 0; return 0;
} }
static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from) static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
{ {
const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from); const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
DSA *dto = EVP_PKEY_get0(to); DSA *dto = EVP_PKEY_get0(to);
if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to))
@ -363,50 +412,58 @@ static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
if (dto->priv_key) if (dto->priv_key)
gost94_compute_public(dto); gost94_compute_public(dto);
return 1; return 1;
} }
static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) { static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
{
EC_KEY *eto = EVP_PKEY_get0(to); EC_KEY *eto = EVP_PKEY_get0(to);
const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from); const EC_KEY *efrom = EVP_PKEY_get0((EVP_PKEY *)from);
if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to))
{
GOSTerr(GOST_F_PARAM_COPY_GOST01, GOSTerr(GOST_F_PARAM_COPY_GOST01,
GOST_R_INCOMPATIBLE_ALGORITHMS); GOST_R_INCOMPATIBLE_ALGORITHMS);
return 0; return 0;
} }
if (!efrom) { if (!efrom)
{
GOSTerr(GOST_F_PARAM_COPY_GOST94, GOSTerr(GOST_F_PARAM_COPY_GOST94,
GOST_R_KEY_PARAMETERS_MISSING); GOST_R_KEY_PARAMETERS_MISSING);
return 0; return 0;
} }
if (!eto) { if (!eto)
{
eto = EC_KEY_new(); eto = EC_KEY_new();
EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto); EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
} }
EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom))); EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom)));
if (EC_KEY_get0_private_key(eto)) { if (EC_KEY_get0_private_key(eto))
{
gost2001_compute_public(eto); gost2001_compute_public(eto);
} }
return 1; return 1;
}
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
{
}
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) {
const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a); const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b); const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
if (!BN_cmp(da->q,db->q)) return 1; if (!BN_cmp(da->q,db->q)) return 1;
return 0; return 0;
} }
static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) {
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)))== 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)))) { EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b))))
{
return 1; return 1;
} }
return 0; return 0;
} }
/* ---------- Public key functions * --------------------------------------*/ /* ---------- Public key functions * --------------------------------------*/
static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub) static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
{ {
X509_ALGOR *palg = NULL; X509_ALGOR *palg = NULL;
const unsigned char *pubkey_buf = NULL; const unsigned char *pubkey_buf = NULL;
unsigned char *databuf; unsigned char *databuf;
@ -436,19 +493,21 @@ static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
OPENSSL_free(databuf); OPENSSL_free(databuf);
return 1; return 1;
} }
static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk) static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
{ {
ASN1_OBJECT *algobj = NULL; ASN1_OBJECT *algobj = NULL;
ASN1_OCTET_STRING *octet = NULL; ASN1_OCTET_STRING *octet = NULL;
void *pval = NULL; void *pval = NULL;
unsigned char *buf=NULL,*databuf,*sptr; unsigned char *buf=NULL,*databuf,*sptr;
int i,j,data_len,ret=0; int i,j,data_len,ret=0;
int ptype; int ptype = V_ASN1_UNDEF;
DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk); DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
if (pk->save_parameters) { if (pk->save_parameters)
{
ASN1_STRING *params = encode_gost_algor_params(pk); ASN1_STRING *params = encode_gost_algor_params(pk);
pval = params; pval = params;
ptype = V_ASN1_SEQUENCE; ptype = V_ASN1_SEQUENCE;
@ -468,9 +527,10 @@ static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
ASN1_BIT_STRING_free(octet); ASN1_BIT_STRING_free(octet);
if (ret <0) return 0; if (ret <0) return 0;
return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret); return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
} }
static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub) static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
{ {
X509_ALGOR *palg = NULL; X509_ALGOR *palg = NULL;
const unsigned char *pubkey_buf = NULL; const unsigned char *pubkey_buf = NULL;
unsigned char *databuf; unsigned char *databuf;
@ -497,10 +557,13 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
{ {
databuf[j]=octet->data[i]; databuf[j]=octet->data[i];
} }
if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) { if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
{
X= getbnfrombuf(databuf,octet->length/2); X= getbnfrombuf(databuf,octet->length/2);
Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2); Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
} else { }
else
{
Y= getbnfrombuf(databuf,octet->length/2); Y= getbnfrombuf(databuf,octet->length/2);
X= getbnfrombuf(databuf+(octet->length/2),octet->length/2); X= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
} }
@ -524,9 +587,10 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
/*EC_POINT_free(pub_key);*/ /*EC_POINT_free(pub_key);*/
return 1; return 1;
} }
static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk) static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
{ {
ASN1_OBJECT *algobj = NULL; ASN1_OBJECT *algobj = NULL;
ASN1_OCTET_STRING *octet = NULL; ASN1_OCTET_STRING *octet = NULL;
void *pval = NULL; void *pval = NULL;
@ -535,10 +599,11 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
const EC_POINT *pub_key; const EC_POINT *pub_key;
BIGNUM *X,*Y,*order; BIGNUM *X,*Y,*order;
const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk); const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
int ptype; int ptype = V_ASN1_UNDEF;
algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk)); algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
if (pk->save_parameters) { if (pk->save_parameters)
{
ASN1_STRING *params = encode_gost_algor_params(pk); ASN1_STRING *params = encode_gost_algor_params(pk);
pval = params; pval = params;
ptype = V_ASN1_SEQUENCE; ptype = V_ASN1_SEQUENCE;
@ -546,7 +611,8 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
order = BN_new(); order = BN_new();
EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL); EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL);
pub_key=EC_KEY_get0_public_key(ec); pub_key=EC_KEY_get0_public_key(ec);
if (!pub_key) { if (!pub_key)
{
GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOSTerr(GOST_F_PUB_ENCODE_GOST01,
GOST_R_PUBLIC_KEY_UNDEFINED); GOST_R_PUBLIC_KEY_UNDEFINED);
return 0; return 0;
@ -559,10 +625,13 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
BN_free(order); BN_free(order);
databuf = OPENSSL_malloc(data_len); databuf = OPENSSL_malloc(data_len);
memset(databuf,0,data_len); memset(databuf,0,data_len);
if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) { if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
{
store_bignum(X,databuf,data_len/2); store_bignum(X,databuf,data_len/2);
store_bignum(Y,databuf+data_len/2,data_len/2); store_bignum(Y,databuf+data_len/2,data_len/2);
} else { }
else
{
store_bignum(X,databuf+data_len/2,data_len/2); store_bignum(X,databuf+data_len/2,data_len/2);
store_bignum(Y,databuf,data_len/2); store_bignum(Y,databuf,data_len/2);
} }
@ -571,7 +640,8 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
octet = ASN1_OCTET_STRING_new(); octet = ASN1_OCTET_STRING_new();
ASN1_STRING_set(octet,NULL,data_len); ASN1_STRING_set(octet,NULL,data_len);
sptr=ASN1_STRING_data(octet); sptr=ASN1_STRING_data(octet);
for (i=0,j=data_len-1;i<data_len;i++,j--) { for (i=0,j=data_len-1;i<data_len;i++,j--)
{
sptr[i]=databuf[j]; sptr[i]=databuf[j];
} }
OPENSSL_free(databuf); OPENSSL_free(databuf);
@ -579,19 +649,22 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
ASN1_BIT_STRING_free(octet); ASN1_BIT_STRING_free(octet);
if (ret <0) return 0; if (ret <0) return 0;
return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret); return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
} }
static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
{ {
const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a); const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b); const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
if (da && db && da->pub_key && db->pub_key if (da && db && da->pub_key && db->pub_key
&& !BN_cmp(da->pub_key,db->pub_key)) { && !BN_cmp(da->pub_key,db->pub_key))
{
return 1; return 1;
} }
return 0; return 0;
} }
static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b) 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 *ea = EVP_PKEY_get0((EVP_PKEY *)a);
const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b); const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
const EC_POINT *ka,*kb; const EC_POINT *ka,*kb;
@ -602,36 +675,43 @@ static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b)
if (!ka || !kb) return 0; if (!ka || !kb) return 0;
ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ; ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ;
return ret; return ret;
} }
static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent, static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx) ASN1_PCTX *pctx)
{ {
const BIGNUM *key; const BIGNUM *key;
if (!BIO_indent(out,indent,128)) return 0; if (!BIO_indent(out,indent,128)) return 0;
key = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key; key = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
if (!key) return 0; if (!key) return 0;
BN_print(out,key); BN_print(out,key);
return 1; return 1;
} }
static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx) ASN1_PCTX *pctx)
{ {
return 0; return 0;
} }
static int pkey_size_gost(const EVP_PKEY *pk) static int pkey_size_gost(const EVP_PKEY *pk)
{ {
return 64; return 64;
} }
static int pkey_bits_gost(const EVP_PKEY *pk) static int pkey_bits_gost(const EVP_PKEY *pk)
{ {
return 256; return 256;
} }
/* ----------------------------------------------------------------------*/ /* ----------------------------------------------------------------------*/
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) { int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info)
{
*ameth = EVP_PKEY_asn1_new(nid, *ameth = EVP_PKEY_asn1_new(nid,
ASN1_PKEY_SIGPARAM_NULL, pemstr, info); ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
if (!*ameth) return 0; if (!*ameth) return 0;
switch (nid) { switch (nid)
{
case NID_id_GostR3410_94_cc: case NID_id_GostR3410_94_cc:
case NID_id_GostR3410_94: case NID_id_GostR3410_94:
EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94); EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
@ -668,4 +748,4 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
break; break;
} }
return 1; return 1;
} }

View File

@ -9,7 +9,7 @@
#include <stdio.h> #include <stdio.h>
#include <openssl/asn1t.h> #include <openssl/asn1t.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include "gost_asn1.h" #include "gost_lcl.h"
ASN1_NDEF_SEQUENCE(GOST_KEY_TRANSPORT) = { ASN1_NDEF_SEQUENCE(GOST_KEY_TRANSPORT) = {
ASN1_SIMPLE(GOST_KEY_TRANSPORT, key_info, GOST_KEY_INFO), ASN1_SIMPLE(GOST_KEY_TRANSPORT, key_info, GOST_KEY_INFO),

View File

@ -1,57 +0,0 @@
/**********************************************************************
* gost_keytrans.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* ASN1 structure declaration for GOST key transport *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#ifndef GOST_KEY_TRANS_H
#define GOST_KEY_TRANS_H
#include <openssl/asn1t.h>
#include <openssl/x509.h>
typedef struct {
ASN1_OCTET_STRING *encrypted_key;
ASN1_OCTET_STRING *imit;
} GOST_KEY_INFO;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_INFO)
typedef struct {
ASN1_OBJECT *cipher;
X509_PUBKEY *ephem_key;
ASN1_OCTET_STRING *eph_iv;
} GOST_KEY_AGREEMENT_INFO;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_AGREEMENT_INFO)
typedef struct {
GOST_KEY_INFO *key_info;
GOST_KEY_AGREEMENT_INFO *key_agreement_info;
} GOST_KEY_TRANSPORT;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_TRANSPORT)
typedef struct { //FIXME incomplete
GOST_KEY_TRANSPORT *gkt;
} GOST_CLIENT_KEY_EXCHANGE_PARAMS;
DECLARE_ASN1_FUNCTIONS(GOST_CLIENT_KEY_EXCHANGE_PARAMS)
typedef struct {
ASN1_OBJECT *key_params;
ASN1_OBJECT *hash_params;
ASN1_OBJECT *cipher_params;
} GOST_KEY_PARAMS;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_PARAMS)
typedef struct {
ASN1_OCTET_STRING *iv;
ASN1_OBJECT *enc_param_set;
} GOST_CIPHER_PARAMS;
DECLARE_ASN1_FUNCTIONS(GOST_CIPHER_PARAMS)
#endif

View File

@ -1,17 +1,16 @@
/********************************************************************** /**********************************************************************
* gost_crypt.c * * gost_crypt.c *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *
* OpenSSL interface to GOST 28147-89 cipher functions * * OpenSSL interface to GOST 28147-89 cipher functions *
* Requires OpenSSL 0.9.9 for compilation * * Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/ **********************************************************************/
#include <string.h> #include <string.h>
#include "crypt.h"
#include "gost89.h" #include "gost89.h"
#include <openssl/rand.h> #include <openssl/rand.h>
#include "e_gost_err.h" #include "e_gost_err.h"
#include "gost_asn1.h" #include "gost_lcl.h"
static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc); const unsigned char *iv, int enc);
#ifdef USE_SSL #ifdef USE_SSL
@ -143,130 +142,154 @@ EVP_MD imit_gost_cpa =
#endif #endif
/* /*
* Correspondence between gost parameter OIDs and substitution blocks * Correspondence between gost parameter OIDs and substitution blocks
* NID field is filed by register_gost_NID function in engine.c * NID field is filed by register_gost_NID function in engine.c
* upon engine initialization * upon engine initialization
*/ */
struct gost_cipher_info gost_cipher_list[]={ struct gost_cipher_info gost_cipher_list[]=
{
/* NID */ /* Subst block */ /* Key meshing*/ /* NID */ /* Subst block */ /* Key meshing*/
/*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/ /*{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},*/
{NID_id_Gost28147_89_cc,&GostR3411_94_CryptoProParamSet,0}, {NID_id_Gost28147_89_cc,&GostR3411_94_CryptoProParamSet,0},
{NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1}, {NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1},
{NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1}, {NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
{NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1}, {NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
{NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1}, {NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
{NID_undef,NULL,0} {NID_undef,NULL,0}
}; };
/* get encryption parameters from crypto network settings /* get encryption parameters from crypto network settings
FIXME For now we use environment var CRYPT_PARAMS as place to FIXME For now we use environment var CRYPT_PARAMS as place to
store these settings. Actually, it is better to use engine control command, read from configuration file to set them */ store these settings. Actually, it is better to use engine control command, read from configuration file to set them */
const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) { const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj)
int nid; {
struct gost_cipher_info *param; int nid;
if (!obj) { struct gost_cipher_info *param;
const char * params = getenv("CRYPT_PARAMS"); if (!obj)
{
const char * params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS);
if (!params || !strlen(params)) if (!params || !strlen(params))
return &gost_cipher_list[0]; return &gost_cipher_list[0];
nid = OBJ_txt2nid(params); nid = OBJ_txt2nid(params);
if (nid == NID_undef) { if (nid == NID_undef)
{
GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS, GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
GOST_R_INVALID_CIPHER_PARAM_OID); GOST_R_INVALID_CIPHER_PARAM_OID);
return NULL; return NULL;
} }
} else { }
else
{
nid= OBJ_obj2nid(obj); nid= OBJ_obj2nid(obj);
} }
for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid; for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid;
param++); param++);
if (!param->sblock) { if (!param->sblock)
{
GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAMS); GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAMS);
return NULL; return NULL;
}
return param;
}
}
return param;
}
/* Sets cipher param from paramset NID. */ /* Sets cipher param from paramset NID. */
int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c,int nid) { int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c,int nid)
const struct gost_cipher_info *param; {
param=get_encryption_params((nid==NID_undef?NULL:OBJ_nid2obj(nid))); const struct gost_cipher_info *param;
if (!param) return 0; param=get_encryption_params((nid==NID_undef?NULL:OBJ_nid2obj(nid)));
if (!param) return 0;
c->paramNID = param->nid;
c->key_meshing=param->key_meshing;
c->count=0;
gost_init(&(c->cctx), param->sblock);
return 1;
}
c->paramNID = param->nid;
c->key_meshing=param->key_meshing;
c->count=0;
gost_init(&(c->cctx), param->sblock);
return 1;
}
/* Initializes EVP_CIPHER_CTX by paramset NID */ /* Initializes EVP_CIPHER_CTX by paramset NID */
static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key, static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc, int paramNID,int mode) { const unsigned char *iv, int enc, int paramNID,int mode)
struct ossl_gost_cipher_ctx *c=ctx->cipher_data; {
if (!gost_cipher_set_param(c,paramNID)) return 0; struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
if (key) gost_key(&(c->cctx),key); if (ctx->app_data == NULL)
if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); {
memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); if (!gost_cipher_set_param(c,paramNID)) return 0;
return 1; ctx->app_data = ctx->cipher_data;
} }
if (key) gost_key(&(c->cctx),key);
if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
return 1;
}
/* Initializes EVP_CIPHER_CTX with fixed cryptopro A paramset */ /* Initializes EVP_CIPHER_CTX with fixed cryptopro A paramset */
int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key, int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) { const unsigned char *iv, int enc)
struct ossl_gost_cipher_ctx *c=ctx->cipher_data; {
gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA); struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
c->key_meshing=1; gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
c->count=0; c->key_meshing=1;
gost_key(&(c->cctx),key); c->count=0;
if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); gost_key(&(c->cctx),key);
memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
return 1; memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
} return 1;
}
/* Initializes EVP_CIPHER_CTX with fixed vizir paramset */ /* Initializes EVP_CIPHER_CTX with fixed vizir paramset */
int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key, int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) { const unsigned char *iv, int enc)
struct ossl_gost_cipher_ctx *c=ctx->cipher_data; {
gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet); struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
c->key_meshing=0; gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
c->count=0; c->key_meshing=0;
gost_key(&(c->cctx),key); c->count=0;
gost_key(&(c->cctx),key);
if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
return 1; return 1;
} }
/* Initializes EVP_CIPHER_CTX with default values */ /* Initializes EVP_CIPHER_CTX with default values */
int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) { const unsigned char *iv, int enc)
return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE); {
} return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE);
}
/* Wrapper around gostcrypt function from gost89.c which perform /* Wrapper around gostcrypt function from gost89.c which perform
* key meshing when nesseccary * key meshing when nesseccary
*/ */
static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) { static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf)
{
struct ossl_gost_cipher_ctx *c = ctx; struct ossl_gost_cipher_ctx *c = ctx;
if (c->count&&c->key_meshing && c->count%1024==0) { if (c->count&&c->key_meshing && c->count%1024==0)
{
cryptopro_key_meshing(&(c->cctx),iv); cryptopro_key_meshing(&(c->cctx),iv);
} }
gostcrypt(&(c->cctx),iv,buf); gostcrypt(&(c->cctx),iv,buf);
c->count+=8; c->count+=8;
} }
static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) { static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf)
struct ossl_gost_cipher_ctx *c = ctx; {
word32 g,go; struct ossl_gost_cipher_ctx *c = ctx;
unsigned char buf1[8]; word32 g,go;
if (c->count && c->key_meshing && c->count %1024 ==0) { unsigned char buf1[8];
if (c->count && c->key_meshing && c->count %1024 ==0)
{
cryptopro_key_meshing(&(c->cctx),iv); cryptopro_key_meshing(&(c->cctx),iv);
} }
if (c->count==0) { if (c->count==0)
gostcrypt(&(c->cctx),iv,buf1); {
} else { gostcrypt(&(c->cctx),iv,buf1);
}
else
{
memcpy(buf1,iv,8); memcpy(buf1,iv,8);
} }
g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24); g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24);
g += 0x01010101; g += 0x01010101;
buf1[0]=g&0xff; buf1[1]=(g>>8)&0xff; buf1[2]=(g>>16)&0xff; buf1[3]=(g>>24)&0xff; buf1[0]=g&0xff; buf1[1]=(g>>8)&0xff; buf1[2]=(g>>16)&0xff; buf1[3]=(g>>24)&0xff;
@ -278,116 +301,139 @@ gostcrypt(&(c->cctx),iv,buf1);
buf1[4]=g&0xff; buf1[5]=(g>>8)&0xff; buf1[6]=(g>>16)&0xff; buf1[7]=(g>>24)&0xff; buf1[4]=g&0xff; buf1[5]=(g>>8)&0xff; buf1[6]=(g>>16)&0xff; buf1[7]=(g>>24)&0xff;
memcpy(iv,buf1,8); memcpy(iv,buf1,8);
gostcrypt(&(c->cctx),buf1,buf); gostcrypt(&(c->cctx),buf1,buf);
c->count +=8; c->count +=8;
} }
/* GOST encryption in CFB mode */ /* GOST encryption in CFB mode */
int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl) { const unsigned char *in, unsigned int inl)
const unsigned char *in_ptr=in; {
unsigned char *out_ptr=out; const unsigned char *in_ptr=in;
int i=0; unsigned char *out_ptr=out;
int j; int i=0;
int j=0;
/* process partial block if any */ /* process partial block if any */
if (ctx->num) if (ctx->num)
{ {
for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
{ {
if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr; if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr;
*out_ptr=ctx->buf[j]^(*in_ptr); *out_ptr=ctx->buf[j]^(*in_ptr);
if (ctx->encrypt) ctx->buf[j+8]=*out_ptr; if (ctx->encrypt) ctx->buf[j+8]=*out_ptr;
} }
if (j==8) { if (j==8)
{
memcpy(ctx->iv,ctx->buf+8,8); memcpy(ctx->iv,ctx->buf+8,8);
ctx->num=0; ctx->num=0;
} else { }
else
{
ctx->num=j; ctx->num=j;
return 1; return 1;
} }
} }
for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) { for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
{
/*block cipher current iv */ /*block cipher current iv */
gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf); gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
/*xor next block of input text with it and output it*/ /*xor next block of input text with it and output it*/
/*output this block */ /*output this block */
if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8); if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8);
for (j=0;j<8;j++) { for (j=0;j<8;j++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j]; out_ptr[j]=ctx->buf[j]^in_ptr[j];
} }
/* Encrypt */ /* Encrypt */
/* Next iv is next block of cipher text*/ /* Next iv is next block of cipher text*/
if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8); if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8);
} }
/* Process rest of buffer */ /* Process rest of buffer */
if (i<inl) { if (i<inl)
{
gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf); gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,j); if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,j);
for (j=0;i<inl;j++,i++) { for (j=0;i<inl;j++,i++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j]; out_ptr[j]=ctx->buf[j]^in_ptr[j];
} }
ctx->num = j; ctx->num = j;
if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j); if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j);
} else { }
else
{
ctx->num = 0; ctx->num = 0;
} }
return 1; return 1;
} }
int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl) { const unsigned char *in, unsigned int inl)
const unsigned char *in_ptr=in; {
unsigned char *out_ptr=out; const unsigned char *in_ptr=in;
int i=0; unsigned char *out_ptr=out;
int j; int i=0;
int j;
/* process partial block if any */ /* process partial block if any */
if (ctx->num) if (ctx->num)
{ {
for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++) for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
{ {
*out_ptr=ctx->buf[j]^(*in_ptr); *out_ptr=ctx->buf[j]^(*in_ptr);
} }
if (j==8) { if (j==8)
{
ctx->num=0; ctx->num=0;
} else { }
else
{
ctx->num=j; ctx->num=j;
return 1; return 1;
} }
} }
for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) { for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
{
/*block cipher current iv */ /*block cipher current iv */
/* Encrypt */ /* Encrypt */
gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf); gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
/*xor next block of input text with it and output it*/ /*xor next block of input text with it and output it*/
/*output this block */ /*output this block */
for (j=0;j<8;j++) { for (j=0;j<8;j++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j]; out_ptr[j]=ctx->buf[j]^in_ptr[j];
} }
} }
/* Process rest of buffer */ /* Process rest of buffer */
if (i<inl) { if (i<inl)
{
gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf); gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
for (j=0;i<inl;j++,i++) { for (j=0;i<inl;j++,i++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j]; out_ptr[j]=ctx->buf[j]^in_ptr[j];
} }
ctx->num = j; ctx->num = j;
} else { }
else
{
ctx->num = 0; ctx->num = 0;
} }
return 1; return 1;
} }
/* Cleaning up of EVP_CIPHER_CTX */ /* Cleaning up of EVP_CIPHER_CTX */
int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
{ {
gost_destroy((gost_ctx *)ctx->cipher_data); gost_destroy((gost_ctx *)ctx->cipher_data);
return 1; ctx->app_data = NULL;
return 1;
}
}
/* Control function for gost cipher */ /* Control function for gost cipher */
int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr) int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr)
{ {
switch (type) switch (type)
{ {
case EVP_CTRL_RAND_KEY: case EVP_CTRL_RAND_KEY:
{ {
if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0) if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0)
@ -400,159 +446,184 @@ switch (type)
default: default:
GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND); GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
return -1; return -1;
} }
return 1; return 1;
} }
/* Set cipher parameters from ASN1 structure */ /* Set cipher parameters from ASN1 structure */
int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
{ {
int len=0; int len=0;
unsigned char *buf=NULL; unsigned char *buf=NULL;
unsigned char *p=NULL; unsigned char *p=NULL;
struct ossl_gost_cipher_ctx *c = ctx->cipher_data; struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
ASN1_OCTET_STRING *os = NULL; ASN1_OCTET_STRING *os = NULL;
if (!gcp) { if (!gcp)
{
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0; return 0;
} }
if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) { if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len))
{
GOST_CIPHER_PARAMS_free(gcp); GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0; return 0;
} }
ASN1_OBJECT_free(gcp->enc_param_set); ASN1_OBJECT_free(gcp->enc_param_set);
gcp->enc_param_set = OBJ_nid2obj(c->paramNID); gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
len = i2d_GOST_CIPHER_PARAMS(gcp, NULL); len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
p = buf = (unsigned char*)OPENSSL_malloc(len); p = buf = (unsigned char*)OPENSSL_malloc(len);
if (!buf) { if (!buf)
{
GOST_CIPHER_PARAMS_free(gcp); GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0; return 0;
} }
i2d_GOST_CIPHER_PARAMS(gcp, &p); i2d_GOST_CIPHER_PARAMS(gcp, &p);
GOST_CIPHER_PARAMS_free(gcp); GOST_CIPHER_PARAMS_free(gcp);
os = ASN1_OCTET_STRING_new(); os = ASN1_OCTET_STRING_new();
if(!os || !ASN1_OCTET_STRING_set(os, buf, len)) { if(!os || !ASN1_OCTET_STRING_set(os, buf, len))
{
OPENSSL_free(buf); OPENSSL_free(buf);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0; return 0;
} }
OPENSSL_free(buf); OPENSSL_free(buf);
ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
return 1;
}
ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
return 1;
}
/* Store parameters into ASN1 structure */ /* Store parameters into ASN1 structure */
int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params) int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
{ {
int ret = -1; int ret = -1;
int len; int len;
GOST_CIPHER_PARAMS *gcp = NULL; GOST_CIPHER_PARAMS *gcp = NULL;
unsigned char *p = params->value.sequence->data; unsigned char *p = params->value.sequence->data;
struct ossl_gost_cipher_ctx *c=ctx->cipher_data; struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) { if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE)
{
return ret; return ret;
} }
gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p, gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
params->value.sequence->length); params->value.sequence->length);
len = gcp->iv->length; len = gcp->iv->length;
if (len != ctx->cipher->iv_len) { if (len != ctx->cipher->iv_len)
{
GOST_CIPHER_PARAMS_free(gcp); GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
GOST_R_INVALID_IV_LENGTH); GOST_R_INVALID_IV_LENGTH);
return -1; return -1;
} }
if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set))) { if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set)))
{
GOST_CIPHER_PARAMS_free(gcp); GOST_CIPHER_PARAMS_free(gcp);
return -1; return -1;
} }
memcpy(ctx->oiv, gcp->iv->data, len); memcpy(ctx->oiv, gcp->iv->data, len);
GOST_CIPHER_PARAMS_free(gcp); GOST_CIPHER_PARAMS_free(gcp);
return 1; return 1;
}
}
#ifdef USE_SSL #ifdef USE_SSL
int gost_imit_init_vizir(EVP_MD_CTX *ctx) { int gost_imit_init_vizir(EVP_MD_CTX *ctx)
struct ossl_gost_imit_ctx *c = ctx->md_data; {
memset(c,0,sizeof(struct ossl_gost_imit_ctx)); struct ossl_gost_imit_ctx *c = ctx->md_data;
gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet); memset(c,0,sizeof(struct ossl_gost_imit_ctx));
return 1; gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
} return 1;
int gost_imit_init_cpa(EVP_MD_CTX *ctx) { }
struct ossl_gost_imit_ctx *c = ctx->md_data;
memset(c,0,sizeof(struct ossl_gost_imit_ctx)); int gost_imit_init_cpa(EVP_MD_CTX *ctx)
c->key_meshing=1; {
gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA); struct ossl_gost_imit_ctx *c = ctx->md_data;
return 1; memset(c,0,sizeof(struct ossl_gost_imit_ctx));
} c->key_meshing=1;
gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
return 1;
}
static void mac_block_mesh(struct ossl_gost_imit_ctx *c,unsigned char *data) static void mac_block_mesh(struct ossl_gost_imit_ctx *c,unsigned char *data)
{ {
char buffer[8]; char buffer[8];
/* We are using local buffer for iv because CryptoPro doesn't /* We are using local buffer for iv because CryptoPro doesn't
* interpret internal state of MAC algorithm as iv during keymeshing * interpret internal state of MAC algorithm as iv during keymeshing
* (but does initialize internal state from iv in key transport * (but does initialize internal state from iv in key transport
*/ */
if (c->key_meshing&& c->count && c->count %1024 ==0) { if (c->key_meshing&& c->count && c->count %1024 ==0)
{
cryptopro_key_meshing(&(c->cctx),buffer); cryptopro_key_meshing(&(c->cctx),buffer);
} }
mac_block(&(c->cctx),c->buffer,data); mac_block(&(c->cctx),c->buffer,data);
c->count +=8; c->count +=8;
} }
int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) { int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count)
{
struct ossl_gost_imit_ctx *c = ctx->md_data; struct ossl_gost_imit_ctx *c = ctx->md_data;
const unsigned char *p = data; const unsigned char *p = data;
size_t bytes = count,i; size_t bytes = count,i;
if (!(c->key_set)) return 0; if (!(c->key_set)) return 0;
if (c->bytes_left) { if (c->bytes_left)
for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++) { {
for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++)
{
c->partial_block[i]=*p; c->partial_block[i]=*p;
} }
if (i==8) { if (i==8)
{
mac_block_mesh(c,c->partial_block); mac_block_mesh(c,c->partial_block);
} else { }
else
{
c->bytes_left = i; c->bytes_left = i;
return 1; return 1;
} }
} }
while (bytes>8) { while (bytes>8)
{
mac_block_mesh(c,p); mac_block_mesh(c,p);
p+=8; p+=8;
bytes-=8; bytes-=8;
} }
if (bytes>0) { if (bytes>0)
{
memcpy(c->partial_block,p,bytes); memcpy(c->partial_block,p,bytes);
c->bytes_left=bytes; c->bytes_left=bytes;
} }
return 1; return 1;
} }
int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) { int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md)
{
struct ossl_gost_imit_ctx *c = ctx->md_data; struct ossl_gost_imit_ctx *c = ctx->md_data;
if (c->bytes_left) { if (c->bytes_left)
{
int i; int i;
for (i=c->bytes_left;i<8;i++) { for (i=c->bytes_left;i<8;i++)
{
c->partial_block[i]=0; c->partial_block[i]=0;
} }
mac_block_mesh(c,c->partial_block); mac_block_mesh(c,c->partial_block);
} }
get_mac(c->buffer,32,md); get_mac(c->buffer,32,md);
return 1; return 1;
} }
int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr) {
switch (type) { int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr)
{
switch (type)
{
case EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH: case EVP_MD_CTRL_GET_TLS_MAC_KEY_LENGTH:
*((unsigned int*)(ptr)) = 32; *((unsigned int*)(ptr)) = 32;
return 1; return 1;
@ -565,15 +636,19 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx,int type, int arg, void *ptr) {
default: default:
return 0; return 0;
} }
} }
int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) {
int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
{
memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx)); memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_imit_ctx));
return 1; return 1;
} }
/* Clean up imit ctx */ /* Clean up imit ctx */
int gost_imit_cleanup(EVP_MD_CTX *ctx) { int gost_imit_cleanup(EVP_MD_CTX *ctx)
{
memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx)); memset(ctx->md_data,0,sizeof(struct ossl_gost_imit_ctx));
return 1; return 1;
}
}
#endif #endif

74
engines/ccgost/gost_ctl.c Normal file
View File

@ -0,0 +1,74 @@
/**********************************************************************
* gost_ctl.c *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Implementation of control commands for GOST engine *
* OpenSSL 0.9.9 libraries required *
**********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <openssl/engine.h>
#include "gost_lcl.h"
static char *gost_params[GOST_PARAM_MAX+1]={NULL};
static const char *gost_envnames[]={"CRYPT_PARAMS"};
const ENGINE_CMD_DEFN gost_cmds[]=
{
/* { GOST_CTRL_RNG,
"RNG",
"Type of random number generator to use",
ENGINE_CMD_FLAG_STRING
},
{ GOST_CTRL_RNG_PARAMS,
"RNG_PARAMS",
"Parameter for random number generator",
ENGINE_CMD_FLAG_STRING
},
*/ { GOST_CTRL_CRYPT_PARAMS,
"CRYPT_PARAMS",
"OID of default GOST 28147-89 parameters",
ENGINE_CMD_FLAG_STRING
},
{0,NULL,NULL,0}
};
int gost_control_func(ENGINE *e,int cmd,long i, void *p, void (*f)(void))
{
int param = cmd-ENGINE_CMD_BASE;
int ret=0;
if (param <0 || param >GOST_PARAM_MAX) return -1;
ret=gost_set_default_param(param,p);
return ret;
}
const char *get_gost_engine_param(int param)
{
char *tmp;
if (param <0 || param >GOST_PARAM_MAX) return NULL;
if (gost_params[param]!=NULL)
{
return gost_params[param];
}
tmp = getenv(gost_envnames[param]);
if (tmp)
{
gost_params[param] = strdup(tmp);
return gost_params[param];
}
return NULL;
}
int gost_set_default_param(int param, const char *value)
{
const char *tmp;
if (param <0 || param >GOST_PARAM_MAX) return 0;
tmp = getenv(gost_envnames[param]);
/* if there is value in the environment, use it, else -passed string * */
if (!tmp) tmp=value;
if (gost_params[param]) free(gost_params[param]);
gost_params[param] = strdup(tmp);
return 1;
}

View File

@ -1,5 +1,5 @@
/********************************************************************** /**********************************************************************
* engine.c * * gost_eng.c *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *
@ -12,10 +12,7 @@
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/obj_mac.h> #include <openssl/obj_mac.h>
#include "e_gost_err.h" #include "e_gost_err.h"
#include "md.h" #include "gost_lcl.h"
#include "crypt.h"
#include "meth.h"
static const char *engine_gost_id = "gost"; static const char *engine_gost_id = "gost";
static const char *engine_gost_name = "Reference implementation of GOST engine"; static const char *engine_gost_name = "Reference implementation of GOST engine";
@ -50,50 +47,73 @@ static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94_cc = NULL, *ameth_GostR3410_94 =
*ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL; *ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL;
static int gost_engine_init(ENGINE *e) { static int gost_engine_init(ENGINE *e)
{
return 1; return 1;
} }
static int gost_engine_finish(ENGINE *e) {
return 1;
}
static int gost_engine_destroy(ENGINE *e) { static int gost_engine_finish(ENGINE *e)
{
return 1; return 1;
} }
static int bind_gost (ENGINE *e,const char *id) { static int gost_engine_destroy(ENGINE *e)
{
return 1;
}
static int bind_gost (ENGINE *e,const char *id)
{
int ret = 0; int ret = 0;
if (id && strcmp(id, engine_gost_id)) return 0; if (id && strcmp(id, engine_gost_id)) return 0;
if (!ENGINE_set_id(e, engine_gost_id)) { if (!ENGINE_set_id(e, engine_gost_id))
{
printf("ENGINE_set_id failed\n"); printf("ENGINE_set_id failed\n");
goto end; goto end;
} }
if (!ENGINE_set_name(e, engine_gost_name)) { if (!ENGINE_set_name(e, engine_gost_name))
{
printf("ENGINE_set_name failed\n"); printf("ENGINE_set_name failed\n");
goto end; goto end;
} }
if (!ENGINE_set_digests(e, gost_digests)) { if (!ENGINE_set_digests(e, gost_digests))
{
printf("ENGINE_set_digests failed\n"); printf("ENGINE_set_digests failed\n");
goto end; goto end;
} }
if (! ENGINE_set_ciphers(e, gost_ciphers)) { if (! ENGINE_set_ciphers(e, gost_ciphers))
{
printf("ENGINE_set_ciphers failed\n"); printf("ENGINE_set_ciphers failed\n");
goto end; goto end;
} }
if (! ENGINE_set_pkey_meths(e, gost_pkey_meths)) { if (! ENGINE_set_pkey_meths(e, gost_pkey_meths))
{
printf("ENGINE_set_pkey_meths failed\n"); printf("ENGINE_set_pkey_meths failed\n");
goto end; goto end;
} }
if (! ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) { if (! ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths))
{
printf("ENGINE_set_pkey_asn1_meths failed\n"); printf("ENGINE_set_pkey_asn1_meths failed\n");
goto end; goto end;
} }
/* Control function and commands */
if (!ENGINE_set_cmd_defns(e,gost_cmds))
{
fprintf(stderr,"ENGINE_set_cmd_defns failed\n");
goto end;
}
if (!ENGINE_set_ctrl_function(e,gost_control_func))
{
fprintf(stderr,"ENGINE_set_ctrl_func failed\n");
goto end;
}
if ( ! ENGINE_set_destroy_function(e, gost_engine_destroy) if ( ! ENGINE_set_destroy_function(e, gost_engine_destroy)
|| ! ENGINE_set_init_function(e,gost_engine_init) || ! ENGINE_set_init_function(e,gost_engine_init)
|| ! ENGINE_set_finish_function(e,gost_engine_finish)) goto end; || ! 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_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_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
@ -110,13 +130,16 @@ static int bind_gost (ENGINE *e,const char *id) {
/* These two actually should go in LIST_ADD command */ /* These two actually should go in LIST_ADD command */
|| ! EVP_add_cipher(&cipher_gost) || ! EVP_add_cipher(&cipher_gost)
|| ! EVP_add_digest(&digest_gost) || ! EVP_add_digest(&digest_gost)
) goto end; )
{
goto end;
}
ERR_load_GOST_strings(); ERR_load_GOST_strings();
ret = 1; ret = 1;
end: end:
return ret; return ret;
} }
#ifdef _WIN32 #ifdef _WIN32
extern __declspec( dllexport ) extern __declspec( dllexport )
@ -131,74 +154,63 @@ extern __declspec( dllexport )
IMPLEMENT_DYNAMIC_CHECK_FN(); IMPLEMENT_DYNAMIC_CHECK_FN();
//#else //#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 */ //#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
static int gost_digests(ENGINE *e, const EVP_MD **digest, static int gost_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid) const int **nids, int nid)
{ {
int ok =1 ; int ok =1 ;
if (!digest) { if (!digest)
{
*nids = gost_digest_nids; *nids = gost_digest_nids;
return 1; return 1;
} }
//printf("Digest no %d requested\n",nid); //printf("Digest no %d requested\n",nid);
if(nid == NID_id_GostR3411_94) { if(nid == NID_id_GostR3411_94)
{
*digest = &digest_gost; *digest = &digest_gost;
} else { }
else
{
ok =0; ok =0;
*digest = NULL; *digest = NULL;
} }
return ok; return ok;
} }
static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher, static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
const int **nids, int nid) { const int **nids, int nid)
{
int ok = 1; int ok = 1;
if (!cipher) { if (!cipher)
{
*nids = gost_cipher_nids; *nids = gost_cipher_nids;
return 1; /* Only one cipher supported */ return 1; /* Only one cipher supported */
} }
if(nid == NID_id_Gost28147_89) { if(nid == NID_id_Gost28147_89)
{
*cipher = &cipher_gost; *cipher = &cipher_gost;
} else { }
else
{
ok = 0; ok = 0;
*cipher = NULL; *cipher = NULL;
} }
return ok; return ok;
} }
static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth, static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
const int **nids, int nid) const int **nids, int nid)
{ {
if (!pmeth) { if (!pmeth)
{
*nids = gost_pkey_meth_nids; *nids = gost_pkey_meth_nids;
return 4; return 4;
} }
switch (nid) { switch (nid)
{
case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1; 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_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_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1;
@ -208,16 +220,18 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
*pmeth = NULL; *pmeth = NULL;
return 0; return 0;
} }
static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
const int **nids, int nid) const int **nids, int nid)
{ {
if (!ameth) { if (!ameth)
{
*nids = gost_pkey_meth_nids; *nids = gost_pkey_meth_nids;
return 4; return 4;
} }
switch (nid) { switch (nid)
{
case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1; 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_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_cc: *ameth = ameth_GostR3410_2001_cc; return 1;
@ -227,4 +241,29 @@ static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
*ameth = NULL; *ameth = NULL;
return 0; return 0;
} }
#ifdef OPENSSL_NO_DYNAMIC_ENGINE
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)
{
ENGINE *toadd =engine_gost();
if (!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
#endif

View File

@ -9,7 +9,7 @@
**********************************************************************/ **********************************************************************/
#include <string.h> #include <string.h>
#include "gost89.h" #include "gost89.h"
#include "keywrap.h" #include "gost_keywrap.h"
/* Diversifies key using random UserKey Material /* Diversifies key using random UserKey Material
* Implements RFC 4357 p 6.5 key diversification algorithm * Implements RFC 4357 p 6.5 key diversification algorithm
@ -20,22 +20,27 @@
* *
*/ */
void keyDiversifyCryptoPro(gost_ctx *ctx,const unsigned char *inputKey, const unsigned char *ukm, unsigned char *outputKey) void keyDiversifyCryptoPro(gost_ctx *ctx,const unsigned char *inputKey, const unsigned char *ukm, unsigned char *outputKey)
{ {
u4 k,s1,s2; u4 k,s1,s2;
int i,j,mask; int i,j,mask;
unsigned char S[8]; unsigned char S[8];
memcpy(outputKey,inputKey,32); memcpy(outputKey,inputKey,32);
for (i=0;i<8;i++) { for (i=0;i<8;i++)
{
/* Make array of integers from key */ /* Make array of integers from key */
/* Compute IV S*/ /* Compute IV S*/
s1=0,s2=0; s1=0,s2=0;
for (j=0,mask=1;j<8;j++,mask<<=1) { for (j=0,mask=1;j<8;j++,mask<<=1)
{
k=((u4)outputKey[4*j])|(outputKey[4*j+1]<<8)| k=((u4)outputKey[4*j])|(outputKey[4*j+1]<<8)|
(outputKey[4*j+2]<<16)|(outputKey[4*j+3]<<24); (outputKey[4*j+2]<<16)|(outputKey[4*j+3]<<24);
if (mask & ukm[i]) { if (mask & ukm[i])
{
s1+=k; s1+=k;
} else { }
else
{
s2+=k; s2+=k;
} }
} }
@ -44,7 +49,7 @@ void keyDiversifyCryptoPro(gost_ctx *ctx,const unsigned char *inputKey, const un
gost_key(ctx,outputKey); gost_key(ctx,outputKey);
gost_enc_cfb(ctx,S,outputKey,outputKey,4); gost_enc_cfb(ctx,S,outputKey,outputKey,4);
} }
} }
/* /*
@ -58,7 +63,7 @@ void keyDiversifyCryptoPro(gost_ctx *ctx,const unsigned char *inputKey, const un
int keyWrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey, const unsigned char *ukm, int keyWrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey, const unsigned char *ukm,
const unsigned char *sessionKey, unsigned char *wrappedKey) const unsigned char *sessionKey, unsigned char *wrappedKey)
{ {
unsigned char kek_ukm[32]; unsigned char kek_ukm[32];
keyDiversifyCryptoPro(ctx,keyExchangeKey,ukm,kek_ukm); keyDiversifyCryptoPro(ctx,keyExchangeKey,ukm,kek_ukm);
gost_key(ctx,kek_ukm); gost_key(ctx,kek_ukm);
@ -66,7 +71,7 @@ int keyWrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey, const un
gost_enc(ctx,sessionKey,wrappedKey+8,4); gost_enc(ctx,sessionKey,wrappedKey+8,4);
gost_mac_iv(ctx,32,ukm,sessionKey,32,wrappedKey+40); gost_mac_iv(ctx,32,ukm,sessionKey,32,wrappedKey+40);
return 1; return 1;
} }
/* /*
* Unwraps key using RFC 4357 6.4 * Unwraps key using RFC 4357 6.4
* ctx - gost encryption context, initialized with some S-boxes * ctx - gost encryption context, initialized with some S-boxes
@ -80,7 +85,7 @@ int keyWrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey, const un
int keyUnwrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey, int keyUnwrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey,
const unsigned char *wrappedKey, unsigned char *sessionKey) const unsigned char *wrappedKey, unsigned char *sessionKey)
{ {
unsigned char kek_ukm[32],cek_mac[4]; unsigned char kek_ukm[32],cek_mac[4];
keyDiversifyCryptoPro(ctx,keyExchangeKey,wrappedKey keyDiversifyCryptoPro(ctx,keyExchangeKey,wrappedKey
/* First 8 bytes of wrapped Key is ukm */ /* First 8 bytes of wrapped Key is ukm */
@ -88,10 +93,11 @@ int keyUnwrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey,
gost_key(ctx,kek_ukm); gost_key(ctx,kek_ukm);
gost_dec(ctx,wrappedKey+8,sessionKey,4); gost_dec(ctx,wrappedKey+8,sessionKey,4);
gost_mac_iv(ctx,32,wrappedKey,sessionKey,32,cek_mac); gost_mac_iv(ctx,32,wrappedKey,sessionKey,32,cek_mac);
if (memcmp(cek_mac,wrappedKey+40,4)) { if (memcmp(cek_mac,wrappedKey+40,4))
{
return 0; return 0;
} }
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
/********************************************************************** /**********************************************************************
* keywrap.c * * gost_keywrap.h *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *

206
engines/ccgost/gost_lcl.h Normal file
View File

@ -0,0 +1,206 @@
#ifndef GOST_TOOLS_H
#define GOST_TOOLS_H
/**********************************************************************
* gost_lcl.h *
* Copyright (c) 2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Internal declarations used in GOST engine *
* OpenSSL 0.9.9 libraries required to compile and use *
* this code *
**********************************************************************/
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/engine.h>
#include <openssl/ec.h>
#include <unistd.h>
#include "gost89.h"
#include "gosthash.h"
/* Control commands */
#define GOST_PARAM_CRYPT_PARAMS 0
#define GOST_PARAM_MAX 0
#define GOST_CTRL_CRYPT_PARAMS (ENGINE_CMD_BASE+GOST_PARAM_CRYPT_PARAMS)
extern const ENGINE_CMD_DEFN gost_cmds[];
int gost_control_func(ENGINE *e,int cmd, long i, void *p, void (*f)(void));
const char *get_gost_engine_param(int param);
int gost_set_default_param(int param, const char *value);
/* method registration */
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info);
int register_pmeth_gost (int id, EVP_PKEY_METHOD **pmeth, int flags);
/* Gost-specific pmeth control-function parameters */
#define param_ctrl_string "paramset"
#define EVP_PKEY_CTRL_GOST_PARAMSET (EVP_PKEY_ALG_CTRL+1)
/* Pmeth internal representation */
struct gost_pmeth_data {
int sign_param_nid; /* Should be set whenever parameters are filled */
EVP_PKEY *eph_seckey;
EVP_MD *md;
};
/* GOST-specific ASN1 structures */
typedef struct {
ASN1_OCTET_STRING *encrypted_key;
ASN1_OCTET_STRING *imit;
} GOST_KEY_INFO;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_INFO)
typedef struct {
ASN1_OBJECT *cipher;
X509_PUBKEY *ephem_key;
ASN1_OCTET_STRING *eph_iv;
} GOST_KEY_AGREEMENT_INFO;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_AGREEMENT_INFO)
typedef struct {
GOST_KEY_INFO *key_info;
GOST_KEY_AGREEMENT_INFO *key_agreement_info;
} GOST_KEY_TRANSPORT;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_TRANSPORT)
typedef struct { //FIXME incomplete
GOST_KEY_TRANSPORT *gkt;
} GOST_CLIENT_KEY_EXCHANGE_PARAMS;
DECLARE_ASN1_FUNCTIONS(GOST_CLIENT_KEY_EXCHANGE_PARAMS)
typedef struct {
ASN1_OBJECT *key_params;
ASN1_OBJECT *hash_params;
ASN1_OBJECT *cipher_params;
} GOST_KEY_PARAMS;
DECLARE_ASN1_FUNCTIONS(GOST_KEY_PARAMS)
typedef struct {
ASN1_OCTET_STRING *iv;
ASN1_OBJECT *enc_param_set;
} GOST_CIPHER_PARAMS;
DECLARE_ASN1_FUNCTIONS(GOST_CIPHER_PARAMS)
/*============== Message digest and cipher related structures ==========*/
/* Structure used as EVP_MD_CTX-md_data.
* It allows to avoid storing in the md-data pointers to
* dynamically allocated memory.
*
* I cannot invent better way to avoid memory leaks, because
* openssl insist on invoking Init on Final-ed digests, and there
* is no reliable way to find out whether pointer in the passed
* md_data is valid or not.
* */
struct ossl_gost_digest_ctx {
gost_hash_ctx dctx;
gost_ctx cctx;
};
/* EVP_MD structure for GOST R 34.11 */
extern EVP_MD digest_gost;
/* 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
/* EVP_PKEY_METHOD key encryption callbacks */
/* From gost94_keyx.c */
int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len );
int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len);
int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len );
int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * in,size_t in_len);
/* From gost2001_keyx.c */
int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len );
int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len);
int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len );
int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * in,size_t in_len);
/* Internal functions to make error processing happy */
int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len,
const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx);
int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
unsigned char *crypted_key, gost_ctx *ctx);
/* Internal functions for signature algorithms */
int fill_GOST94_params(DSA *dsa,int nid);
int fill_GOST2001_params(EC_KEY *eckey, int nid);
int gost_sign_keygen(DSA *dsa) ;
int gost2001_keygen(EC_KEY *ec) ;
DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa) ;
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey);
int gost_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa) ;
int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
DSA_SIG *sig, EC_KEY *ec);
int gost2001_compute_public(EC_KEY *ec) ;
int gost94_compute_public(DSA *dsa) ;
/*============== miscellaneous functions============================= */
/* from gost_sign.c */
/* Convert GOST R 34.11 hash sum to bignum according to standard */
BIGNUM *hashsum2bn(const unsigned char *dgst) ;
/* Store bignum in byte array of given length, prepending by zeros
* if nesseccary */
int store_bignum(BIGNUM *bn, unsigned char *buf,int len);
/* Read bignum, which can have few MSB all-zeros from buffer*/
BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len);
/* Pack GOST R 34.10 signature according to CryptoCom rules */
int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen);
/* Pack GOST R 34.10 signature according to CryptoPro rules */
int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen);
/* Unpack GOST R 34.10 signature according to CryptoCom rules */
DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) ;
/* Unpack GOST R 34.10 signature according to CryptoPro rules */
DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) ;
/* from ameth.c */
/* Get private key as BIGNUM from both R 34.10-94 and R 34.10-2001 keys*/
BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) ;
/* Find NID by GOST 94 parameters */
int gost94_nid_by_params(DSA *p) ;
#endif

View File

@ -7,7 +7,7 @@
* Requires OpenSSL 0.9.9 for compilation * * Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/ **********************************************************************/
#include <string.h> #include <string.h>
#include "md.h" #include "gost_lcl.h"
#include "gosthash.h" #include "gosthash.h"
#include "e_gost_err.h" #include "e_gost_err.h"
@ -19,7 +19,7 @@ static int gost_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from);
static int gost_digest_cleanup(EVP_MD_CTX *ctx); static int gost_digest_cleanup(EVP_MD_CTX *ctx);
EVP_MD digest_gost= EVP_MD digest_gost=
{ {
NID_id_GostR3411_94, NID_id_GostR3411_94,
NID_undef, NID_undef,
32, 32,
@ -35,35 +35,36 @@ EVP_MD digest_gost=
32, 32,
sizeof(struct ossl_gost_digest_ctx ), sizeof(struct ossl_gost_digest_ctx ),
NULL NULL
}; };
int gost_digest_init(EVP_MD_CTX *ctx) int gost_digest_init(EVP_MD_CTX *ctx)
{ {
struct ossl_gost_digest_ctx *c = ctx->md_data; struct ossl_gost_digest_ctx *c = ctx->md_data;
memset(&(c->dctx),0,sizeof(gost_hash_ctx)); memset(&(c->dctx),0,sizeof(gost_hash_ctx));
gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet); gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
c->dctx.cipher_ctx= &(c->cctx); c->dctx.cipher_ctx= &(c->cctx);
return 1; return 1;
} }
int gost_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count) int gost_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count)
{ {
return hash_block((gost_hash_ctx *)ctx->md_data,data,count); return hash_block((gost_hash_ctx *)ctx->md_data,data,count);
} }
int gost_digest_final(EVP_MD_CTX *ctx,unsigned char *md) int gost_digest_final(EVP_MD_CTX *ctx,unsigned char *md)
{ {
return finish_hash((gost_hash_ctx *)ctx->md_data,md); return finish_hash((gost_hash_ctx *)ctx->md_data,md);
} }
int gost_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) int gost_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
{ {
memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx)); memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx));
return 1; return 1;
} }
int gost_digest_cleanup(EVP_MD_CTX *ctx) { int gost_digest_cleanup(EVP_MD_CTX *ctx)
{
memset(ctx->md_data,0,sizeof(struct ossl_gost_digest_ctx)); memset(ctx->md_data,0,sizeof(struct ossl_gost_digest_ctx));
return 1; return 1;
} }

View File

@ -7,7 +7,7 @@
* OpenSSL 0.9.9 libraries required to compile and use * * OpenSSL 0.9.9 libraries required to compile and use *
* this code * * this code *
**********************************************************************/ **********************************************************************/
#include "paramset.h" #include "gost_params.h"
#include <openssl/objects.h> #include <openssl/objects.h>
/* Parameters of GOST 34.10 */ /* Parameters of GOST 34.10 */

View File

@ -1,5 +1,5 @@
/********************************************************************** /**********************************************************************
* paramset.h * * gost_params.h *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *

View File

@ -1,5 +1,5 @@
/********************************************************************** /**********************************************************************
* pmeth.c * * gost_pmeth.c *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *
@ -13,53 +13,57 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "meth.h" #include "gost_params.h"
#include "pmeth.h" #include "gost_lcl.h"
#include "sign.h"
#include "gostkeyx.h"
#include "paramset.h"
#include "tools.h"
#include "e_gost_err.h" #include "e_gost_err.h"
/*-------init, cleanup, copy - uniform for all algs ---------------*/ /*-------init, cleanup, copy - uniform for all algs ---------------*/
/* Allocates new gost_pmeth_data structure and assigns it as data */ /* Allocates new gost_pmeth_data structure and assigns it as data */
static int pkey_gost_init(EVP_PKEY_CTX *ctx) { static int pkey_gost_init(EVP_PKEY_CTX *ctx)
{
struct gost_pmeth_data *data; struct gost_pmeth_data *data;
data = OPENSSL_malloc(sizeof(struct gost_pmeth_data)); data = OPENSSL_malloc(sizeof(struct gost_pmeth_data));
if (!data) return 0; if (!data) return 0;
memset(data,0,sizeof(struct gost_pmeth_data)); memset(data,0,sizeof(struct gost_pmeth_data));
EVP_PKEY_CTX_set_data(ctx,data); EVP_PKEY_CTX_set_data(ctx,data);
return 1; return 1;
} }
/* Copies contents of gost_pmeth_data structure */ /* Copies contents of gost_pmeth_data structure */
static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{ {
struct gost_pmeth_data *dst_data,*src_data; struct gost_pmeth_data *dst_data,*src_data;
if (!pkey_gost_init(dst)) { if (!pkey_gost_init(dst))
{
return 0; return 0;
} }
src_data = EVP_PKEY_CTX_get_data(src); src_data = EVP_PKEY_CTX_get_data(src);
dst_data = EVP_PKEY_CTX_get_data(dst); dst_data = EVP_PKEY_CTX_get_data(dst);
*dst_data = *src_data; *dst_data = *src_data;
if (src_data -> eph_seckey) { if (src_data -> eph_seckey)
{
dst_data ->eph_seckey = NULL; dst_data ->eph_seckey = NULL;
} }
return 1; return 1;
} }
/* Frees up gost_pmeth_data structure */ /* Frees up gost_pmeth_data structure */
static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx) { static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
{
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey); if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
OPENSSL_free(data); OPENSSL_free(data);
} }
/* --------------------- control functions ------------------------------*/ /* --------------------- control functions ------------------------------*/
static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2) static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{ {
struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
switch (type) switch (type)
{ {
case EVP_PKEY_CTRL_MD: case EVP_PKEY_CTRL_MD:
{ {
if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94) { if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
{
GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE); GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
return 0; return 0;
} }
@ -75,45 +79,49 @@ static int pkey_gost_ctrl (EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_GOST_PARAMSET: case EVP_PKEY_CTRL_GOST_PARAMSET:
pctx->sign_param_nid = (int)p1; pctx->sign_param_nid = (int)p1;
pctx->crypt_param_nid= (int)p2;
return 1; return 1;
} }
return -2; return -2;
} }
static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx, static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value) const char *type, const char *value)
{ {
if(!strcmp(type, param_ctrl_string)) { if(!strcmp(type, param_ctrl_string))
{
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
NID_id_GostR3410_94_CryptoPro_A_ParamSet, NID_id_GostR3410_94_CryptoPro_A_ParamSet,
(void *)NID_id_Gost28147_89_cc); NULL);
} }
return -2; return -2;
} }
static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx, static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value) const char *type, const char *value)
{ {
if(!strcmp(type, param_ctrl_string)) { if(!strcmp(type, param_ctrl_string))
{
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
NID_id_GostR3410_2001_ParamSet_cc, NID_id_GostR3410_2001_ParamSet_cc,NULL);
(void *)
NID_id_Gost28147_89_cc);
} }
return -2; return -2;
} }
static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx, static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value) const char *type, const char *value)
{ {
int param_nid=0; int param_nid=0;
if(!strcmp(type, param_ctrl_string)) { if(!strcmp(type, param_ctrl_string))
if (!value) { {
if (!value)
{
return 0; return 0;
} }
if (strlen(value) == 1) { if (strlen(value) == 1)
switch(toupper(value[0])) { {
switch(toupper(value[0]))
{
case 'A': case 'A':
param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet; param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
break; break;
@ -130,8 +138,11 @@ static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
return 0; return 0;
break; break;
} }
} else if ((strlen(value) == 2) && (toupper(value[0]) == 'X')) { }
switch (toupper(value[1])) { else if ((strlen(value) == 2) && (toupper(value[0]) == 'X'))
{
switch (toupper(value[1]))
{
case 'A': case 'A':
param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet; param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet;
break; break;
@ -145,16 +156,21 @@ static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
return 0; return 0;
break; break;
} }
} else { }
else
{
R3410_params *p = R3410_paramset; R3410_params *p = R3410_paramset;
param_nid = OBJ_txt2nid(value); param_nid = OBJ_txt2nid(value);
if (param_nid == NID_undef) { if (param_nid == NID_undef)
{
return 0; return 0;
} }
for (;p->nid != NID_undef;p++) { for (;p->nid != NID_undef;p++)
{
if (p->nid == param_nid) break; if (p->nid == param_nid) break;
} }
if (p->nid == NID_undef) { if (p->nid == NID_undef)
{
GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR, GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR,
GOST_R_INVALID_PARAMSET); GOST_R_INVALID_PARAMSET);
return 0; return 0;
@ -162,21 +178,25 @@ static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
} }
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, (void *)NID_id_Gost28147_89_CryptoPro_A_ParamSet); param_nid, NULL);
} }
return -2; return -2;
} }
static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx, static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value) const char *type, const char *value)
{ {
int param_nid=0; int param_nid=0;
if(!strcmp(type, param_ctrl_string)) { if(!strcmp(type, param_ctrl_string))
if (!value) { {
if (!value)
{
return 0; return 0;
} }
if (strlen(value) == 1) { if (strlen(value) == 1)
switch(toupper(value[0])) { {
switch(toupper(value[0]))
{
case 'A': case 'A':
param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet; param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
break; break;
@ -193,8 +213,11 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
return 0; return 0;
break; break;
} }
} else if ((strlen(value) == 2) && (toupper(value[0]) == 'X')) { }
switch (toupper(value[1])) { else if ((strlen(value) == 2) && (toupper(value[0]) == 'X'))
{
switch (toupper(value[1]))
{
case 'A': case 'A':
param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet; param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
break; break;
@ -205,16 +228,21 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
return 0; return 0;
break; break;
} }
} else { }
else
{
R3410_2001_params *p = R3410_2001_paramset; R3410_2001_params *p = R3410_2001_paramset;
param_nid = OBJ_txt2nid(value); param_nid = OBJ_txt2nid(value);
if (param_nid == NID_undef) { if (param_nid == NID_undef)
{
return 0; return 0;
} }
for (;p->nid != NID_undef;p++) { for (;p->nid != NID_undef;p++)
{
if (p->nid == param_nid) break; if (p->nid == param_nid) break;
} }
if (p->nid == NID_undef) { if (p->nid == NID_undef)
{
GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR, GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
GOST_R_INVALID_PARAMSET); GOST_R_INVALID_PARAMSET);
return 0; return 0;
@ -222,59 +250,73 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
} }
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET, return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, (void *)NID_id_Gost28147_89_CryptoPro_A_ParamSet); param_nid, NULL);
} }
return -2; return -2;
} }
/* --------------------- key generation --------------------------------*/ /* --------------------- key generation --------------------------------*/
/* Generates GOST 94 key and assigns it setting specified type */ /* Generates GOST 94 key and assigns it setting specified type */
static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type) static int pkey_gost94_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
{ {
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
DSA *dsa=NULL; DSA *dsa=NULL;
if (data->sign_param_nid == NID_undef) { if (data->sign_param_nid == NID_undef)
if (type== NID_id_GostR3410_94_cc) { {
if (type== NID_id_GostR3410_94_cc)
{
data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet; data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
} else { }
else
{
GOSTerr(GOST_F_PKEY_GOST94_KEYGEN, GOSTerr(GOST_F_PKEY_GOST94_KEYGEN,
GOST_R_NO_PARAMETERS_SET); GOST_R_NO_PARAMETERS_SET);
return 0; return 0;
} }
} }
dsa = DSA_new(); dsa = DSA_new();
if (!fill_GOST94_params(dsa,data->sign_param_nid)) { if (!fill_GOST94_params(dsa,data->sign_param_nid))
{
DSA_free(dsa); DSA_free(dsa);
return 0; return 0;
} }
gost_sign_keygen(dsa); gost_sign_keygen(dsa);
EVP_PKEY_assign(pkey,type,dsa); EVP_PKEY_assign(pkey,type,dsa);
return 1; return 1;
} }
/* Generates Gost_R3410_94_cc key */ /* Generates Gost_R3410_94_cc key */
static int pkey_gost94cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { static int pkey_gost94cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94_cc); return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94_cc);
} }
/* Generates Gost_R3410_94_cp key */ /* Generates Gost_R3410_94_cp key */
static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { static int pkey_gost94cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94); return pkey_gost94_keygen(ctx,pkey,NID_id_GostR3410_94);
} }
/* Generates GOST_R3410 2001 key and assigns it using specified type */ /* Generates GOST_R3410 2001 key and assigns it using specified type */
static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type) static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
{ {
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
EC_KEY *ec=NULL; EC_KEY *ec=NULL;
if (data->sign_param_nid == NID_undef) { if (data->sign_param_nid == NID_undef)
if (type == NID_id_GostR3410_2001_cc) { {
if (type == NID_id_GostR3410_2001_cc)
{
data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc; data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
} else { }
else {
GOSTerr(GOST_F_PKEY_GOST01_KEYGEN, GOSTerr(GOST_F_PKEY_GOST01_KEYGEN,
GOST_R_NO_PARAMETERS_SET); GOST_R_NO_PARAMETERS_SET);
return 0; return 0;
} }
} }
ec = EC_KEY_new(); ec = EC_KEY_new();
if (!fill_GOST2001_params(ec,data->sign_param_nid)) { if (!fill_GOST2001_params(ec,data->sign_param_nid))
{
EC_KEY_free(ec); EC_KEY_free(ec);
return 0; return 0;
} }
@ -282,20 +324,24 @@ static int pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey,int type)
EVP_PKEY_assign(pkey,type,ec); EVP_PKEY_assign(pkey,type,ec);
return 1; return 1;
} }
/* Generates GOST R3410 2001_cc key */ /* Generates GOST R3410 2001_cc key */
static int pkey_gost01cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { static int pkey_gost01cc_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001_cc); return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001_cc);
} }
/* Generates GOST R3410 2001_cp key */ /* Generates GOST R3410 2001_cp key */
static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { static int pkey_gost01cp_keygen (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001); return pkey_gost01_keygen(ctx,pkey,NID_id_GostR3410_2001);
} }
/* ----------- sign callbacks --------------------------------------*/ /* ----------- sign callbacks --------------------------------------*/
static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbs_len) const unsigned char *tbs, size_t tbs_len)
{ {
DSA_SIG *unpacked_sig=NULL; DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0; if (!siglen) return 0;
@ -305,17 +351,16 @@ static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
return 1; return 1;
} }
unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey)); unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) { if (!unpacked_sig)
{
return 0; return 0;
} }
return pack_sign_cc(unpacked_sig,32,sig,siglen); return pack_sign_cc(unpacked_sig,32,sig,siglen);
}
}
static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbs_len) const unsigned char *tbs, size_t tbs_len)
{ {
DSA_SIG *unpacked_sig=NULL; DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0; if (!siglen) return 0;
@ -325,16 +370,16 @@ static int pkey_gost94_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
return 1; return 1;
} }
unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey)); unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) { if (!unpacked_sig)
{
return 0; return 0;
} }
return pack_sign_cp(unpacked_sig,32,sig,siglen); return pack_sign_cp(unpacked_sig,32,sig,siglen);
}
}
static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbs_len) const unsigned char *tbs, size_t tbs_len)
{ {
DSA_SIG *unpacked_sig=NULL; DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0; if (!siglen) return 0;
@ -344,14 +389,16 @@ static int pkey_gost01_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
return 1; return 1;
} }
unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey)); unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) { if (!unpacked_sig)
{
return 0; return 0;
} }
return pack_sign_cc(unpacked_sig,32,sig,siglen); return pack_sign_cc(unpacked_sig,32,sig,siglen);
} }
static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbs_len) const unsigned char *tbs, size_t tbs_len)
{ {
DSA_SIG *unpacked_sig=NULL; DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0; if (!siglen) return 0;
@ -361,15 +408,17 @@ static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
return 1; return 1;
} }
unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey)); unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) { if (!unpacked_sig)
{
return 0; return 0;
} }
return pack_sign_cp(unpacked_sig,32,sig,siglen); return pack_sign_cp(unpacked_sig,32,sig,siglen);
} }
/* ------------------- verify callbacks ---------------------------*/ /* ------------------- verify callbacks ---------------------------*/
static int pkey_gost94_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, static int pkey_gost94_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs, size_t tbs_len) size_t siglen, const unsigned char *tbs, size_t tbs_len)
{ {
int ok = 0; int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
DSA_SIG *s=unpack_cc_signature(sig,siglen); DSA_SIG *s=unpack_cc_signature(sig,siglen);
@ -377,11 +426,11 @@ static int pkey_gost94_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
DSA_SIG_free(s); DSA_SIG_free(s);
return ok; return ok;
} }
static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs, size_t tbs_len) size_t siglen, const unsigned char *tbs, size_t tbs_len)
{ {
int ok = 0; int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
DSA_SIG *s=unpack_cp_signature(sig,siglen); DSA_SIG *s=unpack_cp_signature(sig,siglen);
@ -389,10 +438,11 @@ static int pkey_gost94_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); if (pub_key) ok = gost_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
DSA_SIG_free(s); DSA_SIG_free(s);
return ok; return ok;
} }
static int pkey_gost01_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, static int pkey_gost01_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs, size_t tbs_len) size_t siglen, const unsigned char *tbs, size_t tbs_len)
{ {
int ok = 0; int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
DSA_SIG *s=unpack_cc_signature(sig,siglen); DSA_SIG *s=unpack_cc_signature(sig,siglen);
@ -405,11 +455,11 @@ static int pkey_gost01_cc_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
DSA_SIG_free(s); DSA_SIG_free(s);
return ok; return ok;
} }
static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs, size_t tbs_len) size_t siglen, const unsigned char *tbs, size_t tbs_len)
{ {
int ok = 0; int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
DSA_SIG *s=unpack_cp_signature(sig,siglen); DSA_SIG *s=unpack_cp_signature(sig,siglen);
@ -422,11 +472,12 @@ static int pkey_gost01_cp_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key)); if (pub_key) ok = gost2001_do_verify(tbs,tbs_len,s,EVP_PKEY_get0(pub_key));
DSA_SIG_free(s); DSA_SIG_free(s);
return ok; return ok;
} }
/* ------------- encrypt init -------------------------------------*/ /* ------------- encrypt init -------------------------------------*/
/* Generates ephermeral key */ /* Generates ephermeral key */
static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx) static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
{ {
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
EVP_PKEY *eph_key = EVP_PKEY_new(); EVP_PKEY *eph_key = EVP_PKEY_new();
EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx);
@ -434,7 +485,8 @@ static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey); if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL); EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL);
if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0; if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0;
switch (EVP_PKEY_base_id(old_key)) { switch (EVP_PKEY_base_id(old_key))
{
case NID_id_GostR3410_2001: case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc: case NID_id_GostR3410_2001_cc:
gost2001_keygen(EVP_PKEY_get0(eph_key)); gost2001_keygen(EVP_PKEY_get0(eph_key));
@ -450,13 +502,16 @@ static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
data->eph_seckey=eph_key; data->eph_seckey=eph_key;
return 1; return 1;
} }
/* ----------------------------------------------------------------*/ /* ----------------------------------------------------------------*/
int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) { int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
{
*pmeth = EVP_PKEY_meth_new(id, flags); *pmeth = EVP_PKEY_meth_new(id, flags);
if (!*pmeth) return 0; if (!*pmeth) return 0;
switch (id) { switch (id)
{
case NID_id_GostR3410_94_cc: case NID_id_GostR3410_94_cc:
EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94cc_str); EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94cc_str);
EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cc_keygen); EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cc_keygen);
@ -510,5 +565,5 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) {
//FIXME derive etc... //FIXME derive etc...
return 1; return 1;
} }

View File

@ -13,29 +13,31 @@
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include "sign.h" #include "gost_params.h"
#include "paramset.h" #include "gost_lcl.h"
#include "tools.h"
#include "e_gost_err.h" #include "e_gost_err.h"
#ifdef DEBUG_SIGN #ifdef DEBUG_SIGN
void dump_signature(const char *message,const unsigned char *buffer,size_t len) { void dump_signature(const char *message,const unsigned char *buffer,size_t len)
{
size_t i; size_t i;
fprintf(stderr,"signature %s Length=%d",message,len); fprintf(stderr,"signature %s Length=%d",message,len);
for (i=0; i<len; i++) { for (i=0; i<len; i++)
{
if (i% 16 ==0) fputc('\n',stderr); if (i% 16 ==0) fputc('\n',stderr);
fprintf (stderr," %02x",buffer[i]); fprintf (stderr," %02x",buffer[i]);
} }
fprintf(stderr,"\nEnd of signature\n"); fprintf(stderr,"\nEnd of signature\n");
} }
void dump_dsa_sig(const char *message, DSA_SIG *sig) { void dump_dsa_sig(const char *message, DSA_SIG *sig)
{
fprintf(stderr,"%s\nR=",message); fprintf(stderr,"%s\nR=",message);
BN_print_fp(stderr,sig->r); BN_print_fp(stderr,sig->r);
fprintf(stderr,"\nS="); fprintf(stderr,"\nS=");
BN_print_fp(stderr,sig->s); BN_print_fp(stderr,sig->s);
fprintf(stderr,"\n"); fprintf(stderr,"\n");
} }
#else #else
@ -47,7 +49,7 @@ void dump_dsa_sig(const char *message, DSA_SIG *sig) {
* Computes signature and returns it as DSA_SIG structure * Computes signature and returns it as DSA_SIG structure
*/ */
DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa) DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
{ {
BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL; BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
DSA_SIG *newsig = DSA_SIG_new(); DSA_SIG *newsig = DSA_SIG_new();
BIGNUM *md = hashsum2bn(dgst); BIGNUM *md = hashsum2bn(dgst);
@ -67,27 +69,31 @@ DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
{ {
BN_one(md); BN_one(md);
} }
do { do
do { {
do
{
/*Generate random number k less than q*/ /*Generate random number k less than q*/
BN_rand_range(k,dsa->q); BN_rand_range(k,dsa->q);
/* generate r = (a^x mod p) mod q */ /* generate r = (a^x mod p) mod q */
BN_mod_exp(tmp,dsa->g, k, dsa->p,ctx); BN_mod_exp(tmp,dsa->g, k, dsa->p,ctx);
if (!(newsig->r)) newsig->r=BN_new(); if (!(newsig->r)) newsig->r=BN_new();
BN_mod(newsig->r,tmp,dsa->q,ctx); BN_mod(newsig->r,tmp,dsa->q,ctx);
} while (BN_is_zero(newsig->r)); }
while (BN_is_zero(newsig->r));
/* generate s = (xr + k(Hm)) mod q */ /* generate s = (xr + k(Hm)) mod q */
BN_mod_mul(tmp,dsa->priv_key,newsig->r,dsa->q,ctx); BN_mod_mul(tmp,dsa->priv_key,newsig->r,dsa->q,ctx);
BN_mod_mul(tmp2,k,md,dsa->q,ctx); BN_mod_mul(tmp2,k,md,dsa->q,ctx);
if (!newsig->s) newsig->s=BN_new(); if (!newsig->s) newsig->s=BN_new();
BN_mod_add(newsig->s,tmp,tmp2,dsa->q,ctx); BN_mod_add(newsig->s,tmp,tmp2,dsa->q,ctx);
} while (BN_is_zero(newsig->s)); }
err: while (BN_is_zero(newsig->s));
err:
BN_free(md); BN_free(md);
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return newsig; return newsig;
} }
/* /*
@ -95,9 +101,8 @@ err:
* and frees up DSA_SIG structure * and frees up DSA_SIG structure
*/ */
int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen) int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
{ {
*siglen = 2*order; *siglen = 2*order;
memset(sig,0,*siglen); memset(sig,0,*siglen);
store_bignum(s->r, sig,order); store_bignum(s->r, sig,order);
@ -105,14 +110,13 @@ int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen)
dump_signature("serialized",sig,*siglen); dump_signature("serialized",sig,*siglen);
DSA_SIG_free(s); DSA_SIG_free(s);
return 1; return 1;
} }
/* /*
* Packs signature according to Cryptopro rules * Packs signature according to Cryptopro rules
* and frees up DSA_SIG structure * and frees up DSA_SIG structure
*/ */
int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen) int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, size_t *siglen)
{ {
*siglen = 2*order; *siglen = 2*order;
memset(sig,0,*siglen); memset(sig,0,*siglen);
store_bignum(s->s, sig, order); store_bignum(s->s, sig, order);
@ -120,10 +124,7 @@ int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen)
dump_signature("serialized",sig,*siglen); dump_signature("serialized",sig,*siglen);
DSA_SIG_free(s); DSA_SIG_free(s);
return 1; return 1;
} }
/* /*
* Verifies signature passed as DSA_SIG structure * Verifies signature passed as DSA_SIG structure
@ -132,7 +133,7 @@ int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen)
int gost_do_verify(const unsigned char *dgst, int dgst_len, int gost_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa) DSA_SIG *sig, DSA *dsa)
{ {
BIGNUM *md, *tmp=NULL; BIGNUM *md, *tmp=NULL;
BIGNUM *q2=NULL; BIGNUM *q2=NULL;
BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL; BIGNUM *u=NULL,*v=NULL,*z1=NULL,*z2=NULL;
@ -159,7 +160,8 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len,
u = BN_CTX_get(ctx); u = BN_CTX_get(ctx);
BN_mod(tmp,md,dsa->q,ctx); BN_mod(tmp,md,dsa->q,ctx);
if (BN_is_zero(tmp)) { if (BN_is_zero(tmp))
{
BN_one(md); BN_one(md);
} }
BN_copy(q2,dsa->q); BN_copy(q2,dsa->q);
@ -177,21 +179,23 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len,
BN_free(md); BN_free(md);
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
if (ok!=0) { if (ok!=0)
{
GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH); GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_MISMATCH);
} }
return (ok==0); return (ok==0);
} }
/* /*
* Computes public keys for GOST R 34.10-94 algorithm * Computes public keys for GOST R 34.10-94 algorithm
* *
*/ */
int gost94_compute_public(DSA *dsa) int gost94_compute_public(DSA *dsa)
{ {
/* Now fill algorithm parameters with correct values */ /* Now fill algorithm parameters with correct values */
BN_CTX *ctx = BN_CTX_new(); BN_CTX *ctx = BN_CTX_new();
if (!dsa->g) { if (!dsa->g)
{
GOSTerr(GOST_F_GOST_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED); GOSTerr(GOST_F_GOST_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITALIZED);
return 0; return 0;
} }
@ -200,14 +204,15 @@ int gost94_compute_public(DSA *dsa)
BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx); BN_mod_exp(dsa->pub_key, dsa->g,dsa->priv_key,dsa->p,ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return 1; return 1;
} }
/* /*
* Fill GOST 94 params, searching them in R3410_paramset array * Fill GOST 94 params, searching them in R3410_paramset array
* by nid of paramset * by nid of paramset
* *
*/ */
int fill_GOST94_params(DSA *dsa,int nid) { int fill_GOST94_params(DSA *dsa,int nid)
{
R3410_params *params=R3410_paramset; R3410_params *params=R3410_paramset;
while (params->nid!=NID_undef && params->nid !=nid) params++; while (params->nid!=NID_undef && params->nid !=nid) params++;
if (params->nid == NID_undef) if (params->nid == NID_undef)
@ -226,7 +231,7 @@ int fill_GOST94_params(DSA *dsa,int nid) {
dsa->g=NULL; dsa->g=NULL;
BN_dec2bn(&(dsa->g),params->a); BN_dec2bn(&(dsa->g),params->a);
return 1; return 1;
} }
/* /*
* Generate GOST R 34.10-94 keypair * Generate GOST R 34.10-94 keypair
@ -234,69 +239,82 @@ int fill_GOST94_params(DSA *dsa,int nid) {
* *
*/ */
int gost_sign_keygen(DSA *dsa) int gost_sign_keygen(DSA *dsa)
{ {
dsa->priv_key = BN_new(); dsa->priv_key = BN_new();
BN_rand_range(dsa->priv_key,dsa->q); BN_rand_range(dsa->priv_key,dsa->q);
return gost94_compute_public( dsa); return gost94_compute_public( dsa);
} }
/* Unpack signature according to cryptocom rules */ /* Unpack signature according to cryptocom rules */
DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen)
{ {
DSA_SIG *s; DSA_SIG *s;
s = DSA_SIG_new(); s = DSA_SIG_new();
if (s == NULL) { if (s == NULL)
{
GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY); GOSTerr(GOST_F_UNPACK_CC_SIGNATURE,GOST_R_NO_MEMORY);
return(NULL); return(NULL);
} }
s->r = getbnfrombuf(sig, siglen/2); s->r = getbnfrombuf(sig, siglen/2);
s->s = getbnfrombuf(sig + siglen/2, siglen/2); s->s = getbnfrombuf(sig + siglen/2, siglen/2);
return s; return s;
} }
/* Unpack signature according to cryptopro rules */ /* Unpack signature according to cryptopro rules */
DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
{ {
DSA_SIG *s; DSA_SIG *s;
s = DSA_SIG_new(); s = DSA_SIG_new();
if (s == NULL) { if (s == NULL)
{
GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY); GOSTerr(GOST_F_UNPACK_CP_SIGNATURE,GOST_R_NO_MEMORY);
return NULL; return NULL;
} }
s->s = getbnfrombuf(sig , siglen/2); s->s = getbnfrombuf(sig , siglen/2);
s->r = getbnfrombuf(sig + siglen/2, siglen/2); s->r = getbnfrombuf(sig + siglen/2, siglen/2);
return s; return s;
} }
/* Convert little-endian byte array into bignum */ /* Convert little-endian byte array into bignum */
BIGNUM *hashsum2bn(const unsigned char *dgst) BIGNUM *hashsum2bn(const unsigned char *dgst)
{ unsigned char buf[32]; {
unsigned char buf[32];
int i; int i;
for (i=0;i<32;i++) { for (i=0;i<32;i++)
{
buf[31-i]=dgst[i]; buf[31-i]=dgst[i];
} }
return getbnfrombuf(buf,32); return getbnfrombuf(buf,32);
} }
/* Convert byte buffer to bignum, skipping leading zeros*/ /* Convert byte buffer to bignum, skipping leading zeros*/
BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len) { BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len)
while (*buf==0&&len>0) { {
while (*buf==0&&len>0)
{
buf++; len--; buf++; len--;
} }
if (len) { if (len)
{
return BN_bin2bn(buf,len,NULL); return BN_bin2bn(buf,len,NULL);
} else { }
else
{
BIGNUM *b=BN_new(); BIGNUM *b=BN_new();
BN_zero(b); BN_zero(b);
return b; return b;
} }
} }
/* Pack bignum into byte buffer of given size, filling all leading bytes /* Pack bignum into byte buffer of given size, filling all leading bytes
* by zeros */ * by zeros */
int store_bignum(BIGNUM *bn, unsigned char *buf,int len) { int store_bignum(BIGNUM *bn, unsigned char *buf,int len)
{
int bytes = BN_num_bytes(bn); int bytes = BN_num_bytes(bn);
if (bytes>len) return 0; if (bytes>len) return 0;
memset(buf,0,len); memset(buf,0,len);
BN_bn2bin(bn,buf+len-bytes); BN_bn2bin(bn,buf+len-bytes);
return 1; return 1;
} }

View File

@ -28,37 +28,39 @@
/* Following functions are various bit meshing routines used in /* Following functions are various bit meshing routines used in
* GOST R 34.11-94 algorithms */ * GOST R 34.11-94 algorithms */
static void swap_bytes (byte *w, byte *k) static void swap_bytes (byte *w, byte *k)
{ {
int i,j; int i,j;
for (i=0;i<4;i++) for (i=0;i<4;i++)
for (j=0;j<8;j++) for (j=0;j<8;j++)
k[i+4*j]=w[8*i+j]; k[i+4*j]=w[8*i+j];
} }
/* was A_A */ /* was A_A */
static void circle_xor8 (const byte *w, byte *k) static void circle_xor8 (const byte *w, byte *k)
{ {
byte buf[8]; byte buf[8];
int i; int i;
memcpy(buf,w,8); memcpy(buf,w,8);
memcpy(k,w+8,24); memcpy(k,w+8,24);
for(i=0;i<8;i++) for(i=0;i<8;i++)
k[i+24]=buf[i]^k[i]; k[i+24]=buf[i]^k[i];
} }
/* was R_R */ /* was R_R */
static void transform_3 (byte *data) static void transform_3 (byte *data)
{ {
unsigned short int acc; unsigned short int acc;
acc=(data[0]^data[2]^data[4]^data[6]^data[24]^data[30])| acc=(data[0]^data[2]^data[4]^data[6]^data[24]^data[30])|
((data[1]^data[3]^data[5]^data[7]^data[25]^data[31])<<8); ((data[1]^data[3]^data[5]^data[7]^data[25]^data[31])<<8);
memmove(data,data+2,30); memmove(data,data+2,30);
data[30]=acc&0xff; data[30]=acc&0xff;
data[31]=acc>>8; data[31]=acc>>8;
} }
/* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/ /* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/
static int add_blocks(int n,byte *left, const byte *right) static int add_blocks(int n,byte *left, const byte *right)
{ {
int i; int i;
int carry=0; int carry=0;
int sum; int sum;
@ -69,19 +71,21 @@ static int add_blocks(int n,byte *left, const byte *right)
carry=sum>>8; carry=sum>>8;
} }
return carry; return carry;
} }
/* Xor two sequences of bytes */ /* Xor two sequences of bytes */
static void xor_blocks (byte *result,const byte *a,const byte *b,size_t len) { static void xor_blocks (byte *result,const byte *a,const byte *b,size_t len)
{
size_t i; size_t i;
for (i=0;i<len;i++) result[i]=a[i]^b[i]; for (i=0;i<len;i++) result[i]=a[i]^b[i];
} }
/* /*
* Calculate H(i+1) = Hash(Hi,Mi) * Calculate H(i+1) = Hash(Hi,Mi)
* Where H and M are 32 bytes long * Where H and M are 32 bytes long
*/ */
static int hash_step(gost_ctx *c,byte *H,const byte *M) static int hash_step(gost_ctx *c,byte *H,const byte *M)
{ {
static byte U[32],W[32],V[32],S[32],Key[32]; static byte U[32],W[32],V[32],S[32],Key[32];
int i; int i;
/* Compute first key */ /* Compute first key */
@ -126,20 +130,23 @@ static int hash_step(gost_ctx *c,byte *H,const byte *M)
transform_3(S); transform_3(S);
memcpy(H,S,32); memcpy(H,S,32);
return 1; return 1;
} }
/* Initialize gost_hash ctx - cleans up temporary structures and /* Initialize gost_hash ctx - cleans up temporary structures and
* set up substitution blocks * set up substitution blocks
*/ */
int init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block) { int init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block)
{
memset(ctx,0,sizeof(gost_hash_ctx)); memset(ctx,0,sizeof(gost_hash_ctx));
ctx->cipher_ctx = (gost_ctx *)MYALLOC(sizeof(gost_ctx)); ctx->cipher_ctx = (gost_ctx *)MYALLOC(sizeof(gost_ctx));
if (!ctx->cipher_ctx) { if (!ctx->cipher_ctx)
{
return 0; return 0;
} }
gost_init(ctx->cipher_ctx,subst_block); gost_init(ctx->cipher_ctx,subst_block);
return 1; return 1;
} }
/* /*
* Free cipher CTX if it is dynamically allocated. Do not use * Free cipher CTX if it is dynamically allocated. Do not use
* if cipher ctx is statically allocated as in OpenSSL implementation of * if cipher ctx is statically allocated as in OpenSSL implementation of
@ -147,86 +154,77 @@ int init_gost_hash_ctx(gost_hash_ctx *ctx, const gost_subst_block *subst_block)
* *
*/ */
void done_gost_hash_ctx(gost_hash_ctx *ctx) void done_gost_hash_ctx(gost_hash_ctx *ctx)
{ {
/* No need to use gost_destroy, because cipher keys are not really /* No need to use gost_destroy, because cipher keys are not really
* secret when hashing */ * secret when hashing */
MYFREE(ctx->cipher_ctx); MYFREE(ctx->cipher_ctx);
} }
/* /*
* reset state of hash context to begin hashing new message * reset state of hash context to begin hashing new message
*/ */
int start_hash(gost_hash_ctx *ctx) { int start_hash(gost_hash_ctx *ctx)
{
if (!ctx->cipher_ctx) return 0; if (!ctx->cipher_ctx) return 0;
memset(&(ctx->H),0,32); memset(&(ctx->H),0,32);
memset(&(ctx->S),0,32); memset(&(ctx->S),0,32);
ctx->len = 0L; ctx->len = 0L;
ctx->left=0; ctx->left=0;
return 1; return 1;
} }
/* /*
* Hash block of arbitrary length * Hash block of arbitrary length
* *
* *
*/ */
int hash_block(gost_hash_ctx *ctx,const byte *block, size_t length) { int hash_block(gost_hash_ctx *ctx,const byte *block, size_t length)
{
const byte *curptr=block; const byte *curptr=block;
const byte *barrier=block+(length-32);/* Last byte we can safely hash*/ const byte *barrier=block+(length-32);/* Last byte we can safely hash*/
gost_ctx *save_c = ctx->cipher_ctx; if (ctx->left)
if (ctx->left) { {
/*There are some bytes from previous step*/ /*There are some bytes from previous step*/
int add_bytes = 32-ctx->left; int add_bytes = 32-ctx->left;
if (add_bytes>length) { if (add_bytes>length)
{
add_bytes = length; add_bytes = length;
} }
memcpy(&(ctx->remainder[ctx->left]),block,add_bytes); memcpy(&(ctx->remainder[ctx->left]),block,add_bytes);
ctx->left+=add_bytes; ctx->left+=add_bytes;
if (ctx->left<32) { if (ctx->left<32)
{
return 1; return 1;
} }
if (ctx->left>32) {
abort();
}
curptr=block+add_bytes; curptr=block+add_bytes;
hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder); hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder);
if (save_c!=ctx->cipher_ctx) {
abort();
}
add_blocks(32,ctx->S,ctx->remainder); add_blocks(32,ctx->S,ctx->remainder);
if (save_c!=ctx->cipher_ctx) {
abort();
}
ctx->len+=32; ctx->len+=32;
ctx->left=0; ctx->left=0;
} }
while (curptr<=barrier) while (curptr<=barrier)
{ {
hash_step(ctx->cipher_ctx,ctx->H,curptr); hash_step(ctx->cipher_ctx,ctx->H,curptr);
if (save_c!=ctx->cipher_ctx) {
abort();
}
add_blocks(32,ctx->S,curptr); add_blocks(32,ctx->S,curptr);
if (save_c!=ctx->cipher_ctx) {
abort();
}
ctx->len+=32; ctx->len+=32;
curptr+=32; curptr+=32;
} }
if (curptr!=block+length) { if (curptr!=block+length)
{
ctx->left=block+length-curptr; ctx->left=block+length-curptr;
if (ctx->left>32) {
abort();
}
memcpy(ctx->remainder,curptr,ctx->left); memcpy(ctx->remainder,curptr,ctx->left);
} }
return 1; return 1;
} }
/* /*
* Compute hash value from current state of ctx * Compute hash value from current state of ctx
* state of hash ctx becomes invalid and cannot be used for further * state of hash ctx becomes invalid and cannot be used for further
* hashing. * hashing.
*/ */
int finish_hash(gost_hash_ctx *ctx,byte *hashval) { int finish_hash(gost_hash_ctx *ctx,byte *hashval)
{
byte buf[32]; byte buf[32];
byte H[32]; byte H[32];
byte S[32]; byte S[32];
@ -234,7 +232,8 @@ int finish_hash(gost_hash_ctx *ctx,byte *hashval) {
byte *bptr; byte *bptr;
memcpy(H,ctx->H,32); memcpy(H,ctx->H,32);
memcpy(S,ctx->S,32); memcpy(S,ctx->S,32);
if (ctx->left) { if (ctx->left)
{
memset(buf,0,32); memset(buf,0,32);
memcpy(buf,ctx->remainder,ctx->left); memcpy(buf,ctx->remainder,ctx->left);
hash_step(ctx->cipher_ctx,H,buf); hash_step(ctx->cipher_ctx,H,buf);
@ -244,7 +243,8 @@ int finish_hash(gost_hash_ctx *ctx,byte *hashval) {
memset(buf,0,32); memset(buf,0,32);
bptr=buf; bptr=buf;
fin_len<<=3; /* Hash length in BITS!!*/ fin_len<<=3; /* Hash length in BITS!!*/
while(fin_len>0) { while(fin_len>0)
{
*(bptr++)=fin_len&0xFF; *(bptr++)=fin_len&0xFF;
fin_len>>=8; fin_len>>=8;
}; };
@ -252,5 +252,5 @@ int finish_hash(gost_hash_ctx *ctx,byte *hashval) {
hash_step(ctx->cipher_ctx,H,S); hash_step(ctx->cipher_ctx,H,S);
memcpy(hashval,H,32); memcpy(hashval,H,32);
return 1; return 1;
} }

View File

@ -1,5 +1,5 @@
/********************************************************************** /**********************************************************************
* gosthash.c * * gosthash.h *
* Copyright (c) 2005-2006 Cryptocom LTD * * Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL * * This file is distributed under the same license as OpenSSL *
* * * *

View File

@ -1,42 +0,0 @@
#ifndef GOSTKEYX_H
#define GOSTKEYX_H
/**********************************************************************
* gostkeyx.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Declaration of the key transport functions for GOST pkey methods *
* *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include <openssl/evp.h>
#include "gost89.h"
/* EVP_PKEY_METHOD callbacks */
/* From gost94_keyx.c */
int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len );
int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len);
int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len );
int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * in,size_t in_len);
/* From gost2001_keyx.c */
int pkey_GOST01cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* key, size_t key_len );
int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * key,size_t key_len);
int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char* in, size_t in_len );
int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, const unsigned char * in,size_t in_len);
/* Internal functions to make error processing happy */
int decrypt_cryptocom_key(unsigned char *sess_key,int max_key_len,
const unsigned char *crypted_key,int crypted_key_len, gost_ctx *ctx);
int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
unsigned char *crypted_key, gost_ctx *ctx);
/*int compute_pair_key_le(unsigned char *pair_key,BIGNUM *pub_key,DH *dh) ;*/
/*
* Computes 256 bit key exchange key for CryptoCom variation of GOST 94
* algorithm
*//*
int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key) ;
DH *make_ephemeral_key(EVP_PKEY *pubk,BIGNUM *ephemeral_key);
int make_cp_exchange_key(DH *dh,EVP_PKEY *pubk, unsigned char *shared_key);
*/
#endif

View File

@ -1,78 +0,0 @@
.\" Hey, Emacs! This is an -*- nroff -*- source file.
.TH MD5SUM 1 "29th November 1995" "Lankester et al." "Debian GNU/Linux"
.SH NAME
gostsum \- generates or checks GOST R34.11-94 message digests
.SH SYNOPSIS
.B gostsum
[\-bv] [\-c [file]] | [file...]
.SH DESCRIPTION
.B gostsum
generates or checks GOST hash sums. The algorithm to generate the
is reasonably fast and strong enough for most cases. Exact
specification of the algorithm is in
.I GOST R34.11-94.
Normally
.B gostsum
generates checksums of all files given to it as a parameter and prints
the checksums followed by the filenames. If, however,
.B \-c
is specified, only one filename parameter is allowed. This file should
contain checksums and filenames to which these checksums refer to, and
the files listed in that file are checked against the checksums listed
there. See option
.B \-c
for more information.
.SS OPTIONS
.TP
.B \-b
Use binary mode. In unix environment, only difference between this and
the normal mode is an asterisk preceding the filename in the output.
.TP
.B \-c
Check md5sum of all files listed in
.I file
against the checksum listed in the same file. The actual format of that
file is the same as output of
.B md5sum.
That is, each line in the file describes a file. A line looks like:
.B <hashsum> <filename>
So, for example, if a file was created and its message digest calculated
like so:
.B echo foo > hash\-test\-file; gost5sum hash\-test\-file
.B gost5sum
would report:
.B d3b07384d113edec49eaa6238ad5ff00\ md5\-test\-file
.TP
.B \-v
Be more verbose. Print filenames when checking (with \-c).
.TP
.B -t
Use test parameter set.
.B gostsum supports two sets of parameters (which are really parameters
of GOST 28147-89 block cipher) specified in the IETF draft
.B draft-popov-cryptopro-cpalgs-02.txt
By default, cryptopro paramset is used. This option enables use of test
paramset as specified in appendices to the GOST.
.SH BUGS
This manpage is not quite accurate and has formatting inconsistent
with other manpages.
.B gostsum
does not accept standard options like
.BR \-\-help .
.SH AUTHOR

View File

@ -19,23 +19,23 @@ int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode);
int hash_stream(gost_hash_ctx *ctx,int fd, char *sum); int hash_stream(gost_hash_ctx *ctx,int fd, char *sum);
int get_line(FILE *f,char *hash,char *filename); int get_line(FILE *f,char *hash,char *filename);
void help() void help()
{ {
fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n" fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n"
"\t-c check message digests (default is generate)\n" "\t-c check message digests (default is generate)\n"
"\t-v verbose, print file names when checking\n" "\t-v verbose, print file names when checking\n"
"\t-b read files in binary mode\n" "\t-b read files in binary mode\n"
"\t-t use test GOST paramset (default is CryptoPro paramset)\n" "\t-t use test GOST paramset (default is CryptoPro paramset)\n"
"The input for -c should be the list of message digests and file names\n" "The input for -c should be the list of message digests and file names\n"
"that is printed on stdout by this program when it generates digests.\n"); "that is printed on stdout by this program when it generates digests.\n");
exit(3); exit(3);
} }
#ifndef O_BINARY #ifndef O_BINARY
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
int main(int argc,char **argv) int main(int argc,char **argv)
{ {
int c,i; int c,i;
int verbose=0; int verbose=0;
int errors=0; int errors=0;
@ -51,13 +51,18 @@ int main(int argc,char **argv)
case 'v': verbose=1; break; case 'v': verbose=1; break;
case 't': b= &GostR3411_94_TestParamSet; break; case 't': b= &GostR3411_94_TestParamSet; break;
case 'b': open_mode |= O_BINARY; break; case 'b': open_mode |= O_BINARY; break;
case 'c': if (optarg) { case 'c':
if (optarg)
{
check_file = fopen(optarg,"r"); check_file = fopen(optarg,"r");
if (!check_file) { if (!check_file)
{
perror(optarg); perror(optarg);
exit(2); exit(2);
} }
} else { }
else
{
check_file= stdin; check_file= stdin;
} }
break; break;
@ -82,86 +87,106 @@ int main(int argc,char **argv)
} }
while (get_line(check_file,inhash,filename)) while (get_line(check_file,inhash,filename))
{ {
if (!hash_file(&ctx,filename,calcsum,open_mode)) { if (!hash_file(&ctx,filename,calcsum,open_mode))
{
exit (2); exit (2);
} }
count++; count++;
if (!strncmp(calcsum,inhash,65)) if (!strncmp(calcsum,inhash,65))
{ {
if (verbose) { if (verbose)
{
fprintf(stderr,"%s\tOK\n",filename); fprintf(stderr,"%s\tOK\n",filename);
} }
} else { }
if (verbose) { else
{
if (verbose)
{
fprintf(stderr,"%s\tFAILED\n",filename); fprintf(stderr,"%s\tFAILED\n",filename);
} else { }
else
{
fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n", fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n",
argv[0],filename); argv[0],filename);
} }
failcount++; failcount++;
} }
} }
if (verbose && failcount) { if (verbose && failcount)
{
fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n", fprintf(stderr,"%s: %d of %d file(f) failed GOST hash sum check\n",
argv[0],failcount,count); argv[0],failcount,count);
} }
exit (failcount?1:0); exit (failcount?1:0);
} }
if (optind==argc) { if (optind==argc)
{
char sum[65]; char sum[65];
if (!hash_stream(&ctx,fileno(stdin),sum)) { if (!hash_stream(&ctx,fileno(stdin),sum))
{
perror("stdin"); perror("stdin");
exit(1); exit(1);
} }
printf("%s -\n",sum); printf("%s -\n",sum);
exit(0); exit(0);
} }
for (i=optind;i<argc;i++) { for (i=optind;i<argc;i++)
{
char sum[65]; char sum[65];
if (!hash_file(&ctx,argv[i],sum,open_mode)) { if (!hash_file(&ctx,argv[i],sum,open_mode))
{
errors++; errors++;
} else { }
else
{
printf("%s %s\n",sum,argv[i]); printf("%s %s\n",sum,argv[i]);
} }
} }
exit(errors?1:0); exit(errors?1:0);
} }
int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode) int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode)
{ {
int fd; int fd;
if ((fd=open(filename,mode))<0) { if ((fd=open(filename,mode))<0)
{
perror(filename); perror(filename);
return 0; return 0;
} }
if (!hash_stream(ctx,fd,sum)) { if (!hash_stream(ctx,fd,sum))
{
perror(filename); perror(filename);
return 0; return 0;
} }
close(fd); close(fd);
return 1; return 1;
} }
int hash_stream(gost_hash_ctx *ctx,int fd, char *sum) int hash_stream(gost_hash_ctx *ctx,int fd, char *sum)
{ {
unsigned char buffer[BUF_SIZE]; unsigned char buffer[BUF_SIZE];
ssize_t bytes; ssize_t bytes;
int i; int i;
start_hash(ctx); start_hash(ctx);
while ((bytes=read(fd,buffer,BUF_SIZE))>0) { while ((bytes=read(fd,buffer,BUF_SIZE))>0)
{
hash_block(ctx,buffer,bytes); hash_block(ctx,buffer,bytes);
} }
if (bytes<0) { if (bytes<0)
{
return 0; return 0;
} }
finish_hash(ctx,buffer); finish_hash(ctx,buffer);
for (i=0;i<32;i++) { for (i=0;i<32;i++)
{
sprintf(sum+2*i,"%02x",buffer[31-i]); sprintf(sum+2*i,"%02x",buffer[31-i]);
} }
return 1; return 1;
} }
int get_line(FILE *f,char *hash,char *filename) { int get_line(FILE *f,char *hash,char *filename)
{
int i; int i;
if (fread(hash,1,64,f)<64) return 0; if (fread(hash,1,64,f)<64) return 0;
hash[64]=0; hash[64]=0;
@ -174,11 +199,12 @@ int get_line(FILE *f,char *hash,char *filename) {
return 0; return 0;
} }
} }
if (fgetc(f)!=' ') { if (fgetc(f)!=' ')
{
fprintf(stderr,"Malformed input line\n"); fprintf(stderr,"Malformed input line\n");
return 0; return 0;
} }
i=strlen(fgets(filename,PATH_MAX,f)); i=strlen(fgets(filename,PATH_MAX,f));
while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0; while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0;
return 1; return 1;
} }

View File

@ -1,41 +0,0 @@
#ifndef GOST_MD_H
#define GOST_MD_H
/**********************************************************************
* md.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Declaration of GOST R 34.11 bindings to OpenSSL *
* *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include <unistd.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include "gost89.h"
#include "gosthash.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Structure used as EVP_MD_CTX-md_data.
* It allows to avoid storing in the md-data pointers to
* dynamically allocated memory.
*
* I cannot invent better way to avoid memory leaks, because
* openssl insist on invoking Init on Final-ed digests, and there
* is no reliable way to find out whether pointer in the passed
* md_data is valid or not.
* */
struct ossl_gost_digest_ctx {
gost_hash_ctx dctx;
gost_ctx cctx;
};
extern EVP_MD digest_gost;
#ifdef __cplusplus
};
#endif
#endif

View File

@ -1,22 +0,0 @@
#ifndef CCE_METH_H
#define CCE_METH_H
/**********************************************************************
* meth.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Declaration of method registration functions *
* *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info);
int register_pmeth_gost (int id, EVP_PKEY_METHOD **pmeth, int flags);
#ifdef __cplusplus
};
#endif
#endif

View File

@ -1,26 +0,0 @@
#ifndef GOST_PMETH_H
#define GOST_PMETH_H
/**********************************************************************
* pmeth.h *
* Copyright (c) 2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Declaration of GOST PKEY context internal data *
* *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include <openssl/bn.h>
#include <openssl/evp.h>
/* Gost-specific control-function parameters */
#define param_ctrl_string "paramset"
#define EVP_PKEY_CTRL_GOST_PARAMSET (EVP_PKEY_ALG_CTRL+1)
struct gost_pmeth_data {
int sign_param_nid; /* Should be set whenever parameters are filled */
int crypt_param_nid;
EVP_PKEY *eph_seckey;
EVP_MD *md;
};
#endif

View File

@ -1,30 +0,0 @@
#ifndef GOST_SIGN_H
#define GOST_SIGN_H
/**********************************************************************
* sign.h *
* Copyright (c) 2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Declaration of internal funtions implementing GOST R 34.10 *
* signature and key generation *
* OpenSSL 0.9.9 libraries required to compile and use *
* this code *
**********************************************************************/
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
int fill_GOST94_params(DSA *dsa,int nid);
int fill_GOST2001_params(EC_KEY *eckey, int nid);
int gost_sign_keygen(DSA *dsa) ;
int gost2001_keygen(EC_KEY *ec) ;
DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa) ;
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey);
int gost_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa) ;
int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
DSA_SIG *sig, EC_KEY *ec);
int gost2001_compute_public(EC_KEY *ec) ;
int gost94_compute_public(DSA *dsa) ;
#endif

View File

@ -1,38 +0,0 @@
#ifndef GOST_TOOLS_H
#define GOST_TOOLS_H
/**********************************************************************
* sign.h *
* Copyright (c) 2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* Miscellaneous functions used in GOST engine *
* OpenSSL 0.9.9 libraries required to compile and use *
* this code *
**********************************************************************/
#include <openssl/evp.h>
#include <openssl/dsa.h>
/* from gost_sign.c */
/* Convert GOST R 34.11 hash sum to bignum according to standard */
BIGNUM *hashsum2bn(const unsigned char *dgst) ;
/* Store bignum in byte array of given length, prepending by zeros
* if nesseccary */
int store_bignum(BIGNUM *bn, unsigned char *buf,int len);
/* Read bignum, which can have few MSB all-zeros from buffer*/
BIGNUM *getbnfrombuf(const unsigned char *buf,size_t len);
/* Pack GOST R 34.10 signature according to CryptoCom rules */
int pack_sign_cc(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen);
/* Pack GOST R 34.10 signature according to CryptoPro rules */
int pack_sign_cp(DSA_SIG *s,int order,unsigned char *sig, unsigned int *siglen);
/* Unpack GOST R 34.10 signature according to CryptoCom rules */
DSA_SIG *unpack_cc_signature(const unsigned char *sig,size_t siglen) ;
/* Unpack GOST R 34.10 signature according to CryptoPro rules */
DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen) ;
/* from ameth.c */
/* Get private key as BIGNUM from both R 34.10-94 and R 34.10-2001 keys*/
BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey) ;
/* Find NID by GOST 94 parameters */
int gost94_nid_by_params(DSA *p) ;
#endif