summaryrefslogtreecommitdiff
path: root/crypto/engine
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-11-05 13:57:22 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-11-05 13:57:22 -0800
commit37a8d409f8ffc065c1b1417f0f3b5ba050e8aa95 (patch)
treed502257cab443605232c089d204c5f964d52b1f0 /crypto/engine
downloadopenssl-37a8d409f8ffc065c1b1417f0f3b5ba050e8aa95.tar.gz
openssl-37a8d409f8ffc065c1b1417f0f3b5ba050e8aa95.tar.bz2
openssl-37a8d409f8ffc065c1b1417f0f3b5ba050e8aa95.zip
Imported Upstream version 1.0.1cupstream/1.0.1c
Diffstat (limited to 'crypto/engine')
-rw-r--r--crypto/engine/Makefile447
-rw-r--r--crypto/engine/README211
-rw-r--r--crypto/engine/eng_all.c135
-rw-r--r--crypto/engine/eng_cnf.c259
-rw-r--r--crypto/engine/eng_cryptodev.c1450
-rw-r--r--crypto/engine/eng_ctrl.c389
-rw-r--r--crypto/engine/eng_dyn.c548
-rw-r--r--crypto/engine/eng_err.c173
-rw-r--r--crypto/engine/eng_fat.c182
-rw-r--r--crypto/engine/eng_init.c154
-rw-r--r--crypto/engine/eng_int.h206
-rw-r--r--crypto/engine/eng_lib.c332
-rw-r--r--crypto/engine/eng_list.c433
-rw-r--r--crypto/engine/eng_openssl.c384
-rw-r--r--crypto/engine/eng_pkey.c196
-rw-r--r--crypto/engine/eng_rdrand.c142
-rw-r--r--crypto/engine/eng_rsax.c668
-rw-r--r--crypto/engine/eng_table.c351
-rw-r--r--crypto/engine/engine.h842
-rw-r--r--crypto/engine/enginetest.c283
-rw-r--r--crypto/engine/tb_asnmth.c246
-rw-r--r--crypto/engine/tb_cipher.c143
-rw-r--r--crypto/engine/tb_dh.c118
-rw-r--r--crypto/engine/tb_digest.c143
-rw-r--r--crypto/engine/tb_dsa.c118
-rw-r--r--crypto/engine/tb_ecdh.c133
-rw-r--r--crypto/engine/tb_ecdsa.c118
-rw-r--r--crypto/engine/tb_pkmeth.c167
-rw-r--r--crypto/engine/tb_rand.c118
-rw-r--r--crypto/engine/tb_rsa.c118
-rw-r--r--crypto/engine/tb_store.c123
31 files changed, 9330 insertions, 0 deletions
diff --git a/crypto/engine/Makefile b/crypto/engine/Makefile
new file mode 100644
index 0000000..d29bdd0
--- /dev/null
+++ b/crypto/engine/Makefile
@@ -0,0 +1,447 @@
+#
+# OpenSSL/crypto/engine/Makefile
+#
+
+DIR= engine
+TOP= ../..
+CC= cc
+INCLUDES= -I.. -I$(TOP) -I../../include
+CFLAG=-g
+MAKEFILE= Makefile
+AR= ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+GENERAL=Makefile
+TEST= enginetest.c
+APPS=
+
+LIB=$(TOP)/libcrypto.a
+LIBSRC= eng_err.c eng_lib.c eng_list.c eng_init.c eng_ctrl.c \
+ eng_table.c eng_pkey.c eng_fat.c eng_all.c \
+ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \
+ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \
+ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \
+ eng_rsax.c eng_rdrand.c
+LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
+ eng_table.o eng_pkey.o eng_fat.o eng_all.o \
+ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \
+ tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \
+ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \
+ eng_rsax.o eng_rdrand.o
+
+SRC= $(LIBSRC)
+
+EXHEADER= engine.h
+HEADER= $(EXHEADER)
+
+ALL= $(GENERAL) $(SRC) $(HEADER)
+
+top:
+ (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+all: lib
+
+lib: $(LIBOBJ)
+ $(AR) $(LIB) $(LIBOBJ)
+ $(RANLIB) $(LIB) || echo Never mind.
+ @touch lib
+
+files:
+ $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+
+links:
+ @$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+ @$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+ @$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+ @[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+ @headerlist="$(EXHEADER)"; for i in $$headerlist ; \
+ do \
+ (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+ chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+ done;
+
+tags:
+ ctags $(SRC)
+
+tests:
+
+lint:
+ lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+ @[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
+ $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC)
+
+dclean:
+ $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+ mv -f Makefile.new $(MAKEFILE)
+
+clean:
+ rm -f *.o */*.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+eng_all.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_all.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_all.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_all.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_all.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_all.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_all.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_all.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_all.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_all.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+eng_all.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_all.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_all.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_all.c eng_int.h
+eng_cnf.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_cnf.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_cnf.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+eng_cnf.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+eng_cnf.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+eng_cnf.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+eng_cnf.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_cnf.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+eng_cnf.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+eng_cnf.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+eng_cnf.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_cnf.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_cnf.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_cnf.o: ../cryptlib.h eng_cnf.c eng_int.h
+eng_cryptodev.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
+eng_cryptodev.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
+eng_cryptodev.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_cryptodev.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_cryptodev.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_cryptodev.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_cryptodev.o: ../../include/openssl/obj_mac.h
+eng_cryptodev.o: ../../include/openssl/objects.h
+eng_cryptodev.o: ../../include/openssl/opensslconf.h
+eng_cryptodev.o: ../../include/openssl/opensslv.h
+eng_cryptodev.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+eng_cryptodev.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_cryptodev.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_cryptodev.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_cryptodev.o: eng_cryptodev.c
+eng_ctrl.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_ctrl.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_ctrl.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_ctrl.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_ctrl.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_ctrl.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_ctrl.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_ctrl.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_ctrl.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_ctrl.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+eng_ctrl.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_ctrl.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_ctrl.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_ctrl.c eng_int.h
+eng_dyn.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_dyn.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_dyn.o: ../../include/openssl/crypto.h ../../include/openssl/dso.h
+eng_dyn.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+eng_dyn.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+eng_dyn.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+eng_dyn.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_dyn.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+eng_dyn.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+eng_dyn.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+eng_dyn.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_dyn.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_dyn.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_dyn.o: ../cryptlib.h eng_dyn.c eng_int.h
+eng_err.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
+eng_err.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+eng_err.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+eng_err.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+eng_err.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+eng_err.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_err.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+eng_err.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+eng_err.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+eng_err.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_err.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_err.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_err.o: eng_err.c
+eng_fat.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_fat.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_fat.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+eng_fat.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+eng_fat.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+eng_fat.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+eng_fat.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_fat.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+eng_fat.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+eng_fat.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+eng_fat.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_fat.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_fat.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_fat.o: ../cryptlib.h eng_fat.c eng_int.h
+eng_init.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_init.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_init.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_init.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_init.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_init.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_init.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_init.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_init.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_init.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+eng_init.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_init.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_init.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_init.c eng_int.h
+eng_lib.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_lib.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_lib.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_lib.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_lib.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_lib.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_lib.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_lib.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_lib.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_lib.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
+eng_lib.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_lib.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_lib.o: ../cryptlib.h eng_int.h eng_lib.c
+eng_list.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_list.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_list.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_list.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_list.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_list.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_list.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_list.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_list.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_list.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+eng_list.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_list.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_list.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h eng_list.c
+eng_openssl.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_openssl.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_openssl.o: ../../include/openssl/crypto.h ../../include/openssl/dh.h
+eng_openssl.o: ../../include/openssl/dsa.h ../../include/openssl/dso.h
+eng_openssl.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+eng_openssl.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+eng_openssl.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+eng_openssl.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_openssl.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+eng_openssl.o: ../../include/openssl/opensslconf.h
+eng_openssl.o: ../../include/openssl/opensslv.h
+eng_openssl.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
+eng_openssl.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
+eng_openssl.o: ../../include/openssl/rand.h ../../include/openssl/rc4.h
+eng_openssl.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
+eng_openssl.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_openssl.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_openssl.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_openssl.c
+eng_pkey.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_pkey.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_pkey.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_pkey.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_pkey.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_pkey.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_pkey.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_pkey.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_pkey.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_pkey.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+eng_pkey.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_pkey.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_pkey.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h eng_pkey.c
+eng_rdrand.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
+eng_rdrand.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+eng_rdrand.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+eng_rdrand.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+eng_rdrand.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+eng_rdrand.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+eng_rdrand.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+eng_rdrand.o: ../../include/openssl/opensslconf.h
+eng_rdrand.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_rdrand.o: ../../include/openssl/pkcs7.h ../../include/openssl/rand.h
+eng_rdrand.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_rdrand.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_rdrand.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_rdrand.o: eng_rdrand.c
+eng_rsax.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
+eng_rsax.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
+eng_rsax.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_rsax.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_rsax.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_rsax.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_rsax.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_rsax.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+eng_rsax.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_rsax.o: ../../include/openssl/pkcs7.h ../../include/openssl/rsa.h
+eng_rsax.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+eng_rsax.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+eng_rsax.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+eng_rsax.o: eng_rsax.c
+eng_table.o: ../../e_os.h ../../include/openssl/asn1.h
+eng_table.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+eng_table.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+eng_table.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+eng_table.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+eng_table.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+eng_table.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+eng_table.o: ../../include/openssl/objects.h
+eng_table.o: ../../include/openssl/opensslconf.h
+eng_table.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+eng_table.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+eng_table.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+eng_table.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+eng_table.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+eng_table.o: eng_table.c
+tb_asnmth.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_asnmth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_asnmth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_asnmth.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_asnmth.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_asnmth.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_asnmth.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_asnmth.o: ../../include/openssl/objects.h
+tb_asnmth.o: ../../include/openssl/opensslconf.h
+tb_asnmth.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_asnmth.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_asnmth.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_asnmth.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_asnmth.o: ../../include/openssl/x509_vfy.h ../asn1/asn1_locl.h ../cryptlib.h
+tb_asnmth.o: eng_int.h tb_asnmth.c
+tb_cipher.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_cipher.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_cipher.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_cipher.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_cipher.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_cipher.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_cipher.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_cipher.o: ../../include/openssl/objects.h
+tb_cipher.o: ../../include/openssl/opensslconf.h
+tb_cipher.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_cipher.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_cipher.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_cipher.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_cipher.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+tb_cipher.o: tb_cipher.c
+tb_dh.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
+tb_dh.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+tb_dh.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+tb_dh.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+tb_dh.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+tb_dh.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+tb_dh.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+tb_dh.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+tb_dh.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+tb_dh.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+tb_dh.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+tb_dh.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+tb_dh.o: ../cryptlib.h eng_int.h tb_dh.c
+tb_digest.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_digest.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_digest.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_digest.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_digest.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_digest.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_digest.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_digest.o: ../../include/openssl/objects.h
+tb_digest.o: ../../include/openssl/opensslconf.h
+tb_digest.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_digest.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_digest.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_digest.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_digest.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+tb_digest.o: tb_digest.c
+tb_dsa.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
+tb_dsa.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+tb_dsa.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+tb_dsa.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+tb_dsa.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+tb_dsa.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+tb_dsa.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+tb_dsa.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+tb_dsa.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+tb_dsa.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+tb_dsa.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+tb_dsa.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+tb_dsa.o: ../cryptlib.h eng_int.h tb_dsa.c
+tb_ecdh.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_ecdh.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_ecdh.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_ecdh.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_ecdh.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_ecdh.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_ecdh.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_ecdh.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+tb_ecdh.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_ecdh.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_ecdh.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_ecdh.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_ecdh.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h tb_ecdh.c
+tb_ecdsa.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_ecdsa.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_ecdsa.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_ecdsa.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_ecdsa.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_ecdsa.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_ecdsa.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_ecdsa.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+tb_ecdsa.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_ecdsa.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_ecdsa.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_ecdsa.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_ecdsa.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h tb_ecdsa.c
+tb_pkmeth.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_pkmeth.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_pkmeth.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_pkmeth.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_pkmeth.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_pkmeth.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_pkmeth.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_pkmeth.o: ../../include/openssl/objects.h
+tb_pkmeth.o: ../../include/openssl/opensslconf.h
+tb_pkmeth.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_pkmeth.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_pkmeth.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_pkmeth.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_pkmeth.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h
+tb_pkmeth.o: tb_pkmeth.c
+tb_rand.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_rand.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_rand.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_rand.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_rand.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_rand.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_rand.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_rand.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+tb_rand.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_rand.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_rand.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_rand.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_rand.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h tb_rand.c
+tb_rsa.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
+tb_rsa.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+tb_rsa.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+tb_rsa.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+tb_rsa.o: ../../include/openssl/engine.h ../../include/openssl/err.h
+tb_rsa.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+tb_rsa.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+tb_rsa.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+tb_rsa.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+tb_rsa.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+tb_rsa.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+tb_rsa.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+tb_rsa.o: ../cryptlib.h eng_int.h tb_rsa.c
+tb_store.o: ../../e_os.h ../../include/openssl/asn1.h
+tb_store.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+tb_store.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+tb_store.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+tb_store.o: ../../include/openssl/ecdsa.h ../../include/openssl/engine.h
+tb_store.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+tb_store.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+tb_store.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+tb_store.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+tb_store.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+tb_store.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+tb_store.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+tb_store.o: ../../include/openssl/x509_vfy.h ../cryptlib.h eng_int.h tb_store.c
diff --git a/crypto/engine/README b/crypto/engine/README
new file mode 100644
index 0000000..6b69b70
--- /dev/null
+++ b/crypto/engine/README
@@ -0,0 +1,211 @@
+Notes: 2001-09-24
+-----------------
+
+This "description" (if one chooses to call it that) needed some major updating
+so here goes. This update addresses a change being made at the same time to
+OpenSSL, and it pretty much completely restructures the underlying mechanics of
+the "ENGINE" code. So it serves a double purpose of being a "ENGINE internals
+for masochists" document *and* a rather extensive commit log message. (I'd get
+lynched for sticking all this in CHANGES or the commit mails :-).
+
+ENGINE_TABLE underlies this restructuring, as described in the internal header
+"eng_int.h", implemented in eng_table.c, and used in each of the "class" files;
+tb_rsa.c, tb_dsa.c, etc.
+
+However, "EVP_CIPHER" underlies the motivation and design of ENGINE_TABLE so
+I'll mention a bit about that first. EVP_CIPHER (and most of this applies
+equally to EVP_MD for digests) is both a "method" and a algorithm/mode
+identifier that, in the current API, "lingers". These cipher description +
+implementation structures can be defined or obtained directly by applications,
+or can be loaded "en masse" into EVP storage so that they can be catalogued and
+searched in various ways, ie. two ways of encrypting with the "des_cbc"
+algorithm/mode pair are;
+
+(i) directly;
+ const EVP_CIPHER *cipher = EVP_des_cbc();
+ EVP_EncryptInit(&ctx, cipher, key, iv);
+ [ ... use EVP_EncryptUpdate() and EVP_EncryptFinal() ...]
+
+(ii) indirectly;
+ OpenSSL_add_all_ciphers();
+ cipher = EVP_get_cipherbyname("des_cbc");
+ EVP_EncryptInit(&ctx, cipher, key, iv);
+ [ ... etc ... ]
+
+The latter is more generally used because it also allows ciphers/digests to be
+looked up based on other identifiers which can be useful for automatic cipher
+selection, eg. in SSL/TLS, or by user-controllable configuration.
+
+The important point about this is that EVP_CIPHER definitions and structures are
+passed around with impunity and there is no safe way, without requiring massive
+rewrites of many applications, to assume that EVP_CIPHERs can be reference
+counted. One an EVP_CIPHER is exposed to the caller, neither it nor anything it
+comes from can "safely" be destroyed. Unless of course the way of getting to
+such ciphers is via entirely distinct API calls that didn't exist before.
+However existing API usage cannot be made to understand when an EVP_CIPHER
+pointer, that has been passed to the caller, is no longer being used.
+
+The other problem with the existing API w.r.t. to hooking EVP_CIPHER support
+into ENGINE is storage - the OBJ_NAME-based storage used by EVP to register
+ciphers simultaneously registers cipher *types* and cipher *implementations* -
+they are effectively the same thing, an "EVP_CIPHER" pointer. The problem with
+hooking in ENGINEs is that multiple ENGINEs may implement the same ciphers. The
+solution is necessarily that ENGINE-provided ciphers simply are not registered,
+stored, or exposed to the caller in the same manner as existing ciphers. This is
+especially necessary considering the fact ENGINE uses reference counts to allow
+for cleanup, modularity, and DSO support - yet EVP_CIPHERs, as exposed to
+callers in the current API, support no such controls.
+
+Another sticking point for integrating cipher support into ENGINE is linkage.
+Already there is a problem with the way ENGINE supports RSA, DSA, etc whereby
+they are available *because* they're part of a giant ENGINE called "openssl".
+Ie. all implementations *have* to come from an ENGINE, but we get round that by
+having a giant ENGINE with all the software support encapsulated. This creates
+linker hassles if nothing else - linking a 1-line application that calls 2 basic
+RSA functions (eg. "RSA_free(RSA_new());") will result in large quantities of
+ENGINE code being linked in *and* because of that DSA, DH, and RAND also. If we
+continue with this approach for EVP_CIPHER support (even if it *was* possible)
+we would lose our ability to link selectively by selectively loading certain
+implementations of certain functionality. Touching any part of any kind of
+crypto would result in massive static linkage of everything else. So the
+solution is to change the way ENGINE feeds existing "classes", ie. how the
+hooking to ENGINE works from RSA, DSA, DH, RAND, as well as adding new hooking
+for EVP_CIPHER, and EVP_MD.
+
+The way this is now being done is by mostly reverting back to how things used to
+work prior to ENGINE :-). Ie. RSA now has a "RSA_METHOD" pointer again - this
+was previously replaced by an "ENGINE" pointer and all RSA code that required
+the RSA_METHOD would call ENGINE_get_RSA() each time on its ENGINE handle to
+temporarily get and use the ENGINE's RSA implementation. Apart from being more
+efficient, switching back to each RSA having an RSA_METHOD pointer also allows
+us to conceivably operate with *no* ENGINE. As we'll see, this removes any need
+for a fallback ENGINE that encapsulates default implementations - we can simply
+have our RSA structure pointing its RSA_METHOD pointer to the software
+implementation and have its ENGINE pointer set to NULL.
+
+A look at the EVP_CIPHER hooking is most explanatory, the RSA, DSA (etc) cases
+turn out to be degenerate forms of the same thing. The EVP storage of ciphers,
+and the existing EVP API functions that return "software" implementations and
+descriptions remain untouched. However, the storage takes more meaning in terms
+of "cipher description" and less meaning in terms of "implementation". When an
+EVP_CIPHER_CTX is actually initialised with an EVP_CIPHER method and is about to
+begin en/decryption, the hooking to ENGINE comes into play. What happens is that
+cipher-specific ENGINE code is asked for an ENGINE pointer (a functional
+reference) for any ENGINE that is registered to perform the algo/mode that the
+provided EVP_CIPHER structure represents. Under normal circumstances, that
+ENGINE code will return NULL because no ENGINEs will have had any cipher
+implementations *registered*. As such, a NULL ENGINE pointer is stored in the
+EVP_CIPHER_CTX context, and the EVP_CIPHER structure is left hooked into the
+context and so is used as the implementation. Pretty much how things work now
+except we'd have a redundant ENGINE pointer set to NULL and doing nothing.
+
+Conversely, if an ENGINE *has* been registered to perform the algorithm/mode
+combination represented by the provided EVP_CIPHER, then a functional reference
+to that ENGINE will be returned to the EVP_CIPHER_CTX during initialisation.
+That functional reference will be stored in the context (and released on
+cleanup) - and having that reference provides a *safe* way to use an EVP_CIPHER
+definition that is private to the ENGINE. Ie. the EVP_CIPHER provided by the
+application will actually be replaced by an EVP_CIPHER from the registered
+ENGINE - it will support the same algorithm/mode as the original but will be a
+completely different implementation. Because this EVP_CIPHER isn't stored in the
+EVP storage, nor is it returned to applications from traditional API functions,
+there is no associated problem with it not having reference counts. And of
+course, when one of these "private" cipher implementations is hooked into
+EVP_CIPHER_CTX, it is done whilst the EVP_CIPHER_CTX holds a functional
+reference to the ENGINE that owns it, thus the use of the ENGINE's EVP_CIPHER is
+safe.
+
+The "cipher-specific ENGINE code" I mentioned is implemented in tb_cipher.c but
+in essence it is simply an instantiation of "ENGINE_TABLE" code for use by
+EVP_CIPHER code. tb_digest.c is virtually identical but, of course, it is for
+use by EVP_MD code. Ditto for tb_rsa.c, tb_dsa.c, etc. These instantiations of
+ENGINE_TABLE essentially provide linker-separation of the classes so that even
+if ENGINEs implement *all* possible algorithms, an application using only
+EVP_CIPHER code will link at most code relating to EVP_CIPHER, tb_cipher.c, core
+ENGINE code that is independant of class, and of course the ENGINE
+implementation that the application loaded. It will *not* however link any
+class-specific ENGINE code for digests, RSA, etc nor will it bleed over into
+other APIs, such as the RSA/DSA/etc library code.
+
+ENGINE_TABLE is a little more complicated than may seem necessary but this is
+mostly to avoid a lot of "init()"-thrashing on ENGINEs (that may have to load
+DSOs, and other expensive setup that shouldn't be thrashed unnecessarily) *and*
+to duplicate "default" behaviour. Basically an ENGINE_TABLE instantiation, for
+example tb_cipher.c, implements a hash-table keyed by integer "nid" values.
+These nids provide the uniquenness of an algorithm/mode - and each nid will hash
+to a potentially NULL "ENGINE_PILE". An ENGINE_PILE is essentially a list of
+pointers to ENGINEs that implement that particular 'nid'. Each "pile" uses some
+caching tricks such that requests on that 'nid' will be cached and all future
+requests will return immediately (well, at least with minimal operation) unless
+a change is made to the pile, eg. perhaps an ENGINE was unloaded. The reason is
+that an application could have support for 10 ENGINEs statically linked
+in, and the machine in question may not have any of the hardware those 10
+ENGINEs support. If each of those ENGINEs has a "des_cbc" implementation, we
+want to avoid every EVP_CIPHER_CTX setup from trying (and failing) to initialise
+each of those 10 ENGINEs. Instead, the first such request will try to do that
+and will either return (and cache) a NULL ENGINE pointer or will return a
+functional reference to the first that successfully initialised. In the latter
+case it will also cache an extra functional reference to the ENGINE as a
+"default" for that 'nid'. The caching is acknowledged by a 'uptodate' variable
+that is unset only if un/registration takes place on that pile. Ie. if
+implementations of "des_cbc" are added or removed. This behaviour can be
+tweaked; the ENGINE_TABLE_FLAG_NOINIT value can be passed to
+ENGINE_set_table_flags(), in which case the only ENGINEs that tb_cipher.c will
+try to initialise from the "pile" will be those that are already initialised
+(ie. it's simply an increment of the functional reference count, and no real
+"initialisation" will take place).
+
+RSA, DSA, DH, and RAND all have their own ENGINE_TABLE code as well, and the
+difference is that they all use an implicit 'nid' of 1. Whereas EVP_CIPHERs are
+actually qualitatively different depending on 'nid' (the "des_cbc" EVP_CIPHER is
+not an interoperable implementation of "aes_256_cbc"), RSA_METHODs are
+necessarily interoperable and don't have different flavours, only different
+implementations. In other words, the ENGINE_TABLE for RSA will either be empty,
+or will have a single ENGING_PILE hashed to by the 'nid' 1 and that pile
+represents ENGINEs that implement the single "type" of RSA there is.
+
+Cleanup - the registration and unregistration may pose questions about how
+cleanup works with the ENGINE_PILE doing all this caching nonsense (ie. when the
+application or EVP_CIPHER code releases its last reference to an ENGINE, the
+ENGINE_PILE code may still have references and thus those ENGINEs will stay
+hooked in forever). The way this is handled is via "unregistration". With these
+new ENGINE changes, an abstract ENGINE can be loaded and initialised, but that
+is an algorithm-agnostic process. Even if initialised, it will not have
+registered any of its implementations (to do so would link all class "table"
+code despite the fact the application may use only ciphers, for example). This
+is deliberately a distinct step. Moreover, registration and unregistration has
+nothing to do with whether an ENGINE is *functional* or not (ie. you can even
+register an ENGINE and its implementations without it being operational, you may
+not even have the drivers to make it operate). What actually happens with
+respect to cleanup is managed inside eng_lib.c with the "engine_cleanup_***"
+functions. These functions are internal-only and each part of ENGINE code that
+could require cleanup will, upon performing its first allocation, register a
+callback with the "engine_cleanup" code. The other part of this that makes it
+tick is that the ENGINE_TABLE instantiations (tb_***.c) use NULL as their
+initialised state. So if RSA code asks for an ENGINE and no ENGINE has
+registered an implementation, the code will simply return NULL and the tb_rsa.c
+state will be unchanged. Thus, no cleanup is required unless registration takes
+place. ENGINE_cleanup() will simply iterate across a list of registered cleanup
+callbacks calling each in turn, and will then internally delete its own storage
+(a STACK). When a cleanup callback is next registered (eg. if the cleanup() is
+part of a gracefull restart and the application wants to cleanup all state then
+start again), the internal STACK storage will be freshly allocated. This is much
+the same as the situation in the ENGINE_TABLE instantiations ... NULL is the
+initialised state, so only modification operations (not queries) will cause that
+code to have to register a cleanup.
+
+What else? The bignum callbacks and associated ENGINE functions have been
+removed for two obvious reasons; (i) there was no way to generalise them to the
+mechanism now used by RSA/DSA/..., because there's no such thing as a BIGNUM
+method, and (ii) because of (i), there was no meaningful way for library or
+application code to automatically hook and use ENGINE supplied bignum functions
+anyway. Also, ENGINE_cpy() has been removed (although an internal-only version
+exists) - the idea of providing an ENGINE_cpy() function probably wasn't a good
+one and now certainly doesn't make sense in any generalised way. Some of the
+RSA, DSA, DH, and RAND functions that were fiddled during the original ENGINE
+changes have now, as a consequence, been reverted back. This is because the
+hooking of ENGINE is now automatic (and passive, it can interally use a NULL
+ENGINE pointer to simply ignore ENGINE from then on).
+
+Hell, that should be enough for now ... comments welcome: geoff@openssl.org
+
diff --git a/crypto/engine/eng_all.c b/crypto/engine/eng_all.c
new file mode 100644
index 0000000..6093376
--- /dev/null
+++ b/crypto/engine/eng_all.c
@@ -0,0 +1,135 @@
+/* crypto/engine/eng_all.c -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte <richard@levitte.org> for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "cryptlib.h"
+#include "eng_int.h"
+
+void ENGINE_load_builtin_engines(void)
+ {
+ /* Some ENGINEs need this */
+ OPENSSL_cpuid_setup();
+#if 0
+ /* There's no longer any need for an "openssl" ENGINE unless, one day,
+ * it is the *only* way for standard builtin implementations to be be
+ * accessed (ie. it would be possible to statically link binaries with
+ * *no* builtin implementations). */
+ ENGINE_load_openssl();
+#endif
+#if !defined(OPENSSL_NO_HW) && (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV))
+ ENGINE_load_cryptodev();
+#endif
+#ifndef OPENSSL_NO_RSAX
+ ENGINE_load_rsax();
+#endif
+#ifndef OPENSSL_NO_RDRAND
+ ENGINE_load_rdrand();
+#endif
+ ENGINE_load_dynamic();
+#ifndef OPENSSL_NO_STATIC_ENGINE
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_4758_CCA
+ ENGINE_load_4758cca();
+#endif
+#ifndef OPENSSL_NO_HW_AEP
+ ENGINE_load_aep();
+#endif
+#ifndef OPENSSL_NO_HW_ATALLA
+ ENGINE_load_atalla();
+#endif
+#ifndef OPENSSL_NO_HW_CSWIFT
+ ENGINE_load_cswift();
+#endif
+#ifndef OPENSSL_NO_HW_NCIPHER
+ ENGINE_load_chil();
+#endif
+#ifndef OPENSSL_NO_HW_NURON
+ ENGINE_load_nuron();
+#endif
+#ifndef OPENSSL_NO_HW_SUREWARE
+ ENGINE_load_sureware();
+#endif
+#ifndef OPENSSL_NO_HW_UBSEC
+ ENGINE_load_ubsec();
+#endif
+#ifndef OPENSSL_NO_HW_PADLOCK
+ ENGINE_load_padlock();
+#endif
+#endif
+#ifndef OPENSSL_NO_GOST
+ ENGINE_load_gost();
+#endif
+#ifndef OPENSSL_NO_GMP
+ ENGINE_load_gmp();
+#endif
+#if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
+ ENGINE_load_capi();
+#endif
+#endif
+ ENGINE_register_all_complete();
+ }
+
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+void ENGINE_setup_bsd_cryptodev(void) {
+ static int bsd_cryptodev_default_loaded = 0;
+ if (!bsd_cryptodev_default_loaded) {
+ ENGINE_load_cryptodev();
+ ENGINE_register_all_complete();
+ }
+ bsd_cryptodev_default_loaded=1;
+}
+#endif
diff --git a/crypto/engine/eng_cnf.c b/crypto/engine/eng_cnf.c
new file mode 100644
index 0000000..95c4070
--- /dev/null
+++ b/crypto/engine/eng_cnf.c
@@ -0,0 +1,259 @@
+/* eng_cnf.c */
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+#include <openssl/conf.h>
+
+/* #define ENGINE_CONF_DEBUG */
+
+/* ENGINE config module */
+
+static char *skip_dot(char *name)
+ {
+ char *p;
+ p = strchr(name, '.');
+ if (p)
+ return p + 1;
+ return name;
+ }
+
+static STACK_OF(ENGINE) *initialized_engines = NULL;
+
+static int int_engine_init(ENGINE *e)
+ {
+ if (!ENGINE_init(e))
+ return 0;
+ if (!initialized_engines)
+ initialized_engines = sk_ENGINE_new_null();
+ if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e))
+ {
+ ENGINE_finish(e);
+ return 0;
+ }
+ return 1;
+ }
+
+
+static int int_engine_configure(char *name, char *value, const CONF *cnf)
+ {
+ int i;
+ int ret = 0;
+ long do_init = -1;
+ STACK_OF(CONF_VALUE) *ecmds;
+ CONF_VALUE *ecmd = NULL;
+ char *ctrlname, *ctrlvalue;
+ ENGINE *e = NULL;
+ int soft = 0;
+
+ name = skip_dot(name);
+#ifdef ENGINE_CONF_DEBUG
+ fprintf(stderr, "Configuring engine %s\n", name);
+#endif
+ /* Value is a section containing ENGINE commands */
+ ecmds = NCONF_get_section(cnf, value);
+
+ if (!ecmds)
+ {
+ ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR);
+ return 0;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++)
+ {
+ ecmd = sk_CONF_VALUE_value(ecmds, i);
+ ctrlname = skip_dot(ecmd->name);
+ ctrlvalue = ecmd->value;
+#ifdef ENGINE_CONF_DEBUG
+ fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue);
+#endif
+
+ /* First handle some special pseudo ctrls */
+
+ /* Override engine name to use */
+ if (!strcmp(ctrlname, "engine_id"))
+ name = ctrlvalue;
+ else if (!strcmp(ctrlname, "soft_load"))
+ soft = 1;
+ /* Load a dynamic ENGINE */
+ else if (!strcmp(ctrlname, "dynamic_path"))
+ {
+ e = ENGINE_by_id("dynamic");
+ if (!e)
+ goto err;
+ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
+ goto err;
+ if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
+ goto err;
+ if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
+ goto err;
+ }
+ /* ... add other pseudos here ... */
+ else
+ {
+ /* At this point we need an ENGINE structural reference
+ * if we don't already have one.
+ */
+ if (!e)
+ {
+ e = ENGINE_by_id(name);
+ if (!e && soft)
+ {
+ ERR_clear_error();
+ return 1;
+ }
+ if (!e)
+ goto err;
+ }
+ /* Allow "EMPTY" to mean no value: this allows a valid
+ * "value" to be passed to ctrls of type NO_INPUT
+ */
+ if (!strcmp(ctrlvalue, "EMPTY"))
+ ctrlvalue = NULL;
+ if (!strcmp(ctrlname, "init"))
+ {
+ if (!NCONF_get_number_e(cnf, value, "init", &do_init))
+ goto err;
+ if (do_init == 1)
+ {
+ if (!int_engine_init(e))
+ goto err;
+ }
+ else if (do_init != 0)
+ {
+ ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_INVALID_INIT_VALUE);
+ goto err;
+ }
+ }
+ else if (!strcmp(ctrlname, "default_algorithms"))
+ {
+ if (!ENGINE_set_default_string(e, ctrlvalue))
+ goto err;
+ }
+ else if (!ENGINE_ctrl_cmd_string(e,
+ ctrlname, ctrlvalue, 0))
+ goto err;
+ }
+
+
+
+ }
+ if (e && (do_init == -1) && !int_engine_init(e))
+ {
+ ecmd = NULL;
+ goto err;
+ }
+ ret = 1;
+ err:
+ if (ret != 1)
+ {
+ ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_CONFIGURATION_ERROR);
+ if (ecmd)
+ ERR_add_error_data(6, "section=", ecmd->section,
+ ", name=", ecmd->name,
+ ", value=", ecmd->value);
+ }
+ if (e)
+ ENGINE_free(e);
+ return ret;
+ }
+
+
+static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
+ {
+ STACK_OF(CONF_VALUE) *elist;
+ CONF_VALUE *cval;
+ int i;
+#ifdef ENGINE_CONF_DEBUG
+ fprintf(stderr, "Called engine module: name %s, value %s\n",
+ CONF_imodule_get_name(md), CONF_imodule_get_value(md));
+#endif
+ /* Value is a section containing ENGINEs to configure */
+ elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
+
+ if (!elist)
+ {
+ ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT, ENGINE_R_ENGINES_SECTION_ERROR);
+ return 0;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(elist); i++)
+ {
+ cval = sk_CONF_VALUE_value(elist, i);
+ if (!int_engine_configure(cval->name, cval->value, cnf))
+ return 0;
+ }
+
+ return 1;
+ }
+
+static void int_engine_module_finish(CONF_IMODULE *md)
+ {
+ ENGINE *e;
+ while ((e = sk_ENGINE_pop(initialized_engines)))
+ ENGINE_finish(e);
+ sk_ENGINE_free(initialized_engines);
+ initialized_engines = NULL;
+ }
+
+
+void ENGINE_add_conf_module(void)
+ {
+ CONF_module_add("engines",
+ int_engine_module_init,
+ int_engine_module_finish);
+ }
diff --git a/crypto/engine/eng_cryptodev.c b/crypto/engine/eng_cryptodev.c
new file mode 100644
index 0000000..5a715ac
--- /dev/null
+++ b/crypto/engine/eng_cryptodev.c
@@ -0,0 +1,1450 @@
+/*
+ * Copyright (c) 2002 Bob Beck <beck@openbsd.org>
+ * Copyright (c) 2002 Theo de Raadt
+ * Copyright (c) 2002 Markus Friedl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <openssl/objects.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+
+#if (defined(__unix__) || defined(unix)) && !defined(USG) && \
+ (defined(OpenBSD) || defined(__FreeBSD__))
+#include <sys/param.h>
+# if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041)
+# define HAVE_CRYPTODEV
+# endif
+# if (OpenBSD >= 200110)
+# define HAVE_SYSLOG_R
+# endif
+#endif
+
+#ifndef HAVE_CRYPTODEV
+
+void
+ENGINE_load_cryptodev(void)
+{
+ /* This is a NOP on platforms without /dev/crypto */
+ return;
+}
+
+#else
+
+#include <sys/types.h>
+#include <crypto/cryptodev.h>
+#include <crypto/dh/dh.h>
+#include <crypto/dsa/dsa.h>
+#include <crypto/err/err.h>
+#include <crypto/rsa/rsa.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+
+struct dev_crypto_state {
+ struct session_op d_sess;
+ int d_fd;
+
+#ifdef USE_CRYPTODEV_DIGESTS
+ char dummy_mac_key[HASH_MAX_LEN];
+
+ unsigned char digest_res[HASH_MAX_LEN];
+ char *mac_data;
+ int mac_len;
+#endif
+};
+
+static u_int32_t cryptodev_asymfeat = 0;
+
+static int get_asym_dev_crypto(void);
+static int open_dev_crypto(void);
+static int get_dev_crypto(void);
+static int get_cryptodev_ciphers(const int **cnids);
+#ifdef USE_CRYPTODEV_DIGESTS
+static int get_cryptodev_digests(const int **cnids);
+#endif
+static int cryptodev_usable_ciphers(const int **nids);
+static int cryptodev_usable_digests(const int **nids);
+static int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx);
+static int cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid);
+static int cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid);
+static int bn2crparam(const BIGNUM *a, struct crparam *crp);
+static int crparam2bn(struct crparam *crp, BIGNUM *a);
+static void zapparams(struct crypt_kop *kop);
+static int cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r,
+ int slen, BIGNUM *s);
+
+static int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+static int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I,
+ RSA *rsa, BN_CTX *ctx);
+static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+static int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
+ BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, BIGNUM *p,
+ BN_CTX *ctx, BN_MONT_CTX *mont);
+static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst,
+ int dlen, DSA *dsa);
+static int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
+static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+static int cryptodev_dh_compute_key(unsigned char *key,
+ const BIGNUM *pub_key, DH *dh);
+static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p,
+ void (*f)(void));
+void ENGINE_load_cryptodev(void);
+
+static const ENGINE_CMD_DEFN cryptodev_defns[] = {
+ { 0, NULL, NULL, 0 }
+};
+
+static struct {
+ int id;
+ int nid;
+ int ivmax;
+ int keylen;
+} ciphers[] = {
+ { CRYPTO_ARC4, NID_rc4, 0, 16, },
+ { CRYPTO_DES_CBC, NID_des_cbc, 8, 8, },
+ { CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24, },
+ { CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16, },
+ { CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24, },
+ { CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32, },
+ { CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16, },
+ { CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16, },
+ { CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0, },
+ { 0, NID_undef, 0, 0, },
+};
+
+#ifdef USE_CRYPTODEV_DIGESTS
+static struct {
+ int id;
+ int nid;
+ int keylen;
+} digests[] = {
+ { CRYPTO_MD5_HMAC, NID_hmacWithMD5, 16},
+ { CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, 20},
+ { CRYPTO_RIPEMD160_HMAC, NID_ripemd160, 16/*?*/},
+ { CRYPTO_MD5_KPDK, NID_undef, 0},
+ { CRYPTO_SHA1_KPDK, NID_undef, 0},
+ { CRYPTO_MD5, NID_md5, 16},
+ { CRYPTO_SHA1, NID_sha1, 20},
+ { 0, NID_undef, 0},
+};
+#endif
+
+/*
+ * Return a fd if /dev/crypto seems usable, 0 otherwise.
+ */
+static int
+open_dev_crypto(void)
+{
+ static int fd = -1;
+
+ if (fd == -1) {
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1)
+ return (-1);
+ /* close on exec */
+ if (fcntl(fd, F_SETFD, 1) == -1) {
+ close(fd);
+ fd = -1;
+ return (-1);
+ }
+ }
+ return (fd);
+}
+
+static int
+get_dev_crypto(void)
+{
+ int fd, retfd;
+
+ if ((fd = open_dev_crypto()) == -1)
+ return (-1);
+#ifndef CRIOGET_NOT_NEEDED
+ if (ioctl(fd, CRIOGET, &retfd) == -1)
+ return (-1);
+
+ /* close on exec */
+ if (fcntl(retfd, F_SETFD, 1) == -1) {
+ close(retfd);
+ return (-1);
+ }
+#else
+ retfd = fd;
+#endif
+ return (retfd);
+}
+
+static void put_dev_crypto(int fd)
+{
+#ifndef CRIOGET_NOT_NEEDED
+ close(fd);
+#endif
+}
+
+/* Caching version for asym operations */
+static int
+get_asym_dev_crypto(void)
+{
+ static int fd = -1;
+
+ if (fd == -1)
+ fd = get_dev_crypto();
+ return fd;
+}
+
+/*
+ * Find out what ciphers /dev/crypto will let us have a session for.
+ * XXX note, that some of these openssl doesn't deal with yet!
+ * returning them here is harmless, as long as we return NULL
+ * when asked for a handler in the cryptodev_engine_ciphers routine
+ */
+static int
+get_cryptodev_ciphers(const int **cnids)
+{
+ static int nids[CRYPTO_ALGORITHM_MAX];
+ struct session_op sess;
+ int fd, i, count = 0;
+
+ if ((fd = get_dev_crypto()) < 0) {
+ *cnids = NULL;
+ return (0);
+ }
+ memset(&sess, 0, sizeof(sess));
+ sess.key = (caddr_t)"123456789abcdefghijklmno";
+
+ for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+ if (ciphers[i].nid == NID_undef)
+ continue;
+ sess.cipher = ciphers[i].id;
+ sess.keylen = ciphers[i].keylen;
+ sess.mac = 0;
+ if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
+ ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+ nids[count++] = ciphers[i].nid;
+ }
+ put_dev_crypto(fd);
+
+ if (count > 0)
+ *cnids = nids;
+ else
+ *cnids = NULL;
+ return (count);
+}
+
+#ifdef USE_CRYPTODEV_DIGESTS
+/*
+ * Find out what digests /dev/crypto will let us have a session for.
+ * XXX note, that some of these openssl doesn't deal with yet!
+ * returning them here is harmless, as long as we return NULL
+ * when asked for a handler in the cryptodev_engine_digests routine
+ */
+static int
+get_cryptodev_digests(const int **cnids)
+{
+ static int nids[CRYPTO_ALGORITHM_MAX];
+ struct session_op sess;
+ int fd, i, count = 0;
+
+ if ((fd = get_dev_crypto()) < 0) {
+ *cnids = NULL;
+ return (0);
+ }
+ memset(&sess, 0, sizeof(sess));
+ sess.mackey = (caddr_t)"123456789abcdefghijklmno";
+ for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+ if (digests[i].nid == NID_undef)
+ continue;
+ sess.mac = digests[i].id;
+ sess.mackeylen = digests[i].keylen;
+ sess.cipher = 0;
+ if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
+ ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+ nids[count++] = digests[i].nid;
+ }
+ put_dev_crypto(fd);
+
+ if (count > 0)
+ *cnids = nids;
+ else
+ *cnids = NULL;
+ return (count);
+}
+#endif /* 0 */
+
+/*
+ * Find the useable ciphers|digests from dev/crypto - this is the first
+ * thing called by the engine init crud which determines what it
+ * can use for ciphers from this engine. We want to return
+ * only what we can do, anythine else is handled by software.
+ *
+ * If we can't initialize the device to do anything useful for
+ * any reason, we want to return a NULL array, and 0 length,
+ * which forces everything to be done is software. By putting
+ * the initalization of the device in here, we ensure we can
+ * use this engine as the default, and if for whatever reason
+ * /dev/crypto won't do what we want it will just be done in
+ * software
+ *
+ * This can (should) be greatly expanded to perhaps take into
+ * account speed of the device, and what we want to do.
+ * (although the disabling of particular alg's could be controlled
+ * by the device driver with sysctl's.) - this is where we
+ * want most of the decisions made about what we actually want
+ * to use from /dev/crypto.
+ */
+static int
+cryptodev_usable_ciphers(const int **nids)
+{
+ return (get_cryptodev_ciphers(nids));
+}
+
+static int
+cryptodev_usable_digests(const int **nids)
+{
+#ifdef USE_CRYPTODEV_DIGESTS
+ return (get_cryptodev_digests(nids));
+#else
+ /*
+ * XXXX just disable all digests for now, because it sucks.
+ * we need a better way to decide this - i.e. I may not
+ * want digests on slow cards like hifn on fast machines,
+ * but might want them on slow or loaded machines, etc.
+ * will also want them when using crypto cards that don't
+ * suck moose gonads - would be nice to be able to decide something
+ * as reasonable default without having hackery that's card dependent.
+ * of course, the default should probably be just do everything,
+ * with perhaps a sysctl to turn algoritms off (or have them off
+ * by default) on cards that generally suck like the hifn.
+ */
+ *nids = NULL;
+ return (0);
+#endif
+}
+
+static int
+cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = ctx->cipher_data;
+ struct session_op *sess = &state->d_sess;
+ const void *iiv;
+ unsigned char save_iv[EVP_MAX_IV_LENGTH];
+
+ if (state->d_fd < 0)
+ return (0);
+ if (!inl)
+ return (1);
+ if ((inl % ctx->cipher->block_size) != 0)
+ return (0);
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = inl;
+ cryp.src = (caddr_t) in;
+ cryp.dst = (caddr_t) out;
+ cryp.mac = 0;
+
+ cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
+
+ if (ctx->cipher->iv_len) {
+ cryp.iv = (caddr_t) ctx->iv;
+ if (!ctx->encrypt) {
+ iiv = in + inl - ctx->cipher->iv_len;
+ memcpy(save_iv, iiv, ctx->cipher->iv_len);
+ }
+ } else
+ cryp.iv = NULL;
+
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) == -1) {
+ /* XXX need better errror handling
+ * this can fail for a number of different reasons.
+ */
+ return (0);
+ }
+
+ if (ctx->cipher->iv_len) {
+ if (ctx->encrypt)
+ iiv = out + inl - ctx->cipher->iv_len;
+ else
+ iiv = save_iv;
+ memcpy(ctx->iv, iiv, ctx->cipher->iv_len);
+ }
+ return (1);
+}
+
+static int
+cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ struct dev_crypto_state *state = ctx->cipher_data;
+ struct session_op *sess = &state->d_sess;
+ int cipher = -1, i;
+
+ for (i = 0; ciphers[i].id; i++)
+ if (ctx->cipher->nid == ciphers[i].nid &&
+ ctx->cipher->iv_len <= ciphers[i].ivmax &&
+ ctx->key_len == ciphers[i].keylen) {
+ cipher = ciphers[i].id;
+ break;
+ }
+
+ if (!ciphers[i].id) {
+ state->d_fd = -1;
+ return (0);
+ }
+
+ memset(sess, 0, sizeof(struct session_op));
+
+ if ((state->d_fd = get_dev_crypto()) < 0)
+ return (0);
+
+ sess->key = (caddr_t)key;
+ sess->keylen = ctx->key_len;
+ sess->cipher = cipher;
+
+ if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) {
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * free anything we allocated earlier when initting a
+ * session, and close the session.
+ */
+static int
+cryptodev_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ int ret = 0;
+ struct dev_crypto_state *state = ctx->cipher_data;
+ struct session_op *sess = &state->d_sess;
+
+ if (state->d_fd < 0)
+ return (0);
+
+ /* XXX if this ioctl fails, someting's wrong. the invoker
+ * may have called us with a bogus ctx, or we could
+ * have a device that for whatever reason just doesn't
+ * want to play ball - it's not clear what's right
+ * here - should this be an error? should it just
+ * increase a counter, hmm. For right now, we return
+ * 0 - I don't believe that to be "right". we could
+ * call the gorpy openssl lib error handlers that
+ * print messages to users of the library. hmm..
+ */
+
+ if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) == -1) {
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+
+ return (ret);
+}
+
+/*
+ * libcrypto EVP stuff - this is how we get wired to EVP so the engine
+ * gets called when libcrypto requests a cipher NID.
+ */
+
+/* RC4 */
+const EVP_CIPHER cryptodev_rc4 = {
+ NID_rc4,
+ 1, 16, 0,
+ EVP_CIPH_VARIABLE_LENGTH,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ NULL,
+ NULL,
+ NULL
+};
+
+/* DES CBC EVP */
+const EVP_CIPHER cryptodev_des_cbc = {
+ NID_des_cbc,
+ 8, 8, 8,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+/* 3DES CBC EVP */
+const EVP_CIPHER cryptodev_3des_cbc = {
+ NID_des_ede3_cbc,
+ 8, 24, 8,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+const EVP_CIPHER cryptodev_bf_cbc = {
+ NID_bf_cbc,
+ 8, 16, 8,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+const EVP_CIPHER cryptodev_cast_cbc = {
+ NID_cast5_cbc,
+ 8, 16, 8,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+const EVP_CIPHER cryptodev_aes_cbc = {
+ NID_aes_128_cbc,
+ 16, 16, 16,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+const EVP_CIPHER cryptodev_aes_192_cbc = {
+ NID_aes_192_cbc,
+ 16, 24, 16,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+const EVP_CIPHER cryptodev_aes_256_cbc = {
+ NID_aes_256_cbc,
+ 16, 32, 16,
+ EVP_CIPH_CBC_MODE,
+ cryptodev_init_key,
+ cryptodev_cipher,
+ cryptodev_cleanup,
+ sizeof(struct dev_crypto_state),
+ EVP_CIPHER_set_asn1_iv,
+ EVP_CIPHER_get_asn1_iv,
+ NULL
+};
+
+/*
+ * Registered by the ENGINE when used to find out how to deal with
+ * a particular NID in the ENGINE. this says what we'll do at the
+ * top level - note, that list is restricted by what we answer with
+ */
+static int
+cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid)
+{
+ if (!cipher)
+ return (cryptodev_usable_ciphers(nids));
+
+ switch (nid) {
+ case NID_rc4:
+ *cipher = &cryptodev_rc4;
+ break;
+ case NID_des_ede3_cbc:
+ *cipher = &cryptodev_3des_cbc;
+ break;
+ case NID_des_cbc:
+ *cipher = &cryptodev_des_cbc;
+ break;
+ case NID_bf_cbc:
+ *cipher = &cryptodev_bf_cbc;
+ break;
+ case NID_cast5_cbc:
+ *cipher = &cryptodev_cast_cbc;
+ break;
+ case NID_aes_128_cbc:
+ *cipher = &cryptodev_aes_cbc;
+ break;
+ case NID_aes_192_cbc:
+ *cipher = &cryptodev_aes_192_cbc;
+ break;
+ case NID_aes_256_cbc:
+ *cipher = &cryptodev_aes_256_cbc;
+ break;
+ default:
+ *cipher = NULL;
+ break;
+ }
+ return (*cipher != NULL);
+}
+
+
+#ifdef USE_CRYPTODEV_DIGESTS
+
+/* convert digest type to cryptodev */
+static int
+digest_nid_to_cryptodev(int nid)
+{
+ int i;
+
+ for (i = 0; digests[i].id; i++)
+ if (digests[i].nid == nid)
+ return (digests[i].id);
+ return (0);
+}
+
+
+static int
+digest_key_length(int nid)
+{
+ int i;
+
+ for (i = 0; digests[i].id; i++)
+ if (digests[i].nid == nid)
+ return digests[i].keylen;
+ return (0);
+}
+
+
+static int cryptodev_digest_init(EVP_MD_CTX *ctx)
+{
+ struct dev_crypto_state *state = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+ int digest;
+
+ if ((digest = digest_nid_to_cryptodev(ctx->digest->type)) == NID_undef){
+ printf("cryptodev_digest_init: Can't get digest \n");
+ return (0);
+ }
+
+ memset(state, 0, sizeof(struct dev_crypto_state));
+
+ if ((state->d_fd = get_dev_crypto()) < 0) {
+ printf("cryptodev_digest_init: Can't get Dev \n");
+ return (0);
+ }
+
+ sess->mackey = state->dummy_mac_key;
+ sess->mackeylen = digest_key_length(ctx->digest->type);
+ sess->mac = digest;
+
+ if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+ printf("cryptodev_digest_init: Open session failed\n");
+ return (0);
+ }
+
+ return (1);
+}
+
+static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
+ size_t count)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+
+ if (!data || state->d_fd < 0) {
+ printf("cryptodev_digest_update: illegal inputs \n");
+ return (0);
+ }
+
+ if (!count) {
+ return (0);
+ }
+
+ if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) {
+ /* if application doesn't support one buffer */
+ state->mac_data = OPENSSL_realloc(state->mac_data, state->mac_len + count);
+
+ if (!state->mac_data) {
+ printf("cryptodev_digest_update: realloc failed\n");
+ return (0);
+ }
+
+ memcpy(state->mac_data + state->mac_len, data, count);
+ state->mac_len += count;
+
+ return (1);
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = count;
+ cryp.src = (caddr_t) data;
+ cryp.dst = NULL;
+ cryp.mac = (caddr_t) state->digest_res;
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
+ printf("cryptodev_digest_update: digest failed\n");
+ return (0);
+ }
+ return (1);
+}
+
+
+static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+
+ int ret = 1;
+
+ if (!md || state->d_fd < 0) {
+ printf("cryptodev_digest_final: illegal input\n");
+ return(0);
+ }
+
+ if (! (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) ) {
+ /* if application doesn't support one buffer */
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = state->mac_len;
+ cryp.src = state->mac_data;
+ cryp.dst = NULL;
+ cryp.mac = (caddr_t)md;
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
+ printf("cryptodev_digest_final: digest failed\n");
+ return (0);
+ }
+
+ return 1;
+ }
+
+ memcpy(md, state->digest_res, ctx->digest->md_size);
+
+ return (ret);
+}
+
+
+static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
+{
+ int ret = 1;
+ struct dev_crypto_state *state = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+
+ if (state == NULL)
+ return 0;
+
+ if (state->d_fd < 0) {
+ printf("cryptodev_digest_cleanup: illegal input\n");
+ return (0);
+ }
+
+ if (state->mac_data) {
+ OPENSSL_free(state->mac_data);
+ state->mac_data = NULL;
+ state->mac_len = 0;
+ }
+
+ if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
+ printf("cryptodev_digest_cleanup: failed to close session\n");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+
+ return (ret);
+}
+
+static int cryptodev_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
+{
+ struct dev_crypto_state *fstate = from->md_data;
+ struct dev_crypto_state *dstate = to->md_data;
+ struct session_op *sess;
+ int digest;
+
+ if (dstate == NULL || fstate == NULL)
+ return 1;
+
+ memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
+
+ sess = &dstate->d_sess;
+
+ digest = digest_nid_to_cryptodev(to->digest->type);
+
+ sess->mackey = dstate->dummy_mac_key;
+ sess->mackeylen = digest_key_length(to->digest->type);
+ sess->mac = digest;
+
+ dstate->d_fd = get_dev_crypto();
+
+ if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) {
+ put_dev_crypto(dstate->d_fd);
+ dstate->d_fd = -1;
+ printf("cryptodev_digest_init: Open session failed\n");
+ return (0);
+ }
+
+ if (fstate->mac_len != 0) {
+ if (fstate->mac_data != NULL)
+ {
+ dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
+ memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
+ dstate->mac_len = fstate->mac_len;
+ }
+ }
+
+ return 1;
+}
+
+
+const EVP_MD cryptodev_sha1 = {
+ NID_sha1,
+ NID_undef,
+ SHA_DIGEST_LENGTH,
+ EVP_MD_FLAG_ONESHOT,
+ cryptodev_digest_init,
+ cryptodev_digest_update,
+ cryptodev_digest_final,
+ cryptodev_digest_copy,
+ cryptodev_digest_cleanup,
+ EVP_PKEY_NULL_method,
+ SHA_CBLOCK,
+ sizeof(struct dev_crypto_state),
+};
+
+const EVP_MD cryptodev_md5 = {
+ NID_md5,
+ NID_undef,
+ 16 /* MD5_DIGEST_LENGTH */,
+ EVP_MD_FLAG_ONESHOT,
+ cryptodev_digest_init,
+ cryptodev_digest_update,
+ cryptodev_digest_final,
+ cryptodev_digest_copy,
+ cryptodev_digest_cleanup,
+ EVP_PKEY_NULL_method,
+ 64 /* MD5_CBLOCK */,
+ sizeof(struct dev_crypto_state),
+};
+
+#endif /* USE_CRYPTODEV_DIGESTS */
+
+
+static int
+cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid)
+{
+ if (!digest)
+ return (cryptodev_usable_digests(nids));
+
+ switch (nid) {
+#ifdef USE_CRYPTODEV_DIGESTS
+ case NID_md5:
+ *digest = &cryptodev_md5;
+ break;
+ case NID_sha1:
+ *digest = &cryptodev_sha1;
+ break;
+ default:
+#endif /* USE_CRYPTODEV_DIGESTS */
+ *digest = NULL;
+ break;
+ }
+ return (*digest != NULL);
+}
+
+/*
+ * Convert a BIGNUM to the representation that /dev/crypto needs.
+ * Upon completion of use, the caller is responsible for freeing
+ * crp->crp_p.
+ */
+static int
+bn2crparam(const BIGNUM *a, struct crparam *crp)
+{
+ int i, j, k;
+ ssize_t bytes, bits;
+ u_char *b;
+
+ crp->crp_p = NULL;
+ crp->crp_nbits = 0;
+
+ bits = BN_num_bits(a);
+ bytes = (bits + 7) / 8;
+
+ b = malloc(bytes);
+ if (b == NULL)
+ return (1);
+ memset(b, 0, bytes);
+
+ crp->crp_p = (caddr_t) b;
+ crp->crp_nbits = bits;
+
+ for (i = 0, j = 0; i < a->top; i++) {
+ for (k = 0; k < BN_BITS2 / 8; k++) {
+ if ((j + k) >= bytes)
+ return (0);
+ b[j + k] = a->d[i] >> (k * 8);
+ }
+ j += BN_BITS2 / 8;
+ }
+ return (0);
+}
+
+/* Convert a /dev/crypto parameter to a BIGNUM */
+static int
+crparam2bn(struct crparam *crp, BIGNUM *a)
+{
+ u_int8_t *pd;
+ int i, bytes;
+
+ bytes = (crp->crp_nbits + 7) / 8;
+
+ if (bytes == 0)
+ return (-1);
+
+ if ((pd = (u_int8_t *) malloc(bytes)) == NULL)
+ return (-1);
+
+ for (i = 0; i < bytes; i++)
+ pd[i] = crp->crp_p[bytes - i - 1];
+
+ BN_bin2bn(pd, bytes, a);
+ free(pd);
+
+ return (0);
+}
+
+static void
+zapparams(struct crypt_kop *kop)
+{
+ int i;
+
+ for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) {
+ if (kop->crk_param[i].crp_p)
+ free(kop->crk_param[i].crp_p);
+ kop->crk_param[i].crp_p = NULL;
+ kop->crk_param[i].crp_nbits = 0;
+ }
+}
+
+static int
+cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen, BIGNUM *s)
+{
+ int fd, ret = -1;
+
+ if ((fd = get_asym_dev_crypto()) < 0)
+ return (ret);
+
+ if (r) {
+ kop->crk_param[kop->crk_iparams].crp_p = calloc(rlen, sizeof(char));
+ kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8;
+ kop->crk_oparams++;
+ }
+ if (s) {
+ kop->crk_param[kop->crk_iparams+1].crp_p = calloc(slen, sizeof(char));
+ kop->crk_param[kop->crk_iparams+1].crp_nbits = slen * 8;
+ kop->crk_oparams++;
+ }
+
+ if (ioctl(fd, CIOCKEY, kop) == 0) {
+ if (r)
+ crparam2bn(&kop->crk_param[kop->crk_iparams], r);
+ if (s)
+ crparam2bn(&kop->crk_param[kop->crk_iparams+1], s);
+ ret = 0;
+ }
+
+ return (ret);
+}
+
+static int
+cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+ struct crypt_kop kop;
+ int ret = 1;
+
+ /* Currently, we know we can do mod exp iff we can do any
+ * asymmetric operations at all.
+ */
+ if (cryptodev_asymfeat == 0) {
+ ret = BN_mod_exp(r, a, p, m, ctx);
+ return (ret);
+ }
+
+ memset(&kop, 0, sizeof kop);
+ kop.crk_op = CRK_MOD_EXP;
+
+ /* inputs: a^p % m */
+ if (bn2crparam(a, &kop.crk_param[0]))
+ goto err;
+ if (bn2crparam(p, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(m, &kop.crk_param[2]))
+ goto err;
+ kop.crk_iparams = 3;
+
+ if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) {
+ const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+ printf("OCF asym process failed, Running in software\n");
+ ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
+
+ } else if (ECANCELED == kop.crk_status) {
+ const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+ printf("OCF hardware operation cancelled. Running in Software\n");
+ ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
+ }
+ /* else cryptodev operation worked ok ==> ret = 1*/
+
+err:
+ zapparams(&kop);
+ return (ret);
+}
+
+static int
+cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+{
+ int r;
+ ctx = BN_CTX_new();
+ r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL);
+ BN_CTX_free(ctx);
+ return (r);
+}
+
+static int
+cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+{
+ struct crypt_kop kop;
+ int ret = 1;
+
+ if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
+ /* XXX 0 means failure?? */
+ return (0);
+ }
+
+ memset(&kop, 0, sizeof kop);
+ kop.crk_op = CRK_MOD_EXP_CRT;
+ /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
+ if (bn2crparam(rsa->p, &kop.crk_param[0]))
+ goto err;
+ if (bn2crparam(rsa->q, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(I, &kop.crk_param[2]))
+ goto err;
+ if (bn2crparam(rsa->dmp1, &kop.crk_param[3]))
+ goto err;
+ if (bn2crparam(rsa->dmq1, &kop.crk_param[4]))
+ goto err;
+ if (bn2crparam(rsa->iqmp, &kop.crk_param[5]))
+ goto err;
+ kop.crk_iparams = 6;
+
+ if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL)) {
+ const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+ printf("OCF asym process failed, running in Software\n");
+ ret = (*meth->rsa_mod_exp)(r0, I, rsa, ctx);
+
+ } else if (ECANCELED == kop.crk_status) {
+ const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+ printf("OCF hardware operation cancelled. Running in Software\n");
+ ret = (*meth->rsa_mod_exp)(r0, I, rsa, ctx);
+ }
+ /* else cryptodev operation worked ok ==> ret = 1*/
+
+err:
+ zapparams(&kop);
+ return (ret);
+}
+
+static RSA_METHOD cryptodev_rsa = {
+ "cryptodev RSA method",
+ NULL, /* rsa_pub_enc */
+ NULL, /* rsa_pub_dec */
+ NULL, /* rsa_priv_enc */
+ NULL, /* rsa_priv_dec */
+ NULL,
+ NULL,
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+ NULL, /* app_data */
+ NULL, /* rsa_sign */
+ NULL /* rsa_verify */
+};
+
+static int
+cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+{
+ return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
+}
+
+static int
+cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
+ BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, BIGNUM *p,
+ BN_CTX *ctx, BN_MONT_CTX *mont)
+{
+ BIGNUM t2;
+ int ret = 0;
+
+ BN_init(&t2);
+
+ /* v = ( g^u1 * y^u2 mod p ) mod q */
+ /* let t1 = g ^ u1 mod p */
+ ret = 0;
+
+ if (!dsa->meth->bn_mod_exp(dsa,t1,dsa->g,u1,dsa->p,ctx,mont))
+ goto err;
+
+ /* let t2 = y ^ u2 mod p */
+ if (!dsa->meth->bn_mod_exp(dsa,&t2,dsa->pub_key,u2,dsa->p,ctx,mont))
+ goto err;
+ /* let u1 = t1 * t2 mod p */
+ if (!BN_mod_mul(u1,t1,&t2,dsa->p,ctx))
+ goto err;
+
+ BN_copy(t1,u1);
+
+ ret = 1;
+err:
+ BN_free(&t2);
+ return(ret);
+}
+
+static DSA_SIG *
+cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+{
+ struct crypt_kop kop;
+ BIGNUM *r = NULL, *s = NULL;
+ DSA_SIG *dsaret = NULL;
+
+ if ((r = BN_new()) == NULL)
+ goto err;
+ if ((s = BN_new()) == NULL) {
+ BN_free(r);
+ goto err;
+ }
+
+ memset(&kop, 0, sizeof kop);
+ kop.crk_op = CRK_DSA_SIGN;
+
+ /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
+ kop.crk_param[0].crp_p = (caddr_t)dgst;
+ kop.crk_param[0].crp_nbits = dlen * 8;
+ if (bn2crparam(dsa->p, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(dsa->q, &kop.crk_param[2]))
+ goto err;
+ if (bn2crparam(dsa->g, &kop.crk_param[3]))
+ goto err;
+ if (bn2crparam(dsa->priv_key, &kop.crk_param[4]))
+ goto err;
+ kop.crk_iparams = 5;
+
+ if (cryptodev_asym(&kop, BN_num_bytes(dsa->q), r,
+ BN_num_bytes(dsa->q), s) == 0) {
+ dsaret = DSA_SIG_new();
+ dsaret->r = r;
+ dsaret->s = s;
+ } else {
+ const DSA_METHOD *meth = DSA_OpenSSL();
+ BN_free(r);
+ BN_free(s);
+ dsaret = (meth->dsa_do_sign)(dgst, dlen, dsa);
+ }
+err:
+ kop.crk_param[0].crp_p = NULL;
+ zapparams(&kop);
+ return (dsaret);
+}
+
+static int
+cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
+ DSA_SIG *sig, DSA *dsa)
+{
+ struct crypt_kop kop;
+ int dsaret = 1;
+
+ memset(&kop, 0, sizeof kop);
+ kop.crk_op = CRK_DSA_VERIFY;
+
+ /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
+ kop.crk_param[0].crp_p = (caddr_t)dgst;
+ kop.crk_param[0].crp_nbits = dlen * 8;
+ if (bn2crparam(dsa->p, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(dsa->q, &kop.crk_param[2]))
+ goto err;
+ if (bn2crparam(dsa->g, &kop.crk_param[3]))
+ goto err;
+ if (bn2crparam(dsa->pub_key, &kop.crk_param[4]))
+ goto err;
+ if (bn2crparam(sig->r, &kop.crk_param[5]))
+ goto err;
+ if (bn2crparam(sig->s, &kop.crk_param[6]))
+ goto err;
+ kop.crk_iparams = 7;
+
+ if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) {
+/*OCF success value is 0, if not zero, change dsaret to fail*/
+ if(0 != kop.crk_status) dsaret = 0;
+ } else {
+ const DSA_METHOD *meth = DSA_OpenSSL();
+
+ dsaret = (meth->dsa_do_verify)(dgst, dlen, sig, dsa);
+ }
+err:
+ kop.crk_param[0].crp_p = NULL;
+ zapparams(&kop);
+ return (dsaret);
+}
+
+static DSA_METHOD cryptodev_dsa = {
+ "cryptodev DSA method",
+ NULL,
+ NULL, /* dsa_sign_setup */
+ NULL,
+ NULL, /* dsa_mod_exp */
+ NULL,
+ NULL, /* init */
+ NULL, /* finish */
+ 0, /* flags */
+ NULL /* app_data */
+};
+
+static int
+cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx)
+{
+ return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
+}
+
+static int
+cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+{
+ struct crypt_kop kop;
+ int dhret = 1;
+ int fd, keylen;
+
+ if ((fd = get_asym_dev_crypto()) < 0) {
+ const DH_METHOD *meth = DH_OpenSSL();
+
+ return ((meth->compute_key)(key, pub_key, dh));
+ }
+
+ keylen = BN_num_bits(dh->p);
+
+ memset(&kop, 0, sizeof kop);
+ kop.crk_op = CRK_DH_COMPUTE_KEY;
+
+ /* inputs: dh->priv_key pub_key dh->p key */
+ if (bn2crparam(dh->priv_key, &kop.crk_param[0]))
+ goto err;
+ if (bn2crparam(pub_key, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(dh->p, &kop.crk_param[2]))
+ goto err;
+ kop.crk_iparams = 3;
+
+ kop.crk_param[3].crp_p = (caddr_t) key;
+ kop.crk_param[3].crp_nbits = keylen * 8;
+ kop.crk_oparams = 1;
+
+ if (ioctl(fd, CIOCKEY, &kop) == -1) {
+ const DH_METHOD *meth = DH_OpenSSL();
+
+ dhret = (meth->compute_key)(key, pub_key, dh);
+ }
+err:
+ kop.crk_param[3].crp_p = NULL;
+ zapparams(&kop);
+ return (dhret);
+}
+
+static DH_METHOD cryptodev_dh = {
+ "cryptodev DH method",
+ NULL, /* cryptodev_dh_generate_key */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0, /* flags */
+ NULL /* app_data */
+};
+
+/*
+ * ctrl right now is just a wrapper that doesn't do much
+ * but I expect we'll want some options soon.
+ */
+static int
+cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
+{
+#ifdef HAVE_SYSLOG_R
+ struct syslog_data sd = SYSLOG_DATA_INIT;
+#endif
+
+ switch (cmd) {
+ default:
+#ifdef HAVE_SYSLOG_R
+ syslog_r(LOG_ERR, &sd,
+ "cryptodev_ctrl: unknown command %d", cmd);
+#else
+ syslog(LOG_ERR, "cryptodev_ctrl: unknown command %d", cmd);
+#endif
+ break;
+ }
+ return (1);
+}
+
+void
+ENGINE_load_cryptodev(void)
+{
+ ENGINE *engine = ENGINE_new();
+ int fd;
+
+ if (engine == NULL)
+ return;
+ if ((fd = get_dev_crypto()) < 0) {
+ ENGINE_free(engine);
+ return;
+ }
+
+ /*
+ * find out what asymmetric crypto algorithms we support
+ */
+ if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) {
+ put_dev_crypto(fd);
+ ENGINE_free(engine);
+ return;
+ }
+ put_dev_crypto(fd);
+
+ if (!ENGINE_set_id(engine, "cryptodev") ||
+ !ENGINE_set_name(engine, "BSD cryptodev engine") ||
+ !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) ||
+ !ENGINE_set_digests(engine, cryptodev_engine_digests) ||
+ !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) ||
+ !ENGINE_set_cmd_defns(engine, cryptodev_defns)) {
+ ENGINE_free(engine);
+ return;
+ }
+
+ if (ENGINE_set_RSA(engine, &cryptodev_rsa)) {
+ const RSA_METHOD *rsa_meth = RSA_PKCS1_SSLeay();
+
+ cryptodev_rsa.bn_mod_exp = rsa_meth->bn_mod_exp;
+ cryptodev_rsa.rsa_mod_exp = rsa_meth->rsa_mod_exp;
+ cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc;
+ cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec;
+ cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_enc;
+ cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec;
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ cryptodev_rsa.bn_mod_exp = cryptodev_bn_mod_exp;
+ if (cryptodev_asymfeat & CRF_MOD_EXP_CRT)
+ cryptodev_rsa.rsa_mod_exp =
+ cryptodev_rsa_mod_exp;
+ else
+ cryptodev_rsa.rsa_mod_exp =
+ cryptodev_rsa_nocrt_mod_exp;
+ }
+ }
+
+ if (ENGINE_set_DSA(engine, &cryptodev_dsa)) {
+ const DSA_METHOD *meth = DSA_OpenSSL();
+
+ memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD));
+ if (cryptodev_asymfeat & CRF_DSA_SIGN)
+ cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign;
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ cryptodev_dsa.bn_mod_exp = cryptodev_dsa_bn_mod_exp;
+ cryptodev_dsa.dsa_mod_exp = cryptodev_dsa_dsa_mod_exp;
+ }
+ if (cryptodev_asymfeat & CRF_DSA_VERIFY)
+ cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify;
+ }
+
+ if (ENGINE_set_DH(engine, &cryptodev_dh)){
+ const DH_METHOD *dh_meth = DH_OpenSSL();
+
+ cryptodev_dh.generate_key = dh_meth->generate_key;
+ cryptodev_dh.compute_key = dh_meth->compute_key;
+ cryptodev_dh.bn_mod_exp = dh_meth->bn_mod_exp;
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ cryptodev_dh.bn_mod_exp = cryptodev_mod_exp_dh;
+ if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY)
+ cryptodev_dh.compute_key =
+ cryptodev_dh_compute_key;
+ }
+ }
+
+ ENGINE_add(engine);
+ ENGINE_free(engine);
+ ERR_clear_error();
+}
+
+#endif /* HAVE_CRYPTODEV */
diff --git a/crypto/engine/eng_ctrl.c b/crypto/engine/eng_ctrl.c
new file mode 100644
index 0000000..5ce25d9
--- /dev/null
+++ b/crypto/engine/eng_ctrl.c
@@ -0,0 +1,389 @@
+/* crypto/engine/eng_ctrl.c */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* When querying a ENGINE-specific control command's 'description', this string
+ * is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL. */
+static const char *int_no_description = "";
+
+/* These internal functions handle 'CMD'-related control commands when the
+ * ENGINE in question has asked us to take care of it (ie. the ENGINE did not
+ * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag. */
+
+static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn)
+ {
+ if((defn->cmd_num == 0) || (defn->cmd_name == NULL))
+ return 1;
+ return 0;
+ }
+
+static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s)
+ {
+ int idx = 0;
+ while(!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0))
+ {
+ idx++;
+ defn++;
+ }
+ if(int_ctrl_cmd_is_null(defn))
+ /* The given name wasn't found */
+ return -1;
+ return idx;
+ }
+
+static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num)
+ {
+ int idx = 0;
+ /* NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So
+ * our searches don't need to take any longer than necessary. */
+ while(!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num))
+ {
+ idx++;
+ defn++;
+ }
+ if(defn->cmd_num == num)
+ return idx;
+ /* The given cmd_num wasn't found */
+ return -1;
+ }
+
+static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
+ void (*f)(void))
+ {
+ int idx;
+ char *s = (char *)p;
+ /* Take care of the easy one first (eg. it requires no searches) */
+ if(cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE)
+ {
+ if((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns))
+ return 0;
+ return e->cmd_defns->cmd_num;
+ }
+ /* One or two commands require that "p" be a valid string buffer */
+ if((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) ||
+ (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) ||
+ (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD))
+ {
+ if(s == NULL)
+ {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ }
+ /* Now handle cmd_name -> cmd_num conversion */
+ if(cmd == ENGINE_CTRL_GET_CMD_FROM_NAME)
+ {
+ if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_name(
+ e->cmd_defns, s)) < 0))
+ {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
+ ENGINE_R_INVALID_CMD_NAME);
+ return -1;
+ }
+ return e->cmd_defns[idx].cmd_num;
+ }
+ /* For the rest of the commands, the 'long' argument must specify a
+ * valie command number - so we need to conduct a search. */
+ if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_num(e->cmd_defns,
+ (unsigned int)i)) < 0))
+ {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
+ ENGINE_R_INVALID_CMD_NUMBER);
+ return -1;
+ }
+ /* Now the logic splits depending on command type */
+ switch(cmd)
+ {
+ case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
+ idx++;
+ if(int_ctrl_cmd_is_null(e->cmd_defns + idx))
+ /* end-of-list */
+ return 0;
+ else
+ return e->cmd_defns[idx].cmd_num;
+ case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
+ return strlen(e->cmd_defns[idx].cmd_name);
+ case ENGINE_CTRL_GET_NAME_FROM_CMD:
+ return BIO_snprintf(s,strlen(e->cmd_defns[idx].cmd_name) + 1,
+ "%s", e->cmd_defns[idx].cmd_name);
+ case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
+ if(e->cmd_defns[idx].cmd_desc)
+ return strlen(e->cmd_defns[idx].cmd_desc);
+ return strlen(int_no_description);
+ case ENGINE_CTRL_GET_DESC_FROM_CMD:
+ if(e->cmd_defns[idx].cmd_desc)
+ return BIO_snprintf(s,
+ strlen(e->cmd_defns[idx].cmd_desc) + 1,
+ "%s", e->cmd_defns[idx].cmd_desc);
+ return BIO_snprintf(s, strlen(int_no_description) + 1,"%s",
+ int_no_description);
+ case ENGINE_CTRL_GET_CMD_FLAGS:
+ return e->cmd_defns[idx].cmd_flags;
+ }
+ /* Shouldn't really be here ... */
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER,ENGINE_R_INTERNAL_LIST_ERROR);
+ return -1;
+ }
+
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
+ {
+ int ctrl_exists, ref_exists;
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ ref_exists = ((e->struct_ref > 0) ? 1 : 0);
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
+ if(!ref_exists)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_REFERENCE);
+ return 0;
+ }
+ /* Intercept any "root-level" commands before trying to hand them on to
+ * ctrl() handlers. */
+ switch(cmd)
+ {
+ case ENGINE_CTRL_HAS_CTRL_FUNCTION:
+ return ctrl_exists;
+ case ENGINE_CTRL_GET_FIRST_CMD_TYPE:
+ case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
+ case ENGINE_CTRL_GET_CMD_FROM_NAME:
+ case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
+ case ENGINE_CTRL_GET_NAME_FROM_CMD:
+ case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
+ case ENGINE_CTRL_GET_DESC_FROM_CMD:
+ case ENGINE_CTRL_GET_CMD_FLAGS:
+ if(ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL))
+ return int_ctrl_helper(e,cmd,i,p,f);
+ if(!ctrl_exists)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION);
+ /* For these cmd-related functions, failure is indicated
+ * by a -1 return value (because 0 is used as a valid
+ * return in some places). */
+ return -1;
+ }
+ default:
+ break;
+ }
+ /* Anything else requires a ctrl() handler to exist. */
+ if(!ctrl_exists)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL,ENGINE_R_NO_CONTROL_FUNCTION);
+ return 0;
+ }
+ return e->ctrl(e, cmd, i, p, f);
+ }
+
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd)
+ {
+ int flags;
+ if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,
+ ENGINE_R_INVALID_CMD_NUMBER);
+ return 0;
+ }
+ if(!(flags & ENGINE_CMD_FLAG_NO_INPUT) &&
+ !(flags & ENGINE_CMD_FLAG_NUMERIC) &&
+ !(flags & ENGINE_CMD_FLAG_STRING))
+ return 0;
+ return 1;
+ }
+
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+ long i, void *p, void (*f)(void), int cmd_optional)
+ {
+ int num;
+
+ if((e == NULL) || (cmd_name == NULL))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,
+ ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) <= 0))
+ {
+ /* If the command didn't *have* to be supported, we fake
+ * success. This allows certain settings to be specified for
+ * multiple ENGINEs and only require a change of ENGINE id
+ * (without having to selectively apply settings). Eg. changing
+ * from a hardware device back to the regular software ENGINE
+ * without editing the config file, etc. */
+ if(cmd_optional)
+ {
+ ERR_clear_error();
+ return 1;
+ }
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD,
+ ENGINE_R_INVALID_CMD_NAME);
+ return 0;
+ }
+ /* Force the result of the control command to 0 or 1, for the reasons
+ * mentioned before. */
+ if (ENGINE_ctrl(e, num, i, p, f) > 0)
+ return 1;
+ return 0;
+ }
+
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional)
+ {
+ int num, flags;
+ long l;
+ char *ptr;
+ if((e == NULL) || (cmd_name == NULL))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,
+ ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) <= 0))
+ {
+ /* If the command didn't *have* to be supported, we fake
+ * success. This allows certain settings to be specified for
+ * multiple ENGINEs and only require a change of ENGINE id
+ * (without having to selectively apply settings). Eg. changing
+ * from a hardware device back to the regular software ENGINE
+ * without editing the config file, etc. */
+ if(cmd_optional)
+ {
+ ERR_clear_error();
+ return 1;
+ }
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INVALID_CMD_NAME);
+ return 0;
+ }
+ if(!ENGINE_cmd_is_executable(e, num))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_CMD_NOT_EXECUTABLE);
+ return 0;
+ }
+ if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL)) < 0)
+ {
+ /* Shouldn't happen, given that ENGINE_cmd_is_executable()
+ * returned success. */
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ /* If the command takes no input, there must be no input. And vice
+ * versa. */
+ if(flags & ENGINE_CMD_FLAG_NO_INPUT)
+ {
+ if(arg != NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_COMMAND_TAKES_NO_INPUT);
+ return 0;
+ }
+ /* We deliberately force the result of ENGINE_ctrl() to 0 or 1
+ * rather than returning it as "return data". This is to ensure
+ * usage of these commands is consistent across applications and
+ * that certain applications don't understand it one way, and
+ * others another. */
+ if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0)
+ return 1;
+ return 0;
+ }
+ /* So, we require input */
+ if(arg == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_COMMAND_TAKES_INPUT);
+ return 0;
+ }
+ /* If it takes string input, that's easy */
+ if(flags & ENGINE_CMD_FLAG_STRING)
+ {
+ /* Same explanation as above */
+ if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0)
+ return 1;
+ return 0;
+ }
+ /* If it doesn't take numeric either, then it is unsupported for use in
+ * a config-setting situation, which is what this function is for. This
+ * should never happen though, because ENGINE_cmd_is_executable() was
+ * used. */
+ if(!(flags & ENGINE_CMD_FLAG_NUMERIC))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ l = strtol(arg, &ptr, 10);
+ if((arg == ptr) || (*ptr != '\0'))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
+ return 0;
+ }
+ /* Force the result of the control command to 0 or 1, for the reasons
+ * mentioned before. */
+ if(ENGINE_ctrl(e, num, l, NULL, NULL) > 0)
+ return 1;
+ return 0;
+ }
diff --git a/crypto/engine/eng_dyn.c b/crypto/engine/eng_dyn.c
new file mode 100644
index 0000000..807da7a
--- /dev/null
+++ b/crypto/engine/eng_dyn.c
@@ -0,0 +1,548 @@
+/* crypto/engine/eng_dyn.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+#include "eng_int.h"
+#include <openssl/dso.h>
+
+/* Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE loader
+ * should implement the hook-up functions with the following prototypes. */
+
+/* Our ENGINE handlers */
+static int dynamic_init(ENGINE *e);
+static int dynamic_finish(ENGINE *e);
+static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
+/* Predeclare our context type */
+typedef struct st_dynamic_data_ctx dynamic_data_ctx;
+/* The implementation for the important control command */
+static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx);
+
+#define DYNAMIC_CMD_SO_PATH ENGINE_CMD_BASE
+#define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1)
+#define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2)
+#define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3)
+#define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4)
+#define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5)
+#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6)
+
+/* The constants used when creating the ENGINE */
+static const char *engine_dynamic_id = "dynamic";
+static const char *engine_dynamic_name = "Dynamic engine loading support";
+static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = {
+ {DYNAMIC_CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the new ENGINE shared library",
+ ENGINE_CMD_FLAG_STRING},
+ {DYNAMIC_CMD_NO_VCHECK,
+ "NO_VCHECK",
+ "Specifies to continue even if version checking fails (boolean)",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {DYNAMIC_CMD_ID,
+ "ID",
+ "Specifies an ENGINE id name for loading",
+ ENGINE_CMD_FLAG_STRING},
+ {DYNAMIC_CMD_LIST_ADD,
+ "LIST_ADD",
+ "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {DYNAMIC_CMD_DIR_LOAD,
+ "DIR_LOAD",
+ "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {DYNAMIC_CMD_DIR_ADD,
+ "DIR_ADD",
+ "Adds a directory from which ENGINEs can be loaded",
+ ENGINE_CMD_FLAG_STRING},
+ {DYNAMIC_CMD_LOAD,
+ "LOAD",
+ "Load up the ENGINE specified by other settings",
+ ENGINE_CMD_FLAG_NO_INPUT},
+ {0, NULL, NULL, 0}
+ };
+static const ENGINE_CMD_DEFN dynamic_cmd_defns_empty[] = {
+ {0, NULL, NULL, 0}
+ };
+
+/* Loading code stores state inside the ENGINE structure via the "ex_data"
+ * element. We load all our state into a single structure and use that as a
+ * single context in the "ex_data" stack. */
+struct st_dynamic_data_ctx
+ {
+ /* The DSO object we load that supplies the ENGINE code */
+ DSO *dynamic_dso;
+ /* The function pointer to the version checking shared library function */
+ dynamic_v_check_fn v_check;
+ /* The function pointer to the engine-binding shared library function */
+ dynamic_bind_engine bind_engine;
+ /* The default name/path for loading the shared library */
+ const char *DYNAMIC_LIBNAME;
+ /* Whether to continue loading on a version check failure */
+ int no_vcheck;
+ /* If non-NULL, stipulates the 'id' of the ENGINE to be loaded */
+ const char *engine_id;
+ /* If non-zero, a successfully loaded ENGINE should be added to the internal
+ * ENGINE list. If 2, the add must succeed or the entire load should fail. */
+ int list_add_value;
+ /* The symbol name for the version checking function */
+ const char *DYNAMIC_F1;
+ /* The symbol name for the "initialise ENGINE structure" function */
+ const char *DYNAMIC_F2;
+ /* Whether to never use 'dirs', use 'dirs' as a fallback, or only use
+ * 'dirs' for loading. Default is to use 'dirs' as a fallback. */
+ int dir_load;
+ /* A stack of directories from which ENGINEs could be loaded */
+ STACK_OF(OPENSSL_STRING) *dirs;
+ };
+
+/* This is the "ex_data" index we obtain and reserve for use with our context
+ * structure. */
+static int dynamic_ex_data_idx = -1;
+
+static void int_free_str(char *s) { OPENSSL_free(s); }
+/* Because our ex_data element may or may not get allocated depending on whether
+ * a "first-use" occurs before the ENGINE is freed, we have a memory leak
+ * problem to solve. We can't declare a "new" handler for the ex_data as we
+ * don't want a dynamic_data_ctx in *all* ENGINE structures of all types (this
+ * is a bug in the design of CRYPTO_EX_DATA). As such, we just declare a "free"
+ * handler and that will get called if an ENGINE is being destroyed and there
+ * was an ex_data element corresponding to our context type. */
+static void dynamic_data_ctx_free_func(void *parent, void *ptr,
+ CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
+ {
+ if(ptr)
+ {
+ dynamic_data_ctx *ctx = (dynamic_data_ctx *)ptr;
+ if(ctx->dynamic_dso)
+ DSO_free(ctx->dynamic_dso);
+ if(ctx->DYNAMIC_LIBNAME)
+ OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME);
+ if(ctx->engine_id)
+ OPENSSL_free((void*)ctx->engine_id);
+ if(ctx->dirs)
+ sk_OPENSSL_STRING_pop_free(ctx->dirs, int_free_str);
+ OPENSSL_free(ctx);
+ }
+ }
+
+/* Construct the per-ENGINE context. We create it blindly and then use a lock to
+ * check for a race - if so, all but one of the threads "racing" will have
+ * wasted their time. The alternative involves creating everything inside the
+ * lock which is far worse. */
+static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx)
+ {
+ dynamic_data_ctx *c;
+ c = OPENSSL_malloc(sizeof(dynamic_data_ctx));
+ if(!c)
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ memset(c, 0, sizeof(dynamic_data_ctx));
+ c->dynamic_dso = NULL;
+ c->v_check = NULL;
+ c->bind_engine = NULL;
+ c->DYNAMIC_LIBNAME = NULL;
+ c->no_vcheck = 0;
+ c->engine_id = NULL;
+ c->list_add_value = 0;
+ c->DYNAMIC_F1 = "v_check";
+ c->DYNAMIC_F2 = "bind_engine";
+ c->dir_load = 1;
+ c->dirs = sk_OPENSSL_STRING_new_null();
+ if(!c->dirs)
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX,ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(c);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e,
+ dynamic_ex_data_idx)) == NULL)
+ {
+ /* Good, we're the first */
+ ENGINE_set_ex_data(e, dynamic_ex_data_idx, c);
+ *ctx = c;
+ c = NULL;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ /* If we lost the race to set the context, c is non-NULL and *ctx is the
+ * context of the thread that won. */
+ if(c)
+ OPENSSL_free(c);
+ return 1;
+ }
+
+/* This function retrieves the context structure from an ENGINE's "ex_data", or
+ * if it doesn't exist yet, sets it up. */
+static dynamic_data_ctx *dynamic_get_data_ctx(ENGINE *e)
+ {
+ dynamic_data_ctx *ctx;
+ if(dynamic_ex_data_idx < 0)
+ {
+ /* Create and register the ENGINE ex_data, and associate our
+ * "free" function with it to ensure any allocated contexts get
+ * freed when an ENGINE goes underground. */
+ int new_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL,
+ dynamic_data_ctx_free_func);
+ if(new_idx == -1)
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_GET_DATA_CTX,ENGINE_R_NO_INDEX);
+ return NULL;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ /* Avoid a race by checking again inside this lock */
+ if(dynamic_ex_data_idx < 0)
+ {
+ /* Good, someone didn't beat us to it */
+ dynamic_ex_data_idx = new_idx;
+ new_idx = -1;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ /* In theory we could "give back" the index here if
+ * (new_idx>-1), but it's not possible and wouldn't gain us much
+ * if it were. */
+ }
+ ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx);
+ /* Check if the context needs to be created */
+ if((ctx == NULL) && !dynamic_set_data_ctx(e, &ctx))
+ /* "set_data" will set errors if necessary */
+ return NULL;
+ return ctx;
+ }
+
+static ENGINE *engine_dynamic(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!ENGINE_set_id(ret, engine_dynamic_id) ||
+ !ENGINE_set_name(ret, engine_dynamic_name) ||
+ !ENGINE_set_init_function(ret, dynamic_init) ||
+ !ENGINE_set_finish_function(ret, dynamic_finish) ||
+ !ENGINE_set_ctrl_function(ret, dynamic_ctrl) ||
+ !ENGINE_set_flags(ret, ENGINE_FLAGS_BY_ID_COPY) ||
+ !ENGINE_set_cmd_defns(ret, dynamic_cmd_defns))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void ENGINE_load_dynamic(void)
+ {
+ ENGINE *toadd = engine_dynamic();
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ /* If the "add" worked, it gets a structural reference. So either way,
+ * we release our just-created reference. */
+ ENGINE_free(toadd);
+ /* If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps). */
+ ERR_clear_error();
+ }
+
+static int dynamic_init(ENGINE *e)
+ {
+ /* We always return failure - the "dyanamic" engine itself can't be used
+ * for anything. */
+ return 0;
+ }
+
+static int dynamic_finish(ENGINE *e)
+ {
+ /* This should never be called on account of "dynamic_init" always
+ * failing. */
+ return 0;
+ }
+
+static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
+ {
+ dynamic_data_ctx *ctx = dynamic_get_data_ctx(e);
+ int initialised;
+
+ if(!ctx)
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,ENGINE_R_NOT_LOADED);
+ return 0;
+ }
+ initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1);
+ /* All our control commands require the ENGINE to be uninitialised */
+ if(initialised)
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,
+ ENGINE_R_ALREADY_LOADED);
+ return 0;
+ }
+ switch(cmd)
+ {
+ case DYNAMIC_CMD_SO_PATH:
+ /* a NULL 'p' or a string of zero-length is the same thing */
+ if(p && (strlen((const char *)p) < 1))
+ p = NULL;
+ if(ctx->DYNAMIC_LIBNAME)
+ OPENSSL_free((void*)ctx->DYNAMIC_LIBNAME);
+ if(p)
+ ctx->DYNAMIC_LIBNAME = BUF_strdup(p);
+ else
+ ctx->DYNAMIC_LIBNAME = NULL;
+ return (ctx->DYNAMIC_LIBNAME ? 1 : 0);
+ case DYNAMIC_CMD_NO_VCHECK:
+ ctx->no_vcheck = ((i == 0) ? 0 : 1);
+ return 1;
+ case DYNAMIC_CMD_ID:
+ /* a NULL 'p' or a string of zero-length is the same thing */
+ if(p && (strlen((const char *)p) < 1))
+ p = NULL;
+ if(ctx->engine_id)
+ OPENSSL_free((void*)ctx->engine_id);
+ if(p)
+ ctx->engine_id = BUF_strdup(p);
+ else
+ ctx->engine_id = NULL;
+ return (ctx->engine_id ? 1 : 0);
+ case DYNAMIC_CMD_LIST_ADD:
+ if((i < 0) || (i > 2))
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,
+ ENGINE_R_INVALID_ARGUMENT);
+ return 0;
+ }
+ ctx->list_add_value = (int)i;
+ return 1;
+ case DYNAMIC_CMD_LOAD:
+ return dynamic_load(e, ctx);
+ case DYNAMIC_CMD_DIR_LOAD:
+ if((i < 0) || (i > 2))
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,
+ ENGINE_R_INVALID_ARGUMENT);
+ return 0;
+ }
+ ctx->dir_load = (int)i;
+ return 1;
+ case DYNAMIC_CMD_DIR_ADD:
+ /* a NULL 'p' or a string of zero-length is the same thing */
+ if(!p || (strlen((const char *)p) < 1))
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,
+ ENGINE_R_INVALID_ARGUMENT);
+ return 0;
+ }
+ {
+ char *tmp_str = BUF_strdup(p);
+ if(!tmp_str)
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ sk_OPENSSL_STRING_insert(ctx->dirs, tmp_str, -1);
+ }
+ return 1;
+ default:
+ break;
+ }
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+static int int_load(dynamic_data_ctx *ctx)
+ {
+ int num, loop;
+ /* Unless told not to, try a direct load */
+ if((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso,
+ ctx->DYNAMIC_LIBNAME, NULL, 0)) != NULL)
+ return 1;
+ /* If we're not allowed to use 'dirs' or we have none, fail */
+ if(!ctx->dir_load || (num = sk_OPENSSL_STRING_num(ctx->dirs)) < 1)
+ return 0;
+ for(loop = 0; loop < num; loop++)
+ {
+ const char *s = sk_OPENSSL_STRING_value(ctx->dirs, loop);
+ char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s);
+ if(!merge)
+ return 0;
+ if(DSO_load(ctx->dynamic_dso, merge, NULL, 0))
+ {
+ /* Found what we're looking for */
+ OPENSSL_free(merge);
+ return 1;
+ }
+ OPENSSL_free(merge);
+ }
+ return 0;
+ }
+
+static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
+ {
+ ENGINE cpy;
+ dynamic_fns fns;
+
+ if(!ctx->dynamic_dso)
+ ctx->dynamic_dso = DSO_new();
+ if(!ctx->DYNAMIC_LIBNAME)
+ {
+ if(!ctx->engine_id)
+ return 0;
+ ctx->DYNAMIC_LIBNAME =
+ DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id);
+ }
+ if(!int_load(ctx))
+ {
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
+ ENGINE_R_DSO_NOT_FOUND);
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ return 0;
+ }
+ /* We have to find a bind function otherwise it'll always end badly */
+ if(!(ctx->bind_engine = (dynamic_bind_engine)DSO_bind_func(
+ ctx->dynamic_dso, ctx->DYNAMIC_F2)))
+ {
+ ctx->bind_engine = NULL;
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
+ ENGINE_R_DSO_FAILURE);
+ return 0;
+ }
+ /* Do we perform version checking? */
+ if(!ctx->no_vcheck)
+ {
+ unsigned long vcheck_res = 0;
+ /* Now we try to find a version checking function and decide how
+ * to cope with failure if/when it fails. */
+ ctx->v_check = (dynamic_v_check_fn)DSO_bind_func(
+ ctx->dynamic_dso, ctx->DYNAMIC_F1);
+ if(ctx->v_check)
+ vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION);
+ /* We fail if the version checker veto'd the load *or* if it is
+ * deferring to us (by returning its version) and we think it is
+ * too old. */
+ if(vcheck_res < OSSL_DYNAMIC_OLDEST)
+ {
+ /* Fail */
+ ctx->bind_engine = NULL;
+ ctx->v_check = NULL;
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
+ ENGINE_R_VERSION_INCOMPATIBILITY);
+ return 0;
+ }
+ }
+ /* First binary copy the ENGINE structure so that we can roll back if
+ * the hand-over fails */
+ memcpy(&cpy, e, sizeof(ENGINE));
+ /* Provide the ERR, "ex_data", memory, and locking callbacks so the
+ * loaded library uses our state rather than its own. FIXME: As noted in
+ * engine.h, much of this would be simplified if each area of code
+ * provided its own "summary" structure of all related callbacks. It
+ * would also increase opaqueness. */
+ fns.static_state = ENGINE_get_static_state();
+ fns.err_fns = ERR_get_implementation();
+ fns.ex_data_fns = CRYPTO_get_ex_data_implementation();
+ CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb,
+ &fns.mem_fns.realloc_cb,
+ &fns.mem_fns.free_cb);
+ fns.lock_fns.lock_locking_cb = CRYPTO_get_locking_callback();
+ fns.lock_fns.lock_add_lock_cb = CRYPTO_get_add_lock_callback();
+ fns.lock_fns.dynlock_create_cb = CRYPTO_get_dynlock_create_callback();
+ fns.lock_fns.dynlock_lock_cb = CRYPTO_get_dynlock_lock_callback();
+ fns.lock_fns.dynlock_destroy_cb = CRYPTO_get_dynlock_destroy_callback();
+ /* Now that we've loaded the dynamic engine, make sure no "dynamic"
+ * ENGINE elements will show through. */
+ engine_set_all_null(e);
+
+ /* Try to bind the ENGINE onto our own ENGINE structure */
+ if(!ctx->bind_engine(e, ctx->engine_id, &fns))
+ {
+ ctx->bind_engine = NULL;
+ ctx->v_check = NULL;
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,ENGINE_R_INIT_FAILED);
+ /* Copy the original ENGINE structure back */
+ memcpy(e, &cpy, sizeof(ENGINE));
+ return 0;
+ }
+ /* Do we try to add this ENGINE to the internal list too? */
+ if(ctx->list_add_value > 0)
+ {
+ if(!ENGINE_add(e))
+ {
+ /* Do we tolerate this or fail? */
+ if(ctx->list_add_value > 1)
+ {
+ /* Fail - NB: By this time, it's too late to
+ * rollback, and trying to do so allows the
+ * bind_engine() code to have created leaks. We
+ * just have to fail where we are, after the
+ * ENGINE has changed. */
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
+ ENGINE_R_CONFLICTING_ENGINE_ID);
+ return 0;
+ }
+ /* Tolerate */
+ ERR_clear_error();
+ }
+ }
+ return 1;
+ }
diff --git a/crypto/engine/eng_err.c b/crypto/engine/eng_err.c
new file mode 100644
index 0000000..81c70ac
--- /dev/null
+++ b/crypto/engine/eng_err.c
@@ -0,0 +1,173 @@
+/* crypto/engine/eng_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2010 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/engine.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_ENGINE,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_ENGINE,0,reason)
+
+static ERR_STRING_DATA ENGINE_str_functs[]=
+ {
+{ERR_FUNC(ENGINE_F_DYNAMIC_CTRL), "DYNAMIC_CTRL"},
+{ERR_FUNC(ENGINE_F_DYNAMIC_GET_DATA_CTX), "DYNAMIC_GET_DATA_CTX"},
+{ERR_FUNC(ENGINE_F_DYNAMIC_LOAD), "DYNAMIC_LOAD"},
+{ERR_FUNC(ENGINE_F_DYNAMIC_SET_DATA_CTX), "DYNAMIC_SET_DATA_CTX"},
+{ERR_FUNC(ENGINE_F_ENGINE_ADD), "ENGINE_add"},
+{ERR_FUNC(ENGINE_F_ENGINE_BY_ID), "ENGINE_by_id"},
+{ERR_FUNC(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE), "ENGINE_cmd_is_executable"},
+{ERR_FUNC(ENGINE_F_ENGINE_CTRL), "ENGINE_ctrl"},
+{ERR_FUNC(ENGINE_F_ENGINE_CTRL_CMD), "ENGINE_ctrl_cmd"},
+{ERR_FUNC(ENGINE_F_ENGINE_CTRL_CMD_STRING), "ENGINE_ctrl_cmd_string"},
+{ERR_FUNC(ENGINE_F_ENGINE_FINISH), "ENGINE_finish"},
+{ERR_FUNC(ENGINE_F_ENGINE_FREE_UTIL), "ENGINE_FREE_UTIL"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_CIPHER), "ENGINE_get_cipher"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_DEFAULT_TYPE), "ENGINE_GET_DEFAULT_TYPE"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_DIGEST), "ENGINE_get_digest"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_NEXT), "ENGINE_get_next"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH), "ENGINE_get_pkey_asn1_meth"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_PKEY_METH), "ENGINE_get_pkey_meth"},
+{ERR_FUNC(ENGINE_F_ENGINE_GET_PREV), "ENGINE_get_prev"},
+{ERR_FUNC(ENGINE_F_ENGINE_INIT), "ENGINE_init"},
+{ERR_FUNC(ENGINE_F_ENGINE_LIST_ADD), "ENGINE_LIST_ADD"},
+{ERR_FUNC(ENGINE_F_ENGINE_LIST_REMOVE), "ENGINE_LIST_REMOVE"},
+{ERR_FUNC(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY), "ENGINE_load_private_key"},
+{ERR_FUNC(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY), "ENGINE_load_public_key"},
+{ERR_FUNC(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT), "ENGINE_load_ssl_client_cert"},
+{ERR_FUNC(ENGINE_F_ENGINE_NEW), "ENGINE_new"},
+{ERR_FUNC(ENGINE_F_ENGINE_REMOVE), "ENGINE_remove"},
+{ERR_FUNC(ENGINE_F_ENGINE_SET_DEFAULT_STRING), "ENGINE_set_default_string"},
+{ERR_FUNC(ENGINE_F_ENGINE_SET_DEFAULT_TYPE), "ENGINE_SET_DEFAULT_TYPE"},
+{ERR_FUNC(ENGINE_F_ENGINE_SET_ID), "ENGINE_set_id"},
+{ERR_FUNC(ENGINE_F_ENGINE_SET_NAME), "ENGINE_set_name"},
+{ERR_FUNC(ENGINE_F_ENGINE_TABLE_REGISTER), "ENGINE_TABLE_REGISTER"},
+{ERR_FUNC(ENGINE_F_ENGINE_UNLOAD_KEY), "ENGINE_UNLOAD_KEY"},
+{ERR_FUNC(ENGINE_F_ENGINE_UNLOCKED_FINISH), "ENGINE_UNLOCKED_FINISH"},
+{ERR_FUNC(ENGINE_F_ENGINE_UP_REF), "ENGINE_up_ref"},
+{ERR_FUNC(ENGINE_F_INT_CTRL_HELPER), "INT_CTRL_HELPER"},
+{ERR_FUNC(ENGINE_F_INT_ENGINE_CONFIGURE), "INT_ENGINE_CONFIGURE"},
+{ERR_FUNC(ENGINE_F_INT_ENGINE_MODULE_INIT), "INT_ENGINE_MODULE_INIT"},
+{ERR_FUNC(ENGINE_F_LOG_MESSAGE), "LOG_MESSAGE"},
+{0,NULL}
+ };
+
+static ERR_STRING_DATA ENGINE_str_reasons[]=
+ {
+{ERR_REASON(ENGINE_R_ALREADY_LOADED) ,"already loaded"},
+{ERR_REASON(ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER),"argument is not a number"},
+{ERR_REASON(ENGINE_R_CMD_NOT_EXECUTABLE) ,"cmd not executable"},
+{ERR_REASON(ENGINE_R_COMMAND_TAKES_INPUT),"command takes input"},
+{ERR_REASON(ENGINE_R_COMMAND_TAKES_NO_INPUT),"command takes no input"},
+{ERR_REASON(ENGINE_R_CONFLICTING_ENGINE_ID),"conflicting engine id"},
+{ERR_REASON(ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED),"ctrl command not implemented"},
+{ERR_REASON(ENGINE_R_DH_NOT_IMPLEMENTED) ,"dh not implemented"},
+{ERR_REASON(ENGINE_R_DSA_NOT_IMPLEMENTED),"dsa not implemented"},
+{ERR_REASON(ENGINE_R_DSO_FAILURE) ,"DSO failure"},
+{ERR_REASON(ENGINE_R_DSO_NOT_FOUND) ,"dso not found"},
+{ERR_REASON(ENGINE_R_ENGINES_SECTION_ERROR),"engines section error"},
+{ERR_REASON(ENGINE_R_ENGINE_CONFIGURATION_ERROR),"engine configuration error"},
+{ERR_REASON(ENGINE_R_ENGINE_IS_NOT_IN_LIST),"engine is not in the list"},
+{ERR_REASON(ENGINE_R_ENGINE_SECTION_ERROR),"engine section error"},
+{ERR_REASON(ENGINE_R_FAILED_LOADING_PRIVATE_KEY),"failed loading private key"},
+{ERR_REASON(ENGINE_R_FAILED_LOADING_PUBLIC_KEY),"failed loading public key"},
+{ERR_REASON(ENGINE_R_FINISH_FAILED) ,"finish failed"},
+{ERR_REASON(ENGINE_R_GET_HANDLE_FAILED) ,"could not obtain hardware handle"},
+{ERR_REASON(ENGINE_R_ID_OR_NAME_MISSING) ,"'id' or 'name' missing"},
+{ERR_REASON(ENGINE_R_INIT_FAILED) ,"init failed"},
+{ERR_REASON(ENGINE_R_INTERNAL_LIST_ERROR),"internal list error"},
+{ERR_REASON(ENGINE_R_INVALID_ARGUMENT) ,"invalid argument"},
+{ERR_REASON(ENGINE_R_INVALID_CMD_NAME) ,"invalid cmd name"},
+{ERR_REASON(ENGINE_R_INVALID_CMD_NUMBER) ,"invalid cmd number"},
+{ERR_REASON(ENGINE_R_INVALID_INIT_VALUE) ,"invalid init value"},
+{ERR_REASON(ENGINE_R_INVALID_STRING) ,"invalid string"},
+{ERR_REASON(ENGINE_R_NOT_INITIALISED) ,"not initialised"},
+{ERR_REASON(ENGINE_R_NOT_LOADED) ,"not loaded"},
+{ERR_REASON(ENGINE_R_NO_CONTROL_FUNCTION),"no control function"},
+{ERR_REASON(ENGINE_R_NO_INDEX) ,"no index"},
+{ERR_REASON(ENGINE_R_NO_LOAD_FUNCTION) ,"no load function"},
+{ERR_REASON(ENGINE_R_NO_REFERENCE) ,"no reference"},
+{ERR_REASON(ENGINE_R_NO_SUCH_ENGINE) ,"no such engine"},
+{ERR_REASON(ENGINE_R_NO_UNLOAD_FUNCTION) ,"no unload function"},
+{ERR_REASON(ENGINE_R_PROVIDE_PARAMETERS) ,"provide parameters"},
+{ERR_REASON(ENGINE_R_RSA_NOT_IMPLEMENTED),"rsa not implemented"},
+{ERR_REASON(ENGINE_R_UNIMPLEMENTED_CIPHER),"unimplemented cipher"},
+{ERR_REASON(ENGINE_R_UNIMPLEMENTED_DIGEST),"unimplemented digest"},
+{ERR_REASON(ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD),"unimplemented public key method"},
+{ERR_REASON(ENGINE_R_VERSION_INCOMPATIBILITY),"version incompatibility"},
+{0,NULL}
+ };
+
+#endif
+
+void ERR_load_ENGINE_strings(void)
+ {
+#ifndef OPENSSL_NO_ERR
+
+ if (ERR_func_error_string(ENGINE_str_functs[0].error) == NULL)
+ {
+ ERR_load_strings(0,ENGINE_str_functs);
+ ERR_load_strings(0,ENGINE_str_reasons);
+ }
+#endif
+ }
diff --git a/crypto/engine/eng_fat.c b/crypto/engine/eng_fat.c
new file mode 100644
index 0000000..789b8d5
--- /dev/null
+++ b/crypto/engine/eng_fat.c
@@ -0,0 +1,182 @@
+/* crypto/engine/eng_fat.c */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include "eng_int.h"
+#include <openssl/conf.h>
+
+int ENGINE_set_default(ENGINE *e, unsigned int flags)
+ {
+ if((flags & ENGINE_METHOD_CIPHERS) && !ENGINE_set_default_ciphers(e))
+ return 0;
+ if((flags & ENGINE_METHOD_DIGESTS) && !ENGINE_set_default_digests(e))
+ return 0;
+#ifndef OPENSSL_NO_RSA
+ if((flags & ENGINE_METHOD_RSA) && !ENGINE_set_default_RSA(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_DSA
+ if((flags & ENGINE_METHOD_DSA) && !ENGINE_set_default_DSA(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_DH
+ if((flags & ENGINE_METHOD_DH) && !ENGINE_set_default_DH(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_ECDH
+ if((flags & ENGINE_METHOD_ECDH) && !ENGINE_set_default_ECDH(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ if((flags & ENGINE_METHOD_ECDSA) && !ENGINE_set_default_ECDSA(e))
+ return 0;
+#endif
+ if((flags & ENGINE_METHOD_RAND) && !ENGINE_set_default_RAND(e))
+ return 0;
+ if((flags & ENGINE_METHOD_PKEY_METHS)
+ && !ENGINE_set_default_pkey_meths(e))
+ return 0;
+ if((flags & ENGINE_METHOD_PKEY_ASN1_METHS)
+ && !ENGINE_set_default_pkey_asn1_meths(e))
+ return 0;
+ return 1;
+ }
+
+/* Set default algorithms using a string */
+
+static int int_def_cb(const char *alg, int len, void *arg)
+ {
+ unsigned int *pflags = arg;
+ if (!strncmp(alg, "ALL", len))
+ *pflags |= ENGINE_METHOD_ALL;
+ else if (!strncmp(alg, "RSA", len))
+ *pflags |= ENGINE_METHOD_RSA;
+ else if (!strncmp(alg, "DSA", len))
+ *pflags |= ENGINE_METHOD_DSA;
+ else if (!strncmp(alg, "ECDH", len))
+ *pflags |= ENGINE_METHOD_ECDH;
+ else if (!strncmp(alg, "ECDSA", len))
+ *pflags |= ENGINE_METHOD_ECDSA;
+ else if (!strncmp(alg, "DH", len))
+ *pflags |= ENGINE_METHOD_DH;
+ else if (!strncmp(alg, "RAND", len))
+ *pflags |= ENGINE_METHOD_RAND;
+ else if (!strncmp(alg, "CIPHERS", len))
+ *pflags |= ENGINE_METHOD_CIPHERS;
+ else if (!strncmp(alg, "DIGESTS", len))
+ *pflags |= ENGINE_METHOD_DIGESTS;
+ else if (!strncmp(alg, "PKEY", len))
+ *pflags |=
+ ENGINE_METHOD_PKEY_METHS|ENGINE_METHOD_PKEY_ASN1_METHS;
+ else if (!strncmp(alg, "PKEY_CRYPTO", len))
+ *pflags |= ENGINE_METHOD_PKEY_METHS;
+ else if (!strncmp(alg, "PKEY_ASN1", len))
+ *pflags |= ENGINE_METHOD_PKEY_ASN1_METHS;
+ else
+ return 0;
+ return 1;
+ }
+
+
+int ENGINE_set_default_string(ENGINE *e, const char *def_list)
+ {
+ unsigned int flags = 0;
+ if (!CONF_parse_list(def_list, ',', 1, int_def_cb, &flags))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_STRING,
+ ENGINE_R_INVALID_STRING);
+ ERR_add_error_data(2, "str=",def_list);
+ return 0;
+ }
+ return ENGINE_set_default(e, flags);
+ }
+
+int ENGINE_register_complete(ENGINE *e)
+ {
+ ENGINE_register_ciphers(e);
+ ENGINE_register_digests(e);
+#ifndef OPENSSL_NO_RSA
+ ENGINE_register_RSA(e);
+#endif
+#ifndef OPENSSL_NO_DSA
+ ENGINE_register_DSA(e);
+#endif
+#ifndef OPENSSL_NO_DH
+ ENGINE_register_DH(e);
+#endif
+#ifndef OPENSSL_NO_ECDH
+ ENGINE_register_ECDH(e);
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ ENGINE_register_ECDSA(e);
+#endif
+ ENGINE_register_RAND(e);
+ ENGINE_register_pkey_meths(e);
+ return 1;
+ }
+
+int ENGINE_register_all_complete(void)
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ if (!(e->flags & ENGINE_FLAGS_NO_REGISTER_ALL))
+ ENGINE_register_complete(e);
+ return 1;
+ }
diff --git a/crypto/engine/eng_init.c b/crypto/engine/eng_init.c
new file mode 100644
index 0000000..7633cf5
--- /dev/null
+++ b/crypto/engine/eng_init.c
@@ -0,0 +1,154 @@
+/* crypto/engine/eng_init.c */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* Initialise a engine type for use (or up its functional reference count
+ * if it's already in use). This version is only used internally. */
+int engine_unlocked_init(ENGINE *e)
+ {
+ int to_return = 1;
+
+ if((e->funct_ref == 0) && e->init)
+ /* This is the first functional reference and the engine
+ * requires initialisation so we do it now. */
+ to_return = e->init(e);
+ if(to_return)
+ {
+ /* OK, we return a functional reference which is also a
+ * structural reference. */
+ e->struct_ref++;
+ e->funct_ref++;
+ engine_ref_debug(e, 0, 1)
+ engine_ref_debug(e, 1, 1)
+ }
+ return to_return;
+ }
+
+/* Free a functional reference to a engine type. This version is only used
+ * internally. */
+int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers)
+ {
+ int to_return = 1;
+
+ /* Reduce the functional reference count here so if it's the terminating
+ * case, we can release the lock safely and call the finish() handler
+ * without risk of a race. We get a race if we leave the count until
+ * after and something else is calling "finish" at the same time -
+ * there's a chance that both threads will together take the count from
+ * 2 to 0 without either calling finish(). */
+ e->funct_ref--;
+ engine_ref_debug(e, 1, -1);
+ if((e->funct_ref == 0) && e->finish)
+ {
+ if(unlock_for_handlers)
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ to_return = e->finish(e);
+ if(unlock_for_handlers)
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(!to_return)
+ return 0;
+ }
+#ifdef REF_CHECK
+ if(e->funct_ref < 0)
+ {
+ fprintf(stderr,"ENGINE_finish, bad functional reference count\n");
+ abort();
+ }
+#endif
+ /* Release the structural reference too */
+ if(!engine_free_util(e, 0))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_FINISH,ENGINE_R_FINISH_FAILED);
+ return 0;
+ }
+ return to_return;
+ }
+
+/* The API (locked) version of "init" */
+int ENGINE_init(ENGINE *e)
+ {
+ int ret;
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_INIT,ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ ret = engine_unlocked_init(e);
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return ret;
+ }
+
+/* The API (locked) version of "finish" */
+int ENGINE_finish(ENGINE *e)
+ {
+ int to_return = 1;
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_FINISH,ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ to_return = engine_unlocked_finish(e, 1);
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ if(!to_return)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_FINISH,ENGINE_R_FINISH_FAILED);
+ return 0;
+ }
+ return to_return;
+ }
diff --git a/crypto/engine/eng_int.h b/crypto/engine/eng_int.h
new file mode 100644
index 0000000..451ef8f
--- /dev/null
+++ b/crypto/engine/eng_int.h
@@ -0,0 +1,206 @@
+/* crypto/engine/eng_int.h */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_INT_H
+#define HEADER_ENGINE_INT_H
+
+#include "cryptlib.h"
+/* Take public definitions from engine.h */
+#include <openssl/engine.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* If we compile with this symbol defined, then both reference counts in the
+ * ENGINE structure will be monitored with a line of output on stderr for each
+ * change. This prints the engine's pointer address (truncated to unsigned int),
+ * "struct" or "funct" to indicate the reference type, the before and after
+ * reference count, and the file:line-number pair. The "engine_ref_debug"
+ * statements must come *after* the change. */
+#ifdef ENGINE_REF_COUNT_DEBUG
+
+#define engine_ref_debug(e, isfunct, diff) \
+ fprintf(stderr, "engine: %08x %s from %d to %d (%s:%d)\n", \
+ (unsigned int)(e), (isfunct ? "funct" : "struct"), \
+ ((isfunct) ? ((e)->funct_ref - (diff)) : ((e)->struct_ref - (diff))), \
+ ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \
+ (__FILE__), (__LINE__));
+
+#else
+
+#define engine_ref_debug(e, isfunct, diff)
+
+#endif
+
+/* Any code that will need cleanup operations should use these functions to
+ * register callbacks. ENGINE_cleanup() will call all registered callbacks in
+ * order. NB: both the "add" functions assume CRYPTO_LOCK_ENGINE to already be
+ * held (in "write" mode). */
+typedef void (ENGINE_CLEANUP_CB)(void);
+typedef struct st_engine_cleanup_item
+ {
+ ENGINE_CLEANUP_CB *cb;
+ } ENGINE_CLEANUP_ITEM;
+DECLARE_STACK_OF(ENGINE_CLEANUP_ITEM)
+void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
+void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
+
+/* We need stacks of ENGINEs for use in eng_table.c */
+DECLARE_STACK_OF(ENGINE)
+
+/* If this symbol is defined then engine_table_select(), the function that is
+ * used by RSA, DSA (etc) code to select registered ENGINEs, cache defaults and
+ * functional references (etc), will display debugging summaries to stderr. */
+/* #define ENGINE_TABLE_DEBUG */
+
+/* This represents an implementation table. Dependent code should instantiate it
+ * as a (ENGINE_TABLE *) pointer value set initially to NULL. */
+typedef struct st_engine_table ENGINE_TABLE;
+int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
+ ENGINE *e, const int *nids, int num_nids, int setdefault);
+void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e);
+void engine_table_cleanup(ENGINE_TABLE **table);
+#ifndef ENGINE_TABLE_DEBUG
+ENGINE *engine_table_select(ENGINE_TABLE **table, int nid);
+#else
+ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l);
+#define engine_table_select(t,n) engine_table_select_tmp(t,n,__FILE__,__LINE__)
+#endif
+typedef void (engine_table_doall_cb)(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg);
+void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, void *arg);
+
+/* Internal versions of API functions that have control over locking. These are
+ * used between C files when functionality needs to be shared but the caller may
+ * already be controlling of the CRYPTO_LOCK_ENGINE lock. */
+int engine_unlocked_init(ENGINE *e);
+int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers);
+int engine_free_util(ENGINE *e, int locked);
+
+/* This function will reset all "set"able values in an ENGINE to NULL. This
+ * won't touch reference counts or ex_data, but is equivalent to calling all the
+ * ENGINE_set_***() functions with a NULL value. */
+void engine_set_all_null(ENGINE *e);
+
+/* NB: Bitwise OR-able values for the "flags" variable in ENGINE are now exposed
+ * in engine.h. */
+
+/* Free up dynamically allocated public key methods associated with ENGINE */
+
+void engine_pkey_meths_free(ENGINE *e);
+void engine_pkey_asn1_meths_free(ENGINE *e);
+
+/* This is a structure for storing implementations of various crypto
+ * algorithms and functions. */
+struct engine_st
+ {
+ const char *id;
+ const char *name;
+ const RSA_METHOD *rsa_meth;
+ const DSA_METHOD *dsa_meth;
+ const DH_METHOD *dh_meth;
+ const ECDH_METHOD *ecdh_meth;
+ const ECDSA_METHOD *ecdsa_meth;
+ const RAND_METHOD *rand_meth;
+ const STORE_METHOD *store_meth;
+ /* Cipher handling is via this callback */
+ ENGINE_CIPHERS_PTR ciphers;
+ /* Digest handling is via this callback */
+ ENGINE_DIGESTS_PTR digests;
+ /* Public key handling via this callback */
+ ENGINE_PKEY_METHS_PTR pkey_meths;
+ /* ASN1 public key handling via this callback */
+ ENGINE_PKEY_ASN1_METHS_PTR pkey_asn1_meths;
+
+ ENGINE_GEN_INT_FUNC_PTR destroy;
+
+ ENGINE_GEN_INT_FUNC_PTR init;
+ ENGINE_GEN_INT_FUNC_PTR finish;
+ ENGINE_CTRL_FUNC_PTR ctrl;
+ ENGINE_LOAD_KEY_PTR load_privkey;
+ ENGINE_LOAD_KEY_PTR load_pubkey;
+
+ ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert;
+
+ const ENGINE_CMD_DEFN *cmd_defns;
+ int flags;
+ /* reference count on the structure itself */
+ int struct_ref;
+ /* reference count on usability of the engine type. NB: This
+ * controls the loading and initialisation of any functionlity
+ * required by this engine, whereas the previous count is
+ * simply to cope with (de)allocation of this structure. Hence,
+ * running_ref <= struct_ref at all times. */
+ int funct_ref;
+ /* A place to store per-ENGINE data */
+ CRYPTO_EX_DATA ex_data;
+ /* Used to maintain the linked-list of engines. */
+ struct engine_st *prev;
+ struct engine_st *next;
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEADER_ENGINE_INT_H */
diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c
new file mode 100644
index 0000000..18a6664
--- /dev/null
+++ b/crypto/engine/eng_lib.c
@@ -0,0 +1,332 @@
+/* crypto/engine/eng_lib.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+#include <openssl/rand.h>
+
+/* The "new"/"free" stuff first */
+
+ENGINE *ENGINE_new(void)
+ {
+ ENGINE *ret;
+
+ ret = (ENGINE *)OPENSSL_malloc(sizeof(ENGINE));
+ if(ret == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ret, 0, sizeof(ENGINE));
+ ret->struct_ref = 1;
+ engine_ref_debug(ret, 0, 1)
+ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data);
+ return ret;
+ }
+
+/* Placed here (close proximity to ENGINE_new) so that modifications to the
+ * elements of the ENGINE structure are more likely to be caught and changed
+ * here. */
+void engine_set_all_null(ENGINE *e)
+ {
+ e->id = NULL;
+ e->name = NULL;
+ e->rsa_meth = NULL;
+ e->dsa_meth = NULL;
+ e->dh_meth = NULL;
+ e->rand_meth = NULL;
+ e->store_meth = NULL;
+ e->ciphers = NULL;
+ e->digests = NULL;
+ e->destroy = NULL;
+ e->init = NULL;
+ e->finish = NULL;
+ e->ctrl = NULL;
+ e->load_privkey = NULL;
+ e->load_pubkey = NULL;
+ e->cmd_defns = NULL;
+ e->flags = 0;
+ }
+
+int engine_free_util(ENGINE *e, int locked)
+ {
+ int i;
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_FREE_UTIL,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if(locked)
+ i = CRYPTO_add(&e->struct_ref,-1,CRYPTO_LOCK_ENGINE);
+ else
+ i = --e->struct_ref;
+ engine_ref_debug(e, 0, -1)
+ if (i > 0) return 1;
+#ifdef REF_CHECK
+ if (i < 0)
+ {
+ fprintf(stderr,"ENGINE_free, bad structural reference count\n");
+ abort();
+ }
+#endif
+ /* Free up any dynamically allocated public key methods */
+ engine_pkey_meths_free(e);
+ engine_pkey_asn1_meths_free(e);
+ /* Give the ENGINE a chance to do any structural cleanup corresponding
+ * to allocation it did in its constructor (eg. unload error strings) */
+ if(e->destroy)
+ e->destroy(e);
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data);
+ OPENSSL_free(e);
+ return 1;
+ }
+
+int ENGINE_free(ENGINE *e)
+ {
+ return engine_free_util(e, 1);
+ }
+
+/* Cleanup stuff */
+
+/* ENGINE_cleanup() is coded such that anything that does work that will need
+ * cleanup can register a "cleanup" callback here. That way we don't get linker
+ * bloat by referring to all *possible* cleanups, but any linker bloat into code
+ * "X" will cause X's cleanup function to end up here. */
+static STACK_OF(ENGINE_CLEANUP_ITEM) *cleanup_stack = NULL;
+static int int_cleanup_check(int create)
+ {
+ if(cleanup_stack) return 1;
+ if(!create) return 0;
+ cleanup_stack = sk_ENGINE_CLEANUP_ITEM_new_null();
+ return (cleanup_stack ? 1 : 0);
+ }
+static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb)
+ {
+ ENGINE_CLEANUP_ITEM *item = OPENSSL_malloc(sizeof(
+ ENGINE_CLEANUP_ITEM));
+ if(!item) return NULL;
+ item->cb = cb;
+ return item;
+ }
+void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
+ {
+ ENGINE_CLEANUP_ITEM *item;
+ if(!int_cleanup_check(1)) return;
+ item = int_cleanup_item(cb);
+ if(item)
+ sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0);
+ }
+void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
+ {
+ ENGINE_CLEANUP_ITEM *item;
+ if(!int_cleanup_check(1)) return;
+ item = int_cleanup_item(cb);
+ if(item)
+ sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item);
+ }
+/* The API function that performs all cleanup */
+static void engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM *item)
+ {
+ (*(item->cb))();
+ OPENSSL_free(item);
+ }
+void ENGINE_cleanup(void)
+ {
+ if(int_cleanup_check(0))
+ {
+ sk_ENGINE_CLEANUP_ITEM_pop_free(cleanup_stack,
+ engine_cleanup_cb_free);
+ cleanup_stack = NULL;
+ }
+ /* FIXME: This should be handled (somehow) through RAND, eg. by it
+ * registering a cleanup callback. */
+ RAND_set_rand_method(NULL);
+ }
+
+/* Now the "ex_data" support */
+
+int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+ {
+ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ENGINE, argl, argp,
+ new_func, dup_func, free_func);
+ }
+
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg)
+ {
+ return(CRYPTO_set_ex_data(&e->ex_data, idx, arg));
+ }
+
+void *ENGINE_get_ex_data(const ENGINE *e, int idx)
+ {
+ return(CRYPTO_get_ex_data(&e->ex_data, idx));
+ }
+
+/* Functions to get/set an ENGINE's elements - mainly to avoid exposing the
+ * ENGINE structure itself. */
+
+int ENGINE_set_id(ENGINE *e, const char *id)
+ {
+ if(id == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_SET_ID,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ e->id = id;
+ return 1;
+ }
+
+int ENGINE_set_name(ENGINE *e, const char *name)
+ {
+ if(name == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_SET_NAME,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ e->name = name;
+ return 1;
+ }
+
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f)
+ {
+ e->destroy = destroy_f;
+ return 1;
+ }
+
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f)
+ {
+ e->init = init_f;
+ return 1;
+ }
+
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f)
+ {
+ e->finish = finish_f;
+ return 1;
+ }
+
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f)
+ {
+ e->ctrl = ctrl_f;
+ return 1;
+ }
+
+int ENGINE_set_flags(ENGINE *e, int flags)
+ {
+ e->flags = flags;
+ return 1;
+ }
+
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns)
+ {
+ e->cmd_defns = defns;
+ return 1;
+ }
+
+const char *ENGINE_get_id(const ENGINE *e)
+ {
+ return e->id;
+ }
+
+const char *ENGINE_get_name(const ENGINE *e)
+ {
+ return e->name;
+ }
+
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e)
+ {
+ return e->destroy;
+ }
+
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e)
+ {
+ return e->init;
+ }
+
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e)
+ {
+ return e->finish;
+ }
+
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e)
+ {
+ return e->ctrl;
+ }
+
+int ENGINE_get_flags(const ENGINE *e)
+ {
+ return e->flags;
+ }
+
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e)
+ {
+ return e->cmd_defns;
+ }
+
+/* eng_lib.o is pretty much linked into anything that touches ENGINE already, so
+ * put the "static_state" hack here. */
+
+static int internal_static_hack = 0;
+
+void *ENGINE_get_static_state(void)
+ {
+ return &internal_static_hack;
+ }
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c
new file mode 100644
index 0000000..27846ed
--- /dev/null
+++ b/crypto/engine/eng_list.c
@@ -0,0 +1,433 @@
+/* crypto/engine/eng_list.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include "eng_int.h"
+
+/* The linked-list of pointers to engine types. engine_list_head
+ * incorporates an implicit structural reference but engine_list_tail
+ * does not - the latter is a computational niceity and only points
+ * to something that is already pointed to by its predecessor in the
+ * list (or engine_list_head itself). In the same way, the use of the
+ * "prev" pointer in each ENGINE is to save excessive list iteration,
+ * it doesn't correspond to an extra structural reference. Hence,
+ * engine_list_head, and each non-null "next" pointer account for
+ * the list itself assuming exactly 1 structural reference on each
+ * list member. */
+static ENGINE *engine_list_head = NULL;
+static ENGINE *engine_list_tail = NULL;
+
+/* This cleanup function is only needed internally. If it should be called, we
+ * register it with the "ENGINE_cleanup()" stack to be called during cleanup. */
+
+static void engine_list_cleanup(void)
+ {
+ ENGINE *iterator = engine_list_head;
+
+ while(iterator != NULL)
+ {
+ ENGINE_remove(iterator);
+ iterator = engine_list_head;
+ }
+ return;
+ }
+
+/* These static functions starting with a lower case "engine_" always
+ * take place when CRYPTO_LOCK_ENGINE has been locked up. */
+static int engine_list_add(ENGINE *e)
+ {
+ int conflict = 0;
+ ENGINE *iterator = NULL;
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ iterator = engine_list_head;
+ while(iterator && !conflict)
+ {
+ conflict = (strcmp(iterator->id, e->id) == 0);
+ iterator = iterator->next;
+ }
+ if(conflict)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD,
+ ENGINE_R_CONFLICTING_ENGINE_ID);
+ return 0;
+ }
+ if(engine_list_head == NULL)
+ {
+ /* We are adding to an empty list. */
+ if(engine_list_tail)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ engine_list_head = e;
+ e->prev = NULL;
+ /* The first time the list allocates, we should register the
+ * cleanup. */
+ engine_cleanup_add_last(engine_list_cleanup);
+ }
+ else
+ {
+ /* We are adding to the tail of an existing list. */
+ if((engine_list_tail == NULL) ||
+ (engine_list_tail->next != NULL))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ engine_list_tail->next = e;
+ e->prev = engine_list_tail;
+ }
+ /* Having the engine in the list assumes a structural
+ * reference. */
+ e->struct_ref++;
+ engine_ref_debug(e, 0, 1)
+ /* However it came to be, e is the last item in the list. */
+ engine_list_tail = e;
+ e->next = NULL;
+ return 1;
+ }
+
+static int engine_list_remove(ENGINE *e)
+ {
+ ENGINE *iterator;
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ /* We need to check that e is in our linked list! */
+ iterator = engine_list_head;
+ while(iterator && (iterator != e))
+ iterator = iterator->next;
+ if(iterator == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE,
+ ENGINE_R_ENGINE_IS_NOT_IN_LIST);
+ return 0;
+ }
+ /* un-link e from the chain. */
+ if(e->next)
+ e->next->prev = e->prev;
+ if(e->prev)
+ e->prev->next = e->next;
+ /* Correct our head/tail if necessary. */
+ if(engine_list_head == e)
+ engine_list_head = e->next;
+ if(engine_list_tail == e)
+ engine_list_tail = e->prev;
+ engine_free_util(e, 0);
+ return 1;
+ }
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void)
+ {
+ ENGINE *ret;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ ret = engine_list_head;
+ if(ret)
+ {
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1)
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return ret;
+ }
+
+ENGINE *ENGINE_get_last(void)
+ {
+ ENGINE *ret;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ ret = engine_list_tail;
+ if(ret)
+ {
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1)
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return ret;
+ }
+
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e)
+ {
+ ENGINE *ret = NULL;
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_GET_NEXT,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ ret = e->next;
+ if(ret)
+ {
+ /* Return a valid structural refernce to the next ENGINE */
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1)
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ /* Release the structural reference to the previous ENGINE */
+ ENGINE_free(e);
+ return ret;
+ }
+
+ENGINE *ENGINE_get_prev(ENGINE *e)
+ {
+ ENGINE *ret = NULL;
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_GET_PREV,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ ret = e->prev;
+ if(ret)
+ {
+ /* Return a valid structural reference to the next ENGINE */
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1)
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ /* Release the structural reference to the previous ENGINE */
+ ENGINE_free(e);
+ return ret;
+ }
+
+/* Add another "ENGINE" type into the list. */
+int ENGINE_add(ENGINE *e)
+ {
+ int to_return = 1;
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_ADD,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if((e->id == NULL) || (e->name == NULL))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_ADD,
+ ENGINE_R_ID_OR_NAME_MISSING);
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(!engine_list_add(e))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_ADD,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ to_return = 0;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return to_return;
+ }
+
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e)
+ {
+ int to_return = 1;
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_REMOVE,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(!engine_list_remove(e))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_REMOVE,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ to_return = 0;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return to_return;
+ }
+
+static void engine_cpy(ENGINE *dest, const ENGINE *src)
+ {
+ dest->id = src->id;
+ dest->name = src->name;
+#ifndef OPENSSL_NO_RSA
+ dest->rsa_meth = src->rsa_meth;
+#endif
+#ifndef OPENSSL_NO_DSA
+ dest->dsa_meth = src->dsa_meth;
+#endif
+#ifndef OPENSSL_NO_DH
+ dest->dh_meth = src->dh_meth;
+#endif
+#ifndef OPENSSL_NO_ECDH
+ dest->ecdh_meth = src->ecdh_meth;
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ dest->ecdsa_meth = src->ecdsa_meth;
+#endif
+ dest->rand_meth = src->rand_meth;
+ dest->store_meth = src->store_meth;
+ dest->ciphers = src->ciphers;
+ dest->digests = src->digests;
+ dest->pkey_meths = src->pkey_meths;
+ dest->destroy = src->destroy;
+ dest->init = src->init;
+ dest->finish = src->finish;
+ dest->ctrl = src->ctrl;
+ dest->load_privkey = src->load_privkey;
+ dest->load_pubkey = src->load_pubkey;
+ dest->cmd_defns = src->cmd_defns;
+ dest->flags = src->flags;
+ }
+
+ENGINE *ENGINE_by_id(const char *id)
+ {
+ ENGINE *iterator;
+ char *load_dir = NULL;
+ if(id == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_BY_ID,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ iterator = engine_list_head;
+ while(iterator && (strcmp(id, iterator->id) != 0))
+ iterator = iterator->next;
+ if(iterator)
+ {
+ /* We need to return a structural reference. If this is an
+ * ENGINE type that returns copies, make a duplicate - otherwise
+ * increment the existing ENGINE's reference count. */
+ if(iterator->flags & ENGINE_FLAGS_BY_ID_COPY)
+ {
+ ENGINE *cp = ENGINE_new();
+ if(!cp)
+ iterator = NULL;
+ else
+ {
+ engine_cpy(cp, iterator);
+ iterator = cp;
+ }
+ }
+ else
+ {
+ iterator->struct_ref++;
+ engine_ref_debug(iterator, 0, 1)
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+#if 0
+ if(iterator == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_BY_ID,
+ ENGINE_R_NO_SUCH_ENGINE);
+ ERR_add_error_data(2, "id=", id);
+ }
+ return iterator;
+#else
+ /* EEK! Experimental code starts */
+ if(iterator) return iterator;
+ /* Prevent infinite recusrion if we're looking for the dynamic engine. */
+ if (strcmp(id, "dynamic"))
+ {
+#ifdef OPENSSL_SYS_VMS
+ if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = "SSLROOT:[ENGINES]";
+#else
+ if((load_dir = getenv("OPENSSL_ENGINES")) == 0) load_dir = ENGINESDIR;
+#endif
+ iterator = ENGINE_by_id("dynamic");
+ if(!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
+ load_dir, 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
+ goto notfound;
+ return iterator;
+ }
+notfound:
+ ENGINE_free(iterator);
+ ENGINEerr(ENGINE_F_ENGINE_BY_ID,ENGINE_R_NO_SUCH_ENGINE);
+ ERR_add_error_data(2, "id=", id);
+ return NULL;
+ /* EEK! Experimental code ends */
+#endif
+ }
+
+int ENGINE_up_ref(ENGINE *e)
+ {
+ if (e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_UP_REF,ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_add(&e->struct_ref,1,CRYPTO_LOCK_ENGINE);
+ return 1;
+ }
diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c
new file mode 100644
index 0000000..9abb95c
--- /dev/null
+++ b/crypto/engine/eng_openssl.c
@@ -0,0 +1,384 @@
+/* crypto/engine/eng_openssl.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/engine.h>
+#include <openssl/dso.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+
+/* This testing gunk is implemented (and explained) lower down. It also assumes
+ * the application explicitly calls "ENGINE_load_openssl()" because this is no
+ * longer automatic in ENGINE_load_builtin_engines(). */
+#define TEST_ENG_OPENSSL_RC4
+#define TEST_ENG_OPENSSL_PKEY
+/* #define TEST_ENG_OPENSSL_RC4_OTHERS */
+#define TEST_ENG_OPENSSL_RC4_P_INIT
+/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */
+#define TEST_ENG_OPENSSL_SHA
+/* #define TEST_ENG_OPENSSL_SHA_OTHERS */
+/* #define TEST_ENG_OPENSSL_SHA_P_INIT */
+/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */
+/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */
+
+/* Now check what of those algorithms are actually enabled */
+#ifdef OPENSSL_NO_RC4
+#undef TEST_ENG_OPENSSL_RC4
+#undef TEST_ENG_OPENSSL_RC4_OTHERS
+#undef TEST_ENG_OPENSSL_RC4_P_INIT
+#undef TEST_ENG_OPENSSL_RC4_P_CIPHER
+#endif
+#if defined(OPENSSL_NO_SHA) || defined(OPENSSL_NO_SHA0) || defined(OPENSSL_NO_SHA1)
+#undef TEST_ENG_OPENSSL_SHA
+#undef TEST_ENG_OPENSSL_SHA_OTHERS
+#undef TEST_ENG_OPENSSL_SHA_P_INIT
+#undef TEST_ENG_OPENSSL_SHA_P_UPDATE
+#undef TEST_ENG_OPENSSL_SHA_P_FINAL
+#endif
+
+#ifdef TEST_ENG_OPENSSL_RC4
+static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid);
+#endif
+#ifdef TEST_ENG_OPENSSL_SHA
+static int openssl_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid);
+#endif
+
+#ifdef TEST_ENG_OPENSSL_PKEY
+static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+#endif
+
+/* The constants used when creating the ENGINE */
+static const char *engine_openssl_id = "openssl";
+static const char *engine_openssl_name = "Software engine support";
+
+/* This internal function is used by ENGINE_openssl() and possibly by the
+ * "dynamic" ENGINE support too */
+static int bind_helper(ENGINE *e)
+ {
+ if(!ENGINE_set_id(e, engine_openssl_id)
+ || !ENGINE_set_name(e, engine_openssl_name)
+#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS
+#ifndef OPENSSL_NO_RSA
+ || !ENGINE_set_RSA(e, RSA_get_default_method())
+#endif
+#ifndef OPENSSL_NO_DSA
+ || !ENGINE_set_DSA(e, DSA_get_default_method())
+#endif
+#ifndef OPENSSL_NO_ECDH
+ || !ENGINE_set_ECDH(e, ECDH_OpenSSL())
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ || !ENGINE_set_ECDSA(e, ECDSA_OpenSSL())
+#endif
+#ifndef OPENSSL_NO_DH
+ || !ENGINE_set_DH(e, DH_get_default_method())
+#endif
+ || !ENGINE_set_RAND(e, RAND_SSLeay())
+#ifdef TEST_ENG_OPENSSL_RC4
+ || !ENGINE_set_ciphers(e, openssl_ciphers)
+#endif
+#ifdef TEST_ENG_OPENSSL_SHA
+ || !ENGINE_set_digests(e, openssl_digests)
+#endif
+#endif
+#ifdef TEST_ENG_OPENSSL_PKEY
+ || !ENGINE_set_load_privkey_function(e, openssl_load_privkey)
+#endif
+ )
+ return 0;
+ /* If we add errors to this ENGINE, ensure the error handling is setup here */
+ /* openssl_load_error_strings(); */
+ return 1;
+ }
+
+static ENGINE *engine_openssl(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!bind_helper(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void ENGINE_load_openssl(void)
+ {
+ ENGINE *toadd = engine_openssl();
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ /* If the "add" worked, it gets a structural reference. So either way,
+ * we release our just-created reference. */
+ ENGINE_free(toadd);
+ ERR_clear_error();
+ }
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+ {
+ if(id && (strcmp(id, engine_openssl_id) != 0))
+ return 0;
+ if(!bind_helper(e))
+ return 0;
+ return 1;
+ }
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#ifdef TEST_ENG_OPENSSL_RC4
+/* This section of code compiles an "alternative implementation" of two modes of
+ * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4"
+ * should under normal circumstances go via this support rather than the default
+ * EVP support. There are other symbols to tweak the testing;
+ * TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time
+ * we're asked for a cipher we don't support (should not happen).
+ * TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time
+ * the "init_key" handler is called.
+ * TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler.
+ */
+#include <openssl/rc4.h>
+#define TEST_RC4_KEY_SIZE 16
+static int test_cipher_nids[] = {NID_rc4,NID_rc4_40};
+static int test_cipher_nids_number = 2;
+typedef struct {
+ unsigned char key[TEST_RC4_KEY_SIZE];
+ RC4_KEY ks;
+ } TEST_RC4_KEY;
+#define test(ctx) ((TEST_RC4_KEY *)(ctx)->cipher_data)
+static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+#ifdef TEST_ENG_OPENSSL_RC4_P_INIT
+ fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n");
+#endif
+ memcpy(&test(ctx)->key[0],key,EVP_CIPHER_CTX_key_length(ctx));
+ RC4_set_key(&test(ctx)->ks,EVP_CIPHER_CTX_key_length(ctx),
+ test(ctx)->key);
+ return 1;
+ }
+static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+ {
+#ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER
+ fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n");
+#endif
+ RC4(&test(ctx)->ks,inl,in,out);
+ return 1;
+ }
+static const EVP_CIPHER test_r4_cipher=
+ {
+ NID_rc4,
+ 1,TEST_RC4_KEY_SIZE,0,
+ EVP_CIPH_VARIABLE_LENGTH,
+ test_rc4_init_key,
+ test_rc4_cipher,
+ NULL,
+ sizeof(TEST_RC4_KEY),
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+static const EVP_CIPHER test_r4_40_cipher=
+ {
+ NID_rc4_40,
+ 1,5 /* 40 bit */,0,
+ EVP_CIPH_VARIABLE_LENGTH,
+ test_rc4_init_key,
+ test_rc4_cipher,
+ NULL,
+ sizeof(TEST_RC4_KEY),
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid)
+ {
+ if(!cipher)
+ {
+ /* We are returning a list of supported nids */
+ *nids = test_cipher_nids;
+ return test_cipher_nids_number;
+ }
+ /* We are being asked for a specific cipher */
+ if(nid == NID_rc4)
+ *cipher = &test_r4_cipher;
+ else if(nid == NID_rc4_40)
+ *cipher = &test_r4_40_cipher;
+ else
+ {
+#ifdef TEST_ENG_OPENSSL_RC4_OTHERS
+ fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for "
+ "nid %d\n", nid);
+#endif
+ *cipher = NULL;
+ return 0;
+ }
+ return 1;
+ }
+#endif
+
+#ifdef TEST_ENG_OPENSSL_SHA
+/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */
+#include <openssl/sha.h>
+static int test_digest_nids[] = {NID_sha1};
+static int test_digest_nids_number = 1;
+static int test_sha1_init(EVP_MD_CTX *ctx)
+ {
+#ifdef TEST_ENG_OPENSSL_SHA_P_INIT
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n");
+#endif
+ return SHA1_Init(ctx->md_data);
+ }
+static int test_sha1_update(EVP_MD_CTX *ctx,const void *data,size_t count)
+ {
+#ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n");
+#endif
+ return SHA1_Update(ctx->md_data,data,count);
+ }
+static int test_sha1_final(EVP_MD_CTX *ctx,unsigned char *md)
+ {
+#ifdef TEST_ENG_OPENSSL_SHA_P_FINAL
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n");
+#endif
+ return SHA1_Final(md,ctx->md_data);
+ }
+static const EVP_MD test_sha_md=
+ {
+ NID_sha1,
+ NID_sha1WithRSAEncryption,
+ SHA_DIGEST_LENGTH,
+ 0,
+ test_sha1_init,
+ test_sha1_update,
+ test_sha1_final,
+ NULL,
+ NULL,
+ EVP_PKEY_RSA_method,
+ SHA_CBLOCK,
+ sizeof(EVP_MD *)+sizeof(SHA_CTX),
+ };
+static int openssl_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid)
+ {
+ if(!digest)
+ {
+ /* We are returning a list of supported nids */
+ *nids = test_digest_nids;
+ return test_digest_nids_number;
+ }
+ /* We are being asked for a specific digest */
+ if(nid == NID_sha1)
+ *digest = &test_sha_md;
+ else
+ {
+#ifdef TEST_ENG_OPENSSL_SHA_OTHERS
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for "
+ "nid %d\n", nid);
+#endif
+ *digest = NULL;
+ return 0;
+ }
+ return 1;
+ }
+#endif
+
+#ifdef TEST_ENG_OPENSSL_PKEY
+static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data)
+ {
+ BIO *in;
+ EVP_PKEY *key;
+ fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", key_id);
+ in = BIO_new_file(key_id, "r");
+ if (!in)
+ return NULL;
+ key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
+ BIO_free(in);
+ return key;
+ }
+#endif
diff --git a/crypto/engine/eng_pkey.c b/crypto/engine/eng_pkey.c
new file mode 100644
index 0000000..1dfa2e3
--- /dev/null
+++ b/crypto/engine/eng_pkey.c
@@ -0,0 +1,196 @@
+/* crypto/engine/eng_pkey.c */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* Basic get/set stuff */
+
+int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f)
+ {
+ e->load_privkey = loadpriv_f;
+ return 1;
+ }
+
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f)
+ {
+ e->load_pubkey = loadpub_f;
+ return 1;
+ }
+
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+ ENGINE_SSL_CLIENT_CERT_PTR loadssl_f)
+ {
+ e->load_ssl_client_cert = loadssl_f;
+ return 1;
+ }
+
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e)
+ {
+ return e->load_privkey;
+ }
+
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e)
+ {
+ return e->load_pubkey;
+ }
+
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e)
+ {
+ return e->load_ssl_client_cert;
+ }
+
+/* API functions to load public/private keys */
+
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data)
+ {
+ EVP_PKEY *pkey;
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(e->funct_ref == 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ENGINE_R_NOT_INITIALISED);
+ return 0;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ if (!e->load_privkey)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ENGINE_R_NO_LOAD_FUNCTION);
+ return 0;
+ }
+ pkey = e->load_privkey(e, key_id, ui_method, callback_data);
+ if (!pkey)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
+ return 0;
+ }
+ return pkey;
+ }
+
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data)
+ {
+ EVP_PKEY *pkey;
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(e->funct_ref == 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
+ ENGINE_R_NOT_INITIALISED);
+ return 0;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ if (!e->load_pubkey)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
+ ENGINE_R_NO_LOAD_FUNCTION);
+ return 0;
+ }
+ pkey = e->load_pubkey(e, key_id, ui_method, callback_data);
+ if (!pkey)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
+ ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
+ return 0;
+ }
+ return pkey;
+ }
+
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey,
+ STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data)
+ {
+
+ if(e == NULL)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(e->funct_ref == 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+ ENGINE_R_NOT_INITIALISED);
+ return 0;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ if (!e->load_ssl_client_cert)
+ {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+ ENGINE_R_NO_LOAD_FUNCTION);
+ return 0;
+ }
+ return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother,
+ ui_method, callback_data);
+ }
diff --git a/crypto/engine/eng_rdrand.c b/crypto/engine/eng_rdrand.c
new file mode 100644
index 0000000..a9ba5ae
--- /dev/null
+++ b/crypto/engine/eng_rdrand.c
@@ -0,0 +1,142 @@
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <openssl/opensslconf.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/engine.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+
+#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ)
+
+size_t OPENSSL_ia32_rdrand(void);
+
+static int get_random_bytes (unsigned char *buf, int num)
+ {
+ size_t rnd;
+
+ while (num>=(int)sizeof(size_t)) {
+ if ((rnd = OPENSSL_ia32_rdrand()) == 0) return 0;
+
+ *((size_t *)buf) = rnd;
+ buf += sizeof(size_t);
+ num -= sizeof(size_t);
+ }
+ if (num) {
+ if ((rnd = OPENSSL_ia32_rdrand()) == 0) return 0;
+
+ memcpy (buf,&rnd,num);
+ }
+
+ return 1;
+ }
+
+static int random_status (void)
+{ return 1; }
+
+static RAND_METHOD rdrand_meth =
+ {
+ NULL, /* seed */
+ get_random_bytes,
+ NULL, /* cleanup */
+ NULL, /* add */
+ get_random_bytes,
+ random_status,
+ };
+
+static int rdrand_init(ENGINE *e)
+{ return 1; }
+
+static const char *engine_e_rdrand_id = "rdrand";
+static const char *engine_e_rdrand_name = "Intel RDRAND engine";
+
+static int bind_helper(ENGINE *e)
+ {
+ if (!ENGINE_set_id(e, engine_e_rdrand_id) ||
+ !ENGINE_set_name(e, engine_e_rdrand_name) ||
+ !ENGINE_set_init_function(e, rdrand_init) ||
+ !ENGINE_set_RAND(e, &rdrand_meth) )
+ return 0;
+
+ return 1;
+ }
+
+static ENGINE *ENGINE_rdrand(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!bind_helper(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void ENGINE_load_rdrand (void)
+ {
+ extern unsigned int OPENSSL_ia32cap_P[];
+
+ if (OPENSSL_ia32cap_P[1] & (1<<(62-32)))
+ {
+ ENGINE *toadd = ENGINE_rdrand();
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ ENGINE_free(toadd);
+ ERR_clear_error();
+ }
+ }
+#else
+void ENGINE_load_rdrand (void) {}
+#endif
diff --git a/crypto/engine/eng_rsax.c b/crypto/engine/eng_rsax.c
new file mode 100644
index 0000000..96e6347
--- /dev/null
+++ b/crypto/engine/eng_rsax.c
@@ -0,0 +1,668 @@
+/* crypto/engine/eng_rsax.c */
+/* Copyright (c) 2010-2010 Intel Corp.
+ * Author: Vinodh.Gopal@intel.com
+ * Jim Guilford
+ * Erdinc.Ozturk@intel.com
+ * Maxim.Perminov@intel.com
+ * Ying.Huang@intel.com
+ *
+ * More information about algorithm used can be found at:
+ * http://www.cse.buffalo.edu/srds2009/escs2009_submission_Gopal.pdf
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ */
+
+#include <openssl/opensslconf.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/crypto.h>
+#include <openssl/buffer.h>
+#include <openssl/engine.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#include <openssl/bn.h>
+#include <openssl/err.h>
+
+/* RSAX is available **ONLY* on x86_64 CPUs */
+#undef COMPILE_RSAX
+
+#if (defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined (_M_X64)) && !defined(OPENSSL_NO_ASM)
+#define COMPILE_RSAX
+static ENGINE *ENGINE_rsax (void);
+#endif
+
+void ENGINE_load_rsax (void)
+ {
+/* On non-x86 CPUs it just returns. */
+#ifdef COMPILE_RSAX
+ ENGINE *toadd = ENGINE_rsax();
+ if(!toadd) return;
+ ENGINE_add(toadd);
+ ENGINE_free(toadd);
+ ERR_clear_error();
+#endif
+ }
+
+#ifdef COMPILE_RSAX
+#define E_RSAX_LIB_NAME "rsax engine"
+
+static int e_rsax_destroy(ENGINE *e);
+static int e_rsax_init(ENGINE *e);
+static int e_rsax_finish(ENGINE *e);
+static int e_rsax_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
+
+#ifndef OPENSSL_NO_RSA
+/* RSA stuff */
+static int e_rsax_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+static int e_rsax_rsa_finish(RSA *r);
+#endif
+
+static const ENGINE_CMD_DEFN e_rsax_cmd_defns[] = {
+ {0, NULL, NULL, 0}
+ };
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD e_rsax_rsa =
+ {
+ "Intel RSA-X method",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ e_rsax_rsa_mod_exp,
+ NULL,
+ NULL,
+ e_rsax_rsa_finish,
+ RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE,
+ NULL,
+ NULL,
+ NULL
+ };
+#endif
+
+/* Constants used when creating the ENGINE */
+static const char *engine_e_rsax_id = "rsax";
+static const char *engine_e_rsax_name = "RSAX engine support";
+
+/* This internal function is used by ENGINE_rsax() */
+static int bind_helper(ENGINE *e)
+ {
+#ifndef OPENSSL_NO_RSA
+ const RSA_METHOD *meth1;
+#endif
+ if(!ENGINE_set_id(e, engine_e_rsax_id) ||
+ !ENGINE_set_name(e, engine_e_rsax_name) ||
+#ifndef OPENSSL_NO_RSA
+ !ENGINE_set_RSA(e, &e_rsax_rsa) ||
+#endif
+ !ENGINE_set_destroy_function(e, e_rsax_destroy) ||
+ !ENGINE_set_init_function(e, e_rsax_init) ||
+ !ENGINE_set_finish_function(e, e_rsax_finish) ||
+ !ENGINE_set_ctrl_function(e, e_rsax_ctrl) ||
+ !ENGINE_set_cmd_defns(e, e_rsax_cmd_defns))
+ return 0;
+
+#ifndef OPENSSL_NO_RSA
+ meth1 = RSA_PKCS1_SSLeay();
+ e_rsax_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+ e_rsax_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+ e_rsax_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+ e_rsax_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+ e_rsax_rsa.bn_mod_exp = meth1->bn_mod_exp;
+#endif
+ return 1;
+ }
+
+static ENGINE *ENGINE_rsax(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!bind_helper(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+#ifndef OPENSSL_NO_RSA
+/* Used to attach our own key-data to an RSA structure */
+static int rsax_ex_data_idx = -1;
+#endif
+
+static int e_rsax_destroy(ENGINE *e)
+ {
+ return 1;
+ }
+
+/* (de)initialisation functions. */
+static int e_rsax_init(ENGINE *e)
+ {
+#ifndef OPENSSL_NO_RSA
+ if (rsax_ex_data_idx == -1)
+ rsax_ex_data_idx = RSA_get_ex_new_index(0,
+ NULL,
+ NULL, NULL, NULL);
+#endif
+ if (rsax_ex_data_idx == -1)
+ return 0;
+ return 1;
+ }
+
+static int e_rsax_finish(ENGINE *e)
+ {
+ return 1;
+ }
+
+static int e_rsax_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
+ {
+ int to_return = 1;
+
+ switch(cmd)
+ {
+ /* The command isn't understood by this engine */
+ default:
+ to_return = 0;
+ break;
+ }
+
+ return to_return;
+ }
+
+
+#ifndef OPENSSL_NO_RSA
+
+#ifdef _WIN32
+typedef unsigned __int64 UINT64;
+#else
+typedef unsigned long long UINT64;
+#endif
+typedef unsigned short UINT16;
+
+/* Table t is interleaved in the following manner:
+ * The order in memory is t[0][0], t[0][1], ..., t[0][7], t[1][0], ...
+ * A particular 512-bit value is stored in t[][index] rather than the more
+ * normal t[index][]; i.e. the qwords of a particular entry in t are not
+ * adjacent in memory
+ */
+
+/* Init BIGNUM b from the interleaved UINT64 array */
+static int interleaved_array_to_bn_512(BIGNUM* b, UINT64 *array);
+
+/* Extract array elements from BIGNUM b
+ * To set the whole array from b, call with n=8
+ */
+static int bn_extract_to_array_512(const BIGNUM* b, unsigned int n, UINT64 *array);
+
+struct mod_ctx_512 {
+ UINT64 t[8][8];
+ UINT64 m[8];
+ UINT64 m1[8]; /* 2^278 % m */
+ UINT64 m2[8]; /* 2^640 % m */
+ UINT64 k1[2]; /* (- 1/m) % 2^128 */
+};
+
+static int mod_exp_pre_compute_data_512(UINT64 *m, struct mod_ctx_512 *data);
+
+void mod_exp_512(UINT64 *result, /* 512 bits, 8 qwords */
+ UINT64 *g, /* 512 bits, 8 qwords */
+ UINT64 *exp, /* 512 bits, 8 qwords */
+ struct mod_ctx_512 *data);
+
+typedef struct st_e_rsax_mod_ctx
+{
+ UINT64 type;
+ union {
+ struct mod_ctx_512 b512;
+ } ctx;
+
+} E_RSAX_MOD_CTX;
+
+static E_RSAX_MOD_CTX *e_rsax_get_ctx(RSA *rsa, int idx, BIGNUM* m)
+{
+ E_RSAX_MOD_CTX *hptr;
+
+ if (idx < 0 || idx > 2)
+ return NULL;
+
+ hptr = RSA_get_ex_data(rsa, rsax_ex_data_idx);
+ if (!hptr) {
+ hptr = OPENSSL_malloc(3*sizeof(E_RSAX_MOD_CTX));
+ if (!hptr) return NULL;
+ hptr[2].type = hptr[1].type= hptr[0].type = 0;
+ RSA_set_ex_data(rsa, rsax_ex_data_idx, hptr);
+ }
+
+ if (hptr[idx].type == (UINT64)BN_num_bits(m))
+ return hptr+idx;
+
+ if (BN_num_bits(m) == 512) {
+ UINT64 _m[8];
+ bn_extract_to_array_512(m, 8, _m);
+ memset( &hptr[idx].ctx.b512, 0, sizeof(struct mod_ctx_512));
+ mod_exp_pre_compute_data_512(_m, &hptr[idx].ctx.b512);
+ }
+
+ hptr[idx].type = BN_num_bits(m);
+ return hptr+idx;
+}
+
+static int e_rsax_rsa_finish(RSA *rsa)
+ {
+ E_RSAX_MOD_CTX *hptr = RSA_get_ex_data(rsa, rsax_ex_data_idx);
+ if(hptr)
+ {
+ OPENSSL_free(hptr);
+ RSA_set_ex_data(rsa, rsax_ex_data_idx, NULL);
+ }
+ if (rsa->_method_mod_n)
+ BN_MONT_CTX_free(rsa->_method_mod_n);
+ if (rsa->_method_mod_p)
+ BN_MONT_CTX_free(rsa->_method_mod_p);
+ if (rsa->_method_mod_q)
+ BN_MONT_CTX_free(rsa->_method_mod_q);
+ return 1;
+ }
+
+
+static int e_rsax_bn_mod_exp(BIGNUM *r, const BIGNUM *g, const BIGNUM *e,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont, E_RSAX_MOD_CTX* rsax_mod_ctx )
+{
+ if (rsax_mod_ctx && BN_get_flags(e, BN_FLG_CONSTTIME) != 0) {
+ if (BN_num_bits(m) == 512) {
+ UINT64 _r[8];
+ UINT64 _g[8];
+ UINT64 _e[8];
+
+ /* Init the arrays from the BIGNUMs */
+ bn_extract_to_array_512(g, 8, _g);
+ bn_extract_to_array_512(e, 8, _e);
+
+ mod_exp_512(_r, _g, _e, &rsax_mod_ctx->ctx.b512);
+ /* Return the result in the BIGNUM */
+ interleaved_array_to_bn_512(r, _r);
+ return 1;
+ }
+ }
+
+ return BN_mod_exp_mont(r, g, e, m, ctx, in_mont);
+}
+
+/* Declares for the Intel CIAP 512-bit / CRT / 1024 bit RSA modular
+ * exponentiation routine precalculations and a structure to hold the
+ * necessary values. These files are meant to live in crypto/rsa/ in
+ * the target openssl.
+ */
+
+/*
+ * Local method: extracts a piece from a BIGNUM, to fit it into
+ * an array. Call with n=8 to extract an entire 512-bit BIGNUM
+ */
+static int bn_extract_to_array_512(const BIGNUM* b, unsigned int n, UINT64 *array)
+{
+ int i;
+ UINT64 tmp;
+ unsigned char bn_buff[64];
+ memset(bn_buff, 0, 64);
+ if (BN_num_bytes(b) > 64) {
+ printf ("Can't support this byte size\n");
+ return 0; }
+ if (BN_num_bytes(b)!=0) {
+ if (!BN_bn2bin(b, bn_buff+(64-BN_num_bytes(b)))) {
+ printf ("Error's in bn2bin\n");
+ /* We have to error, here */
+ return 0; } }
+ while (n-- > 0) {
+ array[n] = 0;
+ for (i=7; i>=0; i--) {
+ tmp = bn_buff[63-(n*8+i)];
+ array[n] |= tmp << (8*i); } }
+ return 1;
+}
+
+/* Init a 512-bit BIGNUM from the UINT64*_ (8 * 64) interleaved array */
+static int interleaved_array_to_bn_512(BIGNUM* b, UINT64 *array)
+{
+ unsigned char tmp[64];
+ int n=8;
+ int i;
+ while (n-- > 0) {
+ for (i = 7; i>=0; i--) {
+ tmp[63-(n*8+i)] = (unsigned char)(array[n]>>(8*i)); } }
+ BN_bin2bn(tmp, 64, b);
+ return 0;
+}
+
+
+/* The main 512bit precompute call */
+static int mod_exp_pre_compute_data_512(UINT64 *m, struct mod_ctx_512 *data)
+ {
+ BIGNUM two_768, two_640, two_128, two_512, tmp, _m, tmp2;
+
+ /* We need a BN_CTX for the modulo functions */
+ BN_CTX* ctx;
+ /* Some tmps */
+ UINT64 _t[8];
+ int i, j, ret = 0;
+
+ /* Init _m with m */
+ BN_init(&_m);
+ interleaved_array_to_bn_512(&_m, m);
+ memset(_t, 0, 64);
+
+ /* Inits */
+ BN_init(&two_768);
+ BN_init(&two_640);
+ BN_init(&two_128);
+ BN_init(&two_512);
+ BN_init(&tmp);
+ BN_init(&tmp2);
+
+ /* Create our context */
+ if ((ctx=BN_CTX_new()) == NULL) { goto err; }
+ BN_CTX_start(ctx);
+
+ /*
+ * For production, if you care, these only need to be set once,
+ * and may be made constants.
+ */
+ BN_lshift(&two_768, BN_value_one(), 768);
+ BN_lshift(&two_640, BN_value_one(), 640);
+ BN_lshift(&two_128, BN_value_one(), 128);
+ BN_lshift(&two_512, BN_value_one(), 512);
+
+ if (0 == (m[7] & 0x8000000000000000)) {
+ exit(1);
+ }
+ if (0 == (m[0] & 0x1)) { /* Odd modulus required for Mont */
+ exit(1);
+ }
+
+ /* Precompute m1 */
+ BN_mod(&tmp, &two_768, &_m, ctx);
+ if (!bn_extract_to_array_512(&tmp, 8, &data->m1[0])) {
+ goto err; }
+
+ /* Precompute m2 */
+ BN_mod(&tmp, &two_640, &_m, ctx);
+ if (!bn_extract_to_array_512(&tmp, 8, &data->m2[0])) {
+ goto err;
+ }
+
+ /*
+ * Precompute k1, a 128b number = ((-1)* m-1 ) mod 2128; k1 should
+ * be non-negative.
+ */
+ BN_mod_inverse(&tmp, &_m, &two_128, ctx);
+ if (!BN_is_zero(&tmp)) { BN_sub(&tmp, &two_128, &tmp); }
+ if (!bn_extract_to_array_512(&tmp, 2, &data->k1[0])) {
+ goto err; }
+
+ /* Precompute t */
+ for (i=0; i<8; i++) {
+ BN_zero(&tmp);
+ if (i & 1) { BN_add(&tmp, &two_512, &tmp); }
+ if (i & 2) { BN_add(&tmp, &two_512, &tmp); }
+ if (i & 4) { BN_add(&tmp, &two_640, &tmp); }
+
+ BN_nnmod(&tmp2, &tmp, &_m, ctx);
+ if (!bn_extract_to_array_512(&tmp2, 8, _t)) {
+ goto err; }
+ for (j=0; j<8; j++) data->t[j][i] = _t[j]; }
+
+ /* Precompute m */
+ for (i=0; i<8; i++) {
+ data->m[i] = m[i]; }
+
+ ret = 1;
+
+err:
+ /* Cleanup */
+ if (ctx != NULL) {
+ BN_CTX_end(ctx); BN_CTX_free(ctx); }
+ BN_free(&two_768);
+ BN_free(&two_640);
+ BN_free(&two_128);
+ BN_free(&two_512);
+ BN_free(&tmp);
+ BN_free(&tmp2);
+ BN_free(&_m);
+
+ return ret;
+}
+
+
+static int e_rsax_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+ {
+ BIGNUM *r1,*m1,*vrfy;
+ BIGNUM local_dmp1,local_dmq1,local_c,local_r1;
+ BIGNUM *dmp1,*dmq1,*c,*pr1;
+ int ret=0;
+
+ BN_CTX_start(ctx);
+ r1 = BN_CTX_get(ctx);
+ m1 = BN_CTX_get(ctx);
+ vrfy = BN_CTX_get(ctx);
+
+ {
+ BIGNUM local_p, local_q;
+ BIGNUM *p = NULL, *q = NULL;
+ int error = 0;
+
+ /* Make sure BN_mod_inverse in Montgomery
+ * intialization uses the BN_FLG_CONSTTIME flag
+ * (unless RSA_FLAG_NO_CONSTTIME is set)
+ */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ BN_init(&local_p);
+ p = &local_p;
+ BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
+
+ BN_init(&local_q);
+ q = &local_q;
+ BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
+ }
+ else
+ {
+ p = rsa->p;
+ q = rsa->q;
+ }
+
+ if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
+ {
+ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx))
+ error = 1;
+ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx))
+ error = 1;
+ }
+
+ /* clean up */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ BN_free(&local_p);
+ BN_free(&local_q);
+ }
+ if ( error )
+ goto err;
+ }
+
+ if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
+ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
+ goto err;
+
+ /* compute I mod q */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ c = &local_c;
+ BN_with_flags(c, I, BN_FLG_CONSTTIME);
+ if (!BN_mod(r1,c,rsa->q,ctx)) goto err;
+ }
+ else
+ {
+ if (!BN_mod(r1,I,rsa->q,ctx)) goto err;
+ }
+
+ /* compute r1^dmq1 mod q */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ dmq1 = &local_dmq1;
+ BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
+ }
+ else
+ dmq1 = rsa->dmq1;
+
+ if (!e_rsax_bn_mod_exp(m1,r1,dmq1,rsa->q,ctx,
+ rsa->_method_mod_q, e_rsax_get_ctx(rsa, 0, rsa->q) )) goto err;
+
+ /* compute I mod p */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ c = &local_c;
+ BN_with_flags(c, I, BN_FLG_CONSTTIME);
+ if (!BN_mod(r1,c,rsa->p,ctx)) goto err;
+ }
+ else
+ {
+ if (!BN_mod(r1,I,rsa->p,ctx)) goto err;
+ }
+
+ /* compute r1^dmp1 mod p */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ dmp1 = &local_dmp1;
+ BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
+ }
+ else
+ dmp1 = rsa->dmp1;
+
+ if (!e_rsax_bn_mod_exp(r0,r1,dmp1,rsa->p,ctx,
+ rsa->_method_mod_p, e_rsax_get_ctx(rsa, 1, rsa->p) )) goto err;
+
+ if (!BN_sub(r0,r0,m1)) goto err;
+ /* This will help stop the size of r0 increasing, which does
+ * affect the multiply if it optimised for a power of 2 size */
+ if (BN_is_negative(r0))
+ if (!BN_add(r0,r0,rsa->p)) goto err;
+
+ if (!BN_mul(r1,r0,rsa->iqmp,ctx)) goto err;
+
+ /* Turn BN_FLG_CONSTTIME flag on before division operation */
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ pr1 = &local_r1;
+ BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
+ }
+ else
+ pr1 = r1;
+ if (!BN_mod(r0,pr1,rsa->p,ctx)) goto err;
+
+ /* If p < q it is occasionally possible for the correction of
+ * adding 'p' if r0 is negative above to leave the result still
+ * negative. This can break the private key operations: the following
+ * second correction should *always* correct this rare occurrence.
+ * This will *never* happen with OpenSSL generated keys because
+ * they ensure p > q [steve]
+ */
+ if (BN_is_negative(r0))
+ if (!BN_add(r0,r0,rsa->p)) goto err;
+ if (!BN_mul(r1,r0,rsa->q,ctx)) goto err;
+ if (!BN_add(r0,r1,m1)) goto err;
+
+ if (rsa->e && rsa->n)
+ {
+ if (!e_rsax_bn_mod_exp(vrfy,r0,rsa->e,rsa->n,ctx,rsa->_method_mod_n, e_rsax_get_ctx(rsa, 2, rsa->n) ))
+ goto err;
+
+ /* If 'I' was greater than (or equal to) rsa->n, the operation
+ * will be equivalent to using 'I mod n'. However, the result of
+ * the verify will *always* be less than 'n' so we don't check
+ * for absolute equality, just congruency. */
+ if (!BN_sub(vrfy, vrfy, I)) goto err;
+ if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) goto err;
+ if (BN_is_negative(vrfy))
+ if (!BN_add(vrfy, vrfy, rsa->n)) goto err;
+ if (!BN_is_zero(vrfy))
+ {
+ /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
+ * miscalculated CRT output, just do a raw (slower)
+ * mod_exp and return that instead. */
+
+ BIGNUM local_d;
+ BIGNUM *d = NULL;
+
+ if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
+ {
+ d = &local_d;
+ BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
+ }
+ else
+ d = rsa->d;
+ if (!e_rsax_bn_mod_exp(r0,I,d,rsa->n,ctx,
+ rsa->_method_mod_n, e_rsax_get_ctx(rsa, 2, rsa->n) )) goto err;
+ }
+ }
+ ret=1;
+
+err:
+ BN_CTX_end(ctx);
+
+ return ret;
+ }
+#endif /* !OPENSSL_NO_RSA */
+#endif /* !COMPILE_RSAX */
diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c
new file mode 100644
index 0000000..4fde948
--- /dev/null
+++ b/crypto/engine/eng_table.c
@@ -0,0 +1,351 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include "eng_int.h"
+
+/* The type of the items in the table */
+typedef struct st_engine_pile
+ {
+ /* The 'nid' of this algorithm/mode */
+ int nid;
+ /* ENGINEs that implement this algorithm/mode. */
+ STACK_OF(ENGINE) *sk;
+ /* The default ENGINE to perform this algorithm/mode. */
+ ENGINE *funct;
+ /* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */
+ int uptodate;
+ } ENGINE_PILE;
+
+DECLARE_LHASH_OF(ENGINE_PILE);
+
+/* The type exposed in eng_int.h */
+struct st_engine_table
+ {
+ LHASH_OF(ENGINE_PILE) piles;
+ }; /* ENGINE_TABLE */
+
+
+typedef struct st_engine_pile_doall
+ {
+ engine_table_doall_cb *cb;
+ void *arg;
+ } ENGINE_PILE_DOALL;
+
+
+/* Global flags (ENGINE_TABLE_FLAG_***). */
+static unsigned int table_flags = 0;
+
+/* API function manipulating 'table_flags' */
+unsigned int ENGINE_get_table_flags(void)
+ {
+ return table_flags;
+ }
+
+void ENGINE_set_table_flags(unsigned int flags)
+ {
+ table_flags = flags;
+ }
+
+/* Internal functions for the "piles" hash table */
+static unsigned long engine_pile_hash(const ENGINE_PILE *c)
+ {
+ return c->nid;
+ }
+
+static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)
+ {
+ return a->nid - b->nid;
+ }
+static IMPLEMENT_LHASH_HASH_FN(engine_pile, ENGINE_PILE)
+static IMPLEMENT_LHASH_COMP_FN(engine_pile, ENGINE_PILE)
+
+static int int_table_check(ENGINE_TABLE **t, int create)
+ {
+ LHASH_OF(ENGINE_PILE) *lh;
+
+ if(*t) return 1;
+ if(!create) return 0;
+ if((lh = lh_ENGINE_PILE_new()) == NULL)
+ return 0;
+ *t = (ENGINE_TABLE *)lh;
+ return 1;
+ }
+
+/* Privately exposed (via eng_int.h) functions for adding and/or removing
+ * ENGINEs from the implementation table */
+int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
+ ENGINE *e, const int *nids, int num_nids, int setdefault)
+ {
+ int ret = 0, added = 0;
+ ENGINE_PILE tmplate, *fnd;
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(!(*table))
+ added = 1;
+ if(!int_table_check(table, 1))
+ goto end;
+ if(added)
+ /* The cleanup callback needs to be added */
+ engine_cleanup_add_first(cleanup);
+ while(num_nids--)
+ {
+ tmplate.nid = *nids;
+ fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
+ if(!fnd)
+ {
+ fnd = OPENSSL_malloc(sizeof(ENGINE_PILE));
+ if(!fnd) goto end;
+ fnd->uptodate = 1;
+ fnd->nid = *nids;
+ fnd->sk = sk_ENGINE_new_null();
+ if(!fnd->sk)
+ {
+ OPENSSL_free(fnd);
+ goto end;
+ }
+ fnd->funct = NULL;
+ (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd);
+ }
+ /* A registration shouldn't add duplciate entries */
+ (void)sk_ENGINE_delete_ptr(fnd->sk, e);
+ /* if 'setdefault', this ENGINE goes to the head of the list */
+ if(!sk_ENGINE_push(fnd->sk, e))
+ goto end;
+ /* "touch" this ENGINE_PILE */
+ fnd->uptodate = 0;
+ if(setdefault)
+ {
+ if(!engine_unlocked_init(e))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,
+ ENGINE_R_INIT_FAILED);
+ goto end;
+ }
+ if(fnd->funct)
+ engine_unlocked_finish(fnd->funct, 0);
+ fnd->funct = e;
+ fnd->uptodate = 1;
+ }
+ nids++;
+ }
+ ret = 1;
+end:
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return ret;
+ }
+static void int_unregister_cb_doall_arg(ENGINE_PILE *pile, ENGINE *e)
+ {
+ int n;
+ /* Iterate the 'c->sk' stack removing any occurance of 'e' */
+ while((n = sk_ENGINE_find(pile->sk, e)) >= 0)
+ {
+ (void)sk_ENGINE_delete(pile->sk, n);
+ pile->uptodate = 0;
+ }
+ if(pile->funct == e)
+ {
+ engine_unlocked_finish(e, 0);
+ pile->funct = NULL;
+ }
+ }
+static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb, ENGINE_PILE, ENGINE)
+
+void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(int_table_check(table, 0))
+ lh_ENGINE_PILE_doall_arg(&(*table)->piles,
+ LHASH_DOALL_ARG_FN(int_unregister_cb),
+ ENGINE, e);
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ }
+
+static void int_cleanup_cb_doall(ENGINE_PILE *p)
+ {
+ sk_ENGINE_free(p->sk);
+ if(p->funct)
+ engine_unlocked_finish(p->funct, 0);
+ OPENSSL_free(p);
+ }
+static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb, ENGINE_PILE)
+
+void engine_table_cleanup(ENGINE_TABLE **table)
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ if(*table)
+ {
+ lh_ENGINE_PILE_doall(&(*table)->piles,
+ LHASH_DOALL_FN(int_cleanup_cb));
+ lh_ENGINE_PILE_free(&(*table)->piles);
+ *table = NULL;
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ }
+
+/* return a functional reference for a given 'nid' */
+#ifndef ENGINE_TABLE_DEBUG
+ENGINE *engine_table_select(ENGINE_TABLE **table, int nid)
+#else
+ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l)
+#endif
+ {
+ ENGINE *ret = NULL;
+ ENGINE_PILE tmplate, *fnd=NULL;
+ int initres, loop = 0;
+
+ if(!(*table))
+ {
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
+ "registered!\n", f, l, nid);
+#endif
+ return NULL;
+ }
+ ERR_set_mark();
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ /* Check again inside the lock otherwise we could race against cleanup
+ * operations. But don't worry about a fprintf(stderr). */
+ if(!int_table_check(table, 0)) goto end;
+ tmplate.nid = nid;
+ fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
+ if(!fnd) goto end;
+ if(fnd->funct && engine_unlocked_init(fnd->funct))
+ {
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
+ "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
+#endif
+ ret = fnd->funct;
+ goto end;
+ }
+ if(fnd->uptodate)
+ {
+ ret = fnd->funct;
+ goto end;
+ }
+trynext:
+ ret = sk_ENGINE_value(fnd->sk, loop++);
+ if(!ret)
+ {
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
+ "registered implementations would initialise\n",
+ f, l, nid);
+#endif
+ goto end;
+ }
+ /* Try to initialise the ENGINE? */
+ if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))
+ initres = engine_unlocked_init(ret);
+ else
+ initres = 0;
+ if(initres)
+ {
+ /* Update 'funct' */
+ if((fnd->funct != ret) && engine_unlocked_init(ret))
+ {
+ /* If there was a previous default we release it. */
+ if(fnd->funct)
+ engine_unlocked_finish(fnd->funct, 0);
+ fnd->funct = ret;
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
+ "setting default to '%s'\n", f, l, nid, ret->id);
+#endif
+ }
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
+ "newly initialised '%s'\n", f, l, nid, ret->id);
+#endif
+ goto end;
+ }
+ goto trynext;
+end:
+ /* If it failed, it is unlikely to succeed again until some future
+ * registrations have taken place. In all cases, we cache. */
+ if(fnd) fnd->uptodate = 1;
+#ifdef ENGINE_TABLE_DEBUG
+ if(ret)
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
+ "ENGINE '%s'\n", f, l, nid, ret->id);
+ else
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
+ "'no matching ENGINE'\n", f, l, nid);
+#endif
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ /* Whatever happened, any failed init()s are not failures in this
+ * context, so clear our error state. */
+ ERR_pop_to_mark();
+ return ret;
+ }
+
+/* Table enumeration */
+
+static void int_cb_doall_arg(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall)
+ {
+ dall->cb(pile->nid, pile->sk, pile->funct, dall->arg);
+ }
+static IMPLEMENT_LHASH_DOALL_ARG_FN(int_cb, ENGINE_PILE,ENGINE_PILE_DOALL)
+
+void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb,
+ void *arg)
+ {
+ ENGINE_PILE_DOALL dall;
+ dall.cb = cb;
+ dall.arg = arg;
+ lh_ENGINE_PILE_doall_arg(&table->piles, LHASH_DOALL_ARG_FN(int_cb),
+ ENGINE_PILE_DOALL, &dall);
+ }
diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h
new file mode 100644
index 0000000..f8be497
--- /dev/null
+++ b/crypto/engine/engine.h
@@ -0,0 +1,842 @@
+/* openssl/engine.h */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_H
+#define HEADER_ENGINE_H
+
+#include <openssl/opensslconf.h>
+
+#ifdef OPENSSL_NO_ENGINE
+#error ENGINE is disabled.
+#endif
+
+#ifndef OPENSSL_NO_DEPRECATED
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#ifndef OPENSSL_NO_ECDH
+#include <openssl/ecdh.h>
+#endif
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/rand.h>
+#include <openssl/ui.h>
+#include <openssl/err.h>
+#endif
+
+#include <openssl/ossl_typ.h>
+#include <openssl/symhacks.h>
+
+#include <openssl/x509.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These flags are used to control combinations of algorithm (methods)
+ * by bitwise "OR"ing. */
+#define ENGINE_METHOD_RSA (unsigned int)0x0001
+#define ENGINE_METHOD_DSA (unsigned int)0x0002
+#define ENGINE_METHOD_DH (unsigned int)0x0004
+#define ENGINE_METHOD_RAND (unsigned int)0x0008
+#define ENGINE_METHOD_ECDH (unsigned int)0x0010
+#define ENGINE_METHOD_ECDSA (unsigned int)0x0020
+#define ENGINE_METHOD_CIPHERS (unsigned int)0x0040
+#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
+#define ENGINE_METHOD_STORE (unsigned int)0x0100
+#define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200
+#define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400
+/* Obvious all-or-nothing cases. */
+#define ENGINE_METHOD_ALL (unsigned int)0xFFFF
+#define ENGINE_METHOD_NONE (unsigned int)0x0000
+
+/* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used
+ * internally to control registration of ENGINE implementations, and can be set
+ * by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to
+ * initialise registered ENGINEs if they are not already initialised. */
+#define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001
+
+/* ENGINE flags that can be set by ENGINE_set_flags(). */
+/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ /* Not used */
+
+/* This flag is for ENGINEs that wish to handle the various 'CMD'-related
+ * control commands on their own. Without this flag, ENGINE_ctrl() handles these
+ * control commands on behalf of the ENGINE using their "cmd_defns" data. */
+#define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002
+
+/* This flag is for ENGINEs who return new duplicate structures when found via
+ * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl()
+ * commands are called in sequence as part of some stateful process like
+ * key-generation setup and execution), it can set this flag - then each attempt
+ * to obtain the ENGINE will result in it being copied into a new structure.
+ * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments
+ * the existing ENGINE's structural reference count. */
+#define ENGINE_FLAGS_BY_ID_COPY (int)0x0004
+
+/* This flag if for an ENGINE that does not want its methods registered as
+ * part of ENGINE_register_all_complete() for example if the methods are
+ * not usable as default methods.
+ */
+
+#define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008
+
+/* ENGINEs can support their own command types, and these flags are used in
+ * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each
+ * command expects. Currently only numeric and string input is supported. If a
+ * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options,
+ * then it is regarded as an "internal" control command - and not for use in
+ * config setting situations. As such, they're not available to the
+ * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to
+ * this list of 'command types' should be reflected carefully in
+ * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */
+
+/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001
+/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to
+ * ENGINE_ctrl) */
+#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002
+/* Indicates that the control command takes *no* input. Ie. the control command
+ * is unparameterised. */
+#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004
+/* Indicates that the control command is internal. This control command won't
+ * be shown in any output, and is only usable through the ENGINE_ctrl_cmd()
+ * function. */
+#define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008
+
+/* NB: These 3 control commands are deprecated and should not be used. ENGINEs
+ * relying on these commands should compile conditional support for
+ * compatibility (eg. if these symbols are defined) but should also migrate the
+ * same functionality to their own ENGINE-specific control functions that can be
+ * "discovered" by calling applications. The fact these control commands
+ * wouldn't be "executable" (ie. usable by text-based config) doesn't change the
+ * fact that application code can find and use them without requiring per-ENGINE
+ * hacking. */
+
+/* These flags are used to tell the ctrl function what should be done.
+ * All command numbers are shared between all engines, even if some don't
+ * make sense to some engines. In such a case, they do nothing but return
+ * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */
+#define ENGINE_CTRL_SET_LOGSTREAM 1
+#define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2
+#define ENGINE_CTRL_HUP 3 /* Close and reinitialise any
+ handles/connections etc. */
+#define ENGINE_CTRL_SET_USER_INTERFACE 4 /* Alternative to callback */
+#define ENGINE_CTRL_SET_CALLBACK_DATA 5 /* User-specific data, used
+ when calling the password
+ callback and the user
+ interface */
+#define ENGINE_CTRL_LOAD_CONFIGURATION 6 /* Load a configuration, given
+ a string that represents a
+ file name or so */
+#define ENGINE_CTRL_LOAD_SECTION 7 /* Load data from a given
+ section in the already loaded
+ configuration */
+
+/* These control commands allow an application to deal with an arbitrary engine
+ * in a dynamic way. Warn: Negative return values indicate errors FOR THESE
+ * COMMANDS because zero is used to indicate 'end-of-list'. Other commands,
+ * including ENGINE-specific command types, return zero for an error.
+ *
+ * An ENGINE can choose to implement these ctrl functions, and can internally
+ * manage things however it chooses - it does so by setting the
+ * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the
+ * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns
+ * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl()
+ * handler need only implement its own commands - the above "meta" commands will
+ * be taken care of. */
+
+/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then
+ * all the remaining control commands will return failure, so it is worth
+ * checking this first if the caller is trying to "discover" the engine's
+ * capabilities and doesn't want errors generated unnecessarily. */
+#define ENGINE_CTRL_HAS_CTRL_FUNCTION 10
+/* Returns a positive command number for the first command supported by the
+ * engine. Returns zero if no ctrl commands are supported. */
+#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11
+/* The 'long' argument specifies a command implemented by the engine, and the
+ * return value is the next command supported, or zero if there are no more. */
+#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12
+/* The 'void*' argument is a command name (cast from 'const char *'), and the
+ * return value is the command that corresponds to it. */
+#define ENGINE_CTRL_GET_CMD_FROM_NAME 13
+/* The next two allow a command to be converted into its corresponding string
+ * form. In each case, the 'long' argument supplies the command. In the NAME_LEN
+ * case, the return value is the length of the command name (not counting a
+ * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer
+ * large enough, and it will be populated with the name of the command (WITH a
+ * trailing EOL). */
+#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14
+#define ENGINE_CTRL_GET_NAME_FROM_CMD 15
+/* The next two are similar but give a "short description" of a command. */
+#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16
+#define ENGINE_CTRL_GET_DESC_FROM_CMD 17
+/* With this command, the return value is the OR'd combination of
+ * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given
+ * engine-specific ctrl command expects. */
+#define ENGINE_CTRL_GET_CMD_FLAGS 18
+
+/* ENGINE implementations should start the numbering of their own control
+ * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */
+#define ENGINE_CMD_BASE 200
+
+/* NB: These 2 nCipher "chil" control commands are deprecated, and their
+ * functionality is now available through ENGINE-specific control commands
+ * (exposed through the above-mentioned 'CMD'-handling). Code using these 2
+ * commands should be migrated to the more general command handling before these
+ * are removed. */
+
+/* Flags specific to the nCipher "chil" engine */
+#define ENGINE_CTRL_CHIL_SET_FORKCHECK 100
+ /* Depending on the value of the (long)i argument, this sets or
+ * unsets the SimpleForkCheck flag in the CHIL API to enable or
+ * disable checking and workarounds for applications that fork().
+ */
+#define ENGINE_CTRL_CHIL_NO_LOCKING 101
+ /* This prevents the initialisation function from providing mutex
+ * callbacks to the nCipher library. */
+
+/* If an ENGINE supports its own specific control commands and wishes the
+ * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its
+ * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries
+ * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that
+ * supports the stated commands (ie. the "cmd_num" entries as described by the
+ * array). NB: The array must be ordered in increasing order of cmd_num.
+ * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set
+ * to zero and/or cmd_name set to NULL. */
+typedef struct ENGINE_CMD_DEFN_st
+ {
+ unsigned int cmd_num; /* The command number */
+ const char *cmd_name; /* The command name itself */
+ const char *cmd_desc; /* A short description of the command */
+ unsigned int cmd_flags; /* The input the command expects */
+ } ENGINE_CMD_DEFN;
+
+/* Generic function pointer */
+typedef int (*ENGINE_GEN_FUNC_PTR)(void);
+/* Generic function pointer taking no arguments */
+typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *);
+/* Specific control function pointer */
+typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, void (*f)(void));
+/* Generic load_key function pointer */
+typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *,
+ UI_METHOD *ui_method, void *callback_data);
+typedef int (*ENGINE_SSL_CLIENT_CERT_PTR)(ENGINE *, SSL *ssl,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
+ STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data);
+/* These callback types are for an ENGINE's handler for cipher and digest logic.
+ * These handlers have these prototypes;
+ * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid);
+ * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid);
+ * Looking at how to implement these handlers in the case of cipher support, if
+ * the framework wants the EVP_CIPHER for 'nid', it will call;
+ * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure)
+ * If the framework wants a list of supported 'nid's, it will call;
+ * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error)
+ */
+/* Returns to a pointer to the array of supported cipher 'nid's. If the second
+ * parameter is non-NULL it is set to the size of the returned array. */
+typedef int (*ENGINE_CIPHERS_PTR)(ENGINE *, const EVP_CIPHER **, const int **, int);
+typedef int (*ENGINE_DIGESTS_PTR)(ENGINE *, const EVP_MD **, const int **, int);
+typedef int (*ENGINE_PKEY_METHS_PTR)(ENGINE *, EVP_PKEY_METHOD **, const int **, int);
+typedef int (*ENGINE_PKEY_ASN1_METHS_PTR)(ENGINE *, EVP_PKEY_ASN1_METHOD **, const int **, int);
+/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE
+ * structures where the pointers have a "structural reference". This means that
+ * their reference is to allowed access to the structure but it does not imply
+ * that the structure is functional. To simply increment or decrement the
+ * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not
+ * required when iterating using ENGINE_get_next as it will automatically
+ * decrement the structural reference count of the "current" ENGINE and
+ * increment the structural reference count of the ENGINE it returns (unless it
+ * is NULL). */
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void);
+ENGINE *ENGINE_get_last(void);
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e);
+ENGINE *ENGINE_get_prev(ENGINE *e);
+/* Add another "ENGINE" type into the array. */
+int ENGINE_add(ENGINE *e);
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e);
+/* Retrieve an engine from the list by its unique "id" value. */
+ENGINE *ENGINE_by_id(const char *id);
+/* Add all the built-in engines. */
+void ENGINE_load_openssl(void);
+void ENGINE_load_dynamic(void);
+#ifndef OPENSSL_NO_STATIC_ENGINE
+void ENGINE_load_4758cca(void);
+void ENGINE_load_aep(void);
+void ENGINE_load_atalla(void);
+void ENGINE_load_chil(void);
+void ENGINE_load_cswift(void);
+void ENGINE_load_nuron(void);
+void ENGINE_load_sureware(void);
+void ENGINE_load_ubsec(void);
+void ENGINE_load_padlock(void);
+void ENGINE_load_capi(void);
+#ifndef OPENSSL_NO_GMP
+void ENGINE_load_gmp(void);
+#endif
+#ifndef OPENSSL_NO_GOST
+void ENGINE_load_gost(void);
+#endif
+#endif
+void ENGINE_load_cryptodev(void);
+void ENGINE_load_rsax(void);
+void ENGINE_load_rdrand(void);
+void ENGINE_load_builtin_engines(void);
+
+/* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation
+ * "registry" handling. */
+unsigned int ENGINE_get_table_flags(void);
+void ENGINE_set_table_flags(unsigned int flags);
+
+/* Manage registration of ENGINEs per "table". For each type, there are 3
+ * functions;
+ * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one)
+ * ENGINE_unregister_***(e) - unregister the implementation from 'e'
+ * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list
+ * Cleanup is automatically registered from each table when required, so
+ * ENGINE_cleanup() will reverse any "register" operations. */
+
+int ENGINE_register_RSA(ENGINE *e);
+void ENGINE_unregister_RSA(ENGINE *e);
+void ENGINE_register_all_RSA(void);
+
+int ENGINE_register_DSA(ENGINE *e);
+void ENGINE_unregister_DSA(ENGINE *e);
+void ENGINE_register_all_DSA(void);
+
+int ENGINE_register_ECDH(ENGINE *e);
+void ENGINE_unregister_ECDH(ENGINE *e);
+void ENGINE_register_all_ECDH(void);
+
+int ENGINE_register_ECDSA(ENGINE *e);
+void ENGINE_unregister_ECDSA(ENGINE *e);
+void ENGINE_register_all_ECDSA(void);
+
+int ENGINE_register_DH(ENGINE *e);
+void ENGINE_unregister_DH(ENGINE *e);
+void ENGINE_register_all_DH(void);
+
+int ENGINE_register_RAND(ENGINE *e);
+void ENGINE_unregister_RAND(ENGINE *e);
+void ENGINE_register_all_RAND(void);
+
+int ENGINE_register_STORE(ENGINE *e);
+void ENGINE_unregister_STORE(ENGINE *e);
+void ENGINE_register_all_STORE(void);
+
+int ENGINE_register_ciphers(ENGINE *e);
+void ENGINE_unregister_ciphers(ENGINE *e);
+void ENGINE_register_all_ciphers(void);
+
+int ENGINE_register_digests(ENGINE *e);
+void ENGINE_unregister_digests(ENGINE *e);
+void ENGINE_register_all_digests(void);
+
+int ENGINE_register_pkey_meths(ENGINE *e);
+void ENGINE_unregister_pkey_meths(ENGINE *e);
+void ENGINE_register_all_pkey_meths(void);
+
+int ENGINE_register_pkey_asn1_meths(ENGINE *e);
+void ENGINE_unregister_pkey_asn1_meths(ENGINE *e);
+void ENGINE_register_all_pkey_asn1_meths(void);
+
+/* These functions register all support from the above categories. Note, use of
+ * these functions can result in static linkage of code your application may not
+ * need. If you only need a subset of functionality, consider using more
+ * selective initialisation. */
+int ENGINE_register_complete(ENGINE *e);
+int ENGINE_register_all_complete(void);
+
+/* Send parametrised control commands to the engine. The possibilities to send
+ * down an integer, a pointer to data or a function pointer are provided. Any of
+ * the parameters may or may not be NULL, depending on the command number. In
+ * actuality, this function only requires a structural (rather than functional)
+ * reference to an engine, but many control commands may require the engine be
+ * functional. The caller should be aware of trying commands that require an
+ * operational ENGINE, and only use functional references in such situations. */
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
+
+/* This function tests if an ENGINE-specific command is usable as a "setting".
+ * Eg. in an application's config file that gets processed through
+ * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to
+ * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd);
+
+/* This function works like ENGINE_ctrl() with the exception of taking a
+ * command name instead of a command number, and can handle optional commands.
+ * See the comment on ENGINE_ctrl_cmd_string() for an explanation on how to
+ * use the cmd_name and cmd_optional. */
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+ long i, void *p, void (*f)(void), int cmd_optional);
+
+/* This function passes a command-name and argument to an ENGINE. The cmd_name
+ * is converted to a command number and the control command is called using
+ * 'arg' as an argument (unless the ENGINE doesn't support such a command, in
+ * which case no control command is called). The command is checked for input
+ * flags, and if necessary the argument will be converted to a numeric value. If
+ * cmd_optional is non-zero, then if the ENGINE doesn't support the given
+ * cmd_name the return value will be success anyway. This function is intended
+ * for applications to use so that users (or config files) can supply
+ * engine-specific config data to the ENGINE at run-time to control behaviour of
+ * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl()
+ * functions that return data, deal with binary data, or that are otherwise
+ * supposed to be used directly through ENGINE_ctrl() in application code. Any
+ * "return" data from an ENGINE_ctrl() operation in this function will be lost -
+ * the return value is interpreted as failure if the return value is zero,
+ * success otherwise, and this function returns a boolean value as a result. In
+ * other words, vendors of 'ENGINE'-enabled devices should write ENGINE
+ * implementations with parameterisations that work in this scheme, so that
+ * compliant ENGINE-based applications can work consistently with the same
+ * configuration for the same ENGINE-enabled devices, across applications. */
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional);
+
+/* These functions are useful for manufacturing new ENGINE structures. They
+ * don't address reference counting at all - one uses them to populate an ENGINE
+ * structure with personalised implementations of things prior to using it
+ * directly or adding it to the builtin ENGINE list in OpenSSL. These are also
+ * here so that the ENGINE structure doesn't have to be exposed and break binary
+ * compatibility! */
+ENGINE *ENGINE_new(void);
+int ENGINE_free(ENGINE *e);
+int ENGINE_up_ref(ENGINE *e);
+int ENGINE_set_id(ENGINE *e, const char *id);
+int ENGINE_set_name(ENGINE *e, const char *name);
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth);
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth);
+int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth);
+int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth);
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth);
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth);
+int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth);
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f);
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f);
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f);
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f);
+int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f);
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f);
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+ ENGINE_SSL_CLIENT_CERT_PTR loadssl_f);
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f);
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f);
+int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f);
+int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f);
+int ENGINE_set_flags(ENGINE *e, int flags);
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns);
+/* These functions allow control over any per-structure ENGINE data. */
+int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg);
+void *ENGINE_get_ex_data(const ENGINE *e, int idx);
+
+/* This function cleans up anything that needs it. Eg. the ENGINE_add() function
+ * automatically ensures the list cleanup function is registered to be called
+ * from ENGINE_cleanup(). Similarly, all ENGINE_register_*** functions ensure
+ * ENGINE_cleanup() will clean up after them. */
+void ENGINE_cleanup(void);
+
+/* These return values from within the ENGINE structure. These can be useful
+ * with functional references as well as structural references - it depends
+ * which you obtained. Using the result for functional purposes if you only
+ * obtained a structural reference may be problematic! */
+const char *ENGINE_get_id(const ENGINE *e);
+const char *ENGINE_get_name(const ENGINE *e);
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e);
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e);
+const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e);
+const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e);
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e);
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e);
+const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e);
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e);
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e);
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e);
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e);
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e);
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e);
+ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e);
+ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e);
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid);
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid);
+const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid);
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid);
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
+ const char *str, int len);
+const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
+ const char *str, int len);
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e);
+int ENGINE_get_flags(const ENGINE *e);
+
+/* FUNCTIONAL functions. These functions deal with ENGINE structures
+ * that have (or will) be initialised for use. Broadly speaking, the
+ * structural functions are useful for iterating the list of available
+ * engine types, creating new engine types, and other "list" operations.
+ * These functions actually deal with ENGINEs that are to be used. As
+ * such these functions can fail (if applicable) when particular
+ * engines are unavailable - eg. if a hardware accelerator is not
+ * attached or not functioning correctly. Each ENGINE has 2 reference
+ * counts; structural and functional. Every time a functional reference
+ * is obtained or released, a corresponding structural reference is
+ * automatically obtained or released too. */
+
+/* Initialise a engine type for use (or up its reference count if it's
+ * already in use). This will fail if the engine is not currently
+ * operational and cannot initialise. */
+int ENGINE_init(ENGINE *e);
+/* Free a functional reference to a engine type. This does not require
+ * a corresponding call to ENGINE_free as it also releases a structural
+ * reference. */
+int ENGINE_finish(ENGINE *e);
+
+/* The following functions handle keys that are stored in some secondary
+ * location, handled by the engine. The storage may be on a card or
+ * whatever. */
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data);
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey,
+ STACK_OF(X509) **pother,
+ UI_METHOD *ui_method, void *callback_data);
+
+/* This returns a pointer for the current ENGINE structure that
+ * is (by default) performing any RSA operations. The value returned
+ * is an incremented reference, so it should be free'd (ENGINE_finish)
+ * before it is discarded. */
+ENGINE *ENGINE_get_default_RSA(void);
+/* Same for the other "methods" */
+ENGINE *ENGINE_get_default_DSA(void);
+ENGINE *ENGINE_get_default_ECDH(void);
+ENGINE *ENGINE_get_default_ECDSA(void);
+ENGINE *ENGINE_get_default_DH(void);
+ENGINE *ENGINE_get_default_RAND(void);
+/* These functions can be used to get a functional reference to perform
+ * ciphering or digesting corresponding to "nid". */
+ENGINE *ENGINE_get_cipher_engine(int nid);
+ENGINE *ENGINE_get_digest_engine(int nid);
+ENGINE *ENGINE_get_pkey_meth_engine(int nid);
+ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid);
+
+/* This sets a new default ENGINE structure for performing RSA
+ * operations. If the result is non-zero (success) then the ENGINE
+ * structure will have had its reference count up'd so the caller
+ * should still free their own reference 'e'. */
+int ENGINE_set_default_RSA(ENGINE *e);
+int ENGINE_set_default_string(ENGINE *e, const char *def_list);
+/* Same for the other "methods" */
+int ENGINE_set_default_DSA(ENGINE *e);
+int ENGINE_set_default_ECDH(ENGINE *e);
+int ENGINE_set_default_ECDSA(ENGINE *e);
+int ENGINE_set_default_DH(ENGINE *e);
+int ENGINE_set_default_RAND(ENGINE *e);
+int ENGINE_set_default_ciphers(ENGINE *e);
+int ENGINE_set_default_digests(ENGINE *e);
+int ENGINE_set_default_pkey_meths(ENGINE *e);
+int ENGINE_set_default_pkey_asn1_meths(ENGINE *e);
+
+/* The combination "set" - the flags are bitwise "OR"d from the
+ * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()"
+ * function, this function can result in unnecessary static linkage. If your
+ * application requires only specific functionality, consider using more
+ * selective functions. */
+int ENGINE_set_default(ENGINE *e, unsigned int flags);
+
+void ENGINE_add_conf_module(void);
+
+/* Deprecated functions ... */
+/* int ENGINE_clear_defaults(void); */
+
+/**************************/
+/* DYNAMIC ENGINE SUPPORT */
+/**************************/
+
+/* Binary/behaviour compatibility levels */
+#define OSSL_DYNAMIC_VERSION (unsigned long)0x00020000
+/* Binary versions older than this are too old for us (whether we're a loader or
+ * a loadee) */
+#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00020000
+
+/* When compiling an ENGINE entirely as an external shared library, loadable by
+ * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
+ * type provides the calling application's (or library's) error functionality
+ * and memory management function pointers to the loaded library. These should
+ * be used/set in the loaded library code so that the loading application's
+ * 'state' will be used/changed in all operations. The 'static_state' pointer
+ * allows the loaded library to know if it shares the same static data as the
+ * calling application (or library), and thus whether these callbacks need to be
+ * set or not. */
+typedef void *(*dyn_MEM_malloc_cb)(size_t);
+typedef void *(*dyn_MEM_realloc_cb)(void *, size_t);
+typedef void (*dyn_MEM_free_cb)(void *);
+typedef struct st_dynamic_MEM_fns {
+ dyn_MEM_malloc_cb malloc_cb;
+ dyn_MEM_realloc_cb realloc_cb;
+ dyn_MEM_free_cb free_cb;
+ } dynamic_MEM_fns;
+/* FIXME: Perhaps the memory and locking code (crypto.h) should declare and use
+ * these types so we (and any other dependant code) can simplify a bit?? */
+typedef void (*dyn_lock_locking_cb)(int,int,const char *,int);
+typedef int (*dyn_lock_add_lock_cb)(int*,int,int,const char *,int);
+typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb)(
+ const char *,int);
+typedef void (*dyn_dynlock_lock_cb)(int,struct CRYPTO_dynlock_value *,
+ const char *,int);
+typedef void (*dyn_dynlock_destroy_cb)(struct CRYPTO_dynlock_value *,
+ const char *,int);
+typedef struct st_dynamic_LOCK_fns {
+ dyn_lock_locking_cb lock_locking_cb;
+ dyn_lock_add_lock_cb lock_add_lock_cb;
+ dyn_dynlock_create_cb dynlock_create_cb;
+ dyn_dynlock_lock_cb dynlock_lock_cb;
+ dyn_dynlock_destroy_cb dynlock_destroy_cb;
+ } dynamic_LOCK_fns;
+/* The top-level structure */
+typedef struct st_dynamic_fns {
+ void *static_state;
+ const ERR_FNS *err_fns;
+ const CRYPTO_EX_DATA_IMPL *ex_data_fns;
+ dynamic_MEM_fns mem_fns;
+ dynamic_LOCK_fns lock_fns;
+ } dynamic_fns;
+
+/* The version checking function should be of this prototype. NB: The
+ * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code.
+ * If this function returns zero, it indicates a (potential) version
+ * incompatibility and the loaded library doesn't believe it can proceed.
+ * Otherwise, the returned value is the (latest) version supported by the
+ * loading library. The loader may still decide that the loaded code's version
+ * is unsatisfactory and could veto the load. The function is expected to
+ * be implemented with the symbol name "v_check", and a default implementation
+ * can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */
+typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version);
+#define IMPLEMENT_DYNAMIC_CHECK_FN() \
+ OPENSSL_EXPORT unsigned long v_check(unsigned long v); \
+ OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
+ if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
+ return 0; }
+
+/* This function is passed the ENGINE structure to initialise with its own
+ * function and command settings. It should not adjust the structural or
+ * functional reference counts. If this function returns zero, (a) the load will
+ * be aborted, (b) the previous ENGINE state will be memcpy'd back onto the
+ * structure, and (c) the shared library will be unloaded. So implementations
+ * should do their own internal cleanup in failure circumstances otherwise they
+ * could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that
+ * the loader is looking for. If this is NULL, the shared library can choose to
+ * return failure or to initialise a 'default' ENGINE. If non-NULL, the shared
+ * library must initialise only an ENGINE matching the passed 'id'. The function
+ * is expected to be implemented with the symbol name "bind_engine". A standard
+ * implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where
+ * the parameter 'fn' is a callback function that populates the ENGINE structure
+ * and returns an int value (zero for failure). 'fn' should have prototype;
+ * [static] int fn(ENGINE *e, const char *id); */
+typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
+ const dynamic_fns *fns);
+#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
+ OPENSSL_EXPORT \
+ int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \
+ OPENSSL_EXPORT \
+ int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
+ if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
+ if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
+ fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
+ return 0; \
+ CRYPTO_set_locking_callback(fns->lock_fns.lock_locking_cb); \
+ CRYPTO_set_add_lock_callback(fns->lock_fns.lock_add_lock_cb); \
+ CRYPTO_set_dynlock_create_callback(fns->lock_fns.dynlock_create_cb); \
+ CRYPTO_set_dynlock_lock_callback(fns->lock_fns.dynlock_lock_cb); \
+ CRYPTO_set_dynlock_destroy_callback(fns->lock_fns.dynlock_destroy_cb); \
+ if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
+ return 0; \
+ if(!ERR_set_implementation(fns->err_fns)) return 0; \
+ skip_cbs: \
+ if(!fn(e,id)) return 0; \
+ return 1; }
+
+/* If the loading application (or library) and the loaded ENGINE library share
+ * the same static data (eg. they're both dynamically linked to the same
+ * libcrypto.so) we need a way to avoid trying to set system callbacks - this
+ * would fail, and for the same reason that it's unnecessary to try. If the
+ * loaded ENGINE has (or gets from through the loader) its own copy of the
+ * libcrypto static data, we will need to set the callbacks. The easiest way to
+ * detect this is to have a function that returns a pointer to some static data
+ * and let the loading application and loaded ENGINE compare their respective
+ * values. */
+void *ENGINE_get_static_state(void);
+
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)
+void ENGINE_setup_bsd_cryptodev(void);
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_ENGINE_strings(void);
+
+/* Error codes for the ENGINE functions. */
+
+/* Function codes. */
+#define ENGINE_F_DYNAMIC_CTRL 180
+#define ENGINE_F_DYNAMIC_GET_DATA_CTX 181
+#define ENGINE_F_DYNAMIC_LOAD 182
+#define ENGINE_F_DYNAMIC_SET_DATA_CTX 183
+#define ENGINE_F_ENGINE_ADD 105
+#define ENGINE_F_ENGINE_BY_ID 106
+#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170
+#define ENGINE_F_ENGINE_CTRL 142
+#define ENGINE_F_ENGINE_CTRL_CMD 178
+#define ENGINE_F_ENGINE_CTRL_CMD_STRING 171
+#define ENGINE_F_ENGINE_FINISH 107
+#define ENGINE_F_ENGINE_FREE_UTIL 108
+#define ENGINE_F_ENGINE_GET_CIPHER 185
+#define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177
+#define ENGINE_F_ENGINE_GET_DIGEST 186
+#define ENGINE_F_ENGINE_GET_NEXT 115
+#define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 193
+#define ENGINE_F_ENGINE_GET_PKEY_METH 192
+#define ENGINE_F_ENGINE_GET_PREV 116
+#define ENGINE_F_ENGINE_INIT 119
+#define ENGINE_F_ENGINE_LIST_ADD 120
+#define ENGINE_F_ENGINE_LIST_REMOVE 121
+#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150
+#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151
+#define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 194
+#define ENGINE_F_ENGINE_NEW 122
+#define ENGINE_F_ENGINE_REMOVE 123
+#define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189
+#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126
+#define ENGINE_F_ENGINE_SET_ID 129
+#define ENGINE_F_ENGINE_SET_NAME 130
+#define ENGINE_F_ENGINE_TABLE_REGISTER 184
+#define ENGINE_F_ENGINE_UNLOAD_KEY 152
+#define ENGINE_F_ENGINE_UNLOCKED_FINISH 191
+#define ENGINE_F_ENGINE_UP_REF 190
+#define ENGINE_F_INT_CTRL_HELPER 172
+#define ENGINE_F_INT_ENGINE_CONFIGURE 188
+#define ENGINE_F_INT_ENGINE_MODULE_INIT 187
+#define ENGINE_F_LOG_MESSAGE 141
+
+/* Reason codes. */
+#define ENGINE_R_ALREADY_LOADED 100
+#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133
+#define ENGINE_R_CMD_NOT_EXECUTABLE 134
+#define ENGINE_R_COMMAND_TAKES_INPUT 135
+#define ENGINE_R_COMMAND_TAKES_NO_INPUT 136
+#define ENGINE_R_CONFLICTING_ENGINE_ID 103
+#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119
+#define ENGINE_R_DH_NOT_IMPLEMENTED 139
+#define ENGINE_R_DSA_NOT_IMPLEMENTED 140
+#define ENGINE_R_DSO_FAILURE 104
+#define ENGINE_R_DSO_NOT_FOUND 132
+#define ENGINE_R_ENGINES_SECTION_ERROR 148
+#define ENGINE_R_ENGINE_CONFIGURATION_ERROR 102
+#define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105
+#define ENGINE_R_ENGINE_SECTION_ERROR 149
+#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128
+#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129
+#define ENGINE_R_FINISH_FAILED 106
+#define ENGINE_R_GET_HANDLE_FAILED 107
+#define ENGINE_R_ID_OR_NAME_MISSING 108
+#define ENGINE_R_INIT_FAILED 109
+#define ENGINE_R_INTERNAL_LIST_ERROR 110
+#define ENGINE_R_INVALID_ARGUMENT 143
+#define ENGINE_R_INVALID_CMD_NAME 137
+#define ENGINE_R_INVALID_CMD_NUMBER 138
+#define ENGINE_R_INVALID_INIT_VALUE 151
+#define ENGINE_R_INVALID_STRING 150
+#define ENGINE_R_NOT_INITIALISED 117
+#define ENGINE_R_NOT_LOADED 112
+#define ENGINE_R_NO_CONTROL_FUNCTION 120
+#define ENGINE_R_NO_INDEX 144
+#define ENGINE_R_NO_LOAD_FUNCTION 125
+#define ENGINE_R_NO_REFERENCE 130
+#define ENGINE_R_NO_SUCH_ENGINE 116
+#define ENGINE_R_NO_UNLOAD_FUNCTION 126
+#define ENGINE_R_PROVIDE_PARAMETERS 113
+#define ENGINE_R_RSA_NOT_IMPLEMENTED 141
+#define ENGINE_R_UNIMPLEMENTED_CIPHER 146
+#define ENGINE_R_UNIMPLEMENTED_DIGEST 147
+#define ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD 101
+#define ENGINE_R_VERSION_INCOMPATIBILITY 145
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/engine/enginetest.c b/crypto/engine/enginetest.c
new file mode 100644
index 0000000..f4d70e7
--- /dev/null
+++ b/crypto/engine/enginetest.c
@@ -0,0 +1,283 @@
+/* crypto/engine/enginetest.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <openssl/e_os2.h>
+
+#ifdef OPENSSL_NO_ENGINE
+int main(int argc, char *argv[])
+{
+ printf("No ENGINE support\n");
+ return(0);
+}
+#else
+#include <openssl/buffer.h>
+#include <openssl/crypto.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+
+static void display_engine_list(void)
+ {
+ ENGINE *h;
+ int loop;
+
+ h = ENGINE_get_first();
+ loop = 0;
+ printf("listing available engine types\n");
+ while(h)
+ {
+ printf("engine %i, id = \"%s\", name = \"%s\"\n",
+ loop++, ENGINE_get_id(h), ENGINE_get_name(h));
+ h = ENGINE_get_next(h);
+ }
+ printf("end of list\n");
+ /* ENGINE_get_first() increases the struct_ref counter, so we
+ must call ENGINE_free() to decrease it again */
+ ENGINE_free(h);
+ }
+
+int main(int argc, char *argv[])
+ {
+ ENGINE *block[512];
+ char buf[256];
+ const char *id, *name;
+ ENGINE *ptr;
+ int loop;
+ int to_return = 1;
+ ENGINE *new_h1 = NULL;
+ ENGINE *new_h2 = NULL;
+ ENGINE *new_h3 = NULL;
+ ENGINE *new_h4 = NULL;
+
+ /* enable memory leak checking unless explicitly disabled */
+ if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
+ {
+ CRYPTO_malloc_debug_init();
+ CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+ }
+ else
+ {
+ /* OPENSSL_DEBUG_MEMORY=off */
+ CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+ }
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+ ERR_load_crypto_strings();
+
+ memset(block, 0, 512 * sizeof(ENGINE *));
+ if(((new_h1 = ENGINE_new()) == NULL) ||
+ !ENGINE_set_id(new_h1, "test_id0") ||
+ !ENGINE_set_name(new_h1, "First test item") ||
+ ((new_h2 = ENGINE_new()) == NULL) ||
+ !ENGINE_set_id(new_h2, "test_id1") ||
+ !ENGINE_set_name(new_h2, "Second test item") ||
+ ((new_h3 = ENGINE_new()) == NULL) ||
+ !ENGINE_set_id(new_h3, "test_id2") ||
+ !ENGINE_set_name(new_h3, "Third test item") ||
+ ((new_h4 = ENGINE_new()) == NULL) ||
+ !ENGINE_set_id(new_h4, "test_id3") ||
+ !ENGINE_set_name(new_h4, "Fourth test item"))
+ {
+ printf("Couldn't set up test ENGINE structures\n");
+ goto end;
+ }
+ printf("\nenginetest beginning\n\n");
+ display_engine_list();
+ if(!ENGINE_add(new_h1))
+ {
+ printf("Add failed!\n");
+ goto end;
+ }
+ display_engine_list();
+ ptr = ENGINE_get_first();
+ if(!ENGINE_remove(ptr))
+ {
+ printf("Remove failed!\n");
+ goto end;
+ }
+ if (ptr)
+ ENGINE_free(ptr);
+ display_engine_list();
+ if(!ENGINE_add(new_h3) || !ENGINE_add(new_h2))
+ {
+ printf("Add failed!\n");
+ goto end;
+ }
+ display_engine_list();
+ if(!ENGINE_remove(new_h2))
+ {
+ printf("Remove failed!\n");
+ goto end;
+ }
+ display_engine_list();
+ if(!ENGINE_add(new_h4))
+ {
+ printf("Add failed!\n");
+ goto end;
+ }
+ display_engine_list();
+ if(ENGINE_add(new_h3))
+ {
+ printf("Add *should* have failed but didn't!\n");
+ goto end;
+ }
+ else
+ printf("Add that should fail did.\n");
+ ERR_clear_error();
+ if(ENGINE_remove(new_h2))
+ {
+ printf("Remove *should* have failed but didn't!\n");
+ goto end;
+ }
+ else
+ printf("Remove that should fail did.\n");
+ ERR_clear_error();
+ if(!ENGINE_remove(new_h3))
+ {
+ printf("Remove failed!\n");
+ goto end;
+ }
+ display_engine_list();
+ if(!ENGINE_remove(new_h4))
+ {
+ printf("Remove failed!\n");
+ goto end;
+ }
+ display_engine_list();
+ /* Depending on whether there's any hardware support compiled
+ * in, this remove may be destined to fail. */
+ ptr = ENGINE_get_first();
+ if(ptr)
+ if(!ENGINE_remove(ptr))
+ printf("Remove failed!i - probably no hardware "
+ "support present.\n");
+ if (ptr)
+ ENGINE_free(ptr);
+ display_engine_list();
+ if(!ENGINE_add(new_h1) || !ENGINE_remove(new_h1))
+ {
+ printf("Couldn't add and remove to an empty list!\n");
+ goto end;
+ }
+ else
+ printf("Successfully added and removed to an empty list!\n");
+ printf("About to beef up the engine-type list\n");
+ for(loop = 0; loop < 512; loop++)
+ {
+ sprintf(buf, "id%i", loop);
+ id = BUF_strdup(buf);
+ sprintf(buf, "Fake engine type %i", loop);
+ name = BUF_strdup(buf);
+ if(((block[loop] = ENGINE_new()) == NULL) ||
+ !ENGINE_set_id(block[loop], id) ||
+ !ENGINE_set_name(block[loop], name))
+ {
+ printf("Couldn't create block of ENGINE structures.\n"
+ "I'll probably also core-dump now, damn.\n");
+ goto end;
+ }
+ }
+ for(loop = 0; loop < 512; loop++)
+ {
+ if(!ENGINE_add(block[loop]))
+ {
+ printf("\nAdding stopped at %i, (%s,%s)\n",
+ loop, ENGINE_get_id(block[loop]),
+ ENGINE_get_name(block[loop]));
+ goto cleanup_loop;
+ }
+ else
+ printf("."); fflush(stdout);
+ }
+cleanup_loop:
+ printf("\nAbout to empty the engine-type list\n");
+ while((ptr = ENGINE_get_first()) != NULL)
+ {
+ if(!ENGINE_remove(ptr))
+ {
+ printf("\nRemove failed!\n");
+ goto end;
+ }
+ ENGINE_free(ptr);
+ printf("."); fflush(stdout);
+ }
+ for(loop = 0; loop < 512; loop++)
+ {
+ OPENSSL_free((void *)ENGINE_get_id(block[loop]));
+ OPENSSL_free((void *)ENGINE_get_name(block[loop]));
+ }
+ printf("\nTests completed happily\n");
+ to_return = 0;
+end:
+ if(to_return)
+ ERR_print_errors_fp(stderr);
+ if(new_h1) ENGINE_free(new_h1);
+ if(new_h2) ENGINE_free(new_h2);
+ if(new_h3) ENGINE_free(new_h3);
+ if(new_h4) ENGINE_free(new_h4);
+ for(loop = 0; loop < 512; loop++)
+ if(block[loop])
+ ENGINE_free(block[loop]);
+ ENGINE_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+ ERR_free_strings();
+ ERR_remove_thread_state(NULL);
+ CRYPTO_mem_leaks_fp(stderr);
+ return to_return;
+ }
+#endif
diff --git a/crypto/engine/tb_asnmth.c b/crypto/engine/tb_asnmth.c
new file mode 100644
index 0000000..7509033
--- /dev/null
+++ b/crypto/engine/tb_asnmth.c
@@ -0,0 +1,246 @@
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+#include "asn1_locl.h"
+#include <openssl/evp.h>
+
+/* If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the
+ * function that is used by EVP to hook in pkey_asn1_meth code and cache
+ * defaults (etc), will display brief debugging summaries to stderr with the
+ * 'nid'. */
+/* #define ENGINE_PKEY_ASN1_METH_DEBUG */
+
+static ENGINE_TABLE *pkey_asn1_meth_table = NULL;
+
+void ENGINE_unregister_pkey_asn1_meths(ENGINE *e)
+ {
+ engine_table_unregister(&pkey_asn1_meth_table, e);
+ }
+
+static void engine_unregister_all_pkey_asn1_meths(void)
+ {
+ engine_table_cleanup(&pkey_asn1_meth_table);
+ }
+
+int ENGINE_register_pkey_asn1_meths(ENGINE *e)
+ {
+ if(e->pkey_asn1_meths)
+ {
+ const int *nids;
+ int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&pkey_asn1_meth_table,
+ engine_unregister_all_pkey_asn1_meths, e, nids,
+ num_nids, 0);
+ }
+ return 1;
+ }
+
+void ENGINE_register_all_pkey_asn1_meths(void)
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_pkey_asn1_meths(e);
+ }
+
+int ENGINE_set_default_pkey_asn1_meths(ENGINE *e)
+ {
+ if(e->pkey_asn1_meths)
+ {
+ const int *nids;
+ int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&pkey_asn1_meth_table,
+ engine_unregister_all_pkey_asn1_meths, e, nids,
+ num_nids, 1);
+ }
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given pkey_asn1_meth 'nid' */
+ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid)
+ {
+ return engine_table_select(&pkey_asn1_meth_table, nid);
+ }
+
+/* Obtains a pkey_asn1_meth implementation from an ENGINE functional reference */
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid)
+ {
+ EVP_PKEY_ASN1_METHOD *ret;
+ ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e);
+ if(!fn || !fn(e, &ret, NULL, nid))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH,
+ ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
+ return NULL;
+ }
+ return ret;
+ }
+
+/* Gets the pkey_asn1_meth callback from an ENGINE structure */
+ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e)
+ {
+ return e->pkey_asn1_meths;
+ }
+
+/* Sets the pkey_asn1_meth callback in an ENGINE structure */
+int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f)
+ {
+ e->pkey_asn1_meths = f;
+ return 1;
+ }
+
+/* Internal function to free up EVP_PKEY_ASN1_METHOD structures before an
+ * ENGINE is destroyed
+ */
+
+void engine_pkey_asn1_meths_free(ENGINE *e)
+ {
+ int i;
+ EVP_PKEY_ASN1_METHOD *pkm;
+ if (e->pkey_asn1_meths)
+ {
+ const int *pknids;
+ int npknids;
+ npknids = e->pkey_asn1_meths(e, NULL, &pknids, 0);
+ for (i = 0; i < npknids; i++)
+ {
+ if (e->pkey_asn1_meths(e, &pkm, NULL, pknids[i]))
+ {
+ EVP_PKEY_asn1_free(pkm);
+ }
+ }
+ }
+ }
+
+/* Find a method based on a string. This does a linear search through
+ * all implemented algorithms. This is OK in practice because only
+ * a small number of algorithms are likely to be implemented in an engine
+ * and it is not used for speed critical operations.
+ */
+
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
+ const char *str, int len)
+ {
+ int i, nidcount;
+ const int *nids;
+ EVP_PKEY_ASN1_METHOD *ameth;
+ if (!e->pkey_asn1_meths)
+ return NULL;
+ if (len == -1)
+ len = strlen(str);
+ nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ for (i = 0; i < nidcount; i++)
+ {
+ e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
+ if (((int)strlen(ameth->pem_str) == len) &&
+ !strncasecmp(ameth->pem_str, str, len))
+ return ameth;
+ }
+ return NULL;
+ }
+
+typedef struct
+ {
+ ENGINE *e;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ const char *str;
+ int len;
+ } ENGINE_FIND_STR;
+
+static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
+ {
+ ENGINE_FIND_STR *lk = arg;
+ int i;
+ if (lk->ameth)
+ return;
+ for (i = 0; i < sk_ENGINE_num(sk); i++)
+ {
+ ENGINE *e = sk_ENGINE_value(sk, i);
+ EVP_PKEY_ASN1_METHOD *ameth;
+ e->pkey_asn1_meths(e, &ameth, NULL, nid);
+ if (((int)strlen(ameth->pem_str) == lk->len) &&
+ !strncasecmp(ameth->pem_str, lk->str, lk->len))
+ {
+ lk->e = e;
+ lk->ameth = ameth;
+ return;
+ }
+ }
+ }
+
+const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
+ const char *str, int len)
+ {
+ ENGINE_FIND_STR fstr;
+ fstr.e = NULL;
+ fstr.ameth = NULL;
+ fstr.str = str;
+ fstr.len = len;
+ CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+ engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr);
+ /* If found obtain a structural reference to engine */
+ if (fstr.e)
+ {
+ fstr.e->struct_ref++;
+ engine_ref_debug(fstr.e, 0, 1)
+ }
+ *pe = fstr.e;
+ CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+ return fstr.ameth;
+ }
diff --git a/crypto/engine/tb_cipher.c b/crypto/engine/tb_cipher.c
new file mode 100644
index 0000000..177fc1f
--- /dev/null
+++ b/crypto/engine/tb_cipher.c
@@ -0,0 +1,143 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_cipher_engine(), the function that
+ * is used by EVP to hook in cipher code and cache defaults (etc), will display
+ * brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_CIPHER_DEBUG */
+
+static ENGINE_TABLE *cipher_table = NULL;
+
+void ENGINE_unregister_ciphers(ENGINE *e)
+ {
+ engine_table_unregister(&cipher_table, e);
+ }
+
+static void engine_unregister_all_ciphers(void)
+ {
+ engine_table_cleanup(&cipher_table);
+ }
+
+int ENGINE_register_ciphers(ENGINE *e)
+ {
+ if(e->ciphers)
+ {
+ const int *nids;
+ int num_nids = e->ciphers(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&cipher_table,
+ engine_unregister_all_ciphers, e, nids,
+ num_nids, 0);
+ }
+ return 1;
+ }
+
+void ENGINE_register_all_ciphers()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_ciphers(e);
+ }
+
+int ENGINE_set_default_ciphers(ENGINE *e)
+ {
+ if(e->ciphers)
+ {
+ const int *nids;
+ int num_nids = e->ciphers(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&cipher_table,
+ engine_unregister_all_ciphers, e, nids,
+ num_nids, 1);
+ }
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given cipher 'nid' */
+ENGINE *ENGINE_get_cipher_engine(int nid)
+ {
+ return engine_table_select(&cipher_table, nid);
+ }
+
+/* Obtains a cipher implementation from an ENGINE functional reference */
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid)
+ {
+ const EVP_CIPHER *ret;
+ ENGINE_CIPHERS_PTR fn = ENGINE_get_ciphers(e);
+ if(!fn || !fn(e, &ret, NULL, nid))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_GET_CIPHER,
+ ENGINE_R_UNIMPLEMENTED_CIPHER);
+ return NULL;
+ }
+ return ret;
+ }
+
+/* Gets the cipher callback from an ENGINE structure */
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e)
+ {
+ return e->ciphers;
+ }
+
+/* Sets the cipher callback in an ENGINE structure */
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f)
+ {
+ e->ciphers = f;
+ return 1;
+ }
diff --git a/crypto/engine/tb_dh.c b/crypto/engine/tb_dh.c
new file mode 100644
index 0000000..6e9d428
--- /dev/null
+++ b/crypto/engine/tb_dh.c
@@ -0,0 +1,118 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_DH(), the function that is
+ * used by DH to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_DH_DEBUG */
+
+static ENGINE_TABLE *dh_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_DH(ENGINE *e)
+ {
+ engine_table_unregister(&dh_table, e);
+ }
+
+static void engine_unregister_all_DH(void)
+ {
+ engine_table_cleanup(&dh_table);
+ }
+
+int ENGINE_register_DH(ENGINE *e)
+ {
+ if(e->dh_meth)
+ return engine_table_register(&dh_table,
+ engine_unregister_all_DH, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_DH()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_DH(e);
+ }
+
+int ENGINE_set_default_DH(ENGINE *e)
+ {
+ if(e->dh_meth)
+ return engine_table_register(&dh_table,
+ engine_unregister_all_DH, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_DH(void)
+ {
+ return engine_table_select(&dh_table, dummy_nid);
+ }
+
+/* Obtains an DH implementation from an ENGINE functional reference */
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e)
+ {
+ return e->dh_meth;
+ }
+
+/* Sets an DH implementation in an ENGINE structure */
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth)
+ {
+ e->dh_meth = dh_meth;
+ return 1;
+ }
diff --git a/crypto/engine/tb_digest.c b/crypto/engine/tb_digest.c
new file mode 100644
index 0000000..d3f4bb2
--- /dev/null
+++ b/crypto/engine/tb_digest.c
@@ -0,0 +1,143 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_digest_engine(), the function that
+ * is used by EVP to hook in digest code and cache defaults (etc), will display
+ * brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_DIGEST_DEBUG */
+
+static ENGINE_TABLE *digest_table = NULL;
+
+void ENGINE_unregister_digests(ENGINE *e)
+ {
+ engine_table_unregister(&digest_table, e);
+ }
+
+static void engine_unregister_all_digests(void)
+ {
+ engine_table_cleanup(&digest_table);
+ }
+
+int ENGINE_register_digests(ENGINE *e)
+ {
+ if(e->digests)
+ {
+ const int *nids;
+ int num_nids = e->digests(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&digest_table,
+ engine_unregister_all_digests, e, nids,
+ num_nids, 0);
+ }
+ return 1;
+ }
+
+void ENGINE_register_all_digests()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_digests(e);
+ }
+
+int ENGINE_set_default_digests(ENGINE *e)
+ {
+ if(e->digests)
+ {
+ const int *nids;
+ int num_nids = e->digests(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&digest_table,
+ engine_unregister_all_digests, e, nids,
+ num_nids, 1);
+ }
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given digest 'nid' */
+ENGINE *ENGINE_get_digest_engine(int nid)
+ {
+ return engine_table_select(&digest_table, nid);
+ }
+
+/* Obtains a digest implementation from an ENGINE functional reference */
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid)
+ {
+ const EVP_MD *ret;
+ ENGINE_DIGESTS_PTR fn = ENGINE_get_digests(e);
+ if(!fn || !fn(e, &ret, NULL, nid))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_GET_DIGEST,
+ ENGINE_R_UNIMPLEMENTED_DIGEST);
+ return NULL;
+ }
+ return ret;
+ }
+
+/* Gets the digest callback from an ENGINE structure */
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e)
+ {
+ return e->digests;
+ }
+
+/* Sets the digest callback in an ENGINE structure */
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f)
+ {
+ e->digests = f;
+ return 1;
+ }
diff --git a/crypto/engine/tb_dsa.c b/crypto/engine/tb_dsa.c
new file mode 100644
index 0000000..e4674f5
--- /dev/null
+++ b/crypto/engine/tb_dsa.c
@@ -0,0 +1,118 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_DSA(), the function that is
+ * used by DSA to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_DSA_DEBUG */
+
+static ENGINE_TABLE *dsa_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_DSA(ENGINE *e)
+ {
+ engine_table_unregister(&dsa_table, e);
+ }
+
+static void engine_unregister_all_DSA(void)
+ {
+ engine_table_cleanup(&dsa_table);
+ }
+
+int ENGINE_register_DSA(ENGINE *e)
+ {
+ if(e->dsa_meth)
+ return engine_table_register(&dsa_table,
+ engine_unregister_all_DSA, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_DSA()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_DSA(e);
+ }
+
+int ENGINE_set_default_DSA(ENGINE *e)
+ {
+ if(e->dsa_meth)
+ return engine_table_register(&dsa_table,
+ engine_unregister_all_DSA, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_DSA(void)
+ {
+ return engine_table_select(&dsa_table, dummy_nid);
+ }
+
+/* Obtains an DSA implementation from an ENGINE functional reference */
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e)
+ {
+ return e->dsa_meth;
+ }
+
+/* Sets an DSA implementation in an ENGINE structure */
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth)
+ {
+ e->dsa_meth = dsa_meth;
+ return 1;
+ }
diff --git a/crypto/engine/tb_ecdh.c b/crypto/engine/tb_ecdh.c
new file mode 100644
index 0000000..c8ec781
--- /dev/null
+++ b/crypto/engine/tb_ecdh.c
@@ -0,0 +1,133 @@
+/* crypto/engine/tb_ecdh.c */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The ECDH engine software is originally written by Nils Gura and
+ * Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_ECDH(), the function that is
+ * used by ECDH to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_ECDH_DEBUG */
+
+static ENGINE_TABLE *ecdh_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_ECDH(ENGINE *e)
+ {
+ engine_table_unregister(&ecdh_table, e);
+ }
+
+static void engine_unregister_all_ECDH(void)
+ {
+ engine_table_cleanup(&ecdh_table);
+ }
+
+int ENGINE_register_ECDH(ENGINE *e)
+ {
+ if(e->ecdh_meth)
+ return engine_table_register(&ecdh_table,
+ engine_unregister_all_ECDH, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_ECDH()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_ECDH(e);
+ }
+
+int ENGINE_set_default_ECDH(ENGINE *e)
+ {
+ if(e->ecdh_meth)
+ return engine_table_register(&ecdh_table,
+ engine_unregister_all_ECDH, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_ECDH(void)
+ {
+ return engine_table_select(&ecdh_table, dummy_nid);
+ }
+
+/* Obtains an ECDH implementation from an ENGINE functional reference */
+const ECDH_METHOD *ENGINE_get_ECDH(const ENGINE *e)
+ {
+ return e->ecdh_meth;
+ }
+
+/* Sets an ECDH implementation in an ENGINE structure */
+int ENGINE_set_ECDH(ENGINE *e, const ECDH_METHOD *ecdh_meth)
+ {
+ e->ecdh_meth = ecdh_meth;
+ return 1;
+ }
diff --git a/crypto/engine/tb_ecdsa.c b/crypto/engine/tb_ecdsa.c
new file mode 100644
index 0000000..005ecb6
--- /dev/null
+++ b/crypto/engine/tb_ecdsa.c
@@ -0,0 +1,118 @@
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_ECDSA(), the function that is
+ * used by ECDSA to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_ECDSA_DEBUG */
+
+static ENGINE_TABLE *ecdsa_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_ECDSA(ENGINE *e)
+ {
+ engine_table_unregister(&ecdsa_table, e);
+ }
+
+static void engine_unregister_all_ECDSA(void)
+ {
+ engine_table_cleanup(&ecdsa_table);
+ }
+
+int ENGINE_register_ECDSA(ENGINE *e)
+ {
+ if(e->ecdsa_meth)
+ return engine_table_register(&ecdsa_table,
+ engine_unregister_all_ECDSA, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_ECDSA()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_ECDSA(e);
+ }
+
+int ENGINE_set_default_ECDSA(ENGINE *e)
+ {
+ if(e->ecdsa_meth)
+ return engine_table_register(&ecdsa_table,
+ engine_unregister_all_ECDSA, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_ECDSA(void)
+ {
+ return engine_table_select(&ecdsa_table, dummy_nid);
+ }
+
+/* Obtains an ECDSA implementation from an ENGINE functional reference */
+const ECDSA_METHOD *ENGINE_get_ECDSA(const ENGINE *e)
+ {
+ return e->ecdsa_meth;
+ }
+
+/* Sets an ECDSA implementation in an ENGINE structure */
+int ENGINE_set_ECDSA(ENGINE *e, const ECDSA_METHOD *ecdsa_meth)
+ {
+ e->ecdsa_meth = ecdsa_meth;
+ return 1;
+ }
diff --git a/crypto/engine/tb_pkmeth.c b/crypto/engine/tb_pkmeth.c
new file mode 100644
index 0000000..1cdb967
--- /dev/null
+++ b/crypto/engine/tb_pkmeth.c
@@ -0,0 +1,167 @@
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+#include <openssl/evp.h>
+
+/* If this symbol is defined then ENGINE_get_pkey_meth_engine(), the function
+ * that is used by EVP to hook in pkey_meth code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_PKEY_METH_DEBUG */
+
+static ENGINE_TABLE *pkey_meth_table = NULL;
+
+void ENGINE_unregister_pkey_meths(ENGINE *e)
+ {
+ engine_table_unregister(&pkey_meth_table, e);
+ }
+
+static void engine_unregister_all_pkey_meths(void)
+ {
+ engine_table_cleanup(&pkey_meth_table);
+ }
+
+int ENGINE_register_pkey_meths(ENGINE *e)
+ {
+ if(e->pkey_meths)
+ {
+ const int *nids;
+ int num_nids = e->pkey_meths(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&pkey_meth_table,
+ engine_unregister_all_pkey_meths, e, nids,
+ num_nids, 0);
+ }
+ return 1;
+ }
+
+void ENGINE_register_all_pkey_meths()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_pkey_meths(e);
+ }
+
+int ENGINE_set_default_pkey_meths(ENGINE *e)
+ {
+ if(e->pkey_meths)
+ {
+ const int *nids;
+ int num_nids = e->pkey_meths(e, NULL, &nids, 0);
+ if(num_nids > 0)
+ return engine_table_register(&pkey_meth_table,
+ engine_unregister_all_pkey_meths, e, nids,
+ num_nids, 1);
+ }
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given pkey_meth 'nid' */
+ENGINE *ENGINE_get_pkey_meth_engine(int nid)
+ {
+ return engine_table_select(&pkey_meth_table, nid);
+ }
+
+/* Obtains a pkey_meth implementation from an ENGINE functional reference */
+const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid)
+ {
+ EVP_PKEY_METHOD *ret;
+ ENGINE_PKEY_METHS_PTR fn = ENGINE_get_pkey_meths(e);
+ if(!fn || !fn(e, &ret, NULL, nid))
+ {
+ ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_METH,
+ ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
+ return NULL;
+ }
+ return ret;
+ }
+
+/* Gets the pkey_meth callback from an ENGINE structure */
+ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e)
+ {
+ return e->pkey_meths;
+ }
+
+/* Sets the pkey_meth callback in an ENGINE structure */
+int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f)
+ {
+ e->pkey_meths = f;
+ return 1;
+ }
+
+/* Internal function to free up EVP_PKEY_METHOD structures before an
+ * ENGINE is destroyed
+ */
+
+void engine_pkey_meths_free(ENGINE *e)
+ {
+ int i;
+ EVP_PKEY_METHOD *pkm;
+ if (e->pkey_meths)
+ {
+ const int *pknids;
+ int npknids;
+ npknids = e->pkey_meths(e, NULL, &pknids, 0);
+ for (i = 0; i < npknids; i++)
+ {
+ if (e->pkey_meths(e, &pkm, NULL, pknids[i]))
+ {
+ EVP_PKEY_meth_free(pkm);
+ }
+ }
+ }
+ }
diff --git a/crypto/engine/tb_rand.c b/crypto/engine/tb_rand.c
new file mode 100644
index 0000000..f36f67c
--- /dev/null
+++ b/crypto/engine/tb_rand.c
@@ -0,0 +1,118 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_RAND(), the function that is
+ * used by RAND to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_RAND_DEBUG */
+
+static ENGINE_TABLE *rand_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_RAND(ENGINE *e)
+ {
+ engine_table_unregister(&rand_table, e);
+ }
+
+static void engine_unregister_all_RAND(void)
+ {
+ engine_table_cleanup(&rand_table);
+ }
+
+int ENGINE_register_RAND(ENGINE *e)
+ {
+ if(e->rand_meth)
+ return engine_table_register(&rand_table,
+ engine_unregister_all_RAND, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_RAND()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_RAND(e);
+ }
+
+int ENGINE_set_default_RAND(ENGINE *e)
+ {
+ if(e->rand_meth)
+ return engine_table_register(&rand_table,
+ engine_unregister_all_RAND, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_RAND(void)
+ {
+ return engine_table_select(&rand_table, dummy_nid);
+ }
+
+/* Obtains an RAND implementation from an ENGINE functional reference */
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e)
+ {
+ return e->rand_meth;
+ }
+
+/* Sets an RAND implementation in an ENGINE structure */
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth)
+ {
+ e->rand_meth = rand_meth;
+ return 1;
+ }
diff --git a/crypto/engine/tb_rsa.c b/crypto/engine/tb_rsa.c
new file mode 100644
index 0000000..fbc707f
--- /dev/null
+++ b/crypto/engine/tb_rsa.c
@@ -0,0 +1,118 @@
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_RSA(), the function that is
+ * used by RSA to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_RSA_DEBUG */
+
+static ENGINE_TABLE *rsa_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_RSA(ENGINE *e)
+ {
+ engine_table_unregister(&rsa_table, e);
+ }
+
+static void engine_unregister_all_RSA(void)
+ {
+ engine_table_cleanup(&rsa_table);
+ }
+
+int ENGINE_register_RSA(ENGINE *e)
+ {
+ if(e->rsa_meth)
+ return engine_table_register(&rsa_table,
+ engine_unregister_all_RSA, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_RSA()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_RSA(e);
+ }
+
+int ENGINE_set_default_RSA(ENGINE *e)
+ {
+ if(e->rsa_meth)
+ return engine_table_register(&rsa_table,
+ engine_unregister_all_RSA, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_RSA(void)
+ {
+ return engine_table_select(&rsa_table, dummy_nid);
+ }
+
+/* Obtains an RSA implementation from an ENGINE functional reference */
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e)
+ {
+ return e->rsa_meth;
+ }
+
+/* Sets an RSA implementation in an ENGINE structure */
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth)
+ {
+ e->rsa_meth = rsa_meth;
+ return 1;
+ }
diff --git a/crypto/engine/tb_store.c b/crypto/engine/tb_store.c
new file mode 100644
index 0000000..8cc435c
--- /dev/null
+++ b/crypto/engine/tb_store.c
@@ -0,0 +1,123 @@
+/* ====================================================================
+ * Copyright (c) 2003 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "eng_int.h"
+
+/* If this symbol is defined then ENGINE_get_default_STORE(), the function that is
+ * used by STORE to hook in implementation code and cache defaults (etc), will
+ * display brief debugging summaries to stderr with the 'nid'. */
+/* #define ENGINE_STORE_DEBUG */
+
+static ENGINE_TABLE *store_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_STORE(ENGINE *e)
+ {
+ engine_table_unregister(&store_table, e);
+ }
+
+static void engine_unregister_all_STORE(void)
+ {
+ engine_table_cleanup(&store_table);
+ }
+
+int ENGINE_register_STORE(ENGINE *e)
+ {
+ if(e->store_meth)
+ return engine_table_register(&store_table,
+ engine_unregister_all_STORE, e, &dummy_nid, 1, 0);
+ return 1;
+ }
+
+void ENGINE_register_all_STORE()
+ {
+ ENGINE *e;
+
+ for(e=ENGINE_get_first() ; e ; e=ENGINE_get_next(e))
+ ENGINE_register_STORE(e);
+ }
+
+/* The following two functions are removed because they're useless. */
+#if 0
+int ENGINE_set_default_STORE(ENGINE *e)
+ {
+ if(e->store_meth)
+ return engine_table_register(&store_table,
+ engine_unregister_all_STORE, e, &dummy_nid, 1, 1);
+ return 1;
+ }
+#endif
+
+#if 0
+/* Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references). */
+ENGINE *ENGINE_get_default_STORE(void)
+ {
+ return engine_table_select(&store_table, dummy_nid);
+ }
+#endif
+
+/* Obtains an STORE implementation from an ENGINE functional reference */
+const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e)
+ {
+ return e->store_meth;
+ }
+
+/* Sets an STORE implementation in an ENGINE structure */
+int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth)
+ {
+ e->store_meth = store_meth;
+ return 1;
+ }