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
THISDIR?=$(shell perl -MCwd -e 'print getcwd')
OPENSSL_DIR?=$(THISDIR)/../openssl
ENGINE_ID?=gost
TESTSUITE_DIR?=$(THISDIR)/test-suite
FOR?=$(HOST)
CC=gcc
CFLAGS=-fPIC -g -Wall -I$(OPENSSL_DIR)/include
LDFLAGS=-g -L $(OPENSSL_DIR) -static-libgcc
ifeq "$(FOR)" "s64"
CFLAGS+=-m64
LDFLAGS+=-m64
endif
OS:=$(shell uname -s)
ifeq "$(OS)" "FreeBSD"
LIBDIR:=$(shell LD_LIBRARY_PATH=$(OPENSSL_DIR) $(OPENSSL_DIR)/apps/openssl version -d|sed -e 's/^[^"]*"//' -e 's/".*$$//')/lib
LDFLAGS+=-rpath $(LIBDIR)
endif
DIR=ccgost
TOP=../..
CC=cc
INCLUDES= -I../../include
CFLAG=-g
MAKEFILE= Makefile
AR= ar r
CFLAGS= $(INCLUDES) $(CFLAG)
LIB=$(TOP)/libcrypto.a
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
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
SRC=$(LIBSRC)
LIBNAME=gost
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)
DLLSUFFIX=.dll
EXESUFFIX=.exe
CFLAGS+=-mno-cygwin
LDFLAGS+=-mno-cygwin
ifeq "$(OS)" "Linux"
CC=i586-mingw32msvc-gcc
endif
LIBS=-lcrypto.dll
else
ENGINE_LIB?=lib$(ENGINE_ID)$(DLLSUFFIX)
LIBS=-lcrypto
DLLSUFFIX=.so
endif
export DLLSUFFIX
export EXESUFFIX
ifneq "$(FOR)" ""
export FOR
endif
CFLAGS+=$(DEBUG_FLAGS)
export ENGINE_LIB
ENG_SOURCES=md_gost.c gost_crypt.c gost_asn1.c ameth.c pmeth.c\
gost_crypt.c gost_sign.c gost2001.c md_gost.c gost_crypt.c\
engine.c gost94_keyx.c keywrap.c gost2001_keyx.c
all: $(ENGINE_LIB) openssl.cnf
buildtests:
$(ENGINE_LIB): e_gost_err.o engine.o ameth.o pmeth.o params.o md_gost.o gosthash.o gost89.o gost_sign.o gost_crypt.o keywrap.o gost2001.o gost94_keyx.o gost2001_keyx.o gost_asn1.o
$(CC) $(LDFLAGS) -shared -o $@ $+ $(LIBS) $(LDFLAGS)
openssl.cnf: openssl.cnf.1 openssl.cnf.2
cat $+ > $@
openssl.cnf.1:
echo "openssl_conf = openssl_def" > $@
openssl.cnf.2:
echo "[openssl_def]" > $@
echo "engines = engine_section" >> $@
echo "[engine_section]" >> $@
echo "$(ENGINE_ID) = $(ENGINE_ID)_section" >> $@
echo "[$(ENGINE_ID)_section]" >> $@
echo "dynamic_path = $(THISDIR)/$(ENGINE_LIB)" >> $@
echo "engine_id = $(ENGINE_ID)" >> $@
echo "default_algorithms = ALL" >> $@
gosthash1.o: gosthash.c
$(CC) -c $(CFLAGS) -o $@ -DOPENSSL_BUILD $+
gostsum: gostsum.o gosthash.o gost89.o
inttests: gosttest$(EXESUFFIX) etalon wraptest$(EXESUFFIX) etalon.wrap ectest$(EXESUFFIX) etalon.ec
./gosttest${EXESUFFIX} > gost_test
diff -uw gost_test etalon
./wraptest$(EXESUFFIX) > wrap_test
diff -uw wrap_test etalon.wrap
./ectest$(EXESUFFIX) > ec_test 2>&1
diff -uw ec_test etalon.ec
ectest$(EXESUFFIX): ectest.o gost2001_dbg.o gost_sign_dbg.o params.o e_gost_err.o
$(CC) -o $@ $(LDFLAGS) $+ -lcrypto
%_dbg.o: %.c
$(CC) -c $(CFLAGS) -DDEBUG_SIGN -DDEBUG_KEYS -o $@ $+
gosttest$(EXESUFFIX): gosttest.o gosthash.o gost89.o
$(CC) $(LDFLAGS) -o $@ $+
wraptest$(EXESUFFIX): wraptest.c keywrap.c gost89.c
$(CC) -DDEBUG_DH $(LDFLAGS) -o $@ $+
sign_ex: LOADLIBES=-lcrypto
sign_ex: sign_ex.o
lint:
lint -DLINT $(INCLUDES) $(SRC)>fluff
dclean:
$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
mv -f Makefile.new $(MAKEFILE)
clean:
rm -f core gosttest gostsum *.o gost_test openssl.cnf* $(ENGINE_LIB)
if [ -f t/Makefile ]; then $(MAKE) -C t clean; fi
if [ -f $(TESTSUITE_DIR)/Makefile ]; then $(MAKE) -C $(TESTSUITE_DIR) clean; fi
e_gost_err.c e_gost_err.h: $(ENG_SOURCES) gost.ec e_gost_err.proto
perl $(OPENSSL_DIR)/util/mkerr.pl -conf gost.ec -nostatic -debug -write $(ENG_SOURCES)
rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff *.so *.sl *.dll
tests: openssl.cnf.2
OPENSSL_DIR=$(OPENSSL_DIR) $(MAKE) -C $(TESTSUITE_DIR) CONFADD=$(THISDIR)/openssl.cnf.2
# depedencies
#
#
gost_sign.o: gost_sign.c sign.h paramset.h tools.h e_gost_err.h
pmeth.o: pmeth.c meth.h pmeth.h sign.h paramset.h e_gost_err.h
ameth.o: ameth.c tools.h meth.h pmeth.h gost_asn1.h crypt.h e_gost_err.h paramset.h
keywrap.o: keywrap.c gost89.h keywrap.h
gost2001.o: gost2001.c tools.h sign.h paramset.h e_gost_err.h
engine.o: engine.c md.h crypt.h meth.h e_gost_err.h
# DO NOT DELETE THIS LINE -- make depend depends on it.
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
gost_asn1.o: gost_asn1.c gost_asn1.h
gost_crypt.o: gost_crypt.c crypt.h gost89.h e_gost_err.h gost_asn1.h
gosthash.o: gosthash.c gost89.h gosthash.h
md_gost.o: md_gost.c md.h gosthash.h e_gost_err.h
params.o: params.c paramset.h
gost94_keyx.o: gost94_keyx.c gost_asn1.h gost89.h gosthash.h crypt.h pmeth.h keywrap.h e_gost_err.h gostkeyx.h
gost2001_keyx.o: gost2001_keyx.c gost89.h gost_asn1.h e_gost_err.h keywrap.h crypt.h sign.h gostkeyx.h pmeth.h gosthash.h tools.h
gost94_keyx.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
gost94_keyx.o: ../../include/openssl/bio.h ../../include/openssl/bn.h
gost94_keyx.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
gost94_keyx.o: ../../include/openssl/dh.h ../../include/openssl/dsa.h
gost94_keyx.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
gost94_keyx.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
gost94_keyx.o: ../../include/openssl/engine.h ../../include/openssl/evp.h
gost94_keyx.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
gost94_keyx.o: ../../include/openssl/objects.h
gost94_keyx.o: ../../include/openssl/opensslconf.h
gost94_keyx.o: ../../include/openssl/opensslv.h
gost94_keyx.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
gost94_keyx.o: ../../include/openssl/rand.h ../../include/openssl/safestack.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,95 +70,95 @@
static ERR_STRING_DATA GOST_str_functs[]=
{
{ERR_FUNC(GOST_F_DECODE_GOST_ALGOR_PARAMS), "DECODE_GOST_ALGOR_PARAMS"},
{ERR_FUNC(GOST_F_DECRYPT_CRYPTOCOM_KEY), "decrypt_cryptocom_key"},
{ERR_FUNC(GOST_F_ENCODE_GOST_ALGOR_PARAMS), "ENCODE_GOST_ALGOR_PARAMS"},
{ERR_FUNC(GOST_F_FILL_GOST2001_PARAMS), "FILL_GOST2001_PARAMS"},
{ERR_FUNC(GOST_F_FILL_GOST94_PARAMS), "FILL_GOST94_PARAMS"},
{ERR_FUNC(GOST_F_GET_ENCRYPTION_PARAMS), "get_encryption_params"},
{ERR_FUNC(GOST_F_GOST2001_COMPUTE_PUBLIC), "GOST2001_COMPUTE_PUBLIC"},
{ERR_FUNC(GOST_F_GOST2001_DO_SIGN), "GOST2001_DO_SIGN"},
{ERR_FUNC(GOST_F_GOST2001_DO_VERIFY), "GOST2001_DO_VERIFY"},
{ERR_FUNC(GOST_F_GOST89_GET_ASN1_PARAMETERS), "gost89_get_asn1_parameters"},
{ERR_FUNC(GOST_F_GOST89_SET_ASN1_PARAMETERS), "gost89_set_asn1_parameters"},
{ERR_FUNC(GOST_F_GOST94_COPY_PARAMETERS), "GOST94_COPY_PARAMETERS"},
{ERR_FUNC(GOST_F_GOST_CIPHER_CTL), "gost_cipher_ctl"},
{ERR_FUNC(GOST_F_GOST_COMPUTE_PUBLIC), "GOST_COMPUTE_PUBLIC"},
{ERR_FUNC(GOST_F_GOST_DO_SIGN), "GOST_DO_SIGN"},
{ERR_FUNC(GOST_F_GOST_DO_VERIFY), "GOST_DO_VERIFY"},
{ERR_FUNC(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001), "MAKE_RFC4490_KEYTRANSPORT_2001"},
{ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"},
{ERR_FUNC(GOST_F_PARAM_COPY_GOST94), "PARAM_COPY_GOST94"},
{ERR_FUNC(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT), "PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT"},
{ERR_FUNC(GOST_F_PKCS7_GOST94_KEY_TRANSPORT_DECRYPT), "PKCS7_GOST94_KEY_TRANSPORT_DECRYPT"},
{ERR_FUNC(GOST_F_PKEY_GOST01CC_DECRYPT), "pkey_GOST01cc_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01CC_ENCRYPT), "pkey_GOST01cc_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01CP_ENCRYPT), "pkey_GOST01cp_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01_KEYGEN), "PKEY_GOST01_KEYGEN"},
{ERR_FUNC(GOST_F_PKEY_GOST94CC_DECRYPT), "pkey_GOST94cc_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CC_ENCRYPT), "pkey_GOST94cc_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CP_DECRYPT), "pkey_GOST94cp_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CP_ENCRYPT), "pkey_GOST94cp_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94_KEYGEN), "PKEY_GOST94_KEYGEN"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL), "PKEY_GOST_CTRL"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL01_STR), "PKEY_GOST_CTRL01_STR"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL94_STR), "PKEY_GOST_CTRL94_STR"},
{ERR_FUNC(GOST_F_PRIV_DECODE_GOST_94), "PRIV_DECODE_GOST_94"},
{ERR_FUNC(GOST_F_PUB_DECODE_GOST01), "PUB_DECODE_GOST01"},
{ERR_FUNC(GOST_F_PUB_DECODE_GOST94), "PUB_DECODE_GOST94"},
{ERR_FUNC(GOST_F_PUB_ENCODE_GOST01), "PUB_ENCODE_GOST01"},
{ERR_FUNC(GOST_F_UNPACK_CC_SIGNATURE), "UNPACK_CC_SIGNATURE"},
{ERR_FUNC(GOST_F_UNPACK_CP_SIGNATURE), "UNPACK_CP_SIGNATURE"},
{0,NULL}
{ERR_FUNC(GOST_F_DECODE_GOST_ALGOR_PARAMS), "DECODE_GOST_ALGOR_PARAMS"},
{ERR_FUNC(GOST_F_DECRYPT_CRYPTOCOM_KEY), "decrypt_cryptocom_key"},
{ERR_FUNC(GOST_F_ENCODE_GOST_ALGOR_PARAMS), "ENCODE_GOST_ALGOR_PARAMS"},
{ERR_FUNC(GOST_F_FILL_GOST2001_PARAMS), "FILL_GOST2001_PARAMS"},
{ERR_FUNC(GOST_F_FILL_GOST94_PARAMS), "FILL_GOST94_PARAMS"},
{ERR_FUNC(GOST_F_GET_ENCRYPTION_PARAMS), "get_encryption_params"},
{ERR_FUNC(GOST_F_GOST2001_COMPUTE_PUBLIC), "GOST2001_COMPUTE_PUBLIC"},
{ERR_FUNC(GOST_F_GOST2001_DO_SIGN), "GOST2001_DO_SIGN"},
{ERR_FUNC(GOST_F_GOST2001_DO_VERIFY), "GOST2001_DO_VERIFY"},
{ERR_FUNC(GOST_F_GOST89_GET_ASN1_PARAMETERS), "gost89_get_asn1_parameters"},
{ERR_FUNC(GOST_F_GOST89_SET_ASN1_PARAMETERS), "gost89_set_asn1_parameters"},
{ERR_FUNC(GOST_F_GOST94_COPY_PARAMETERS), "GOST94_COPY_PARAMETERS"},
{ERR_FUNC(GOST_F_GOST_CIPHER_CTL), "gost_cipher_ctl"},
{ERR_FUNC(GOST_F_GOST_COMPUTE_PUBLIC), "GOST_COMPUTE_PUBLIC"},
{ERR_FUNC(GOST_F_GOST_DO_SIGN), "GOST_DO_SIGN"},
{ERR_FUNC(GOST_F_GOST_DO_VERIFY), "GOST_DO_VERIFY"},
{ERR_FUNC(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001), "MAKE_RFC4490_KEYTRANSPORT_2001"},
{ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"},
{ERR_FUNC(GOST_F_PARAM_COPY_GOST94), "PARAM_COPY_GOST94"},
{ERR_FUNC(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT), "PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT"},
{ERR_FUNC(GOST_F_PKCS7_GOST94_KEY_TRANSPORT_DECRYPT), "PKCS7_GOST94_KEY_TRANSPORT_DECRYPT"},
{ERR_FUNC(GOST_F_PKEY_GOST01CC_DECRYPT), "pkey_GOST01cc_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01CC_ENCRYPT), "pkey_GOST01cc_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01CP_ENCRYPT), "pkey_GOST01cp_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST01_KEYGEN), "PKEY_GOST01_KEYGEN"},
{ERR_FUNC(GOST_F_PKEY_GOST94CC_DECRYPT), "pkey_GOST94cc_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CC_ENCRYPT), "pkey_GOST94cc_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CP_DECRYPT), "pkey_GOST94cp_decrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94CP_ENCRYPT), "pkey_GOST94cp_encrypt"},
{ERR_FUNC(GOST_F_PKEY_GOST94_KEYGEN), "PKEY_GOST94_KEYGEN"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL), "PKEY_GOST_CTRL"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL01_STR), "PKEY_GOST_CTRL01_STR"},
{ERR_FUNC(GOST_F_PKEY_GOST_CTRL94_STR), "PKEY_GOST_CTRL94_STR"},
{ERR_FUNC(GOST_F_PRIV_DECODE_GOST_94), "PRIV_DECODE_GOST_94"},
{ERR_FUNC(GOST_F_PUB_DECODE_GOST01), "PUB_DECODE_GOST01"},
{ERR_FUNC(GOST_F_PUB_DECODE_GOST94), "PUB_DECODE_GOST94"},
{ERR_FUNC(GOST_F_PUB_ENCODE_GOST01), "PUB_ENCODE_GOST01"},
{ERR_FUNC(GOST_F_UNPACK_CC_SIGNATURE), "UNPACK_CC_SIGNATURE"},
{ERR_FUNC(GOST_F_UNPACK_CP_SIGNATURE), "UNPACK_CP_SIGNATURE"},
{0,NULL}
};
static ERR_STRING_DATA GOST_str_reasons[]=
{
{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"},
{ERR_REASON(GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT),"ctx not initialized for encrypt"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_MAC) ,"error computing mac"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"},
{ERR_REASON(GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO),"error packing key transport info"},
{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
{ERR_REASON(GOST_R_ERROR_STORING_ENCRYPTED_KEY),"error storing encrypted key"},
{ERR_REASON(GOST_R_ERROR_STORING_IV) ,"error storing iv"},
{ERR_REASON(GOST_R_ERROR_STORING_MAC) ,"error storing mac"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
{ERR_REASON(GOST_R_INVALID_ENCRYPTED_KEY_SIZE),"invalid encrypted key size"},
{ERR_REASON(GOST_R_INVALID_GOST94_PARMSET),"invalid gost94 parmset"},
{ERR_REASON(GOST_R_INVALID_IV_LENGTH) ,"invalid iv length"},
{ERR_REASON(GOST_R_INVALID_PARAMSET) ,"invalid paramset"},
{ERR_REASON(GOST_R_KEY_IS_NOT_INITALIZED),"key is not initalized"},
{ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED),"key is not initialized"},
{ERR_REASON(GOST_R_KEY_PARAMETERS_MISSING),"key parameters missing"},
{ERR_REASON(GOST_R_MALLOC_FAILURE) ,"malloc failure"},
{ERR_REASON(GOST_R_NOT_ENOUGH_SPACE_FOR_KEY),"not enough space for key"},
{ERR_REASON(GOST_R_NO_MEMORY) ,"no memory"},
{ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"},
{ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"},
{ERR_REASON(GOST_R_RANDOM_GENERATOR_ERROR),"random generator error"},
{ERR_REASON(GOST_R_RANDOM_GENERATOR_FAILURE),"random generator failure"},
{ERR_REASON(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED),"random number generator failed"},
{ERR_REASON(GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH),"session key mac does not match"},
{ERR_REASON(GOST_R_SIGNATURE_MISMATCH) ,"signature mismatch"},
{ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"},
{ERR_REASON(GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND),"unsupported cipher ctl command"},
{ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"},
{0,NULL}
{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"},
{ERR_REASON(GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT),"ctx not initialized for encrypt"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_MAC) ,"error computing mac"},
{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"},
{ERR_REASON(GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO),"error packing key transport info"},
{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
{ERR_REASON(GOST_R_ERROR_STORING_ENCRYPTED_KEY),"error storing encrypted key"},
{ERR_REASON(GOST_R_ERROR_STORING_IV) ,"error storing iv"},
{ERR_REASON(GOST_R_ERROR_STORING_MAC) ,"error storing mac"},
{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAMS),"invalid cipher params"},
{ERR_REASON(GOST_R_INVALID_CIPHER_PARAM_OID),"invalid cipher param oid"},
{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE) ,"invalid digest type"},
{ERR_REASON(GOST_R_INVALID_ENCRYPTED_KEY_SIZE),"invalid encrypted key size"},
{ERR_REASON(GOST_R_INVALID_GOST94_PARMSET),"invalid gost94 parmset"},
{ERR_REASON(GOST_R_INVALID_IV_LENGTH) ,"invalid iv length"},
{ERR_REASON(GOST_R_INVALID_PARAMSET) ,"invalid paramset"},
{ERR_REASON(GOST_R_KEY_IS_NOT_INITALIZED),"key is not initalized"},
{ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED),"key is not initialized"},
{ERR_REASON(GOST_R_KEY_PARAMETERS_MISSING),"key parameters missing"},
{ERR_REASON(GOST_R_MALLOC_FAILURE) ,"malloc failure"},
{ERR_REASON(GOST_R_NOT_ENOUGH_SPACE_FOR_KEY),"not enough space for key"},
{ERR_REASON(GOST_R_NO_MEMORY) ,"no memory"},
{ERR_REASON(GOST_R_NO_PARAMETERS_SET) ,"no parameters set"},
{ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"},
{ERR_REASON(GOST_R_RANDOM_GENERATOR_ERROR),"random generator error"},
{ERR_REASON(GOST_R_RANDOM_GENERATOR_FAILURE),"random generator failure"},
{ERR_REASON(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED),"random number generator failed"},
{ERR_REASON(GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH),"session key mac does not match"},
{ERR_REASON(GOST_R_SIGNATURE_MISMATCH) ,"signature mismatch"},
{ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"},
{ERR_REASON(GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND),"unsupported cipher ctl command"},
{ERR_REASON(GOST_R_UNSUPPORTED_PARAMETER_SET),"unsupported parameter set"},
{0,NULL}
};
#endif
#ifdef GOST_LIB_NAME
static ERR_STRING_DATA GOST_lib_name[]=
{
{0 ,GOST_LIB_NAME},
{0,NULL}
{
{0 ,GOST_LIB_NAME},
{0,NULL}
};
#endif

View file

@ -6,9 +6,8 @@
* Implementation of GOST R 34.10-2001 *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include "tools.h"
#include "sign.h"
#include "paramset.h"
#include "gost_lcl.h"
#include "gost_params.h"
#include <string.h>
#include <openssl/rand.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
* 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;
EC_GROUP *grp;
EC_GROUP *grp=NULL;
BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL;
EC_POINT *P=NULL;
BN_CTX *ctx=BN_CTX_new();
@ -48,10 +48,11 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) {
y=BN_CTX_get(ctx);
q=BN_CTX_get(ctx);
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);
goto err;
}
}
BN_hex2bn(&p,params->p);
BN_hex2bn(&a,params->a);
BN_hex2bn(&b,params->b);
@ -66,7 +67,7 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) {
BN_hex2bn(&q,params->q);
#ifdef DEBUG_KEYS
fprintf(stderr,"Set params index %d oid %s\nq=",
(params-R3410_2001_paramset),OBJ_nid2sn(params->nid));
(params-R3410_2001_paramset),OBJ_nid2sn(params->nid));
BN_print_fp(stderr,q);
fprintf(stderr,"\n");
#endif
@ -76,14 +77,13 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) {
EC_KEY_set_group(eckey,grp);
ok=1;
err:
err:
EC_POINT_free(P);
EC_GROUP_free(grp);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
}
/*
@ -91,88 +91,96 @@ err:
*
*
*/
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey) {
DSA_SIG *newsig = NULL;
BIGNUM *md = hashsum2bn(dgst);
BIGNUM *order = NULL;
const EC_GROUP *group;
const BIGNUM *priv_key;
BIGNUM *r=NULL,*s=NULL,*X=NULL,*tmp=NULL,*tmp2=NULL, *k=NULL,*e=NULL;
EC_POINT *C=NULL;
BN_CTX *ctx = BN_CTX_new();
BN_CTX_start(ctx);
OPENSSL_assert(dlen==32);
newsig=DSA_SIG_new();
if (!newsig)
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
{
DSA_SIG *newsig = NULL;
BIGNUM *md = hashsum2bn(dgst);
BIGNUM *order = NULL;
const EC_GROUP *group;
const BIGNUM *priv_key;
BIGNUM *r=NULL,*s=NULL,*X=NULL,*tmp=NULL,*tmp2=NULL, *k=NULL,*e=NULL;
EC_POINT *C=NULL;
BN_CTX *ctx = BN_CTX_new();
BN_CTX_start(ctx);
OPENSSL_assert(dlen==32);
newsig=DSA_SIG_new();
if (!newsig)
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY);
goto err;
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY);
goto err;
}
group = EC_KEY_get0_group(eckey);
order=BN_CTX_get(ctx);
EC_GROUP_get_order(group,order,ctx);
priv_key = EC_KEY_get0_private_key(eckey);
e = BN_CTX_get(ctx);
BN_mod(e,md,order,ctx);
group = EC_KEY_get0_group(eckey);
order=BN_CTX_get(ctx);
EC_GROUP_get_order(group,order,ctx);
priv_key = EC_KEY_get0_private_key(eckey);
e = BN_CTX_get(ctx);
BN_mod(e,md,order,ctx);
#ifdef DEBUG_SIGN
fprintf(stderr,"digest as bignum=");
BN_print_fp(stderr,md);
fprintf(stderr,"\ndigest mod q=");
BN_print_fp(stderr,e);
fprintf(stderr,"\n");
fprintf(stderr,"digest as bignum=");
BN_print_fp(stderr,md);
fprintf(stderr,"\ndigest mod q=");
BN_print_fp(stderr,e);
fprintf(stderr,"\n");
#endif
if (BN_is_zero(e))
if (BN_is_zero(e))
{
BN_one(e);
BN_one(e);
}
k =BN_CTX_get(ctx);
C=EC_POINT_new(group);
do {
do {
if (!BN_rand_range(k,order))
k =BN_CTX_get(ctx);
C=EC_POINT_new(group);
do
{
do
{
if (!BN_rand_range(k,order))
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
DSA_SIG_free(newsig);
goto err;
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
DSA_SIG_free(newsig);
goto err;
}
if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
DSA_SIG_free(newsig);
goto err;
if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx))
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
DSA_SIG_free(newsig);
goto err;
}
if (!X) X=BN_CTX_get(ctx);
if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
DSA_SIG_free(newsig);
goto err;
if (!X) X=BN_CTX_get(ctx);
if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx))
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
DSA_SIG_free(newsig);
goto err;
}
if (!r) r=BN_CTX_get(ctx);
BN_nnmod(r,X,order,ctx);
} while (BN_is_zero(r));
/* s = (r*priv_key+k*e) mod order */
if (!tmp) tmp = BN_CTX_get(ctx);
BN_mod_mul(tmp,priv_key,r,order,ctx);
if (!tmp2) tmp2 = BN_CTX_get(ctx);
BN_mod_mul(tmp2,k,e,order,ctx);
if (!s) s=BN_CTX_get(ctx);
BN_mod_add(s,tmp,tmp2,order,ctx);
} while (BN_is_zero(s));
if (!r) r=BN_CTX_get(ctx);
BN_nnmod(r,X,order,ctx);
}
while (BN_is_zero(r));
/* s = (r*priv_key+k*e) mod order */
if (!tmp) tmp = BN_CTX_get(ctx);
BN_mod_mul(tmp,priv_key,r,order,ctx);
if (!tmp2) tmp2 = BN_CTX_get(ctx);
BN_mod_mul(tmp2,k,e,order,ctx);
if (!s) s=BN_CTX_get(ctx);
BN_mod_add(s,tmp,tmp2,order,ctx);
}
while (BN_is_zero(s));
newsig->s=BN_dup(s);
newsig->r=BN_dup(r);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(C);
BN_free(md);
return newsig;
}
newsig->s=BN_dup(s);
newsig->r=BN_dup(r);
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(C);
BN_free(md);
return newsig;
}
/*
* Verifies gost 2001 signature
*
*/
int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
DSA_SIG *sig, EC_KEY *ec) {
DSA_SIG *sig, EC_KEY *ec)
{
BN_CTX *ctx=BN_CTX_new();
const EC_GROUP *group = EC_KEY_get0_group(ec);
BIGNUM *order;
@ -196,11 +204,11 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
pub_key = EC_KEY_get0_public_key(ec);
if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
(BN_cmp(sig->s,order)>=1) || (BN_cmp(sig->r,order)>=1))
{
GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
goto err;
{
GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
goto err;
}
}
md = hashsum2bn(dgst);
BN_mod(e,md,order,ctx);
@ -225,15 +233,15 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
#endif
C = EC_POINT_new(group);
if (!EC_POINT_mul(group,C,z1,pub_key,z2,ctx))
{
{
GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB);
goto err;
}
}
if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx))
{
{
GOSTerr(GOST_F_GOST2001_DO_VERIFY,ERR_R_EC_LIB);
goto err;
}
}
BN_mod(R,X,order,ctx);
#ifdef DEBUG_SIGN
fprintf(stderr,"\nX=");
@ -242,83 +250,91 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
BN_print_fp(stderr,R);
fprintf(stderr,"\n");
#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);
} else {
}
else
{
ok = 1;
}
err:
}
err:
EC_POINT_free(C);
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_free(md);
return ok;
}
}
/*
* Computes GOST R 34.10-2001 public key
*
*
*/
int gost2001_compute_public(EC_KEY *ec)
{
{
const EC_GROUP *group = EC_KEY_get0_group(ec);
EC_POINT *pub_key=NULL;
const BIGNUM *priv_key=NULL;
BN_CTX *ctx=NULL;
int ok=0;
if (!group) {
if (!group)
{
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,GOST_R_KEY_IS_NOT_INITIALIZED);
return 0;
}
}
ctx=BN_CTX_new();
BN_CTX_start(ctx);
if (!(priv_key=EC_KEY_get0_private_key(ec)))
{
{
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB);
goto err;
}
}
pub_key = EC_POINT_new(group);
if (!EC_POINT_mul(group,pub_key,priv_key,NULL,NULL,ctx))
{
{
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB);
goto err;
}
if (!EC_KEY_set_public_key(ec,pub_key)) {
}
if (!EC_KEY_set_public_key(ec,pub_key))
{
GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC,ERR_R_EC_LIB);
goto err;
}
}
ok = 256;
err:
err:
BN_CTX_end(ctx);
EC_POINT_free(pub_key);
BN_CTX_free(ctx);
return ok;
}
}
/*
*
* Generates GOST R 34.10-2001 keypair
*
*
*/
int gost2001_keygen(EC_KEY *ec) {
int gost2001_keygen(EC_KEY *ec)
{
BIGNUM *order = BN_new(),*d=BN_new();
const EC_GROUP *group = EC_KEY_get0_group(ec);
EC_GROUP_get_order(group,order,NULL);
do {
if (!BN_rand_range(d,order))
do
{
if (!BN_rand_range(d,order))
{
GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
BN_free(d);
BN_free(order);
return 0;
}
} while (BN_is_zero(d));
}
}
while (BN_is_zero(d));
EC_KEY_set_private_key(ec,d);
BN_free(d);
BN_free(order);
return gost2001_compute_public(ec);
}
}

View file

@ -13,49 +13,48 @@
#include <openssl/objects.h>
#include "gost89.h"
#include "gosthash.h"
#include "gost_asn1.h"
#include "e_gost_err.h"
#include "keywrap.h"
#include "crypt.h"
#include "sign.h"
#include "pmeth.h"
#include "tools.h"
#include "gostkeyx.h"
#include "gost_keywrap.h"
#include "gost_lcl.h"
/* Transform ECDH shared key into little endian as required by Cryptocom
* 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;
char* outbuf= out;
int i;
if (*outlen < inlen) {
return NULL;
}
for (i=0;i<inlen;i++) {
if (*outlen < inlen)
{
return NULL;
}
for (i=0;i<inlen;i++)
{
outbuf[inlen-1-i]=inbuf[i];
}
}
*outlen = inlen;
return out;
}
}
/* 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_copy(out,peer_key);
EC_KEY_set_private_key(out,seckey);
gost2001_compute_public(out);
return out;
}
}
/* Packs GOST elliptic curve key into EVP_PKEY setting same parameters
* as in passed pubkey
*/
static EVP_PKEY *ec_ephemeral_key_to_EVP(EVP_PKEY *pubk,int type,EC_KEY *ephemeral)
{
{
EVP_PKEY *newkey;
newkey = EVP_PKEY_new();
EVP_PKEY_assign(newkey,type,ephemeral);
return newkey;
}
}
/*
* 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,
size_t *out_len, const unsigned char *key,size_t key_len)
{
{
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
GOST_KEY_TRANSPORT *gkt = NULL;
@ -73,66 +72,68 @@ int pkey_GOST01cc_encrypt (EVP_PKEY_CTX *pctx,unsigned char *out,
EC_KEY *ephemeral=NULL;
const EC_POINT *pub_key_point=NULL;
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};
ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk), gost_get_priv_key(data->eph_seckey));
if (!ephemeral) goto err;
/* compute shared key */
pub_key_point=EC_KEY_get0_public_key(EVP_PKEY_get0(pubk));
if (!ECDH_compute_key(shared_key,32,pub_key_point,ephemeral,make_key_le))
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err;
}
}
/* encrypt session key */
gost_init(&ctx, &GostR3411_94_CryptoProParamSet);
gost_key(&ctx,shared_key);
encrypt_cryptocom_key(key,key_len,encrypted_key,&ctx);
/* compute hmac of session key */
if (!gost_mac(&ctx,32,key,32,hmac))
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_COMPUTING_MAC);
return -1;
}
}
gkt = GOST_KEY_TRANSPORT_new();
if (!gkt)
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_NO_MEMORY);
return -1;
}
}
/* Store IV which is always zero in our case */
if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,iv,8))
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_IV);
goto err;
}
}
if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,hmac,4))
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_MAC);
goto err;
}
}
if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,encrypted_key,32))
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY);
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);
goto err;
}
}
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(NID_id_Gost28147_89_cc);
if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret = 1;
;
err:
err:
if (gkt) GOST_KEY_TRANSPORT_free(gkt);
return ret;
}
}
/*
* EVP_PKEY_METHOD callback decrypt
* 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 */
EVP_PKEY *priv=EVP_PKEY_CTX_get0_pkey(pctx);
GOST_KEY_TRANSPORT *gkt = NULL;
@ -145,17 +146,19 @@ int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
const EC_POINT *pub_key_point;
EVP_PKEY *eph_key;
if (!key) {
if (!key)
{
*key_len = 32;
return 1;
}
}
/* Parse passed octet string and find out public key, iv and HMAC*/
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len);
if (!gkt) {
in_len);
if (!gkt)
{
GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return 0;
}
}
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
/* Initialization vector is really ignored here */
OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8);
@ -168,37 +171,40 @@ int pkey_GOST01cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
i=ECDH_compute_key(shared_key,32,pub_key_point,EVP_PKEY_get0(priv),make_key_le);
EVP_PKEY_free(eph_key);
if (!i)
{
{
GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
GOST_KEY_TRANSPORT_free(gkt);
return 0;
}
}
/* Decrypt session key */
gost_init(&ctx, &GostR3411_94_CryptoProParamSet);
gost_key(&ctx,shared_key);
if (!decrypt_cryptocom_key(key,*key_len,gkt->key_info->encrypted_key->data,
gkt->key_info->encrypted_key->length, &ctx))
{
{
GOST_KEY_TRANSPORT_free(gkt);
return 0;
}
}
GOST_KEY_TRANSPORT_free(gkt);
/* 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);
return 0;
}
/* HMAC of session key is not correct */
if (memcmp(hmac,hmac_comp,4)!=0) {
}
/* HMAC of session key is not correct */
if (memcmp(hmac,hmac_comp,4)!=0)
{
GOSTerr(GOST_F_PKEY_GOST01CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH);
return 0;
}
}
return 1;
}
}
/* 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];
BIGNUM *UKM=NULL,*p=NULL,*order=NULL,*X=NULL,*Y=NULL;
const BIGNUM* key=EC_KEY_get0_private_key(priv_key);
@ -207,9 +213,10 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
gost_hash_ctx hash_ctx;
BN_CTX *ctx = BN_CTX_new();
for (i=0;i<8;i++) {
for (i=0;i<8;i++)
{
ukm_be[7-i]=ukm[i];
}
}
BN_CTX_start(ctx);
UKM=getbnfrombuf(ukm_be,8);
p=BN_CTX_get(ctx);
@ -220,15 +227,16 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
BN_mod_mul(p,key,UKM,order,ctx);
EC_POINT_mul(EC_KEY_get0_group(priv_key),pnt,NULL,pub_key,p,ctx);
EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(priv_key),
pnt,X,Y,ctx);
pnt,X,Y,ctx);
/*Serialize elliptic curve point same way as we do it when saving
* key */
store_bignum(Y,databuf,32);
store_bignum(X,databuf+32,32);
/* And reverse byte order of whole buffer */
for (i=0;i<64;i++) {
for (i=0;i<64;i++)
{
hashbuf[63-i]=databuf[i];
}
}
init_gost_hash_ctx(&hash_ctx,&GostR3411_94_CryptoProParamSet);
start_hash(&hash_ctx);
hash_block(&hash_ctx,hashbuf,64);
@ -239,7 +247,7 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
BN_CTX_free(ctx);
EC_POINT_free(pnt);
return 32;
}
}
/* Generates ephemeral key based on pubk algorithm
* computes shared key using VKO and returns filled up
@ -247,9 +255,9 @@ static int VKO_compute_key(unsigned char *shared_key,size_t shared_key_size,cons
*/
/* Public, because it would be needed in SSL implementation */
GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_key,
const unsigned char *key,size_t keylen, unsigned char *ukm,
size_t ukm_len)
{
const unsigned char *key,size_t keylen, unsigned char *ukm,
size_t ukm_len)
{
const struct gost_cipher_info *param=get_encryption_params(NULL);
EC_KEY *ephemeral = NULL;
@ -260,43 +268,49 @@ GOST_KEY_TRANSPORT *make_rfc4490_keytransport_2001(EVP_PKEY *pubk,BIGNUM *eph_ke
EVP_PKEY *newkey=NULL;
/* 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;
}
}
ephemeral = make_ec_ephemeral_key(EVP_PKEY_get0(pubk),eph_key);
VKO_compute_key(shared_key,32,pub_key_point,ephemeral,ukm);
gost_init(&ctx,param->sblock);
keyWrapCryptoPro(&ctx,shared_key,ukm,key,crypted_key);
gkt = GOST_KEY_TRANSPORT_new();
if (!gkt) {
if (!gkt)
{
goto memerr;
}
}
if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,
ukm,8)) {
ukm,8))
{
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;
}
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;
}
}
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);
goto err;
}
}
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
EVP_PKEY_free(newkey);
return gkt;
memerr:
GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,
GOST_R_MALLOC_FAILURE);
err:
GOST_KEY_TRANSPORT_free(gkt);
return NULL;
}
memerr:
GOSTerr(GOST_F_MAKE_RFC4490_KEYTRANSPORT_2001,
GOST_R_MALLOC_FAILURE);
err:
GOST_KEY_TRANSPORT_free(gkt);
return NULL;
}
/*
* 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)
{
{
GOST_KEY_TRANSPORT *gkt=NULL;
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
unsigned char ukm[8];
int ret=0;
if (RAND_bytes(ukm,8)<=0) {
if (RAND_bytes(ukm,8)<=0)
{
GOSTerr(GOST_F_PKEY_GOST01CP_ENCRYPT,
GOST_R_RANDOM_GENERATOR_FAILURE);
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;
}
}
if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt,&out))>0) ret =1;
GOST_KEY_TRANSPORT_free(gkt);
return ret;
err:
GOST_KEY_TRANSPORT_free(gkt);
return -1;
}
err:
GOST_KEY_TRANSPORT_free(gkt);
return -1;
}
/* Public, because it would be needed in SSL implementation */
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 sharedKey[32];
gost_ctx ctx;
@ -346,40 +362,44 @@ int decrypt_rfc4490_shared_key_2001(EVP_PKEY *priv,GOST_KEY_TRANSPORT *gkt,
OPENSSL_assert(gkt->key_info->imit->length==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)),
EVP_PKEY_get0(priv),wrappedKey);
if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key_buf)) {
EVP_PKEY_get0(priv),wrappedKey);
if (!keyUnwrapCryptoPro(&ctx,sharedKey,wrappedKey,key_buf))
{
GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,
GOST_R_ERROR_COMPUTING_SHARED_KEY);
GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err;
}
}
EVP_PKEY_free(eph_key);
return 32;
err:
err:
EVP_PKEY_free(eph_key);
return -1;
}
}
/*
* EVP_PKEY_METHOD callback decrypt
* 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;
EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
GOST_KEY_TRANSPORT *gkt = NULL;
int ret=0;
if (!key) {
if (!key)
{
*key_len = 32;
return 1;
}
}
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len);
if (!gkt) {
in_len);
if (!gkt)
{
GOSTerr(GOST_F_PKCS7_GOST94CP_KEY_TRANSPORT_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
return -1;
}
}
ret = decrypt_rfc4490_shared_key_2001(priv,gkt,key,*key_len);
GOST_KEY_TRANSPORT_free(gkt);
return ret;
}
}

View file

@ -20,30 +20,30 @@
/* Substitution blocks from test examples for GOST R 34.11-94*/
gost_subst_block GostR3411_94_TestParamSet = {
{0X1,0XF,0XD,0X0,0X5,0X7,0XA,0X4,0X9,0X2,0X3,0XE,0X6,0XB,0X8,0XC},
{0XD,0XB,0X4,0X1,0X3,0XF,0X5,0X9,0X0,0XA,0XE,0X7,0X6,0X8,0X2,0XC},
{0X4,0XB,0XA,0X0,0X7,0X2,0X1,0XD,0X3,0X6,0X8,0X5,0X9,0XC,0XF,0XE},
{0X6,0XC,0X7,0X1,0X5,0XF,0XD,0X8,0X4,0XA,0X9,0XE,0X0,0X3,0XB,0X2},
{0X7,0XD,0XA,0X1,0X0,0X8,0X9,0XF,0XE,0X4,0X6,0XC,0XB,0X2,0X5,0X3},
{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},
{0X4,0XA,0X9,0X2,0XD,0X8,0X0,0XE,0X6,0XB,0X1,0XC,0X7,0XF,0X5,0X3}
};
{0X1,0XF,0XD,0X0,0X5,0X7,0XA,0X4,0X9,0X2,0X3,0XE,0X6,0XB,0X8,0XC},
{0XD,0XB,0X4,0X1,0X3,0XF,0X5,0X9,0X0,0XA,0XE,0X7,0X6,0X8,0X2,0XC},
{0X4,0XB,0XA,0X0,0X7,0X2,0X1,0XD,0X3,0X6,0X8,0X5,0X9,0XC,0XF,0XE},
{0X6,0XC,0X7,0X1,0X5,0XF,0XD,0X8,0X4,0XA,0X9,0XE,0X0,0X3,0XB,0X2},
{0X7,0XD,0XA,0X1,0X0,0X8,0X9,0XF,0XE,0X4,0X6,0XC,0XB,0X2,0X5,0X3},
{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},
{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 */
gost_subst_block GostR3411_94_CryptoProParamSet= {
{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
{0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
{0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
{0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
{0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
{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},
{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
} ;
{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
{0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
{0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
{0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
{0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
{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},
{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
} ;
/* Test paramset from GOST 28147 */
gost_subst_block Gost28147_TestParamSet =
{
{
{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},
{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},
{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}
};
};
@ -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},
{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}
};
};
/* 1.2.643.2.2.31.2 */
gost_subst_block Gost28147_CryptoProParamSetB=
{
{
{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},
{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},
{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}
};
};
/* 1.2.643.2.2.31.3 */
gost_subst_block Gost28147_CryptoProParamSetC=
{
{
{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},
{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},
{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}
};
};
/* 1.2.643.2.2.31.4 */
gost_subst_block Gost28147_CryptoProParamSetD=
{
{
{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},
{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},
{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}
};
};
const byte CryptoProKeyMeshingKey[]={
@ -112,62 +112,64 @@ const byte CryptoProKeyMeshingKey[]={
0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4,
0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12,
0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B
};
};
/* 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;
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->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->k21[i] = b->k2[i>>4] <<4 | b->k1 [i &15];
}
}
}
/* Part of GOST 28147 algorithm moved into separate function */
static word32
f(gost_ctx *c,word32 x)
{ x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
c->k43[x>> 8 & 255] | c->k21[x & 255];
/* Rotate left 11 bits */
return x<<11 | x>>(32-11);
}
static word32 f(gost_ctx *c,word32 x)
{
x = c->k87[x>>24 & 255] | c->k65[x>>16 & 255]|
c->k43[x>> 8 & 255] | c->k21[x & 255];
/* Rotate left 11 bits */
return x<<11 | x>>(32-11);
}
/* Low-level encryption routine - encrypts one 64 bit block*/
void gostcrypt(gost_ctx *c, const byte *in, byte *out)
{
register word32 n1, n2; /* As named in the GOST */
n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
/* Instead of swapping halves, swap names each round */
{
register word32 n1, n2; /* As named in the GOST */
n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<24);
n2 = in[4]|(in[5]<<8)|(in[6]<<16)|(in[7]<<24);
/* Instead of swapping halves, swap names each round */
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
n2 ^= f(c,n1+c->k[1]); n1 ^= f(c,n2+c->k[0]);
n2 ^= f(c,n1+c->k[7]); n1 ^= f(c,n2+c->k[6]);
n2 ^= f(c,n1+c->k[5]); n1 ^= f(c,n2+c->k[4]);
n2 ^= f(c,n1+c->k[3]); n1 ^= f(c,n2+c->k[2]);
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[4] = (n1&0xff); out[5] = (n1>>8)&0xff; out[6]=(n1>>16)&0xff; out[7]=n1>>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;
}
/* Low-level decryption routine. Decrypts one 64-bit block */
void gostdecrypt(gost_ctx *c, const byte *in,byte *out)
{
{
register word32 n1, n2; /* As named in the GOST */
n1 = in[0]|(in[1]<<8)|(in[2]<<16)|(in[3]<<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]);
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;
}
}
/* Encrypts several blocks in ECB mode */
void gost_enc(gost_ctx *c,const byte *clear,byte *cipher, int blocks)
{
{
int i;
for(i=0;i<blocks;i++){
for(i=0;i<blocks;i++)
{
gostcrypt(c,clear,cipher);
clear+=8;
cipher+=8;
}
}
}
/* Decrypts several blocks in ECB mode */
void gost_dec(gost_ctx *c, const byte *cipher,byte *clear, int blocks)
{
{
int i;
for(i=0;i<blocks;i++) {
for(i=0;i<blocks;i++)
{
gostdecrypt(c,cipher,clear);
clear+=8;
cipher+=8;
}
}
}
/* 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 gamma[8];
int i,j;
const byte *in;
byte *out;
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);
for (j=0;j<8;j++) {
for (j=0;j<8;j++)
{
cur_iv[j]=out[j]=in[j]^gamma[j];
}
}
}
}
}
/* 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 gamma[8];
int i,j;
const byte *in;
byte *out;
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);
for (j=0;j<8;j++) {
for (j=0;j<8;j++)
{
out[j]=(cur_iv[j]=in[j])^gamma[j];
}
}
}
}
}
/* Encrypts one block using specified key */
void gost_enc_with_key(gost_ctx *c,byte *key,byte *inblock,byte *outblock)
{
{
gost_key(c,key);
gostcrypt(c,inblock,outblock);
}
}
/* Set 256 bit key into context */
void gost_key(gost_ctx *c, const byte *k)
{
{
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);
}
}
}
}
/* Retrieve 256-bit key from context */
void gost_get_key(gost_ctx *c, byte *k)
{
{
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+1]=(c->k[i]>>8 )&0xFF;
k[j+2]=(c->k[i]>>16) &0xFF;
k[j+3]=(c->k[i]>>24) &0xFF;
}
}
}
}
/* Initalize context. Provides default value for subst_block */
void gost_init(gost_ctx *c, const gost_subst_block *b)
{
if(!b) {
{
if(!b)
{
b=&GostR3411_94_TestParamSet;
}
}
kboxinit(c,b);
}
}
/* Cleans up key from context */
void gost_destroy(gost_ctx *c)
{
{
int i; for(i=0;i<8;i++) c->k[i]=0;
}
}
/* Compute GOST 28147 mac block
*
@ -297,80 +310,86 @@ void gost_destroy(gost_ctx *c)
* buffer - 8-byte mac state buffer
* block 8-byte block to process.
* */
void mac_block(gost_ctx *c,byte *buffer,const byte *block) {
register word32 n1, n2; /* As named in the GOST */
int i;
for (i=0; i<8; i++) {
buffer[i]^=block[i];
}
n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24);
n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24);
/* Instead of swapping halves, swap names each round */
void mac_block(gost_ctx *c,byte *buffer,const byte *block)
{
register word32 n1, n2; /* As named in the GOST */
int i;
for (i=0; i<8; i++)
{
buffer[i]^=block[i];
}
n1 = buffer[0]|(buffer[1]<<8)|(buffer[2]<<16)|(buffer[3]<<24);
n2 = buffer[4]|(buffer[5]<<8)|(buffer[6]<<16)|(buffer[7]<<24);
/* Instead of swapping halves, swap names each round */
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
n2 ^= f(c,n1+c->k[0]); n1 ^= f(c,n2+c->k[1]);
n2 ^= f(c,n1+c->k[2]); n1 ^= f(c,n2+c->k[3]);
n2 ^= f(c,n1+c->k[4]); n1 ^= f(c,n2+c->k[5]);
n2 ^= f(c,n1+c->k[6]); n1 ^= f(c,n2+c->k[7]);
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;
}
}
/* 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 rembits = nbits & 7;
int mask =rembits?((1<rembits)-1):0;
int i;
for (i=0;i<nbytes;i++) out[i]=buffer[i];
if (rembits) out[i]=buffer[i]&mask;
}
}
/* Compute mac of specified length (in bits) from data.
* Context should be initialized with key and subst blocks */
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 buf2[8];
int i;
for (i=0;i+8<=data_len;i+=8)
mac_block(ctx,buffer,data+i);
if (i<data_len) {
if (i<data_len)
{
memset(buf2,0,8);
memcpy(buf2,data+i,data_len-i);
mac_block(ctx,buffer,buf2);
}
}
get_mac(buffer,mac_len,mac);
return 1;
}
}
/* 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,
unsigned int data_len,unsigned char *mac)
{
unsigned int data_len,unsigned char *mac)
{
byte buffer[8];
byte buf2[8];
int i;
memcpy (buffer,iv,8);
for (i=0;i+8<=data_len;i+=8)
mac_block(ctx,buffer,data+i);
if (i<data_len) {
if (i<data_len)
{
memset(buf2,0,8);
memcpy(buf2,data+i,data_len-i);
mac_block(ctx,buffer,buf2);
}
}
get_mac(buffer,mac_len,mac);
return 1;
}
}
/* 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];
/* Set static 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 */
gostcrypt(ctx,iv,newiv);
memcpy(iv,newiv,8);
}
}

View file

@ -14,62 +14,59 @@
#include <openssl/evp.h>
#include <openssl/objects.h>
#include "gostkeyx.h"
#include "gost_asn1.h"
#include "gost89.h"
#include "gosthash.h"
#include "crypt.h"
#include "e_gost_err.h"
#include "pmeth.h"
#include "keywrap.h"
#include "tools.h"
#include "gost_keywrap.h"
#include "gost_lcl.h"
/* Common functions for both 94 and 2001 key exchange schemes */
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 j;
int blocks = crypted_key_len >>3;
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);
return 0;
}
}
if ((crypted_key_len & 7) !=0)
{
{
GOSTerr(GOST_F_DECRYPT_CRYPTOCOM_KEY,GOST_R_INVALID_ENCRYPTED_KEY_SIZE);
return 0;
}
}
for (i=blocks-1;i>0;i--)
{
{
gostcrypt(ctx,crypted_key+(i-1)*8,gamma);
for(j=0;j<8;j++)
{
{
sess_key[i*8+j]=gamma[j]^crypted_key[i*8+j];
}
}
}
}
gostcrypt(ctx,sess_key+crypted_key_len-8,gamma);
for(j=0;j<8;j++)
{
{
sess_key[j]=gamma[j]^crypted_key[j];
}
}
return 1;
}
}
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 j;
unsigned char gamma[8];
memcpy(gamma,sess_key+key_len-8,8);
for (i=0;i<key_len;i+=8)
{
{
gostcrypt(ctx,gamma,gamma);
for (j=0;j<8;j++)
gamma[j]=crypted_key[i+j]=sess_key[i+j]^gamma[j];
}
}
return 1;
}
}
/* Implementation of the Diffi-Hellman key agreement scheme based on
* GOST-94 keys */
@ -78,23 +75,24 @@ int encrypt_cryptocom_key(const unsigned char *sess_key,int key_len,
* algorigthm
*/
static int compute_pair_key_le(unsigned char *pair_key,BIGNUM *pub_key,DH *dh)
{
{
unsigned char be_key[128];
int i,key_size;
key_size=DH_compute_key(be_key,pub_key,dh);
if (!key_size) return 0;
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];
}
}
return key_size;
}
}
/*
* Computes 256 bit key exchange key for CryptoCom variation of GOST 94
* algorithm
*/
static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key)
{
{
unsigned char dh_key [128];
int i;
/* Compute key */
@ -105,34 +103,39 @@ static int make_gost_shared_key(DH *dh,EVP_PKEY *pubk,unsigned char *shared_key)
* 2^509<p<2^512, so DH_size can be exactly 128 or exactly 64 only
*/
if (DH_size(dh)==128)
for (i=0;i<64;i++) {
if (DH_size(dh)==128)
{
for (i=0;i<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];
}
}
return 1;
}
}
static DH *make_ephemeral_key(EVP_PKEY *pubk,BIGNUM *ephemeral_key)
{
{
DH *dh = DH_new();
dh->g = BN_dup(pubk->pkey.dsa->g);
dh->p = BN_dup(pubk->pkey.dsa->p);
dh->priv_key = BN_dup(ephemeral_key);
/* Generate ephemeral key pair */
if (!DH_generate_key(dh)) {
if (!DH_generate_key(dh))
{
DH_free(dh);
return NULL;
}
}
return dh;
}
}
/*
* 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)
{
{
unsigned char dh_key [128];
gost_hash_ctx hash_ctx;
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);
done_gost_hash_ctx(&hash_ctx);
return 1;
}
}
/* EVP_PKEY_METHOD callback encrypt for
* 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 )
{
{
GOST_KEY_TRANSPORT *gkt=NULL;
DH *dh = NULL;
unsigned char shared_key[32], ukm[8],crypted_key[44];
@ -159,64 +163,72 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
int size=-1;
gost_ctx cctx;
if (!(data->eph_seckey)) {
if (!(data->eph_seckey))
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
return -1;
}
}
dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey));
gost_init(&cctx,param->sblock);
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,
GOST_R_RANDOM_GENERATOR_FAILURE);
GOST_R_RANDOM_GENERATOR_FAILURE);
return -1;
}
}
keyWrapCryptoPro(&cctx,shared_key,ukm,key,crypted_key);
gkt = GOST_KEY_TRANSPORT_new();
if (!gkt) {
if (!gkt)
{
goto memerr;
}
}
if(!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,
ukm,8)) {
ukm,8))
{
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;
}
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;
}
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);
goto err;
}
}
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid);
*outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out);
if (!size) {
if (!size)
{
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO);
size=-1;
}
}
GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh);
return 1;
memerr:
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_MALLOC_FAILURE);
err:
GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh);
return -1;
}
memerr:
GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT,
GOST_R_MALLOC_FAILURE);
err:
GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh);
return -1;
}
/* EVP_PKEY_METHOD callback encrypt for
* 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)
{
{
EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(ctx);
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
/* create DH structure filling parameters from passed pub_key */
@ -225,68 +237,70 @@ int pkey_GOST94cc_encrypt (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen
gost_ctx cctx;
EVP_PKEY *newkey=NULL;
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,
GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
GOST_R_CTX_NOT_INITIALIZED_FOR_ENCRYPT);
return -1;
}
}
dh = make_ephemeral_key(pubk,gost_get_priv_key(data->eph_seckey));
if (!dh) goto err;
/* compute shared key */
if (!make_gost_shared_key(dh,pubk,shared_key))
{
{
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err;
}
}
/* encrypt session key */
gost_init(&cctx, &GostR3411_94_CryptoProParamSet);
gost_key(&cctx,shared_key);
encrypt_cryptocom_key(key,key_len,encrypted_key,&cctx);
/* compute hmac of session key */
if (!gost_mac(&cctx,32,key,32,hmac))
{
{
DH_free(dh);
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_COMPUTING_MAC);
return -1;
}
}
gkt = GOST_KEY_TRANSPORT_new();
if (!gkt)
{
{
DH_free(dh);
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_NO_MEMORY);
return -1;
}
}
/* Store IV which is always zero in our case */
if (!ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv,iv,8))
{
{
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_IV);
goto err;
}
}
if (!ASN1_OCTET_STRING_set(gkt->key_info->imit,hmac,4))
{
{
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_MAC);
goto err;
}
}
if (!ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key,encrypted_key,32))
{
{
GOSTerr(GOST_F_PKEY_GOST94CC_ENCRYPT,GOST_R_ERROR_STORING_ENCRYPTED_KEY);
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);
goto err;
}
}
ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
gkt->key_agreement_info->cipher = OBJ_nid2obj(NID_id_Gost28147_89_cc);
*outlen = i2d_GOST_KEY_TRANSPORT(gkt,&out);
err:
err:
if (gkt) GOST_KEY_TRANSPORT_free(gkt);
if (dh) DH_free(dh);
if (newkey) EVP_PKEY_free(newkey);
return 1;
}
}
/* EVP_PLEY_METHOD callback decrypt for
* GOST R 34.10-94 cryptopro modification
@ -302,21 +316,23 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
EVP_PKEY *eph_key=NULL;
EVP_PKEY *priv= EVP_PKEY_CTX_get0_pkey(ctx);
if (!key) {
if (!key)
{
*key_len = 32;
return 1;
}
}
dh->g = BN_dup(priv->pkey.dsa->g);
dh->p = BN_dup(priv->pkey.dsa->p);
dh->priv_key = BN_dup(priv->pkey.dsa->priv_key);
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len);
if (!gkt) {
in_len);
if (!gkt)
{
GOSTerr(GOST_F_PKEY_GOST94CP_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
DH_free(dh);
return 0;
}
}
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
param = get_encryption_params(gkt->key_agreement_info->cipher);
gost_init(&cctx,param->sblock);
@ -327,11 +343,12 @@ int pkey_GOST94cp_decrypt (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_le
OPENSSL_assert(gkt->key_info->imit->length==4);
memcpy(wrappedKey+40,gkt->key_info->imit->data,4);
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,
GOST_R_ERROR_COMPUTING_SHARED_KEY);
GOST_R_ERROR_COMPUTING_SHARED_KEY);
goto err;
}
}
EVP_PKEY_free(eph_key);
GOST_KEY_TRANSPORT_free(gkt);
@ -342,14 +359,14 @@ err:
GOST_KEY_TRANSPORT_free(gkt);
DH_free(dh);
return -1;
}
}
/* EVP_PKEY_METHOD callback decrypt for
* 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)
{
{
/* Form DH params from compute shared key */
GOST_KEY_TRANSPORT *gkt = NULL;
const unsigned char *p=in;
@ -362,22 +379,24 @@ int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
EVP_PKEY *eph_key;
EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
if (!key) {
if (!key)
{
*key_len = 32;
return 1;
}
}
/* Construct DH structure from the our GOST private key */
dh->g = BN_dup(priv->pkey.dsa->g);
dh->p = BN_dup(priv->pkey.dsa->p);
dh->priv_key = BN_dup(priv->pkey.dsa->priv_key);
/* Parse passed octet string and find out public key, iv and HMAC*/
gkt = d2i_GOST_KEY_TRANSPORT(NULL,(const unsigned char **)&p,
in_len);
if (!gkt) {
in_len);
if (!gkt)
{
GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
DH_free(dh);
return 0;
}
}
eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
/* Initialization vector is really ignored here */
OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8);
@ -390,31 +409,33 @@ int pkey_GOST94cc_decrypt (EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_l
EVP_PKEY_free(eph_key);
DH_free(dh);
if (!i)
{
{
GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_ERROR_COMPUTING_SHARED_KEY);
GOST_KEY_TRANSPORT_free(gkt);
return 0;
}
}
/* Decrypt session key */
gost_init(&ctx, &GostR3411_94_CryptoProParamSet);
gost_key(&ctx,shared_key);
if (!decrypt_cryptocom_key(key,*key_len,gkt->key_info->encrypted_key->data,
gkt->key_info->encrypted_key->length, &ctx))
{
{
GOST_KEY_TRANSPORT_free(gkt);
return 0;
}
}
GOST_KEY_TRANSPORT_free(gkt);
/* 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);
return 0;
}
/* HMAC of session key is not correct */
if (memcmp(hmac,hmac_comp,4)!=0) {
}
/* HMAC of session key is not correct */
if (memcmp(hmac,hmac_comp,4)!=0)
{
GOSTerr(GOST_F_PKEY_GOST94CC_DECRYPT,GOST_R_SESSION_KEY_MAC_DOES_NOT_MATCH);
return 0;
}
}
return 1;
}
}

View file

@ -1,5 +1,5 @@
/**********************************************************************
* ameth.c *
* gost_ameth.c *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
@ -10,91 +10,91 @@
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <string.h>
#include "meth.h"
#include "pmeth.h"
#include "paramset.h"
#include "gost_asn1.h"
#include "crypt.h"
#include "sign.h"
#include "tools.h"
#include "gost_params.h"
#include "gost_lcl.h"
#include "e_gost_err.h"
int gost94_nid_by_params(DSA *p)
{
{
R3410_params *gost_params;
BIGNUM *q=BN_new();
for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++) {
for (gost_params = R3410_paramset;gost_params->q!=NULL; gost_params++)
{
BN_dec2bn(&q,gost_params->q);
if (!BN_cmp(q,p->q))
{
{
BN_free(q);
return gost_params->nid;
}
}
}
}
BN_free(q);
return NID_undef;
}
}
static ASN1_STRING *encode_gost_algor_params(const EVP_PKEY *key)
{
{
ASN1_STRING *params = ASN1_STRING_new();
GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
int pkey_param_nid = NID_undef;
int cipher_param_nid = NID_undef;
if (!params || !gkp) {
if (!params || !gkp)
{
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
params = NULL;
goto err;
}
switch (EVP_PKEY_base_id(key)) {
case NID_id_GostR3410_2001_cc:
pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
cipher_param_nid = NID_id_Gost28147_89_cc;
break;
case NID_id_GostR3410_94_cc:
pkey_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
cipher_param_nid = NID_id_Gost28147_89_cc;
break;
case NID_id_GostR3410_2001:
pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
cipher_param_nid = get_encryption_params(NULL)->nid;
break;
case NID_id_GostR3410_94:
pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
if (pkey_param_nid == NID_undef) {
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
GOST_R_INVALID_GOST94_PARMSET);
ASN1_STRING_free(params);
params=NULL;
goto err;
}
cipher_param_nid = get_encryption_params(NULL)->nid;
break;
}
switch (EVP_PKEY_base_id(key))
{
case NID_id_GostR3410_2001_cc:
pkey_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
cipher_param_nid = NID_id_Gost28147_89_cc;
break;
case NID_id_GostR3410_94_cc:
pkey_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
cipher_param_nid = NID_id_Gost28147_89_cc;
break;
case NID_id_GostR3410_2001:
pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
cipher_param_nid = get_encryption_params(NULL)->nid;
break;
case NID_id_GostR3410_94:
pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
if (pkey_param_nid == NID_undef)
{
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
GOST_R_INVALID_GOST94_PARMSET);
ASN1_STRING_free(params);
params=NULL;
goto err;
}
cipher_param_nid = get_encryption_params(NULL)->nid;
break;
}
gkp->key_params = OBJ_nid2obj(pkey_param_nid);
gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
/*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
if (params->length <=0 )
{
{
GOSTerr(GOST_F_ENCODE_GOST_ALGOR_PARAMS,
ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
params = NULL;
goto err;
}
}
params ->type = V_ASN1_SEQUENCE;
err:
err:
GOST_KEY_PARAMS_free(gkp);
return params;
}
}
/* Parses GOST algorithm parameters from X509_ALGOR and
* modifies pkey setting NID and parameters
*/
static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
{
{
ASN1_OBJECT *palg_obj =NULL;
int ptype = V_ASN1_UNDEF;
int pkey_nid = NID_undef,param_nid = NID_undef;
@ -103,161 +103,184 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
GOST_KEY_PARAMS *gkp = NULL;
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,
GOST_R_BAD_KEY_PARAMETERS_FORMAT);
return 0;
}
}
p=pval->data;
pkey_nid = OBJ_obj2nid(palg_obj);
gkp = d2i_GOST_KEY_PARAMS(NULL,&p,pval->length);
if (!gkp) {
if (!gkp)
{
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);
GOST_KEY_PARAMS_free(gkp);
EVP_PKEY_set_type(pkey,pkey_nid);
switch (pkey_nid) {
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
{ DSA *dsa= EVP_PKEY_get0(pkey);
if (!dsa) {
dsa = DSA_new();
if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0;
switch (pkey_nid)
{
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
{
DSA *dsa= EVP_PKEY_get0(pkey);
if (!dsa)
{
dsa = DSA_new();
if (!EVP_PKEY_assign(pkey,pkey_nid,dsa)) return 0;
}
if (!fill_GOST94_params(dsa,param_nid)) return 0;
break;
if (!fill_GOST94_params(dsa,param_nid)) return 0;
break;
}
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
{ EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec) {
ec = EC_KEY_new();
if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
{
ec = EC_KEY_new();
if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
}
if (!fill_GOST2001_params(ec,param_nid)) return 0;
}
}
if (!fill_GOST2001_params(ec,param_nid)) return 0;
}
}
return 1;
}
}
static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
{
switch (EVP_PKEY_base_id(pkey)) {
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
{ DSA *dsa = EVP_PKEY_get0(pkey);
if (!dsa) {
dsa = DSA_new();
EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa);
}
dsa->priv_key = BN_dup(priv);
if (!EVP_PKEY_missing_parameters(pkey))
gost94_compute_public(dsa);
break;
}
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
{ EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec) {
ec = EC_KEY_new();
EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec);
}
if (!EC_KEY_set_private_key(ec,priv)) return 0;
if (!EVP_PKEY_missing_parameters(pkey))
gost2001_compute_public(ec);
break;
}
}
return 1;
}
BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
{
switch (EVP_PKEY_base_id(pkey)) {
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
{ DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
if (!dsa) {
return NULL;
}
if (!dsa->priv_key) return NULL;
return BN_dup(dsa->priv_key);
break;
}
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
{ EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
const BIGNUM* priv;
if (!ec) {
return NULL;
}
if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
return BN_dup(priv);
break;
}
}
return NULL;
}
static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
long arg1, void *arg2)
{
switch (op)
{
switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
{
DSA *dsa = EVP_PKEY_get0(pkey);
if (!dsa)
{
dsa = DSA_new();
EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),dsa);
}
dsa->priv_key = BN_dup(priv);
if (!EVP_PKEY_missing_parameters(pkey))
gost94_compute_public(dsa);
break;
}
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0(pkey);
if (!ec)
{
ec = EC_KEY_new();
EVP_PKEY_assign(pkey,EVP_PKEY_base_id(pkey),ec);
}
if (!EC_KEY_set_private_key(ec,priv)) return 0;
if (!EVP_PKEY_missing_parameters(pkey))
gost2001_compute_public(ec);
break;
}
}
return 1;
}
BIGNUM* gost_get_priv_key(const EVP_PKEY *pkey)
{
switch (EVP_PKEY_base_id(pkey))
{
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
{
DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pkey);
if (!dsa)
{
return NULL;
}
if (!dsa->priv_key) return NULL;
return BN_dup(dsa->priv_key);
break;
}
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
{
EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
const BIGNUM* priv;
if (!ec)
{
return NULL;
}
if (!(priv=EC_KEY_get0_private_key(ec))) return NULL;
return BN_dup(priv);
break;
}
}
return NULL;
}
static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
long arg1, void *arg2)
{
switch (op)
{
case ASN1_PKEY_CTRL_PKCS7_SIGN:
if (arg1 == 0) {
if (arg1 == 0)
{
X509_ALGOR *alg1 = NULL, *alg2 = NULL;
int nid = EVP_PKEY_base_id(pkey);
PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2,
NULL, &alg1, &alg2);
NULL, &alg1, &alg2);
X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
V_ASN1_NULL, 0);
if (nid == NID_undef) {
V_ASN1_NULL, 0);
if (nid == NID_undef)
{
return (-1);
}
}
X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_NULL, 0);
}
}
return 1;
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
if (arg1 == 0)
{
X509_ALGOR *alg;
ASN1_STRING * params = encode_gost_algor_params(pkey);
if (!params) {
if (!params)
{
return -1;
}
}
PKCS7_RECIP_INFO_get0_alg((PKCS7_RECIP_INFO*)arg2, &alg);
X509_ALGOR_set0(alg, OBJ_nid2obj(pkey->type),
V_ASN1_SEQUENCE, params);
V_ASN1_SEQUENCE, params);
}
return 1;
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = NID_id_GostR3411_94;
return 2;
}
*(int *)arg2 = NID_id_GostR3411_94;
return 2;
}
return -2;
}
/*----------------------- free functions * ------------------------------*/
static void pkey_free_gost94(EVP_PKEY *key) {
if (key->pkey.dsa) {
DSA_free(key->pkey.dsa);
}
}
static void pkey_free_gost01(EVP_PKEY *key) {
if (key->pkey.ec) {
EC_KEY_free(key->pkey.ec);
}
}
/*----------------------- free functions * ------------------------------*/
static void pkey_free_gost94(EVP_PKEY *key)
{
if (key->pkey.dsa)
{
DSA_free(key->pkey.dsa);
}
}
static void pkey_free_gost01(EVP_PKEY *key)
{
if (key->pkey.ec)
{
EC_KEY_free(key->pkey.ec);
}
}
/* ------------------ private key functions -----------------------------*/
static int priv_decode_gost( EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf)
{
{
const unsigned char *pkey_buf = NULL,*p=NULL;
int priv_len = 0;
BIGNUM *pk_num=NULL;
@ -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))
return 0;
p = pkey_buf;
if (!decode_gost_algor_params(pk,palg)) {
if (!decode_gost_algor_params(pk,palg))
{
return 0;
}
priv_key=d2i_ASN1_INTEGER(NULL,&p,priv_len);
if (!priv_key) {
}
if (!(pk_num = ASN1_INTEGER_to_BN(priv_key, NULL))) {
GOSTerr(GOST_F_PRIV_DECODE_GOST_94,
EVP_R_DECODE_ERROR);
}
}
if (V_ASN1_OCTET_STRING == *p)
{
/* New format - Little endian octet string */
unsigned char rev_buf[32];
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,
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);
BN_free(pk_num);
return ret;
}
}
/* ----------------------------------------------------------------------*/
static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
{
{
ASN1_OBJECT *algobj = OBJ_nid2obj(EVP_PKEY_base_id(pk));
ASN1_STRING *params = encode_gost_algor_params(pk);
unsigned char *priv_buf = NULL;
@ -295,9 +341,10 @@ static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
BIGNUM *key;
ASN1_INTEGER *asn1key=NULL;
if (!params) {
if (!params)
{
return 0;
}
}
key = gost_get_priv_key(pk);
asn1key = BN_to_ASN1_INTEGER(key,NULL);
BN_free(key);
@ -305,11 +352,11 @@ static int priv_encode_gost(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
ASN1_INTEGER_free(asn1key);
return PKCS8_pkey_set0(p8,algobj,0,V_ASN1_SEQUENCE,params,
priv_buf,priv_len);
}
}
static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx)
{
ASN1_PCTX *pctx)
{
BIGNUM *key;
if (!BIO_indent(out,indent,128)) return 0;
key = gost_get_priv_key(pkey);
@ -317,96 +364,106 @@ static int priv_print_gost (BIO *out,const EVP_PKEY *pkey, int indent,
BN_print(out,key);
BN_free(key);
return 1;
}
}
/* ---------------------------------------------------------------------*/
static int param_missing_gost94(const EVP_PKEY *pk)
{
{
const DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)pk);
if (!dsa) return 1;
if (!dsa->q) return 1;
return 0;
}
}
static int param_missing_gost01(const EVP_PKEY *pk)
{
{
const EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pk);
if (!ec) return 1;
if (!EC_KEY_get0_group(ec)) return 1;
return 0;
}
}
static int param_copy_gost94(EVP_PKEY *to, const EVP_PKEY *from)
{
{
const DSA *dfrom = EVP_PKEY_get0((EVP_PKEY *)from);
DSA *dto = EVP_PKEY_get0(to);
if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to))
{
{
GOSTerr(GOST_F_PARAM_COPY_GOST94,
GOST_R_INCOMPATIBLE_ALGORITHMS);
GOST_R_INCOMPATIBLE_ALGORITHMS);
return 0;
}
}
if (!dfrom)
{
{
GOSTerr(GOST_F_PARAM_COPY_GOST94,
GOST_R_KEY_PARAMETERS_MISSING);
GOST_R_KEY_PARAMETERS_MISSING);
return 0;
}
}
if (!dto)
{
{
dto = DSA_new();
EVP_PKEY_assign(to,EVP_PKEY_base_id(from),dto);
}
}
#define COPYBIGNUM(a,b,x) if (a->x) BN_free(a->x); a->x=BN_dup(b->x);
COPYBIGNUM(dto,dfrom,p)
COPYBIGNUM(dto,dfrom,q)
COPYBIGNUM(dto,dfrom,g)
COPYBIGNUM(dto,dfrom,q)
COPYBIGNUM(dto,dfrom,g)
if (dto->priv_key)
gost94_compute_public(dto);
if (dto->priv_key)
gost94_compute_public(dto);
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);
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,
GOST_R_INCOMPATIBLE_ALGORITHMS);
GOST_R_INCOMPATIBLE_ALGORITHMS);
return 0;
}
if (!efrom) {
}
if (!efrom)
{
GOSTerr(GOST_F_PARAM_COPY_GOST94,
GOST_R_KEY_PARAMETERS_MISSING);
GOST_R_KEY_PARAMETERS_MISSING);
return 0;
}
if (!eto) {
}
if (!eto)
{
eto = EC_KEY_new();
EVP_PKEY_assign(to,EVP_PKEY_base_id(from),eto);
}
}
EC_KEY_set_group(eto,EC_GROUP_dup(EC_KEY_get0_group(efrom)));
if (EC_KEY_get0_private_key(eto)) {
if (EC_KEY_get0_private_key(eto))
{
gost2001_compute_public(eto);
}
}
return 1;
}
}
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b) {
static int param_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
{
const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
if (!BN_cmp(da->q,db->q)) return 1;
return 0;
}
static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) {
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))==
EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b)))) {
return 1;
}
static int param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
{
if (EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)a)))==
EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)b))))
{
return 1;
}
return 0;
}
}
/* ---------- Public key functions * --------------------------------------*/
static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
{
{
X509_ALGOR *palg = NULL;
const unsigned char *pubkey_buf = NULL;
unsigned char *databuf;
@ -416,43 +473,45 @@ static int pub_decode_gost94(EVP_PKEY *pk, X509_PUBKEY *pub)
ASN1_OCTET_STRING *octet= NULL;
if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
&palg, pub)) return 0;
&palg, pub)) return 0;
EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);
if (!decode_gost_algor_params(pk,palg)) return 0;
octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
if (!octet)
{
{
GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
return 0;
}
}
databuf = OPENSSL_malloc(octet->length);
for (i=0,j=octet->length-1;i<octet->length;i++,j--)
{
{
databuf[j]=octet->data[i];
}
}
dsa = EVP_PKEY_get0(pk);
dsa->pub_key=BN_bin2bn(databuf,octet->length,NULL);
ASN1_OCTET_STRING_free(octet);
OPENSSL_free(databuf);
return 1;
}
}
static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
{
{
ASN1_OBJECT *algobj = NULL;
ASN1_OCTET_STRING *octet = NULL;
void *pval = NULL;
unsigned char *buf=NULL,*databuf,*sptr;
int i,j,data_len,ret=0;
int ptype;
int ptype = V_ASN1_UNDEF;
DSA *dsa = EVP_PKEY_get0((EVP_PKEY *)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);
pval = params;
ptype = V_ASN1_SEQUENCE;
}
}
data_len = BN_num_bytes(dsa->pub_key);
databuf = OPENSSL_malloc(data_len);
BN_bn2bin(dsa->pub_key,databuf);
@ -460,17 +519,18 @@ static int pub_encode_gost94(X509_PUBKEY *pub,const EVP_PKEY *pk)
ASN1_STRING_set(octet,NULL,data_len);
sptr = ASN1_STRING_data(octet);
for (i=0,j=data_len-1; i< data_len;i++,j--)
{
{
sptr[i]=databuf[j];
}
}
OPENSSL_free(databuf);
ret = i2d_ASN1_OCTET_STRING(octet,&buf);
ASN1_BIT_STRING_free(octet);
if (ret <0) return 0;
return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
}
}
static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
{
{
X509_ALGOR *palg = NULL;
const unsigned char *pubkey_buf = NULL;
unsigned char *databuf;
@ -482,51 +542,55 @@ static int pub_decode_gost01(EVP_PKEY *pk,X509_PUBKEY *pub)
const EC_GROUP *group;
if (!X509_PUBKEY_get0_param(&palgobj,&pubkey_buf,&pub_len,
&palg, pub)) return 0;
&palg, pub)) return 0;
EVP_PKEY_assign(pk,OBJ_obj2nid(palgobj),NULL);
if (!decode_gost_algor_params(pk,palg)) return 0;
group = EC_KEY_get0_group(EVP_PKEY_get0(pk));
octet = d2i_ASN1_OCTET_STRING(NULL,&pubkey_buf,pub_len);
if (!octet)
{
{
GOSTerr(GOST_F_PUB_DECODE_GOST94,ERR_R_MALLOC_FAILURE);
return 0;
}
}
databuf = OPENSSL_malloc(octet->length);
for (i=0,j=octet->length-1;i<octet->length;i++,j--)
{
{
databuf[j]=octet->data[i];
}
if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc) {
}
if (EVP_PKEY_base_id(pk) == NID_id_GostR3410_2001_cc)
{
X= getbnfrombuf(databuf,octet->length/2);
Y= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
} else {
}
else
{
Y= getbnfrombuf(databuf,octet->length/2);
X= getbnfrombuf(databuf+(octet->length/2),octet->length/2);
}
}
OPENSSL_free(databuf);
pub_key = EC_POINT_new(group);
if (!EC_POINT_set_affine_coordinates_GFp(group
,pub_key,X,Y,NULL))
{
,pub_key,X,Y,NULL))
{
GOSTerr(GOST_F_PUB_DECODE_GOST01,
ERR_R_EC_LIB);
ERR_R_EC_LIB);
return 0;
}
}
BN_free(X);
BN_free(Y);
if (!EC_KEY_set_public_key(EVP_PKEY_get0(pk),pub_key))
{
{
GOSTerr(GOST_F_PUB_DECODE_GOST01,
ERR_R_EC_LIB);
ERR_R_EC_LIB);
return 0;
}
}
/*EC_POINT_free(pub_key);*/
return 1;
}
}
static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
{
{
ASN1_OBJECT *algobj = NULL;
ASN1_OCTET_STRING *octet = NULL;
void *pval = NULL;
@ -535,22 +599,24 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
const EC_POINT *pub_key;
BIGNUM *X,*Y,*order;
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));
if (pk->save_parameters) {
if (pk->save_parameters)
{
ASN1_STRING *params = encode_gost_algor_params(pk);
pval = params;
ptype = V_ASN1_SEQUENCE;
}
}
order = BN_new();
EC_GROUP_get_order(EC_KEY_get0_group(ec),order,NULL);
pub_key=EC_KEY_get0_public_key(ec);
if (!pub_key) {
if (!pub_key)
{
GOSTerr(GOST_F_PUB_ENCODE_GOST01,
GOST_R_PUBLIC_KEY_UNDEFINED);
GOST_R_PUBLIC_KEY_UNDEFINED);
return 0;
}
}
X=BN_new();
Y=BN_new();
EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec),
@ -559,39 +625,46 @@ static int pub_encode_gost01(X509_PUBKEY *pub,const EVP_PKEY *pk)
BN_free(order);
databuf = OPENSSL_malloc(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(Y,databuf+data_len/2,data_len/2);
} else {
}
else
{
store_bignum(X,databuf+data_len/2,data_len/2);
store_bignum(Y,databuf,data_len/2);
}
}
BN_free(X);
BN_free(Y);
octet = ASN1_OCTET_STRING_new();
ASN1_STRING_set(octet,NULL,data_len);
sptr=ASN1_STRING_data(octet);
for (i=0,j=data_len-1;i<data_len;i++,j--) {
for (i=0,j=data_len-1;i<data_len;i++,j--)
{
sptr[i]=databuf[j];
}
}
OPENSSL_free(databuf);
ret = i2d_ASN1_OCTET_STRING(octet,&buf);
ASN1_BIT_STRING_free(octet);
if (ret <0) return 0;
return X509_PUBKEY_set0_param(pub,algobj,ptype,pval,buf,ret);
}
}
static int pub_cmp_gost94(const EVP_PKEY *a, const EVP_PKEY *b)
{
{
const DSA *da = EVP_PKEY_get0((EVP_PKEY *)a);
const DSA *db = EVP_PKEY_get0((EVP_PKEY *)b);
if (da && db && da->pub_key && db->pub_key
&& !BN_cmp(da->pub_key,db->pub_key)) {
return 1;
}
&& !BN_cmp(da->pub_key,db->pub_key))
{
return 1;
}
return 0;
}
}
static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b)
{
{
const EC_KEY *ea = EVP_PKEY_get0((EVP_PKEY *)a);
const EC_KEY *eb = EVP_PKEY_get0((EVP_PKEY *)b);
const EC_POINT *ka,*kb;
@ -602,36 +675,43 @@ static int pub_cmp_gost01(const EVP_PKEY *a,const EVP_PKEY *b)
if (!ka || !kb) return 0;
ret = (0==EC_POINT_cmp(EC_KEY_get0_group(ea),ka,kb,NULL)) ;
return ret;
}
}
static int pub_print_gost94(BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx)
{
{
const BIGNUM *key;
if (!BIO_indent(out,indent,128)) return 0;
key = ((DSA *)EVP_PKEY_get0((EVP_PKEY *)pkey))->pub_key;
if (!key) return 0;
BN_print(out,key);
return 1;
}
}
static int pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx)
{
{
return 0;
}
}
static int pkey_size_gost(const EVP_PKEY *pk)
{
{
return 64;
}
}
static int pkey_bits_gost(const EVP_PKEY *pk)
{
{
return 256;
}
}
/* ----------------------------------------------------------------------*/
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info) {
int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info)
{
*ameth = EVP_PKEY_asn1_new(nid,
ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
ASN1_PKEY_SIGPARAM_NULL, pemstr, info);
if (!*ameth) return 0;
switch (nid) {
switch (nid)
{
case NID_id_GostR3410_94_cc:
case NID_id_GostR3410_94:
EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost94);
@ -666,6 +746,6 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
break;
}
}
return 1;
}
}

View file

@ -9,7 +9,7 @@
#include <stdio.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "gost_asn1.h"
#include "gost_lcl.h"
ASN1_NDEF_SEQUENCE(GOST_KEY_TRANSPORT) = {
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,32 +1,31 @@
/**********************************************************************
* gost_crypt.c *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* OpenSSL interface to GOST 28147-89 cipher functions *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
* gost_crypt.c *
* Copyright (c) 2005-2006 Cryptocom LTD *
* This file is distributed under the same license as OpenSSL *
* *
* OpenSSL interface to GOST 28147-89 cipher functions *
* Requires OpenSSL 0.9.9 for compilation *
**********************************************************************/
#include <string.h>
#include "crypt.h"
#include "gost89.h"
#include <openssl/rand.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,
const unsigned char *iv, int enc);
const unsigned char *iv, int enc);
#ifdef USE_SSL
/* Specialized init functions which set specific parameters */
static 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);
static 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);
#endif
/* Handles block of data in CFB mode */
static 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);
/* Handles block of data in CNT mode */
static 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);
/* Cleanup function */
static int gost_cipher_cleanup(EVP_CIPHER_CTX *);
/* set/get cipher parameters */
@ -37,57 +36,57 @@ static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr);
EVP_CIPHER cipher_gost =
{
NID_id_Gost28147_89,
1,/*block_size*/
32,/*key_size*/
8,/*iv_len - ñèíõðîïîñûëêà*/
EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
gost_cipher_init,
gost_cipher_do_cfb,
gost_cipher_cleanup,
sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */
gost89_set_asn1_parameters,
gost89_get_asn1_parameters,
gost_cipher_ctl,
NULL,
NID_id_Gost28147_89,
1,/*block_size*/
32,/*key_size*/
8,/*iv_len - ñèíõðîïîñûëêà*/
EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
gost_cipher_init,
gost_cipher_do_cfb,
gost_cipher_cleanup,
sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */
gost89_set_asn1_parameters,
gost89_get_asn1_parameters,
gost_cipher_ctl,
NULL,
};
#ifdef USE_SSL
static EVP_CIPHER cipher_gost_vizircfb =
{
NID_undef,
1,/*block_size*/
32,/*key_size*/
8,/*iv_len - ñèíõðîïîñûëêà*/
EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
gost_cipher_init_vizir,
gost_cipher_do_cfb,
gost_cipher_cleanup,
sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
gost89_set_asn1_parameters,
gost89_get_asn1_parameters,
gost_cipher_ctl,
NULL,
NID_undef,
1,/*block_size*/
32,/*key_size*/
8,/*iv_len - ñèíõðîïîñûëêà*/
EVP_CIPH_CFB_MODE| EVP_CIPH_NO_PADDING |
EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
gost_cipher_init_vizir,
gost_cipher_do_cfb,
gost_cipher_cleanup,
sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
gost89_set_asn1_parameters,
gost89_get_asn1_parameters,
gost_cipher_ctl,
NULL,
};
static EVP_CIPHER cipher_gost_cpacnt =
{
NID_undef,
1,/*block_size*/
32,/*key_size*/
8,/*iv_len - ñèíõðîïîñûëêà*/
EVP_CIPH_OFB_MODE| EVP_CIPH_NO_PADDING |
EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
gost_cipher_init_cpa,
gost_cipher_do_cnt,
gost_cipher_cleanup,
sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
gost89_set_asn1_parameters,
gost89_get_asn1_parameters,
gost_cipher_ctl,
NULL,
NID_undef,
1,/*block_size*/
32,/*key_size*/
8,/*iv_len - ñèíõðîïîñûëêà*/
EVP_CIPH_OFB_MODE| EVP_CIPH_NO_PADDING |
EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
gost_cipher_init_cpa,
gost_cipher_do_cnt,
gost_cipher_cleanup,
sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */
gost89_set_asn1_parameters,
gost89_get_asn1_parameters,
gost_cipher_ctl,
NULL,
};
/* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */
/* Init functions which set specific parameters */
@ -143,130 +142,154 @@ EVP_MD imit_gost_cpa =
#endif
/*
* Correspondence between gost parameter OIDs and substitution blocks
* NID field is filed by register_gost_NID function in engine.c
* upon engine initialization
*/
* Correspondence between gost parameter OIDs and substitution blocks
* NID field is filed by register_gost_NID function in engine.c
* upon engine initialization
*/
struct gost_cipher_info gost_cipher_list[]={
struct gost_cipher_info gost_cipher_list[]=
{
/* NID */ /* Subst block */ /* Key meshing*/
/*{NID_id_GostR3411_94_CryptoProParamSet,&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_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
{NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
{NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
{NID_undef,NULL,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_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
{NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
{NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
{NID_undef,NULL,0}
};
/* get encryption parameters from crypto network settings
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 */
const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) {
int nid;
struct gost_cipher_info *param;
if (!obj) {
const char * params = getenv("CRYPT_PARAMS");
if (!params || !strlen(params))
return &gost_cipher_list[0];
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 */
const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj)
{
int nid;
struct gost_cipher_info *param;
if (!obj)
{
const char * params = get_gost_engine_param(GOST_PARAM_CRYPT_PARAMS);
if (!params || !strlen(params))
return &gost_cipher_list[0];
nid = OBJ_txt2nid(params);
if (nid == NID_undef) {
GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
nid = OBJ_txt2nid(params);
if (nid == NID_undef)
{
GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,
GOST_R_INVALID_CIPHER_PARAM_OID);
return NULL;
}
}
else
{
nid= OBJ_obj2nid(obj);
}
for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid;
param++);
if (!param->sblock)
{
GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAMS);
return NULL;
}
} else {
nid= OBJ_obj2nid(obj);
}
for (param=gost_cipher_list;param->sblock!=NULL && param->nid!=nid;
param++);
if (!param->sblock) {
GOSTerr(GOST_F_GET_ENCRYPTION_PARAMS,GOST_R_INVALID_CIPHER_PARAMS);
return NULL;
}
return param;
}
}
return param;
}
/* Sets cipher param from paramset 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)));
if (!param) return 0;
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)));
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 */
static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *key,
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;
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;
}
const unsigned char *iv, int enc, int paramNID,int mode)
{
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
if (ctx->app_data == NULL)
{
if (!gost_cipher_set_param(c,paramNID)) return 0;
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 */
int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) {
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
c->key_meshing=1;
c->count=0;
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;
}
const unsigned char *iv, int enc)
{
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
c->key_meshing=1;
c->count=0;
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 vizir paramset */
int gost_cipher_init_vizir(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) {
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
c->key_meshing=0;
c->count=0;
gost_key(&(c->cctx),key);
const unsigned char *iv, int enc)
{
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
c->key_meshing=0;
c->count=0;
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;
}
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 default values */
int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) {
return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE);
}
/* Wrapper around gostcrypt function from gost89.c which perform
* key meshing when nesseccary
*/
static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf) {
struct ossl_gost_cipher_ctx *c = ctx;
if (c->count&&c->key_meshing && c->count%1024==0) {
cryptopro_key_meshing(&(c->cctx),iv);
const unsigned char *iv, int enc)
{
return gost_cipher_init_param(ctx,key,iv,enc,NID_undef,EVP_CIPH_CFB_MODE);
}
/* Wrapper around gostcrypt function from gost89.c which perform
* key meshing when nesseccary
*/
static void gost_crypt_mesh (void *ctx,unsigned char *iv,unsigned char *buf)
{
struct ossl_gost_cipher_ctx *c = ctx;
if (c->count&&c->key_meshing && c->count%1024==0)
{
cryptopro_key_meshing(&(c->cctx),iv);
}
gostcrypt(&(c->cctx),iv,buf);
c->count+=8;
}
}
static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf) {
struct ossl_gost_cipher_ctx *c = ctx;
word32 g,go;
unsigned char buf1[8];
if (c->count && c->key_meshing && c->count %1024 ==0) {
cryptopro_key_meshing(&(c->cctx),iv);
}
if (c->count==0) {
gostcrypt(&(c->cctx),iv,buf1);
} else {
memcpy(buf1,iv,8);
}
static void gost_cnt_next (void *ctx, unsigned char *iv, unsigned char *buf)
{
struct ossl_gost_cipher_ctx *c = ctx;
word32 g,go;
unsigned char buf1[8];
if (c->count && c->key_meshing && c->count %1024 ==0)
{
cryptopro_key_meshing(&(c->cctx),iv);
}
if (c->count==0)
{
gostcrypt(&(c->cctx),iv,buf1);
}
else
{
memcpy(buf1,iv,8);
}
g = buf1[0]|(buf1[1]<<8)|(buf1[2]<<16)|(buf1[3]<<24);
g += 0x01010101;
buf1[0]=g&0xff; buf1[1]=(g>>8)&0xff; buf1[2]=(g>>16)&0xff; buf1[3]=(g>>24)&0xff;
@ -278,302 +301,354 @@ gostcrypt(&(c->cctx),iv,buf1);
buf1[4]=g&0xff; buf1[5]=(g>>8)&0xff; buf1[6]=(g>>16)&0xff; buf1[7]=(g>>24)&0xff;
memcpy(iv,buf1,8);
gostcrypt(&(c->cctx),buf1,buf);
c->count +=8;
}
c->count +=8;
}
/* GOST encryption in CFB mode */
int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl) {
const unsigned char *in_ptr=in;
unsigned char *out_ptr=out;
int i=0;
int j;
/* process partial block if any */
if (ctx->num)
{
for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
const unsigned char *in, unsigned int inl)
{
if (!ctx->encrypt) ctx->buf[j+8]=*in_ptr;
*out_ptr=ctx->buf[j]^(*in_ptr);
if (ctx->encrypt) ctx->buf[j+8]=*out_ptr;
}
if (j==8) {
memcpy(ctx->iv,ctx->buf+8,8);
ctx->num=0;
} else {
ctx->num=j;
return 1;
}
}
const unsigned char *in_ptr=in;
unsigned char *out_ptr=out;
int i=0;
int j=0;
/* process partial block if any */
if (ctx->num)
{
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;
*out_ptr=ctx->buf[j]^(*in_ptr);
if (ctx->encrypt) ctx->buf[j+8]=*out_ptr;
}
if (j==8)
{
memcpy(ctx->iv,ctx->buf+8,8);
ctx->num=0;
}
else
{
ctx->num=j;
return 1;
}
}
for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) {
/*block cipher current iv */
gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
/*xor next block of input text with it and output it*/
/*output this block */
if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8);
for (j=0;j<8;j++) {
for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
{
/*block cipher current iv */
gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
/*xor next block of input text with it and output it*/
/*output this block */
if (!ctx->encrypt) memcpy(ctx->iv,in_ptr,8);
for (j=0;j<8;j++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j];
}
/* Encrypt */
/* Next iv is next block of cipher text*/
if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8);
}
}
/* Encrypt */
/* Next iv is next block of cipher text*/
if (ctx->encrypt) memcpy(ctx->iv,out_ptr,8);
}
/* Process rest of buffer */
if (i<inl) {
gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,j);
for (j=0;i<inl;j++,i++) {
if (i<inl)
{
gost_crypt_mesh(ctx->cipher_data,ctx->iv,ctx->buf);
if (!ctx->encrypt) memcpy(ctx->buf+8,in_ptr,j);
for (j=0;i<inl;j++,i++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j];
}
ctx->num = j;
if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j);
} else {
ctx->num = 0;
}
return 1;
}
}
ctx->num = j;
if (ctx->encrypt) memcpy(ctx->buf+8,out_ptr,j);
}
else
{
ctx->num = 0;
}
return 1;
}
int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl) {
const unsigned char *in_ptr=in;
unsigned char *out_ptr=out;
int i=0;
int j;
/* process partial block if any */
if (ctx->num)
{
for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
const unsigned char *in, unsigned int inl)
{
*out_ptr=ctx->buf[j]^(*in_ptr);
}
if (j==8) {
ctx->num=0;
} else {
ctx->num=j;
return 1;
}
}
const unsigned char *in_ptr=in;
unsigned char *out_ptr=out;
int i=0;
int j;
/* process partial block if any */
if (ctx->num)
{
for (j=ctx->num,i=0;j<8 && i<inl;j++,i++,in_ptr++,out_ptr++)
{
*out_ptr=ctx->buf[j]^(*in_ptr);
}
if (j==8)
{
ctx->num=0;
}
else
{
ctx->num=j;
return 1;
}
}
for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8) {
/*block cipher current iv */
/* Encrypt */
gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
/*xor next block of input text with it and output it*/
/*output this block */
for (j=0;j<8;j++) {
for (;i+8<inl;i+=8,in_ptr+=8,out_ptr+=8)
{
/*block cipher current iv */
/* Encrypt */
gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
/*xor next block of input text with it and output it*/
/*output this block */
for (j=0;j<8;j++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j];
}
}
}
}
/* Process rest of buffer */
if (i<inl) {
gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
for (j=0;i<inl;j++,i++) {
if (i<inl)
{
gost_cnt_next(ctx->cipher_data,ctx->iv,ctx->buf);
for (j=0;i<inl;j++,i++)
{
out_ptr[j]=ctx->buf[j]^in_ptr[j];
}
ctx->num = j;
} else {
ctx->num = 0;
}
return 1;
}
}
ctx->num = j;
}
else
{
ctx->num = 0;
}
return 1;
}
/* Cleaning up of EVP_CIPHER_CTX */
int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx)
{
gost_destroy((gost_ctx *)ctx->cipher_data);
return 1;
{
gost_destroy((gost_ctx *)ctx->cipher_data);
ctx->app_data = NULL;
return 1;
}
}
/* Control function for gost cipher */
int gost_cipher_ctl(EVP_CIPHER_CTX *ctx,int type,int arg,void *ptr)
{
switch (type)
{
case EVP_CTRL_RAND_KEY:
{
switch (type)
{
if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0)
{
GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_RANDOM_GENERATOR_ERROR);
return -1;
}
break;
}
default:
GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
case EVP_CTRL_RAND_KEY:
{
if (RAND_bytes((unsigned char *)ptr,ctx->key_len)<=0)
{
GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_RANDOM_GENERATOR_ERROR);
return -1;
}
return 1;
}
}
break;
}
default:
GOSTerr(GOST_F_GOST_CIPHER_CTL,GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND);
return -1;
}
return 1;
}
/* Set cipher parameters from ASN1 structure */
int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
{
int len=0;
unsigned char *buf=NULL;
unsigned char *p=NULL;
struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
ASN1_OCTET_STRING *os = NULL;
if (!gcp) {
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) {
{
int len=0;
unsigned char *buf=NULL;
unsigned char *p=NULL;
struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
ASN1_OCTET_STRING *os = NULL;
if (!gcp)
{
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len))
{
GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
ASN1_OBJECT_free(gcp->enc_param_set);
gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
p = buf = (unsigned char*)OPENSSL_malloc(len);
if (!buf)
{
GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
i2d_GOST_CIPHER_PARAMS(gcp, &p);
GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
ASN1_OBJECT_free(gcp->enc_param_set);
gcp->enc_param_set = OBJ_nid2obj(c->paramNID);
len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
p = buf = (unsigned char*)OPENSSL_malloc(len);
if (!buf) {
GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
i2d_GOST_CIPHER_PARAMS(gcp, &p);
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);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
OPENSSL_free(buf);
GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, GOST_R_NO_MEMORY);
return 0;
}
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 */
int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx,ASN1_TYPE *params)
{
int ret = -1;
int len;
GOST_CIPHER_PARAMS *gcp = NULL;
unsigned char *p = params->value.sequence->data;
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
return ret;
}
{
int ret = -1;
int len;
GOST_CIPHER_PARAMS *gcp = NULL;
unsigned char *p = params->value.sequence->data;
struct ossl_gost_cipher_ctx *c=ctx->cipher_data;
if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE)
{
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);
len = gcp->iv->length;
if (len != ctx->cipher->iv_len) {
GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
len = gcp->iv->length;
if (len != ctx->cipher->iv_len)
{
GOST_CIPHER_PARAMS_free(gcp);
GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS,
GOST_R_INVALID_IV_LENGTH);
return -1;
}
if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set))) {
return -1;
}
if (!gost_cipher_set_param(c,OBJ_obj2nid(gcp->enc_param_set)))
{
GOST_CIPHER_PARAMS_free(gcp);
return -1;
}
memcpy(ctx->oiv, gcp->iv->data, len);
GOST_CIPHER_PARAMS_free(gcp);
return -1;
}
memcpy(ctx->oiv, gcp->iv->data, len);
GOST_CIPHER_PARAMS_free(gcp);
return 1;
}
return 1;
}
#ifdef USE_SSL
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));
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));
c->key_meshing=1;
gost_init(&(c->cctx),&Gost28147_CryptoProParamSetA);
return 1;
}
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));
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));
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)
{
{
char buffer[8];
/* We are using local buffer for iv because CryptoPro doesn't
* interpret internal state of MAC algorithm as iv during keymeshing
* (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);
}
}
mac_block(&(c->cctx),c->buffer,data);
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;
const unsigned char *p = data;
size_t bytes = count,i;
if (!(c->key_set)) return 0;
if (c->bytes_left) {
for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++) {
if (c->bytes_left)
{
for (i=c->bytes_left;i<8&&bytes>0;bytes--,i++,p++)
{
c->partial_block[i]=*p;
}
if (i==8) {
}
if (i==8)
{
mac_block_mesh(c,c->partial_block);
} else {
}
else
{
c->bytes_left = i;
return 1;
}
}
while (bytes>8) {
}
}
while (bytes>8)
{
mac_block_mesh(c,p);
p+=8;
bytes-=8;
}
if (bytes>0) {
}
if (bytes>0)
{
memcpy(c->partial_block,p,bytes);
c->bytes_left=bytes;
}
}
return 1;
}
int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md) {
struct ossl_gost_imit_ctx *c = ctx->md_data;
if (c->bytes_left) {
int i;
for (i=c->bytes_left;i<8;i++) {
c->partial_block[i]=0;
}
mac_block_mesh(c,c->partial_block);
}
int gost_imit_final(EVP_MD_CTX *ctx,unsigned char *md)
{
struct ossl_gost_imit_ctx *c = ctx->md_data;
if (c->bytes_left)
{
int i;
for (i=c->bytes_left;i<8;i++)
{
c->partial_block[i]=0;
}
mac_block_mesh(c,c->partial_block);
}
get_mac(c->buffer,32,md);
return 1;
}
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:
*((unsigned int*)(ptr)) = 32;
return 1;
case EVP_MD_CTRL_SET_KEY:
{
gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),ptr) ;
((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1;
}
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:
*((unsigned int*)(ptr)) = 32;
return 1;
case EVP_MD_CTRL_SET_KEY:
{
gost_key(&(((struct ossl_gost_imit_ctx*)(ctx->md_data))->cctx),ptr) ;
((struct ossl_gost_imit_ctx*)(ctx->md_data))->key_set = 1;
}
default:
return 0;
}
}
int gost_imit_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) {
default:
return 0;
}
}
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));
return 1;
}
}
/* 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));
return 1;
}
}
#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 *
* This file is distributed under the same license as OpenSSL *
* *
@ -12,26 +12,23 @@
#include <openssl/engine.h>
#include <openssl/obj_mac.h>
#include "e_gost_err.h"
#include "md.h"
#include "crypt.h"
#include "meth.h"
#include "gost_lcl.h"
static const char *engine_gost_id = "gost";
static const char *engine_gost_name = "Reference implementation of GOST engine";
/* Symmetric cipher and digest function registrar */
static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
const int **nids, int nid);
static int gost_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int ind);
const int **nids, int ind);
static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
const int **nids, int nid);
const int **nids, int nid);
static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
const int **nids, int nid);
const int **nids, int nid);
static int gost_cipher_nids[] =
{NID_id_Gost28147_89, 0};
@ -41,7 +38,7 @@ static int gost_digest_nids[] =
static int gost_pkey_meth_nids[] =
{NID_id_GostR3410_94_cc, NID_id_GostR3410_94, NID_id_GostR3410_2001_cc,
NID_id_GostR3410_2001, 0};
NID_id_GostR3410_2001, 0};
static EVP_PKEY_METHOD *pmeth_GostR3410_94_cc = NULL, *pmeth_GostR3410_94 = NULL,
*pmeth_GostR3410_2001_cc = NULL, *pmeth_GostR3410_2001 = NULL;
@ -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;
static int gost_engine_init(ENGINE *e) {
static int gost_engine_init(ENGINE *e)
{
return 1;
}
static int gost_engine_finish(ENGINE *e) {
return 1;
}
}
static int gost_engine_destroy(ENGINE *e) {
static int gost_engine_finish(ENGINE *e)
{
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;
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");
goto end;
}
if (!ENGINE_set_name(e, engine_gost_name)) {
}
if (!ENGINE_set_name(e, engine_gost_name))
{
printf("ENGINE_set_name failed\n");
goto end;
}
if (!ENGINE_set_digests(e, gost_digests)) {
}
if (!ENGINE_set_digests(e, gost_digests))
{
printf("ENGINE_set_digests failed\n");
goto end;
}
if (! ENGINE_set_ciphers(e, gost_ciphers)) {
}
if (! ENGINE_set_ciphers(e, gost_ciphers))
{
printf("ENGINE_set_ciphers failed\n");
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");
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");
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)
|| ! 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, &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 */
|| ! EVP_add_cipher(&cipher_gost)
|| ! EVP_add_digest(&digest_gost)
) goto end;
)
{
goto end;
}
ERR_load_GOST_strings();
ret = 1;
end:
end:
return ret;
}
}
#ifdef _WIN32
extern __declspec( dllexport )
@ -131,100 +154,116 @@ extern __declspec( dllexport )
IMPLEMENT_DYNAMIC_CHECK_FN();
//#else
static ENGINE *engine_gost(void)
//#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
static int gost_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid)
{
int ok =1 ;
if (!digest)
{
*nids = gost_digest_nids;
return 1;
}
//printf("Digest no %d requested\n",nid);
if(nid == NID_id_GostR3411_94)
{
*digest = &digest_gost;
}
else
{
ok =0;
*digest = NULL;
}
return ok;
}
static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
const int **nids, int nid)
{
int ok = 1;
if (!cipher)
{
*nids = gost_cipher_nids;
return 1; /* Only one cipher supported */
}
if(nid == NID_id_Gost28147_89)
{
*cipher = &cipher_gost;
}
else
{
ok = 0;
*cipher = NULL;
}
return ok;
}
static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
const int **nids, int nid)
{
if (!pmeth)
{
*nids = gost_pkey_meth_nids;
return 4;
}
switch (nid)
{
case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1;
case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1;
case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
default:;
}
*pmeth = NULL;
return 0;
}
static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
const int **nids, int nid)
{
if (!ameth)
{
*nids = gost_pkey_meth_nids;
return 4;
}
switch (nid)
{
case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1;
case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1;
case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
default:;
}
*ameth = NULL;
return 0;
}
#ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *engine_gost(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
if (!ret)
return NULL;
if(!bind_gost(ret, engine_gost_id))
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 *toadd =engine_gost();
if (!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
//#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
#endif
static int gost_digests(ENGINE *e, const EVP_MD **digest,
const int **nids, int nid)
{
int ok =1 ;
if (!digest) {
*nids = gost_digest_nids;
return 1;
}
//printf("Digest no %d requested\n",nid);
if(nid == NID_id_GostR3411_94) {
*digest = &digest_gost;
} else {
ok =0;
*digest = NULL;
}
return ok;
}
static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
const int **nids, int nid) {
int ok = 1;
if (!cipher) {
*nids = gost_cipher_nids;
return 1; /* Only one cipher supported */
}
if(nid == NID_id_Gost28147_89) {
*cipher = &cipher_gost;
} else {
ok = 0;
*cipher = NULL;
}
return ok;
}
static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
const int **nids, int nid)
{
if (!pmeth) {
*nids = gost_pkey_meth_nids;
return 4;
}
switch (nid) {
case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1;
case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1;
case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
default:;
}
*pmeth = NULL;
return 0;
}
static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
const int **nids, int nid)
{
if (!ameth) {
*nids = gost_pkey_meth_nids;
return 4;
}
switch (nid) {
case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1;
case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1;
case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
default:;
}
*ameth = NULL;
return 0;
}

View file

@ -9,7 +9,7 @@
**********************************************************************/
#include <string.h>
#include "gost89.h"
#include "keywrap.h"
#include "gost_keywrap.h"
/* Diversifies key using random UserKey Material
* Implements RFC 4357 p 6.5 key diversification algorithm
@ -20,31 +20,36 @@
*
*/
void keyDiversifyCryptoPro(gost_ctx *ctx,const unsigned char *inputKey, const unsigned char *ukm, unsigned char *outputKey)
{
{
u4 k,s1,s2;
int i,j,mask;
unsigned char S[8];
memcpy(outputKey,inputKey,32);
for (i=0;i<8;i++) {
for (i=0;i<8;i++)
{
/* Make array of integers from key */
/* Compute IV S*/
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)|
(outputKey[4*j+2]<<16)|(outputKey[4*j+3]<<24);
if (mask & ukm[i]) {
if (mask & ukm[i])
{
s1+=k;
} else {
}
else
{
s2+=k;
}
}
}
S[0]=s1&0xff; S[1]=(s1>>8)&0xff; S[2]=(s1>>16)&0xff; S[3]=(s1>>24)&0xff;
S[4]=s2&0xff; S[5]=(s2>>8)&0xff; S[6]=(s2>>16)&0xff; S[7]=(s2>>24)&0xff;
gost_key(ctx,outputKey);
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,
const unsigned char *sessionKey, unsigned char *wrappedKey)
{
{
unsigned char kek_ukm[32];
keyDiversifyCryptoPro(ctx,keyExchangeKey,ukm,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_mac_iv(ctx,32,ukm,sessionKey,32,wrappedKey+40);
return 1;
}
}
/*
* Unwraps key using RFC 4357 6.4
* ctx - gost encryption context, initialized with some S-boxes
@ -79,19 +84,20 @@ int keyWrapCryptoPro(gost_ctx *ctx,const unsigned char *keyExchangeKey, const un
*/
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];
keyDiversifyCryptoPro(ctx,keyExchangeKey,wrappedKey
/* First 8 bytes of wrapped Key is ukm */
,kek_ukm);
/* First 8 bytes of wrapped Key is ukm */
,kek_ukm);
gost_key(ctx,kek_ukm);
gost_dec(ctx,wrappedKey+8,sessionKey,4);
gost_mac_iv(ctx,32,wrappedKey,sessionKey,32,cek_mac);
if (memcmp(cek_mac,wrappedKey+40,4)) {
return 0;
}
if (memcmp(cek_mac,wrappedKey+40,4))
{
return 0;
}
return 1;
}
}

View file

@ -1,5 +1,5 @@
/**********************************************************************
* keywrap.c *
* gost_keywrap.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* 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 *
**********************************************************************/
#include <string.h>
#include "md.h"
#include "gost_lcl.h"
#include "gosthash.h"
#include "e_gost_err.h"
@ -19,51 +19,52 @@ static int gost_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from);
static int gost_digest_cleanup(EVP_MD_CTX *ctx);
EVP_MD digest_gost=
{
NID_id_GostR3411_94,
NID_undef,
32,
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
gost_digest_init,
gost_digest_update,
gost_digest_final,
gost_digest_copy,
gost_digest_cleanup,
NULL,
NULL,
{NID_undef,NID_undef,0,0,0},
32,
sizeof(struct ossl_gost_digest_ctx ),
NULL
};
{
NID_id_GostR3411_94,
NID_undef,
32,
EVP_MD_FLAG_PKEY_METHOD_SIGNATURE,
gost_digest_init,
gost_digest_update,
gost_digest_final,
gost_digest_copy,
gost_digest_cleanup,
NULL,
NULL,
{NID_undef,NID_undef,0,0,0},
32,
sizeof(struct ossl_gost_digest_ctx ),
NULL
};
int gost_digest_init(EVP_MD_CTX *ctx)
{
{
struct ossl_gost_digest_ctx *c = ctx->md_data;
memset(&(c->dctx),0,sizeof(gost_hash_ctx));
gost_init(&(c->cctx),&GostR3411_94_CryptoProParamSet);
c->dctx.cipher_ctx= &(c->cctx);
return 1;
}
}
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);
}
}
int gost_digest_final(EVP_MD_CTX *ctx,unsigned char *md)
{
{
return finish_hash((gost_hash_ctx *)ctx->md_data,md);
}
}
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));
return 1;
}
{
memcpy(to->md_data,from->md_data,sizeof(struct ossl_gost_digest_ctx));
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));
return 1;
}
}

View file

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

View file

@ -1,5 +1,5 @@
/**********************************************************************
* paramset.h *
* gost_params.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* 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 *
* This file is distributed under the same license as OpenSSL *
* *
@ -13,107 +13,115 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "meth.h"
#include "pmeth.h"
#include "sign.h"
#include "gostkeyx.h"
#include "paramset.h"
#include "tools.h"
#include "gost_params.h"
#include "gost_lcl.h"
#include "e_gost_err.h"
/*-------init, cleanup, copy - uniform for all algs ---------------*/
/* 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;
data = OPENSSL_malloc(sizeof(struct gost_pmeth_data));
if (!data) return 0;
memset(data,0,sizeof(struct gost_pmeth_data));
EVP_PKEY_CTX_set_data(ctx,data);
return 1;
}
}
/* Copies contents of gost_pmeth_data structure */
static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
{
struct gost_pmeth_data *dst_data,*src_data;
if (!pkey_gost_init(dst)) {
if (!pkey_gost_init(dst))
{
return 0;
}
}
src_data = EVP_PKEY_CTX_get_data(src);
dst_data = EVP_PKEY_CTX_get_data(dst);
*dst_data = *src_data;
if (src_data -> eph_seckey) {
if (src_data -> eph_seckey)
{
dst_data ->eph_seckey = NULL;
}
}
return 1;
}
}
/* 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);
if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
OPENSSL_free(data);
}
}
/* --------------------- control functions ------------------------------*/
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);
switch (type)
{
{
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);
return 0;
}
pctx->md = (EVP_MD *)p2;
return 1;
GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
return 0;
}
break;
pctx->md = (EVP_MD *)p2;
return 1;
}
break;
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
return 1;
return 1;
case EVP_PKEY_CTRL_GOST_PARAMSET:
pctx->sign_param_nid = (int)p1;
pctx->crypt_param_nid= (int)p2;
return 1;
}
return -2;
}
static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if(!strcmp(type, param_ctrl_string)) {
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
NID_id_GostR3410_94_CryptoPro_A_ParamSet,
(void *)NID_id_Gost28147_89_cc);
}
return -2;
}
static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if(!strcmp(type, param_ctrl_string)) {
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
NID_id_GostR3410_2001_ParamSet_cc,
(void *)
NID_id_Gost28147_89_cc);
}
return -2;
}
static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
int param_nid=0;
if(!strcmp(type, param_ctrl_string)) {
if (!value) {
return 0;
}
if (strlen(value) == 1) {
switch(toupper(value[0])) {
return -2;
}
static int pkey_gost_ctrl94cc_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if(!strcmp(type, param_ctrl_string))
{
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
NID_id_GostR3410_94_CryptoPro_A_ParamSet,
NULL);
}
return -2;
}
static int pkey_gost_ctrl01cc_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if(!strcmp(type, param_ctrl_string))
{
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
NID_id_GostR3410_2001_ParamSet_cc,NULL);
}
return -2;
}
static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
int param_nid=0;
if(!strcmp(type, param_ctrl_string))
{
if (!value)
{
return 0;
}
if (strlen(value) == 1)
{
switch(toupper(value[0]))
{
case 'A':
param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
break;
@ -129,9 +137,12 @@ static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
default:
return 0;
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':
param_nid = NID_id_GostR3410_94_CryptoPro_XchA_ParamSet;
break;
@ -144,39 +155,48 @@ static int pkey_gost_ctrl94_str(EVP_PKEY_CTX *ctx,
default:
return 0;
break;
}
}
} else {
else
{
R3410_params *p = R3410_paramset;
param_nid = OBJ_txt2nid(value);
if (param_nid == NID_undef) {
if (param_nid == NID_undef)
{
return 0;
}
for (;p->nid != NID_undef;p++) {
}
for (;p->nid != NID_undef;p++)
{
if (p->nid == param_nid) break;
}
if (p->nid == NID_undef) {
}
if (p->nid == NID_undef)
{
GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR,
GOST_R_INVALID_PARAMSET);
GOST_R_INVALID_PARAMSET);
return 0;
}
}
}
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, (void *)NID_id_Gost28147_89_CryptoPro_A_ParamSet);
}
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, NULL);
}
return -2;
}
}
static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
int param_nid=0;
if(!strcmp(type, param_ctrl_string)) {
if (!value) {
if(!strcmp(type, param_ctrl_string))
{
if (!value)
{
return 0;
}
if (strlen(value) == 1) {
switch(toupper(value[0])) {
}
if (strlen(value) == 1)
{
switch(toupper(value[0]))
{
case 'A':
param_nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet;
break;
@ -192,9 +212,12 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
default:
return 0;
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':
param_nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet;
break;
@ -204,172 +227,198 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
default:
return 0;
break;
}
}
} else {
else
{
R3410_2001_params *p = R3410_2001_paramset;
param_nid = OBJ_txt2nid(value);
if (param_nid == NID_undef) {
if (param_nid == NID_undef)
{
return 0;
}
for (;p->nid != NID_undef;p++) {
}
for (;p->nid != NID_undef;p++)
{
if (p->nid == param_nid) break;
}
if (p->nid == NID_undef) {
}
if (p->nid == NID_undef)
{
GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
GOST_R_INVALID_PARAMSET);
GOST_R_INVALID_PARAMSET);
return 0;
}
}
}
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, (void *)NID_id_Gost28147_89_CryptoPro_A_ParamSet);
}
return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
param_nid, NULL);
}
return -2;
}
}
/* --------------------- key generation --------------------------------*/
/* Generates GOST 94 key and assigns it setting specified 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);
DSA *dsa=NULL;
if (data->sign_param_nid == NID_undef) {
if (type== NID_id_GostR3410_94_cc) {
if (data->sign_param_nid == NID_undef)
{
if (type== NID_id_GostR3410_94_cc)
{
data->sign_param_nid = NID_id_GostR3410_94_CryptoPro_A_ParamSet;
} else {
}
else
{
GOSTerr(GOST_F_PKEY_GOST94_KEYGEN,
GOST_R_NO_PARAMETERS_SET);
GOST_R_NO_PARAMETERS_SET);
return 0;
}
}
}
}
dsa = DSA_new();
if (!fill_GOST94_params(dsa,data->sign_param_nid)) {
if (!fill_GOST94_params(dsa,data->sign_param_nid))
{
DSA_free(dsa);
return 0;
}
}
gost_sign_keygen(dsa);
EVP_PKEY_assign(pkey,type,dsa);
return 1;
}
}
/* 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);
}
}
/* 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);
}
}
/* 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)
{
{
struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
EC_KEY *ec=NULL;
if (data->sign_param_nid == NID_undef) {
if (type == NID_id_GostR3410_2001_cc) {
if (data->sign_param_nid == NID_undef)
{
if (type == NID_id_GostR3410_2001_cc)
{
data->sign_param_nid = NID_id_GostR3410_2001_ParamSet_cc;
} else {
}
else {
GOSTerr(GOST_F_PKEY_GOST01_KEYGEN,
GOST_R_NO_PARAMETERS_SET);
GOST_R_NO_PARAMETERS_SET);
return 0;
}
}
}
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);
return 0;
}
}
gost2001_keygen(ec);
EVP_PKEY_assign(pkey,type,ec);
return 1;
}
}
/* 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);
}
}
/* 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);
}
}
/* ----------- sign callbacks --------------------------------------*/
static int pkey_gost94_cc_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbs_len)
{
{
DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0;
if (!sig)
{
if (!sig)
{
*siglen= 64; /* better to check size of pkey->pkey.dsa-q */
return 1;
}
}
unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) {
if (!unpacked_sig)
{
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,
const unsigned char *tbs, size_t tbs_len)
{
{
DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0;
if (!sig)
{
if (!sig)
{
*siglen= 64; /* better to check size of pkey->pkey.dsa-q */
return 1;
}
}
unpacked_sig = gost_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) {
if (!unpacked_sig)
{
return 0;
}
}
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,
const unsigned char *tbs, size_t tbs_len)
{
{
DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0;
if (!sig)
{
if (!sig)
{
*siglen= 64; /* better to check size of curve order*/
return 1;
}
}
unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) {
if (!unpacked_sig)
{
return 0;
}
}
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,
const unsigned char *tbs, size_t tbs_len)
{
{
DSA_SIG *unpacked_sig=NULL;
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
if (!siglen) return 0;
if (!sig)
{
if (!sig)
{
*siglen= 64; /* better to check size of curve order*/
return 1;
}
}
unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
if (!unpacked_sig) {
if (!unpacked_sig)
{
return 0;
}
}
return pack_sign_cp(unpacked_sig,32,sig,siglen);
}
}
/* ------------------- verify callbacks ---------------------------*/
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)
{
{
int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
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));
DSA_SIG_free(s);
return ok;
}
}
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)
{
{
int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
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));
DSA_SIG_free(s);
return ok;
}
}
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)
{
{
int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
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));
DSA_SIG_free(s);
return ok;
}
}
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)
{
{
int ok = 0;
EVP_PKEY* pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
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));
DSA_SIG_free(s);
return ok;
}
}
/* ------------- encrypt init -------------------------------------*/
/* 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);
EVP_PKEY *eph_key = EVP_PKEY_new();
EVP_PKEY *old_key =EVP_PKEY_CTX_get0_pkey(ctx);
@ -434,46 +485,50 @@ static int pkey_gost_encrypt_init(EVP_PKEY_CTX *ctx)
if (data->eph_seckey) EVP_PKEY_free(data->eph_seckey);
EVP_PKEY_assign(eph_key,EVP_PKEY_base_id(old_key),NULL);
if (!EVP_PKEY_copy_parameters(eph_key,old_key)) return 0;
switch (EVP_PKEY_base_id(old_key)) {
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
gost2001_keygen(EVP_PKEY_get0(eph_key));
break;
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
gost_sign_keygen(EVP_PKEY_get0(eph_key));
break;
switch (EVP_PKEY_base_id(old_key))
{
case NID_id_GostR3410_2001:
case NID_id_GostR3410_2001_cc:
gost2001_keygen(EVP_PKEY_get0(eph_key));
break;
case NID_id_GostR3410_94:
case NID_id_GostR3410_94_cc:
gost_sign_keygen(EVP_PKEY_get0(eph_key));
break;
}
}
data->eph_seckey=eph_key;
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);
if (!*pmeth) return 0;
switch (id) {
switch (id)
{
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_sign(*pmeth, NULL, pkey_gost94_cc_sign);
EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cc_verify);
EVP_PKEY_meth_set_encrypt(*pmeth,
EVP_PKEY_meth_set_encrypt(*pmeth,
pkey_gost_encrypt_init, pkey_GOST94cc_encrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cc_decrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cc_decrypt);
break;
case NID_id_GostR3410_94:
EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl94_str);
EVP_PKEY_meth_set_keygen(*pmeth,NULL,pkey_gost94cp_keygen);
EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost94_cp_sign);
EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost94_cp_verify);
EVP_PKEY_meth_set_encrypt(*pmeth,
EVP_PKEY_meth_set_encrypt(*pmeth,
pkey_gost_encrypt_init, pkey_GOST94cp_encrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST94cp_decrypt);
break;
@ -484,9 +539,9 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) {
EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cc_keygen);
EVP_PKEY_meth_set_encrypt(*pmeth,
EVP_PKEY_meth_set_encrypt(*pmeth,
pkey_gost_encrypt_init, pkey_GOST01cc_encrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cc_decrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cc_decrypt);
break;
/* There is intentionally no break here */
case NID_id_GostR3410_2001:
@ -496,13 +551,13 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) {
EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost01cp_keygen);
EVP_PKEY_meth_set_encrypt(*pmeth,
EVP_PKEY_meth_set_encrypt(*pmeth,
pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
break;
default: //Unsupported method
return 0;
}
}
EVP_PKEY_meth_set_init(*pmeth, pkey_gost_init);
EVP_PKEY_meth_set_cleanup(*pmeth, pkey_gost_cleanup);
@ -510,5 +565,5 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags) {
//FIXME derive etc...
return 1;
}
}

View file

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

View file

@ -28,60 +28,64 @@
/* Following functions are various bit meshing routines used in
* GOST R 34.11-94 algorithms */
static void swap_bytes (byte *w, byte *k)
{
{
int i,j;
for (i=0;i<4;i++)
for (j=0;j<8;j++)
k[i+4*j]=w[8*i+j];
}
}
/* was A_A */
static void circle_xor8 (const byte *w, byte *k)
{
{
byte buf[8];
int i;
memcpy(buf,w,8);
memcpy(k,w+8,24);
for(i=0;i<8;i++)
k[i+24]=buf[i]^k[i];
}
}
/* was R_R */
static void transform_3 (byte *data)
{
{
unsigned short int acc;
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);
memmove(data,data+2,30);
data[30]=acc&0xff;
data[31]=acc>>8;
}
}
/* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/
static int add_blocks(int n,byte *left, const byte *right)
{
int i;
int carry=0;
int sum;
for (i=0;i<n;i++)
{
{
int i;
int carry=0;
int sum;
for (i=0;i<n;i++)
{
sum=(int)left[i]+(int)right[i]+carry;
left[i]=sum & 0xff;
carry=sum>>8;
}
return carry;
}
}
return carry;
}
/* 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;
for (i=0;i<len;i++) result[i]=a[i]^b[i];
}
}
/*
* Calculate H(i+1) = Hash(Hi,Mi)
* Where H and M are 32 bytes long
*/
static int hash_step(gost_ctx *c,byte *H,const byte *M)
{
{
static byte U[32],W[32],V[32],S[32],Key[32];
int i;
/* Compute first key */
@ -126,20 +130,23 @@ static int hash_step(gost_ctx *c,byte *H,const byte *M)
transform_3(S);
memcpy(H,S,32);
return 1;
}
}
/* Initialize gost_hash ctx - cleans up temporary structures and
* 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));
ctx->cipher_ctx = (gost_ctx *)MYALLOC(sizeof(gost_ctx));
if (!ctx->cipher_ctx) {
return 0;
}
if (!ctx->cipher_ctx)
{
return 0;
}
gost_init(ctx->cipher_ctx,subst_block);
return 1;
}
}
/*
* Free cipher CTX if it is dynamically allocated. Do not use
* 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)
{
{
/* No need to use gost_destroy, because cipher keys are not really
* secret when hashing */
MYFREE(ctx->cipher_ctx);
}
}
/*
* 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;
memset(&(ctx->H),0,32);
memset(&(ctx->S),0,32);
ctx->len = 0L;
ctx->left=0;
return 1;
}
}
/*
* 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 *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*/
int add_bytes = 32-ctx->left;
if (add_bytes>length) {
if (add_bytes>length)
{
add_bytes = length;
}
}
memcpy(&(ctx->remainder[ctx->left]),block,add_bytes);
ctx->left+=add_bytes;
if (ctx->left<32) {
if (ctx->left<32)
{
return 1;
}
if (ctx->left>32) {
abort();
}
}
curptr=block+add_bytes;
hash_step(ctx->cipher_ctx,ctx->H,ctx->remainder);
if (save_c!=ctx->cipher_ctx) {
abort();
}
add_blocks(32,ctx->S,ctx->remainder);
if (save_c!=ctx->cipher_ctx) {
abort();
}
ctx->len+=32;
ctx->left=0;
}
}
while (curptr<=barrier)
{
{
hash_step(ctx->cipher_ctx,ctx->H,curptr);
if (save_c!=ctx->cipher_ctx) {
abort();
}
add_blocks(32,ctx->S,curptr);
if (save_c!=ctx->cipher_ctx) {
abort();
}
ctx->len+=32;
curptr+=32;
}
if (curptr!=block+length) {
ctx->left=block+length-curptr;
if (ctx->left>32) {
abort();
}
if (curptr!=block+length)
{
ctx->left=block+length-curptr;
memcpy(ctx->remainder,curptr,ctx->left);
}
}
return 1;
}
}
/*
* Compute hash value from current state of ctx
* state of hash ctx becomes invalid and cannot be used for further
* hashing.
*/
int finish_hash(gost_hash_ctx *ctx,byte *hashval) {
int finish_hash(gost_hash_ctx *ctx,byte *hashval)
{
byte buf[32];
byte H[32];
byte S[32];
@ -234,23 +232,25 @@ int finish_hash(gost_hash_ctx *ctx,byte *hashval) {
byte *bptr;
memcpy(H,ctx->H,32);
memcpy(S,ctx->S,32);
if (ctx->left) {
if (ctx->left)
{
memset(buf,0,32);
memcpy(buf,ctx->remainder,ctx->left);
hash_step(ctx->cipher_ctx,H,buf);
add_blocks(32,S,buf);
fin_len+=ctx->left;
}
}
memset(buf,0,32);
bptr=buf;
fin_len<<=3; /* Hash length in BITS!!*/
while(fin_len>0) {
while(fin_len>0)
{
*(bptr++)=fin_len&0xFF;
fin_len>>=8;
};
};
hash_step(ctx->cipher_ctx,H,buf);
hash_step(ctx->cipher_ctx,H,S);
memcpy(hashval,H,32);
return 1;
}
}

View file

@ -1,5 +1,5 @@
/**********************************************************************
* gosthash.c *
* gosthash.h *
* Copyright (c) 2005-2006 Cryptocom LTD *
* 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

@ -5,8 +5,8 @@
* *
* Almost drop-in replacement for md5sum and sha1sum *
* which computes GOST R 34.11-94 hashsum instead *
* *
**********************************************************************/
* *
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -18,24 +18,24 @@
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 get_line(FILE *f,char *hash,char *filename);
void help()
{
void help()
{
fprintf(stderr,"gostsum [-bvt] [-c [file]]| [files]\n"
"\t-c check message digests (default is generate)\n"
"\t-v verbose, print file names when checking\n"
"\t-b read files in binary mode\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"
"that is printed on stdout by this program when it generates digests.\n");
exit(3);
}
"\t-c check message digests (default is generate)\n"
"\t-v verbose, print file names when checking\n"
"\t-b read files in binary mode\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"
"that is printed on stdout by this program when it generates digests.\n");
exit(3);
}
#ifndef O_BINARY
#define O_BINARY 0
#endif
int main(int argc,char **argv)
{
int main(int argc,char **argv)
{
int c,i;
int verbose=0;
int errors=0;
@ -44,141 +44,167 @@ int main(int argc,char **argv)
FILE *check_file = NULL;
gost_hash_ctx ctx;
while( (c=getopt(argc,argv,"bc::tv"))!=-1)
{
switch (c)
while( (c=getopt(argc,argv,"bc::tv"))!=-1)
{
case 'v': verbose=1; break;
case 't': b= &GostR3411_94_TestParamSet; break;
case 'b': open_mode |= O_BINARY; break;
case 'c': if (optarg) {
switch (c)
{
case 'v': verbose=1; break;
case 't': b= &GostR3411_94_TestParamSet; break;
case 'b': open_mode |= O_BINARY; break;
case 'c':
if (optarg)
{
check_file = fopen(optarg,"r");
if (!check_file) {
if (!check_file)
{
perror(optarg);
exit(2);
}
}
} else {
else
{
check_file= stdin;
}
break;
default:
}
break;
default:
fprintf(stderr,"invalid option %c",optopt);
help();
}
}
}
init_gost_hash_ctx(&ctx,b);
if (check_file)
{
if (check_file)
{
char inhash[65],calcsum[65],filename[PATH_MAX];
int failcount=0,count=0;;
if (check_file==stdin && optind<argc)
{
if (check_file==stdin && optind<argc)
{
check_file=fopen(argv[optind],"r");
if (!check_file)
{
if (!check_file)
{
perror(argv[optind]);
exit(2);
}
}
while (get_line(check_file,inhash,filename))
{
if (!hash_file(&ctx,filename,calcsum,open_mode)) {
exit (2);
}
}
count++;
if (!strncmp(calcsum,inhash,65))
while (get_line(check_file,inhash,filename))
{
if (verbose) {
if (!hash_file(&ctx,filename,calcsum,open_mode))
{
exit (2);
}
count++;
if (!strncmp(calcsum,inhash,65))
{
if (verbose)
{
fprintf(stderr,"%s\tOK\n",filename);
}
}
} else {
if (verbose) {
else
{
if (verbose)
{
fprintf(stderr,"%s\tFAILED\n",filename);
} else {
}
else
{
fprintf(stderr,"%s: GOST hash sum check failed for '%s'\n",
argv[0],filename);
}
argv[0],filename);
}
failcount++;
}
}
}
if (verbose && failcount) {
if (verbose && failcount)
{
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);
}
if (optind==argc) {
}
if (optind==argc)
{
char sum[65];
if (!hash_stream(&ctx,fileno(stdin),sum)) {
if (!hash_stream(&ctx,fileno(stdin),sum))
{
perror("stdin");
exit(1);
}
}
printf("%s -\n",sum);
exit(0);
}
for (i=optind;i<argc;i++) {
}
for (i=optind;i<argc;i++)
{
char sum[65];
if (!hash_file(&ctx,argv[i],sum,open_mode)) {
if (!hash_file(&ctx,argv[i],sum,open_mode))
{
errors++;
} else {
}
else
{
printf("%s %s\n",sum,argv[i]);
}
}
}
}
exit(errors?1:0);
}
int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode)
{
int fd;
if ((fd=open(filename,mode))<0) {
perror(filename);
return 0;
}
if (!hash_stream(ctx,fd,sum)) {
int hash_file(gost_hash_ctx *ctx,char *filename,char *sum,int mode)
{
int fd;
if ((fd=open(filename,mode))<0)
{
perror(filename);
return 0;
}
}
if (!hash_stream(ctx,fd,sum))
{
perror(filename);
return 0;
}
close(fd);
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];
ssize_t bytes;
int i;
start_hash(ctx);
while ((bytes=read(fd,buffer,BUF_SIZE))>0) {
while ((bytes=read(fd,buffer,BUF_SIZE))>0)
{
hash_block(ctx,buffer,bytes);
}
if (bytes<0) {
}
if (bytes<0)
{
return 0;
}
}
finish_hash(ctx,buffer);
for (i=0;i<32;i++) {
sprintf(sum+2*i,"%02x",buffer[31-i]);
}
for (i=0;i<32;i++)
{
sprintf(sum+2*i,"%02x",buffer[31-i]);
}
return 1;
}
}
int get_line(FILE *f,char *hash,char *filename) {
int get_line(FILE *f,char *hash,char *filename)
{
int i;
if (fread(hash,1,64,f)<64) return 0;
hash[64]=0;
for (i=0;i<64;i++)
{
for (i=0;i<64;i++)
{
if (hash[i]<'0' || (hash[i]>'9' && hash[i]<'A') || (hash[i]>'F'
&& hash[i]<'a')||hash[i]>'f')
{
&& hash[i]<'a')||hash[i]>'f')
{
fprintf(stderr,"Not a hash value '%s'\n",hash);
return 0;
}
}
if (fgetc(f)!=' ') {
}
}
if (fgetc(f)!=' ')
{
fprintf(stderr,"Malformed input line\n");
return 0;
}
}
i=strlen(fgets(filename,PATH_MAX,f));
while (filename[--i]=='\n'||filename[i]=='\r') filename[i]=0;
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