summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Hozza <thozza@redhat.com>2014-08-21 16:37:44 +0200
committerTomas Hozza <thozza@redhat.com>2014-10-14 14:02:38 +0200
commitdce2d1bd1c15bb6a5b3edbc5cff4cd02336ac7f4 (patch)
tree1374f5404cc9afe5e3cadb7d4f51805d376b2485
parent23b1421845d9c6446c744992573e15725b5e1516 (diff)
downloadbind-dce2d1bd1c15bb6a5b3edbc5cff4cd02336ac7f4.tar.gz
bind-dce2d1bd1c15bb6a5b3edbc5cff4cd02336ac7f4.tar.xz
bind-dce2d1bd1c15bb6a5b3edbc5cff4cd02336ac7f4.zip
Added native PKCS#11 functionality
Resolves: rhbz#1097752 Signed-off-by: Tomas Hozza <thozza@redhat.com>
-rw-r--r--bind-9.5-sdb.patch68
-rw-r--r--bind-9.9-dist-native-pkcs11.patch745
-rw-r--r--bind-9.9-native-pkcs11.patch19840
-rw-r--r--bind.spec143
-rw-r--r--bind97-dist-pkcs11.patch22
-rw-r--r--named-pkcs11.service26
6 files changed, 20772 insertions, 72 deletions
diff --git a/bind-9.5-sdb.patch b/bind-9.5-sdb.patch
index 270ec9e..99475e6 100644
--- a/bind-9.5-sdb.patch
+++ b/bind-9.5-sdb.patch
@@ -1,30 +1,30 @@
-diff -up bind-9.9.3rc1/bin/Makefile.in.sdb bind-9.9.3rc1/bin/Makefile.in
---- bind-9.9.3rc1/bin/Makefile.in.sdb 2013-04-05 00:21:21.000000000 +0200
-+++ bind-9.9.3rc1/bin/Makefile.in 2013-04-16 15:21:22.286944331 +0200
+diff -up bind-9.9.4-P2/bin/Makefile.in.sdb bind-9.9.4-P2/bin/Makefile.in
+--- bind-9.9.4-P2/bin/Makefile.in.sdb 2013-12-20 01:28:28.000000000 +0100
++++ bind-9.9.4-P2/bin/Makefile.in 2014-07-22 10:29:23.940233449 +0200
@@ -19,8 +19,8 @@ srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
--SUBDIRS = named rndc dig dnssec tools tests nsupdate \
+-SUBDIRS = named named-pkcs11 rndc dig dnssec dnssec-pkcs11 tools tests nsupdate \
- check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@
-+SUBDIRS = named named-sdb rndc dig dnssec tools tests nsupdate \
++SUBDIRS = named named-pkcs11 named-sdb rndc dig dnssec dnssec-pkcs11 tools tests nsupdate \
+ check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@ sdb_tools
TARGETS =
@BIND9_MAKE_RULES@
-diff -up bind-9.9.3rc1/bin/named/Makefile.in.sdb bind-9.9.3rc1/bin/named/Makefile.in
---- bind-9.9.3rc1/bin/named/Makefile.in.sdb 2013-04-16 15:21:22.102944727 +0200
-+++ bind-9.9.3rc1/bin/named/Makefile.in 2013-04-16 15:21:22.286944331 +0200
-@@ -49,7 +49,7 @@ CINCLUDES = -I${srcdir}/include -I${srcd
+diff -up bind-9.9.4-P2/bin/named/Makefile.in.sdb bind-9.9.4-P2/bin/named/Makefile.in
+--- bind-9.9.4-P2/bin/named/Makefile.in.sdb 2014-07-22 10:29:23.873233351 +0200
++++ bind-9.9.4-P2/bin/named/Makefile.in 2014-07-22 10:30:43.247348398 +0200
+@@ -52,7 +52,7 @@ CINCLUDES = -I${srcdir}/include -I${srcd
${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@
--CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @USE_OPENSSL@
-+CDEFINES = @USE_PKCS11@ @USE_OPENSSL@
+-CDEFINES = @CONTRIB_DLZ@ @CRYPTO@
++CDEFINES = @CRYPTO@
CWARNINGS =
-@@ -73,11 +73,11 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS}
+@@ -79,11 +79,11 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS}
LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \
@@ -38,7 +38,7 @@ diff -up bind-9.9.3rc1/bin/named/Makefile.in.sdb bind-9.9.3rc1/bin/named/Makefil
SUBDIRS = unix
-@@ -90,8 +90,7 @@ OBJS = builtin.@O@ client.@O@ config.@O
+@@ -96,8 +96,7 @@ OBJS = builtin.@O@ client.@O@ config.@O
tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \
zoneconf.@O@ \
lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
@@ -48,7 +48,7 @@ diff -up bind-9.9.3rc1/bin/named/Makefile.in.sdb bind-9.9.3rc1/bin/named/Makefil
UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@
-@@ -104,8 +103,7 @@ SRCS = builtin.c client.c config.c cont
+@@ -110,8 +109,7 @@ SRCS = builtin.c client.c config.c cont
tkeyconf.c tsigconf.c update.c xfrout.c \
zoneconf.c \
lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
@@ -58,7 +58,7 @@ diff -up bind-9.9.3rc1/bin/named/Makefile.in.sdb bind-9.9.3rc1/bin/named/Makefil
MANPAGES = named.8 lwresd.8 named.conf.5
-@@ -180,7 +178,5 @@ install:: named@EXEEXT@ lwresd@EXEEXT@ i
+@@ -187,7 +185,5 @@ install:: named@EXEEXT@ lwresd@EXEEXT@ i
${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8
${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5
@@ -66,9 +66,9 @@ diff -up bind-9.9.3rc1/bin/named/Makefile.in.sdb bind-9.9.3rc1/bin/named/Makefil
-
named-symtbl.@O@: named-symtbl.c
${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c named-symtbl.c
-diff -up bind-9.9.3rc1/bin/named-sdb/main.c.sdb bind-9.9.3rc1/bin/named-sdb/main.c
---- bind-9.9.3rc1/bin/named-sdb/main.c.sdb 2013-04-16 15:21:22.249944411 +0200
-+++ bind-9.9.3rc1/bin/named-sdb/main.c 2013-04-16 15:21:22.287944329 +0200
+diff -up bind-9.9.4-P2/bin/named-sdb/main.c.sdb bind-9.9.4-P2/bin/named-sdb/main.c
+--- bind-9.9.4-P2/bin/named-sdb/main.c.sdb 2014-07-22 10:29:23.919233417 +0200
++++ bind-9.9.4-P2/bin/named-sdb/main.c 2014-07-22 10:29:23.940233449 +0200
@@ -83,6 +83,9 @@
* Include header files for database drivers here.
*/
@@ -79,7 +79,7 @@ diff -up bind-9.9.3rc1/bin/named-sdb/main.c.sdb bind-9.9.3rc1/bin/named-sdb/main
#ifdef CONTRIB_DLZ
/*
-@@ -808,6 +811,10 @@ setup(void) {
+@@ -814,6 +817,10 @@ setup(void) {
ns_main_earlyfatal("isc_app_start() failed: %s",
isc_result_totext(result));
@@ -90,7 +90,7 @@ diff -up bind-9.9.3rc1/bin/named-sdb/main.c.sdb bind-9.9.3rc1/bin/named-sdb/main
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
ISC_LOG_NOTICE, "starting %s %s%s", ns_g_product,
ns_g_version, saved_command_line);
-@@ -920,6 +927,57 @@ setup(void) {
+@@ -926,6 +933,57 @@ setup(void) {
isc_result_totext(result));
#endif
@@ -148,7 +148,7 @@ diff -up bind-9.9.3rc1/bin/named-sdb/main.c.sdb bind-9.9.3rc1/bin/named-sdb/main
ns_server_create(ns_g_mctx, &ns_g_server);
}
-@@ -951,6 +1009,10 @@ cleanup(void) {
+@@ -957,6 +1015,10 @@ cleanup(void) {
dns_name_destroy();
@@ -159,10 +159,10 @@ diff -up bind-9.9.3rc1/bin/named-sdb/main.c.sdb bind-9.9.3rc1/bin/named-sdb/main
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
ISC_LOG_NOTICE, "exiting");
ns_log_shutdown();
-diff -up bind-9.9.3rc1/bin/named-sdb/Makefile.in.sdb bind-9.9.3rc1/bin/named-sdb/Makefile.in
---- bind-9.9.3rc1/bin/named-sdb/Makefile.in.sdb 2013-04-16 15:21:22.243944424 +0200
-+++ bind-9.9.3rc1/bin/named-sdb/Makefile.in 2013-04-16 15:21:22.287944329 +0200
-@@ -32,10 +32,10 @@ top_srcdir = @top_srcdir@
+diff -up bind-9.9.4-P2/bin/named-sdb/Makefile.in.sdb bind-9.9.4-P2/bin/named-sdb/Makefile.in
+--- bind-9.9.4-P2/bin/named-sdb/Makefile.in.sdb 2014-07-22 10:29:23.917233415 +0200
++++ bind-9.9.4-P2/bin/named-sdb/Makefile.in 2014-07-22 10:29:23.941233449 +0200
+@@ -34,10 +34,10 @@ top_srcdir = @top_srcdir@
#
# Add database drivers here.
#
@@ -176,7 +176,7 @@ diff -up bind-9.9.3rc1/bin/named-sdb/Makefile.in.sdb bind-9.9.3rc1/bin/named-sdb
DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers
-@@ -81,7 +81,7 @@ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BI
+@@ -87,7 +87,7 @@ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BI
SUBDIRS = unix
@@ -185,7 +185,7 @@ diff -up bind-9.9.3rc1/bin/named-sdb/Makefile.in.sdb bind-9.9.3rc1/bin/named-sdb
OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
controlconf.@O@ interfacemgr.@O@ \
-@@ -139,7 +139,7 @@ config.@O@: config.c bind.keys.h
+@@ -146,7 +146,7 @@ config.@O@: config.c bind.keys.h
-DNS_SYSCONFDIR=\"${sysconfdir}\" \
-c ${srcdir}/config.c
@@ -194,7 +194,7 @@ diff -up bind-9.9.3rc1/bin/named-sdb/Makefile.in.sdb bind-9.9.3rc1/bin/named-sdb
export MAKE_SYMTABLE="yes"; \
export BASEOBJS="${OBJS} ${UOBJS}"; \
${FINALBUILDCMD}
-@@ -170,15 +170,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3
+@@ -177,15 +177,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3
installdirs:
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
@@ -212,12 +212,12 @@ diff -up bind-9.9.3rc1/bin/named-sdb/Makefile.in.sdb bind-9.9.3rc1/bin/named-sdb
@DLZ_DRIVER_RULES@
-diff -up bind-9.9.3rc1/configure.in.sdb bind-9.9.3rc1/configure.in
---- bind-9.9.3rc1/configure.in.sdb 2013-04-16 15:21:22.208944499 +0200
-+++ bind-9.9.3rc1/configure.in 2013-04-16 15:21:19.395950103 +0200
-@@ -3651,12 +3651,15 @@ AC_CONFIG_FILES([
- bin/dnssec/Makefile
- bin/named/Makefile
+diff -up bind-9.9.4-P2/configure.in.sdb bind-9.9.4-P2/configure.in
+--- bind-9.9.4-P2/configure.in.sdb 2014-07-22 10:29:23.909233403 +0200
++++ bind-9.9.4-P2/configure.in 2014-07-22 10:29:23.942233450 +0200
+@@ -3900,12 +3900,15 @@ AC_CONFIG_FILES([
+ bin/named-pkcs11/Makefile
+ bin/named-pkcs11/unix/Makefile
bin/named/unix/Makefile
+ bin/named-sdb/Makefile
+ bin/named-sdb/unix/Makefile
diff --git a/bind-9.9-dist-native-pkcs11.patch b/bind-9.9-dist-native-pkcs11.patch
new file mode 100644
index 0000000..4e181a8
--- /dev/null
+++ b/bind-9.9-dist-native-pkcs11.patch
@@ -0,0 +1,745 @@
+diff --git a/bin/Makefile.in b/bin/Makefile.in
+index 87ca5b2..187ec23 100644
+--- a/bin/Makefile.in
++++ b/bin/Makefile.in
+@@ -19,7 +19,7 @@ srcdir = @srcdir@
+ VPATH = @srcdir@
+ top_srcdir = @top_srcdir@
+
+-SUBDIRS = named rndc dig dnssec tools tests nsupdate \
++SUBDIRS = named named-pkcs11 rndc dig dnssec dnssec-pkcs11 tools tests nsupdate \
+ check confgen @PYTHON_TOOLS@ @PKCS11_TOOLS@
+ TARGETS =
+
+diff --git a/bin/dnssec-pkcs11/Makefile.in b/bin/dnssec-pkcs11/Makefile.in
+index 4f1bf90..3da5277 100644
+--- a/bin/dnssec-pkcs11/Makefile.in
++++ b/bin/dnssec-pkcs11/Makefile.in
+@@ -23,18 +23,18 @@ top_srcdir = @top_srcdir@
+
+ @BIND9_MAKE_INCLUDES@
+
+-CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
++CINCLUDES = ${DNS_PKCS11_INCLUDES} ${ISC_PKCS11_INCLUDES}
+
+ CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \
+- @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\"
++ @CRYPTO_PK11@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\"
+ CWARNINGS =
+
+-DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+-ISCLIBS = ../../lib/isc/libisc.@A@
+-ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
++DNSLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ @DNS_CRYPTO_PK11_LIBS@
++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
++ISCNOSYMLIBS = ../../lib/isc-pkcs11/libisc-pkcs11-nosymtbl.@A@
+
+-DNSDEPLIBS = ../../lib/dns/libdns.@A@
+-ISCDEPLIBS = ../../lib/isc/libisc.@A@
++DNSDEPLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@
++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+
+ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+@@ -43,10 +43,10 @@ LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+ NOSYMLIBS = ${DNSLIBS} ${ISCNOSYMLIBS} @LIBS@
+
+ # Alphabetically
+-TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
+- dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@ \
+- dnssec-revoke@EXEEXT@ dnssec-settime@EXEEXT@ \
+- dnssec-verify@EXEEXT@ dnssec-importkey@EXEEXT@
++TARGETS = dnssec-keygen-pkcs11@EXEEXT@ dnssec-signzone-pkcs11@EXEEXT@ \
++ dnssec-keyfromlabel-pkcs11@EXEEXT@ dnssec-dsfromkey-pkcs11@EXEEXT@ \
++ dnssec-revoke-pkcs11@EXEEXT@ dnssec-settime-pkcs11@EXEEXT@ \
++ dnssec-verify-pkcs11@EXEEXT@ dnssec-importkey-pkcs11@EXEEXT@
+
+ OBJS = dnssectool.@O@
+
+@@ -67,15 +67,15 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+ @BIND9_MAKE_RULES@
+
+-dnssec-dsfromkey@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS}
++dnssec-dsfromkey-pkcs11@EXEEXT@: dnssec-dsfromkey.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-dsfromkey.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+-dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS}
++dnssec-keyfromlabel-pkcs11@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-keyfromlabel.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+-dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS}
++dnssec-keygen-pkcs11@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-keygen.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+@@ -83,7 +83,7 @@ dnssec-signzone.@O@: dnssec-signzone.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/dnssec-signzone.c
+
+-dnssec-signzone@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS}
++dnssec-signzone-pkcs11@EXEEXT@: dnssec-signzone.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-signzone.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+@@ -91,19 +91,19 @@ dnssec-verify.@O@: dnssec-verify.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/dnssec-verify.c
+
+-dnssec-verify@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS}
++dnssec-verify-pkcs11@EXEEXT@: dnssec-verify.@O@ ${OBJS} ${DEPLIBS}
+ export BASEOBJS="dnssec-verify.@O@ ${OBJS}"; \
+ ${FINALBUILDCMD}
+
+-dnssec-revoke@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS}
++dnssec-revoke-pkcs11@EXEEXT@: dnssec-revoke.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-revoke.@O@ ${OBJS} ${LIBS}
+
+-dnssec-settime@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS}
++dnssec-settime-pkcs11@EXEEXT@: dnssec-settime.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-settime.@O@ ${OBJS} ${LIBS}
+
+-dnssec-importkey@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS}
++dnssec-importkey-pkcs11@EXEEXT@: dnssec-importkey.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-importkey.@O@ ${OBJS} ${LIBS}
+
+@@ -114,11 +114,9 @@ docclean manclean maintainer-clean::
+
+ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+ install:: ${TARGETS} installdirs
+ for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done
+- for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done
+
+ clean distclean::
+ rm -f ${TARGETS}
+diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in
+index 4f1bf90..e1132ea 100644
+--- a/bin/dnssec/Makefile.in
++++ b/bin/dnssec/Makefile.in
+@@ -25,7 +25,7 @@ top_srcdir = @top_srcdir@
+
+ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+-CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \
++CDEFINES = -DVERSION=\"${VERSION}\" \
+ @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\"
+ CWARNINGS =
+
+diff --git a/bin/named-pkcs11/Makefile.in b/bin/named-pkcs11/Makefile.in
+index 10cbdec..c70af88 100644
+--- a/bin/named-pkcs11/Makefile.in
++++ b/bin/named-pkcs11/Makefile.in
+@@ -47,26 +47,26 @@ DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@
+ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@
+
+ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \
+- ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+- ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
++ ${LWRES_INCLUDES} ${DNS_PKCS11_INCLUDES} ${BIND9_INCLUDES} \
++ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_PKCS11_INCLUDES} \
+ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@
+
+-CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@
++CDEFINES = @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO_PK11@
+
+ CWARNINGS =
+
+-DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
++DNSLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@ @DNS_CRYPTO_LIBS@
+ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+-ISCLIBS = ../../lib/isc/libisc.@A@
++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+ ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+ LWRESLIBS = ../../lib/lwres/liblwres.@A@
+ BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+-DNSDEPLIBS = ../../lib/dns/libdns.@A@
++DNSDEPLIBS = ../../lib/dns-pkcs11/libdns-pkcs11.@A@
+ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@
+-ISCDEPLIBS = ../../lib/isc/libisc.@A@
++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+@@ -75,15 +75,15 @@ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \
+
+ LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
+ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \
+- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
++ @LIBS@
+
+ NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
+ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \
+- ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
++ @LIBS@
+
+ SUBDIRS = unix
+
+-TARGETS = named@EXEEXT@ lwresd@EXEEXT@
++TARGETS = named-pkcs11@EXEEXT@
+
+ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
+ controlconf.@O@ interfacemgr.@O@ \
+@@ -92,8 +92,7 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
+ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \
+ zoneconf.@O@ \
+ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
+- lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \
+- ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS}
++ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@
+
+ UOBJS = unix/os.@O@ unix/dlz_dlopen_driver.@O@
+
+@@ -106,8 +105,7 @@ SRCS = builtin.c client.c config.c control.c \
+ tkeyconf.c tsigconf.c update.c xfrout.c \
+ zoneconf.c \
+ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
+- lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \
+- ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS}
++ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c
+
+ MANPAGES = named.8 lwresd.8 named.conf.5
+
+@@ -143,7 +141,7 @@ config.@O@: config.c bind.keys.h
+ -DNS_SYSCONFDIR=\"${sysconfdir}\" \
+ -c ${srcdir}/config.c
+
+-named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS}
++named-pkcs11@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS}
+ export MAKE_SYMTABLE="yes"; \
+ export BASEOBJS="${OBJS} ${UOBJS}"; \
+ ${FINALBUILDCMD}
+@@ -174,15 +172,9 @@ statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h
+
+ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5
+- $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+-
+-install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs
+- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir}
+- (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@)
+- ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8
+- ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8
+- ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5
++
++install:: named-pkcs11@EXEEXT@ installdirs
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-pkcs11@EXEEXT@ ${DESTDIR}${sbindir}
+
+ @DLZ_DRIVER_RULES@
+
+diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in
+index 10cbdec..1be4e2f 100644
+--- a/bin/named/Makefile.in
++++ b/bin/named/Makefile.in
+@@ -51,7 +51,7 @@ CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \
+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
+ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@
+
+-CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@
++CDEFINES = @CONTRIB_DLZ@ @CRYPTO@
+
+ CWARNINGS =
+
+diff --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in
+index 15d3fb5..32cc753 100644
+--- a/bin/pkcs11/Makefile.in
++++ b/bin/pkcs11/Makefile.in
+@@ -20,13 +20,13 @@ top_srcdir = @top_srcdir@
+
+ @BIND9_MAKE_INCLUDES@
+
+-CINCLUDES = ${ISC_INCLUDES}
++CINCLUDES = ${ISC_PKCS11_INCLUDES}
+
+ CDEFINES =
+
+-ISCLIBS = ../../lib/isc/libisc.@A@
++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+
+-ISCDEPLIBS = ../../lib/isc/libisc.@A@
++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+
+ DEPLIBS = ${ISCDEPLIBS}
+
+diff --git a/configure.in b/configure.in
+index 4ab50d8..917b98b 100644
+--- a/configure.in
++++ b/configure.in
+@@ -671,10 +671,10 @@ AC_ARG_WITH(pkcs11,
+ openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw"
+ if test "$use_openssl" = "auto"
+ then
+- if test "$want_native_pkcs11" = "yes"
+- then
+- use_openssl="native_pkcs11"
+- else
++# if test "$want_native_pkcs11" = "yes"
++# then
++# use_openssl="native_pkcs11"
++# else
+ for d in $openssldirs
+ do
+ if test -f $d/include/openssl/opensslv.h
+@@ -683,7 +683,7 @@ then
+ break
+ fi
+ done
+- fi
++# fi
+ fi
+ OPENSSL_ECDSA=""
+ OPENSSL_GOST=""
+@@ -742,11 +742,11 @@ case "$use_openssl" in
+ If you don't want OpenSSL, use --without-openssl])
+ ;;
+ *)
+- if test "$want_native_pkcs11" = "yes"
+- then
+- AC_MSG_RESULT()
+- AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.])
+- fi
++# if test "$want_native_pkcs11" = "yes"
++# then
++# AC_MSG_RESULT()
++# AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.])
++# fi
+ if test "$use_openssl" = "yes"
+ then
+ # User did not specify a path - guess it
+@@ -1026,6 +1026,7 @@ AC_SUBST(OPENSSL_ECDSA)
+ AC_SUBST(OPENSSL_GOST)
+
+ DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS"
++DNS_CRYPTO_PK11_LIBS="$DNS_CRYPTO_LIBS"
+
+ #
+ # Use OpenSSL for hash functions
+@@ -1209,7 +1210,7 @@ case "$use_pkcs11" in
+ esac
+ AC_SUBST(PKCS11_PROVIDER)
+
+-
++CRYPTO_PK11=""
+ PKCS11_ECDSA=""
+ PKCS11_GOST=""
+ AC_MSG_CHECKING(for native PKCS11)
+@@ -1217,7 +1218,7 @@ AC_MSG_CHECKING(for native PKCS11)
+ case "$want_native_pkcs11" in
+ yes)
+ AC_MSG_RESULT(using native PKCS11 crypto)
+- CRYPTO="-DPKCS11CRYPTO"
++ CRYPTO_PK11="-DPKCS11CRYPTO"
+ PKCS11LINKOBJS='${PKCS11LINKOBJS}'
+ PKCS11LINKSRCS='${PKCS11LINKSRCS}'
+ PKCS11_TEST=pkcs11
+@@ -1254,6 +1255,7 @@ esac
+ AC_SUBST(PKCS11LINKOBJS)
+ AC_SUBST(PKCS11LINKSRCS)
+ AC_SUBST(CRYPTO)
++AC_SUBST(CRYPTO_PK11)
+ AC_SUBST(PKCS11_ECDSA)
+ AC_SUBST(PKCS11_GOST)
+ AC_SUBST(PKCS11_TEST)
+@@ -1465,12 +1467,13 @@ AC_SUBST(USE_GSSAPI)
+ AC_SUBST(DST_GSSAPI_INC)
+ AC_SUBST(DNS_GSSAPI_LIBS)
+ DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS"
+-
++DNS_CRYPTO_PK11_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_PK11_LIBS"
+ #
+ # Applications linking with libdns also need to link with these libraries.
+ #
+
+ AC_SUBST(DNS_CRYPTO_LIBS)
++AC_SUBST(DNS_CRYPTO_PK11_LIBS)
+
+ #
+ # was --with-randomdev specified?
+@@ -4010,7 +4013,10 @@ AC_CONFIG_FILES([
+ bin/confgen/unix/Makefile
+ bin/dig/Makefile
+ bin/dnssec/Makefile
++ bin/dnssec-pkcs11/Makefile
+ bin/named/Makefile
++ bin/named-pkcs11/Makefile
++ bin/named-pkcs11/unix/Makefile
+ bin/named/unix/Makefile
+ bin/nsupdate/Makefile
+ bin/pkcs11/Makefile
+@@ -4088,11 +4094,19 @@ AC_CONFIG_FILES([
+ lib/dns/include/dns/Makefile
+ lib/dns/include/dst/Makefile
+ lib/dns/tests/Makefile
++ lib/dns-pkcs11/Makefile
++ lib/dns-pkcs11/include/Makefile
++ lib/dns-pkcs11/include/dns/Makefile
++ lib/dns-pkcs11/include/dst/Makefile
+ lib/export/Makefile
+ lib/export/dns/Makefile
+ lib/export/dns/include/Makefile
+ lib/export/dns/include/dns/Makefile
+ lib/export/dns/include/dst/Makefile
++ lib/export/dns-pkcs11/Makefile
++ lib/export/dns-pkcs11/include/Makefile
++ lib/export/dns-pkcs11/include/dns/Makefile
++ lib/export/dns-pkcs11/include/dst/Makefile
+ lib/export/irs/Makefile
+ lib/export/irs/include/Makefile
+ lib/export/irs/include/irs/Makefile
+@@ -4106,6 +4120,16 @@ AC_CONFIG_FILES([
+ lib/export/isc/unix/Makefile
+ lib/export/isc/unix/include/Makefile
+ lib/export/isc/unix/include/isc/Makefile
++ lib/export/isc-pkcs11/$thread_dir/Makefile
++ lib/export/isc-pkcs11/$thread_dir/include/Makefile
++ lib/export/isc-pkcs11/$thread_dir/include/isc/Makefile
++ lib/export/isc-pkcs11/Makefile
++ lib/export/isc-pkcs11/include/Makefile
++ lib/export/isc-pkcs11/include/isc/Makefile
++ lib/export/isc-pkcs11/nls/Makefile
++ lib/export/isc-pkcs11/unix/Makefile
++ lib/export/isc-pkcs11/unix/include/Makefile
++ lib/export/isc-pkcs11/unix/include/isc/Makefile
+ lib/export/isccfg/Makefile
+ lib/export/isccfg/include/Makefile
+ lib/export/isccfg/include/isccfg/Makefile
+@@ -4134,6 +4158,24 @@ AC_CONFIG_FILES([
+ lib/isc/unix/include/Makefile
+ lib/isc/unix/include/isc/Makefile
+ lib/isc/unix/include/pkcs11/Makefile
++ lib/isc-pkcs11/$arch/Makefile
++ lib/isc-pkcs11/$arch/include/Makefile
++ lib/isc-pkcs11/$arch/include/isc/Makefile
++ lib/isc-pkcs11/$thread_dir/Makefile
++ lib/isc-pkcs11/$thread_dir/include/Makefile
++ lib/isc-pkcs11/$thread_dir/include/isc/Makefile
++ lib/isc-pkcs11/Makefile
++ lib/isc-pkcs11/include/Makefile
++ lib/isc-pkcs11/include/isc/Makefile
++ lib/isc-pkcs11/include/isc/platform.h
++ lib/isc-pkcs11/include/pk11/Makefile
++ lib/isc-pkcs11/include/pkcs11/Makefile
++ lib/isc-pkcs11/tests/Makefile
++ lib/isc-pkcs11/nls/Makefile
++ lib/isc-pkcs11/unix/Makefile
++ lib/isc-pkcs11/unix/include/Makefile
++ lib/isc-pkcs11/unix/include/isc/Makefile
++ lib/isc-pkcs11/unix/include/pkcs11/Makefile
+ lib/isccc/Makefile
+ lib/isccc/include/Makefile
+ lib/isccc/include/isccc/Makefile
+diff --git a/lib/Makefile.in b/lib/Makefile.in
+index 8dc1d38..8e48d5e 100644
+--- a/lib/Makefile.in
++++ b/lib/Makefile.in
+@@ -23,7 +23,7 @@ top_srcdir = @top_srcdir@
+ # Attempt to disable parallel processing.
+ .NOTPARALLEL:
+ .NO_PARALLEL:
+-SUBDIRS = isc isccc dns isccfg bind9 lwres tests
++SUBDIRS = isc isccc dns isccfg bind9 lwres tests isc-pkcs11 dns-pkcs11
+ TARGETS =
+
+ @BIND9_MAKE_RULES@
+diff --git a/lib/dns-pkcs11/Makefile.in b/lib/dns-pkcs11/Makefile.in
+index 4204121..d26b84e 100644
+--- a/lib/dns-pkcs11/Makefile.in
++++ b/lib/dns-pkcs11/Makefile.in
+@@ -27,16 +27,16 @@ top_srcdir = @top_srcdir@
+
+ USE_ISC_SPNEGO = @USE_ISC_SPNEGO@
+
+-CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \
++CINCLUDES = -I. -I${top_srcdir}/lib/dns-pkcs11 -Iinclude ${DNS_PKCS11_INCLUDES} ${ISC_PKCS11_INCLUDES} \
+ @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+
+-CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ ${USE_ISC_SPNEGO}
++CDEFINES = -DUSE_MD5 @CRYPTO_PK11@ @USE_GSSAPI@ ${USE_ISC_SPNEGO}
+
+ CWARNINGS =
+
+-ISCLIBS = ../../lib/isc/libisc.@A@
++ISCLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+
+-ISCDEPLIBS = ../../lib/isc/libisc.@A@
++ISCDEPLIBS = ../../lib/isc-pkcs11/libisc-pkcs11.@A@
+
+ LIBS = @LIBS@
+
+@@ -132,27 +132,27 @@ dynamic_db.@O@: dynamic_db.c
+ -DDYNDB_LIBDIR=\"@libdir@/bind/\" \
+ -c ${srcdir}/dynamic_db.c
+
+-libdns.@SA@: ${OBJS}
++libdns-pkcs11.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+-libdns.la: ${OBJS}
++libdns-pkcs11.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns.la -rpath ${libdir} \
++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-pkcs11.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+- ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS}
++ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_PK11_LIBS@ ${LIBS}
+
+-timestamp: libdns.@A@
++timestamp: libdns-pkcs11.@A@
+ touch timestamp
+
+ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+ install:: timestamp installdirs
+- ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libdns.@A@ ${DESTDIR}${libdir}
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libdns-pkcs11.@A@ ${DESTDIR}${libdir}
+
+ clean distclean::
+- rm -f libdns.@A@ timestamp
++ rm -f libdns-pkcs11.@A@ timestamp
+ rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h
+ rm -f include/dns/rdatastruct.h
+
+@@ -182,7 +182,7 @@ code.h: gen
+ ./gen -s ${srcdir} > code.h
+
+ gen: gen.c
+- ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc/include \
++ ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc-pkcs11/include \
+ ${BUILD_CPPFLAGS} ${BUILD_LDFLAGS} -o $@ ${srcdir}/gen.c ${BUILD_LIBS}
+
+ rbtdb64.@O@: rbtdb.c
+diff --git a/lib/export/Makefile.in b/lib/export/Makefile.in
+index 1fd7216..a8a1342 100644
+--- a/lib/export/Makefile.in
++++ b/lib/export/Makefile.in
+@@ -21,7 +21,7 @@ top_srcdir = @top_srcdir@
+ # Attempt to disable parallel processing.
+ .NOTPARALLEL:
+ .NO_PARALLEL:
+-SUBDIRS = isc dns isccfg irs samples
++SUBDIRS = isc dns isccfg irs samples isc-pkcs11 dns-pkcs11
+ TARGETS =
+
+ @BIND9_MAKE_RULES@
+diff --git a/lib/export/dns-pkcs11/Makefile.in b/lib/export/dns-pkcs11/Makefile.in
+index e10bf59..669509f 100644
+--- a/lib/export/dns-pkcs11/Makefile.in
++++ b/lib/export/dns-pkcs11/Makefile.in
+@@ -15,7 +15,7 @@
+ # $Id$
+
+ top_srcdir = @top_srcdir@
+-srcdir = @top_srcdir@/lib/dns
++srcdir = @top_srcdir@/lib/dns-pkcs11
+ export_srcdir = @top_srcdir@/lib/export
+
+ # Attempt to disable parallel processing.
+@@ -28,16 +28,16 @@ export_srcdir = @top_srcdir@/lib/export
+
+ @BIND9_MAKE_INCLUDES@
+
+-CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \
+- ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
++CINCLUDES = -I. -I${top_srcdir}/lib/dns-pkcs11 -Iinclude ${DNS_PKCS11_INCLUDES} -I${export_srcdir}/isc-pkcs11/include \
++ ${ISC_PKCS11_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+
+-CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@
++CDEFINES = -DUSE_MD5 @CRYPTO_PK11@ @USE_GSSAPI@
+
+ CWARNINGS =
+
+-ISCLIBS = ../isc/libisc-export.@A@
++ISCLIBS = ../isc-pkcs11/libisc-pkcs11-export.@A@
+
+-ISCDEPLIBS = ../isc/libisc-export.@A@
++ISCDEPLIBS = ../isc-pkcs11/libisc-pkcs11-export.@A@
+
+ LIBS = @LIBS@
+
+@@ -116,29 +116,29 @@ version.@O@: ${srcdir}/version.c
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+-libdns-export.@SA@: ${OBJS}
++libdns-pkcs11-export.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+-libdns-export.la: ${OBJS}
++libdns-pkcs11-export.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-export.la \
++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libdns-pkcs11-export.la \
+ -rpath ${export_libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+- ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS}
++ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_PK11_LIBS@ ${LIBS}
+
+-timestamp: libdns-export.@A@
++timestamp: libdns-pkcs11-export.@A@
+ touch timestamp
+
+ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir}
+
+ install:: timestamp installdirs
+- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-export.@A@ \
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libdns-pkcs11-export.@A@ \
+ ${DESTDIR}${export_libdir}/
+
+ clean distclean::
+- rm -f libdns-export.@A@ timestamp
++ rm -f libdns-pkcs11-export.@A@ timestamp
+ rm -f gen code.h include/dns/enumtype.h include/dns/enumclass.h
+ rm -f include/dns/rdatastruct.h
+
+diff --git a/lib/export/isc-pkcs11/Makefile.in b/lib/export/isc-pkcs11/Makefile.in
+index 70f2a77..25bfd4d 100644
+--- a/lib/export/isc-pkcs11/Makefile.in
++++ b/lib/export/isc-pkcs11/Makefile.in
+@@ -15,7 +15,7 @@
+ # $Id: Makefile.in,v 1.8 2010/06/09 23:50:58 tbox Exp $
+
+ top_srcdir = @top_srcdir@
+-srcdir = @top_srcdir@/lib/isc
++srcdir = @top_srcdir@/lib/isc-pkcs11
+ export_srcdir = @top_srcdir@/lib/export
+
+ @BIND9_VERSION@
+@@ -25,9 +25,9 @@ export_srcdir = @top_srcdir@/lib/export
+ CINCLUDES = -I${srcdir}/unix/include \
+ -I${srcdir}/@ISC_THREAD_DIR@/include \
+ -I${srcdir}/@ISC_ARCH_DIR@/include \
+- -I${export_srcdir}/isc/include -I${srcdir}/include \
++ -I${export_srcdir}/isc-pkcs11/include -I${srcdir}/include \
+ @ISC_OPENSSL_INC@
+-CDEFINES = @CRYPTO@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \
++CDEFINES = @CRYPTO_PK11@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \
+ -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \
+ -DUSE_TIMERIMPREGISTER
+ CWARNINGS =
+@@ -121,26 +121,26 @@ version.@O@: ${srcdir}/version.c
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+-libisc-export.@SA@: ${OBJS}
++libisc-pkcs11-export.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+-libisc-export.la: ${OBJS}
++libisc-pkcs11-export.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-export.la \
++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11-export.la \
+ -rpath ${export_libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${LIBS}
+
+-timestamp: libisc-export.@A@
++timestamp: libisc-pkcs11-export.@A@
+ touch timestamp
+
+ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${export_libdir}
+
+ install:: timestamp installdirs
+- ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc-export.@A@ \
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} libisc-pkcs11-export.@A@ \
+ ${DESTDIR}${export_libdir}
+
+ clean distclean::
+- rm -f libisc-export.@A@ libisc-export.la timestamp
++ rm -f libisc-pkcs11-export.@A@ libisc-pkcs11-export.la timestamp
+diff --git a/lib/isc-pkcs11/Makefile.in b/lib/isc-pkcs11/Makefile.in
+index 0fbedc3..de2977d 100644
+--- a/lib/isc-pkcs11/Makefile.in
++++ b/lib/isc-pkcs11/Makefile.in
+@@ -31,8 +31,8 @@ CINCLUDES = -I${srcdir}/unix/include \
+ -I${srcdir}/@ISC_THREAD_DIR@/include \
+ -I${srcdir}/@ISC_ARCH_DIR@/include \
+ -I./include \
+- -I${srcdir}/include @ISC_OPENSSL_INC@ ${DNS_INCLUDES}
+-CDEFINES = @CRYPTO@ -DPK11_LIB_LOCATION=\"${PROVIDER}\"
++ -I${srcdir}/include ${DNS_PKCS11_INCLUDES}
++CDEFINES = @CRYPTO_PK11@ -DPK11_LIB_LOCATION=\"${PROVIDER}\"
+ CWARNINGS =
+
+ # Alphabetically
+@@ -111,35 +111,35 @@ version.@O@: version.c
+ -DLIBAGE=${LIBAGE} \
+ -c ${srcdir}/version.c
+
+-libisc.@SA@: ${OBJS} ${SYMTBLOBJS}
++libisc-pkcs11.@SA@: ${OBJS} ${SYMTBLOBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS} ${SYMTBLOBJS}
+ ${RANLIB} $@
+
+-libisc-nosymtbl.@SA@: ${OBJS}
++libisc-pkcs11-nosymtbl.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+-libisc.la: ${OBJS} ${SYMTBLOBJS}
++libisc-pkcs11.la: ${OBJS} ${SYMTBLOBJS}
+ ${LIBTOOL_MODE_LINK} \
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \
++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${SYMTBLOBJS} ${LIBS}
+
+-libisc-nosymtbl.la: ${OBJS}
++libisc-pkcs11-nosymtbl.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-nosymtbl.la -rpath ${libdir} \
++ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc-pkcs11-nosymtbl.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${LIBS}
+
+-timestamp: libisc.@A@ libisc-nosymtbl.@A@
++timestamp: libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@
+ touch timestamp
+
+ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+ install:: timestamp installdirs
+- ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libisc.@A@ ${DESTDIR}${libdir}
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libisc-pkcs11.@A@ ${DESTDIR}${libdir}
+
+ clean distclean::
+- rm -f libisc.@A@ libisc-nosymtbl.@A@ libisc.la \
+- libisc-nosymtbl.la timestamp
++ rm -f libisc-pkcs11.@A@ libisc-pkcs11-nosymtbl.@A@ libisc-pkcs11.la \
++ libisc-pkcs11-nosymtbl.la timestamp
+diff --git a/make/includes.in b/make/includes.in
+index f2f1b3f..639477c 100644
+--- a/make/includes.in
++++ b/make/includes.in
+@@ -46,3 +46,13 @@ BIND9_INCLUDES = @BIND9_BIND9_BUILDINCLUDE@ \
+
+ TEST_INCLUDES = \
+ -I${top_srcdir}/lib/tests/include
++
++ISC_PKCS11_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \
++ -I${top_srcdir}/lib/isc-pkcs11 \
++ -I${top_srcdir}/lib/isc-pkcs11/include \
++ -I${top_srcdir}/lib/isc-pkcs11/unix/include \
++ -I${top_srcdir}/lib/isc-pkcs11/@ISC_THREAD_DIR@/include \
++ -I${top_srcdir}/lib/isc-pkcs11/@ISC_ARCH_DIR@/include
++
++DNS_PKCS11_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \
++ -I${top_srcdir}/lib/dns-pkcs11/include
diff --git a/bind-9.9-native-pkcs11.patch b/bind-9.9-native-pkcs11.patch
new file mode 100644
index 0000000..2499834
--- /dev/null
+++ b/bind-9.9-native-pkcs11.patch
@@ -0,0 +1,19840 @@
+diff -up bind-9.9.6/acconfig.h.native_pkcs11 bind-9.9.6/acconfig.h
+--- bind-9.9.6/acconfig.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/acconfig.h 2014-10-09 13:29:59.168238327 +0200
+@@ -135,14 +135,11 @@ int sigwait(const unsigned int *set, int
+ /** define if you have strerror in the C library. */
+ #undef HAVE_STRERROR
+
+-/** Define if you are running under Compaq TruCluster. */
+-#undef HAVE_TRUCLUSTER
+-
+ /* Define if OpenSSL includes DSA support */
+ #undef HAVE_OPENSSL_DSA
+
+-/* Define if OpenSSL includes ECDSA support */
+-#undef HAVE_OPENSSL_ECDSA
++/* Define if you have getpassphrase in the C library. */
++#undef HAVE_GETPASSPHRASE
+
+ /* Define to the length type used by the socket API (socklen_t, size_t, int). */
+ #undef ISC_SOCKADDR_LEN_T
+diff -up bind-9.9.6/bin/check/Makefile.in.native_pkcs11 bind-9.9.6/bin/check/Makefile.in
+--- bind-9.9.6/bin/check/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/check/Makefile.in 2014-10-09 13:29:59.168238327 +0200
+@@ -75,7 +75,8 @@ named-checkconf@EXEEXT@: named-checkconf
+ export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+-named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
++named-checkzone@EXEEXT@: named-checkzone.@O@ check-tool.@O@ \
++ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="named-checkzone.@O@ check-tool.@O@"; \
+ export LIBS0="${ISCCFGLIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+diff -up bind-9.9.6/bin/dig/dighost.c.native_pkcs11 bind-9.9.6/bin/dig/dighost.c
+--- bind-9.9.6/bin/dig/dighost.c.native_pkcs11 2014-10-09 13:29:59.160238317 +0200
++++ bind-9.9.6/bin/dig/dighost.c 2014-10-09 13:29:59.169238328 +0200
+@@ -105,6 +105,10 @@
+
+ #include <dig/dig.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #if ! defined(NS_INADDRSZ)
+ #define NS_INADDRSZ 4
+ #endif
+@@ -1369,6 +1373,11 @@ setup_libs(void) {
+
+ debug("setup_libs()");
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
++ dns_result_register();
++
+ result = isc_net_probeipv4();
+ if (result == ISC_R_SUCCESS)
+ have_ipv4 = ISC_TRUE;
+@@ -1427,8 +1436,6 @@ setup_libs(void) {
+
+ result = isc_mutex_init(&lookup_lock);
+ check_result(result, "isc_mutex_init");
+-
+- dns_result_register();
+ }
+
+ /*%
+diff -up bind-9.9.6/bin/dig/Makefile.in.native_pkcs11 bind-9.9.6/bin/dig/Makefile.in
+--- bind-9.9.6/bin/dig/Makefile.in.native_pkcs11 2014-10-09 13:29:59.131238278 +0200
++++ bind-9.9.6/bin/dig/Makefile.in 2014-10-09 13:29:59.168238327 +0200
+@@ -28,7 +28,7 @@ READLINE_LIB = @READLINE_LIB@
+ CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISC_INCLUDES} ${LWRES_INCLUDES} ${ISCCFG_INCLUDES}
+
+-CDEFINES = -DVERSION=\"${VERSION}\"
++CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@
+ CWARNINGS =
+
+ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+@@ -44,13 +44,13 @@ BIND9DEPLIBS = ../../lib/bind9/libbind9.
+ ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+
+-DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} \
+- ${LWRESDEPLIBS}
++DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \
++ ${ISCCFGDEPLIBS} ${LWRESDEPLIBS}
+
+-LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
++LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
+ ${ISCLIBS} @IDNLIBS@ @LIBS@ -lidn
+
+-NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
++NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
+ ${ISCNOSYMLIBS} @IDNLIBS@ @LIBS@ -lidn
+
+ SUBDIRS =
+@@ -75,14 +75,17 @@ EXT_CFLAGS = -DWITH_LIBIDN
+
+ dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \
++ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+ host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \
++ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+ nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="nslookup.@O@ dighost.@O@ ${READLINE_LIB} ${UOBJS}"; \
++ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+ doc man:: ${MANOBJS}
+diff -up bind-9.9.6/bin/dnssec/dnssec-dsfromkey.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-dsfromkey.c
+--- bind-9.9.6/bin/dnssec/dnssec-dsfromkey.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-dsfromkey.c 2014-10-09 13:29:59.170238330 +0200
+@@ -47,6 +47,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ #ifndef PATH_MAX
+@@ -369,6 +373,9 @@ main(int argc, char **argv) {
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+@@ -452,7 +459,7 @@ main(int argc, char **argv) {
+ else if (strcasecmp(algname, "SHA256") == 0 ||
+ strcasecmp(algname, "SHA-256") == 0)
+ dtype = DNS_DSDIGEST_SHA256;
+-#ifdef HAVE_OPENSSL_GOST
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
+ else if (strcasecmp(algname, "GOST") == 0)
+ dtype = DNS_DSDIGEST_GOST;
+ #endif
+diff -up bind-9.9.6/bin/dnssec/dnssec-importkey.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-importkey.c
+--- bind-9.9.6/bin/dnssec/dnssec-importkey.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-importkey.c 2014-10-09 13:36:48.705781339 +0200
+@@ -47,6 +47,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ #ifndef PATH_MAX
+@@ -303,6 +307,9 @@ main(int argc, char **argv) {
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+diff -up bind-9.9.6/bin/dnssec/dnssec-importkey.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-importkey.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-importkey.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-importkey.docbook 2014-10-09 13:29:59.171238331 +0200
+@@ -212,6 +212,16 @@
+ </refsect1>
+
+ <refsect1>
++ <title>FILES</title>
++ <para>
++ A keyfile can be designed by the key identification
++ <filename>Knnnn.+aaa+iiiii</filename> or the full file name
++ <filename>Knnnn.+aaa+iiiii.key</filename> as generated by
++ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>.
++ </para>
++ </refsect1>
++
++ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+diff -up bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.c
+--- bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.c 2014-10-09 13:52:31.245043631 +0200
+@@ -41,6 +41,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ #define MAX_RSA 4096 /* should be long enough... */
+@@ -74,10 +78,15 @@ usage(void) {
+ "NSEC3RSASHA1 if using -3)\n");
+ fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
+ fprintf(stderr, " -c class (default: IN)\n");
+-#ifdef USE_PKCS11
+- fprintf(stderr, " -E enginename (default: pkcs11)\n");
++ fprintf(stderr, " -E <engine>:\n");
++#if defined(PKCS11CRYPTO)
++ fprintf(stderr, " path to PKCS#11 provider library "
++ "(default is %s)\n", PK11_LIB_LOCATION);
++#elif defined(USE_PKCS11)
++ fprintf(stderr, " name of an OpenSSL engine to use "
++ "(default is \"pkcs11\")\n");
+ #else
+- fprintf(stderr, " -E enginename\n");
++ fprintf(stderr, " name of an OpenSSL engine to use\n");
+ #endif
+ fprintf(stderr, " -f keyflag: KSK | REVOKE\n");
+ fprintf(stderr, " -K directory: directory in which to place "
+@@ -122,7 +131,7 @@ main(int argc, char **argv) {
+ const char *predecessor = NULL;
+ dst_key_t *prevkey = NULL;
+ #ifdef USE_PKCS11
+- const char *engine = "pkcs11";
++ const char *engine = PKCS11_ENGINE;
+ #else
+ const char *engine = NULL;
+ #endif
+@@ -168,6 +177,9 @@ main(int argc, char **argv) {
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+@@ -556,7 +568,7 @@ main(int argc, char **argv) {
+
+ /* associate the key */
+ ret = dst_key_fromlabel(name, alg, flags, protocol,
+- rdclass, engine, label, NULL, mctx, &key);
++ rdclass, "pkcs11", label, NULL, mctx, &key);
+ isc_entropy_stopcallbacksources(ectx);
+
+ if (ret != ISC_R_SUCCESS) {
+@@ -564,7 +576,7 @@ main(int argc, char **argv) {
+ char algstr[DNS_SECALG_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_secalg_format(alg, algstr, sizeof(algstr));
+- fatal("failed to get key %s/%s: %s\n",
++ fatal("failed to get key %s/%s: %s",
+ namestr, algstr, isc_result_totext(ret));
+ /* NOTREACHED */
+ exit(-1);
+diff -up bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-keyfromlabel.docbook 2014-10-09 13:29:59.171238331 +0200
+@@ -139,8 +139,15 @@
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+- Specifies the name of the crypto hardware (OpenSSL engine).
+- When compiled with PKCS#11 support it defaults to "pkcs11".
++ Specifies the cryptographic hardware to use.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -149,9 +156,32 @@
+ <term>-l <replaceable class="parameter">label</replaceable></term>
+ <listitem>
+ <para>
+- Specifies the label of the key pair in the crypto hardware.
+- The label may be preceded by an optional OpenSSL engine name,
+- separated by a colon, as in "pkcs11:keylabel".
++ Specifies the label for a key pair in the crypto hardware.
++ </para>
++ <para>
++ When <acronym>BIND</acronym> 9 is built with OpenSSL-based
++ PKCS#11 support, the label is an arbitrary string that
++ identifies a particular key. It may be preceded by an
++ optional OpenSSL engine name, followed by a colon, as in
++ "pkcs11:<replaceable>keylabel<replaceable>".
++ </para>
++ <para>
++ When <acronym>BIND</acronym> 9 is built with native PKCS#11
++ support, the label is a PKCS#11 URI string in the format
++ "pkcs11:<option>keyword</option>=<replaceable>value</replaceable><optional>;<option>keyword</option>=<replaceable>value</replaceable>;...</optional>"
++ Keywords include "token", which identifies the HSM; "object", which
++ identifies the key; and "pin-source", which identifies a file from
++ which the HSM's PIN code can be obtained. The label will be
++ stored in the on-disk "private" file.
++ </para>
++ <para>
++ If the label contains a
++ <option>pin-source</option> field, tools using the generated
++ key files will be able to use the HSM for signing and other
++ operations without any need for an operator to manually enter
++ a PIN. Note: Making the HSM's PIN accessible in this manner
++ may reduce the security advantage of using an HSM; be sure
++ this is what you want to do before making use of this feature.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -488,7 +518,8 @@
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+- <citetitle>RFC 4034</citetitle>.
++ <citetitle>RFC 4034</citetitle>,
++ <citetitle>The PKCS#11 URI Scheme (draft-pechanec-pkcs11uri-13)</citetitle>.
+ </para>
+ </refsect1>
+
+diff -up bind-9.9.6/bin/dnssec/dnssec-keygen.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-keygen.c
+--- bind-9.9.6/bin/dnssec/dnssec-keygen.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-keygen.c 2014-10-09 13:29:59.172238332 +0200
+@@ -56,6 +56,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ #define MAX_RSA 4096 /* should be long enough... */
+@@ -117,10 +121,15 @@ usage(void) {
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
+ fprintf(stderr, " -c <class>: (default: IN)\n");
+ fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
+-#ifdef USE_PKCS11
+- fprintf(stderr, " -E <engine name> (default \"pkcs11\")\n");
++ fprintf(stderr, " -E <engine>:\n");
++#if defined(PKCS11CRYPTO)
++ fprintf(stderr, " path to PKCS#11 provider library "
++ "(default is %s)\n", PK11_LIB_LOCATION);
++#elif defined(USE_PKCS11)
++ fprintf(stderr, " name of an OpenSSL engine to use "
++ "(default is \"pkcs11\")\n");
+ #else
+- fprintf(stderr, " -E <engine name>\n");
++ fprintf(stderr, " name of an OpenSSL engine to use\n");
+ #endif
+ fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n");
+ fprintf(stderr, " -g <generator>: use specified generator "
+@@ -132,7 +141,6 @@ usage(void) {
+ "records with (default: 0)\n");
+ fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; "
+ "use KEY for SIG(0))\n");
+- fprintf(stderr, " ECCGOST:\tignored\n");
+ fprintf(stderr, " -t <type>: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+@@ -222,7 +230,7 @@ main(int argc, char **argv) {
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+ #ifdef USE_PKCS11
+- const char *engine = "pkcs11";
++ const char *engine = PKCS11_ENGINE;
+ #else
+ const char *engine = NULL;
+ #endif
+@@ -249,6 +257,9 @@ main(int argc, char **argv) {
+ if (argc == 1)
+ usage();
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+diff -up bind-9.9.6/bin/dnssec/dnssec-keygen.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-keygen.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-keygen.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-keygen.docbook 2014-10-09 13:29:59.172238332 +0200
+@@ -225,10 +225,15 @@
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+- Uses a crypto hardware (OpenSSL engine) for random number
+- and, when supported, key generation. When compiled with PKCS#11
+- support it defaults to pkcs11; the empty name resets it to
+- no engine.
++ Specifies the cryptographic hardware to use, when applicable.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+diff -up bind-9.9.6/bin/dnssec/dnssec-revoke.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-revoke.c
+--- bind-9.9.6/bin/dnssec/dnssec-revoke.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-revoke.c 2014-10-09 13:29:59.172238332 +0200
+@@ -36,6 +36,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ const char *program = "dnssec-revoke";
+@@ -51,7 +55,10 @@ usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+-#ifdef USE_PKCS11
++#if defined(PKCS11CRYPTO)
++ fprintf(stderr, " -E engine: specify PKCS#11 provider "
++ "(default: %s)\n", PK11_LIB_LOCATION);
++#elif defined(USE_PKCS11)
+ fprintf(stderr, " -E engine: specify OpenSSL engine "
+ "(default \"pkcs11\")\n");
+ #else
+@@ -75,7 +82,7 @@ int
+ main(int argc, char **argv) {
+ isc_result_t result;
+ #ifdef USE_PKCS11
+- const char *engine = "pkcs11";
++ const char *engine = PKCS11_ENGINE;
+ #else
+ const char *engine = NULL;
+ #endif
+@@ -99,6 +106,9 @@ main(int argc, char **argv) {
+ if (result != ISC_R_SUCCESS)
+ fatal("Out of memory");
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+diff -up bind-9.9.6/bin/dnssec/dnssec-revoke.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-revoke.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-revoke.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-revoke.docbook 2014-10-09 13:29:59.172238332 +0200
+@@ -119,8 +119,15 @@
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+- Use the given OpenSSL engine. When compiled with PKCS#11 support
+- it defaults to pkcs11; the empty name resets it to no engine.
++ Specifies the cryptographic hardware to use, when applicable.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+diff -up bind-9.9.6/bin/dnssec/dnssec-settime.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-settime.c
+--- bind-9.9.6/bin/dnssec/dnssec-settime.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-settime.c 2014-10-09 13:29:59.172238332 +0200
+@@ -39,6 +39,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ const char *program = "dnssec-settime";
+@@ -55,7 +59,10 @@ usage(void) {
+ fprintf(stderr, " %s [options] keyfile\n\n", program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "General options:\n");
+-#ifdef USE_PKCS11
++#if defined(PKCS11CRYPTO)
++ fprintf(stderr, " -E engine: specify PKCS#11 provider "
++ "(default: %s)\n", PK11_LIB_LOCATION);
++#elif defined(USE_PKCS11)
+ fprintf(stderr, " -E engine: specify OpenSSL engine "
+ "(default \"pkcs11\")\n");
+ #else
+@@ -118,7 +125,7 @@ int
+ main(int argc, char **argv) {
+ isc_result_t result;
+ #ifdef USE_PKCS11
+- const char *engine = "pkcs11";
++ const char *engine = PKCS11_ENGINE;
+ #else
+ const char *engine = NULL;
+ #endif
+@@ -164,6 +171,9 @@ main(int argc, char **argv) {
+
+ setup_logging(verbose, mctx, &log);
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+diff -up bind-9.9.6/bin/dnssec/dnssec-settime.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-settime.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-settime.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-settime.docbook 2014-10-09 13:29:59.173238334 +0200
+@@ -163,8 +163,15 @@
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+- Use the given OpenSSL engine. When compiled with PKCS#11 support
+- it defaults to pkcs11; the empty name resets it to no engine.
++ Specifies the cryptographic hardware to use, when applicable.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+diff -up bind-9.9.6/bin/dnssec/dnssec-signzone.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-signzone.c
+--- bind-9.9.6/bin/dnssec/dnssec-signzone.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-signzone.c 2014-10-09 13:29:59.173238334 +0200
+@@ -84,6 +84,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ #ifndef PATH_MAX
+@@ -2957,7 +2961,10 @@ usage(void) {
+ fprintf(stderr, "verify generated signatures\n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-E engine:\n");
+-#ifdef USE_PKCS11
++#if defined(PKCS11CRYPTO)
++ fprintf(stderr, "\t\tpath to PKCS#11 provider library "
++ "(default is %s)\n", PK11_LIB_LOCATION);
++#elif defined(USE_PKCS11)
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+ #else
+@@ -3056,7 +3063,7 @@ main(int argc, char *argv[]) {
+ isc_log_t *log = NULL;
+ isc_boolean_t pseudorandom = ISC_FALSE;
+ #ifdef USE_PKCS11
+- const char *engine = "pkcs11";
++ const char *engine = PKCS11_ENGINE;
+ #else
+ const char *engine = NULL;
+ #endif
+@@ -3109,6 +3116,9 @@ main(int argc, char *argv[]) {
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+diff -up bind-9.9.6/bin/dnssec/dnssec-signzone.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-signzone.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-signzone.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-signzone.docbook 2014-10-09 13:29:59.173238334 +0200
+@@ -178,10 +178,17 @@
+ <term>-E <replaceable class="parameter">engine</replaceable></term>
+ <listitem>
+ <para>
+- Uses a crypto hardware (OpenSSL engine) for the crypto operations
+- it supports, for instance signing with private keys from
+- a secure key store. When compiled with PKCS#11 support
+- it defaults to pkcs11; the empty name resets it to no engine.
++ When applicable, specifies the hardware to use for
++ cryptographic operations, such as a secure key store used
++ for signing.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+diff -up bind-9.9.6/bin/dnssec/dnssectool.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssectool.c
+diff -up bind-9.9.6/bin/dnssec/dnssec-verify.c.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-verify.c
+--- bind-9.9.6/bin/dnssec/dnssec-verify.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-verify.c 2014-10-09 13:29:59.173238334 +0200
+@@ -67,6 +67,10 @@
+
+ #include <dst/dst.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
++
+ #include "dnssectool.h"
+
+ const char *program = "dnssec-verify";
+@@ -136,7 +140,10 @@ usage(void) {
+ fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-E engine:\n");
+-#ifdef USE_PKCS11
++#if defined(PKCS11CRYPTO)
++ fprintf(stderr, "\t\tpath to PKCS#11 provider library "
++ "(default is %s)\n", PK11_LIB_LOCATION);
++#elif defined(USE_PKCS11)
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+ #else
+@@ -155,7 +162,7 @@ main(int argc, char *argv[]) {
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ #ifdef USE_PKCS11
+- const char *engine = "pkcs11";
++ const char *engine = PKCS11_ENGINE;
+ #else
+ const char *engine = NULL;
+ #endif
+@@ -195,6 +202,9 @@ main(int argc, char *argv[]) {
+ if (result != ISC_R_SUCCESS)
+ fatal("out of memory");
+
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+ dns_result_register();
+
+ isc_commandline_errprint = ISC_FALSE;
+diff -up bind-9.9.6/bin/dnssec/dnssec-verify.docbook.native_pkcs11 bind-9.9.6/bin/dnssec/dnssec-verify.docbook
+--- bind-9.9.6/bin/dnssec/dnssec-verify.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/dnssec-verify.docbook 2014-10-09 13:29:59.174238335 +0200
+@@ -79,6 +79,23 @@
+ </varlistentry>
+
+ <varlistentry>
++ <term>-E <replaceable class="parameter">engine</replaceable></term>
++ <listitem>
++ <para>
++ Specifies the cryptographic hardware to use, when applicable.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
++ </para>
++ </listitem>
++ </varlistentry>
++
++ <varlistentry>
+ <term>-I <replaceable class="parameter">input-format</replaceable></term>
+ <listitem>
+ <para>
+diff -up bind-9.9.6/bin/dnssec/Makefile.in.native_pkcs11 bind-9.9.6/bin/dnssec/Makefile.in
+--- bind-9.9.6/bin/dnssec/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/dnssec/Makefile.in 2014-10-09 13:29:59.170238330 +0200
+@@ -25,7 +25,8 @@ top_srcdir = @top_srcdir@
+
+ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+-CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@
++CDEFINES = -DVERSION=\"${VERSION}\" @USE_PKCS11@ @PKCS11_ENGINE@ \
++ @CRYPTO@ -DPK11_LIB_LOCATION=\"@PKCS11_PROVIDER@\"
+ CWARNINGS =
+
+ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+diff -up bind-9.9.6/bin/named/include/named/globals.h.native_pkcs11 bind-9.9.6/bin/named/include/named/globals.h
+--- bind-9.9.6/bin/named/include/named/globals.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/named/include/named/globals.h 2014-10-09 13:29:59.174238335 +0200
+@@ -147,8 +147,8 @@ EXTERN const char * lwresd_g_defaultpid
+
+ EXTERN const char * ns_g_username INIT(NULL);
+
+-#ifdef USE_PKCS11
+-EXTERN const char * ns_g_engine INIT("pkcs11");
++#if defined(USE_PKCS11)
++EXTERN const char * ns_g_engine INIT(PKCS11_ENGINE);
+ #else
+ EXTERN const char * ns_g_engine INIT(NULL);
+ #endif
+diff -up bind-9.9.6/bin/named/main.c.native_pkcs11 bind-9.9.6/bin/named/main.c
+--- bind-9.9.6/bin/named/main.c.native_pkcs11 2014-10-09 13:29:59.125238270 +0200
++++ bind-9.9.6/bin/named/main.c 2014-10-09 13:29:59.175238336 +0200
+@@ -49,6 +49,9 @@
+ #include <dns/view.h>
+
+ #include <dst/result.h>
++#ifdef PKCS11CRYPTO
++#include <pk11/result.h>
++#endif
+
+ #include <dlz/dlz_dlopen_driver.h>
+
+@@ -1111,6 +1114,9 @@ main(int argc, char *argv[]) {
+ dns_result_register();
+ dst_result_register();
+ isccc_result_register();
++#ifdef PKCS11CRYPTO
++ pk11_result_register();
++#endif
+
+ parse_command_line(argc, argv);
+
+diff -up bind-9.9.6/bin/named/Makefile.in.native_pkcs11 bind-9.9.6/bin/named/Makefile.in
+--- bind-9.9.6/bin/named/Makefile.in.native_pkcs11 2014-10-09 13:29:59.121238265 +0200
++++ bind-9.9.6/bin/named/Makefile.in 2014-10-09 13:29:59.174238335 +0200
+@@ -51,7 +51,7 @@ CINCLUDES = -I${srcdir}/include -I${srcd
+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
+ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@
+
+-CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @USE_OPENSSL@
++CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@
+
+ CWARNINGS =
+
+diff -up bind-9.9.6/bin/named/named.docbook.native_pkcs11 bind-9.9.6/bin/named/named.docbook
+--- bind-9.9.6/bin/named/named.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/named/named.docbook 2014-10-09 13:29:59.175238336 +0200
+@@ -153,11 +153,17 @@
+ <term>-E <replaceable class="parameter">engine-name</replaceable></term>
+ <listitem>
+ <para>
+- Use a crypto hardware (OpenSSL engine) for the crypto operations
+- it supports, for instance re-signing with private keys from
+- a secure key store. When compiled with PKCS#11 support
+- <replaceable class="parameter">engine-name</replaceable>
+- defaults to pkcs11, the empty name resets it to no engine.
++ When applicable, specifies the hardware to use for
++ cryptographic operations, such as a secure key store used
++ for signing.
++ </para>
++ <para>
++ When BIND is built with OpenSSL PKCS#11 support, this defaults
++ to the string "pkcs11", which identifies an OpenSSL engine
++ that can drive a cryptographic accelerator or hardware service
++ module. When BIND is built with native PKCS#11 cryptography
++ (--enable-native-pkcs11), it defaults to the path of the PKCS#11
++ provider library specified via "--with-pkcs11".
+ </para>
+ </listitem>
+ </varlistentry>
+diff -up bind-9.9.6/bin/named/server.c.native_pkcs11 bind-9.9.6/bin/named/server.c
+--- bind-9.9.6/bin/named/server.c.native_pkcs11 2014-10-09 13:29:59.155238310 +0200
++++ bind-9.9.6/bin/named/server.c 2014-10-09 13:29:59.176238338 +0200
+@@ -6249,6 +6249,11 @@ ns_server_create(isc_mem_t *mctx, ns_ser
+ server->in_roothints = NULL;
+ server->blackholeacl = NULL;
+
++ /* Must be first. */
++ CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy,
++ ns_g_engine, ISC_ENTROPY_GOODONLY),
++ "initializing DST");
++
+ CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
+ &server->in_roothints),
+ "setting up root hints");
+@@ -6265,10 +6270,6 @@ ns_server_create(isc_mem_t *mctx, ns_ser
+ ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "allocating reload event");
+
+- CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy,
+- ns_g_engine, ISC_ENTROPY_GOODONLY),
+- "initializing DST");
+-
+ server->tkeyctx = NULL;
+ CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
+ &server->tkeyctx),
+diff -up bind-9.9.6/bin/nsupdate/Makefile.in.native_pkcs11 bind-9.9.6/bin/nsupdate/Makefile.in
+--- bind-9.9.6/bin/nsupdate/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/nsupdate/Makefile.in 2014-10-09 13:29:59.176238338 +0200
+@@ -48,9 +48,11 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libiscc
+
+ DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS}
+
+-LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@
++LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
++ ${ISCLIBS} @LIBS@
+
+-NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} ${ISCNOSYMLIBS} @LIBS@
++NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
++ ${ISCNOSYMLIBS} @LIBS@
+
+ SUBDIRS =
+
+diff -up bind-9.9.6/bin/pkcs11/Makefile.in.native_pkcs11 bind-9.9.6/bin/pkcs11/Makefile.in
+--- bind-9.9.6/bin/pkcs11/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/Makefile.in 2014-10-09 13:29:59.176238338 +0200
+@@ -20,38 +20,51 @@ top_srcdir = @top_srcdir@
+
+ @BIND9_MAKE_INCLUDES@
+
+-PROVIDER = @PKCS11_PROVIDER@
++CINCLUDES = ${ISC_INCLUDES}
+
+-CINCLUDES = -I${srcdir}/include -I${srcdir}/unix
++CDEFINES =
+
+-CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\"
++ISCLIBS = ../../lib/isc/libisc.@A@
+
+-# if FORCE_STATIC_PROVIDER: LIBS = ${PROVIDER}
+-LIBS = -ldl
++ISCDEPLIBS = ../../lib/isc/libisc.@A@
++
++DEPLIBS = ${ISCDEPLIBS}
+
+-SUBDIRS =
++# if FORCE_STATIC_PROVIDER: LIBS = ${PROVIDER}
++LIBS = ${ISCLIBS} @LIBS@
+
+-TARGETS = pkcs11-keygen@EXEEXT@ pkcs11-list@EXEEXT@ \
+- pkcs11-destroy@EXEEXT@
+-SRCS = pkcs11-keygen.c pkcs11-list.c pkcs11-destroy.c
++SUBDIRS = benchmarks
+
+-MANPAGES = pkcs11-keygen.8 pkcs11-list.8 pkcs11-destroy.8
+-HTMLPAGES = pkcs11-keygen.html pkcs11-list.html pkcs11-destroy.html
++TARGETS = pkcs11-list@EXEEXT@ pkcs11-destroy@EXEEXT@ \
++ pkcs11-keygen@EXEEXT@ pkcs11-tokens@EXEEXT@
++SRCS = pkcs11-list.c pkcs11-destroy.c \
++ pkcs11-keygen.c pkcs11-tokens.c
++OBJS = pkcs11-list.@O@ pkcs11-destroy.@O@ \
++ pkcs11-keygen.@O@ pkcs11-tokens.@O@
++
++MANPAGES = pkcs11-list.8 pkcs11-destroy.8 \
++ pkcs11-keygen.8 pkcs11-tokens.8
++HTMLPAGES = pkcs11-list.html pkcs11-destroy.html \
++ pkcs11-keygen.html pkcs11-tokens.html
+ MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+ @BIND9_MAKE_RULES@
+
+-pkcs11-keygen@EXEEXT@: @srcdir@/pkcs11-keygen.c
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+- -o $@ @srcdir@/pkcs11-keygen.c ${LIBS}
+-
+-pkcs11-list@EXEEXT@: @srcdir@/pkcs11-list.c
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+- -o $@ @srcdir@/pkcs11-list.c ${LIBS}
+-
+-pkcs11-destroy@EXEEXT@: @srcdir@/pkcs11-destroy.c
+- ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+- -o $@ @srcdir@/pkcs11-destroy.c ${LIBS}
++pkcs11-list@EXEEXT@: @srcdir@/pkcs11-list.@O@ ${DEPLIBS}
++ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
++ -o $@ @srcdir@/pkcs11-list.@O@ ${LIBS}
++
++pkcs11-destroy@EXEEXT@: @srcdir@/pkcs11-destroy.@O@ ${DEPLIBS}
++ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
++ -o $@ @srcdir@/pkcs11-destroy.@O@ ${LIBS}
++
++pkcs11-keygen@EXEEXT@: @srcdir@/pkcs11-keygen.@O@ ${DEPLIBS}
++ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
++ -o $@ @srcdir@/pkcs11-keygen.@O@ ${LIBS}
++
++pkcs11-tokens@EXEEXT@: @srcdir@/pkcs11-tokens.@O@ ${DEPLIBS}
++ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
++ -o $@ @srcdir@/pkcs11-tokens.@O@ ${LIBS}
+
+ doc man:: ${MANOBJS}
+
+@@ -63,12 +76,14 @@ installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+ install:: ${TARGETS} installdirs
+- ${INSTALL_PROGRAM} pkcs11-keygen@EXEEXT@ ${DESTDIR}${sbindir}
+- ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ ${DESTDIR}${sbindir}
+- ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ ${DESTDIR}${sbindir}
+- ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-list@EXEEXT@ ${DESTDIR}${sbindir}
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-destroy@EXEEXT@ ${DESTDIR}${sbindir}
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-keygen@EXEEXT@ ${DESTDIR}${sbindir}
++ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} pkcs11-tokens@EXEEXT@ ${DESTDIR}${sbindir}
+ ${INSTALL_DATA} ${srcdir}/pkcs11-list.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/pkcs11-destroy.8 ${DESTDIR}${mandir}/man8
++ ${INSTALL_DATA} ${srcdir}/pkcs11-keygen.8 ${DESTDIR}${mandir}/man8
++ ${INSTALL_DATA} ${srcdir}/pkcs11-tokens.8 ${DESTDIR}${mandir}/man8
+
+ clean distclean::
+- rm -f ${TARGETS}
++ rm -f ${OBJS} ${TARGETS}
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-destroy.8.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-destroy.8
+--- bind-9.9.6/bin/pkcs11/pkcs11-destroy.8.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-destroy.8 2014-10-09 13:29:59.176238338 +0200
+@@ -32,7 +32,7 @@
+ pkcs11\-destroy \- destroy PKCS#11 objects
+ .SH "SYNOPSIS"
+ .HP 15
+-\fBpkcs11\-destroy\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {\-i\ \fIID\fR | \-l\ \fIlabel\fR} [\fB\-p\ \fR\fB\fIPIN\fR\fR]
++\fBpkcs11\-destroy\fR [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {\-i\ \fIID\fR | \-l\ \fIlabel\fR} [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-w\ \fR\fB\fIseconds\fR\fR]
+ .SH "DESCRIPTION"
+ .PP
+ \fBpkcs11\-destroy\fR
+@@ -41,7 +41,7 @@ destroys keys stored in a PKCS#11 device
+ or
+ \fBlabel\fR.
+ .PP
+-Matching keys are displayed before being destroyed. There is a five second delay to allow the user to interrupt the process before the destruction takes place.
++Matching keys are displayed before being destroyed. By default, there is a five second delay to allow the user to interrupt the process before the destruction takes place.
+ .SH "ARGUMENTS"
+ .PP
+ \-m \fImodule\fR
+@@ -70,6 +70,12 @@ Specify the PIN for the device. If no PI
+ \fBpkcs11\-destroy\fR
+ will prompt for it.
+ .RE
++.PP
++\-w \fIseconds\fR
++.RS 4
++Specify how long to pause before carrying out key destruction. The default is five seconds. If set to
++0, destruction will be immediate.
++.RE
+ .SH "SEE ALSO"
+ .PP
+ \fBpkcs11\-list\fR(3),
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-destroy.c.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-destroy.c
+--- bind-9.9.6/bin/pkcs11/pkcs11-destroy.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-destroy.c 2014-10-09 13:29:59.176238338 +0200
+@@ -40,7 +40,10 @@
+
+ /* $Id: pkcs11-destroy.c,v 1.8 2010/01/13 21:19:52 fdupont Exp $ */
+
+-/* pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label] [-p $pin] */
++/*
++ * pkcs11-destroy [-m module] [-s $slot] [-i $id | -l $label]
++ * [-p $pin] [ -w $wait ]
++ */
+
+ /*! \file */
+
+@@ -52,74 +55,70 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/types.h>
+-#include "cryptoki.h"
+
+-#ifdef WIN32
+-#define sleep(x) Sleep(x)
+-#include "win32.c"
+-#else
+-#ifndef FORCE_STATIC_PROVIDER
+-#include "unix.c"
+-#endif
+-#endif
++#include <isc/commandline.h>
++#include <isc/result.h>
++#include <isc/types.h>
++
++#include <pk11/pk11.h>
++#include <pk11/result.h>
+
+ #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+ #define getpassphrase(x) getpass(x)
+ #endif
+
+ int
+-main(int argc, char *argv[])
+-{
++main(int argc, char *argv[]) {
++ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+- CK_UTF8CHAR *pin = NULL;
+ CK_BYTE attr_id[2];
+ CK_OBJECT_HANDLE akey[50];
++ pk11_context_t pctx;
++ char *lib_name = NULL;
+ char *label = NULL;
++ char *pin = NULL;
+ int error = 0;
+- unsigned int id = 0, i = 0;
++ unsigned int id = 0, i = 0, wait = 5;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &attr_id, sizeof(attr_id)}
+ };
+- char *pk11_provider;
+ unsigned int j, len;
+- extern char *optarg;
+- extern int optopt;
+-
+- pk11_provider = getenv("PKCS11_PROVIDER");
+- if (pk11_provider != NULL)
+- pk11_libname = pk11_provider;
+
+- while ((c = getopt(argc, argv, ":m:s:i:l:p:")) != -1) {
++ while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:w:")) != -1) {
+ switch (c) {
+ case 'm':
+- pk11_libname = optarg;
++ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+- slot = atoi(optarg);
++ slot = atoi(isc_commandline_argument);
+ break;
+ case 'i':
+- id = atoi(optarg);
++ id = atoi(isc_commandline_argument);
+ id &= 0xffff;
+ break;
+ case 'l':
+- label = optarg;
++ label = isc_commandline_argument;
+ break;
+ case 'p':
+- pin = (CK_UTF8CHAR *)optarg;
++ pin = isc_commandline_argument;
++ break;
++ case 'w':
++ wait = atoi(isc_commandline_argument);
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+- optopt);
++ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+- fprintf(stderr, "Unrecognised option: -%c\n", optopt);
++ fprintf(stderr, "Unrecognised option: -%c\n",
++ isc_commandline_option);
+ errflg++;
+ }
+ }
+@@ -127,56 +126,49 @@ main(int argc, char *argv[])
+ if (errflg || (id && (label != NULL))) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tpkcs11-destroy [-m module] [-s slot] "
+- "[-i id | -l label] [-p pin]\n");
++ "[-i id | -l label] [-p pin] [-w waittime]\n");
+ exit(1);
+ }
+
+ if (id) {
+- printf("id %i\n", id);
+ attr_id[0] = (id >> 8) & 0xff;
+ attr_id[1] = id & 0xff;
+ } else if (label) {
+- printf("label %s\n", label);
+ search_template[0].type = CKA_LABEL;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+ }
+
+- /* Initialize the CRYPTOKI library */
+- rv = C_Initialize(NULL_PTR);
+- if (rv != CKR_OK) {
+- if (rv == 0xfe)
+- fprintf(stderr,
+- "Can't load or link module \"%s\"\n",
+- pk11_libname);
+- else
+- fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
+- exit(1);
+- }
++ pk11_result_register();
+
+- /* Open a session on the slot found */
+- rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
+- NULL_PTR, NULL_PTR, &hSession);
+- if (rv != CKR_OK) {
+- fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv);
+- error = 1;
+- goto exit_program;
+- }
++ /* Initialize the CRYPTOKI library */
++ if (lib_name != NULL)
++ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+- pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
++ pin = getpassphrase("Enter Pin: ");
+
+ /* Login to the Token (Keystore) */
+- rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+- memset(pin, 0, strlen((char *)pin));
+- if (rv != CKR_OK) {
+- fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv);
+- error = 1;
+- goto exit_session;
++ result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_TRUE,
++ ISC_TRUE, (const char *) pin, slot);
++ if (result == PK11_R_NORANDOMSERVICE ||
++ result == PK11_R_NODIGESTSERVICE ||
++ result == PK11_R_NOAESSERVICE) {
++ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
++ fprintf(stderr, "This HSM will not work with BIND 9 "
++ "using native PKCS#11.\n");
++ } else if (result != ISC_R_SUCCESS) {
++ fprintf(stderr, "Unrecoverable error initializing "
++ "PKCS#11: %s\n", isc_result_totext(result));
++ exit(1);
+ }
+
+- rv = C_FindObjectsInit(hSession, search_template,
+- ((id != 0) || (label != NULL)) ? 1 : 0);
++ memset(pin, 0, strlen(pin));
++
++ hSession = pctx.session;
++
++ rv = pkcs_C_FindObjectsInit(hSession, search_template,
++ ((id != 0) || (label != NULL)) ? 1 : 0);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
+@@ -184,13 +176,19 @@ main(int argc, char *argv[])
+ goto exit_session;
+ }
+
+- rv = C_FindObjects(hSession, akey, 50, &ulObjectCount);
++ rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
++ if (ulObjectCount == 0) {
++ printf("No matching key objects found.\n");
++ goto exit_search;
++ } else
++ printf("Key object%s found:\n", ulObjectCount > 1 ? "s" : "");
++
+ for (i = 0; i < ulObjectCount; i++) {
+ CK_OBJECT_CLASS oclass = 0;
+ CK_BYTE labelbuf[64 + 1];
+@@ -204,7 +202,8 @@ main(int argc, char *argv[])
+ memset(labelbuf, 0, sizeof(labelbuf));
+ memset(idbuf, 0, sizeof(idbuf));
+
+- rv = C_GetAttributeValue(hSession, akey[i], attr_template, 3);
++ rv = pkcs_C_GetAttributeValue(hSession, akey[i],
++ attr_template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GetAttributeValue[%u]: rv = 0x%.8lX\n",
+@@ -213,7 +212,7 @@ main(int argc, char *argv[])
+ goto exit_search;
+ }
+ len = attr_template[2].ulValueLen;
+- printf("object[%u]: class %lu label '%s' id[%lu] ",
++ printf(" object[%u]: class %lu, label '%s', id[%lu] ",
+ i, oclass, labelbuf, attr_template[2].ulValueLen);
+ if (len > 4)
+ len = 4;
+@@ -227,32 +226,40 @@ main(int argc, char *argv[])
+ printf("\n");
+ }
+
+- /* give a chance to kill this */
+- printf("sleeping 5 seconds...\n");
+- sleep(5);
++ if (wait != 0) {
++ printf("WARNING: This action is irreversible! "
++ "Destroying key objects in %d seconds\n ", wait);
++ for (i = 0; i < wait; i++) {
++ printf(".");
++ fflush(stdout);
++ sleep(1);
++ }
++ printf("\n");
++ }
+
+ for (i = 0; i < ulObjectCount; i++) {
+- rv = C_DestroyObject(hSession, akey[i]);
++ rv = pkcs_C_DestroyObject(hSession, akey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+- "C_DestroyObject[%u]: rv = 0x%.8lX\n",
++ "C_DestroyObject[%u] failed: rv = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ }
+ }
+
++ if (error == 0)
++ printf("Destruction complete.\n");
++
+ exit_search:
+- rv = C_FindObjectsFinal(hSession);
++ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+- (void)C_CloseSession(hSession);
+-
+- exit_program:
+- (void)C_Finalize(NULL_PTR);
++ pk11_return_session(&pctx);
++ (void) pk11_finalize();
+
+ exit(error);
+ }
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-destroy.html.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-destroy.html
+--- bind-9.9.6/bin/pkcs11/pkcs11-destroy.html.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-destroy.html 2014-10-09 13:30:22.434269214 +0200
+@@ -29,23 +29,23 @@
+ </div>
+ <div class="refsynopsisdiv">
+ <h2>Synopsis</h2>
+-<div class="cmdsynopsis"><p><code class="command">pkcs11-destroy</code> [<code class="option">-m <em class="replaceable"><code>module</code></em></code>] [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>] { -i <em class="replaceable"><code>ID</code></em> | -l <em class="replaceable"><code>label</code></em> } [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>]</p></div>
++<div class="cmdsynopsis"><p><code class="command">pkcs11-destroy</code> [<code class="option">-m <em class="replaceable"><code>module</code></em></code>] [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>] { -i <em class="replaceable"><code>ID</code></em> | -l <em class="replaceable"><code>label</code></em> } [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>] [<code class="option">-w <em class="replaceable"><code>seconds</code></em></code>]</p></div>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543384"></a><h2>DESCRIPTION</h2>
++<a name="id2543393"></a><h2>DESCRIPTION</h2>
+ <p>
+ <span><strong class="command">pkcs11-destroy</strong></span> destroys keys stored in a
+ PKCS#11 device, identified by their <code class="option">ID</code> or
+ <code class="option">label</code>.
+ </p>
+ <p>
+- Matching keys are displayed before being destroyed. There is a
+- five second delay to allow the user to interrupt the process
+- before the destruction takes place.
++ Matching keys are displayed before being destroyed. By default,
++ there is a five second delay to allow the user to interrupt the
++ process before the destruction takes place.
+ </p>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543406"></a><h2>ARGUMENTS</h2>
++<a name="id2543415"></a><h2>ARGUMENTS</h2>
+ <div class="variablelist"><dl>
+ <dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
+ <dd><p>
+@@ -71,17 +71,23 @@
+ Specify the PIN for the device. If no PIN is provided on the
+ command line, <span><strong class="command">pkcs11-destroy</strong></span> will prompt for it.
+ </p></dd>
++<dt><span class="term">-w <em class="replaceable"><code>seconds</code></em></span></dt>
++<dd><p>
++ Specify how long to pause before carrying out key destruction.
++ The default is five seconds. If set to <code class="literal">0</code>,
++ destruction will be immediate.
++ </p></dd>
+ </dl></div>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543507"></a><h2>SEE ALSO</h2>
++<a name="id2543537"></a><h2>SEE ALSO</h2>
+ <p>
+ <span class="citerefentry"><span class="refentrytitle">pkcs11-list</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">pkcs11-keygen</span>(3)</span>
+ </p>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543533"></a><h2>AUTHOR</h2>
++<a name="id2543563"></a><h2>AUTHOR</h2>
+ <p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+ </div>
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-keygen.8.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-keygen.8
+--- bind-9.9.6/bin/pkcs11/pkcs11-keygen.8.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-keygen.8 2014-10-09 13:30:22.435269215 +0200
+@@ -23,80 +23,91 @@
+ .\" Manual: BIND9
+ .\" Source: BIND9
+ .\"
+-.TH "PKCS11\-KEYGEN" "8" "Sep 18, 2009" "BIND9" "BIND9"
++.TH "PKCS11\-ECGEN" "8" "Feb 30, 2012" "BIND9" "BIND9"
+ .\" disable hyphenation
+ .nh
+ .\" disable justification (adjust text to left margin only)
+ .ad l
+ .SH "NAME"
+-pkcs11\-keygen \- generate RSA keys on a PKCS#11 device
++pkcs11\-keygen \- generate keys on a PKCS#11 device
+ .SH "SYNOPSIS"
+ .HP 14
+-\fBpkcs11\-keygen\fR [\fB\-P\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] [\fB\-e\fR] {\-b\ \fIkeysize\fR} {\-l\ \fIlabel\fR} [\fB\-i\ \fR\fB\fIid\fR\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR]
++\fBpkcs11\-keygen\fR {\-a\ \fIalgorithm\fR} [\fB\-b\ \fR\fB\fIkeysize\fR\fR] [\fB\-e\fR] [\fB\-i\ \fR\fB\fIid\fR\fR] [\fB\-m\ \fR\fB\fImodule\fR\fR] [\fB\-P\fR] [\fB\-p\ \fR\fB\fIPIN\fR\fR] [\fB\-q\fR] [\fB\-S\fR] [\fB\-s\ \fR\fB\fIslot\fR\fR] {label}
+ .SH "DESCRIPTION"
+ .PP
+ \fBpkcs11\-keygen\fR
+-causes a PKCS#11 device to generate a new RSA key pair with the specified
++causes a PKCS#11 device to generate a new key pair with the given
+ \fBlabel\fR
+-and with
++(which must be unique) and with
+ \fBkeysize\fR
+-bits of modulus.
++bits of prime.
+ .SH "ARGUMENTS"
+ .PP
+-\-P
+-.RS 4
+-Set the new private key to be non\-sensitive and extractable. The allows the private key data to be read from the PKCS#11 device. The default is for private keys to be sensitive and non\-extractable.
+-.RE
+-.PP
+-\-m \fImodule\fR
++\-a \fIalgorithm\fR
+ .RS 4
+-Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.
++Specify the key algorithm class: Supported classes are RSA, DSA, DH, and ECC. In addition to these strings, the
++\fBalgorithm\fR
++can be specified as a DNSSEC signing algorithm that will be used with this key; for example, NSEC3RSASHA1 maps to RSA, and ECDSAP256SHA256 maps to ECC. The default class is "RSA".
+ .RE
+ .PP
+-\-s \fIslot\fR
++\-b \fIkeysize\fR
+ .RS 4
+-Open the session with the given PKCS#11 slot. The default is slot 0.
++Create the key pair with
++\fBkeysize\fR
++bits of prime. For ECC keys, the only valid values are 256 and 384, and the default is 256.
+ .RE
+ .PP
+ \-e
+ .RS 4
+-Use a large exponent.
++For RSA keys only, use a large exponent.
+ .RE
+ .PP
+-\-b \fIkeysize\fR
++\-i \fIid\fR
+ .RS 4
+-Create the key pair with
+-\fBkeysize\fR
+-bits of modulus.
++Create key objects with id. The id is either an unsigned short 2 byte or an unsigned long 4 byte number.
+ .RE
+ .PP
+-\-l \fIlabel\fR
++\-m \fImodule\fR
+ .RS 4
+-Create key objects with the given label. This name must be unique.
++Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.
+ .RE
+ .PP
+-\-i \fIid\fR
++\-P
+ .RS 4
+-Create key objects with id. The id is either an unsigned short 2 byte or an unsigned long 4 byte number.
++Set the new private key to be non\-sensitive and extractable. The allows the private key data to be read from the PKCS#11 device. The default is for private keys to be sensitive and non\-extractable.
+ .RE
+ .PP
+ \-p \fIPIN\fR
+ .RS 4
+ Specify the PIN for the device. If no PIN is provided on the command line,
+-\fBpkcs11\-keygen\fR
++\fBpkcs11\-ecgen\fR
+ will prompt for it.
+ .RE
++.PP
++\-e
++.RS 4
++Quiet mode: suppress unnecessary output.
++.RE
++.PP
++\-S
++.RS 4
++For Diffie\-Hellman (DH) keys only, use a special prime of 768, 1024 or 1536 bit size and base (aka generator) 2. If not specified, bit size will default to 1024.
++.RE
++.PP
++\-s \fIslot\fR
++.RS 4
++Open the session with the given PKCS#11 slot. The default is slot 0.
++.RE
+ .SH "SEE ALSO"
+ .PP
++\fBpkcs11\-rsagen\fR(3),
++\fBpkcs11\-dsagen\fR(3),
+ \fBpkcs11\-list\fR(3),
+ \fBpkcs11\-destroy\fR(3),
+ \fBdnssec\-keyfromlabel\fR(3),
+-.SH "CAVEAT"
+-.PP
+-Some PKCS#11 providers crash with big public exponent.
+ .SH "AUTHOR"
+ .PP
+ Internet Systems Consortium
+ .SH "COPYRIGHT"
+-Copyright \(co 2009 Internet Systems Consortium, Inc. ("ISC")
++Copyright \(co 2012 Internet Systems Consortium, Inc. ("ISC")
+ .br
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-keygen.c.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-keygen.c
+--- bind-9.9.6/bin/pkcs11/pkcs11-keygen.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-keygen.c 2014-10-09 13:30:22.436269217 +0200
+@@ -40,18 +40,19 @@
+
+ /* $Id: pkcs11-keygen.c,v 1.9 2009/10/26 23:36:53 each Exp $ */
+
+-/* pkcs11-keygen - pkcs11 rsa key generator
+-*
+-* create RSASHA1 key in the keystore of an SCA6000
+-* The calculation of key tag is left to the script
+-* that converts the key into a DNSKEY RR and inserts
+-* it into a zone file.
+-*
+-* usage:
+-* pkcs11-keygen [-P] [-m module] [-s slot] [-e] -b keysize
+-* -l label [-i id] [-p pin]
+-*
+-*/
++/* pkcs11-keygen - PKCS#11 key generator
++ *
++ * Create a key in the keystore of an HSM
++ *
++ * The calculation of key tag is left to the script
++ * that converts the key into a DNSKEY RR and inserts
++ * it into a zone file.
++ *
++ * usage:
++ * pkcs11-keygen [-P] [-m module] [-s slot] [-e] [-b keysize]
++ * [-i id] [-p pin] -l label
++ *
++ */
+
+ /*! \file */
+
+@@ -63,15 +64,16 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/types.h>
+-#include "cryptoki.h"
+
+-#ifdef WIN32
+-#include "win32.c"
+-#else
+-#ifndef FORCE_STATIC_PROVIDER
+-#include "unix.c"
+-#endif
+-#endif
++#include <isc/commandline.h>
++#include <isc/result.h>
++#include <isc/types.h>
++
++#include <pk11/pk11.h>
++#include <pk11/result.h>
++#define WANT_DH_PRIMES
++#define WANT_ECC_CURVES
++#include <pk11/constants.h>
+
+ #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+ #define getpassphrase(x) getpass(x)
+@@ -81,188 +83,478 @@
+ static CK_BBOOL truevalue = TRUE;
+ static CK_BBOOL falsevalue = FALSE;
+
++/* Key class: RSA, ECC, DSA, DH, or unknown */
++typedef enum {
++ key_unknown,
++ key_rsa,
++ key_dsa,
++ key_dh,
++ key_ecc
++} key_class_t;
++
++/*
++ * Private key template: usable for most key classes without
++ * modificaton; override CKA_SIGN with CKA_DERIVE for DH
++ */
++#define PRIVATE_LABEL 0
++#define PRIVATE_SIGN 1
++#define PRIVATE_DERIVE 1
++#define PRIVATE_TOKEN 2
++#define PRIVATE_PRIVATE 3
++#define PRIVATE_SENSITIVE 4
++#define PRIVATE_EXTRACTABLE 5
++#define PRIVATE_ID 6
++#define PRIVATE_ATTRS 7
++static CK_ATTRIBUTE private_template[] = {
++ {CKA_LABEL, NULL_PTR, 0},
++ {CKA_SIGN, &truevalue, sizeof(truevalue)},
++ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
++ {CKA_PRIVATE, &truevalue, sizeof(truevalue)},
++ {CKA_SENSITIVE, &truevalue, sizeof(truevalue)},
++ {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)},
++ {CKA_ID, NULL_PTR, 0}
++};
++
++/*
++ * Public key template for RSA keys
++ */
++#define RSA_LABEL 0
++#define RSA_VERIFY 1
++#define RSA_TOKEN 2
++#define RSA_PRIVATE 3
++#define RSA_MODULUS_BITS 4
++#define RSA_PUBLIC_EXPONENT 5
++#define RSA_ID 6
++#define RSA_ATTRS 7
++static CK_ATTRIBUTE rsa_template[] = {
++ {CKA_LABEL, NULL_PTR, 0},
++ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
++ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
++ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
++ {CKA_MODULUS_BITS, NULL_PTR, 0},
++ {CKA_PUBLIC_EXPONENT, NULL_PTR, 0},
++ {CKA_ID, NULL_PTR, 0}
++};
++
++/*
++ * Public key template for ECC keys
++ */
++#define ECC_LABEL 0
++#define ECC_VERIFY 1
++#define ECC_TOKEN 2
++#define ECC_PRIVATE 3
++#define ECC_PARAMS 4
++#define ECC_ID 5
++#define ECC_ATTRS 6
++static CK_ATTRIBUTE ecc_template[] = {
++ {CKA_LABEL, NULL_PTR, 0},
++ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
++ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
++ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
++ {CKA_EC_PARAMS, NULL_PTR, 0},
++ {CKA_ID, NULL_PTR, 0}
++};
++
++/*
++ * Public key template for DSA keys
++ */
++#define DSA_LABEL 0
++#define DSA_VERIFY 1
++#define DSA_TOKEN 2
++#define DSA_PRIVATE 3
++#define DSA_PRIME 4
++#define DSA_SUBPRIME 5
++#define DSA_BASE 6
++#define DSA_ID 7
++#define DSA_ATTRS 8
++static CK_ATTRIBUTE dsa_template[] = {
++ {CKA_LABEL, NULL_PTR, 0},
++ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
++ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
++ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
++ {CKA_PRIME, NULL_PTR, 0},
++ {CKA_SUBPRIME, NULL_PTR, 0},
++ {CKA_BASE, NULL_PTR, 0},
++ {CKA_ID, NULL_PTR, 0}
++};
++#define DSA_PARAM_PRIME 0
++#define DSA_PARAM_SUBPRIME 1
++#define DSA_PARAM_BASE 2
++#define DSA_PARAM_ATTRS 3
++static CK_ATTRIBUTE dsa_param_template[] = {
++ {CKA_PRIME, NULL_PTR, 0},
++ {CKA_SUBPRIME, NULL_PTR, 0},
++ {CKA_BASE, NULL_PTR, 0},
++};
++#define DSA_DOMAIN_PRIMEBITS 0
++#define DSA_DOMAIN_PRIVATE 1
++#define DSA_DOMAIN_ATTRS 2
++static CK_ATTRIBUTE dsa_domain_template[] = {
++ {CKA_PRIME_BITS, NULL_PTR, 0},
++ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
++};
++
++/*
++ * Public key template for DH keys
++ */
++#define DH_LABEL 0
++#define DH_VERIFY 1
++#define DH_TOKEN 2
++#define DH_PRIVATE 3
++#define DH_PRIME 4
++#define DH_BASE 5
++#define DH_ID 6
++#define DH_ATTRS 7
++static CK_ATTRIBUTE dh_template[] = {
++ {CKA_LABEL, NULL_PTR, 0},
++ {CKA_VERIFY, &truevalue, sizeof(truevalue)},
++ {CKA_TOKEN, &truevalue, sizeof(truevalue)},
++ {CKA_PRIVATE, &falsevalue, sizeof(falsevalue)},
++ {CKA_PRIME, NULL_PTR, 0},
++ {CKA_BASE, NULL_PTR, 0},
++ {CKA_ID, NULL_PTR, 0}
++};
++#define DH_PARAM_PRIME 0
++#define DH_PARAM_BASE 1
++#define DH_PARAM_ATTRS 2
++static CK_ATTRIBUTE dh_param_template[] = {
++ {CKA_PRIME, NULL_PTR, 0},
++ {CKA_BASE, NULL_PTR, 0},
++};
++#define DH_DOMAIN_PRIMEBITS 0
++#define DH_DOMAIN_ATTRS 1
++static CK_ATTRIBUTE dh_domain_template[] = {
++ {CKA_PRIME_BITS, NULL_PTR, 0},
++};
++
++/*
++ * Convert from text to key class. Accepts the names of DNSSEC
++ * signing algorithms, so e.g., ECDSAP256SHA256 maps to ECC and
++ * NSEC3RSASHA1 maps to RSA.
++ */
++static key_class_t
++keyclass_fromtext(const char *name) {
++ if (name == NULL)
++ return (key_unknown);
++
++ if (strncasecmp(name, "rsa", 3) == 0 ||
++ strncasecmp(name, "nsec3rsa", 8) == 0)
++ return (key_rsa);
++ else if (strncasecmp(name, "dsa", 3) == 0 ||
++ strncasecmp(name, "nsec3dsa", 8) == 0)
++ return (key_dsa);
++ else if (strcasecmp(name, "dh") == 0)
++ return (key_dh);
++ else if (strncasecmp(name, "ecc", 3) == 0 ||
++ strncasecmp(name, "ecdsa", 5) == 0)
++ return (key_ecc);
++ else
++ return (key_unknown);
++}
++
++static void
++usage() {
++ fprintf(stderr,
++ "Usage:\n"
++ "\tpkcs11-keygen -a algorithm -b keysize -l label\n"
++ "\t [-P] [-m module] "
++ "[-s slot] [-e] [-S] [-i id] [-p PIN]\n");
++ exit(2);
++}
++
+ int
+-main(int argc, char *argv[])
+-{
++main(int argc, char *argv[]) {
++ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+- CK_MECHANISM genmech;
++ CK_MECHANISM mech, dpmech;
+ CK_SESSION_HANDLE hSession;
+- CK_UTF8CHAR *pin = NULL;
+- CK_ULONG modulusbits = 0;
++ char *lib_name = NULL;
++ char *pin = NULL;
++ CK_ULONG bits = 0;
+ CK_CHAR *label = NULL;
+- CK_OBJECT_HANDLE privatekey, publickey;
+- CK_BYTE public_exponent[5];
+- CK_ULONG expsize = 3;
++ CK_OBJECT_HANDLE privatekey, publickey, domainparams;
++ CK_BYTE exponent[5];
++ CK_ULONG expsize = 0;
++ pk11_context_t pctx;
+ int error = 0;
+ int c, errflg = 0;
+- int hide = 1;
+- int idlen = 0;
++ int hide = 1, special = 0, quiet = 0;
++ int idlen = 0, id_offset = 0;
++ unsigned int i;
+ unsigned long id = 0;
+ CK_BYTE idbuf[4];
+ CK_ULONG ulObjectCount;
+- /* Set search template */
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_LABEL, NULL_PTR, 0}
+ };
+- CK_ATTRIBUTE publickey_template[] = {
+- {CKA_LABEL, NULL_PTR, 0},
+- {CKA_VERIFY, &truevalue, sizeof(truevalue)},
+- {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+- {CKA_MODULUS_BITS, &modulusbits, sizeof(modulusbits)},
+- {CKA_PUBLIC_EXPONENT, &public_exponent, expsize},
+- {CKA_ID, &idbuf, idlen}
+- };
+- CK_ULONG publickey_attrcnt = 6;
+- CK_ATTRIBUTE privatekey_template[] = {
+- {CKA_LABEL, NULL_PTR, 0},
+- {CKA_SIGN, &truevalue, sizeof(truevalue)},
+- {CKA_TOKEN, &truevalue, sizeof(truevalue)},
+- {CKA_PRIVATE, &truevalue, sizeof(truevalue)},
+- {CKA_SENSITIVE, &truevalue, sizeof(truevalue)},
+- {CKA_EXTRACTABLE, &falsevalue, sizeof(falsevalue)},
+- {CKA_ID, &idbuf, idlen}
+- };
+- CK_ULONG privatekey_attrcnt = 7;
+- char *pk11_provider;
+- extern char *optarg;
+- extern int optopt;
+-
+- pk11_provider = getenv("PKCS11_PROVIDER");
+- if (pk11_provider != NULL)
+- pk11_libname = pk11_provider;
+
+- while ((c = getopt(argc, argv, ":Pm:s:b:ei:l:p:")) != -1) {
++ CK_ATTRIBUTE *public_template = NULL;
++ CK_ATTRIBUTE *domain_template = NULL;
++ CK_ATTRIBUTE *param_template = NULL;
++ CK_ULONG public_attrcnt = 0, private_attrcnt = PRIVATE_ATTRS;
++ CK_ULONG domain_attrcnt = 0, param_attrcnt = 0;
++ key_class_t keyclass = key_rsa;
++ pk11_optype_t op_type = OP_ANY;
++
++#define OPTIONS ":a:b:ei:l:m:Pp:qSs:"
++ while ((c = isc_commandline_parse(argc, argv, OPTIONS)) != -1) {
+ switch (c) {
++ case 'a':
++ keyclass = keyclass_fromtext(isc_commandline_argument);
++ break;
+ case 'P':
+ hide = 0;
+ break;
+ case 'm':
+- pk11_libname = optarg;
++ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+- slot = atoi(optarg);
++ slot = atoi(isc_commandline_argument);
+ break;
+ case 'e':
+ expsize = 5;
+ break;
+ case 'b':
+- modulusbits = atoi(optarg);
++ bits = atoi(isc_commandline_argument);
+ break;
+ case 'l':
+- label = (CK_CHAR *)optarg;
++ /* -l option is retained for backward compatibility * */
++ label = (CK_CHAR *)isc_commandline_argument;
+ break;
+ case 'i':
+- id = strtoul(optarg, NULL, 0);
++ id = strtoul(isc_commandline_argument, NULL, 0);
+ idlen = 4;
+ break;
+ case 'p':
+- pin = (CK_UTF8CHAR *)optarg;
++ pin = isc_commandline_argument;
++ break;
++ case 'q':
++ quiet = 1;
++ break;
++ case 'S':
++ special = 1;
+ break;
+ case ':':
+ fprintf(stderr,
+ "Option -%c requires an operand\n",
+- optopt);
++ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+- fprintf(stderr, "Unrecognised option: -%c\n", optopt);
++ fprintf(stderr, "Unrecognised option: -%c\n",
++ isc_commandline_option);
+ errflg++;
+ }
+ }
+
+- if (errflg || !modulusbits || (label == NULL)) {
+- fprintf(stderr, "Usage:\n");
+- fprintf(stderr, "\tpkcs11-keygen -b keysize -l label\n");
+- fprintf(stderr, "\t [-P] [-m module] "
+- "[-s slot] [-e] [-i id] [-p PIN]\n");
++ if (label == NULL && isc_commandline_index < argc)
++ label = (CK_CHAR *)argv[isc_commandline_index];
++
++ if (errflg || (label == NULL))
++ usage();
++
++ if (expsize != 0 && keyclass != key_rsa) {
++ fprintf(stderr, "The -e option is only compatible "
++ "with RSA key generation\n");
+ exit(2);
+ }
++
++ if (special != 0 && keyclass != key_dh) {
++ fprintf(stderr, "The -S option is only compatible "
++ "with Diffie-Hellman key generation\n");
++ exit(2);
++ }
++
++ switch (keyclass) {
++ case key_rsa:
++ op_type = OP_RSA;
++ if (expsize == 0)
++ expsize = 3;
++ if (bits == 0)
++ usage();
++
++ mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ public_template = rsa_template;
++ public_attrcnt = RSA_ATTRS;
++ id_offset = RSA_ID;
++
++ /* Set public exponent to F4 or F5 */
++ exponent[0] = 0x01;
++ exponent[1] = 0x00;
++ if (expsize == 3)
++ exponent[2] = 0x01;
++ else {
++ exponent[2] = 0x00;
++ exponent[3] = 0x00;
++ exponent[4] = 0x01;
++ }
++
++ public_template[RSA_MODULUS_BITS].pValue = &bits;
++ public_template[RSA_MODULUS_BITS].ulValueLen = sizeof(bits);
++ public_template[RSA_PUBLIC_EXPONENT].pValue = &exponent;
++ public_template[RSA_PUBLIC_EXPONENT].ulValueLen = expsize;
++ break;
++ case key_ecc:
++ op_type = OP_EC;
++ if (bits == 0)
++ bits = 256;
++ else if (bits != 256 && bits != 384) {
++ fprintf(stderr, "ECC keys only support bit sizes of "
++ "256 and 384\n");
++ exit(2);
++ }
++
++ mech.mechanism = CKM_EC_KEY_PAIR_GEN;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ public_template = ecc_template;
++ public_attrcnt = ECC_ATTRS;
++ id_offset = ECC_ID;
++
++ if (bits == 256) {
++ public_template[4].pValue = pk11_ecc_prime256v1;
++ public_template[4].ulValueLen =
++ sizeof(pk11_ecc_prime256v1);
++ } else {
++ public_template[4].pValue = pk11_ecc_secp384r1;
++ public_template[4].ulValueLen =
++ sizeof(pk11_ecc_secp384r1);
++ }
++
++ break;
++ case key_dsa:
++ op_type = OP_DSA;
++ if (bits == 0)
++ usage();
++
++ dpmech.mechanism = CKM_DSA_PARAMETER_GEN;
++ dpmech.pParameter = NULL;
++ dpmech.ulParameterLen = 0;
++ mech.mechanism = CKM_DSA_KEY_PAIR_GEN;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ public_template = dsa_template;
++ public_attrcnt = DSA_ATTRS;
++ id_offset = DSA_ID;
++
++ domain_template = dsa_domain_template;
++ domain_attrcnt = DSA_DOMAIN_ATTRS;
++ param_template = dsa_param_template;
++ param_attrcnt = DSA_PARAM_ATTRS;
++
++ domain_template[DSA_DOMAIN_PRIMEBITS].pValue = &bits;
++ domain_template[DSA_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits);
++ break;
++ case key_dh:
++ op_type = OP_DH;
++ if (special && bits == 0)
++ bits = 1024;
++ else if (special &&
++ bits != 768 && bits != 1024 && bits != 1536)
++ {
++ fprintf(stderr, "When using the special prime (-S) "
++ "option, only key sizes of\n"
++ "768, 1024 or 1536 are supported.\n");
++ exit(2);
++ } else if (bits == 0)
++ usage();
++
++ dpmech.mechanism = CKM_DH_PKCS_PARAMETER_GEN;
++ dpmech.pParameter = NULL;
++ dpmech.ulParameterLen = 0;
++ mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ /* Override CKA_SIGN attribute */
++ private_template[PRIVATE_DERIVE].type = CKA_DERIVE;
++
++ public_template = dh_template;
++ public_attrcnt = DH_ATTRS;
++ id_offset = DH_ID;
++
++ domain_template = dh_domain_template;
++ domain_attrcnt = DH_DOMAIN_ATTRS;
++ param_template = dh_param_template;
++ param_attrcnt = DH_PARAM_ATTRS;
++
++ domain_template[DH_DOMAIN_PRIMEBITS].pValue = &bits;
++ domain_template[DH_DOMAIN_PRIMEBITS].ulValueLen = sizeof(bits);
++ break;
++ case key_unknown:
++ usage();
++ }
+
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen((char *)label);
+- publickey_template[0].pValue = label;
+- publickey_template[0].ulValueLen = strlen((char *)label);
+- privatekey_template[0].pValue = label;
+- privatekey_template[0].ulValueLen = strlen((char *)label);
+-
+- /* Set public exponent to F4 or F5 */
+- public_exponent[0] = 0x01;
+- public_exponent[1] = 0x00;
+- if (expsize == 3)
+- public_exponent[2] = 0x01;
+- else {
+- publickey_template[4].ulValueLen = expsize;
+- public_exponent[2] = 0x00;
+- public_exponent[3] = 0x00;
+- public_exponent[4] = 0x01;
+- }
+-
+- /* Set up mechanism for generating key pair */
+- genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+- genmech.pParameter = NULL_PTR;
+- genmech.ulParameterLen = 0;
++ public_template[0].pValue = label;
++ public_template[0].ulValueLen = strlen((char *)label);
++ private_template[0].pValue = label;
++ private_template[0].ulValueLen = strlen((char *)label);
+
+ if (idlen == 0) {
+- publickey_attrcnt--;
+- privatekey_attrcnt--;
+- } else if (id <= 0xffff) {
+- idlen = 2;
+- publickey_template[5].ulValueLen = idlen;
+- privatekey_template[6].ulValueLen = idlen;
+- idbuf[0] = (CK_BYTE)(id >> 8);
+- idbuf[1] = (CK_BYTE)id;
++ public_attrcnt--;
++ private_attrcnt--;
+ } else {
+- idbuf[0] = (CK_BYTE)(id >> 24);
+- idbuf[1] = (CK_BYTE)(id >> 16);
+- idbuf[2] = (CK_BYTE)(id >> 8);
+- idbuf[3] = (CK_BYTE)id;
+- }
+-
+- /* Initialize the CRYPTOKI library */
+- rv = C_Initialize(NULL_PTR);
++ if (id <= 0xffff) {
++ idlen = 2;
++ idbuf[0] = (CK_BYTE)(id >> 8);
++ idbuf[1] = (CK_BYTE)id;
++ } else {
++ idbuf[0] = (CK_BYTE)(id >> 24);
++ idbuf[1] = (CK_BYTE)(id >> 16);
++ idbuf[2] = (CK_BYTE)(id >> 8);
++ idbuf[3] = (CK_BYTE)id;
++ }
+
+- if (rv != CKR_OK) {
+- if (rv == 0xfe)
+- fprintf(stderr,
+- "Can't load or link module \"%s\"\n",
+- pk11_libname);
+- else
+- fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
+- exit(1);
++ public_template[id_offset].pValue = idbuf;
++ public_template[id_offset].ulValueLen = idlen;
++ private_template[PRIVATE_ID].pValue = idbuf;
++ private_template[PRIVATE_ID].ulValueLen = idlen;
+ }
+
+- /* Open a session on the slot found */
+- rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
+- NULL_PTR, NULL_PTR, &hSession);
++ pk11_result_register();
+
+- if (rv != CKR_OK) {
+- fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv);
+- error = 1;
+- goto exit_program;
+- }
++ /* Initialize the CRYPTOKI library */
++ if (lib_name != NULL)
++ pk11_set_lib_name(lib_name);
+
+- /* Login to the Token (Keystore) */
+ if (pin == NULL)
+- pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
++ pin = getpassphrase("Enter Pin: ");
+
+- rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+- memset(pin, 0, strlen((char *)pin));
+- if (rv != CKR_OK) {
+- fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv);
+- error = 1;
+- goto exit_session;
++ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
++ ISC_TRUE, (const char *) pin, slot);
++ if (result == PK11_R_NORANDOMSERVICE ||
++ result == PK11_R_NODIGESTSERVICE ||
++ result == PK11_R_NOAESSERVICE) {
++ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
++ fprintf(stderr, "This HSM will not work with BIND 9 "
++ "using native PKCS#11.\n");
++ } else if (result != ISC_R_SUCCESS) {
++ fprintf(stderr, "Unrecoverable error initializing "
++ "PKCS#11: %s\n", isc_result_totext(result));
++ exit(1);
+ }
+
++ /* Login to the Token (Keystore) */
++ memset(pin, 0, strlen(pin));
++ hSession = pctx.session;
++
+ /* check if a key with the same id already exists */
+- rv = C_FindObjectsInit(hSession, search_template, 1);
++ rv = pkcs_C_FindObjectsInit(hSession, search_template, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+- rv = C_FindObjects(hSession, &privatekey, 1, &ulObjectCount);
++ rv = pkcs_C_FindObjects(hSession, &privatekey, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8lX\n", rv);
+ error = 1;
+@@ -276,33 +568,140 @@ main(int argc, char *argv[])
+
+ /* Set attributes if the key is not to be hidden */
+ if (!hide) {
+- privatekey_template[4].pValue = &falsevalue;
+- privatekey_template[5].pValue = &truevalue;
++ private_template[4].pValue = &falsevalue;
++ private_template[5].pValue = &truevalue;
++ }
++
++ if (keyclass == key_rsa || keyclass == key_ecc)
++ goto generate_keys;
++
++ /*
++ * Special setup for Diffie-Hellman keys
++ */
++ if (special != 0) {
++ public_template[DH_BASE].pValue = pk11_dh_bn2;
++ public_template[DH_BASE].ulValueLen = sizeof(pk11_dh_bn2);
++ if (bits == 768) {
++ public_template[DH_PRIME].pValue = pk11_dh_bn768;
++ public_template[DH_PRIME].ulValueLen =
++ sizeof(pk11_dh_bn768);
++ } else if (bits == 1024) {
++ public_template[DH_PRIME].pValue = pk11_dh_bn1024;
++ public_template[DH_PRIME].ulValueLen =
++ sizeof(pk11_dh_bn1024);
++ } else {
++ public_template[DH_PRIME].pValue = pk11_dh_bn1536;
++ public_template[DH_PRIME].ulValueLen =
++ sizeof(pk11_dh_bn1536);
++ }
++ param_attrcnt = 0;
++ goto generate_keys;
++ }
++
++ /* Generate Domain parameters */
++ rv = pkcs_C_GenerateKey(hSession, &dpmech, domain_template,
++ domain_attrcnt, &domainparams);
++
++ if (rv != CKR_OK) {
++ fprintf(stderr,
++ "C_GenerateKey: Error = 0x%.8lX\n", rv);
++ error = 1;
++ goto exit_search;
++ }
++
++ /* Get Domain parameters */
++ rv = pkcs_C_GetAttributeValue(hSession, domainparams,
++ param_template, param_attrcnt);
++
++ if (rv != CKR_OK) {
++ fprintf(stderr,
++ "C_GetAttributeValue0: Error = 0x%.8lX\n", rv);
++ error = 1;
++ goto exit_domain;
++ }
++
++ /* Allocate space for parameter attributes */
++ for (i = 0; i < param_attrcnt; i++)
++ param_template[i].pValue = malloc(param_template[i].ulValueLen);
++
++ rv = pkcs_C_GetAttributeValue(hSession, domainparams,
++ dsa_param_template, DSA_PARAM_ATTRS);
++
++ if (rv != CKR_OK) {
++ fprintf(stderr,
++ "C_GetAttributeValue1: Error = 0x%.8lX\n", rv);
++ error = 1;
++ goto exit_params;
++ }
++
++ switch (keyclass) {
++ case key_dsa:
++ public_template[DSA_PRIME].pValue =
++ param_template[DSA_PARAM_PRIME].pValue;
++ public_template[DSA_PRIME].ulValueLen =
++ param_template[DSA_PARAM_PRIME].ulValueLen;
++ public_template[DSA_SUBPRIME].pValue =
++ param_template[DSA_PARAM_SUBPRIME].pValue;
++ public_template[DSA_SUBPRIME].ulValueLen =
++ param_template[DSA_PARAM_SUBPRIME].ulValueLen;
++ public_template[DSA_BASE].pValue =
++ param_template[DSA_PARAM_BASE].pValue;
++ public_template[DSA_BASE].ulValueLen =
++ param_template[DSA_PARAM_BASE].ulValueLen;
++ break;
++ case key_dh:
++ public_template[DH_PRIME].pValue =
++ param_template[DH_PARAM_PRIME].pValue;
++ public_template[DH_PRIME].ulValueLen =
++ param_template[DH_PARAM_PRIME].ulValueLen;
++ public_template[DH_BASE].pValue =
++ param_template[DH_PARAM_BASE].pValue;
++ public_template[DH_BASE].ulValueLen =
++ param_template[DH_PARAM_BASE].ulValueLen;
++ default:
++ break;
+ }
+
++ generate_keys:
+ /* Generate Key pair for signing/verifying */
+- rv = C_GenerateKeyPair(hSession, &genmech,
+- publickey_template, publickey_attrcnt,
+- privatekey_template, privatekey_attrcnt,
++ rv = pkcs_C_GenerateKeyPair(hSession, &mech,
++ public_template, public_attrcnt,
++ private_template, private_attrcnt,
+ &publickey, &privatekey);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateKeyPair: Error = 0x%.8lX\n", rv);
+ error = 1;
++ } else if (!quiet)
++ printf("Key pair generation complete.\n");
++
++ exit_params:
++ /* Free parameter attributes */
++ if (keyclass == key_dsa || keyclass == key_dh)
++ for (i = 0; i < param_attrcnt; i++)
++ free(param_template[i].pValue);
++
++ exit_domain:
++ /* Destroy domain parameters */
++ if (keyclass == key_dsa || (keyclass == key_dh && !special)) {
++ rv = pkcs_C_DestroyObject(hSession, domainparams);
++ if (rv != CKR_OK) {
++ fprintf(stderr,
++ "C_DestroyObject: Error = 0x%.8lX\n", rv);
++ error = 1;
++ }
+ }
+-
++
+ exit_search:
+- rv = C_FindObjectsFinal(hSession);
++ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+- (void)C_CloseSession(hSession);
+-
+- exit_program:
+- (void)C_Finalize(NULL_PTR);
++ pk11_return_session(&pctx);
++ (void) pk11_finalize();
+
+ exit(error);
+ }
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-keygen.docbook.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-keygen.docbook
+--- bind-9.9.6/bin/pkcs11/pkcs11-keygen.docbook.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-keygen.docbook 2014-10-09 14:01:11.112819539 +0200
+@@ -17,20 +17,20 @@
+ - PERFORMANCE OF THIS SOFTWARE.
+ -->
+
+-<refentry id="man.pkcs11-keygen">
++<refentry id="man.pkcs11-ecgen">
+ <refentryinfo>
+- <date>October 05, 2009</date>
++ <date>Feb 30, 2012</date>
+ </refentryinfo>
+
+ <refmeta>
+- <refentrytitle><application>pkcs11-keygen</application></refentrytitle>
++ <refentrytitle><application>pkcs11-ecgen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>pkcs11-keygen</application></refname>
+- <refpurpose>generate RSA keys on a PKCS#11 device</refpurpose>
++ <refpurpose>generate keys on a PKCS#11 device</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+@@ -44,14 +44,17 @@
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>pkcs11-keygen</command>
+- <arg><option>-P</option></arg>
+- <arg><option>-m <replaceable class="parameter">module</replaceable></option></arg>
+- <arg><option>-s <replaceable class="parameter">slot</replaceable></option></arg>
++ <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg>
++ <arg><option>-b <replaceable class="parameter">keysize</replaceable></option></arg>
+ <arg><option>-e</option></arg>
+- <arg choice="req">-b <replaceable class="parameter">keysize</replaceable></arg>
+- <arg choice="req">-l <replaceable class="parameter">label</replaceable></arg>
+ <arg><option>-i <replaceable class="parameter">id</replaceable></option></arg>
++ <arg><option>-m <replaceable class="parameter">module</replaceable></option></arg>
++ <arg><option>-P</option></arg>
+ <arg><option>-p <replaceable class="parameter">PIN</replaceable></option></arg>
++ <arg><option>-q</option></arg>
++ <arg><option>-S</option></arg>
++ <arg><option>-s <replaceable class="parameter">slot</replaceable></option></arg>
++ <arg choice="req">label</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+@@ -59,8 +62,8 @@
+ <title>DESCRIPTION</title>
+ <para>
+ <command>pkcs11-keygen</command> causes a PKCS#11 device to generate
+- a new RSA key pair with the specified <option>label</option> and
+- with <option>keysize</option> bits of modulus.
++ a new key pair with the given <option>label</option> (which must be
++ unique) and with <option>keysize</option> bits of prime.
+ </para>
+ </refsect1>
+
+@@ -68,83 +71,109 @@
+ <title>ARGUMENTS</title>
+ <variablelist>
+ <varlistentry>
+- <term>-P</term>
++ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+- Set the new private key to be non-sensitive and extractable.
+- The allows the private key data to be read from the PKCS#11
+- device. The default is for private keys to be sensitive and
+- non-extractable.
++ Specify the key algorithm class: Supported classes are RSA,
++ DSA, DH, and ECC. In addition to these strings, the
++ <option>algorithm</option> can be specified as a DNSSEC
++ signing algorithm that will be used with this key; for
++ example, NSEC3RSASHA1 maps to RSA, and ECDSAP256SHA256 maps
++ to ECC. The default class is "RSA".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-m <replaceable class="parameter">module</replaceable></term>
++ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+- Specify the PKCS#11 provider module. This must be the full
+- path to a shared library object implementing the PKCS#11 API
+- for the device.
++ Create the key pair with <option>keysize</option> bits of
++ prime. For ECC keys, the only valid values are 256 and 384,
++ and the default is 256.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-s <replaceable class="parameter">slot</replaceable></term>
++ <term>-e</term>
+ <listitem>
+ <para>
+- Open the session with the given PKCS#11 slot. The default is
+- slot 0.
++ For RSA keys only, use a large exponent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-e</term>
++ <term>-i <replaceable class="parameter">id</replaceable></term>
+ <listitem>
+ <para>
+- Use a large exponent.
++ Create key objects with id. The id is either
++ an unsigned short 2 byte or an unsigned long 4 byte number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-b <replaceable class="parameter">keysize</replaceable></term>
++ <term>-m <replaceable class="parameter">module</replaceable></term>
+ <listitem>
+ <para>
+- Create the key pair with <option>keysize</option> bits of
+- modulus.
++ Specify the PKCS#11 provider module. This must be the full
++ path to a shared library object implementing the PKCS#11 API
++ for the device.
++ </para>
++ </listitem>
++ </varlistentry>
++
++ <varlistentry>
++ <term>-P</term>
++ <listitem>
++ <para>
++ Set the new private key to be non-sensitive and extractable.
++ The allows the private key data to be read from the PKCS#11
++ device. The default is for private keys to be sensitive and
++ non-extractable.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-l <replaceable class="parameter">label</replaceable></term>
++ <term>-p <replaceable class="parameter">PIN</replaceable></term>
+ <listitem>
+ <para>
+- Create key objects with the given label.
+- This name must be unique.
++ Specify the PIN for the device. If no PIN is provided on
++ the command line, <command>pkcs11-ecgen</command> will
++ prompt for it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-i <replaceable class="parameter">id</replaceable></term>
++ <term>-q</term>
+ <listitem>
+ <para>
+- Create key objects with id. The id is either
+- an unsigned short 2 byte or an unsigned long 4 byte number.
++ Quiet mode: suppress unnecessary output.
++ </para>
++ </listitem>
++ </varlistentry>
++
++ <varlistentry>
++ <term>-S</term>
++ <listitem>
++ <para>
++ For Diffie-Hellman (DH) keys only, use a special prime of
++ 768, 1024 or 1536 bit size and base (aka generator) 2.
++ If not specified, bit size will default to 1024.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+- <term>-p <replaceable class="parameter">PIN</replaceable></term>
++ <term>-s <replaceable class="parameter">slot</replaceable></term>
+ <listitem>
+ <para>
+- Specify the PIN for the device. If no PIN is provided on the
+- command line, <command>pkcs11-keygen</command> will prompt for it.
++ Open the session with the given PKCS#11 slot. The default is
++ slot 0.
+ </para>
+ </listitem>
+ </varlistentry>
+@@ -155,6 +184,12 @@
+ <title>SEE ALSO</title>
+ <para>
+ <citerefentry>
++ <refentrytitle>pkcs11-rsagen</refentrytitle><manvolnum>3</manvolnum>
++ </citerefentry>,
++ <citerefentry>
++ <refentrytitle>pkcs11-dsagen</refentrytitle><manvolnum>3</manvolnum>
++ </citerefentry>,
++ <citerefentry>
+ <refentrytitle>pkcs11-list</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+@@ -167,11 +202,6 @@
+ </refsect1>
+
+ <refsect1>
+- <title>CAVEAT</title>
+- <para>Some PKCS#11 providers crash with big public exponent.</para>
+- </refsect1>
+-
+- <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-keygen.html.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-keygen.html
+--- bind-9.9.6/bin/pkcs11/pkcs11-keygen.html.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-keygen.html 2014-10-09 13:30:22.438269219 +0200
+@@ -18,36 +18,53 @@
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+-<title>pkcs11-keygen</title>
++<title>pkcs11-ecgen</title>
+ <meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+ </head>
+ <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+-<a name="man.pkcs11-keygen"></a><div class="titlepage"></div>
++<a name="man.pkcs11-ecgen"></a><div class="titlepage"></div>
+ <div class="refnamediv">
+ <h2>Name</h2>
+-<p><span class="application">pkcs11-keygen</span> &#8212; generate RSA keys on a PKCS#11 device</p>
++<p><span class="application">pkcs11-keygen</span> &#8212; generate keys on a PKCS#11 device</p>
+ </div>
+ <div class="refsynopsisdiv">
+ <h2>Synopsis</h2>
+-<div class="cmdsynopsis"><p><code class="command">pkcs11-keygen</code> [<code class="option">-P</code>] [<code class="option">-m <em class="replaceable"><code>module</code></em></code>] [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>] [<code class="option">-e</code>] {-b <em class="replaceable"><code>keysize</code></em>} {-l <em class="replaceable"><code>label</code></em>} [<code class="option">-i <em class="replaceable"><code>id</code></em></code>] [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>]</p></div>
++<div class="cmdsynopsis"><p><code class="command">pkcs11-keygen</code> {-a <em class="replaceable"><code>algorithm</code></em>} [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>] [<code class="option">-e</code>] [<code class="option">-i <em class="replaceable"><code>id</code></em></code>] [<code class="option">-m <em class="replaceable"><code>module</code></em></code>] [<code class="option">-P</code>] [<code class="option">-p <em class="replaceable"><code>PIN</code></em></code>] [<code class="option">-q</code>] [<code class="option">-S</code>] [<code class="option">-s <em class="replaceable"><code>slot</code></em></code>] {label}</p></div>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543397"></a><h2>DESCRIPTION</h2>
++<a name="id2543410"></a><h2>DESCRIPTION</h2>
+ <p>
+ <span><strong class="command">pkcs11-keygen</strong></span> causes a PKCS#11 device to generate
+- a new RSA key pair with the specified <code class="option">label</code> and
+- with <code class="option">keysize</code> bits of modulus.
++ a new key pair with the given <code class="option">label</code> (which must be
++ unique) and with <code class="option">keysize</code> bits of prime.
+ </p>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543416"></a><h2>ARGUMENTS</h2>
++<a name="id2543430"></a><h2>ARGUMENTS</h2>
+ <div class="variablelist"><dl>
+-<dt><span class="term">-P</span></dt>
++<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+ <dd><p>
+- Set the new private key to be non-sensitive and extractable.
+- The allows the private key data to be read from the PKCS#11
+- device. The default is for private keys to be sensitive and
+- non-extractable.
++ Specify the key algorithm class: Supported classes are RSA,
++ DSA, DH, and ECC. In addition to these strings, the
++ <code class="option">algorithm</code> can be specified as a DNSSEC
++ signing algorithm that will be used with this key; for
++ example, NSEC3RSASHA1 maps to RSA, and ECDSAP256SHA256 maps
++ to ECC. The default class is "RSA".
++ </p></dd>
++<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
++<dd><p>
++ Create the key pair with <code class="option">keysize</code> bits of
++ prime. For ECC keys, the only valid values are 256 and 384,
++ and the default is 256.
++ </p></dd>
++<dt><span class="term">-e</span></dt>
++<dd><p>
++ For RSA keys only, use a large exponent.
++ </p></dd>
++<dt><span class="term">-i <em class="replaceable"><code>id</code></em></span></dt>
++<dd><p>
++ Create key objects with id. The id is either
++ an unsigned short 2 byte or an unsigned long 4 byte number.
+ </p></dd>
+ <dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
+ <dd><p>
+@@ -55,51 +72,48 @@
+ path to a shared library object implementing the PKCS#11 API
+ for the device.
+ </p></dd>
+-<dt><span class="term">-s <em class="replaceable"><code>slot</code></em></span></dt>
+-<dd><p>
+- Open the session with the given PKCS#11 slot. The default is
+- slot 0.
+- </p></dd>
+-<dt><span class="term">-e</span></dt>
++<dt><span class="term">-P</span></dt>
+ <dd><p>
+- Use a large exponent.
++ Set the new private key to be non-sensitive and extractable.
++ The allows the private key data to be read from the PKCS#11
++ device. The default is for private keys to be sensitive and
++ non-extractable.
+ </p></dd>
+-<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
++<dt><span class="term">-p <em class="replaceable"><code>PIN</code></em></span></dt>
+ <dd><p>
+- Create the key pair with <code class="option">keysize</code> bits of
+- modulus.
++ Specify the PIN for the device. If no PIN is provided on
++ the command line, <span><strong class="command">pkcs11-ecgen</strong></span> will
++ prompt for it.
+ </p></dd>
+-<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
++<dt><span class="term">-q</span></dt>
+ <dd><p>
+- Create key objects with the given label.
+- This name must be unique.
++ Quiet mode: suppress unnecessary output.
+ </p></dd>
+-<dt><span class="term">-i <em class="replaceable"><code>id</code></em></span></dt>
++<dt><span class="term">-S</span></dt>
+ <dd><p>
+- Create key objects with id. The id is either
+- an unsigned short 2 byte or an unsigned long 4 byte number.
++ For Diffie-Hellman (DH) keys only, use a special prime of
++ 768, 1024 or 1536 bit size and base (aka generator) 2.
++ If not specified, bit size will default to 1024.
+ </p></dd>
+-<dt><span class="term">-p <em class="replaceable"><code>PIN</code></em></span></dt>
++<dt><span class="term">-s <em class="replaceable"><code>slot</code></em></span></dt>
+ <dd><p>
+- Specify the PIN for the device. If no PIN is provided on the
+- command line, <span><strong class="command">pkcs11-keygen</strong></span> will prompt for it.
++ Open the session with the given PKCS#11 slot. The default is
++ slot 0.
+ </p></dd>
+ </dl></div>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543563"></a><h2>SEE ALSO</h2>
++<a name="id2543605"></a><h2>SEE ALSO</h2>
+ <p>
++ <span class="citerefentry"><span class="refentrytitle">pkcs11-rsagen</span>(3)</span>,
++ <span class="citerefentry"><span class="refentrytitle">pkcs11-dsagen</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">pkcs11-list</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">pkcs11-destroy</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keyfromlabel</span>(3)</span>,
+ </p>
+ </div>
+ <div class="refsect1" lang="en">
+-<a name="id2543598"></a><h2>CAVEAT</h2>
+-<p>Some PKCS#11 providers crash with big public exponent.</p>
+-</div>
+-<div class="refsect1" lang="en">
+-<a name="id2543609"></a><h2>AUTHOR</h2>
++<a name="id2543657"></a><h2>AUTHOR</h2>
+ <p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+ </div>
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-list.c.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-list.c
+--- bind-9.9.6/bin/pkcs11/pkcs11-list.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-list.c 2014-10-09 13:30:22.438269219 +0200
+@@ -52,74 +52,68 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <sys/types.h>
+-#include "cryptoki.h"
+
+-#ifdef WIN32
+-#include "win32.c"
+-#else
+-#ifndef FORCE_STATIC_PROVIDER
+-#include "unix.c"
+-#endif
+-#endif
++#include <isc/commandline.h>
++#include <isc/result.h>
++#include <isc/types.h>
++
++#include <pk11/pk11.h>
++#include <pk11/result.h>
+
+ #if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+ #define getpassphrase(x) getpass(x)
+ #endif
+
+ int
+-main(int argc, char *argv[])
+-{
++main(int argc, char *argv[]) {
++ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+- CK_UTF8CHAR *pin = NULL;
+ CK_BYTE attr_id[2];
+ CK_OBJECT_HANDLE akey[50];
++ pk11_context_t pctx;
++ char *lib_name = NULL;
+ char *label = NULL;
+- int error = 0, public = 0, all = 0;
++ char *pin = NULL;
++ isc_boolean_t error = ISC_FALSE, logon = ISC_TRUE, all = ISC_FALSE;
+ unsigned int i = 0, id = 0;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &attr_id, sizeof(attr_id)}
+ };
+- char *pk11_provider;
+- extern char *optarg;
+- extern int optopt;
+-
+- pk11_provider = getenv("PKCS11_PROVIDER");
+- if (pk11_provider != NULL)
+- pk11_libname = pk11_provider;
+
+- while ((c = getopt(argc, argv, ":m:s:i:l:p:P")) != -1) {
++ while ((c = isc_commandline_parse(argc, argv, ":m:s:i:l:p:P")) != -1) {
+ switch (c) {
+ case 'P':
+- public = 1;
++ logon = ISC_FALSE;
+ break;
+ case 'm':
+- pk11_libname = optarg;
++ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+- slot = atoi(optarg);
++ slot = atoi(isc_commandline_argument);
+ break;
+ case 'i':
+- id = atoi(optarg);
++ id = atoi(isc_commandline_argument);
+ id &= 0xffff;
+ break;
+ case 'l':
+- label = optarg;
++ label = isc_commandline_argument;
+ break;
+ case 'p':
+- pin = (CK_UTF8CHAR *)optarg;
++ pin = isc_commandline_argument;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n",
+- optopt);
++ isc_commandline_option);
+ errflg++;
+ break;
+ case '?':
+ default:
+- fprintf(stderr, "Unrecognised option: -%c\n", optopt);
++ fprintf(stderr, "Unrecognised option: -%c\n",
++ isc_commandline_option);
+ errflg++;
+ }
+ }
+@@ -132,7 +126,7 @@ main(int argc, char *argv[])
+ }
+
+ if (!id && (label == NULL))
+- all = 1;
++ all = ISC_TRUE;
+
+ if (slot)
+ printf("slot %lu\n", slot);
+@@ -148,41 +142,37 @@ main(int argc, char *argv[])
+ search_template[0].ulValueLen = strlen(label);
+ }
+
++ pk11_result_register();
++
+ /* Initialize the CRYPTOKI library */
+- rv = C_Initialize(NULL_PTR);
+- if (rv != CKR_OK) {
+- if (rv == 0xfe)
+- fprintf(stderr,
+- "Can't load or link module \"%s\"\n",
+- pk11_libname);
+- else
+- fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
++ if (lib_name != NULL)
++ pk11_set_lib_name(lib_name);
++
++ if (logon && pin == NULL)
++ pin = getpassphrase("Enter Pin: ");
++
++ result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_FALSE,
++ logon, pin, slot);
++ if (result == PK11_R_NORANDOMSERVICE ||
++ result == PK11_R_NODIGESTSERVICE ||
++ result == PK11_R_NOAESSERVICE) {
++ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
++ fprintf(stderr, "This HSM will not work with BIND 9 "
++ "using native PKCS#11.\n");
++ } else if (result != ISC_R_SUCCESS) {
++ fprintf(stderr, "Unrecoverable error initializing "
++ "PKCS#11: %s\n", isc_result_totext(result));
++ fprintf(stderr, "Unrecoverable error initializing "
++ "PKCS#11: %s\n", isc_result_totext(result));
+ exit(1);
+ }
+
+- /* Open a session on the slot found */
+- rv = C_OpenSession(slot, CKF_SERIAL_SESSION,
+- NULL_PTR, NULL_PTR, &hSession);
+- if (rv != CKR_OK) {
+- fprintf(stderr, "C_OpenSession: Error = 0x%.8lX\n", rv);
+- error = 1;
+- goto exit_program;
+- }
++ if (pin != NULL)
++ memset(pin, 0, strlen(pin));
+
+- /* Login to the Token (Keystore) */
+- if (!public) {
+- if (pin == NULL)
+- pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+- rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+- memset(pin, 0, strlen((char *)pin));
+- if (rv != CKR_OK) {
+- fprintf(stderr, "C_Login: Error = 0x%.8lX\n", rv);
+- error = 1;
+- goto exit_session;
+- }
+- }
++ hSession = pctx.session;
+
+- rv = C_FindObjectsInit(hSession, search_template, all ? 0 : 1);
++ rv = pkcs_C_FindObjectsInit(hSession, search_template, all ? 0 : 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+@@ -191,7 +181,7 @@ main(int argc, char *argv[])
+
+ ulObjectCount = 1;
+ while (ulObjectCount) {
+- rv = C_FindObjects(hSession, akey, 50, &ulObjectCount);
++ rv = pkcs_C_FindObjects(hSession, akey, 50, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjects: Error = 0x%.8lX\n",
+@@ -215,7 +205,7 @@ main(int argc, char *argv[])
+ memset(labelbuf, 0, sizeof(labelbuf));
+ memset(idbuf, 0, sizeof(idbuf));
+
+- rv = C_GetAttributeValue(hSession, akey[i],
++ rv = pkcs_C_GetAttributeValue(hSession, akey[i],
+ template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+@@ -260,17 +250,15 @@ main(int argc, char *argv[])
+ }
+
+ exit_search:
+- rv = C_FindObjectsFinal(hSession);
++ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+- (void)C_CloseSession(hSession);
+-
+- exit_program:
+- (void)C_Finalize(NULL_PTR);
++ pk11_return_session(&pctx);
++ (void) pk11_finalize();
+
+ exit(error);
+ }
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-tokens.8.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-tokens.8
+--- bind-9.9.6/bin/pkcs11/pkcs11-tokens.8.native_pkcs11 2014-10-09 13:30:22.438269219 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-tokens.8 2014-10-09 13:30:22.438269219 +0200
+@@ -0,0 +1,51 @@
++.\" Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++.\"
++.\" Permission to use, copy, modify, and/or distribute this software for any
++.\" purpose with or without fee is hereby granted, provided that the above
++.\" copyright notice and this permission notice appear in all copies.
++.\"
++.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++.\" PERFORMANCE OF THIS SOFTWARE.
++.\"
++.\" $Id$
++.\"
++.hy 0
++.ad l
++.\" Title: pkcs11\-tokens
++.\" Author:
++.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
++.\" Date: August 25, 2013
++.\" Manual: BIND9
++.\" Source: BIND9
++.\"
++.TH "PKCS11\-TOKENS" "8" "August 25, 2013" "BIND9" "BIND9"
++.\" disable hyphenation
++.nh
++.\" disable justification (adjust text to left margin only)
++.ad l
++.SH "NAME"
++pkcs11\-tokens \- list PKCS#11 available tokens
++.SH "SYNOPSIS"
++.HP 14
++\fBpkcs11\-tokens\fR [\fB\-m\ \fR\fB\fImodule\fR\fR]
++.SH "DESCRIPTION"
++.PP
++\fBpkcs11\-tokens\fR
++lists the PKCS#11 available tokens with defaults from the slot/token scan performed at application initialization.
++.SH "ARGUMENTS"
++.PP
++\-m \fImodule\fR
++.RS 4
++Specify the PKCS#11 provider module. This must be the full path to a shared library object implementing the PKCS#11 API for the device.
++.RE
++.SH "AUTHOR"
++.PP
++Internet Systems Consortium
++.SH "COPYRIGHT"
++Copyright \(co 2013 Internet Systems Consortium, Inc. ("ISC")
++.br
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-tokens.c.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-tokens.c
+--- bind-9.9.6/bin/pkcs11/pkcs11-tokens.c.native_pkcs11 2014-10-09 13:30:22.438269219 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-tokens.c 2014-10-09 13:30:22.438269219 +0200
+@@ -0,0 +1,106 @@
++/*
++ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++/* pkcs11-tokens [-m module] */
++
++/*! \file */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <string.h>
++#include <sys/types.h>
++
++#include <isc/commandline.h>
++#include <isc/mem.h>
++#include <isc/result.h>
++#include <isc/types.h>
++
++#include <pk11/pk11.h>
++#include <pk11/result.h>
++
++int
++main(int argc, char *argv[]) {
++ isc_result_t result;
++ char *lib_name = NULL;
++ int c, errflg = 0;
++ isc_mem_t *mctx = NULL;
++ pk11_context_t pctx;
++
++ while ((c = isc_commandline_parse(argc, argv, ":m:")) != -1) {
++ switch (c) {
++ case 'm':
++ lib_name = isc_commandline_argument;
++ break;
++ case ':':
++ fprintf(stderr, "Option -%c requires an operand\n",
++ isc_commandline_option);
++ errflg++;
++ break;
++ case '?':
++ default:
++ fprintf(stderr, "Unrecognised option: -%c\n",
++ isc_commandline_option);
++ errflg++;
++ }
++ }
++
++ if (errflg) {
++ fprintf(stderr, "Usage:\n");
++ fprintf(stderr, "\tpkcs11-tokens [-m module]\n");
++ exit(1);
++ }
++
++ if (isc_mem_create(0, 0, &mctx) != ISC_R_SUCCESS) {
++ fprintf(stderr, "isc_mem_create() failed\n");
++ exit(1);
++ }
++
++ pk11_result_register();
++
++ /* Initialize the CRYPTOKI library */
++ if (lib_name != NULL)
++ pk11_set_lib_name(lib_name);
++
++ result = pk11_get_session(&pctx, OP_ANY, ISC_FALSE, ISC_FALSE,
++ ISC_FALSE, NULL, 0);
++ if (result == PK11_R_NORANDOMSERVICE ||
++ result == PK11_R_NODIGESTSERVICE ||
++ result == PK11_R_NOAESSERVICE) {
++ fprintf(stderr, "Warning: %s\n", isc_result_totext(result));
++ fprintf(stderr, "This HSM will not work with BIND 9 "
++ "using native PKCS#11.\n\n");
++ } else if (result != ISC_R_SUCCESS) {
++ fprintf(stderr, "Unrecoverable error initializing "
++ "PKCS#11: %s\n", isc_result_totext(result));
++ exit(1);
++ }
++
++ pk11_dump_tokens();
++
++ if (pctx.handle != NULL)
++ pk11_return_session(&pctx);
++ (void) pk11_finalize();
++
++ isc_mem_destroy(&mctx);
++
++ exit(0);
++}
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-tokens.docbook.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-tokens.docbook
+--- bind-9.9.6/bin/pkcs11/pkcs11-tokens.docbook.native_pkcs11 2014-10-09 13:30:22.438269219 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-tokens.docbook 2014-10-09 13:30:22.438269219 +0200
+@@ -0,0 +1,86 @@
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
++ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
++ [<!ENTITY mdash "&#8212;">]>
++<!--
++ - Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ -
++ - Permission to use, copy, modify, and/or distribute this software for any
++ - purpose with or without fee is hereby granted, provided that the above
++ - copyright notice and this permission notice appear in all copies.
++ -
++ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ - PERFORMANCE OF THIS SOFTWARE.
++-->
++
++<!-- $Id$ -->
++<refentry id="man.pkcs11-tokens">
++ <refentryinfo>
++ <date>August 25, 2013</date>
++ </refentryinfo>
++
++ <refmeta>
++ <refentrytitle><application>pkcs11-tokens</application></refentrytitle>
++ <manvolnum>8</manvolnum>
++ <refmiscinfo>BIND9</refmiscinfo>
++ </refmeta>
++
++ <refnamediv>
++ <refname><application>pkcs11-tokens</application></refname>
++ <refpurpose>list PKCS#11 available tokens</refpurpose>
++ </refnamediv>
++
++ <docinfo>
++ <copyright>
++ <year>2013</year>
++ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
++ </copyright>
++ </docinfo>
++
++ <refsynopsisdiv>
++ <cmdsynopsis>
++ <command>pkcs11-tokens</command>
++ <arg><option>-m <replaceable class="parameter">module</replaceable></option></arg>
++ </cmdsynopsis>
++ </refsynopsisdiv>
++
++ <refsect1>
++ <title>DESCRIPTION</title>
++ <para>
++ <command>pkcs11-tokens</command>
++ lists the PKCS#11 available tokens with defaults from the slot/token
++ scan performed at application initialization.
++ </para>
++ </refsect1>
++
++ <refsect1>
++ <title>ARGUMENTS</title>
++ <variablelist>
++ <varlistentry>
++ <term>-m <replaceable class="parameter">module</replaceable></term>
++ <listitem>
++ <para>
++ Specify the PKCS#11 provider module. This must be the full
++ path to a shared library object implementing the PKCS#11 API
++ for the device.
++ </para>
++ </listitem>
++ </varlistentry>
++ </variablelist>
++ </refsect1>
++
++ <refsect1>
++ <title>AUTHOR</title>
++ <para><corpauthor>Internet Systems Consortium</corpauthor>
++ </para>
++ </refsect1>
++
++</refentry><!--
++ - Local variables:
++ - mode: sgml
++ - End:
++-->
+diff -up bind-9.9.6/bin/pkcs11/pkcs11-tokens.html.native_pkcs11 bind-9.9.6/bin/pkcs11/pkcs11-tokens.html
+--- bind-9.9.6/bin/pkcs11/pkcs11-tokens.html.native_pkcs11 2014-10-09 13:30:22.439269221 +0200
++++ bind-9.9.6/bin/pkcs11/pkcs11-tokens.html 2014-10-09 13:30:22.439269221 +0200
+@@ -0,0 +1,58 @@
++<!--
++ - Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ -
++ - Permission to use, copy, modify, and/or distribute this software for any
++ - purpose with or without fee is hereby granted, provided that the above
++ - copyright notice and this permission notice appear in all copies.
++ -
++ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ - PERFORMANCE OF THIS SOFTWARE.
++-->
++<!-- $Id$ -->
++<html>
++<head>
++<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
++<title>pkcs11-tokens</title>
++<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
++</head>
++<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
++<a name="man.pkcs11-tokens"></a><div class="titlepage"></div>
++<div class="refnamediv">
++<h2>Name</h2>
++<p><span class="application">pkcs11-tokens</span> &#8212; list PKCS#11 available tokens</p>
++</div>
++<div class="refsynopsisdiv">
++<h2>Synopsis</h2>
++<div class="cmdsynopsis"><p><code class="command">pkcs11-tokens</code> [<code class="option">-m <em class="replaceable"><code>module</code></em></code>]</p></div>
++</div>
++<div class="refsect1" lang="en">
++<a name="id2543342"></a><h2>DESCRIPTION</h2>
++<p>
++ <span><strong class="command">pkcs11-tokens</strong></span>
++ lists the PKCS#11 available tokens with defaults from the slot/token
++ scan performed at application initialization.
++ </p>
++</div>
++<div class="refsect1" lang="en">
++<a name="id2543355"></a><h2>ARGUMENTS</h2>
++<div class="variablelist"><dl>
++<dt><span class="term">-m <em class="replaceable"><code>module</code></em></span></dt>
++<dd><p>
++ Specify the PKCS#11 provider module. This must be the full
++ path to a shared library object implementing the PKCS#11 API
++ for the device.
++ </p></dd>
++</dl></div>
++</div>
++<div class="refsect1" lang="en">
++<a name="id2543382"></a><h2>AUTHOR</h2>
++<p><span class="corpauthor">Internet Systems Consortium</span>
++ </p>
++</div>
++</div></body>
++</html>
+diff -up bind-9.9.6/bin/rndc/Makefile.in.native_pkcs11 bind-9.9.6/bin/rndc/Makefile.in
+--- bind-9.9.6/bin/rndc/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/rndc/Makefile.in 2014-10-09 13:30:22.439269221 +0200
+@@ -45,7 +45,8 @@ BIND9DEPLIBS = ../../lib/bind9/libbind9.
+ LIBS = ${ISCLIBS} @LIBS@
+ NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@
+
+-RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS}
++RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} \
++ ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+ CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+diff -up bind-9.9.6/bin/tests/dst/dst_test.c.native_pkcs11 bind-9.9.6/bin/tests/dst/dst_test.c
+--- bind-9.9.6/bin/tests/dst/dst_test.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/tests/dst/dst_test.c 2014-10-09 13:30:22.439269221 +0200
+@@ -30,6 +30,7 @@
+ #include <isc/string.h> /* Required for HP/UX (and others?) */
+
+ #include <dns/fixedname.h>
++#include <dns/log.h>
+ #include <dns/name.h>
+ #include <dns/result.h>
+
+@@ -58,7 +59,8 @@ use(dst_key_t *key, isc_mem_t *mctx) {
+ isc_buffer_add(&databuf, strlen(data));
+ isc_buffer_usedregion(&databuf, &datareg);
+
+- ret = dst_context_create(key, mctx, &ctx);
++ ret = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_GENERAL, ISC_TRUE, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ printf("contextcreate(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+@@ -78,7 +80,8 @@ use(dst_key_t *key, isc_mem_t *mctx) {
+
+ isc_buffer_forward(&sigbuf, 1);
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+- ret = dst_context_create(key, mctx, &ctx);
++ ret = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_GENERAL, ISC_FALSE, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ printf("contextcreate(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+diff -up bind-9.9.6/bin/tests/dst/t_dst.c.native_pkcs11 bind-9.9.6/bin/tests/dst/t_dst.c
+--- bind-9.9.6/bin/tests/dst/t_dst.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/tests/dst/t_dst.c 2014-10-09 13:30:22.439269221 +0200
+@@ -110,7 +110,8 @@ use(dst_key_t *key, isc_mem_t *mctx, isc
+ isc_buffer_add(&databuf, strlen(data));
+ isc_buffer_usedregion(&databuf, &datareg);
+
+- ret = dst_context_create(key, mctx, &ctx);
++ ret = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_GENERAL, ISC_TRUE, &ctx);
+ if (ret != exp_result) {
+ t_info("dst_context_create(%d) returned (%s) expected (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret),
+@@ -139,7 +140,8 @@ use(dst_key_t *key, isc_mem_t *mctx, isc
+ dst_context_destroy(&ctx);
+
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+- ret = dst_context_create(key, mctx, &ctx);
++ ret = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_GENERAL, ISC_FALSE, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_context_create(%d) returned (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret));
+@@ -806,7 +808,9 @@ t2_sigchk(char *datapath, char *sigpath,
+ memset(sig, 0, sizeof(sig));
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+
+- isc_result = dst_context_create(key, mctx, &ctx);
++ isc_result = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_GENERAL,
++ ISC_TRUE, &ctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_context_create(%d) failed %s\n",
+ dst_result_totext(isc_result));
+@@ -872,7 +876,9 @@ t2_sigchk(char *datapath, char *sigpath,
+ if (strstr(expected_result, "!"))
+ exp_res = 1;
+
+- isc_result = dst_context_create(key, mctx, &ctx);
++ isc_result = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_GENERAL,
++ ISC_FALSE, &ctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_context_create returned %s\n",
+ isc_result_totext(isc_result));
+diff -up bind-9.9.6/bin/tests/system/autosign/prereq.sh.native_pkcs11 bind-9.9.6/bin/tests/system/autosign/prereq.sh
+diff -up bind-9.9.6/bin/tests/system/cleanpkcs11.sh.native_pkcs11 bind-9.9.6/bin/tests/system/cleanpkcs11.sh
+--- bind-9.9.6/bin/tests/system/cleanpkcs11.sh.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/tests/system/cleanpkcs11.sh 2014-10-09 13:30:22.447269231 +0200
+@@ -16,6 +16,10 @@
+
+ # $Id: cleanpkcs11.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $
+
++SYSTEMTESTTOP=.
++. $SYSTEMTESTTOP/conf.sh
++
++
+ if [ ! -x ../../pkcs11/pkcs11-destroy ]; then exit 1; fi
+
+-../../pkcs11/pkcs11-destroy -s ${SLOT:-0} -p 1234
++$PK11DEL -w0 > /dev/null 2>&1
+diff -up bind-9.9.6/bin/tests/system/conf.sh.in.native_pkcs11 bind-9.9.6/bin/tests/system/conf.sh.in
+--- bind-9.9.6/bin/tests/system/conf.sh.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/tests/system/conf.sh.in 2014-10-09 13:30:22.447269231 +0200
+@@ -47,9 +47,9 @@ CHECKDS=$TOP/bin/python/dnssec-checkds
+ COVERAGE=$TOP/bin/python/dnssec-coverage
+ CHECKZONE=$TOP/bin/check/named-checkzone
+ CHECKCONF=$TOP/bin/check/named-checkconf
+-PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -s ${SLOT:-0} -p 1234"
+-PK11LIST="$TOP/bin/pkcs11/pkcs11-list -s ${SLOT:-0} -p 1234"
+-PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s ${SLOT:-0} -p 1234"
++PK11GEN="$TOP/bin/pkcs11/pkcs11-keygen -q -s ${SLOT:-0} -p ${HSMPIN:-1234}"
++PK11LIST="$TOP/bin/pkcs11/pkcs11-list -s ${SLOT:-0} -p ${HSMPIN:-1234}"
++PK11DEL="$TOP/bin/pkcs11/pkcs11-destroy -s ${SLOT:-0} -p ${HSMPIN:-1234} -w 0"
+ JOURNALPRINT=$TOP/bin/tools/named-journalprint
+ VERIFY=$TOP/bin/dnssec/dnssec-verify
+ ARPANAME=$TOP/bin/tools/arpaname
+diff -up bind-9.9.6/bin/tests/system/rsabigexponent/Makefile.in.native_pkcs11 bind-9.9.6/bin/tests/system/rsabigexponent/Makefile.in
+--- bind-9.9.6/bin/tests/system/rsabigexponent/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/tests/system/rsabigexponent/Makefile.in 2014-10-09 13:30:40.896293723 +0200
+@@ -24,7 +24,7 @@ top_srcdir = @top_srcdir@
+
+ CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+
+-CDEFINES = @USE_OPENSSL@
++CDEFINES = @CRYPTO@
+ CWARNINGS =
+
+ DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+diff -up bind-9.9.6/bin/tests/system/rsabigexponent/prereq.sh.native_pkcs11 bind-9.9.6/bin/tests/system/rsabigexponent/prereq.sh
+diff -up bind-9.9.6/bin/tests/system/smartsign/prereq.sh.native_pkcs11 bind-9.9.6/bin/tests/system/smartsign/prereq.sh
+diff -up bind-9.9.6/bin/tests/system/tkey/keycreate.c.native_pkcs11 bind-9.9.6/bin/tests/system/tkey/keycreate.c
+--- bind-9.9.6/bin/tests/system/tkey/keycreate.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/bin/tests/system/tkey/keycreate.c 2014-10-09 13:30:40.898293726 +0200
+@@ -228,6 +228,7 @@ main(int argc, char *argv[]) {
+ dns_result_register();
+
+ mctx = NULL;
++ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ ectx = NULL;
+diff -up bind-9.9.6/bin/tests/system/tkey/prereq.sh.native_pkcs11 bind-9.9.6/bin/tests/system/tkey/prereq.sh
+diff -up bind-9.9.6/config.h.in.native_pkcs11 bind-9.9.6/config.h.in
+--- bind-9.9.6/config.h.in.native_pkcs11 2014-10-09 13:29:59.165238323 +0200
++++ bind-9.9.6/config.h.in 2014-10-09 14:43:04.443750544 +0200
+@@ -135,14 +135,11 @@ int sigwait(const unsigned int *set, int
+ /** define if you have strerror in the C library. */
+ #undef HAVE_STRERROR
+
+-/** Define if you are running under Compaq TruCluster. */
+-#undef HAVE_TRUCLUSTER
+-
+ /* Define if OpenSSL includes DSA support */
+ #undef HAVE_OPENSSL_DSA
+
+-/* Define if OpenSSL includes ECDSA support */
+-#undef HAVE_OPENSSL_ECDSA
++/* Define if you have getpassphrase in the C library. */
++#undef HAVE_GETPASSPHRASE
+
+ /* Define to the length type used by the socket API (socklen_t, size_t, int). */
+ #undef ISC_SOCKADDR_LEN_T
+@@ -190,6 +187,9 @@ int sigwait(const unsigned int *set, int
+ /* Define to 1 if you have the `chroot' function. */
+ #undef HAVE_CHROOT
+
++/* Define if clock_gettime is available. */
++#undef HAVE_CLOCK_GETTIME
++
+ /* Define to 1 if you have the <devpoll.h> header file. */
+ #undef HAVE_DEVPOLL_H
+
+@@ -301,6 +301,12 @@ int sigwait(const unsigned int *set, int
+ /* Define if your OpenSSL version supports GOST. */
+ #undef HAVE_OPENSSL_GOST
+
++/* Define if your PKCS11 provider supports ECDSA. */
++#undef HAVE_PKCS11_ECDSA
++
++/* Define if your PKCS11 provider supports GOST. */
++#undef HAVE_PKCS11_GOST
++
+ /* Define to 1 if you have the `pthread_yield' function. */
+ #undef HAVE_PTHREAD_YIELD
+
+@@ -439,6 +445,9 @@ int sigwait(const unsigned int *set, int
+ (O_NDELAY/O_NONBLOCK). */
+ #undef PORT_NONBLOCK
+
++/* Define if GOST private keys are encoded in ASN.1. */
++#undef PREFER_GOSTASN1
++
+ /* The size of `void *', as computed by sizeof. */
+ /* #undef SIZEOF_VOID_P */
+
+diff -up bind-9.9.6/configure.in.native_pkcs11 bind-9.9.6/configure.in
+--- bind-9.9.6/configure.in.native_pkcs11 2014-10-09 13:29:59.165238323 +0200
++++ bind-9.9.6/configure.in 2014-10-09 16:23:45.648903195 +0200
+@@ -655,25 +655,76 @@ AC_ARG_WITH(openssl,
+ (Required for DNSSEC)],
+ use_openssl="$withval", use_openssl="auto")
+
++#
++# was --enable-native-pkcs11 specified?
++# (note it implies both --without-openssl and --with-pkcs11)
++#
++AC_ARG_ENABLE(native-pkcs11,
++ [ --enable-native-pkcs11 use native PKCS11 for all crypto [[default=no]]],
++ want_native_pkcs11="$enableval", want_native_pkcs11="no")
++
++AC_ARG_WITH(pkcs11,
++[ --with-pkcs11[=PATH] Build with PKCS11 support [yes|no|path]
++ (PATH is for the PKCS11 provider)],
++ use_pkcs11="$withval", use_pkcs11="auto")
++
+ openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw"
+ if test "$use_openssl" = "auto"
+ then
+- for d in $openssldirs
+- do
+- if test -f $d/include/openssl/opensslv.h
+- then
+- use_openssl=$d
+- break
+- fi
+- done
++ if test "$want_native_pkcs11" = "yes"
++ then
++ use_openssl="native_pkcs11"
++ else
++ for d in $openssldirs
++ do
++ if test -f $d/include/openssl/opensslv.h
++ then
++ use_openssl=$d
++ break
++ fi
++ done
++ fi
+ fi
+ OPENSSL_ECDSA=""
+ OPENSSL_GOST=""
++AC_ARG_WITH(gost,
++[ --with-gost Crypto GOST [yes|no|raw|asn1].],
++ with_gost="$withval", with_gost="auto")
++AC_ARG_WITH(ecdsa, [ --with-ecdsa OpenSSL ECDSA],
++ with_ecdsa="$withval", with_ecdsa="auto")
++
++gosttype="raw"
++case "$with_gost" in
++ raw)
++ with_gost="yes"
++ ;;
++ asn1)
++ AC_DEFINE(PREFER_GOSTASN1, 1,
++ [Define if GOST private keys are encoded in ASN.1.])
++ gosttype="asn1"
++ with_gost="yes"
++ ;;
++ auto|yes|no)
++ ;;
++ *)
++ AC_MSG_ERROR(unknown GOST private key encoding)
++ ;;
++esac
++
+ case "$use_openssl" in
++ native_pkcs11)
++ AC_MSG_RESULT(disabled because of native PKCS11)
++ DST_OPENSSL_INC=""
++ CRYPTO=""
++ OPENSSLGOSTLINKOBJS=""
++ OPENSSLGOSTLINKSRS=""
++ OPENSSLLINKOBJS=""
++ OPENSSLLINKSRCS=""
++ ;;
+ no)
+ AC_MSG_RESULT(no)
+ DST_OPENSSL_INC=""
+- USE_OPENSSL=""
++ CRYPTO=""
+ OPENSSLGOSTLINKOBJS=""
+ OPENSSLGOSTLINKSRS=""
+ OPENSSLLINKOBJS=""
+@@ -681,7 +732,7 @@ case "$use_openssl" in
+ ;;
+ auto)
+ DST_OPENSSL_INC=""
+- USE_OPENSSL=""
++ CRYPTO=""
+ OPENSSLGOSTLINKOBJS=""
+ OPENSSLGOSTLINKSRS=""
+ OPENSSLLINKOBJS=""
+@@ -691,6 +742,11 @@ case "$use_openssl" in
+ If you don't want OpenSSL, use --without-openssl])
+ ;;
+ *)
++ if test "$want_native_pkcs11" = "yes"
++ then
++ AC_MSG_RESULT()
++ AC_MSG_ERROR([OpenSSL and native PKCS11 cannot be used together.])
++ fi
+ if test "$use_openssl" = "yes"
+ then
+ # User did not specify a path - guess it
+@@ -712,7 +768,7 @@ If you don't want OpenSSL, use --without
+ then
+ AC_MSG_ERROR(["$use_openssl/include/openssl/opensslv.h" not found])
+ fi
+- USE_OPENSSL='-DOPENSSL'
++ CRYPTO='-DOPENSSL'
+ if test "$use_openssl" = "/usr"
+ then
+ DST_OPENSSL_INC=""
+@@ -748,6 +804,7 @@ If you don't want OpenSSL, use --without
+ fi
+ AC_MSG_RESULT(using OpenSSL from $use_openssl/lib and $use_openssl/include)
+
++ saved_cc="$CC"
+ saved_cflags="$CFLAGS"
+ saved_libs="$LIBS"
+ CFLAGS="$CFLAGS $DST_OPENSSL_INC"
+@@ -854,9 +911,8 @@ int main() {
+ [AC_MSG_RESULT(no)
+ have_ecdsa="no"],
+ [AC_MSG_RESULT(using --with-ecdsa)])
+- AC_ARG_WITH(ecdsa, [ --with-ecdsa OpenSSL ECDSA],
+- with_ecdsa="$withval", with_ecdsa="auto")
+- case "$with_ecdsa" in
++
++ case "$with_ecdsa" in
+ yes)
+ case "$have_ecdsa" in
+ no) AC_MSG_ERROR([ecdsa not supported]) ;;
+@@ -884,6 +940,15 @@ int main() {
+
+ AC_MSG_CHECKING(for OpenSSL GOST support)
+ have_gost=""
++ case "$use_pkcs11" in
++ auto|no)
++ ;;
++ *)
++ if $use_threads; then
++ CC="$CC -pthread"
++ fi
++ ;;
++ esac
+ AC_TRY_RUN([
+ #include <openssl/conf.h>
+ #include <openssl/engine.h>
+@@ -911,9 +976,8 @@ int main() {
+ [AC_MSG_RESULT(no)
+ have_gost="no"],
+ [AC_MSG_RESULT(using --with-gost)])
+- AC_ARG_WITH(gost, [ --with-gost OpenSSL GOST],
+- with_gost="$withval", with_gost="auto")
+- case "$with_gost" in
++
++ case "$with_gost" in
+ yes)
+ case "$have_gost" in
+ no) AC_MSG_ERROR([gost not supported]) ;;
+@@ -925,8 +989,8 @@ int main() {
+ *)
+ case "$have_gost" in
+ yes|no) ;;
+- *) AC_MSG_ERROR([need --with-gost=[[yes or no]]]) ;;
+- esac
++ *) AC_MSG_ERROR([need --with-gost=[[yes, no, raw or asn1]]]) ;;
++ esac
+ ;;
+ esac
+ case $have_gost in
+@@ -953,7 +1017,6 @@ esac
+ # it as needed) if it is found.
+ #
+
+-AC_SUBST(USE_OPENSSL)
+ AC_SUBST(DST_OPENSSL_INC)
+ AC_SUBST(OPENSSLGOSTLINKOBJS)
+ AC_SUBST(OPENSSLGOSTLINKSRCS)
+@@ -973,7 +1036,7 @@ AC_ARG_ENABLE(openssl-hash,
+ want_openssl_hash="$enableval", want_openssl_hash="no")
+ case $want_openssl_hash in
+ yes)
+- if test "$USE_OPENSSL" = ""
++ if test "$CRYPTO" = ""
+ then
+ AC_MSG_ERROR([No OpenSSL for hash functions])
+ fi
+@@ -988,6 +1051,44 @@ esac
+ AC_SUBST(ISC_PLATFORM_OPENSSLHASH)
+ AC_SUBST(ISC_OPENSSL_INC)
+
++AC_ARG_WITH(libtool,
++ [ --with-libtool use GNU libtool],
++ use_libtool="$withval", use_libtool="no")
++
++case $use_libtool in
++ yes)
++ AM_PROG_LIBTOOL
++ O=lo
++ A=la
++ LIBTOOL_MKDEP_SED='s;\.o;\.lo;'
++ LIBTOOL_MODE_COMPILE='--mode=compile --tag=CC'
++ LIBTOOL_MODE_INSTALL='--mode=install --tag=CC'
++ LIBTOOL_MODE_LINK='--mode=link --tag=CC'
++ INSTALL_LIBRARY='${INSTALL_PROGRAM}'
++ case "$host" in
++ *) LIBTOOL_ALLOW_UNDEFINED= ;;
++ esac
++ case "$host" in
++ *-ibm-aix*) LIBTOOL_IN_MAIN="-Wl,-bI:T_testlist.imp" ;;
++ *) LIBTOOL_IN_MAIN= ;;
++ esac;
++ ;;
++ *)
++ O=o
++ A=a
++ LIBTOOL=
++ AC_SUBST(LIBTOOL)
++ LIBTOOL_MKDEP_SED=
++ LIBTOOL_MODE_COMPILE=
++ LIBTOOL_MODE_INSTALL=
++ LIBTOOL_MODE_LINK=
++ LIBTOOL_ALLOW_UNDEFINED=
++ LIBTOOL_IN_MAIN=
++ INSTALL_LIBRARY='${INSTALL_DATA}'
++ ;;
++esac
++AC_SUBST(INSTALL_LIBRARY)
++
+ #
+ # PKCS11 (aka crypto hardware) support
+ #
+@@ -995,25 +1096,101 @@ AC_SUBST(ISC_OPENSSL_INC)
+ #
+
+ AC_MSG_CHECKING(for PKCS11 support)
+-AC_ARG_WITH(pkcs11,
+-[ --with-pkcs11[=PATH] Build with PKCS11 support [yes|no|path]
+- (PATH is for the PKCS11 provider)],
+- use_pkcs11="$withval", use_pkcs11="no")
+
++if test "$use_pkcs11" = "auto"
++then
++ if test "$want_native_pkcs11" = "yes"
++ then
++ use_pkcs11="yes"
++ else
++ use_pkcs11="no"
++ fi
++fi
+ case "$use_pkcs11" in
+ no|'')
+- AC_MSG_RESULT(disabled)
+- USE_PKCS11=''
+- PKCS11_TOOLS=''
++ AC_MSG_RESULT(no)
++ USE_PKCS11=""
++ PKCS11_TEST=""
++ PKCS11_TOOLS=""
++ ISC_PK11_C=""
++ ISC_PK11_O=""
++ ISC_PK11_API_C=""
++ ISC_PK11_API_O=""
++ ISC_PK11_RESULT_C=""
++ ISC_PK11_RESULT_O=""
++ ISC_ISCPK11_API_C=""
++ ISC_ISCPK11_API_O=""
+ ;;
+ yes|*)
+- AC_MSG_RESULT(using OpenSSL with PKCS11 support)
++ AC_MSG_RESULT(yes)
++ if ! $use_threads; then
++ AC_MSG_ERROR([PKCS11 requires thread support])
++ fi
++ if test "$CRYPTO" != ""
++ then
++ AC_MSG_CHECKING(for OpenSSL with PKCS11 support)
++ saved_cc="$CC"
++ saved_cflags="$CFLAGS"
++ saved_libs="$LIBS"
++ CC="$CC -pthread"
++ CFLAGS="$CFLAGS $DST_OPENSSL_INC"
++ LIBS="$LIBS $DNS_OPENSSL_LIBS"
++ AC_TRY_RUN([
++#include <openssl/conf.h>
++#include <openssl/engine.h>
++int main() {
++ ENGINE *e;
++
++ OPENSSL_config(NULL);
++ e = ENGINE_by_id("pkcs11");
++ if (e == NULL)
++ return (1);
++ if (ENGINE_init(e) <= 0)
++ return (1);
++ return (0);
++}
++],
++ [AC_MSG_RESULT(yes)
++ PKCS11_TEST=pkcs11ssl
++ PKCS11_ENGINE='-DPKCS11_ENGINE="\"pkcs11\""'],
++ [AC_MSG_RESULT(no)
++ PKCS11_TEST=''
++ PKCS11_ENGINE='-DPKCS11_ENGINE=NULL'],
++ [AC_MSG_RESULT(cross compile, defaulting to no)
++ PKCS11_TEST=''
++ PKCS11_ENGINE='-DPKCS11_ENGINE=NULL'])
++ CC="$saved_cc"
++ CFLAGS="$saved_cflags"
++ LIBS="$saved_libs"
++ else
++ PKCS11_TEST=''
++ PKCS11_ENGINE='-DPKCS11_ENGINE=NULL'
++
++ fi
+ USE_PKCS11='-DUSE_PKCS11'
+ PKCS11_TOOLS=pkcs11
++ AC_CHECK_FUNC(getpassphrase, AC_DEFINE(HAVE_GETPASSPHRASE),)
++ ISC_PK11_C="pk11.c"
++ ISC_PK11_O="pk11.$O"
++ ISC_PK11_API_C="pk11_api.c"
++ ISC_PK11_API_O="pk11_api.$O"
++ ISC_PK11_RESULT_C="pk11_result.c"
++ ISC_PK11_RESULT_O="pk11_result.$O"
++ ISC_ISCPK11_API_C="unix/pk11_api.c"
++ ISC_ISCPK11_API_O="unix/pk11_api.$O"
+ ;;
+ esac
+ AC_SUBST(USE_PKCS11)
+ AC_SUBST(PKCS11_TOOLS)
++AC_SUBST(PKCS11_ENGINE)
++AC_SUBST(ISC_PK11_C)
++AC_SUBST(ISC_PK11_O)
++AC_SUBST(ISC_PK11_API_C)
++AC_SUBST(ISC_PK11_API_O)
++AC_SUBST(ISC_PK11_RESULT_C)
++AC_SUBST(ISC_PK11_RESULT_O)
++AC_SUBST(ISC_ISCPK11_API_C)
++AC_SUBST(ISC_ISCPK11_API_O)
+
+ AC_MSG_CHECKING(for PKCS11 tools)
+ case "$use_pkcs11" in
+@@ -1021,13 +1198,77 @@ case "$use_pkcs11" in
+ AC_MSG_RESULT(disabled)
+ PKCS11_PROVIDER="undefined"
+ ;;
+- *)
+- AC_MSG_RESULT(PKCS11 provider is "$use_pkcs11")
++ yes|'')
++ PKCS11_PROVIDER="undefined"
++ AC_MSG_RESULT(enabled)
++ ;;
++ *)
+ PKCS11_PROVIDER="$use_pkcs11"
++ AC_MSG_RESULT([enabled, PKCS11 provider is $PKCS11_PROVIDER])
+ ;;
+ esac
+ AC_SUBST(PKCS11_PROVIDER)
+
++
++PKCS11_ECDSA=""
++PKCS11_GOST=""
++AC_MSG_CHECKING(for native PKCS11)
++
++case "$want_native_pkcs11" in
++ yes)
++ AC_MSG_RESULT(using native PKCS11 crypto)
++ CRYPTO="-DPKCS11CRYPTO"
++ PKCS11LINKOBJS='${PKCS11LINKOBJS}'
++ PKCS11LINKSRCS='${PKCS11LINKSRCS}'
++ PKCS11_TEST=pkcs11
++ AC_MSG_CHECKING(for PKCS11 ECDSA)
++ case "$with_ecdsa" in
++ no)
++ AC_MSG_RESULT([disabled])
++ ;;
++ *)
++ AC_MSG_RESULT(enabled)
++ PKCS11_ECDSA="yes"
++ AC_DEFINE(HAVE_PKCS11_ECDSA, 1,
++ [Define if your PKCS11 provider supports ECDSA.])
++ ;;
++ esac
++ AC_MSG_CHECKING(for PKCS11 GOST)
++ case "$with_gost" in
++ yes)
++ AC_MSG_RESULT(enabled)
++ PKCS11_GOST="yes"
++ AC_DEFINE(HAVE_PKCS11_GOST, 1,
++ [Define if your PKCS11 provider supports GOST.])
++ ;;
++ *)
++ AC_MSG_RESULT([disabled])
++ ;;
++ esac
++ ;;
++ no|'')
++ AC_MSG_RESULT(disabled)
++ ;;
++esac
++
++AC_SUBST(PKCS11LINKOBJS)
++AC_SUBST(PKCS11LINKSRCS)
++AC_SUBST(CRYPTO)
++AC_SUBST(PKCS11_ECDSA)
++AC_SUBST(PKCS11_GOST)
++AC_SUBST(PKCS11_TEST)
++
++# for PKCS11 benchmarks
++have_clock_gt=no
++AC_CHECK_FUNC(clock_gettime,have_clock_gt=yes,)
++if test "$have_clock_gt" = "no"; then
++ AC_CHECK_LIB(rt,clock_gettime,have_clock_gt=ye,,)
++ fi
++if test "$have_clock_gt" = "yes"; then
++ AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if clock_gettime is available.])
++fi
++
++
+ AC_MSG_CHECKING(for GSSAPI library)
+ AC_ARG_WITH(gssapi,
+ [ --with-gssapi=PATH Specify path for system-supplied GSSAPI [[default=yes]]],
+@@ -1712,44 +1953,6 @@ esac
+
+ AC_SUBST(PURIFY)
+
+-AC_ARG_WITH(libtool,
+- [ --with-libtool use GNU libtool],
+- use_libtool="$withval", use_libtool="no")
+-
+-case $use_libtool in
+- yes)
+- AM_PROG_LIBTOOL
+- O=lo
+- A=la
+- LIBTOOL_MKDEP_SED='s;\.o;\.lo;'
+- LIBTOOL_MODE_COMPILE='--mode=compile --tag=CC'
+- LIBTOOL_MODE_INSTALL='--mode=install --tag=CC'
+- LIBTOOL_MODE_LINK='--mode=link --tag=CC'
+- INSTALL_LIBRARY='${INSTALL_PROGRAM}'
+- case "$host" in
+- *) LIBTOOL_ALLOW_UNDEFINED= ;;
+- esac
+- case "$host" in
+- *-ibm-aix*) LIBTOOL_IN_MAIN="-Wl,-bI:T_testlist.imp" ;;
+- *) LIBTOOL_IN_MAIN= ;;
+- esac;
+- ;;
+- *)
+- O=o
+- A=a
+- LIBTOOL=
+- AC_SUBST(LIBTOOL)
+- LIBTOOL_MKDEP_SED=
+- LIBTOOL_MODE_COMPILE=
+- LIBTOOL_MODE_INSTALL=
+- LIBTOOL_MODE_LINK=
+- LIBTOOL_ALLOW_UNDEFINED=
+- LIBTOOL_IN_MAIN=
+- INSTALL_LIBRARY='${INSTALL_DATA}'
+- ;;
+-esac
+-AC_SUBST(INSTALL_LIBRARY)
+-
+ #
+ # enable/disable dumping stack backtrace. Also check if the system supports
+ # glibc-compatible backtrace() function.
+@@ -3510,6 +3713,9 @@ BIND9_CONFIGARGS="`echo $BIND9_CONFIGARG
+ BIND9_CONFIGARGS="CONFIGARGS=${BIND9_CONFIGARGS}"
+ AC_SUBST(BIND9_CONFIGARGS)
+
++AC_SUBST_FILE(LIBISCPK11_API)
++LIBISCPK11_API="$srcdir/lib/iscpk11/api"
++
+ AC_SUBST_FILE(LIBISC_API)
+ LIBISC_API="$srcdir/lib/isc/api"
+
+@@ -3920,11 +4128,14 @@ AC_CONFIG_FILES([
+ lib/isc/include/Makefile
+ lib/isc/include/isc/Makefile
+ lib/isc/include/isc/platform.h
++ lib/isc/include/pk11/Makefile
++ lib/isc/include/pkcs11/Makefile
+ lib/isc/tests/Makefile
+ lib/isc/nls/Makefile
+ lib/isc/unix/Makefile
+ lib/isc/unix/include/Makefile
+ lib/isc/unix/include/isc/Makefile
++ lib/isc/unix/include/pkcs11/Makefile
+ lib/isccc/Makefile
+ lib/isccc/include/Makefile
+ lib/isccc/include/isccc/Makefile
+@@ -3997,12 +4208,8 @@ test "$atf" = "no" || echo " Automate
+ if test "$enable_full_report" = "yes"; then
+ test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" || \
+ echo " IPv6 support (--enable-ipv6)"
+- test "X$USE_OPENSSL" = "X" || \
++ test "X$CRYPTO" = "X" -o "$want_native_pkcs11" = "yes" || \
+ echo " OpenSSL cryptography/DNSSEC (--with-openssl)"
+- test "$OPENSSL_GOST" != "yes" || \
+- echo " GOST algorithm support (--with-gost)"
+- test "$OPENSSL_ECDSA" != "yes" || \
+- echo " ECDSA algorithm support (--with-ecdsa)"
+ test "X$PYTHON" = "X" || echo " Python tools (--with-python)"
+ test "X$libxml2_libs" = "X" || echo " XML statistics (--with-libxml2)"
+ fi
+@@ -4039,11 +4246,13 @@ test "$enable_fixed" = "yes" || \
+ test "$want_backtrace" = "yes" || \
+ echo " Print backtrace on crash (--enable-backtrace)"
+ test "$atf" = "no" && echo " Automated Testing Framework (--with-atf)"
+-test "X$USE_OPENSSL" = "X" && \
+- echo " OpenSSL cryptography/DNSSEC (--with-openssl)"
+-test "X$USE_OPENSSL" != "X" -a "$OPENSSL_GOST" != "yes" && \
++test "X$CRYPTO" = "X" -o "$want_native_pkcs11" = "yes" && \
++ echo " OpenSSL cryptography/DNSSEC (--with-openssl)"
++test "$want_native_pkcs11" != "yes" && \
++ echo " Native PKCS#11 cryptography/DNSSEC (--enable-native-pkcs11)"
++test "X$CRYPTO" = "X" -o "$OPENSSL_GOST" = "yes" -o "$PKCS11_GOST" = "yes" || \
+ echo " GOST algorithm support (--with-gost)"
+-test "X$USE_OPENSSL" != "X" -a "$OPENSSL_ECDSA" != "yes" && \
++test "X$CRYPTO" = "X" -o "$OPENSSL_ECDSA" = "yes" -o "$PKCS11_ECDSA" = "yes" || \
+ echo " ECDSA algorithm support (--with-ecdsa)"
+ test "X$PYTHON" = "X" && echo " Python tools (--with-python)"
+ test "X$libxml2_libs" = "X" && echo " XML statistics (--with-libxml2)"
+@@ -4055,9 +4264,11 @@ if test "X$ac_unrecognized_opts" != "X";
+ fi
+ echo "========================================================================"
+
+-if test "X$USE_OPENSSL" = "X"; then
++if test "X$CRYPTO" = "X"; then
+ cat << \EOF
+-BIND is being built without OpenSSL. This means it will not have DNSSEC support.
++BIND 9 is being built without cryptography support. This means it will
++not have DNSSEC support. Use --with-openssl, or --with-pkcs11 and
++--enable-native-pkcs11 to enable cryptography.
+ EOF
+ fi
+
+diff -up bind-9.9.6/doc/arm/pkcs11.xml.native_pkcs11 bind-9.9.6/doc/arm/pkcs11.xml
+--- bind-9.9.6/doc/arm/pkcs11.xml.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/doc/arm/pkcs11.xml 2014-10-10 14:39:38.862755114 +0200
+@@ -20,52 +20,115 @@
+ <!-- $Id: pkcs11.xml,v 1.7 2012/01/16 22:50:12 each Exp $ -->
+
+ <sect1 id="pkcs11">
+- <title>PKCS #11 (Cryptoki) support</title>
+- <para>PKCS #11 (Public Key Cryptography Standard #11) defines a
+- platform- independent API for the control of hardware security
+- modules (HSMs) and other cryptographic support devices.</para>
+- <para>BIND 9 is known to work with two HSMs: The Sun SCA 6000
+- cryptographic acceleration board, tested under Solaris x86, and
+- the AEP Keyper network-attached key storage device, tested with
+- Debian Linux, Solaris x86 and Windows Server 2003.</para>
++ <title>PKCS#11 (Cryptoki) support</title>
++ <para>
++ PKCS#11 (Public Key Cryptography Standard #11) defines a
++ platform-independent API for the control of hardware security
++ modules (HSMs) and other cryptographic support devices.
++ </para>
++ <para>
++ BIND 9 is known to work with three HSMs: The AEP Keyper, which has
++ been tested with Debian Linux, Solaris x86 and Windows Server 2003;
++ the Thales nShield, tested with Debian Linux; and the Sun SCA 6000
++ cryptographic acceleration board, tested with Solaris x86. In
++ addition, BIND can be used with SoftHSM, a software-based HSM
++ simulator produced by the OpenDNSSEC project.
++ </para>
++ <para>
++ PKCS#11 makes use of a "provider library": a dynamically loadable
++ library which provides a low-level PKCS#11 interface to drive the HSM
++ hardware. The PKCS#11 provider library comes from the HSM vendor, and
++ it is specific to the HSM to be controlled.
++ </para>
++ <para>
++ There are two available mechanisms for PKCS#11 support in BIND 9:
++ OpenSSL-based PKCS#11 and native PKCS#11. When using the first
++ mechanism, BIND uses a modified version of OpenSSL, which loads
++ the provider library and operates the HSM indirectly; any
++ cryptographic operations not supported by the HSM can be carried
++ out by OpenSSL instead. The second mechanism enables BIND to bypass
++ OpenSSL completely; BIND loads the provider library itself, and uses
++ the PKCS#11 API to drive the HSM directly.
++ </para>
+ <sect2>
+ <title>Prerequisites</title>
+- <para>See the HSM vendor documentation for information about
+- installing, initializing, testing and troubleshooting the
+- HSM.</para>
+- <para>BIND 9 uses OpenSSL for cryptography, but stock OpenSSL
+- does not yet fully support PKCS #11. However, a PKCS #11 engine
+- for OpenSSL is available from the OpenSolaris project. It has
+- been modified by ISC to work with with BIND 9, and to provide
+- new features such as PIN management and key by
+- reference.</para>
+- <para>The patched OpenSSL depends on a "PKCS #11 provider".
+- This is a shared library object, providing a low-level PKCS #11
+- interface to the HSM hardware. It is dynamically loaded by
+- OpenSSL at runtime. The PKCS #11 provider comes from the HSM
+- vendor, and is specific to the HSM to be controlled.</para>
+- <para>There are two "flavors" of PKCS #11 support provided by
+- the patched OpenSSL, one of which must be chosen at
+- configuration time. The correct choice depends on the HSM
+- hardware:</para>
++ <para>
++ See the documentation provided by your HSM vendor for
++ information about installing, initializing, testing and
++ troubleshooting the HSM.
++ </para>
++ </sect2>
++ <sect2>
++ <title>Native PKCS#11</title>
++ <para>
++ Native PKCS#11 mode will only work with an HSM capable of carrying
++ out <emphasis>every</emphasis> cryptographic operation BIND 9 may
++ need. The HSM's provider library must have a complete implementation
++ of the PKCS#11 API, so that all these functions are accessible. As of
++ this writing, only the Thales nShield HSM and the latest development
++ version of SoftHSM can be used in this fashion. For other HSM's,
++ including the AEP Keyper, Sun SCA 6000 and older versions of SoftHSM,
++ use OpenSSL-based PKCS#11. (Note: As more HSMs become capable of
++ supporting native PKCS#11, it is expected that OpenSSL-based
++ PKCS#11 will eventually be deprecated.)
++ </para>
++ <para>
++ To build BIND with native PKCS#11, configure as follows:
++ </para>
++ <screen>
++$ <userinput>cd bind9</userinput>
++$ <userinput>./configure --enable-native-pkcs11 \
++ --with-pkcs11=<replaceable>provider-library-path</replaceable></userinput>
++ </screen>
++ <para>
++ This will cause all BIND tools, including <command>named</command>
++ and the <command>dnssec-*</command> and <command>pkcs11-*</command>
++ tools, to use the PKCS#11 provider library specified in
++ <replaceable>provider-library-path</replaceable> for cryptography.
++ (The provider library path can be overridden using the
++ <option>-E</option> in <command>named</command> and the
++ <command>dnssec-*</command> tools, or the <option>-m</option> in
++ the <command>pkcs11-*</command> tools.)
++ </para>
++ </sect2>
++ <sect2>
++ <title>OpenSSL-based PKCS#11</title>
++ <para>
++ OpenSSL-based PKCS#11 mode uses a modified version of the
++ OpenSSL library; stock OpenSSL does not fully support PKCS#11.
++ ISC provides a patch to OpenSSL to correct this. This patch is
++ based on work originally done by the OpenSolaris project; it has been
++ modified by ISC to provide new features such as PIN management and
++ key-by-reference.
++ </para>
++ <para>
++ There are two "flavors" of PKCS#11 support provided by
++ the patched OpenSSL, one of which must be chosen at
++ configuration time. The correct choice depends on the HSM
++ hardware:
++ </para>
+ <itemizedlist>
+ <listitem>
+- <para>Use 'crypto-accelerator' with HSMs that have hardware
+- cryptographic acceleration features, such as the SCA 6000
+- board. This causes OpenSSL to run all supported
+- cryptographic operations in the HSM.</para>
++ <para>
++ Use 'crypto-accelerator' with HSMs that have hardware
++ cryptographic acceleration features, such as the SCA 6000
++ board. This causes OpenSSL to run all supported
++ cryptographic operations in the HSM.
++ </para>
+ </listitem>
+ <listitem>
+- <para>Use 'sign-only' with HSMs that are designed to
+- function primarily as secure key storage devices, but lack
+- hardware acceleration. These devices are highly secure, but
+- are not necessarily any faster at cryptography than the
+- system CPU &mdash; often, they are slower. It is therefore
+- most efficient to use them only for those cryptographic
+- functions that require access to the secured private key,
+- such as zone signing, and to use the system CPU for all
+- other computationally-intensive operations. The AEP Keyper
+- is an example of such a device.</para>
++ <para>
++ Use 'sign-only' with HSMs that are designed to
++ function primarily as secure key storage devices, but lack
++ hardware acceleration. These devices are highly secure, but
++ are not necessarily any faster at cryptography than the
++ system CPU &mdash; often, they are slower. It is therefore
++ most efficient to use them only for those cryptographic
++ functions that require access to the secured private key,
++ such as zone signing, and to use the system CPU for all
++ other computationally-intensive operations. The AEP Keyper
++ is an example of such a device.
++ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+@@ -77,106 +140,139 @@
+ 1.0.0 and 1.0.1.
+ </para>
+ <note>
+- The latest OpenSSL versions at the time of the BIND release
+- are 0.9.8y, 1.0.0k and 1.0.1e.
+- ISC will provide an updated patch as new versions of OpenSSL
++ The latest OpenSSL versions as of this writing (January 2014)
++ are 0.9.8y, 1.0.0l, and 1.0.1f.
++ ISC will provide updated patches as new versions of OpenSSL
++ are released. The version number in the following examples
+ are released. The version number in the following examples
+ is expected to change.</note>
+ <para>
+- Before building BIND 9 with PKCS #11 support, it will be
+- necessary to build OpenSSL with this patch in place and inform
+- it of the path to the HSM-specific PKCS #11 provider
+- library.</para>
+- <para>Obtain OpenSSL 0.9.8s:</para>
+- <screen>
+-$ <userinput>wget <ulink>http://www.openssl.org/source/openssl-0.9.8s.tar.gz</ulink></userinput>
+-</screen>
+- <para>Extract the tarball:</para>
+- <screen>
+-$ <userinput>tar zxf openssl-0.9.8s.tar.gz</userinput>
+-</screen>
+- <para>Apply the patch from the BIND 9 release:</para>
+- <screen>
+-$ <userinput>patch -p1 -d openssl-0.9.8s \
+- &lt; bind9/bin/pkcs11/openssl-0.9.8s-patch</userinput>
+-</screen>
+- <note>(Note that the patch file may not be compatible with the
+- "patch" utility on all operating systems. You may need to
+- install GNU patch.)</note>
+- <para>When building OpenSSL, place it in a non-standard
+- location so that it does not interfere with OpenSSL libraries
+- elsewhere on the system. In the following examples, we choose
+- to install into "/opt/pkcs11/usr". We will use this location
+- when we configure BIND 9.</para>
++ Before building BIND 9 with PKCS#11 support, it will be
++ necessary to build OpenSSL with the patch in place, and configure
++ it with the path to your HSM's PKCS#11 provider library.
++ </para>
++ </sect3>
++ <title>Patching OpenSSL</title>
++ <screen>
++$ <userinput>wget <ulink>http://www.openssl.org/source/openssl-0.9.8y.tar.gz</ulink></userinput>
++ </screen>
++ <para>Extract the tarball:</para>
++ <screen>
++$ <userinput>tar zxf openssl-0.9.8y.tar.gz</userinput>
++</screen>
++ <para>Apply the patch from the BIND 9 release:</para>
++ <screen>
++$ <userinput>patch -p1 -d openssl-0.9.8y \
++ &lt; bind9/bin/pkcs11/openssl-0.9.8y-patch</userinput>
++</screen>
++ <note>
++ Note that the patch file may not be compatible with the
++ "patch" utility on all operating systems. You may need to
++ install GNU patch.
++ </note>
++ <para>
++ When building OpenSSL, place it in a non-standard
++ location so that it does not interfere with OpenSSL libraries
++ elsewhere on the system. In the following examples, we choose
++ to install into "/opt/pkcs11/usr". We will use this location
++ when we configure BIND 9.
++ </para>
++ <para>
++ Later, when building BIND 9, the location of the custom-built
++ OpenSSL library will need to be specified via configure.
++ </para>
++ </sect3>
+ <sect3>
+ <!-- Example 1 -->
+ <title>Building OpenSSL for the AEP Keyper on Linux</title>
+- <para>The AEP Keyper is a highly secure key storage device,
+- but does not provide hardware cryptographic acceleration. It
+- can carry out cryptographic operations, but it is probably
+- slower than your system's CPU. Therefore, we choose the
+- 'sign-only' flavor when building OpenSSL.</para>
+- <para>The Keyper-specific PKCS #11 provider library is
+- delivered with the Keyper software. In this example, we place
+- it /opt/pkcs11/usr/lib:</para>
++ <para>
++ The AEP Keyper is a highly secure key storage device,
++ but does not provide hardware cryptographic acceleration. It
++ can carry out cryptographic operations, but it is probably
++ slower than your system's CPU. Therefore, we choose the
++ 'sign-only' flavor when building OpenSSL.
++ </para>
++ <para>
++ The Keyper-specific PKCS#11 provider library is
++ delivered with the Keyper software. In this example, we place
++ it /opt/pkcs11/usr/lib:
++ </para>
+ <screen>
+ $ <userinput>cp pkcs11.GCC4.0.2.so.4.05 /opt/pkcs11/usr/lib/libpkcs11.so</userinput>
+ </screen>
+- <para>This library is only available for Linux as a 32-bit
+- binary. If we are compiling on a 64-bit Linux system, it is
+- necessary to force a 32-bit build, by specifying -m32 in the
+- build options.</para>
+- <para>Finally, the Keyper library requires threads, so we
+- must specify -pthread.</para>
++ <para>
++ This library is only available for Linux as a 32-bit
++ binary. If we are compiling on a 64-bit Linux system, it is
++ necessary to force a 32-bit build, by specifying -m32 in the
++ build options.
++ </para>
++ <para>
++ Finally, the Keyper library requires threads, so we
++ must specify -pthread.
++ </para>
+ <screen>
+-$ <userinput>cd openssl-0.9.8s</userinput>
++$ <userinput>cd openssl-0.9.8y</userinput>
+ $ <userinput>./Configure linux-generic32 -m32 -pthread \
+ --pk11-libname=/opt/pkcs11/usr/lib/libpkcs11.so \
+ --pk11-flavor=sign-only \
+ --prefix=/opt/pkcs11/usr</userinput>
+ </screen>
+- <para>After configuring, run "<command>make</command>"
+- and "<command>make test</command>". If "<command>make
+- test</command>" fails with "pthread_atfork() not found", you forgot to
+- add the -pthread above.</para>
++ <para>
++ After configuring, run "<command>make</command>"
++ and "<command>make test</command>". If "<command>make
++ test</command>" fails with "pthread_atfork() not found", you forgot to
++ add the -pthread above.
++ </para>
+ </sect3>
+ <sect3>
+ <!-- Example 2 -->
+ <title>Building OpenSSL for the SCA 6000 on Solaris</title>
+- <para>The SCA-6000 PKCS #11 provider is installed as a system
+- library, libpkcs11. It is a true crypto accelerator, up to 4
+- times faster than any CPU, so the flavor shall be
+- 'crypto-accelerator'.</para>
+- <para>In this example, we are building on Solaris x86 on an
+- AMD64 system.</para>
++ <para>
++ The SCA-6000 PKCS#11 provider is installed as a system
++ library, libpkcs11. It is a true crypto accelerator, up to 4
++ times faster than any CPU, so the flavor shall be
++ 'crypto-accelerator'.
++ </para>
++ <para>
++ In this example, we are building on Solaris x86 on an
++ AMD64 system.
++ </para>
+ <screen>
+-$ <userinput>cd openssl-0.9.8s</userinput>
++$ <userinput>cd openssl-0.9.8y</userinput>
+ $ <userinput>./Configure solaris64-x86_64-cc \
+ --pk11-libname=/usr/lib/64/libpkcs11.so \
+ --pk11-flavor=crypto-accelerator \
+ --prefix=/opt/pkcs11/usr</userinput>
+ </screen>
+- <para>(For a 32-bit build, use "solaris-x86-cc" and
+- /usr/lib/libpkcs11.so.)</para>
+- <para>After configuring, run
+- <command>make</command> and
+- <command>make test</command>.</para>
++ <para>
++ (For a 32-bit build, use "solaris-x86-cc" and /usr/lib/libpkcs11.so.)
++ </para>
++ <para>
++ After configuring, run
++ <command>make</command> and
++ <command>make test</command>.
++ </para>
+ </sect3>
+ <sect3>
+ <!-- Example 3 -->
+ <title>Building OpenSSL for SoftHSM</title>
+- <para>SoftHSM is a software library provided by the OpenDNSSEC
+- project (http://www.opendnssec.org) which provides a PKCS#11
+- interface to a virtual HSM, implemented in the form of encrypted
+- data on the local filesystem. It uses the Botan library for
+- encryption and SQLite3 for data storage. Though less secure
+- than a true HSM, it can provide more secure key storage than
+- traditional key files, and can allow you to experiment with
+- PKCS#11 when an HSM is not available.</para>
+- <para>The SoftHSM cryptographic store must be installed and
+- initialized before using it with OpenSSL, and the SOFTHSM_CONF
+- environment variable must always point to the SoftHSM configuration
+- file:</para>
++ <para>
++ SoftHSM is a software library provided by the OpenDNSSEC
++ project (http://www.opendnssec.org) which provides a PKCS#11
++ interface to a virtual HSM, implemented in the form of encrypted
++ data on the local filesystem. SoftHSM can be configured to use
++ either OpenSSL or the Botan library for encryption, and SQLite3
++ for data storage. Though less secure than a true HSM, it can
++ provide more secure key storage than traditional key files,
++ and can allow you to experiment with PKCS#11 when an HSM is
++ not available.
++ </para>
++ <para>
++ The SoftHSM cryptographic store must be installed and
++ initialized before using it with OpenSSL, and the SOFTHSM_CONF
++ environment variable must always point to the SoftHSM configuration
++ file:
++ </para>
+ <screen>
+ $ <userinput> cd softhsm-1.3.0 </userinput>
+ $ <userinput> configure --prefix=/opt/pkcs11/usr </userinput>
+@@ -186,25 +282,31 @@ $ <userinput> export SOFTHSM_CONF=/opt/p
+ $ <userinput> echo "0:/opt/pkcs11/softhsm.db" > $SOFTHSM_CONF </userinput>
+ $ <userinput> /opt/pkcs11/usr/bin/softhsm --init-token 0 --slot 0 --label softhsm </userinput>
+ </screen>
+- <para>SoftHSM can perform all cryptographic operations, but
+- since it only uses your system CPU, there is no need to use it
+- for anything but signing. Therefore, we choose the 'sign-only'
+- flavor when building OpenSSL.</para>
++ <para>
++ SoftHSM can perform all cryptographic operations, but
++ since it only uses your system CPU, there is no advantage to using
++ it for anything but signing. Therefore, we choose the 'sign-only'
++ flavor when building OpenSSL.
++ </para>
+ <screen>
+-$ <userinput>cd openssl-0.9.8s</userinput>
++$ <userinput>cd openssl-0.9.8y</userinput>
+ $ <userinput>./Configure linux-x86_64 -pthread \
+- --pk11-libname=/opt/pkcs11/usr/lib/libpkcs11.so \
++ --pk11-libname=/opt/pkcs11/usr/lib/libsofthsm.so \
+ --pk11-flavor=sign-only \
+ --prefix=/opt/pkcs11/usr</userinput>
+ </screen>
+- <para>After configuring, run "<command>make</command>"
+- and "<command>make test</command>".</para>
++ <para>
++ After configuring, run "<command>make</command>"
++ and "<command>make test</command>".
++ </para>
+ </sect3>
+- <para>Once you have built OpenSSL, run
+- "<command>apps/openssl engine pkcs11</command>" to confirm
+- that PKCS #11 support was compiled in correctly. The output
+- should be one of the following lines, depending on the flavor
+- selected:</para>
++ <para>
++ Once you have built OpenSSL, run
++ "<command>apps/openssl engine pkcs11</command>" to confirm
++ that PKCS#11 support was compiled in correctly. The output
++ should be one of the following lines, depending on the flavor
++ selected:
++ </para>
+ <screen>
+ (pkcs11) PKCS #11 engine support (sign only)
+ </screen>
+@@ -212,29 +314,31 @@ $ <userinput>./Configure linux-x86_64 -p
+ <screen>
+ (pkcs11) PKCS #11 engine support (crypto accelerator)
+ </screen>
+- <para>Next, run
+- "<command>apps/openssl engine pkcs11 -t</command>". This will
+- attempt to initialize the PKCS #11 engine. If it is able to
+- do so successfully, it will report
+- <quote><literal>[ available ]</literal></quote>.</para>
+- <para>If the output is correct, run
+- "<command>make install</command>" which will install the
+- modified OpenSSL suite to
+- <filename>/opt/pkcs11/usr</filename>.</para>
+- </sect2>
+- <sect2>
+- <title>Building BIND 9 with PKCS#11</title>
+- <para>When building BIND 9, the location of the custom-built
+- OpenSSL library must be specified via configure.</para>
++ <para>
++ Next, run
++ "<command>apps/openssl engine pkcs11 -t</command>". This will
++ attempt to initialize the PKCS#11 engine. If it is able to
++ do so successfully, it will report
++ <quote><literal>[ available ]</literal></quote>.
++ </para>
++ <para>
++ If the output is correct, run
++ "<command>make install</command>" which will install the
++ modified OpenSSL suite to <filename>/opt/pkcs11/usr</filename>.
++ </para>
+ <sect3>
+ <!-- Example 4 -->
+ <title>Configuring BIND 9 for Linux with the AEP Keyper</title>
+- <para>To link with the PKCS #11 provider, threads must be
+- enabled in the BIND 9 build.</para>
+- <para>The PKCS #11 library for the AEP Keyper is currently
+- only available as a 32-bit binary. If we are building on a
+- 64-bit host, we must force a 32-bit build by adding "-m32" to
+- the CC options on the "configure" command line.</para>
++ <para>
++ To link with the PKCS#11 provider, threads must be
++ enabled in the BIND 9 build.
++ </para>
++ <para>
++ The PKCS#11 library for the AEP Keyper is currently
++ only available as a 32-bit binary. If we are building on a
++ 64-bit host, we must force a 32-bit build by adding "-m32" to
++ the CC options on the "configure" command line.
++ </para>
+ <screen>
+ $ <userinput>cd ../bind9</userinput>
+ $ <userinput>./configure CC="gcc -m32" --enable-threads \
+@@ -245,8 +349,10 @@ $ <userinput>./configure CC="gcc -m32" -
+ <sect3>
+ <!-- Example 5 -->
+ <title>Configuring BIND 9 for Solaris with the SCA 6000</title>
+- <para>To link with the PKCS #11 provider, threads must be
+- enabled in the BIND 9 build.</para>
++ <para>
++ To link with the PKCS#11 provider, threads must be
++ enabled in the BIND 9 build.
++ </para>
+ <screen>
+ $ <userinput>cd ../bind9</userinput>
+ $ <userinput>./configure CC="cc -xarch=amd64" --enable-threads \
+@@ -254,11 +360,13 @@ $ <userinput>./configure CC="cc -xarch=a
+ --with-pkcs11=/usr/lib/64/libpkcs11.so</userinput>
+ </screen>
+ <para>(For a 32-bit build, omit CC="cc -xarch=amd64".)</para>
+- <para>If configure complains about OpenSSL not working, you
+- may have a 32/64-bit architecture mismatch. Or, you may have
+- incorrectly specified the path to OpenSSL (it should be the
+- same as the --prefix argument to the OpenSSL
+- Configure).</para>
++ <para>
++ If configure complains about OpenSSL not working, you
++ may have a 32/64-bit architecture mismatch. Or, you may have
++ incorrectly specified the path to OpenSSL (it should be the
++ same as the --prefix argument to the OpenSSL
++ Configure).
++ </para>
+ </sect3>
+ <sect3>
+ <!-- Example 6 -->
+@@ -267,63 +375,85 @@ $ <userinput>./configure CC="cc -xarch=a
+ $ <userinput>cd ../bind9</userinput>
+ $ <userinput>./configure --enable-threads \
+ --with-openssl=/opt/pkcs11/usr \
+- --with-pkcs11=/opt/pkcs11/usr/lib/libpkcs11.so</userinput>
++ --with-pkcs11=/opt/pkcs11/usr/lib/libsofthsm.so</userinput>
+ </screen>
+ </sect3>
+- <para>After configuring, run
+- "<command>make</command>",
+- "<command>make test</command>" and
+- "<command>make install</command>".</para>
+- <para>(Note: If "make test" fails in the "pkcs11" system test, you may
+- have forgotten to set the SOFTHSM_CONF environment variable.)</para>
++ <para>
++ After configuring, run
++ "<command>make</command>",
++ "<command>make test</command>" and
++ "<command>make install</command>".
++ </para>
++ <para>
++ (Note: If "make test" fails in the "pkcs11" system test, you may
++ have forgotten to set the SOFTHSM_CONF environment variable.)
++ </para>
+ </sect2>
+ <sect2>
+- <title>PKCS #11 Tools</title>
+- <para>BIND 9 includes a minimal set of tools to operate the
+- HSM, including
+- <command>pkcs11-keygen</command> to generate a new key pair
+- within the HSM,
+- <command>pkcs11-list</command> to list objects currently
+- available, and
+- <command>pkcs11-destroy</command> to remove objects.</para>
+- <para>In UNIX/Linux builds, these tools are built only if BIND
+- 9 is configured with the --with-pkcs11 option. (NOTE: If
+- --with-pkcs11 is set to "yes", rather than to the path of the
+- PKCS #11 provider, then the tools will be built but the
+- provider will be left undefined. Use the -m option or the
+- PKCS11_PROVIDER environment variable to specify the path to the
+- provider.)</para>
++ <title>PKCS#11 Tools</title>
++ <para>
++ BIND 9 includes a minimal set of tools to operate the
++ HSM, including
++ <command>pkcs11-keygen</command> to generate a new key pair
++ within the HSM,
++ <command>pkcs11-list</command> to list objects currently
++ available,
++ <command>pkcs11-destroy</command> to remove objects, and
++ <command>pkcs11-tokens</command> to list available tokens.
++ </para>
++ <para>
++ In UNIX/Linux builds, these tools are built only if BIND
++ 9 is configured with the --with-pkcs11 option. (Note: If
++ --with-pkcs11 is set to "yes", rather than to the path of the
++ PKCS#11 provider, then the tools will be built but the
++ provider will be left undefined. Use the -m option or the
++ PKCS11_PROVIDER environment variable to specify the path to the
++ provider.)
++ </para>
+ </sect2>
+ <sect2>
+ <title>Using the HSM</title>
+- <para>First, we must set up the runtime environment so the
+- OpenSSL and PKCS #11 libraries can be loaded:</para>
++ <para>
++ For OpenSSL-based PKCS#11, we must first set up the runtime
++ environment so the OpenSSL and PKCS#11 libraries can be loaded:
++ </para>
+ <screen>
+ $ <userinput>export LD_LIBRARY_PATH=/opt/pkcs11/usr/lib:${LD_LIBRARY_PATH}</userinput>
+ </screen>
+- <para>When operating an AEP Keyper, it is also necessary to
+- specify the location of the "machine" file, which stores
+- information about the Keyper for use by PKCS #11 provider
+- library. If the machine file is in
+- <filename>/opt/Keyper/PKCS11Provider/machine</filename>,
+- use:</para>
++ <para>
++ This causes <command>named</command> and other binaries to load
++ the OpenSSL library from <filename>/opt/pkcs11/usr/lib</filename>
++ rather than from the default location. This step is not necessary
++ when using native PKCS#11.
++ </para>
++ <para>
++ Some HSMs require other environment variables to be set.
++ For example, when operating an AEP Keyper, it is necessary to
++ specify the location of the "machine" file, which stores
++ information about the Keyper for use by the provider
++ library. If the machine file is in
++ <filename>/opt/Keyper/PKCS11Provider/machine</filename>,
++ use:
++ </para>
+ <screen>
+ $ <userinput>export KEYPER_LIBRARY_PATH=/opt/Keyper/PKCS11Provider</userinput>
+ </screen>
+- <!-- TODO: why not defined at compile time? -->
+- <para>These environment variables must be set whenever running
+- any tool that uses the HSM, including
+- <command>pkcs11-keygen</command>,
+- <command>pkcs11-list</command>,
+- <command>pkcs11-destroy</command>,
+- <command>dnssec-keyfromlabel</command>,
+- <command>dnssec-signzone</command>,
+- <command>dnssec-keygen</command>(which will use the HSM for
+- random number generation), and
+- <command>named</command>.</para>
+- <para>We can now create and use keys in the HSM. In this case,
+- we will create a 2048 bit key and give it the label
+- "sample-ksk":</para>
++ <para>
++ Such environment variables must be set whenever running
++ any tool that uses the HSM, including
++ <command>pkcs11-keygen</command>,
++ <command>pkcs11-list</command>,
++ <command>pkcs11-destroy</command>,
++ <command>dnssec-keyfromlabel</command>,
++ <command>dnssec-signzone</command>,
++ <command>dnssec-keygen</command>, and
++ <command>named</command>.
++ </para>
++ <para>
++ We can now create and use keys in the HSM. In this case,
++ we will create a 2048 bit key and give it the label
++ "sample-ksk":
++ </para>
+ <screen>
+ $ <userinput>pkcs11-keygen -b 2048 -l sample-ksk</userinput>
+ </screen>
+@@ -334,44 +464,56 @@ Enter PIN:
+ object[0]: handle 2147483658 class 3 label[8] 'sample-ksk' id[0]
+ object[1]: handle 2147483657 class 2 label[8] 'sample-ksk' id[0]
+ </screen>
+- <para>Before using this key to sign a zone, we must create a
+- pair of BIND 9 key files. The "dnssec-keyfromlabel" utility
+- does this. In this case, we will be using the HSM key
+- "sample-ksk" as the key-signing key for "example.net":</para>
++ <para>
++ Before using this key to sign a zone, we must create a
++ pair of BIND 9 key files. The "dnssec-keyfromlabel" utility
++ does this. In this case, we will be using the HSM key
++ "sample-ksk" as the key-signing key for "example.net":
++ </para>
+ <screen>
+ $ <userinput>dnssec-keyfromlabel -l sample-ksk -f KSK example.net</userinput>
+ </screen>
+- <para>The resulting K*.key and K*.private files can now be used
+- to sign the zone. Unlike normal K* files, which contain both
+- public and private key data, these files will contain only the
+- public key data, plus an identifier for the private key which
+- remains stored within the HSM. The HSM handles signing with the
+- private key.</para>
+- <para>If you wish to generate a second key in the HSM for use
+- as a zone-signing key, follow the same procedure above, using a
+- different keylabel, a smaller key size, and omitting "-f KSK"
+- from the dnssec-keyfromlabel arguments:</para>
++ <para>
++ The resulting K*.key and K*.private files can now be used
++ to sign the zone. Unlike normal K* files, which contain both
++ public and private key data, these files will contain only the
++ public key data, plus an identifier for the private key which
++ remains stored within the HSM. Signing with the private key takes
++ place inside the HSM.
++ </para>
++ <para>
++ If you wish to generate a second key in the HSM for use
++ as a zone-signing key, follow the same procedure above, using a
++ different keylabel, a smaller key size, and omitting "-f KSK"
++ from the dnssec-keyfromlabel arguments:
++ </para>
+ <screen>
+ $ <userinput>pkcs11-keygen -b 1024 -l sample-zsk</userinput>
+ $ <userinput>dnssec-keyfromlabel -l sample-zsk example.net</userinput>
+ </screen>
+- <para>Alternatively, you may prefer to generate a conventional
+- on-disk key, using dnssec-keygen:</para>
++ <para>
++ Alternatively, you may prefer to generate a conventional
++ on-disk key, using dnssec-keygen:
++ </para>
+ <screen>
+ $ <userinput>dnssec-keygen example.net</userinput>
+ </screen>
+- <para>This provides less security than an HSM key, but since
+- HSMs can be slow or cumbersome to use for security reasons, it
+- may be more efficient to reserve HSM keys for use in the less
+- frequent key-signing operation. The zone-signing key can be
+- rolled more frequently, if you wish, to compensate for a
+- reduction in key security.</para>
+- <para>Now you can sign the zone. (Note: If not using the -S
+- option to
+- <command>dnssec-signzone</command>, it will be necessary to add
+- the contents of both
+- <filename>K*.key</filename> files to the zone master file before
+- signing it.)</para>
++ <para>
++ This provides less security than an HSM key, but since
++ HSMs can be slow or cumbersome to use for security reasons, it
++ may be more efficient to reserve HSM keys for use in the less
++ frequent key-signing operation. The zone-signing key can be
++ rolled more frequently, if you wish, to compensate for a
++ reduction in key security. (Note: When using native PKCS#11,
++ there is no speed advantage to using on-disk keys, as cryptographic
++ operations will be done by the HSM regardless.)
++ </para>
++ <para>
++ Now you can sign the zone. (Note: If not using the -S
++ option to <command>dnssec-signzone</command>, it will be
++ necessary to add the contents of both <filename>K*.key</filename>
++ files to the zone master file before signing it.)
++ </para>
+ <screen>
+ $ <userinput>dnssec-signzone -S example.net</userinput>
+ Enter PIN:
+@@ -384,36 +526,50 @@ example.net.signed
+ </sect2>
+ <sect2>
+ <title>Specifying the engine on the command line</title>
+- <para>The OpenSSL engine can be specified in
+- <command>named</command> and all of the BIND
+- <command>dnssec-*</command> tools by using the "-E
+- &lt;engine&gt;" command line option. If BIND 9 is built with
+- the --with-pkcs11 option, this option defaults to "pkcs11".
+- Specifying the engine will generally not be necessary unless
+- for some reason you wish to use a different OpenSSL
+- engine.</para>
+- <para>If you wish to disable use of the "pkcs11" engine &mdash;
+- for troubleshooting purposes, or because the HSM is unavailable
+- &mdash; set the engine to the empty string. For example:</para>
++ <para>
++ When using OpenSSL-based PKCS#11, the "engine" to be used by
++ OpenSSL can be specified in <command>named</command> and all of
++ the BIND <command>dnssec-*</command> tools by using the "-E
++ &lt;engine&gt;" command line option. If BIND 9 is built with
++ the --with-pkcs11 option, this option defaults to "pkcs11".
++ Specifying the engine will generally not be necessary unless
++ for some reason you wish to use a different OpenSSL
++ engine.
++ </para>
++ <para>
++ If you wish to disable use of the "pkcs11" engine &mdash;
++ for troubleshooting purposes, or because the HSM is unavailable
++ &mdash; set the engine to the empty string. For example:
++ </para>
+ <screen>
+ $ <userinput>dnssec-signzone -E '' -S example.net</userinput>
+ </screen>
+- <para>This causes
+- <command>dnssec-signzone</command> to run as if it were compiled
+- without the --with-pkcs11 option.</para>
++ <para>
++ This causes
++ <command>dnssec-signzone</command> to run as if it were compiled
++ without the --with-pkcs11 option.
++ </para>
++ <para>
++ When built with native PKCS#11 mode, the "engine" option has a
++ different meaning: it specifies the path to the PKCS#11 provider
++ library. This may be useful when testing a new provider library.
++ </para>
+ </sect2>
+ <sect2>
+ <title>Running named with automatic zone re-signing</title>
+- <para>If you want
+- <command>named</command> to dynamically re-sign zones using HSM
+- keys, and/or to to sign new records inserted via nsupdate, then
+- named must have access to the HSM PIN. This can be accomplished
+- by placing the PIN into the openssl.cnf file (in the above
+- examples,
+- <filename>/opt/pkcs11/usr/ssl/openssl.cnf</filename>).</para>
+- <para>The location of the openssl.cnf file can be overridden by
+- setting the OPENSSL_CONF environment variable before running
+- named.</para>
++ <para>
++ If you want <command>named</command> to dynamically re-sign zones
++ using HSM keys, and/or to to sign new records inserted via nsupdate,
++ then named must have access to the HSM PIN. In OpenSSL-based PKCS#11,
++ this is accomplished by placing the PIN into the openssl.cnf file
++ (in the above examples,
++ <filename>/opt/pkcs11/usr/ssl/openssl.cnf</filename>).
++ </para>
++ <para>
++ The location of the openssl.cnf file can be overridden by
++ setting the OPENSSL_CONF environment variable before running
++ named.
++ </para>
+ <para>Sample openssl.cnf:</para>
+ <programlisting>
+ openssl_conf = openssl_def
+@@ -424,22 +580,25 @@ $ <userinput>dnssec-signzone -E '' -S ex
+ [ pkcs11_section ]
+ PIN = <replaceable>&lt;PLACE PIN HERE&gt;</replaceable>
+ </programlisting>
+- <para>This will also allow the dnssec-* tools to access the HSM
+- without PIN entry. (The pkcs11-* tools access the HSM directly,
+- not via OpenSSL, so a PIN will still be required to use
+- them.)</para>
+-<!--
+-If the PIN is not known, I believe the first time named needs the
+-PIN to open a key, it'll ask you to type in the PIN, which will be
+-a problem because it probably won't be running on a terminal
+--->
++ <para>
++ This will also allow the dnssec-* tools to access the HSM
++ without PIN entry. (The pkcs11-* tools access the HSM directly,
++ not via OpenSSL, so a PIN will still be required to use
++ them.)
++ </para>
++ <para>
++ In native PKCS#11 mode, the PIN can be provided in a file specified
++ as an attribute of the key's label. For example, if a key had the label
++ <userinput>pkcs11:object=local-zsk;pin-source=/etc/hsmpin"</userinput>,
++ then the PIN would be read from the file
++ <filename>/etc/hsmpin</filename>.
++ </para>
+ <warning>
+- <para>Placing the HSM's PIN in a text file in
+- this manner may reduce the security advantage of using an
+- HSM. Be sure this is what you want to do before configuring
+- OpenSSL in this way.</para>
++ <para>
++ Placing the HSM's PIN in a text file in this manner may reduce the
++ security advantage of using an HSM. Be sure this is what you want to
++ do before configuring OpenSSL in this way.
++ </para>
+ </warning>
+ </sect2>
+- <!-- TODO: what is alternative then for named dynamic re-signing? -->
+- <!-- TODO: what happens if PIN is not known? named will log about it? -->
+ </sect1>
+diff -up bind-9.9.6/lib/dns/dnssec.c.native_pkcs11 bind-9.9.6/lib/dns/dnssec.c
+--- bind-9.9.6/lib/dns/dnssec.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/dnssec.c 2014-10-09 13:30:40.904293734 +0200
+@@ -275,7 +275,8 @@ dns_dnssec_sign(dns_name_t *name, dns_rd
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_databuf;
+
+- ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx);
++ ret = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_DNSSEC, ISC_TRUE, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_databuf;
+
+@@ -470,7 +471,8 @@ dns_dnssec_verify3(dns_name_t *name, dns
+ }
+
+ again:
+- ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx);
++ ret = dst_context_create4(key, mctx, DNS_LOGCATEGORY_DNSSEC,
++ ISC_FALSE, maxbits, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_struct;
+
+@@ -872,7 +874,8 @@ dns_dnssec_signmessage(dns_message_t *ms
+
+ isc_buffer_init(&databuf, data, sizeof(data));
+
+- RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx));
++ RETERR(dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_DNSSEC, ISC_TRUE, &ctx));
+
+ /*
+ * Digest the fields of the SIG - we can cheat and use
+@@ -1022,7 +1025,8 @@ dns_dnssec_verifymessage(isc_buffer_t *s
+ goto failure;
+ }
+
+- RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx));
++ RETERR(dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_DNSSEC, ISC_FALSE, &ctx));
+
+ /*
+ * Digest the SIG(0) record, except for the signature.
+diff -up bind-9.9.6/lib/dns/ds.c.native_pkcs11 bind-9.9.6/lib/dns/ds.c
+--- bind-9.9.6/lib/dns/ds.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/ds.c 2014-10-09 13:30:40.904293734 +0200
+@@ -38,11 +38,8 @@
+
+ #include <dst/dst.h>
+
+-#ifdef HAVE_OPENSSL_GOST
+-#include <dst/result.h>
+-#include <openssl/evp.h>
+-
+-extern const EVP_MD * EVP_gost(void);
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
++#include "dst_gost.h"
+ #endif
+
+ isc_result_t
+@@ -59,9 +56,8 @@ dns_ds_buildrdata(dns_name_t *owner, dns
+ isc_sha1_t sha1;
+ isc_sha256_t sha256;
+ isc_sha384_t sha384;
+-#ifdef HAVE_OPENSSL_GOST
+- EVP_MD_CTX ctx;
+- const EVP_MD *md;
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
++ isc_gost_t gost;
+ #endif
+
+ REQUIRE(key != NULL);
+@@ -88,29 +84,23 @@ dns_ds_buildrdata(dns_name_t *owner, dns
+ isc_sha1_final(&sha1, digest);
+ break;
+
+-#ifdef HAVE_OPENSSL_GOST
+-#define CHECK(x) \
+- if ((x) != 1) { \
+- EVP_MD_CTX_cleanup(&ctx); \
+- return (DST_R_CRYPTOFAILURE); \
+- }
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
++#define RETERR(x) do { \
++ isc_result_t ret = (x); \
++ if (ret != ISC_R_SUCCESS) { \
++ isc_gost_invalidate(&gost); \
++ return (ret); \
++ } \
++} while (0)
+
+ case DNS_DSDIGEST_GOST:
+- md = EVP_gost();
+- if (md == NULL)
+- return (DST_R_CRYPTOFAILURE);
+- EVP_MD_CTX_init(&ctx);
+- CHECK(EVP_DigestInit(&ctx, md));
++ RETERR(isc_gost_init(&gost));
+ dns_name_toregion(name, &r);
+- CHECK(EVP_DigestUpdate(&ctx,
+- (const void *) r.base,
+- (size_t) r.length));
++ RETERR(isc_gost_update(&gost, r.base, r.length));
+ dns_rdata_toregion(key, &r);
+ INSIST(r.length >= 4);
+- CHECK(EVP_DigestUpdate(&ctx,
+- (const void *) r.base,
+- (size_t) r.length));
+- CHECK(EVP_DigestFinal(&ctx, digest, NULL));
++ RETERR(isc_gost_update(&gost, r.base, r.length));
++ RETERR(isc_gost_final(&gost, digest));
+ break;
+ #endif
+
+@@ -147,7 +137,7 @@ dns_ds_buildrdata(dns_name_t *owner, dns
+ ds.length = ISC_SHA1_DIGESTLENGTH;
+ break;
+
+-#ifdef HAVE_OPENSSL_GOST
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
+ case DNS_DSDIGEST_GOST:
+ ds.length = ISC_GOST_DIGESTLENGTH;
+ break;
+diff -up bind-9.9.6/lib/dns/dst_api.c.native_pkcs11 bind-9.9.6/lib/dns/dst_api.c
+--- bind-9.9.6/lib/dns/dst_api.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/dst_api.c 2014-10-09 13:30:40.905293735 +0200
+@@ -75,9 +75,7 @@
+ #define DST_AS_STR(t) ((t).value.as_textregion.base)
+
+ static dst_func_t *dst_t_func[DST_MAX_ALGS];
+-#ifdef BIND9
+ static isc_entropy_t *dst_entropy_pool = NULL;
+-#endif
+ static unsigned int dst_entropy_flags = 0;
+ static isc_boolean_t dst_initialized = ISC_FALSE;
+
+@@ -169,7 +167,7 @@ dst_lib_init2(isc_mem_t *mctx, isc_entro
+ #endif
+ REQUIRE(dst_initialized == ISC_FALSE);
+
+-#ifndef OPENSSL
++#if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
+ UNUSED(engine);
+ #endif
+
+@@ -234,7 +232,24 @@ dst_lib_init2(isc_mem_t *mctx, isc_entro
+ RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
+ RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
+ #endif
+-#endif /* OPENSSL */
++#elif PKCS11CRYPTO
++ RETERR(dst__pkcs11_init(mctx, engine));
++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5]));
++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1]));
++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256]));
++ RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512]));
++ RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA]));
++ RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
++ RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH]));
++#ifdef HAVE_PKCS11_ECDSA
++ RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
++ RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
++#endif
++#ifdef HAVE_PKCS11_GOST
++ RETERR(dst__pkcs11gost_init(&dst_t_func[DST_ALG_ECCGOST]));
++#endif
++#endif /* if OPENSSL, elif PKCS11CRYPTO */
+ #ifdef GSSAPI
+ RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
+ #endif
+@@ -259,7 +274,9 @@ dst_lib_destroy(void) {
+ dst_t_func[i]->cleanup();
+ #ifdef OPENSSL
+ dst__openssl_destroy();
+-#endif
++#elif PKCS11CRYPTO
++ (void) dst__pkcs11_destroy();
++#endif /* if OPENSSL, elif PKCS11CRYPTO */
+ if (dst__memory_pool != NULL)
+ isc_mem_detach(&dst__memory_pool);
+ #ifdef BIND9
+@@ -279,13 +296,31 @@ dst_algorithm_supported(unsigned int alg
+
+ isc_result_t
+ dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
+- return (dst_context_create2(key, mctx,
+- DNS_LOGCATEGORY_GENERAL, dctxp));
++ return (dst_context_create4(key, mctx, DNS_LOGCATEGORY_GENERAL,
++ ISC_TRUE, 0, dctxp));
+ }
+
+ isc_result_t
+ dst_context_create2(dst_key_t *key, isc_mem_t *mctx,
+- isc_logcategory_t *category, dst_context_t **dctxp) {
++ isc_logcategory_t *category, dst_context_t **dctxp)
++{
++ return (dst_context_create4(key, mctx, category, ISC_TRUE, 0, dctxp));
++}
++
++isc_result_t
++dst_context_create3(dst_key_t *key, isc_mem_t *mctx,
++ isc_logcategory_t *category, isc_boolean_t useforsigning,
++ dst_context_t **dctxp)
++{
++ return (dst_context_create4(key, mctx, category,
++ useforsigning, 0, dctxp));
++}
++
++isc_result_t
++dst_context_create4(dst_key_t *key, isc_mem_t *mctx,
++ isc_logcategory_t *category, isc_boolean_t useforsigning,
++ int maxbits, dst_context_t **dctxp)
++{
+ dst_context_t *dctx;
+ isc_result_t result;
+
+@@ -294,7 +329,7 @@ dst_context_create2(dst_key_t *key, isc_
+ REQUIRE(mctx != NULL);
+ REQUIRE(dctxp != NULL && *dctxp == NULL);
+
+- if (key->func->createctx == NULL)
++ if (key->func->createctx == NULL && key->func->createctx2 == NULL)
+ return (DST_R_UNSUPPORTEDALG);
+ if (key->keydata.generic == NULL)
+ return (DST_R_NULLKEY);
+@@ -305,7 +340,14 @@ dst_context_create2(dst_key_t *key, isc_
+ dctx->key = key;
+ dctx->mctx = mctx;
+ dctx->category = category;
+- result = key->func->createctx(key, dctx);
++ if (useforsigning)
++ dctx->use = DO_SIGN;
++ else
++ dctx->use = DO_VERIFY;
++ if (key->func->createctx2 != NULL)
++ result = key->func->createctx2(key, maxbits, dctx);
++ else
++ result = key->func->createctx(key, dctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dctx, sizeof(dst_context_t));
+ return (result);
+@@ -1796,7 +1838,7 @@ algorithm_status(unsigned int alg) {
+
+ if (dst_algorithm_supported(alg))
+ return (ISC_R_SUCCESS);
+-#ifndef OPENSSL
++#if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
+ if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
+ alg == DST_ALG_DSA || alg == DST_ALG_DH ||
+ alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
+@@ -1842,11 +1884,18 @@ dst__entropy_getdata(void *buf, unsigned
+
+ if (len == 0)
+ return (ISC_R_SUCCESS);
++
++#ifdef PKCS11CRYPTO
++ UNUSED(pseudo);
++ UNUSED(flags);
++ return (pk11_rand_bytes(buf, len));
++#else /* PKCS11CRYPTO */
+ if (pseudo)
+ flags &= ~ISC_ENTROPY_GOODONLY;
+ else
+ flags |= ISC_ENTROPY_BLOCKING;
+ return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
++#endif /* PKCS11CRYPTO */
+ #else
+ UNUSED(buf);
+ UNUSED(len);
+@@ -1858,7 +1907,7 @@ dst__entropy_getdata(void *buf, unsigned
+
+ unsigned int
+ dst__entropy_status(void) {
+-#ifdef BIND9
++#ifndef PKCS11CRYPTO
+ #ifdef GSSAPI
+ unsigned int flags = dst_entropy_flags;
+ isc_result_t ret;
+diff -up bind-9.9.6/lib/dns/dst_gost.h.native_pkcs11 bind-9.9.6/lib/dns/dst_gost.h
+--- bind-9.9.6/lib/dns/dst_gost.h.native_pkcs11 2014-10-09 13:30:40.906293736 +0200
++++ bind-9.9.6/lib/dns/dst_gost.h 2014-10-09 13:30:40.906293736 +0200
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef DST_GOST_H
++#define DST_GOST_H 1
++
++#include <isc/lang.h>
++#include <isc/log.h>
++#include <dst/result.h>
++
++#define ISC_GOST_DIGESTLENGTH 32U
++
++#ifdef HAVE_OPENSSL_GOST
++#include <openssl/evp.h>
++
++typedef EVP_MD_CTX isc_gost_t;
++#endif
++#ifdef HAVE_PKCS11_GOST
++#include <pk11/pk11.h>
++
++typedef pk11_context_t isc_gost_t;
++#endif
++
++ISC_LANG_BEGINDECLS
++
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
++
++isc_result_t
++isc_gost_init(isc_gost_t *ctx);
++
++void
++isc_gost_invalidate(isc_gost_t *ctx);
++
++isc_result_t
++isc_gost_update(isc_gost_t *ctx, const unsigned char *data, unsigned int len);
++
++isc_result_t
++isc_gost_final(isc_gost_t *ctx, unsigned char *digest);
++
++ISC_LANG_ENDDECLS
++
++#endif /* HAVE_OPENSSL_GOST || HAVE_PKCS11_GOST */
++
++#endif /* DST_GOST_H */
+diff -up bind-9.9.6/lib/dns/dst_internal.h.native_pkcs11 bind-9.9.6/lib/dns/dst_internal.h
+--- bind-9.9.6/lib/dns/dst_internal.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/dst_internal.h 2014-10-09 13:30:40.906293736 +0200
+@@ -84,6 +84,12 @@ typedef struct dst_hmacsha256_key dst_hm
+ typedef struct dst_hmacsha384_key dst_hmacsha384_key_t;
+ typedef struct dst_hmacsha512_key dst_hmacsha512_key_t;
+
++/*%
++ * Indicate whether a DST context will be used for signing
++ * or for verification
++ */
++typedef enum { DO_SIGN, DO_VERIFY } dst_use_t;
++
+ /*% DST Key Structure */
+ struct dst_key {
+ unsigned int magic;
+@@ -112,6 +118,8 @@ struct dst_key {
+ DSA *dsa;
+ DH *dh;
+ EVP_PKEY *pkey;
++#elif PKCS11CRYPTO
++ pk11_object_t *pkey;
+ #endif
+ dst_hmacmd5_key_t *hmacmd5;
+ dst_hmacsha1_key_t *hmacsha1;
+@@ -139,6 +147,7 @@ struct dst_key {
+
+ struct dst_context {
+ unsigned int magic;
++ dst_use_t use;
+ dst_key_t *key;
+ isc_mem_t *mctx;
+ isc_logcategory_t *category;
+@@ -157,6 +166,8 @@ struct dst_context {
+ isc_hmacsha512_t *hmacsha512ctx;
+ #ifdef OPENSSL
+ EVP_MD_CTX *evp_md_ctx;
++#elif PKCS11CRYPTO
++ pk11_context_t *pk11_ctx;
+ #endif
+ } ctxdata;
+ };
+@@ -166,6 +177,8 @@ struct dst_func {
+ * Context functions
+ */
+ isc_result_t (*createctx)(dst_key_t *key, dst_context_t *dctx);
++ isc_result_t (*createctx2)(dst_key_t *key, int maxbits,
++ dst_context_t *dctx);
+ void (*destroyctx)(dst_context_t *dctx);
+ isc_result_t (*adddata)(dst_context_t *dctx, const isc_region_t *data);
+
+@@ -209,6 +222,7 @@ struct dst_func {
+ * Initializers
+ */
+ isc_result_t dst__openssl_init(const char *engine);
++#define dst__pkcs11_init pk11_initialize
+
+ isc_result_t dst__hmacmd5_init(struct dst_func **funcp);
+ isc_result_t dst__hmacsha1_init(struct dst_func **funcp);
+@@ -218,20 +232,30 @@ isc_result_t dst__hmacsha384_init(struct
+ isc_result_t dst__hmacsha512_init(struct dst_func **funcp);
+ isc_result_t dst__opensslrsa_init(struct dst_func **funcp,
+ unsigned char algorithm);
++isc_result_t dst__pkcs11rsa_init(struct dst_func **funcp);
+ isc_result_t dst__openssldsa_init(struct dst_func **funcp);
++isc_result_t dst__pkcs11dsa_init(struct dst_func **funcp);
+ isc_result_t dst__openssldh_init(struct dst_func **funcp);
++isc_result_t dst__pkcs11dh_init(struct dst_func **funcp);
+ isc_result_t dst__gssapi_init(struct dst_func **funcp);
++#ifdef HAVE_OPENSSL_ECDSA
++isc_result_t dst__opensslecdsa_init(struct dst_func **funcp);
++#endif
++#ifdef HAVE_PKCS11_ECDSA
++isc_result_t dst__pkcs11ecdsa_init(struct dst_func **funcp);
++#endif
+ #ifdef HAVE_OPENSSL_GOST
+ isc_result_t dst__opensslgost_init(struct dst_func **funcp);
+ #endif
+-#ifdef HAVE_OPENSSL_ECDSA
+-isc_result_t dst__opensslecdsa_init(struct dst_func **funcp);
++#ifdef HAVE_PKCS11_GOST
++isc_result_t dst__pkcs11gost_init(struct dst_func **funcp);
+ #endif
+
+ /*%
+ * Destructors
+ */
+ void dst__openssl_destroy(void);
++#define dst__pkcs11_destroy pk11_finalize
+
+ /*%
+ * Memory allocators using the DST memory pool.
+diff -up bind-9.9.6/lib/dns/dst_parse.c.native_pkcs11 bind-9.9.6/lib/dns/dst_parse.c
+--- bind-9.9.6/lib/dns/dst_parse.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/dst_parse.c 2014-10-09 13:30:40.907293738 +0200
+@@ -93,7 +93,6 @@ static struct parse_map map[] = {
+ {TAG_RSA_COEFFICIENT, "Coefficient:"},
+ {TAG_RSA_ENGINE, "Engine:" },
+ {TAG_RSA_LABEL, "Label:" },
+- {TAG_RSA_PIN, "PIN:" },
+
+ {TAG_DH_PRIME, "Prime(p):"},
+ {TAG_DH_GENERATOR, "Generator(g):"},
+@@ -107,8 +106,11 @@ static struct parse_map map[] = {
+ {TAG_DSA_PUBLIC, "Public_value(y):"},
+
+ {TAG_GOST_PRIVASN1, "GostAsn1:"},
++ {TAG_GOST_PRIVRAW, "PrivateKey:"},
+
+ {TAG_ECDSA_PRIVATEKEY, "PrivateKey:"},
++ {TAG_ECDSA_ENGINE, "Engine:" },
++ {TAG_ECDSA_LABEL, "Label:" },
+
+ {TAG_HMACMD5_KEY, "Key:"},
+ {TAG_HMACMD5_BITS, "Bits:"},
+@@ -262,22 +264,42 @@ check_gost(const dst_private_t *priv, is
+
+ if (priv->nelements != GOST_NTAGS)
+ return (-1);
+- if (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0))
++ if ((priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 0)) &&
++ (priv->elements[0].tag != TAG(DST_ALG_ECCGOST, 1)))
+ return (-1);
+ return (0);
+ }
+
+ static int
+ check_ecdsa(const dst_private_t *priv, isc_boolean_t external) {
++ int i, j;
++ isc_boolean_t have[ECDSA_NTAGS];
++ isc_boolean_t ok;
++ unsigned int mask;
+
+ if (external)
+ return ((priv->nelements == 0) ? 0 : -1);
+
+- if (priv->nelements != ECDSA_NTAGS)
+- return (-1);
+- if (priv->elements[0].tag != TAG(DST_ALG_ECDSA256, 0))
+- return (-1);
+- return (0);
++ for (i = 0; i < ECDSA_NTAGS; i++)
++ have[i] = ISC_FALSE;
++ for (j = 0; j < priv->nelements; j++) {
++ for (i = 0; i < ECDSA_NTAGS; i++)
++ if (priv->elements[j].tag == TAG(DST_ALG_ECDSA256, i))
++ break;
++ if (i == ECDSA_NTAGS)
++ return (-1);
++ have[i] = ISC_TRUE;
++ }
++
++ mask = ~0;
++ mask <<= sizeof(mask) * 8 - TAG_SHIFT;
++ mask >>= sizeof(mask) * 8 - TAG_SHIFT;
++
++ if (have[TAG_ECDSA_ENGINE & mask])
++ ok = have[TAG_ECDSA_LABEL & mask];
++ else
++ ok = have[TAG_ECDSA_PRIVATEKEY & mask];
++ return (ok ? 0 : -1 );
+ }
+
+ static int
+diff -up bind-9.9.6/lib/dns/dst_parse.h.native_pkcs11 bind-9.9.6/lib/dns/dst_parse.h
+--- bind-9.9.6/lib/dns/dst_parse.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/dst_parse.h 2014-10-09 13:30:40.907293738 +0200
+@@ -63,7 +63,6 @@
+ #define TAG_RSA_COEFFICIENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 7)
+ #define TAG_RSA_ENGINE ((DST_ALG_RSAMD5 << TAG_SHIFT) + 8)
+ #define TAG_RSA_LABEL ((DST_ALG_RSAMD5 << TAG_SHIFT) + 9)
+-#define TAG_RSA_PIN ((DST_ALG_RSAMD5 << TAG_SHIFT) + 10)
+
+ #define DH_NTAGS 4
+ #define TAG_DH_PRIME ((DST_ALG_DH << TAG_SHIFT) + 0)
+@@ -80,9 +79,12 @@
+
+ #define GOST_NTAGS 1
+ #define TAG_GOST_PRIVASN1 ((DST_ALG_ECCGOST << TAG_SHIFT) + 0)
++#define TAG_GOST_PRIVRAW ((DST_ALG_ECCGOST << TAG_SHIFT) + 1)
+
+-#define ECDSA_NTAGS 1
++#define ECDSA_NTAGS 4
+ #define TAG_ECDSA_PRIVATEKEY ((DST_ALG_ECDSA256 << TAG_SHIFT) + 0)
++#define TAG_ECDSA_ENGINE ((DST_ALG_ECDSA256 << TAG_SHIFT) + 1)
++#define TAG_ECDSA_LABEL ((DST_ALG_ECDSA256 << TAG_SHIFT) + 2)
+
+ #define OLD_HMACMD5_NTAGS 1
+ #define HMACMD5_NTAGS 2
+diff -up bind-9.9.6/lib/dns/dst_pkcs11.h.native_pkcs11 bind-9.9.6/lib/dns/dst_pkcs11.h
+--- bind-9.9.6/lib/dns/dst_pkcs11.h.native_pkcs11 2014-10-09 13:30:40.907293738 +0200
++++ bind-9.9.6/lib/dns/dst_pkcs11.h 2014-10-09 13:30:40.907293738 +0200
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef DST_PKCS11_H
++#define DST_PKCS11_H 1
++
++#include <isc/lang.h>
++#include <isc/log.h>
++#include <isc/result.h>
++
++ISC_LANG_BEGINDECLS
++
++isc_result_t
++dst__pkcs11_toresult(const char *funcname, const char *file, int line,
++ isc_result_t fallback, CK_RV rv);
++
++#define PK11_CALL(func, args, fallback) \
++ ((void) (((rv = (func) args) == CKR_OK) || \
++ ((ret = dst__pkcs11_toresult(#func, __FILE__, __LINE__, \
++ fallback, rv)), 0)))
++
++#define PK11_RET(func, args, fallback) \
++ ((void) (((rv = (func) args) == CKR_OK) || \
++ ((ret = dst__pkcs11_toresult(#func, __FILE__, __LINE__, \
++ fallback, rv)), 0))); \
++ if (rv != CKR_OK) goto err;
++
++ISC_LANG_ENDDECLS
++
++#endif /* DST_PKCS11_H */
+diff -up bind-9.9.6/lib/dns/dst_result.c.native_pkcs11 bind-9.9.6/lib/dns/dst_result.c
+--- bind-9.9.6/lib/dns/dst_result.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/dst_result.c 2014-10-09 13:30:40.907293738 +0200
+@@ -50,7 +50,8 @@ static const char *text[DST_R_NRESULTS]
+ "failure computing a shared secret", /*%< 18 */
+ "no randomness available", /*%< 19 */
+ "bad key type", /*%< 20 */
+- "no engine" /*%< 21 */
++ "no engine", /*%< 21 */
++ "illegal operation for an external key",/*%< 22 */
+ };
+
+ #define DST_RESULT_RESULTSET 2
+diff -up bind-9.9.6/lib/dns/gssapi_link.c.native_pkcs11 bind-9.9.6/lib/dns/gssapi_link.c
+--- bind-9.9.6/lib/dns/gssapi_link.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/gssapi_link.c 2014-10-09 13:30:40.908293739 +0200
+@@ -359,6 +359,7 @@ gssapi_dump(dst_key_t *key, isc_mem_t *m
+ static dst_func_t gssapi_functions = {
+ gssapi_create_signverify_ctx,
+ gssapi_destroy_signverify_ctx,
++ NULL, /*%< createctx2 */
+ gssapi_adddata,
+ gssapi_sign,
+ gssapi_verify,
+diff -up bind-9.9.6/lib/dns/hmac_link.c.native_pkcs11 bind-9.9.6/lib/dns/hmac_link.c
+--- bind-9.9.6/lib/dns/hmac_link.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/hmac_link.c 2014-10-09 13:30:40.909293740 +0200
+@@ -281,6 +281,9 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
++ if (key->external)
++ result = DST_R_EXTERNALKEY;
++
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
+ switch (priv.elements[i].tag) {
+@@ -309,6 +312,7 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t
+
+ static dst_func_t hmacmd5_functions = {
+ hmacmd5_createctx,
++ NULL, /*%< createctx2 */
+ hmacmd5_destroyctx,
+ hmacmd5_adddata,
+ hmacmd5_sign,
+@@ -526,6 +530,9 @@ hmacsha1_tofile(const dst_key_t *key, co
+ if (key->keydata.hmacsha1 == NULL)
+ return (DST_R_NULLKEY);
+
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
+ hkey = key->keydata.hmacsha1;
+
+ priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
+@@ -557,8 +564,11 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
++ if (key->external)
++ result = DST_R_EXTERNALKEY;
++
+ key->key_bits = 0;
+- for (i = 0; i < priv.nelements; i++) {
++ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA1_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+@@ -585,6 +595,7 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t
+
+ static dst_func_t hmacsha1_functions = {
+ hmacsha1_createctx,
++ NULL, /*%< createctx2 */
+ hmacsha1_destroyctx,
+ hmacsha1_adddata,
+ hmacsha1_sign,
+@@ -804,6 +815,9 @@ hmacsha224_tofile(const dst_key_t *key,
+ if (key->keydata.hmacsha224 == NULL)
+ return (DST_R_NULLKEY);
+
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
+ hkey = key->keydata.hmacsha224;
+
+ priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
+@@ -835,6 +849,9 @@ hmacsha224_parse(dst_key_t *key, isc_lex
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
++ if (key->external)
++ result = DST_R_EXTERNALKEY;
++
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+@@ -863,6 +880,7 @@ hmacsha224_parse(dst_key_t *key, isc_lex
+
+ static dst_func_t hmacsha224_functions = {
+ hmacsha224_createctx,
++ NULL, /*%< createctx2 */
+ hmacsha224_destroyctx,
+ hmacsha224_adddata,
+ hmacsha224_sign,
+@@ -1082,6 +1100,9 @@ hmacsha256_tofile(const dst_key_t *key,
+ if (key->keydata.hmacsha256 == NULL)
+ return (DST_R_NULLKEY);
+
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
+ hkey = key->keydata.hmacsha256;
+
+ priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
+@@ -1113,8 +1134,11 @@ hmacsha256_parse(dst_key_t *key, isc_lex
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
++ if (key->external)
++ result = DST_R_EXTERNALKEY;
++
+ key->key_bits = 0;
+- for (i = 0; i < priv.nelements; i++) {
++ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA256_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+@@ -1141,6 +1165,7 @@ hmacsha256_parse(dst_key_t *key, isc_lex
+
+ static dst_func_t hmacsha256_functions = {
+ hmacsha256_createctx,
++ NULL, /*%< createctx2 */
+ hmacsha256_destroyctx,
+ hmacsha256_adddata,
+ hmacsha256_sign,
+@@ -1360,6 +1385,9 @@ hmacsha384_tofile(const dst_key_t *key,
+ if (key->keydata.hmacsha384 == NULL)
+ return (DST_R_NULLKEY);
+
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
+ hkey = key->keydata.hmacsha384;
+
+ priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
+@@ -1391,8 +1419,11 @@ hmacsha384_parse(dst_key_t *key, isc_lex
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
++ if (key->external)
++ result = DST_R_EXTERNALKEY;
++
+ key->key_bits = 0;
+- for (i = 0; i < priv.nelements; i++) {
++ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA384_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+@@ -1419,6 +1450,7 @@ hmacsha384_parse(dst_key_t *key, isc_lex
+
+ static dst_func_t hmacsha384_functions = {
+ hmacsha384_createctx,
++ NULL, /*%< createctx2 */
+ hmacsha384_destroyctx,
+ hmacsha384_adddata,
+ hmacsha384_sign,
+@@ -1638,6 +1670,9 @@ hmacsha512_tofile(const dst_key_t *key,
+ if (key->keydata.hmacsha512 == NULL)
+ return (DST_R_NULLKEY);
+
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
+ hkey = key->keydata.hmacsha512;
+
+ priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
+@@ -1669,8 +1704,11 @@ hmacsha512_parse(dst_key_t *key, isc_lex
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
++ if (key->external)
++ result = DST_R_EXTERNALKEY;
++
+ key->key_bits = 0;
+- for (i = 0; i < priv.nelements; i++) {
++ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA512_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+@@ -1697,6 +1735,7 @@ hmacsha512_parse(dst_key_t *key, isc_lex
+
+ static dst_func_t hmacsha512_functions = {
+ hmacsha512_createctx,
++ NULL, /*%< createctx2 */
+ hmacsha512_destroyctx,
+ hmacsha512_adddata,
+ hmacsha512_sign,
+diff -up bind-9.9.6/lib/dns/include/dst/dst.h.native_pkcs11 bind-9.9.6/lib/dns/include/dst/dst.h
+--- bind-9.9.6/lib/dns/include/dst/dst.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/include/dst/dst.h 2014-10-09 13:30:40.909293740 +0200
+@@ -175,6 +175,16 @@ isc_result_t
+ dst_context_create2(dst_key_t *key, isc_mem_t *mctx,
+ isc_logcategory_t *category, dst_context_t **dctxp);
+
++isc_result_t
++dst_context_create3(dst_key_t *key, isc_mem_t *mctx,
++ isc_logcategory_t *category, isc_boolean_t useforsigning,
++ dst_context_t **dctxp);
++
++isc_result_t
++dst_context_create4(dst_key_t *key, isc_mem_t *mctx,
++ isc_logcategory_t *category, isc_boolean_t useforsigning,
++ int maxbits, dst_context_t **dctxp);
++
+ /*%<
+ * Creates a context to be used for a sign or verify operation.
+ *
+diff -up bind-9.9.6/lib/dns/include/dst/result.h.native_pkcs11 bind-9.9.6/lib/dns/include/dst/result.h
+--- bind-9.9.6/lib/dns/include/dst/result.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/include/dst/result.h 2014-10-09 13:30:40.909293740 +0200
+@@ -57,8 +57,9 @@
+ #define DST_R_NORANDOMNESS (ISC_RESULTCLASS_DST + 19)
+ #define DST_R_BADKEYTYPE (ISC_RESULTCLASS_DST + 20)
+ #define DST_R_NOENGINE (ISC_RESULTCLASS_DST + 21)
++#define DST_R_EXTERNALKEY (ISC_RESULTCLASS_DST + 22)
+
+-#define DST_R_NRESULTS 22 /* Number of results */
++#define DST_R_NRESULTS 23 /* Number of results */
+
+ ISC_LANG_BEGINDECLS
+
+diff -up bind-9.9.6/lib/dns/Makefile.in.native_pkcs11 bind-9.9.6/lib/dns/Makefile.in
+--- bind-9.9.6/lib/dns/Makefile.in.native_pkcs11 2014-10-09 13:29:59.134238282 +0200
++++ bind-9.9.6/lib/dns/Makefile.in 2014-10-09 13:30:40.903293732 +0200
+@@ -27,10 +27,10 @@ top_srcdir = @top_srcdir@
+
+ USE_ISC_SPNEGO = @USE_ISC_SPNEGO@
+
+-CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} \
+- ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
++CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \
++ @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+
+-CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@ ${USE_ISC_SPNEGO}
++CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@ ${USE_ISC_SPNEGO}
+
+ CWARNINGS =
+
+@@ -47,7 +47,10 @@ OPENSSLLINKOBJS = openssl_link.@O@ opens
+ opensslecdsa_link.@O@ @OPENSSLGOSTLINKOBJS@ \
+ opensslrsa_link.@O@
+
+-DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ \
++PKCS11LINKOBJS = pkcs11dh_link.@O@ pkcs11dsa_link.@O@ pkcs11rsa_link.@O@ \
++ pkcs11ecdsa_link.@O@ pkcs11gost_link.@O@ pkcs11.@O@
++
++DSTOBJS = @DST_EXTRA_OBJS@ @OPENSSLLINKOBJS@ @PKCS11LINKOBJS@ \
+ dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
+ gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@
+
+@@ -79,7 +82,10 @@ OPENSSLGOSTLINKSRCS = opensslgost_link.c
+ OPENSSLLINKSRCS = openssl_link.c openssldh_link.c openssldsa_link.c \
+ opensslecdsa_link.c @OPENSSLGOSTLINKSRCS@ opensslrsa_link.c
+
+-DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ \
++PKCS11LINKSRCS = pkcs11dh_link.c pkcs11dsa_link.c pkcs11rsa_link.c \
++ pkcs11ecdsa_link.c pkcs11gost_link.c pkcs11.c
++
++DSTSRCS = @DST_EXTRA_SRCS@ @OPENSSLLINKSRCS@ @PKCS11LINKSRCS@ \
+ dst_api.c dst_lib.c dst_parse.c \
+ dst_result.c gssapi_link.c gssapictx.c \
+ hmac_link.c key.c
+diff -up bind-9.9.6/lib/dns/openssldh_link.c.native_pkcs11 bind-9.9.6/lib/dns/openssldh_link.c
+--- bind-9.9.6/lib/dns/openssldh_link.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/openssldh_link.c 2014-10-09 13:30:40.910293742 +0200
+@@ -463,6 +463,9 @@ openssldh_tofile(const dst_key_t *key, c
+ if (key->keydata.dh == NULL)
+ return (DST_R_NULLKEY);
+
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
+ dh = key->keydata.dh;
+
+ memset(bufs, 0, sizeof(bufs));
+@@ -528,6 +531,9 @@ openssldh_parse(dst_key_t *key, isc_lex_
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
++ if (key->external)
++ DST_RET(DST_R_EXTERNALKEY);
++
+ dh = DH_new();
+ if (dh == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+@@ -630,6 +636,7 @@ openssldh_cleanup(void) {
+
+ static dst_func_t openssldh_functions = {
+ NULL, /*%< createctx */
++ NULL, /*%< createctx2 */
+ NULL, /*%< destroyctx */
+ NULL, /*%< adddata */
+ NULL, /*%< openssldh_sign */
+diff -up bind-9.9.6/lib/dns/opensslecdsa_link.c.native_pkcs11 bind-9.9.6/lib/dns/opensslecdsa_link.c
+--- bind-9.9.6/lib/dns/opensslecdsa_link.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/opensslecdsa_link.c 2014-10-10 18:07:20.746138258 +0200
+@@ -18,7 +18,7 @@
+
+ #include <config.h>
+
+-#ifdef HAVE_OPENSSL_ECDSA
++#if defined(OPENSSL) && defined(HAVE_OPENSSL_ECDSA)
+
+ #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384)
+ #error "ECDSA without EVP for SHA2?"
+@@ -474,7 +474,7 @@ opensslecdsa_tofile(const dst_key_t *key
+ priv.elements[0].length = BN_num_bytes(privkey);
+ BN_bn2bin(privkey, buf);
+ priv.elements[0].data = buf;
+- priv.nelements = ECDSA_NTAGS;
++ priv.nelements = 1;
+ ret = dst__privstruct_writefile(key, &priv, directory);
+
+ err:
+@@ -519,60 +519,50 @@ static isc_result_t
+ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
+ dst_private_t priv;
+ isc_result_t ret;
+- EVP_PKEY *pkey, *pubpkey;
+- EC_KEY *eckey = NULL, *pubeckey = NULL;
+- const EC_POINT *pubkey;
+- BIGNUM *privkey;
++ EVP_PKEY *pkey;
++ EC_KEY *eckey = NULL;
++ BIGNUM *privkey = NULL;
+ int group_nid;
+ isc_mem_t *mctx = key->mctx;
+
+ REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
+ key->key_alg == DST_ALG_ECDSA384);
+
+- if (key->key_alg == DST_ALG_ECDSA256)
+- group_nid = NID_X9_62_prime256v1;
+- else
+- group_nid = NID_secp384r1;
+-
+- eckey = EC_KEY_new_by_curve_name(group_nid);
+- if (eckey == NULL)
+- return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+-
+ /* read private key file */
+ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
+ if (ret != ISC_R_SUCCESS)
+ goto err;
+
+ if (key->external) {
+- /*
+- * Copy the public key to this new key.
+- */
+- if (pub == NULL)
+- DST_RET(DST_R_INVALIDPRIVATEKEY);
+- pubpkey = pub->keydata.pkey;
+- pubeckey = EVP_PKEY_get1_EC_KEY(pubpkey);
+- if (pubeckey == NULL)
+- DST_RET(DST_R_INVALIDPRIVATEKEY);
+- pubkey = EC_KEY_get0_public_key(pubeckey);
+- if (pubkey == NULL)
+- DST_RET(DST_R_INVALIDPRIVATEKEY);
+- if (EC_KEY_set_public_key(eckey, pubkey) != 1)
+- DST_RET(DST_R_INVALIDPRIVATEKEY);
+- if (EC_KEY_check_key(eckey) != 1)
++ if (priv.nelements != 0)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+- } else {
+- privkey = BN_bin2bn(priv.elements[0].data,
+- priv.elements[0].length, NULL);
+- if (privkey == NULL)
+- DST_RET(ISC_R_NOMEMORY);
+- if (!EC_KEY_set_private_key(eckey, privkey))
+- DST_RET(ISC_R_NOMEMORY);
+- if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
++ if (pub == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ key->keydata.pkey = pub->keydata.pkey;
++ pub->keydata.pkey = NULL;
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
++ return (ISC_R_SUCCESS);
+ }
+
++ if (key->key_alg == DST_ALG_ECDSA256)
++ group_nid = NID_X9_62_prime256v1;
++ else
++ group_nid = NID_secp384r1;
++
++ eckey = EC_KEY_new_by_curve_name(group_nid);
++ if (eckey == NULL)
++ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
++
++ privkey = BN_bin2bn(priv.elements[0].data,
++ priv.elements[0].length, NULL);
++ if (privkey == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ if (!EC_KEY_set_private_key(eckey, privkey))
++ DST_RET(ISC_R_NOMEMORY);
++ if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ DST_RET (ISC_R_NOMEMORY);
+@@ -584,10 +574,10 @@ opensslecdsa_parse(dst_key_t *key, isc_l
+ ret = ISC_R_SUCCESS;
+
+ err:
++ if (privkey != NULL)
++ BN_clear_free(privkey);
+ if (eckey != NULL)
+ EC_KEY_free(eckey);
+- if (pubeckey != NULL)
+- EC_KEY_free(pubeckey);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ret);
+@@ -595,6 +585,7 @@ opensslecdsa_parse(dst_key_t *key, isc_l
+
+ static dst_func_t opensslecdsa_functions = {
+ opensslecdsa_createctx,
++ NULL, /*%< createctx2 */
+ opensslecdsa_destroyctx,
+ opensslecdsa_adddata,
+ opensslecdsa_sign,
+diff -up bind-9.9.6/lib/dns/opensslgost_link.c.native_pkcs11 bind-9.9.6/lib/dns/opensslgost_link.c
+--- bind-9.9.6/lib/dns/opensslgost_link.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/opensslgost_link.c 2014-10-09 13:30:47.820302915 +0200
+@@ -30,6 +30,7 @@
+ #include "dst_internal.h"
+ #include "dst_openssl.h"
+ #include "dst_parse.h"
++#include "dst_gost.h"
+
+ #include <openssl/err.h>
+ #include <openssl/objects.h>
+@@ -44,6 +45,60 @@ const EVP_MD *EVP_gost(void) {
+ return (opensslgost_digest);
+ }
+
++/* ISC methods */
++
++isc_result_t
++isc_gost_init(isc_gost_t *ctx) {
++ const EVP_MD *md;
++ int ret;
++
++ INSIST(ctx != NULL);
++
++ md = EVP_gost();
++ if (md == NULL)
++ return (DST_R_CRYPTOFAILURE);
++ EVP_MD_CTX_init(ctx);
++ ret = EVP_DigestInit(ctx, md);
++ if (ret != 1)
++ return (DST_R_CRYPTOFAILURE);
++ return (ISC_R_SUCCESS);
++}
++
++void
++isc_gost_invalidate(isc_gost_t *ctx) {
++ EVP_MD_CTX_cleanup(ctx);
++}
++
++isc_result_t
++isc_gost_update(isc_gost_t *ctx, const unsigned char *data,
++ unsigned int len)
++{
++ int ret;
++
++ INSIST(ctx != NULL);
++ INSIST(data != NULL);
++
++ ret = EVP_DigestUpdate(ctx, (const void *) data, (size_t) len);
++ if (ret != 1)
++ return (DST_R_CRYPTOFAILURE);
++ return (ISC_R_SUCCESS);
++}
++
++isc_result_t
++isc_gost_final(isc_gost_t *ctx, unsigned char *digest) {
++ int ret;
++
++ INSIST(ctx != NULL);
++ INSIST(digest != NULL);
++
++ ret = EVP_DigestFinal(ctx, digest, NULL);
++ if (ret != 1)
++ return (DST_R_CRYPTOFAILURE);
++ return (ISC_R_SUCCESS);
++}
++
++/* DST methods */
++
+ #define DST_RET(a) {ret = a; goto err;}
+
+ static isc_result_t opensslgost_todns(const dst_key_t *key,
+@@ -285,6 +340,8 @@ opensslgost_fromdns(dst_key_t *key, isc_
+ return (ISC_R_SUCCESS);
+ }
+
++#ifdef PREFER_GOSTASN1
++
+ static isc_result_t
+ opensslgost_tofile(const dst_key_t *key, const char *directory) {
+ EVP_PKEY *pkey;
+@@ -318,7 +375,7 @@ opensslgost_tofile(const dst_key_t *key,
+ priv.elements[0].tag = TAG_GOST_PRIVASN1;
+ priv.elements[0].length = len;
+ priv.elements[0].data = der;
+- priv.nelements = GOST_NTAGS;
++ priv.nelements = 1;
+
+ result = dst__privstruct_writefile(key, &priv, directory);
+ fail:
+@@ -327,42 +384,146 @@ opensslgost_tofile(const dst_key_t *key,
+ return (result);
+ }
+
++#else
++
++static isc_result_t
++opensslgost_tofile(const dst_key_t *key, const char *directory) {
++ EVP_PKEY *pkey;
++ EC_KEY *eckey;
++ const BIGNUM *privkey;
++ dst_private_t priv;
++ isc_result_t ret;
++ unsigned char *buf = NULL;
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external) {
++ priv.nelements = 0;
++ return (dst__privstruct_writefile(key, &priv, directory));
++ }
++
++ pkey = key->keydata.pkey;
++ eckey = EVP_PKEY_get0(pkey);
++ if (eckey == NULL)
++ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
++ privkey = EC_KEY_get0_private_key(eckey);
++ if (privkey == NULL)
++ return (ISC_R_FAILURE);
++
++ buf = isc_mem_get(key->mctx, BN_num_bytes(privkey));
++ if (buf == NULL)
++ return (ISC_R_NOMEMORY);
++
++ priv.elements[0].tag = TAG_GOST_PRIVRAW;
++ priv.elements[0].length = BN_num_bytes(privkey);
++ BN_bn2bin(privkey, buf);
++ priv.elements[0].data = buf;
++ priv.nelements = 1;
++
++ ret = dst__privstruct_writefile(key, &priv, directory);
++
++ if (buf != NULL)
++ isc_mem_put(key->mctx, buf, BN_num_bytes(privkey));
++ return (ret);
++}
++#endif
++
++static unsigned char gost_dummy_key[71] = {
++ 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
++ 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
++ 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
++ 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
++ 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b,
++ 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5,
++ 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65,
++ 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63,
++ 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6
++};
++
+ static isc_result_t
+ opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
+ dst_private_t priv;
+ isc_result_t ret;
+ isc_mem_t *mctx = key->mctx;
+ EVP_PKEY *pkey = NULL;
++ EC_KEY *eckey;
++ const EC_POINT *pubkey = NULL;
++ BIGNUM *privkey = NULL;
+ const unsigned char *p;
+
+- UNUSED(pub);
+-
+ /* read private key file */
+ ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, lexer, mctx, &priv);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ if (key->external) {
+- INSIST(priv.nelements == 0);
++ if (priv.nelements != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ if (pub == NULL)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+ key->keydata.pkey = pub->keydata.pkey;
+ pub->keydata.pkey = NULL;
+- } else {
+- INSIST(priv.elements[0].tag == TAG_GOST_PRIVASN1);
++ key->key_size = pub->key_size;
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ISC_R_SUCCESS);
++ }
++
++ INSIST((priv.elements[0].tag == TAG_GOST_PRIVASN1) ||
++ (priv.elements[0].tag == TAG_GOST_PRIVRAW));
++
++ if (priv.elements[0].tag == TAG_GOST_PRIVASN1) {
+ p = priv.elements[0].data;
+ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
+ (long) priv.elements[0].length) == NULL)
+- DST_RET(dst__openssl_toresult2("d2i_PrivateKey",
+- DST_R_INVALIDPRIVATEKEY));
+- key->keydata.pkey = pkey;
++ DST_RET(dst__openssl_toresult2(
++ "d2i_PrivateKey",
++ DST_R_INVALIDPRIVATEKEY));
++ } else {
++ if ((pub != NULL) && (pub->keydata.pkey != NULL)) {
++ eckey = EVP_PKEY_get0(pub->keydata.pkey);
++ pubkey = EC_KEY_get0_public_key(eckey);
++ }
++
++ privkey = BN_bin2bn(priv.elements[0].data,
++ priv.elements[0].length, NULL);
++ if (privkey == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++
++ /* can't create directly the whole key */
++ p = gost_dummy_key;
++ if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
++ (long) sizeof(gost_dummy_key)) == NULL)
++ DST_RET(dst__openssl_toresult2(
++ "d2i_PrivateKey",
++ DST_R_INVALIDPRIVATEKEY));
++
++ eckey = EVP_PKEY_get0(pkey);
++ if (eckey == NULL)
++ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
++ if (!EC_KEY_set_private_key(eckey, privkey))
++ DST_RET(ISC_R_NOMEMORY);
++
++ /* have to (re)set the public key */
++#ifdef notyet
++ (void) gost2001_compute_public(eckey);
++#else
++ if ((pubkey != NULL) && !EC_KEY_set_public_key(eckey, pubkey))
++ DST_RET(ISC_R_NOMEMORY);
++#endif
++ BN_clear_free(privkey);
++ privkey = NULL;
+ }
++ key->keydata.pkey = pkey;
+ key->key_size = EVP_PKEY_bits(pkey);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ISC_R_SUCCESS);
+
+ err:
++ if (privkey != NULL)
++ BN_clear_free(privkey);
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ opensslgost_destroy(key);
+@@ -382,6 +543,7 @@ opensslgost_cleanup(void) {
+
+ static dst_func_t opensslgost_functions = {
+ opensslgost_createctx,
++ NULL, /*%< createctx2 */
+ opensslgost_destroyctx,
+ opensslgost_adddata,
+ opensslgost_sign,
+diff -up bind-9.9.6/lib/dns/opensslrsa_link.c.native_pkcs11 bind-9.9.6/lib/dns/opensslrsa_link.c
+--- bind-9.9.6/lib/dns/opensslrsa_link.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/opensslrsa_link.c 2014-10-09 13:30:47.820302915 +0200
+@@ -1196,6 +1196,24 @@ opensslrsa_parse(dst_key_t *key, isc_lex
+ EVP_PKEY *pkey = NULL;
+ #endif
+
++ /* read private key file */
++ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ if (key->external) {
++ if (priv.nelements != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ if (pub == NULL)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ key->keydata.pkey = pub->keydata.pkey;
++ pub->keydata.pkey = NULL;
++ key->key_size = pub->key_size;
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ISC_R_SUCCESS);
++ }
++
+ #if USE_EVP
+ if (pub != NULL && pub->keydata.pkey != NULL)
+ pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey);
+@@ -1206,14 +1224,6 @@ opensslrsa_parse(dst_key_t *key, isc_lex
+ }
+ #endif
+
+- /* read private key file */
+- ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
+- if (ret != ISC_R_SUCCESS)
+- goto err;
+-
+- if (key->external && priv.nelements != 0)
+- DST_RET(DST_R_INVALIDPRIVATEKEY);
+-
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_RSA_ENGINE:
+@@ -1297,8 +1307,6 @@ opensslrsa_parse(dst_key_t *key, isc_lex
+ continue;
+ case TAG_RSA_LABEL:
+ continue;
+- case TAG_RSA_PIN:
+- continue;
+ default:
+ bn = BN_bin2bn(priv.elements[i].data,
+ priv.elements[i].length, NULL);
+@@ -1338,10 +1346,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex
+
+ if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
+ DST_RET(DST_R_INVALIDPRIVATEKEY);
+- if (!key->external) {
+- if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
+- DST_RET(ISC_R_RANGE);
+- }
++ if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
++ DST_RET(ISC_R_RANGE);
+ key->key_size = BN_num_bits(rsa->n);
+ if (pubrsa != NULL)
+ RSA_free(pubrsa);
+@@ -1448,6 +1454,7 @@ opensslrsa_fromlabel(dst_key_t *key, con
+
+ static dst_func_t opensslrsa_functions = {
+ opensslrsa_createctx,
++ NULL, /*%< createctx2 */
+ opensslrsa_destroyctx,
+ opensslrsa_adddata,
+ opensslrsa_sign,
+diff -up bind-9.9.6/lib/dns/pkcs11.c.native_pkcs11 bind-9.9.6/lib/dns/pkcs11.c
+--- bind-9.9.6/lib/dns/pkcs11.c.native_pkcs11 2014-10-09 13:30:47.821302916 +0200
++++ bind-9.9.6/lib/dns/pkcs11.c 2014-10-09 13:30:47.821302916 +0200
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifdef PKCS11CRYPTO
++
++#include <config.h>
++
++#include <dns/log.h>
++#include <dns/result.h>
++
++#include <pk11/pk11.h>
++#include <pk11/internal.h>
++
++#include "dst_pkcs11.h"
++
++isc_result_t
++dst__pkcs11_toresult(const char *funcname, const char *file, int line,
++ isc_result_t fallback, CK_RV rv)
++{
++ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
++ DNS_LOGMODULE_CRYPTO, ISC_LOG_WARNING,
++ "%s:%d: %s: Error = 0x%.8lX\n",
++ file, line, funcname, rv);
++ if (rv == CKR_HOST_MEMORY)
++ return (ISC_R_NOMEMORY);
++ return (fallback);
++}
++
++
++#else /* PKCS11CRYPTO */
++
++#include <isc/util.h>
++
++EMPTY_TRANSLATION_UNIT
++
++#endif /* PKCS11CRYPTO */
++/*! \file */
+diff -up bind-9.9.6/lib/dns/pkcs11dh_link.c.native_pkcs11 bind-9.9.6/lib/dns/pkcs11dh_link.c
+--- bind-9.9.6/lib/dns/pkcs11dh_link.c.native_pkcs11 2014-10-09 13:30:47.822302918 +0200
++++ bind-9.9.6/lib/dns/pkcs11dh_link.c 2014-10-09 13:30:47.822302918 +0200
+@@ -0,0 +1,1140 @@
++/*
++ * Portions Copyright (C) 20012 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#ifdef PKCS11CRYPTO
++
++#include <config.h>
++
++#include <ctype.h>
++
++#include <isc/mem.h>
++#include <isc/string.h>
++#include <isc/util.h>
++
++#include <dst/result.h>
++
++#include "dst_internal.h"
++#include "dst_parse.h"
++#include "dst_pkcs11.h"
++
++#include <pk11/pk11.h>
++#include <pk11/internal.h>
++#define WANT_DH_PRIMES
++#include <pk11/constants.h>
++
++#include <pkcs11/pkcs11.h>
++
++/*
++ * PKCS#3 DH keys:
++ * mechanisms:
++ * CKM_DH_PKCS_PARAMETER_GEN,
++ * CKM_DH_PKCS_KEY_PAIR_GEN,
++ * CKM_DH_PKCS_DERIVE
++ * domain parameters:
++ * object class CKO_DOMAIN_PARAMETERS
++ * key type CKK_DH
++ * attribute CKA_PRIME (prime p)
++ * attribute CKA_BASE (base g)
++ * optional attribute CKA_PRIME_BITS (p length in bits)
++ * public key:
++ * object class CKO_PUBLIC_KEY
++ * key type CKK_DH
++ * attribute CKA_PRIME (prime p)
++ * attribute CKA_BASE (base g)
++ * attribute CKA_VALUE (public value y)
++ * private key:
++ * object class CKO_PRIVATE_KEY
++ * key type CKK_DH
++ * attribute CKA_PRIME (prime p)
++ * attribute CKA_BASE (base g)
++ * attribute CKA_VALUE (private value x)
++ * optional attribute CKA_VALUE_BITS (x length in bits)
++ * reuse CKA_PRIVATE_EXPONENT for key pair private value
++ */
++
++#define CKA_VALUE2 CKA_PRIVATE_EXPONENT
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++#define DST_RET(a) {ret = a; goto err;}
++
++static void pkcs11dh_destroy(dst_key_t *key);
++static isc_result_t pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data);
++
++static isc_result_t
++pkcs11dh_loadpriv(const dst_key_t *key,
++ CK_SESSION_HANDLE session,
++ CK_OBJECT_HANDLE *hKey)
++{
++ CK_RV rv;
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_DH;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_PRIME, NULL, 0 },
++ { CKA_BASE, NULL, 0 },
++ { CKA_VALUE, NULL, 0 }
++ };
++ CK_ATTRIBUTE *attr;
++ const pk11_object_t *priv;
++ isc_result_t ret;
++ unsigned int i;
++
++ priv = key->keydata.pkey;
++ if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) {
++ *hKey = priv->object;
++ return (ISC_R_SUCCESS);
++ }
++
++ attr = pk11_attribute_bytype(priv, CKA_PRIME);
++ if (attr == NULL)
++ return (DST_R_INVALIDPRIVATEKEY);
++ keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++
++ attr = pk11_attribute_bytype(priv, CKA_BASE);
++ if (attr == NULL)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (keyTemplate[7].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen);
++ keyTemplate[7].ulValueLen = attr->ulValueLen;
++
++ attr = pk11_attribute_bytype(priv, CKA_VALUE2);
++ if (attr == NULL)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (keyTemplate[8].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen);
++ keyTemplate[8].ulValueLen = attr->ulValueLen;
++
++ PK11_CALL(pkcs_C_CreateObject,
++ (session, keyTemplate, (CK_ULONG) 9, hKey),
++ DST_R_COMPUTESECRETFAILURE);
++ if (rv == CKR_OK)
++ ret = ISC_R_SUCCESS;
++
++ err:
++ for (i = 6; i <= 8; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(key->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ return (ret);
++}
++
++static isc_result_t
++pkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
++ isc_buffer_t *secret)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
++ CK_OBJECT_HANDLE hDerived = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
++ CK_ATTRIBUTE *attr;
++ CK_ULONG secLen;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE_LEN, &secLen, (CK_ULONG) sizeof(secLen) }
++ };
++ CK_ATTRIBUTE valTemplate[] =
++ {
++ { CKA_VALUE, NULL, 0 }
++ };
++ CK_BYTE *secValue;
++ pk11_context_t ctx;
++ isc_result_t ret;
++ unsigned int i;
++ isc_region_t r;
++
++ REQUIRE(pub->keydata.pkey != NULL);
++ REQUIRE(priv->keydata.pkey != NULL);
++ REQUIRE(priv->keydata.pkey->repr != NULL);
++ attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_PRIME);
++ if (attr == NULL)
++ return (DST_R_INVALIDPUBLICKEY);
++ REQUIRE(attr != NULL);
++ secLen = attr->ulValueLen;
++ attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE);
++ if (attr == NULL)
++ return (DST_R_INVALIDPUBLICKEY);
++
++ ret = pk11_get_session(&ctx, OP_DH, ISC_TRUE, ISC_FALSE, ISC_FALSE,
++ NULL, pk11_get_best_token(OP_DH));
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ mech.ulParameterLen = attr->ulValueLen;
++ mech.pParameter = isc_mem_get(pub->mctx, mech.ulParameterLen);
++ if (mech.pParameter == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(mech.pParameter, attr->pValue, mech.ulParameterLen);
++
++ ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ PK11_RET(pkcs_C_DeriveKey,
++ (ctx.session, &mech, hKey,
++ keyTemplate, (CK_ULONG) 6, &hDerived),
++ DST_R_COMPUTESECRETFAILURE);
++
++ attr = valTemplate;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (ctx.session, hDerived, attr, (CK_ULONG) 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(pub->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (ctx.session, hDerived, attr, (CK_ULONG) 1),
++ DST_R_CRYPTOFAILURE);
++
++ /* strip leading zeros */
++ secValue = (CK_BYTE_PTR) attr->pValue;
++ for (i = 0; i < attr->ulValueLen; i++)
++ if (secValue[i] != 0)
++ break;
++ isc_buffer_availableregion(secret, &r);
++ if (r.length < attr->ulValueLen - i)
++ DST_RET(ISC_R_NOSPACE);
++ memcpy(r.base, secValue + i, attr->ulValueLen - i);
++ isc_buffer_add(secret, attr->ulValueLen - i);
++ ret = ISC_R_SUCCESS;
++
++ err:
++ if (hDerived != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx.session, hDerived);
++ if (valTemplate[0].pValue != NULL) {
++ memset(valTemplate[0].pValue, 0, valTemplate[0].ulValueLen);
++ isc_mem_put(pub->mctx,
++ valTemplate[0].pValue,
++ valTemplate[0].ulValueLen);
++ }
++ if ((hKey != CK_INVALID_HANDLE) && !priv->keydata.pkey->ontoken)
++ (void) pkcs_C_DestroyObject(ctx.session, hKey);
++ if (mech.pParameter != NULL) {
++ memset(mech.pParameter, 0, mech.ulParameterLen);
++ isc_mem_put(pub->mctx, mech.pParameter, mech.ulParameterLen);
++ }
++ pk11_return_session(&ctx);
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11dh_compare(const dst_key_t *key1, const dst_key_t *key2) {
++ pk11_object_t *dh1, *dh2;
++ CK_ATTRIBUTE *attr1, *attr2;
++
++ dh1 = key1->keydata.pkey;
++ dh2 = key2->keydata.pkey;
++
++ if ((dh1 == NULL) && (dh2 == NULL))
++ return (ISC_TRUE);
++ else if ((dh1 == NULL) || (dh2 == NULL))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dh1, CKA_PRIME);
++ attr2 = pk11_attribute_bytype(dh2, CKA_PRIME);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dh1, CKA_BASE);
++ attr2 = pk11_attribute_bytype(dh2, CKA_BASE);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dh1, CKA_VALUE);
++ attr2 = pk11_attribute_bytype(dh2, CKA_VALUE);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dh1, CKA_VALUE2);
++ attr2 = pk11_attribute_bytype(dh2, CKA_VALUE2);
++ if (((attr1 != NULL) || (attr2 != NULL)) &&
++ ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
++ return (ISC_FALSE);
++
++ if (!dh1->ontoken && !dh2->ontoken)
++ return (ISC_TRUE);
++ else if (dh1->ontoken || dh2->ontoken ||
++ (dh1->object != dh2->object))
++ return (ISC_FALSE);
++
++ return (ISC_TRUE);
++}
++
++static isc_boolean_t
++pkcs11dh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
++ pk11_object_t *dh1, *dh2;
++ CK_ATTRIBUTE *attr1, *attr2;
++
++ dh1 = key1->keydata.pkey;
++ dh2 = key2->keydata.pkey;
++
++ if ((dh1 == NULL) && (dh2 == NULL))
++ return (ISC_TRUE);
++ else if ((dh1 == NULL) || (dh2 == NULL))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dh1, CKA_PRIME);
++ attr2 = pk11_attribute_bytype(dh2, CKA_PRIME);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dh1, CKA_BASE);
++ attr2 = pk11_attribute_bytype(dh2, CKA_BASE);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ return (ISC_TRUE);
++}
++
++static isc_result_t
++pkcs11dh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_DH_PKCS_PARAMETER_GEN, NULL, 0 };
++ CK_OBJECT_HANDLE domainparams = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS dClass = CKO_DOMAIN_PARAMETERS;
++ CK_KEY_TYPE keyType = CKK_DH;
++ CK_ULONG bits = 0;
++ CK_ATTRIBUTE dTemplate[] =
++ {
++ { CKA_CLASS, &dClass, (CK_ULONG) sizeof(dClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) }
++ };
++ CK_ATTRIBUTE pTemplate[] =
++ {
++ { CKA_PRIME, NULL, 0 },
++ { CKA_BASE, NULL, 0 }
++ };
++ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
++ CK_ATTRIBUTE pubTemplate[] =
++ {
++ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
++ { CKA_KEY_TYPE,&keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIME, NULL, 0 },
++ { CKA_BASE, NULL, 0 },
++ };
++ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
++ CK_ATTRIBUTE privTemplate[] =
++ {
++ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *dh = NULL;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++
++ UNUSED(callback);
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_DH, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_DH));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ bits = key->key_size;
++ if ((generator == 0) &&
++ ((bits == 768) || (bits == 1024) || (bits == 1536))) {
++ if (bits == 768) {
++ pubTemplate[4].pValue =
++ isc_mem_get(key->mctx, sizeof(pk11_dh_bn768));
++ if (pubTemplate[4].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(pubTemplate[4].pValue,
++ pk11_dh_bn768, sizeof(pk11_dh_bn768));
++ pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn768);
++ } else if (bits == 1024) {
++ pubTemplate[4].pValue =
++ isc_mem_get(key->mctx, sizeof(pk11_dh_bn1024));
++ if (pubTemplate[4].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(pubTemplate[4].pValue,
++ pk11_dh_bn1024, sizeof(pk11_dh_bn1024));
++ pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1024);
++ } else {
++ pubTemplate[4].pValue =
++ isc_mem_get(key->mctx, sizeof(pk11_dh_bn1536));
++ if (pubTemplate[4].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(pubTemplate[4].pValue,
++ pk11_dh_bn1536, sizeof(pk11_dh_bn1536));
++ pubTemplate[4].ulValueLen = sizeof(pk11_dh_bn1536);
++ }
++ pubTemplate[5].pValue = isc_mem_get(key->mctx,
++ sizeof(pk11_dh_bn2));
++ if (pubTemplate[5].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(pubTemplate[5].pValue, pk11_dh_bn2, sizeof(pk11_dh_bn2));
++ pubTemplate[5].ulValueLen = sizeof(pk11_dh_bn2);
++ } else {
++ PK11_RET(pkcs_C_GenerateKey,
++ (pk11_ctx->session, &mech,
++ dTemplate, (CK_ULONG) 5, &domainparams),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, domainparams,
++ pTemplate, (CK_ULONG) 2),
++ DST_R_CRYPTOFAILURE);
++ pTemplate[0].pValue = isc_mem_get(key->mctx,
++ pTemplate[0].ulValueLen);
++ if (pTemplate[0].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen);
++ pTemplate[1].pValue = isc_mem_get(key->mctx,
++ pTemplate[1].ulValueLen);
++ if (pTemplate[1].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, domainparams,
++ pTemplate, (CK_ULONG) 2),
++ DST_R_CRYPTOFAILURE);
++
++ pubTemplate[4].pValue = pTemplate[0].pValue;
++ pubTemplate[4].ulValueLen = pTemplate[0].ulValueLen;
++ pTemplate[0].pValue = NULL;
++ pubTemplate[5].pValue = pTemplate[1].pValue;
++ pubTemplate[5].ulValueLen = pTemplate[1].ulValueLen;
++ pTemplate[1].pValue = NULL;
++ }
++
++ mech.mechanism = CKM_DH_PKCS_KEY_PAIR_GEN;
++ PK11_RET(pkcs_C_GenerateKeyPair,
++ (pk11_ctx->session, &mech,
++ pubTemplate, (CK_ULONG) 6,
++ privTemplate, (CK_ULONG) 7,
++ &pub, &priv),
++ DST_R_CRYPTOFAILURE);
++
++ dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
++ if (dh == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dh, 0, sizeof(*dh));
++ key->keydata.pkey = dh;
++ dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
++ if (dh->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dh->repr, 0, sizeof(*attr) * 4);
++ dh->attrcnt = 4;
++
++ attr = dh->repr;
++ attr[0].type = CKA_PRIME;
++ attr[0].pValue = pubTemplate[4].pValue;
++ attr[0].ulValueLen = pubTemplate[4].ulValueLen;
++ pubTemplate[4].pValue = NULL;
++
++ attr[1].type = CKA_BASE;
++ attr[1].pValue = pubTemplate[5].pValue;
++ attr[1].ulValueLen = pubTemplate[5].ulValueLen;
++ pubTemplate[5].pValue =NULL;
++
++ attr += 2;
++ attr->type = CKA_VALUE;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++
++ attr++;
++ attr->type = CKA_VALUE;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->type = CKA_VALUE2;
++
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11dh_destroy(key);
++ if (priv != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ if (pub != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ if (domainparams != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, domainparams);
++
++ if (pubTemplate[4].pValue != NULL) {
++ memset(pubTemplate[4].pValue, 0, pubTemplate[4].ulValueLen);
++ isc_mem_put(key->mctx,
++ pubTemplate[4].pValue,
++ pubTemplate[4].ulValueLen);
++ }
++ if (pubTemplate[5].pValue != NULL) {
++ memset(pubTemplate[5].pValue, 0, pubTemplate[5].ulValueLen);
++ isc_mem_put(key->mctx,
++ pubTemplate[5].pValue,
++ pubTemplate[5].ulValueLen);
++ }
++ if (pTemplate[0].pValue != NULL) {
++ memset(pTemplate[0].pValue, 0, pTemplate[0].ulValueLen);
++ isc_mem_put(key->mctx,
++ pTemplate[0].pValue,
++ pTemplate[0].ulValueLen);
++ }
++ if (pTemplate[1].pValue != NULL) {
++ memset(pTemplate[1].pValue, 0, pTemplate[1].ulValueLen);
++ isc_mem_put(key->mctx,
++ pTemplate[1].pValue,
++ pTemplate[1].ulValueLen);
++ }
++
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11dh_isprivate(const dst_key_t *key) {
++ pk11_object_t *dh = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (dh == NULL)
++ return (ISC_FALSE);
++ attr = pk11_attribute_bytype(dh, CKA_VALUE2);
++ return (ISC_TF((attr != NULL) || dh->ontoken));
++}
++
++static void
++pkcs11dh_destroy(dst_key_t *key) {
++ pk11_object_t *dh = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (dh == NULL)
++ return;
++
++ INSIST((dh->object == CK_INVALID_HANDLE) || dh->ontoken);
++
++ for (attr = pk11_attribute_first(dh);
++ attr != NULL;
++ attr = pk11_attribute_next(dh, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ case CKA_VALUE2:
++ case CKA_PRIME:
++ case CKA_BASE:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (dh->repr != NULL) {
++ memset(dh->repr, 0, dh->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr));
++ }
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ key->keydata.pkey = NULL;
++}
++
++static void
++uint16_toregion(isc_uint16_t val, isc_region_t *region) {
++ *region->base++ = (val & 0xff00) >> 8;
++ *region->base++ = (val & 0x00ff);
++}
++
++static isc_uint16_t
++uint16_fromregion(isc_region_t *region) {
++ isc_uint16_t val;
++ unsigned char *cp = region->base;
++
++ val = ((unsigned int)(cp[0])) << 8;
++ val |= ((unsigned int)(cp[1]));
++
++ region->base += 2;
++ return (val);
++}
++
++static isc_result_t
++pkcs11dh_todns(const dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *dh;
++ CK_ATTRIBUTE *attr;
++ isc_region_t r;
++ isc_uint16_t dnslen, plen = 0, glen = 0, publen = 0;
++ CK_BYTE *prime = NULL, *base = NULL, *pub = NULL;
++
++ REQUIRE(key->keydata.pkey != NULL);
++
++ dh = key->keydata.pkey;
++
++ for (attr = pk11_attribute_first(dh);
++ attr != NULL;
++ attr = pk11_attribute_next(dh, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ pub = (CK_BYTE *) attr->pValue;
++ publen = (isc_uint16_t) attr->ulValueLen;
++ break;
++ case CKA_PRIME:
++ prime = (CK_BYTE *) attr->pValue;
++ plen = (isc_uint16_t) attr->ulValueLen;
++ break;
++ case CKA_BASE:
++ base = (CK_BYTE *) attr->pValue;
++ glen = (isc_uint16_t) attr->ulValueLen;
++ break;
++ }
++ REQUIRE((prime != NULL) && (base != NULL) && (pub != NULL));
++
++ isc_buffer_availableregion(data, &r);
++
++ if ((glen == 1) && (memcmp(pk11_dh_bn2, base, glen) == 0) &&
++ (((plen == sizeof(pk11_dh_bn768)) &&
++ (memcmp(pk11_dh_bn768, prime, plen) == 0)) ||
++ ((plen == sizeof(pk11_dh_bn1024)) &&
++ (memcmp(pk11_dh_bn1024, prime, plen) == 0)) ||
++ ((plen == sizeof(pk11_dh_bn1536)) &&
++ (memcmp(pk11_dh_bn1536, prime, plen) == 0)))) {
++ plen = 1;
++ glen = 0;
++ }
++
++ dnslen = plen + glen + publen + 6;
++ if (r.length < (unsigned int) dnslen)
++ return (ISC_R_NOSPACE);
++
++ uint16_toregion(plen, &r);
++ if (plen == 1) {
++ if (memcmp(pk11_dh_bn768, prime, sizeof(pk11_dh_bn768)) == 0)
++ *r.base = 1;
++ else if (memcmp(pk11_dh_bn1024, prime,
++ sizeof(pk11_dh_bn1024)) == 0)
++ *r.base = 2;
++ else
++ *r.base = 3;
++ }
++ else
++ memcpy(r.base, prime, plen);
++ r.base += plen;
++
++ uint16_toregion(glen, &r);
++ if (glen > 0)
++ memcpy(r.base, base, glen);
++ r.base += glen;
++
++ uint16_toregion(publen, &r);
++ memcpy(r.base, pub, publen);
++ r.base += publen;
++
++ isc_buffer_add(data, dnslen);
++
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++pkcs11dh_fromdns(dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *dh;
++ isc_region_t r;
++ isc_uint16_t plen, glen, plen_, glen_, publen;
++ CK_BYTE *prime = NULL, *base = NULL, *pub = NULL;
++ CK_ATTRIBUTE *attr;
++ int special = 0;
++
++ isc_buffer_remainingregion(data, &r);
++ if (r.length == 0)
++ return (ISC_R_SUCCESS);
++
++ dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
++ if (dh == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(dh, 0, sizeof(*dh));
++
++ /*
++ * Read the prime length. 1 & 2 are table entries, > 16 means a
++ * prime follows, otherwise an error.
++ */
++ if (r.length < 2) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ plen = uint16_fromregion(&r);
++ if (plen < 16 && plen != 1 && plen != 2) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ if (r.length < plen) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ plen_ = plen;
++ if (plen == 1 || plen == 2) {
++ if (plen == 1)
++ special = *r.base++;
++ else
++ special = uint16_fromregion(&r);
++ switch (special) {
++ case 1:
++ prime = pk11_dh_bn768;
++ plen_ = sizeof(pk11_dh_bn768);
++ break;
++ case 2:
++ prime = pk11_dh_bn1024;
++ plen_ = sizeof(pk11_dh_bn1024);
++ break;
++ case 3:
++ prime = pk11_dh_bn1536;
++ plen_ = sizeof(pk11_dh_bn1536);
++ break;
++ default:
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ }
++ else {
++ prime = r.base;
++ r.base += plen;
++ }
++
++ /*
++ * Read the generator length. This should be 0 if the prime was
++ * special, but it might not be. If it's 0 and the prime is not
++ * special, we have a problem.
++ */
++ if (r.length < 2) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ glen = uint16_fromregion(&r);
++ if (r.length < glen) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ glen_ = glen;
++ if (special != 0) {
++ if (glen == 0) {
++ base = pk11_dh_bn2;
++ glen_ = sizeof(pk11_dh_bn2);
++ }
++ else {
++ base = r.base;
++ if (memcmp(base, pk11_dh_bn2, glen) == 0) {
++ base = pk11_dh_bn2;
++ glen_ = sizeof(pk11_dh_bn2);
++ }
++ else {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ }
++ }
++ else {
++ if (glen == 0) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ base = r.base;
++ }
++ r.base += glen;
++
++ if (r.length < 2) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ publen = uint16_fromregion(&r);
++ if (r.length < publen) {
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ pub = r.base;
++ r.base += publen;
++
++ key->key_size = pk11_numbits(prime, plen_);
++
++ dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
++ if (dh->repr == NULL)
++ goto nomemory;
++ memset(dh->repr, 0, sizeof(*attr) * 3);
++ dh->attrcnt = 3;
++
++ attr = dh->repr;
++ attr[0].type = CKA_PRIME;
++ attr[0].pValue = isc_mem_get(key->mctx, plen_);
++ if (attr[0].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[0].pValue, prime, plen_);
++ attr[0].ulValueLen = (CK_ULONG) plen_;
++
++ attr[1].type = CKA_BASE;
++ attr[1].pValue = isc_mem_get(key->mctx, glen_);
++ if (attr[1].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[1].pValue, base, glen_);
++ attr[1].ulValueLen = (CK_ULONG) glen_;
++
++ attr[2].type = CKA_VALUE;
++ attr[2].pValue = isc_mem_get(key->mctx, publen);
++ if (attr[2].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[2].pValue, pub, publen);
++ attr[2].ulValueLen = (CK_ULONG) publen;
++
++ isc_buffer_forward(data, plen + glen + publen + 6);
++
++ key->keydata.pkey = dh;
++
++ return (ISC_R_SUCCESS);
++
++ nomemory:
++ for (attr = pk11_attribute_first(dh);
++ attr != NULL;
++ attr = pk11_attribute_next(dh, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ case CKA_PRIME:
++ case CKA_BASE:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (dh->repr != NULL) {
++ memset(dh->repr, 0, dh->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx, dh->repr, dh->attrcnt * sizeof(*attr));
++ }
++ memset(dh, 0, sizeof(*dh));
++ isc_mem_put(key->mctx, dh, sizeof(*dh));
++ return (ISC_R_NOMEMORY);
++}
++
++static isc_result_t
++pkcs11dh_tofile(const dst_key_t *key, const char *directory) {
++ int i;
++ pk11_object_t *dh;
++ CK_ATTRIBUTE *attr;
++ CK_ATTRIBUTE *prime = NULL, *base = NULL, *pub = NULL, *prv = NULL;
++ dst_private_t priv;
++ unsigned char *bufs[4];
++ isc_result_t result;
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external)
++ return (DST_R_EXTERNALKEY);
++
++ dh = key->keydata.pkey;
++
++ for (attr = pk11_attribute_first(dh);
++ attr != NULL;
++ attr = pk11_attribute_next(dh, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ pub = attr;
++ break;
++ case CKA_VALUE2:
++ prv = attr;
++ break;
++ case CKA_PRIME:
++ prime = attr;
++ break;
++ case CKA_BASE:
++ base = attr;
++ break;
++ }
++ if ((prime == NULL) || (base == NULL) ||
++ (pub == NULL) || (prv == NULL))
++ return (DST_R_NULLKEY);
++
++ memset(bufs, 0, sizeof(bufs));
++ for (i = 0; i < 4; i++) {
++ bufs[i] = isc_mem_get(key->mctx, prime->ulValueLen);
++ if (bufs[i] == NULL) {
++ result = ISC_R_NOMEMORY;
++ goto fail;
++ }
++ memset(bufs[i], 0, prime->ulValueLen);
++ }
++
++ i = 0;
++
++ priv.elements[i].tag = TAG_DH_PRIME;
++ priv.elements[i].length = (unsigned short) prime->ulValueLen;
++ memcpy(bufs[i], prime->pValue, prime->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++
++ priv.elements[i].tag = TAG_DH_GENERATOR;
++ priv.elements[i].length = (unsigned short) base->ulValueLen;
++ memcpy(bufs[i], base->pValue, base->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++
++ priv.elements[i].tag = TAG_DH_PRIVATE;
++ priv.elements[i].length = (unsigned short) prv->ulValueLen;
++ memcpy(bufs[i], prv->pValue, prv->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++
++ priv.elements[i].tag = TAG_DH_PUBLIC;
++ priv.elements[i].length = (unsigned short) pub->ulValueLen;
++ memcpy(bufs[i], pub->pValue, pub->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++
++ priv.nelements = i;
++ result = dst__privstruct_writefile(key, &priv, directory);
++ fail:
++ for (i = 0; i < 4; i++) {
++ if (bufs[i] == NULL)
++ break;
++ memset(bufs[i], 0, prime->ulValueLen);
++ isc_mem_put(key->mctx, bufs[i], prime->ulValueLen);
++ }
++ return (result);
++}
++
++static isc_result_t
++pkcs11dh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
++ dst_private_t priv;
++ isc_result_t ret;
++ int i;
++ pk11_object_t *dh = NULL;
++ CK_ATTRIBUTE *attr;
++ isc_mem_t *mctx;
++
++ UNUSED(pub);
++ mctx = key->mctx;
++
++ /* read private key file */
++ ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ if (key->external)
++ DST_RET(DST_R_EXTERNALKEY);
++
++ dh = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dh));
++ if (dh == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dh, 0, sizeof(*dh));
++ key->keydata.pkey = dh;
++ dh->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
++ if (dh->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dh->repr, 0, sizeof(*attr) * 4);
++ dh->attrcnt = 4;
++ attr = dh->repr;
++ attr[0].type = CKA_PRIME;
++ attr[1].type = CKA_BASE;
++ attr[2].type = CKA_VALUE;
++ attr[3].type = CKA_VALUE2;
++
++ for (i = 0; i < priv.nelements; i++) {
++ CK_BYTE *bn;
++
++ bn = isc_mem_get(key->mctx, priv.elements[i].length);
++ if (bn == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(bn, priv.elements[i].data, priv.elements[i].length);
++
++ switch (priv.elements[i].tag) {
++ case TAG_DH_PRIME:
++ attr = pk11_attribute_bytype(dh, CKA_PRIME);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DH_GENERATOR:
++ attr = pk11_attribute_bytype(dh, CKA_BASE);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DH_PRIVATE:
++ attr = pk11_attribute_bytype(dh, CKA_VALUE2);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DH_PUBLIC:
++ attr = pk11_attribute_bytype(dh, CKA_VALUE);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ }
++ }
++ dst__privstruct_free(&priv, mctx);
++
++ attr = pk11_attribute_bytype(dh, CKA_PRIME);
++ INSIST(attr != NULL);
++ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11dh_destroy(key);
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++}
++
++static dst_func_t pkcs11dh_functions = {
++ NULL, /*%< createctx */
++ NULL, /*%< createctx2 */
++ NULL, /*%< destroyctx */
++ NULL, /*%< adddata */
++ NULL, /*%< sign */
++ NULL, /*%< verify */
++ NULL, /*%< verify2 */
++ pkcs11dh_computesecret,
++ pkcs11dh_compare,
++ pkcs11dh_paramcompare,
++ pkcs11dh_generate,
++ pkcs11dh_isprivate,
++ pkcs11dh_destroy,
++ pkcs11dh_todns,
++ pkcs11dh_fromdns,
++ pkcs11dh_tofile,
++ pkcs11dh_parse,
++ NULL, /*%< cleanup */
++ NULL, /*%< fromlabel */
++ NULL, /*%< dump */
++ NULL, /*%< restore */
++};
++
++isc_result_t
++dst__pkcs11dh_init(dst_func_t **funcp) {
++ REQUIRE(funcp != NULL);
++ if (*funcp == NULL)
++ *funcp = &pkcs11dh_functions;
++ return (ISC_R_SUCCESS);
++}
++
++#else /* PKCS11CRYPTO */
++
++#include <isc/util.h>
++
++EMPTY_TRANSLATION_UNIT
++
++#endif /* PKCS11CRYPTO */
++/*! \file */
+diff -up bind-9.9.6/lib/dns/pkcs11dsa_link.c.native_pkcs11 bind-9.9.6/lib/dns/pkcs11dsa_link.c
+--- bind-9.9.6/lib/dns/pkcs11dsa_link.c.native_pkcs11 2014-10-09 13:30:47.824302920 +0200
++++ bind-9.9.6/lib/dns/pkcs11dsa_link.c 2014-10-09 13:30:47.824302920 +0200
+@@ -0,0 +1,1130 @@
++/*
++ * Portions Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ *
++ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#ifdef PKCS11CRYPTO
++
++#include <config.h>
++
++#include <string.h>
++
++#include <isc/entropy.h>
++#include <isc/mem.h>
++#include <isc/sha1.h>
++#include <isc/util.h>
++
++#include <dst/result.h>
++
++#include "dst_internal.h"
++#include "dst_parse.h"
++#include "dst_pkcs11.h"
++
++#include <pk11/internal.h>
++
++/*
++ * FIPS 186-2 DSA keys:
++ * mechanisms:
++ * CKM_DSA_SHA1,
++ * CKM_DSA_KEY_PAIR_GEN,
++ * CKM_DSA_PARAMETER_GEN
++ * domain parameters:
++ * object class CKO_DOMAIN_PARAMETERS
++ * key type CKK_DSA
++ * attribute CKA_PRIME (prime p)
++ * attribute CKA_SUBPRIME (subprime q)
++ * attribute CKA_BASE (base g)
++ * optional attribute CKA_PRIME_BITS (p length in bits)
++ * public keys:
++ * object class CKO_PUBLIC_KEY
++ * key type CKK_DSA
++ * attribute CKA_PRIME (prime p)
++ * attribute CKA_SUBPRIME (subprime q)
++ * attribute CKA_BASE (base g)
++ * attribute CKA_VALUE (public value y)
++ * private keys:
++ * object class CKO_PRIVATE_KEY
++ * key type CKK_DSA
++ * attribute CKA_PRIME (prime p)
++ * attribute CKA_SUBPRIME (subprime q)
++ * attribute CKA_BASE (base g)
++ * attribute CKA_VALUE (private value x)
++ * reuse CKA_PRIVATE_EXPONENT for key pair private value
++ */
++
++#define CKA_VALUE2 CKA_PRIVATE_EXPONENT
++
++#define DST_RET(a) {ret = a; goto err;}
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++static isc_result_t pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data);
++static void pkcs11dsa_destroy(dst_key_t *key);
++
++static isc_result_t
++pkcs11dsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_DSA;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_PRIME, NULL, 0 },
++ { CKA_SUBPRIME, NULL, 0 },
++ { CKA_BASE, NULL, 0 },
++ { CKA_VALUE, NULL, 0 }
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *dsa;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_DSA));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ dsa = key->keydata.pkey;
++ if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) {
++ pk11_ctx->ontoken = dsa->ontoken;
++ pk11_ctx->object = dsa->object;
++ goto token_key;
++ }
++
++ for (attr = pk11_attribute_first(dsa);
++ attr != NULL;
++ attr = pk11_attribute_next(dsa, attr))
++ switch (attr->type) {
++ case CKA_PRIME:
++ INSIST(keyTemplate[6].type == attr->type);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_SUBPRIME:
++ INSIST(keyTemplate[7].type == attr->type);
++ keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[7].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[7].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[7].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_BASE:
++ INSIST(keyTemplate[8].type == attr->type);
++ keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[8].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[8].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[8].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_VALUE2:
++ INSIST(keyTemplate[9].type == CKA_VALUE);
++ keyTemplate[9].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[9].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[9].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[9].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 10,
++ &pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ token_key:
++
++ PK11_RET(pkcs_C_SignInit,
++ (pk11_ctx->session, &mech, pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++
++ for (i = 6; i <= 9; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object);
++ for (i = 6; i <= 9; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11dsa_createctx_verify(dst_key_t *key, dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_DSA;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_PRIME, NULL, 0 },
++ { CKA_SUBPRIME, NULL, 0 },
++ { CKA_BASE, NULL, 0 },
++ { CKA_VALUE, NULL, 0 }
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *dsa;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_DSA));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ dsa = key->keydata.pkey;
++ if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) {
++ pk11_ctx->ontoken = dsa->ontoken;
++ pk11_ctx->object = dsa->object;
++ goto token_key;
++ }
++
++ for (attr = pk11_attribute_first(dsa);
++ attr != NULL;
++ attr = pk11_attribute_next(dsa, attr))
++ switch (attr->type) {
++ case CKA_PRIME:
++ INSIST(keyTemplate[5].type == attr->type);
++ keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[5].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[5].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[5].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_SUBPRIME:
++ INSIST(keyTemplate[6].type == attr->type);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_BASE:
++ INSIST(keyTemplate[7].type == attr->type);
++ keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[7].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[7].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[7].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_VALUE:
++ INSIST(keyTemplate[8].type == attr->type);
++ keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[8].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[8].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[8].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 9,
++ &pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ token_key:
++
++ PK11_RET(pkcs_C_VerifyInit,
++ (pk11_ctx->session, &mech, pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++
++ for (i = 5; i <= 8; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object);
++ for (i = 5; i <= 8; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11dsa_createctx(dst_key_t *key, dst_context_t *dctx) {
++ if (dctx->use == DO_SIGN)
++ return (pkcs11dsa_createctx_sign(key, dctx));
++ else
++ return (pkcs11dsa_createctx_verify(key, dctx));
++}
++
++static void
++pkcs11dsa_destroyctx(dst_context_t *dctx) {
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++
++ if (pk11_ctx != NULL) {
++ if (!pk11_ctx->ontoken &&
++ (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session,
++ pk11_ctx->object);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ dctx->ctxdata.pk11_ctx = NULL;
++ }
++}
++
++static isc_result_t
++pkcs11dsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ if (dctx->use == DO_SIGN)
++ PK11_CALL(pkcs_C_SignUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++ else
++ PK11_CALL(pkcs_C_VerifyUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++ return (ret);
++}
++
++static isc_result_t
++pkcs11dsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
++ CK_RV rv;
++ CK_ULONG siglen = ISC_SHA1_DIGESTLENGTH * 2;
++ isc_region_t r;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ isc_buffer_availableregion(sig, &r);
++ if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
++ return (ISC_R_NOSPACE);
++
++ PK11_RET(pkcs_C_SignFinal,
++ (pk11_ctx->session, (CK_BYTE_PTR) r.base + 1, &siglen),
++ DST_R_SIGNFAILURE);
++ if (siglen != ISC_SHA1_DIGESTLENGTH * 2)
++ return (DST_R_SIGNFAILURE);
++
++ *r.base = (dctx->key->key_size - 512)/64;
++ isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
++
++ err:
++ return (ret);
++}
++
++static isc_result_t
++pkcs11dsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ PK11_CALL(pkcs_C_VerifyFinal,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) sig->base + 1,
++ (CK_ULONG) sig->length - 1),
++ DST_R_VERIFYFAILURE);
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11dsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
++ pk11_object_t *dsa1, *dsa2;
++ CK_ATTRIBUTE *attr1, *attr2;
++
++ dsa1 = key1->keydata.pkey;
++ dsa2 = key2->keydata.pkey;
++
++ if ((dsa1 == NULL) && (dsa2 == NULL))
++ return (ISC_TRUE);
++ else if ((dsa1 == NULL) || (dsa2 == NULL))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dsa1, CKA_PRIME);
++ attr2 = pk11_attribute_bytype(dsa2, CKA_PRIME);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dsa1, CKA_SUBPRIME);
++ attr2 = pk11_attribute_bytype(dsa2, CKA_SUBPRIME);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dsa1, CKA_BASE);
++ attr2 = pk11_attribute_bytype(dsa2, CKA_BASE);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE);
++ attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE2);
++ attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE2);
++ if (((attr1 != NULL) || (attr2 != NULL)) &&
++ ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
++ return (ISC_FALSE);
++
++ if (!dsa1->ontoken && !dsa2->ontoken)
++ return (ISC_TRUE);
++ else if (dsa1->ontoken || dsa2->ontoken ||
++ (dsa1->object != dsa2->object))
++ return (ISC_FALSE);
++
++ return (ISC_TRUE);
++}
++
++static isc_result_t
++pkcs11dsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_DSA_PARAMETER_GEN, NULL, 0 };
++ CK_OBJECT_HANDLE dp = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS dpClass = CKO_DOMAIN_PARAMETERS;
++ CK_KEY_TYPE keyType = CKK_DSA;
++ CK_ULONG bits = 0;
++ CK_ATTRIBUTE dpTemplate[] =
++ {
++ { CKA_CLASS, &dpClass, (CK_ULONG) sizeof(dpClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) },
++ };
++ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
++ CK_ATTRIBUTE pubTemplate[] =
++ {
++ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_PRIME, NULL, 0 },
++ { CKA_SUBPRIME, NULL, 0 },
++ { CKA_BASE, NULL, 0 }
++ };
++ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
++ CK_ATTRIBUTE privTemplate[] =
++ {
++ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *dsa;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ UNUSED(unused);
++ UNUSED(callback);
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_DSA));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ bits = key->key_size;
++ PK11_RET(pkcs_C_GenerateKey,
++ (pk11_ctx->session, &mech, dpTemplate, (CK_ULONG) 5, &dp),
++ DST_R_CRYPTOFAILURE);
++
++ dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
++ if (dsa == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dsa, 0, sizeof(*dsa));
++ key->keydata.pkey = dsa;
++ dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5);
++ if (dsa->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dsa->repr, 0, sizeof(*attr) * 5);
++ dsa->attrcnt = 5;
++
++ attr = dsa->repr;
++ attr[0].type = CKA_PRIME;
++ attr[1].type = CKA_SUBPRIME;
++ attr[2].type = CKA_BASE;
++ attr[3].type = CKA_VALUE;
++ attr[4].type = CKA_VALUE2;
++
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, dp, attr, 3),
++ DST_R_CRYPTOFAILURE);
++
++ for (i = 0; i <= 2; i++) {
++ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
++ if (attr[i].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr[i].pValue, 0, attr[i].ulValueLen);
++ }
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, dp, attr, 3),
++ DST_R_CRYPTOFAILURE);
++ pubTemplate[5].pValue = attr[0].pValue;
++ pubTemplate[5].ulValueLen = attr[0].ulValueLen;
++ pubTemplate[6].pValue = attr[1].pValue;
++ pubTemplate[6].ulValueLen = attr[1].ulValueLen;
++ pubTemplate[7].pValue = attr[2].pValue;
++ pubTemplate[7].ulValueLen = attr[2].ulValueLen;
++
++ mech.mechanism = CKM_DSA_KEY_PAIR_GEN;
++ PK11_RET(pkcs_C_GenerateKeyPair,
++ (pk11_ctx->session, &mech,
++ pubTemplate, (CK_ULONG) 8,
++ privTemplate, (CK_ULONG) 7,
++ &pub, &priv),
++ DST_R_CRYPTOFAILURE);
++
++ attr = dsa->repr;
++ attr += 3;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++
++ attr++;
++ attr->type = CKA_VALUE;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->type = CKA_VALUE2;
++
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, dp);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11dsa_destroy(key);
++ if (priv != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ if (pub != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ if (dp != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, dp);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11dsa_isprivate(const dst_key_t *key) {
++ pk11_object_t *dsa = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (dsa == NULL)
++ return (ISC_FALSE);
++ attr = pk11_attribute_bytype(dsa, CKA_VALUE2);
++ return (ISC_TF((attr != NULL) || dsa->ontoken));
++}
++
++static void
++pkcs11dsa_destroy(dst_key_t *key) {
++ pk11_object_t *dsa = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (dsa == NULL)
++ return;
++
++ INSIST((dsa->object == CK_INVALID_HANDLE) || dsa->ontoken);
++
++ for (attr = pk11_attribute_first(dsa);
++ attr != NULL;
++ attr = pk11_attribute_next(dsa, attr))
++ switch (attr->type) {
++ case CKA_PRIME:
++ case CKA_SUBPRIME:
++ case CKA_BASE:
++ case CKA_VALUE:
++ case CKA_VALUE2:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (dsa->repr != NULL) {
++ memset(dsa->repr, 0, dsa->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ dsa->repr,
++ dsa->attrcnt * sizeof(*attr));
++ }
++ memset(dsa, 0, sizeof(*dsa));
++ isc_mem_put(key->mctx, dsa, sizeof(*dsa));
++ key->keydata.pkey = NULL;
++}
++
++
++static isc_result_t
++pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *dsa;
++ CK_ATTRIBUTE *attr;
++ isc_region_t r;
++ int dnslen;
++ unsigned int t, p_bytes;
++ CK_ATTRIBUTE *prime = NULL, *subprime = NULL;
++ CK_ATTRIBUTE *base = NULL, *pub_key = NULL;
++ CK_BYTE *cp;
++
++ REQUIRE(key->keydata.pkey != NULL);
++
++ dsa = key->keydata.pkey;
++
++ for (attr = pk11_attribute_first(dsa);
++ attr != NULL;
++ attr = pk11_attribute_next(dsa, attr))
++ switch (attr->type) {
++ case CKA_PRIME:
++ prime = attr;
++ break;
++ case CKA_SUBPRIME:
++ subprime = attr;
++ break;
++ case CKA_BASE:
++ base = attr;
++ break;
++ case CKA_VALUE:
++ pub_key = attr;
++ break;
++ }
++ REQUIRE((prime != NULL) && (subprime != NULL) &&
++ (base != NULL) && (pub_key != NULL));
++
++ isc_buffer_availableregion(data, &r);
++
++ t = (prime->ulValueLen - 64) / 8;
++ if (t > 8)
++ return (DST_R_INVALIDPUBLICKEY);
++ p_bytes = 64 + 8 * t;
++
++ dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
++ if (r.length < (unsigned int) dnslen)
++ return (ISC_R_NOSPACE);
++
++ memset(r.base, 0, dnslen);
++ *r.base++ = t;
++ cp = (CK_BYTE *) subprime->pValue;
++ memcpy(r.base + ISC_SHA1_DIGESTLENGTH - subprime->ulValueLen,
++ cp, subprime->ulValueLen);
++ r.base += ISC_SHA1_DIGESTLENGTH;
++ cp = (CK_BYTE *) prime->pValue;
++ memcpy(r.base + key->key_size/8 - prime->ulValueLen,
++ cp, prime->ulValueLen);
++ r.base += p_bytes;
++ cp = (CK_BYTE *) base->pValue;
++ memcpy(r.base + key->key_size/8 - base->ulValueLen,
++ cp, base->ulValueLen);
++ r.base += p_bytes;
++ cp = (CK_BYTE *) pub_key->pValue;
++ memcpy(r.base + key->key_size/8 - pub_key->ulValueLen,
++ cp, pub_key->ulValueLen);
++ r.base += p_bytes;
++
++ isc_buffer_add(data, dnslen);
++
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++pkcs11dsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *dsa;
++ isc_region_t r;
++ unsigned int t, p_bytes;
++ CK_BYTE *prime, *subprime, *base, *pub_key;
++ CK_ATTRIBUTE *attr;
++
++ isc_buffer_remainingregion(data, &r);
++ if (r.length == 0)
++ return (ISC_R_SUCCESS);
++
++ dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
++ if (dsa == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(dsa, 0, sizeof(*dsa));
++
++ t = (unsigned int) *r.base++;
++ if (t > 8) {
++ memset(dsa, 0, sizeof(*dsa));
++ isc_mem_put(key->mctx, dsa, sizeof(*dsa));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ p_bytes = 64 + 8 * t;
++
++ if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
++ memset(dsa, 0, sizeof(*dsa));
++ isc_mem_put(key->mctx, dsa, sizeof(*dsa));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++
++ subprime = r.base;
++ r.base += ISC_SHA1_DIGESTLENGTH;
++
++ prime = r.base;
++ r.base += p_bytes;
++
++ base = r.base;
++ r.base += p_bytes;
++
++ pub_key = r.base;
++ r.base += p_bytes;
++
++ key->key_size = p_bytes * 8;
++
++ isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
++
++ dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
++ if (dsa->repr == NULL)
++ goto nomemory;
++ memset(dsa->repr, 0, sizeof(*attr) * 4);
++ dsa->attrcnt = 4;
++
++ attr = dsa->repr;
++ attr[0].type = CKA_PRIME;
++ attr[0].pValue = isc_mem_get(key->mctx, p_bytes);
++ if (attr[0].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[0].pValue, prime, p_bytes);
++ attr[0].ulValueLen = p_bytes;
++
++ attr[1].type = CKA_SUBPRIME;
++ attr[1].pValue = isc_mem_get(key->mctx, ISC_SHA1_DIGESTLENGTH);
++ if (attr[1].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[1].pValue, subprime, ISC_SHA1_DIGESTLENGTH);
++ attr[1].ulValueLen = ISC_SHA1_DIGESTLENGTH;
++
++ attr[2].type = CKA_BASE;
++ attr[2].pValue = isc_mem_get(key->mctx, p_bytes);
++ if (attr[2].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[2].pValue, base, p_bytes);
++ attr[2].ulValueLen = p_bytes;
++
++ attr[3].type = CKA_VALUE;
++ attr[3].pValue = isc_mem_get(key->mctx, p_bytes);
++ if (attr[3].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[3].pValue, pub_key, p_bytes);
++ attr[3].ulValueLen = p_bytes;
++
++ key->keydata.pkey = dsa;
++
++ return (ISC_R_SUCCESS);
++
++ nomemory:
++ for (attr = pk11_attribute_first(dsa);
++ attr != NULL;
++ attr = pk11_attribute_next(dsa, attr))
++ switch (attr->type) {
++ case CKA_PRIME:
++ case CKA_SUBPRIME:
++ case CKA_BASE:
++ case CKA_VALUE:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (dsa->repr != NULL) {
++ memset(dsa->repr, 0, dsa->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ dsa->repr,
++ dsa->attrcnt * sizeof(*attr));
++ }
++ memset(dsa, 0, sizeof(*dsa));
++ isc_mem_put(key->mctx, dsa, sizeof(*dsa));
++ return (ISC_R_NOMEMORY);
++}
++
++static isc_result_t
++pkcs11dsa_tofile(const dst_key_t *key, const char *directory) {
++ int cnt = 0;
++ pk11_object_t *dsa;
++ CK_ATTRIBUTE *attr;
++ CK_ATTRIBUTE *prime = NULL, *subprime = NULL, *base = NULL;
++ CK_ATTRIBUTE *pub_key = NULL, *priv_key = NULL;
++ dst_private_t priv;
++ unsigned char bufs[5][128];
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external) {
++ priv.nelements = 0;
++ return (dst__privstruct_writefile(key, &priv, directory));
++ }
++
++ dsa = key->keydata.pkey;
++
++ for (attr = pk11_attribute_first(dsa);
++ attr != NULL;
++ attr = pk11_attribute_next(dsa, attr))
++ switch (attr->type) {
++ case CKA_PRIME:
++ prime = attr;
++ break;
++ case CKA_SUBPRIME:
++ subprime = attr;
++ break;
++ case CKA_BASE:
++ base = attr;
++ break;
++ case CKA_VALUE:
++ pub_key = attr;
++ break;
++ case CKA_VALUE2:
++ priv_key = attr;
++ break;
++ }
++ if ((prime == NULL) || (subprime == NULL) || (base == NULL) ||
++ (pub_key == NULL) || (priv_key ==NULL))
++ return (DST_R_NULLKEY);
++
++ priv.elements[cnt].tag = TAG_DSA_PRIME;
++ priv.elements[cnt].length = (unsigned short) prime->ulValueLen;
++ memcpy(bufs[cnt], prime->pValue, prime->ulValueLen);
++ priv.elements[cnt].data = bufs[cnt];
++ cnt++;
++
++ priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
++ priv.elements[cnt].length = (unsigned short) subprime->ulValueLen;
++ memcpy(bufs[cnt], subprime->pValue, subprime->ulValueLen);
++ priv.elements[cnt].data = bufs[cnt];
++ cnt++;
++
++ priv.elements[cnt].tag = TAG_DSA_BASE;
++ priv.elements[cnt].length = (unsigned short) base->ulValueLen;
++ memcpy(bufs[cnt], base->pValue, base->ulValueLen);
++ priv.elements[cnt].data = bufs[cnt];
++ cnt++;
++
++ priv.elements[cnt].tag = TAG_DSA_PRIVATE;
++ priv.elements[cnt].length = (unsigned short) priv_key->ulValueLen;
++ memcpy(bufs[cnt], priv_key->pValue, priv_key->ulValueLen);
++ priv.elements[cnt].data = bufs[cnt];
++ cnt++;
++
++ priv.elements[cnt].tag = TAG_DSA_PUBLIC;
++ priv.elements[cnt].length = (unsigned short) pub_key->ulValueLen;
++ memcpy(bufs[cnt], pub_key->pValue, pub_key->ulValueLen);
++ priv.elements[cnt].data = bufs[cnt];
++ cnt++;
++
++ priv.nelements = cnt;
++ return (dst__privstruct_writefile(key, &priv, directory));
++}
++
++static isc_result_t
++pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
++ dst_private_t priv;
++ isc_result_t ret;
++ int i;
++ pk11_object_t *dsa = NULL;
++ CK_ATTRIBUTE *attr;
++ isc_mem_t *mctx = key->mctx;
++
++ /* read private key file */
++ ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ if (key->external) {
++ if (priv.nelements != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ if (pub == NULL)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ key->keydata.pkey = pub->keydata.pkey;
++ pub->keydata.pkey = NULL;
++ key->key_size = pub->key_size;
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++ }
++
++ dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
++ if (dsa == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dsa, 0, sizeof(*dsa));
++ key->keydata.pkey = dsa;
++
++ dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5);
++ if (dsa->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(dsa->repr, 0, sizeof(*attr) * 5);
++ dsa->attrcnt = 5;
++ attr = dsa->repr;
++ attr[0].type = CKA_PRIME;
++ attr[1].type = CKA_SUBPRIME;
++ attr[2].type = CKA_BASE;
++ attr[3].type = CKA_VALUE;
++ attr[4].type = CKA_VALUE2;
++
++ for (i = 0; i < priv.nelements; i++) {
++ CK_BYTE *bn;
++
++ bn = isc_mem_get(key->mctx, priv.elements[i].length);
++ if (bn == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(bn,
++ priv.elements[i].data,
++ priv.elements[i].length);
++
++ switch (priv.elements[i].tag) {
++ case TAG_DSA_PRIME:
++ attr = pk11_attribute_bytype(dsa, CKA_PRIME);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DSA_SUBPRIME:
++ attr = pk11_attribute_bytype(dsa,
++ CKA_SUBPRIME);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DSA_BASE:
++ attr = pk11_attribute_bytype(dsa, CKA_BASE);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DSA_PRIVATE:
++ attr = pk11_attribute_bytype(dsa, CKA_VALUE2);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_DSA_PUBLIC:
++ attr = pk11_attribute_bytype(dsa, CKA_VALUE);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ }
++ }
++ dst__privstruct_free(&priv, mctx);
++
++ attr = pk11_attribute_bytype(dsa, CKA_PRIME);
++ INSIST(attr != NULL);
++ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11dsa_destroy(key);
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++}
++
++static dst_func_t pkcs11dsa_functions = {
++ pkcs11dsa_createctx,
++ NULL, /*%< createctx2 */
++ pkcs11dsa_destroyctx,
++ pkcs11dsa_adddata,
++ pkcs11dsa_sign,
++ pkcs11dsa_verify,
++ NULL, /*%< verify2 */
++ NULL, /*%< computesecret */
++ pkcs11dsa_compare,
++ NULL, /*%< paramcompare */
++ pkcs11dsa_generate,
++ pkcs11dsa_isprivate,
++ pkcs11dsa_destroy,
++ pkcs11dsa_todns,
++ pkcs11dsa_fromdns,
++ pkcs11dsa_tofile,
++ pkcs11dsa_parse,
++ NULL, /*%< cleanup */
++ NULL, /*%< fromlabel */
++ NULL, /*%< dump */
++ NULL, /*%< restore */
++};
++
++isc_result_t
++dst__pkcs11dsa_init(dst_func_t **funcp) {
++ REQUIRE(funcp != NULL);
++ if (*funcp == NULL)
++ *funcp = &pkcs11dsa_functions;
++ return (ISC_R_SUCCESS);
++}
++
++#else /* PKCS11CRYPTO */
++
++#include <isc/util.h>
++
++EMPTY_TRANSLATION_UNIT
++
++#endif /* PKCS11CRYPTO */
++/*! \file */
+diff -up bind-9.9.6/lib/dns/pkcs11ecdsa_link.c.native_pkcs11 bind-9.9.6/lib/dns/pkcs11ecdsa_link.c
+--- bind-9.9.6/lib/dns/pkcs11ecdsa_link.c.native_pkcs11 2014-10-09 13:30:47.826302923 +0200
++++ bind-9.9.6/lib/dns/pkcs11ecdsa_link.c 2014-10-09 13:30:47.826302923 +0200
+@@ -0,0 +1,1189 @@
++/*
++ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#include <config.h>
++
++#if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_ECDSA)
++
++#include <isc/entropy.h>
++#include <isc/mem.h>
++#include <isc/sha2.h>
++#include <isc/string.h>
++#include <isc/util.h>
++
++#include <dns/keyvalues.h>
++#include <dst/result.h>
++
++#include "dst_internal.h"
++#include "dst_parse.h"
++#include "dst_pkcs11.h"
++
++#include <pk11/pk11.h>
++#include <pk11/internal.h>
++#define WANT_ECC_CURVES
++#include <pk11/constants.h>
++
++#include <pkcs11/pkcs11.h>
++
++/*
++ * FIPS 186-3 ECDSA keys:
++ * mechanisms:
++ * CKM_ECDSA,
++ * CKM_EC_KEY_PAIR_GEN
++ * domain parameters:
++ * CKA_EC_PARAMS (choice with OID namedCurve)
++ * public keys:
++ * object class CKO_PUBLIC_KEY
++ * key type CKK_EC
++ * attribute CKA_EC_PARAMS (choice with OID namedCurve)
++ * attribute CKA_EC_POINT (point Q)
++ * private keys:
++ * object class CKO_PRIVATE_KEY
++ * key type CKK_EC
++ * attribute CKA_EC_PARAMS (choice with OID namedCurve)
++ * attribute CKA_VALUE (big int d)
++ * point format: 0x04 (octet-string) <2*size+1> 0x4 (uncompressed) <x> <y>
++ */
++
++#define TAG_OCTECT_STRING 0x04
++#define UNCOMPRESSED 0x04
++
++#define DST_RET(a) {ret = a; goto err;}
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++static isc_result_t pkcs11ecdsa_todns(const dst_key_t *key,
++ isc_buffer_t *data);
++static void pkcs11ecdsa_destroy(dst_key_t *key);
++static isc_result_t pkcs11ecdsa_fetch(dst_key_t *key, const char *engine,
++ const char *label, dst_key_t *pub);
++
++static isc_result_t
++pkcs11ecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = {0, NULL, 0 };
++ CK_SLOT_ID slotid;
++ pk11_context_t *pk11_ctx;
++ pk11_object_t *ec = key->keydata.pkey;
++ isc_result_t ret;
++
++ UNUSED(key);
++ REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
++ dctx->key->key_alg == DST_ALG_ECDSA384);
++
++ if (dctx->key->key_alg == DST_ALG_ECDSA256)
++ mech.mechanism = CKM_SHA256;
++ else
++ mech.mechanism = CKM_SHA384;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ if (ec->ontoken && (dctx->use == DO_SIGN))
++ slotid = ec->slot;
++ else
++ slotid = pk11_get_best_token(OP_EC);
++ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE, ISC_FALSE,
++ NULL, slotid);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ PK11_RET(pkcs_C_DigestInit, (pk11_ctx->session, &mech), ISC_R_FAILURE);
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++ return (ISC_R_SUCCESS);
++
++ err:
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static void
++pkcs11ecdsa_destroyctx(dst_context_t *dctx) {
++ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA384_DIGESTLENGTH;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++
++ REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
++ dctx->key->key_alg == DST_ALG_ECDSA384);
++
++ if (pk11_ctx != NULL) {
++ (void) pkcs_C_DigestFinal(pk11_ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ dctx->ctxdata.pk11_ctx = NULL;
++ }
++}
++
++static isc_result_t
++pkcs11ecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
++ dctx->key->key_alg == DST_ALG_ECDSA384);
++
++ PK11_CALL(pkcs_C_DigestUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11ecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 };
++ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_EC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_EC_PARAMS, NULL, 0 },
++ { CKA_VALUE, NULL, 0 }
++ };
++ CK_ATTRIBUTE *attr;
++ CK_BYTE digest[ISC_SHA384_DIGESTLENGTH];
++ CK_ULONG dgstlen;
++ CK_ULONG siglen;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ dst_key_t *key = dctx->key;
++ pk11_object_t *ec = key->keydata.pkey;
++ isc_region_t r;
++ isc_result_t ret = ISC_R_SUCCESS;
++ unsigned int i;
++
++ REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
++ key->key_alg == DST_ALG_ECDSA384);
++ REQUIRE(ec != NULL);
++
++ if (key->key_alg == DST_ALG_ECDSA256) {
++ dgstlen = ISC_SHA256_DIGESTLENGTH;
++ siglen = DNS_SIG_ECDSA256SIZE;
++ } else {
++ siglen = DNS_SIG_ECDSA384SIZE;
++ dgstlen = ISC_SHA384_DIGESTLENGTH;
++ }
++
++ PK11_RET(pkcs_C_DigestFinal,
++ (pk11_ctx->session, digest, &dgstlen),
++ ISC_R_FAILURE);
++
++ isc_buffer_availableregion(sig, &r);
++ if (r.length < siglen)
++ DST_RET(ISC_R_NOSPACE);
++
++ if (ec->ontoken && (ec->object != CK_INVALID_HANDLE)) {
++ pk11_ctx->ontoken = ec->ontoken;
++ pk11_ctx->object = ec->object;
++ goto token_key;
++ }
++
++ for (attr = pk11_attribute_first(ec);
++ attr != NULL;
++ attr = pk11_attribute_next(ec, attr))
++ switch (attr->type) {
++ case CKA_EC_PARAMS:
++ INSIST(keyTemplate[5].type == attr->type);
++ keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[5].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[5].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[5].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_VALUE:
++ INSIST(keyTemplate[6].type == attr->type);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 7,
++ &hKey),
++ ISC_R_FAILURE);
++
++ token_key:
++
++ PK11_RET(pkcs_C_SignInit,
++ (pk11_ctx->session, &mech,
++ pk11_ctx->ontoken ? pk11_ctx->object : hKey),
++ ISC_R_FAILURE);
++
++ PK11_RET(pkcs_C_Sign,
++ (pk11_ctx->session,
++ digest, dgstlen,
++ (CK_BYTE_PTR) r.base, &siglen),
++ DST_R_SIGNFAILURE);
++
++ isc_buffer_add(sig, (unsigned int) siglen);
++
++ err:
++
++ if (hKey != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey);
++ for (i = 5; i <= 6; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ dctx->ctxdata.pk11_ctx = NULL;
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11ecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_ECDSA, NULL, 0 };
++ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_EC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_EC_PARAMS, NULL, 0 },
++ { CKA_EC_POINT, NULL, 0 }
++ };
++ CK_ATTRIBUTE *attr;
++ CK_BYTE digest[ISC_SHA384_DIGESTLENGTH];
++ CK_ULONG dgstlen;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ dst_key_t *key = dctx->key;
++ pk11_object_t *ec = key->keydata.pkey;
++ isc_result_t ret = ISC_R_SUCCESS;
++ unsigned int i;
++
++ REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
++ key->key_alg == DST_ALG_ECDSA384);
++ REQUIRE(ec != NULL);
++
++ if (key->key_alg == DST_ALG_ECDSA256)
++ dgstlen = ISC_SHA256_DIGESTLENGTH;
++ else
++ dgstlen = ISC_SHA384_DIGESTLENGTH;
++
++ PK11_RET(pkcs_C_DigestFinal,
++ (pk11_ctx->session, digest, &dgstlen),
++ ISC_R_FAILURE);
++
++ for (attr = pk11_attribute_first(ec);
++ attr != NULL;
++ attr = pk11_attribute_next(ec, attr))
++ switch (attr->type) {
++ case CKA_EC_PARAMS:
++ INSIST(keyTemplate[5].type == attr->type);
++ keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[5].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[5].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[5].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_EC_POINT:
++ INSIST(keyTemplate[6].type == attr->type);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 7,
++ &hKey),
++ ISC_R_FAILURE);
++
++ PK11_RET(pkcs_C_VerifyInit,
++ (pk11_ctx->session, &mech, hKey),
++ ISC_R_FAILURE);
++
++ PK11_RET(pkcs_C_Verify,
++ (pk11_ctx->session,
++ digest, dgstlen,
++ (CK_BYTE_PTR) sig->base, (CK_ULONG) sig->length),
++ DST_R_SIGNFAILURE);
++
++ err:
++
++ if (hKey != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, hKey);
++ for (i = 5; i <= 6; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ dctx->ctxdata.pk11_ctx = NULL;
++
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11ecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
++ pk11_object_t *ec1, *ec2;
++ CK_ATTRIBUTE *attr1, *attr2;
++
++ ec1 = key1->keydata.pkey;
++ ec2 = key2->keydata.pkey;
++
++ if ((ec1 == NULL) && (ec2 == NULL))
++ return (ISC_TRUE);
++ else if ((ec1 == NULL) || (ec2 == NULL))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(ec1, CKA_EC_PARAMS);
++ attr2 = pk11_attribute_bytype(ec2, CKA_EC_PARAMS);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(ec1, CKA_EC_POINT);
++ attr2 = pk11_attribute_bytype(ec2, CKA_EC_POINT);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(ec1, CKA_VALUE);
++ attr2 = pk11_attribute_bytype(ec2, CKA_VALUE);
++ if (((attr1 != NULL) || (attr2 != NULL)) &&
++ ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
++ return (ISC_FALSE);
++
++ if (!ec1->ontoken && !ec2->ontoken)
++ return (ISC_TRUE);
++ else if (ec1->ontoken || ec2->ontoken ||
++ (ec1->object != ec2->object))
++ return (ISC_FALSE);
++
++ return (ISC_TRUE);
++}
++
++#define SETCURVE() \
++ if (key->key_alg == DST_ALG_ECDSA256) { \
++ attr->pValue = isc_mem_get(key->mctx, \
++ sizeof(pk11_ecc_prime256v1)); \
++ if (attr->pValue == NULL) \
++ DST_RET(ISC_R_NOMEMORY); \
++ memcpy(attr->pValue, \
++ pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1)); \
++ attr->ulValueLen = sizeof(pk11_ecc_prime256v1); \
++ } else { \
++ attr->pValue = isc_mem_get(key->mctx, \
++ sizeof(pk11_ecc_secp384r1)); \
++ if (attr->pValue == NULL) \
++ DST_RET(ISC_R_NOMEMORY); \
++ memcpy(attr->pValue, \
++ pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1)); \
++ attr->ulValueLen = sizeof(pk11_ecc_secp384r1); \
++ }
++
++#define FREECURVE() \
++ if (attr->pValue != NULL) { \
++ memset(attr->pValue, 0, attr->ulValueLen); \
++ isc_mem_put(key->mctx, attr->pValue, attr->ulValueLen); \
++ attr->pValue = NULL; \
++ }
++
++static isc_result_t
++pkcs11ecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_EC_KEY_PAIR_GEN, NULL, 0 };
++ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_EC;
++ CK_ATTRIBUTE pubTemplate[] =
++ {
++ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_EC_PARAMS, NULL, 0 }
++ };
++ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
++ CK_ATTRIBUTE privTemplate[] =
++ {
++ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) }
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *ec;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++
++ REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
++ key->key_alg == DST_ALG_ECDSA384);
++ UNUSED(unused);
++ UNUSED(callback);
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_EC));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
++ if (ec == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(ec, 0, sizeof(*ec));
++ key->keydata.pkey = ec;
++ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
++ if (ec->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(ec->repr, 0, sizeof(*attr) * 3);
++ ec->attrcnt = 3;
++
++ attr = ec->repr;
++ attr[0].type = CKA_EC_PARAMS;
++ attr[1].type = CKA_EC_POINT;
++ attr[2].type = CKA_VALUE;
++
++ attr = &pubTemplate[5];
++ SETCURVE();
++
++ PK11_RET(pkcs_C_GenerateKeyPair,
++ (pk11_ctx->session, &mech,
++ pubTemplate, (CK_ULONG) 6,
++ privTemplate, (CK_ULONG) 7,
++ &pub, &priv),
++ DST_R_CRYPTOFAILURE);
++
++ attr = &pubTemplate[5];
++ FREECURVE();
++
++ attr = ec->repr;
++ SETCURVE();
++
++ attr++;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++
++ attr++;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11ecdsa_destroy(key);
++ if (priv != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ if (pub != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11ecdsa_isprivate(const dst_key_t *key) {
++ pk11_object_t *ec = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (ec == NULL)
++ return (ISC_FALSE);
++ attr = pk11_attribute_bytype(ec, CKA_VALUE);
++ return (ISC_TF((attr != NULL) || ec->ontoken));
++}
++
++static void
++pkcs11ecdsa_destroy(dst_key_t *key) {
++ pk11_object_t *ec = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (ec == NULL)
++ return;
++
++ INSIST((ec->object == CK_INVALID_HANDLE) || ec->ontoken);
++
++ for (attr = pk11_attribute_first(ec);
++ attr != NULL;
++ attr = pk11_attribute_next(ec, attr))
++ switch (attr->type) {
++ case CKA_LABEL:
++ case CKA_ID:
++ case CKA_EC_PARAMS:
++ case CKA_EC_POINT:
++ case CKA_VALUE:
++ FREECURVE();
++ break;
++ }
++ if (ec->repr != NULL) {
++ memset(ec->repr, 0, ec->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ ec->repr,
++ ec->attrcnt * sizeof(*attr));
++ }
++ memset(ec, 0, sizeof(*ec));
++ isc_mem_put(key->mctx, ec, sizeof(*ec));
++ key->keydata.pkey = NULL;
++}
++
++static isc_result_t
++pkcs11ecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *ec;
++ isc_region_t r;
++ unsigned int len;
++ CK_ATTRIBUTE *attr;
++
++ REQUIRE(key->keydata.pkey != NULL);
++
++ if (key->key_alg == DST_ALG_ECDSA256)
++ len = DNS_KEY_ECDSA256SIZE;
++ else
++ len = DNS_KEY_ECDSA384SIZE;
++
++ ec = key->keydata.pkey;
++ attr = pk11_attribute_bytype(ec, CKA_EC_POINT);
++ if ((attr == NULL) ||
++ (attr->ulValueLen != len + 3) ||
++ (((CK_BYTE_PTR) attr->pValue)[0] != TAG_OCTECT_STRING) ||
++ (((CK_BYTE_PTR) attr->pValue)[1] != len + 1) ||
++ (((CK_BYTE_PTR) attr->pValue)[2] != UNCOMPRESSED))
++ return (ISC_R_FAILURE);
++
++ isc_buffer_availableregion(data, &r);
++ if (r.length < len)
++ return (ISC_R_NOSPACE);
++ memcpy(r.base, (CK_BYTE_PTR) attr->pValue + 3, len);
++ isc_buffer_add(data, len);
++
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++pkcs11ecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *ec;
++ isc_region_t r;
++ unsigned int len;
++ CK_ATTRIBUTE *attr;
++
++ REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
++ key->key_alg == DST_ALG_ECDSA384);
++
++ if (key->key_alg == DST_ALG_ECDSA256)
++ len = DNS_KEY_ECDSA256SIZE;
++ else
++ len = DNS_KEY_ECDSA384SIZE;
++
++ isc_buffer_remainingregion(data, &r);
++ if (r.length == 0)
++ return (ISC_R_SUCCESS);
++ if (r.length != len)
++ return (DST_R_INVALIDPUBLICKEY);
++
++ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
++ if (ec == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(ec, 0, sizeof(*ec));
++ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
++ if (ec->repr == NULL)
++ goto nomemory;
++ ec->attrcnt = 2;
++
++ attr = ec->repr;
++ attr->type = CKA_EC_PARAMS;
++ if (key->key_alg == DST_ALG_ECDSA256) {
++ attr->pValue =
++ isc_mem_get(key->mctx, sizeof(pk11_ecc_prime256v1));
++ if (attr->pValue == NULL)
++ goto nomemory;
++ memcpy(attr->pValue,
++ pk11_ecc_prime256v1, sizeof(pk11_ecc_prime256v1));
++ attr->ulValueLen = sizeof(pk11_ecc_prime256v1);
++ } else {
++ attr->pValue =
++ isc_mem_get(key->mctx, sizeof(pk11_ecc_secp384r1));
++ if (attr->pValue == NULL)
++ goto nomemory;
++ memcpy(attr->pValue,
++ pk11_ecc_secp384r1, sizeof(pk11_ecc_secp384r1));
++ attr->ulValueLen = sizeof(pk11_ecc_secp384r1);
++ }
++
++ attr++;
++ attr->type = CKA_EC_POINT;
++ attr->pValue = isc_mem_get(key->mctx, len + 3);
++ if (attr->pValue == NULL)
++ goto nomemory;
++ ((CK_BYTE_PTR) attr->pValue)[0] = TAG_OCTECT_STRING;
++ ((CK_BYTE_PTR) attr->pValue)[1] = len + 1;
++ ((CK_BYTE_PTR) attr->pValue)[2] = UNCOMPRESSED;
++ memcpy((CK_BYTE_PTR) attr->pValue + 3, r.base, len);
++ attr->ulValueLen = len + 3;
++
++ isc_buffer_forward(data, len);
++ key->keydata.pkey = ec;
++ return (ISC_R_SUCCESS);
++
++ nomemory:
++ for (attr = pk11_attribute_first(ec);
++ attr != NULL;
++ attr = pk11_attribute_next(ec, attr))
++ switch (attr->type) {
++ case CKA_EC_PARAMS:
++ case CKA_EC_POINT:
++ FREECURVE();
++ break;
++ }
++ if (ec->repr != NULL) {
++ memset(ec->repr, 0, ec->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ ec->repr,
++ ec->attrcnt * sizeof(*attr));
++ }
++ memset(ec, 0, sizeof(*ec));
++ isc_mem_put(key->mctx, ec, sizeof(*ec));
++ return (ISC_R_NOMEMORY);
++}
++
++static isc_result_t
++pkcs11ecdsa_tofile(const dst_key_t *key, const char *directory) {
++ isc_result_t ret;
++ pk11_object_t *ec;
++ dst_private_t priv;
++ unsigned char *buf = NULL;
++ unsigned int i = 0;
++ CK_ATTRIBUTE *attr;
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external) {
++ priv.nelements = 0;
++ return (dst__privstruct_writefile(key, &priv, directory));
++ }
++
++ ec = key->keydata.pkey;
++ attr = pk11_attribute_bytype(ec, CKA_VALUE);
++ if (attr != NULL) {
++ buf = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (buf == NULL)
++ return (ISC_R_NOMEMORY);
++ priv.elements[i].tag = TAG_ECDSA_PRIVATEKEY;
++ priv.elements[i].length = (unsigned short) attr->ulValueLen;
++ memcpy(buf, attr->pValue, attr->ulValueLen);
++ priv.elements[i].data = buf;
++ i++;
++ }
++
++ if (key->engine != NULL) {
++ priv.elements[i].tag = TAG_ECDSA_ENGINE;
++ priv.elements[i].length = strlen(key->engine) + 1;
++ priv.elements[i].data = (unsigned char *)key->engine;
++ i++;
++ }
++
++ if (key->label != NULL) {
++ priv.elements[i].tag = TAG_ECDSA_LABEL;
++ priv.elements[i].length = strlen(key->label) + 1;
++ priv.elements[i].data = (unsigned char *)key->label;
++ i++;
++ }
++
++ priv.nelements = i;
++ ret = dst__privstruct_writefile(key, &priv, directory);
++
++ if (buf != NULL) {
++ memset(buf, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx, buf, attr->ulValueLen);
++ }
++ return (ret);
++}
++
++static isc_result_t
++pkcs11ecdsa_fetch(dst_key_t *key, const char *engine, const char *label,
++ dst_key_t *pub)
++{
++ CK_RV rv;
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_EC;
++ CK_ATTRIBUTE searchTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_LABEL, NULL, 0 }
++ };
++ CK_ULONG cnt;
++ CK_ATTRIBUTE *attr;
++ CK_ATTRIBUTE *pubattr;
++ pk11_object_t *ec;
++ pk11_object_t *pubec;
++ pk11_context_t *pk11_ctx = NULL;
++ isc_result_t ret;
++
++ if (label == NULL)
++ return (DST_R_NOENGINE);
++
++ ec = key->keydata.pkey;
++ pubec = pub->keydata.pkey;
++
++ ec->object = CK_INVALID_HANDLE;
++ ec->ontoken = ISC_TRUE;
++ ec->reqlogon = ISC_TRUE;
++ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
++ if (ec->repr == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(ec->repr, 0, sizeof(*attr) * 2);
++ ec->attrcnt = 2;
++ attr = ec->repr;
++
++ attr->type = CKA_EC_PARAMS;
++ pubattr = pk11_attribute_bytype(pubec, CKA_EC_PARAMS);
++ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
++ attr->ulValueLen = pubattr->ulValueLen;
++ attr++;
++
++ attr->type = CKA_EC_POINT;
++ pubattr = pk11_attribute_bytype(pubec, CKA_EC_POINT);
++ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
++ attr->ulValueLen = pubattr->ulValueLen;
++
++ ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
++ ec->reqlogon, NULL, ec->slot);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ attr = pk11_attribute_bytype(ec, CKA_LABEL);
++ if (attr == NULL) {
++ attr = pk11_attribute_bytype(ec, CKA_ID);
++ INSIST(attr != NULL);
++ searchTemplate[3].type = CKA_ID;
++ }
++ searchTemplate[3].pValue = attr->pValue;
++ searchTemplate[3].ulValueLen = attr->ulValueLen;
++
++ PK11_RET(pkcs_C_FindObjectsInit,
++ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_FindObjects,
++ (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
++ DST_R_CRYPTOFAILURE);
++ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
++ if (cnt == 0)
++ DST_RET(ISC_R_NOTFOUND);
++ if (cnt > 1)
++ DST_RET(ISC_R_EXISTS);
++
++ if (engine != NULL) {
++ key->engine = isc_mem_strdup(key->mctx, engine);
++ if (key->engine == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ }
++
++ key->label = isc_mem_strdup(key->mctx, label);
++ if (key->label == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (pk11_ctx != NULL) {
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ }
++ return (ret);
++}
++
++static isc_result_t
++pkcs11ecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
++ dst_private_t priv;
++ isc_result_t ret;
++ pk11_object_t *ec = NULL;
++ CK_ATTRIBUTE *attr, *pattr;
++ isc_mem_t *mctx = key->mctx;
++ unsigned int i;
++ const char *engine = NULL, *label = NULL;
++
++ REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
++ key->key_alg == DST_ALG_ECDSA384);
++
++ if ((pub == NULL) || (pub->keydata.pkey == NULL))
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ /* read private key file */
++ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ if (key->external) {
++ if (priv.nelements != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ key->keydata.pkey = pub->keydata.pkey;
++ pub->keydata.pkey = NULL;
++ key->key_size = pub->key_size;
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++ }
++
++ for (i = 0; i < priv.nelements; i++) {
++ switch (priv.elements[i].tag) {
++ case TAG_ECDSA_ENGINE:
++ engine = (char *)priv.elements[i].data;
++ break;
++ case TAG_ECDSA_LABEL:
++ label = (char *)priv.elements[i].data;
++ break;
++ default:
++ break;
++ }
++ }
++ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
++ if (ec == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(ec, 0, sizeof(*ec));
++ key->keydata.pkey = ec;
++
++ /* Is this key is stored in a HSM? See if we can fetch it. */
++ if ((label != NULL) || (engine != NULL)) {
++ ret = pkcs11ecdsa_fetch(key, engine, label, pub);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++ }
++
++ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
++ if (ec->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(ec->repr, 0, sizeof(*attr) * 3);
++ ec->attrcnt = 3;
++
++ attr = ec->repr;
++ attr->type = CKA_EC_PARAMS;
++ pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_PARAMS);
++ INSIST(pattr != NULL);
++ attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pattr->pValue, pattr->ulValueLen);
++ attr->ulValueLen = pattr->ulValueLen;
++
++ attr++;
++ attr->type = CKA_EC_POINT;
++ pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_POINT);
++ INSIST(pattr != NULL);
++ attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pattr->pValue, pattr->ulValueLen);
++ attr->ulValueLen = pattr->ulValueLen;
++
++ attr++;
++ attr->type = CKA_VALUE;
++ attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, priv.elements[0].data, priv.elements[0].length);
++ attr->ulValueLen = priv.elements[0].length;
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11ecdsa_destroy(key);
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++}
++
++static isc_result_t
++pkcs11ecdsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
++ const char *pin)
++{
++ CK_RV rv;
++ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_EC;
++ CK_ATTRIBUTE searchTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_LABEL, NULL, 0 }
++ };
++ CK_ULONG cnt;
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *ec;
++ pk11_context_t *pk11_ctx = NULL;
++ isc_result_t ret;
++ unsigned int i;
++
++ UNUSED(pin);
++
++ ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
++ if (ec == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(ec, 0, sizeof(*ec));
++ ec->object = CK_INVALID_HANDLE;
++ ec->ontoken = ISC_TRUE;
++ ec->reqlogon = ISC_TRUE;
++ key->keydata.pkey = ec;
++
++ ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
++ if (ec->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(ec->repr, 0, sizeof(*attr) * 2);
++ ec->attrcnt = 2;
++ attr = ec->repr;
++ attr[0].type = CKA_EC_PARAMS;
++ attr[1].type = CKA_EC_POINT;
++
++ ret = pk11_parse_uri(ec, label, key->mctx, OP_EC);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_EC, ISC_TRUE, ISC_FALSE,
++ ec->reqlogon, NULL, ec->slot);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ attr = pk11_attribute_bytype(ec, CKA_LABEL);
++ if (attr == NULL) {
++ attr = pk11_attribute_bytype(ec, CKA_ID);
++ INSIST(attr != NULL);
++ searchTemplate[3].type = CKA_ID;
++ }
++ searchTemplate[3].pValue = attr->pValue;
++ searchTemplate[3].ulValueLen = attr->ulValueLen;
++
++ PK11_RET(pkcs_C_FindObjectsInit,
++ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_FindObjects,
++ (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
++ DST_R_CRYPTOFAILURE);
++ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
++ if (cnt == 0)
++ DST_RET(ISC_R_NOTFOUND);
++ if (cnt > 1)
++ DST_RET(ISC_R_EXISTS);
++
++ attr = ec->repr;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, hKey, attr, 2),
++ DST_R_CRYPTOFAILURE);
++ for (i = 0; i <= 1; i++) {
++ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
++ if (attr[i].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr[i].pValue, 0, attr[i].ulValueLen);
++ }
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, hKey, attr, 2),
++ DST_R_CRYPTOFAILURE);
++
++ keyClass = CKO_PRIVATE_KEY;
++ PK11_RET(pkcs_C_FindObjectsInit,
++ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_FindObjects,
++ (pk11_ctx->session, &ec->object, (CK_ULONG) 1, &cnt),
++ DST_R_CRYPTOFAILURE);
++ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
++ if (cnt == 0)
++ DST_RET(ISC_R_NOTFOUND);
++ if (cnt > 1)
++ DST_RET(ISC_R_EXISTS);
++
++ if (engine != NULL) {
++ key->engine = isc_mem_strdup(key->mctx, engine);
++ if (key->engine == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ }
++
++ key->label = isc_mem_strdup(key->mctx, label);
++ if (key->label == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11ecdsa_destroy(key);
++ if (pk11_ctx != NULL) {
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ }
++ return (ret);
++}
++
++static dst_func_t pkcs11ecdsa_functions = {
++ pkcs11ecdsa_createctx,
++ NULL, /*%< createctx2 */
++ pkcs11ecdsa_destroyctx,
++ pkcs11ecdsa_adddata,
++ pkcs11ecdsa_sign,
++ pkcs11ecdsa_verify,
++ NULL, /*%< verify2 */
++ NULL, /*%< computesecret */
++ pkcs11ecdsa_compare,
++ NULL, /*%< paramcompare */
++ pkcs11ecdsa_generate,
++ pkcs11ecdsa_isprivate,
++ pkcs11ecdsa_destroy,
++ pkcs11ecdsa_todns,
++ pkcs11ecdsa_fromdns,
++ pkcs11ecdsa_tofile,
++ pkcs11ecdsa_parse,
++ NULL, /*%< cleanup */
++ pkcs11ecdsa_fromlabel,
++ NULL, /*%< dump */
++ NULL, /*%< restore */
++};
++
++isc_result_t
++dst__pkcs11ecdsa_init(dst_func_t **funcp) {
++ REQUIRE(funcp != NULL);
++ if (*funcp == NULL)
++ *funcp = &pkcs11ecdsa_functions;
++ return (ISC_R_SUCCESS);
++}
++
++#else /* PKCS11CRYPTO && HAVE_PKCS11_ECDSA */
++
++#include <isc/util.h>
++
++EMPTY_TRANSLATION_UNIT
++
++#endif /* PKCS11CRYPTO && HAVE_PKCS11_ECDSA */
++/*! \file */
+diff -up bind-9.9.6/lib/dns/pkcs11gost_link.c.native_pkcs11 bind-9.9.6/lib/dns/pkcs11gost_link.c
+--- bind-9.9.6/lib/dns/pkcs11gost_link.c.native_pkcs11 2014-10-09 13:30:47.827302924 +0200
++++ bind-9.9.6/lib/dns/pkcs11gost_link.c 2014-10-09 13:30:47.827302924 +0200
+@@ -0,0 +1,949 @@
++/*
++ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#include <config.h>
++
++#if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_GOST)
++
++#include <isc/entropy.h>
++#include <isc/mem.h>
++#include <isc/sha2.h>
++#include <isc/string.h>
++#include <isc/util.h>
++
++#include <dns/keyvalues.h>
++#include <dns/log.h>
++#include <dst/result.h>
++
++#include "dst_internal.h"
++#include "dst_parse.h"
++#include "dst_pkcs11.h"
++#include "dst_gost.h"
++
++#include <pk11/pk11.h>
++#include <pk11/internal.h>
++#define WANT_GOST_PARAMS
++#include <pk11/constants.h>
++
++#include <pkcs11/pkcs11.h>
++
++/*
++ * RU CryptoPro GOST keys:
++ * mechanisms:
++ * CKM_GOSTR3411
++ * CKM_GOSTR3410_WITH_GOSTR3411
++ * CKM_GOSTR3410_KEY_PAIR_GEN
++ * domain parameters:
++ * CKA_GOSTR3410_PARAMS (fixed BER OID 1.2.643.2.2.35.1)
++ * CKA_GOSTR3411_PARAMS (fixed BER OID 1.2.643.2.2.30.1)
++ * CKA_GOST28147_PARAMS (optional, don't use)
++ * public keys:
++ * object class CKO_PUBLIC_KEY
++ * key type CKK_GOSTR3410
++ * attribute CKA_VALUE (point Q)
++ * attribute CKA_GOSTR3410_PARAMS
++ * attribute CKA_GOSTR3411_PARAMS
++ * attribute CKA_GOST28147_PARAMS
++ * private keys:
++ * object class CKO_PRIVATE_KEY
++ * key type CKK_GOSTR3410
++ * attribute CKA_VALUE (big int d)
++ * attribute CKA_GOSTR3410_PARAMS
++ * attribute CKA_GOSTR3411_PARAMS
++ * attribute CKA_GOST28147_PARAMS
++ * point format: <x> <y> (little endian)
++ */
++
++#define CKA_VALUE2 CKA_PRIVATE_EXPONENT
++
++#define ISC_GOST_SIGNATURELENGTH 64
++#define ISC_GOST_PUBKEYLENGTH 64
++
++/* HASH methods */
++
++isc_result_t
++isc_gost_init(isc_gost_t *ctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_GOSTR3411, NULL, 0 };
++ int ret = ISC_R_SUCCESS;
++
++ ret = pk11_get_session(ctx, OP_GOST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0);
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++ PK11_CALL(pkcs_C_DigestInit, (ctx->session, &mech), ISC_R_FAILURE);
++ return (ret);
++}
++
++void
++isc_gost_invalidate(isc_gost_t *ctx) {
++ CK_BYTE garbage[ISC_GOST_DIGESTLENGTH];
++ CK_ULONG len = ISC_GOST_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(ctx);
++}
++
++isc_result_t
++isc_gost_update(isc_gost_t *ctx, const unsigned char *buf, unsigned int len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++ int ret = ISC_R_SUCCESS;
++
++ DE_CONST(buf, pPart);
++ PK11_CALL(pkcs_C_DigestUpdate,
++ (ctx->session, pPart, (CK_ULONG) len),
++ ISC_R_FAILURE);
++ return (ret);
++}
++
++isc_result_t
++isc_gost_final(isc_gost_t *ctx, unsigned char *digest) {
++ CK_RV rv;
++ CK_ULONG len = ISC_GOST_DIGESTLENGTH;
++ int ret = ISC_R_SUCCESS;
++
++ PK11_CALL(pkcs_C_DigestFinal,
++ (ctx->session, (CK_BYTE_PTR) digest, &len),
++ ISC_R_FAILURE);
++ pk11_return_session(ctx);
++ return (ret);
++}
++
++/* DST methods */
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++#define DST_RET(a) {ret = a; goto err;}
++
++static isc_result_t pkcs11gost_todns(const dst_key_t *key, isc_buffer_t *data);
++static void pkcs11gost_destroy(dst_key_t *key);
++
++static isc_result_t
++pkcs11gost_createctx_sign(dst_key_t *key, dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_GOSTR3410;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, 0 },
++ { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset,
++ (CK_ULONG) sizeof(pk11_gost_a_paramset) },
++ { CKA_GOSTR3411_PARAMS, pk11_gost_paramset,
++ (CK_ULONG) sizeof(pk11_gost_paramset) }
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *gost;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_GOST));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ gost = key->keydata.pkey;
++ if (gost->ontoken && (gost->object != CK_INVALID_HANDLE)) {
++ pk11_ctx->ontoken = gost->ontoken;
++ pk11_ctx->object = gost->object;
++ goto token_key;
++ }
++
++ for (attr = pk11_attribute_first(gost);
++ attr != NULL;
++ attr = pk11_attribute_next(gost, attr))
++ switch (attr->type) {
++ case CKA_VALUE2:
++ INSIST(keyTemplate[6].type == CKA_VALUE);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 9,
++ &pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ token_key:
++
++ PK11_RET(pkcs_C_SignInit,
++ (pk11_ctx->session, &mech, pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++
++ for (i = 6; i <= 6; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object);
++ for (i = 6; i <= 6; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11gost_createctx_verify(dst_key_t *key, dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_GOSTR3410_WITH_GOSTR3411, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_GOSTR3410;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, 0 },
++ { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset,
++ (CK_ULONG) sizeof(pk11_gost_a_paramset) },
++ { CKA_GOSTR3411_PARAMS, pk11_gost_paramset,
++ (CK_ULONG) sizeof(pk11_gost_paramset) }
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *gost;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_GOST));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ gost = key->keydata.pkey;
++ if (gost->ontoken && (gost->object != CK_INVALID_HANDLE)) {
++ pk11_ctx->ontoken = gost->ontoken;
++ pk11_ctx->object = gost->object;
++ goto token_key;
++ }
++
++ for (attr = pk11_attribute_first(gost);
++ attr != NULL;
++ attr = pk11_attribute_next(gost, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ INSIST(keyTemplate[5].type == attr->type);
++ keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[5].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[5].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[5].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 8,
++ &pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ token_key:
++
++ PK11_RET(pkcs_C_VerifyInit,
++ (pk11_ctx->session, &mech, pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++
++ for (i = 5; i <= 5; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object);
++ for (i = 5; i <= 5; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11gost_createctx(dst_key_t *key, dst_context_t *dctx) {
++ if (dctx->use == DO_SIGN)
++ return (pkcs11gost_createctx_sign(key, dctx));
++ else
++ return (pkcs11gost_createctx_verify(key, dctx));
++}
++
++static void
++pkcs11gost_destroyctx(dst_context_t *dctx) {
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++
++ if (pk11_ctx != NULL) {
++ if (!pk11_ctx->ontoken &&
++ (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session,
++ pk11_ctx->object);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ dctx->ctxdata.pk11_ctx = NULL;
++ }
++}
++
++static isc_result_t
++pkcs11gost_adddata(dst_context_t *dctx, const isc_region_t *data) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ if (dctx->use == DO_SIGN)
++ PK11_CALL(pkcs_C_SignUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++ else
++ PK11_CALL(pkcs_C_VerifyUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++ return (ret);
++}
++
++static isc_result_t
++pkcs11gost_sign(dst_context_t *dctx, isc_buffer_t *sig) {
++ CK_RV rv;
++ CK_ULONG siglen = ISC_GOST_SIGNATURELENGTH;
++ isc_region_t r;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ isc_buffer_availableregion(sig, &r);
++ if (r.length < ISC_GOST_SIGNATURELENGTH)
++ return (ISC_R_NOSPACE);
++
++ PK11_RET(pkcs_C_SignFinal,
++ (pk11_ctx->session, (CK_BYTE_PTR) r.base, &siglen),
++ DST_R_SIGNFAILURE);
++ if (siglen != ISC_GOST_SIGNATURELENGTH)
++ return (DST_R_SIGNFAILURE);
++
++ isc_buffer_add(sig, ISC_GOST_SIGNATURELENGTH);
++
++ err:
++ return (ret);
++}
++
++static isc_result_t
++pkcs11gost_verify(dst_context_t *dctx, const isc_region_t *sig) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ PK11_CALL(pkcs_C_VerifyFinal,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) sig->base,
++ (CK_ULONG) sig->length),
++ DST_R_VERIFYFAILURE);
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11gost_compare(const dst_key_t *key1, const dst_key_t *key2) {
++ pk11_object_t *gost1, *gost2;
++ CK_ATTRIBUTE *attr1, *attr2;
++
++ gost1 = key1->keydata.pkey;
++ gost2 = key2->keydata.pkey;
++
++ if ((gost1 == NULL) && (gost2 == NULL))
++ return (ISC_TRUE);
++ else if ((gost1 == NULL) || (gost2 == NULL))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(gost1, CKA_VALUE);
++ attr2 = pk11_attribute_bytype(gost2, CKA_VALUE);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(gost1, CKA_VALUE2);
++ attr2 = pk11_attribute_bytype(gost2, CKA_VALUE2);
++ if (((attr1 != NULL) || (attr2 != NULL)) &&
++ ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
++ return (ISC_FALSE);
++
++ if (!gost1->ontoken && !gost2->ontoken)
++ return (ISC_TRUE);
++ else if (gost1->ontoken || gost2->ontoken ||
++ (gost1->object != gost2->object))
++ return (ISC_FALSE);
++
++ return (ISC_TRUE);
++}
++
++static isc_result_t
++pkcs11gost_generate(dst_key_t *key, int unused, void (*callback)(int)) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_GOSTR3410_KEY_PAIR_GEN, NULL, 0 };
++ CK_KEY_TYPE keyType = CKK_GOSTR3410;
++ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
++ CK_ATTRIBUTE pubTemplate[] =
++ {
++ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_GOSTR3410_PARAMS, pk11_gost_a_paramset,
++ (CK_ULONG) sizeof(pk11_gost_a_paramset) },
++ { CKA_GOSTR3411_PARAMS, pk11_gost_paramset,
++ (CK_ULONG) sizeof(pk11_gost_paramset) }
++ };
++ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
++ CK_ATTRIBUTE privTemplate[] =
++ {
++ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *gost;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++
++ UNUSED(unused);
++ UNUSED(callback);
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_GOST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_GOST));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ PK11_RET(pkcs_C_GenerateKeyPair,
++ (pk11_ctx->session, &mech,
++ pubTemplate, (CK_ULONG) 7,
++ privTemplate, (CK_ULONG) 7,
++ &pub, &priv),
++ DST_R_CRYPTOFAILURE);
++
++ gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost));
++ if (gost == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(gost, 0, sizeof(*gost));
++ key->keydata.pkey = gost;
++ gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx,
++ sizeof(*attr) * 2);
++ if (gost->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(gost->repr, 0, sizeof(*attr) * 2);
++ gost->attrcnt = 2;
++
++ attr = gost->repr;
++ attr[0].type = CKA_VALUE;
++ attr[1].type = CKA_VALUE2;
++
++ attr = gost->repr;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 1),
++ DST_R_CRYPTOFAILURE);
++
++ attr++;
++ attr->type = CKA_VALUE;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr->pValue, 0, attr->ulValueLen);
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 1),
++ DST_R_CRYPTOFAILURE);
++ attr->type = CKA_VALUE2;
++
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11gost_destroy(key);
++ if (priv != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ if (pub != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11gost_isprivate(const dst_key_t *key) {
++ pk11_object_t *gost = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (gost == NULL)
++ return (ISC_FALSE);
++ attr = pk11_attribute_bytype(gost, CKA_VALUE2);
++ return (ISC_TF((attr != NULL) || gost->ontoken));
++}
++
++static void
++pkcs11gost_destroy(dst_key_t *key) {
++ pk11_object_t *gost = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (gost == NULL)
++ return;
++
++ INSIST((gost->object == CK_INVALID_HANDLE) || gost->ontoken);
++
++ for (attr = pk11_attribute_first(gost);
++ attr != NULL;
++ attr = pk11_attribute_next(gost, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ case CKA_VALUE2:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (gost->repr != NULL) {
++ memset(gost->repr, 0, gost->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ gost->repr,
++ gost->attrcnt * sizeof(*attr));
++ }
++ memset(gost, 0, sizeof(*gost));
++ isc_mem_put(key->mctx, gost, sizeof(*gost));
++ key->keydata.pkey = NULL;
++}
++
++static isc_result_t
++pkcs11gost_todns(const dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *gost;
++ isc_region_t r;
++ CK_ATTRIBUTE *attr;
++
++ REQUIRE(key->keydata.pkey != NULL);
++
++ gost = key->keydata.pkey;
++ attr = pk11_attribute_bytype(gost, CKA_VALUE);
++ if ((attr == NULL) || (attr->ulValueLen != ISC_GOST_PUBKEYLENGTH))
++ return (ISC_R_FAILURE);
++
++ isc_buffer_availableregion(data, &r);
++ if (r.length < ISC_GOST_PUBKEYLENGTH)
++ return (ISC_R_NOSPACE);
++ memcpy(r.base, (CK_BYTE_PTR) attr->pValue, ISC_GOST_PUBKEYLENGTH);
++ isc_buffer_add(data, ISC_GOST_PUBKEYLENGTH);
++
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++pkcs11gost_fromdns(dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *gost;
++ isc_region_t r;
++ CK_ATTRIBUTE *attr;
++
++ isc_buffer_remainingregion(data, &r);
++ if (r.length == 0)
++ return (ISC_R_SUCCESS);
++ if (r.length != ISC_GOST_PUBKEYLENGTH)
++ return (DST_R_INVALIDPUBLICKEY);
++
++ gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost));
++ if (gost == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(gost, 0, sizeof(*gost));
++ gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr));
++ if (gost->repr == NULL)
++ goto nomemory;
++ gost->attrcnt = 1;
++
++ attr = gost->repr;
++ attr->type = CKA_VALUE;
++ attr->pValue = isc_mem_get(key->mctx, ISC_GOST_PUBKEYLENGTH);
++ if (attr->pValue == NULL)
++ goto nomemory;
++ memcpy((CK_BYTE_PTR) attr->pValue, r.base, ISC_GOST_PUBKEYLENGTH);
++ attr->ulValueLen = ISC_GOST_PUBKEYLENGTH;
++
++ isc_buffer_forward(data, ISC_GOST_PUBKEYLENGTH);
++ key->keydata.pkey = gost;
++ return (ISC_R_SUCCESS);
++
++ nomemory:
++ for (attr = pk11_attribute_first(gost);
++ attr != NULL;
++ attr = pk11_attribute_next(gost, attr))
++ switch (attr->type) {
++ case CKA_VALUE:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (gost->repr != NULL) {
++ memset(gost->repr, 0, gost->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ gost->repr,
++ gost->attrcnt * sizeof(*attr));
++ }
++ memset(gost, 0, sizeof(*gost));
++ isc_mem_put(key->mctx, gost, sizeof(*gost));
++ return (ISC_R_NOMEMORY);
++}
++
++static unsigned char gost_private_der[39] = {
++ 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
++ 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
++ 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
++ 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
++ 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20
++};
++
++#ifdef PREFER_GOSTASN1
++
++static isc_result_t
++pkcs11gost_tofile(const dst_key_t *key, const char *directory) {
++ isc_result_t ret;
++ pk11_object_t *gost;
++ dst_private_t priv;
++ unsigned char *buf = NULL;
++ unsigned int i = 0;
++ CK_ATTRIBUTE *attr;
++ int adj;
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external) {
++ priv.nelements = 0;
++ return (dst__privstruct_writefile(key, &priv, directory));
++ }
++
++ gost = key->keydata.pkey;
++ attr = pk11_attribute_bytype(gost, CKA_VALUE2);
++ if (attr != NULL) {
++ buf = isc_mem_get(key->mctx, attr->ulValueLen + 39);
++ if (buf == NULL)
++ return (ISC_R_NOMEMORY);
++ priv.elements[i].tag = TAG_GOST_PRIVASN1;
++ priv.elements[i].length =
++ (unsigned short) attr->ulValueLen + 39;
++ memcpy(buf, gost_private_der, 39);
++ memcpy(buf +39, attr->pValue, attr->ulValueLen);
++ adj = (int) attr->ulValueLen - 32;
++ if (adj != 0) {
++ buf[1] += adj;
++ buf[36] += adj;
++ buf[38] += adj;
++ }
++ priv.elements[i].data = buf;
++ i++;
++ } else
++ return (DST_R_CRYPTOFAILURE);
++
++ priv.nelements = i;
++ ret = dst__privstruct_writefile(key, &priv, directory);
++
++ if (buf != NULL) {
++ memset(buf, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx, buf, attr->ulValueLen);
++ }
++ return (ret);
++}
++
++#else
++
++static isc_result_t
++pkcs11gost_tofile(const dst_key_t *key, const char *directory) {
++ isc_result_t ret;
++ pk11_object_t *gost;
++ dst_private_t priv;
++ unsigned char *buf = NULL;
++ unsigned int i = 0;
++ CK_ATTRIBUTE *attr;
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external) {
++ priv.nelements = 0;
++ return (dst__privstruct_writefile(key, &priv, directory));
++ }
++
++ gost = key->keydata.pkey;
++ attr = pk11_attribute_bytype(gost, CKA_VALUE2);
++ if (attr != NULL) {
++ buf = isc_mem_get(key->mctx, attr->ulValueLen);
++ if (buf == NULL)
++ return (ISC_R_NOMEMORY);
++ priv.elements[i].tag = TAG_GOST_PRIVRAW;
++ priv.elements[i].length = (unsigned short) attr->ulValueLen;
++ memcpy(buf, attr->pValue, attr->ulValueLen);
++ priv.elements[i].data = buf;
++ i++;
++ } else
++ return (DST_R_CRYPTOFAILURE);
++
++ priv.nelements = i;
++ ret = dst__privstruct_writefile(key, &priv, directory);
++
++ if (buf != NULL) {
++ memset(buf, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx, buf, attr->ulValueLen);
++ }
++ return (ret);
++}
++#endif
++
++static isc_result_t
++pkcs11gost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
++ dst_private_t priv;
++ isc_result_t ret;
++ pk11_object_t *gost = NULL;
++ CK_ATTRIBUTE *attr, *pattr;
++ isc_mem_t *mctx = key->mctx;
++
++ if ((pub == NULL) || (pub->keydata.pkey == NULL))
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ /* read private key file */
++ ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ if (key->external) {
++ if (priv.nelements != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ key->keydata.pkey = pub->keydata.pkey;
++ pub->keydata.pkey = NULL;
++ key->key_size = pub->key_size;
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++ }
++
++ if (priv.elements[0].tag == TAG_GOST_PRIVASN1) {
++ int adj = (int) priv.elements[0].length - (39 + 32);
++ unsigned char buf[39];
++
++ if ((adj > 0) || (adj < -31))
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ memcpy(buf, gost_private_der, 39);
++ if (adj != 0) {
++ buf[1] += adj;
++ buf[36] += adj;
++ buf[38] += adj;
++ }
++ if (memcmp(priv.elements[0].data, buf, 39) != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ priv.elements[0].tag = TAG_GOST_PRIVRAW;
++ priv.elements[0].length -= 39;
++ memmove(priv.elements[0].data,
++ priv.elements[0].data + 39,
++ 32 + adj);
++ }
++
++ gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost));
++ if (gost == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(gost, 0, sizeof(*gost));
++ key->keydata.pkey = gost;
++
++ gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx,
++ sizeof(*attr) * 2);
++ if (gost->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(gost->repr, 0, sizeof(*attr) * 2);
++ gost->attrcnt = 2;
++
++ attr = gost->repr;
++ attr->type = CKA_VALUE;
++ pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE);
++ INSIST(pattr != NULL);
++ attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pattr->pValue, pattr->ulValueLen);
++ attr->ulValueLen = pattr->ulValueLen;
++
++ attr++;
++ attr->type = CKA_VALUE2;
++ attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, priv.elements[0].data, priv.elements[0].length);
++ attr->ulValueLen = priv.elements[0].length;
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11gost_destroy(key);
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++}
++
++static dst_func_t pkcs11gost_functions = {
++ pkcs11gost_createctx,
++ NULL, /*%< createctx2 */
++ pkcs11gost_destroyctx,
++ pkcs11gost_adddata,
++ pkcs11gost_sign,
++ pkcs11gost_verify,
++ NULL, /*%< verify2 */
++ NULL, /*%< computesecret */
++ pkcs11gost_compare,
++ NULL, /*%< paramcompare */
++ pkcs11gost_generate,
++ pkcs11gost_isprivate,
++ pkcs11gost_destroy,
++ pkcs11gost_todns,
++ pkcs11gost_fromdns,
++ pkcs11gost_tofile,
++ pkcs11gost_parse,
++ NULL, /*%< cleanup */
++ NULL, /*%< fromlabel */
++ NULL, /*%< dump */
++ NULL, /*%< restore */
++};
++
++isc_result_t
++dst__pkcs11gost_init(dst_func_t **funcp) {
++ REQUIRE(funcp != NULL);
++ if (*funcp == NULL)
++ *funcp = &pkcs11gost_functions;
++ return (ISC_R_SUCCESS);
++}
++
++#else /* PKCS11CRYPTO && HAVE_PKCS11_GOST */
++
++#include <isc/util.h>
++
++EMPTY_TRANSLATION_UNIT
++
++#endif /* PKCS11CRYPTO && HAVE_PKCS11_GOST */
++/*! \file */
+diff -up bind-9.9.6/lib/dns/pkcs11rsa_link.c.native_pkcs11 bind-9.9.6/lib/dns/pkcs11rsa_link.c
+--- bind-9.9.6/lib/dns/pkcs11rsa_link.c.native_pkcs11 2014-10-09 13:30:47.829302927 +0200
++++ bind-9.9.6/lib/dns/pkcs11rsa_link.c 2014-10-09 13:30:47.829302927 +0200
+@@ -0,0 +1,1583 @@
++/*
++ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#ifdef PKCS11CRYPTO
++
++#include <config.h>
++
++#include <isc/entropy.h>
++#include <isc/md5.h>
++#include <isc/sha1.h>
++#include <isc/sha2.h>
++#include <isc/mem.h>
++#include <isc/string.h>
++#include <isc/util.h>
++
++#include <dst/result.h>
++
++#include "dst_internal.h"
++#include "dst_parse.h"
++#include "dst_pkcs11.h"
++
++#include <pk11/internal.h>
++
++/*
++ * Limit the size of public exponents.
++ */
++#ifndef RSA_MAX_PUBEXP_BITS
++#define RSA_MAX_PUBEXP_BITS 35
++#endif
++
++#define DST_RET(a) {ret = a; goto err;}
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++static isc_result_t pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data);
++static void pkcs11rsa_destroy(dst_key_t *key);
++static isc_result_t pkcs11rsa_fetch(dst_key_t *key, const char *engine,
++ const char *label, dst_key_t *pub);
++
++static isc_result_t
++pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { 0, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_RSA;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_MODULUS, NULL, 0 },
++ { CKA_PUBLIC_EXPONENT, NULL, 0 },
++ { CKA_PRIVATE_EXPONENT, NULL, 0 },
++ { CKA_PRIME_1, NULL, 0 },
++ { CKA_PRIME_2, NULL, 0 },
++ { CKA_EXPONENT_1, NULL, 0 },
++ { CKA_EXPONENT_2, NULL, 0 },
++ { CKA_COEFFICIENT, NULL, 0 }
++ };
++ CK_ATTRIBUTE *attr;
++ CK_SLOT_ID slotid;
++ pk11_object_t *rsa;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ REQUIRE(key->key_alg == DST_ALG_RSAMD5 ||
++ key->key_alg == DST_ALG_RSASHA1 ||
++ key->key_alg == DST_ALG_NSEC3RSASHA1 ||
++ key->key_alg == DST_ALG_RSASHA256 ||
++ key->key_alg == DST_ALG_RSASHA512);
++
++ rsa = key->keydata.pkey;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ if (rsa->ontoken)
++ slotid = rsa->slot;
++ else
++ slotid = pk11_get_best_token(OP_RSA);
++ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
++ rsa->reqlogon, NULL, slotid);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ if (rsa->ontoken && (rsa->object != CK_INVALID_HANDLE)) {
++ pk11_ctx->ontoken = rsa->ontoken;
++ pk11_ctx->object = rsa->object;
++ goto token_key;
++ }
++
++ for (attr = pk11_attribute_first(rsa);
++ attr != NULL;
++ attr = pk11_attribute_next(rsa, attr))
++ switch (attr->type) {
++ case CKA_MODULUS:
++ INSIST(keyTemplate[6].type == attr->type);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_PUBLIC_EXPONENT:
++ INSIST(keyTemplate[7].type == attr->type);
++ keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[7].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[7].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[7].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_PRIVATE_EXPONENT:
++ INSIST(keyTemplate[8].type == attr->type);
++ keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[8].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[8].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[8].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_PRIME_1:
++ INSIST(keyTemplate[9].type == attr->type);
++ keyTemplate[9].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[9].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[9].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[9].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_PRIME_2:
++ INSIST(keyTemplate[10].type == attr->type);
++ keyTemplate[10].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[10].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[10].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[10].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_EXPONENT_1:
++ INSIST(keyTemplate[11].type == attr->type);
++ keyTemplate[11].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[11].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[11].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[11].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_EXPONENT_2:
++ INSIST(keyTemplate[12].type == attr->type);
++ keyTemplate[12].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[12].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[12].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[12].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_COEFFICIENT:
++ INSIST(keyTemplate[13].type == attr->type);
++ keyTemplate[13].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[13].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[13].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[13].ulValueLen = attr->ulValueLen;
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 14,
++ &pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ token_key:
++
++ switch (dctx->key->key_alg) {
++ case DST_ALG_RSAMD5:
++ mech.mechanism = CKM_MD5_RSA_PKCS;
++ break;
++ case DST_ALG_RSASHA1:
++ case DST_ALG_NSEC3RSASHA1:
++ mech.mechanism = CKM_SHA1_RSA_PKCS;
++ break;
++ case DST_ALG_RSASHA256:
++ mech.mechanism = CKM_SHA256_RSA_PKCS;
++ break;
++ case DST_ALG_RSASHA512:
++ mech.mechanism = CKM_SHA512_RSA_PKCS;
++ break;
++ default:
++ INSIST(0);
++ }
++
++ PK11_RET(pkcs_C_SignInit,
++ (pk11_ctx->session, &mech, pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++
++ for (i = 6; i <= 13; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session,
++ pk11_ctx->object);
++ for (i = 6; i <= 13; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
++ dst_context_t *dctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { 0, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_RSA;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_MODULUS, NULL, 0 },
++ { CKA_PUBLIC_EXPONENT, NULL, 0 },
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *rsa;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ REQUIRE(key->key_alg == DST_ALG_RSAMD5 ||
++ key->key_alg == DST_ALG_RSASHA1 ||
++ key->key_alg == DST_ALG_NSEC3RSASHA1 ||
++ key->key_alg == DST_ALG_RSASHA256 ||
++ key->key_alg == DST_ALG_RSASHA512);
++
++ rsa = key->keydata.pkey;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
++ rsa->reqlogon, NULL,
++ pk11_get_best_token(OP_RSA));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ for (attr = pk11_attribute_first(rsa);
++ attr != NULL;
++ attr = pk11_attribute_next(rsa, attr))
++ switch (attr->type) {
++ case CKA_MODULUS:
++ INSIST(keyTemplate[5].type == attr->type);
++ keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[5].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[5].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[5].ulValueLen = attr->ulValueLen;
++ break;
++ case CKA_PUBLIC_EXPONENT:
++ INSIST(keyTemplate[6].type == attr->type);
++ keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
++ attr->ulValueLen);
++ if (keyTemplate[6].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(keyTemplate[6].pValue,
++ attr->pValue,
++ attr->ulValueLen);
++ keyTemplate[6].ulValueLen = attr->ulValueLen;
++ if (pk11_numbits(attr->pValue,
++ attr->ulValueLen) > maxbits &&
++ maxbits != 0)
++ DST_RET(DST_R_VERIFYFAILURE);
++ break;
++ }
++ pk11_ctx->object = CK_INVALID_HANDLE;
++ pk11_ctx->ontoken = ISC_FALSE;
++ PK11_RET(pkcs_C_CreateObject,
++ (pk11_ctx->session,
++ keyTemplate, (CK_ULONG) 7,
++ &pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ switch (dctx->key->key_alg) {
++ case DST_ALG_RSAMD5:
++ mech.mechanism = CKM_MD5_RSA_PKCS;
++ break;
++ case DST_ALG_RSASHA1:
++ case DST_ALG_NSEC3RSASHA1:
++ mech.mechanism = CKM_SHA1_RSA_PKCS;
++ break;
++ case DST_ALG_RSASHA256:
++ mech.mechanism = CKM_SHA256_RSA_PKCS;
++ break;
++ case DST_ALG_RSASHA512:
++ mech.mechanism = CKM_SHA512_RSA_PKCS;
++ break;
++ default:
++ INSIST(0);
++ }
++
++ PK11_RET(pkcs_C_VerifyInit,
++ (pk11_ctx->session, &mech, pk11_ctx->object),
++ ISC_R_FAILURE);
++
++ dctx->ctxdata.pk11_ctx = pk11_ctx;
++
++ for (i = 5; i <= 6; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session,
++ pk11_ctx->object);
++ for (i = 5; i <= 6; i++)
++ if (keyTemplate[i].pValue != NULL) {
++ memset(keyTemplate[i].pValue, 0,
++ keyTemplate[i].ulValueLen);
++ isc_mem_put(dctx->mctx,
++ keyTemplate[i].pValue,
++ keyTemplate[i].ulValueLen);
++ }
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_result_t
++pkcs11rsa_createctx(dst_key_t *key, dst_context_t *dctx) {
++ if (dctx->use == DO_SIGN)
++ return (pkcs11rsa_createctx_sign(key, dctx));
++ else
++ return (pkcs11rsa_createctx_verify(key, 0U, dctx));
++}
++
++static isc_result_t
++pkcs11rsa_createctx2(dst_key_t *key, int maxbits, dst_context_t *dctx) {
++ if (dctx->use == DO_SIGN)
++ return (pkcs11rsa_createctx_sign(key, dctx));
++ else
++ return (pkcs11rsa_createctx_verify(key,
++ (unsigned) maxbits, dctx));
++}
++
++static void
++pkcs11rsa_destroyctx(dst_context_t *dctx) {
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++
++ if (pk11_ctx != NULL) {
++ if (!pk11_ctx->ontoken &&
++ (pk11_ctx->object != CK_INVALID_HANDLE))
++ (void) pkcs_C_DestroyObject(pk11_ctx->session,
++ pk11_ctx->object);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ dctx->ctxdata.pk11_ctx = NULL;
++ }
++}
++
++static isc_result_t
++pkcs11rsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ if (dctx->use == DO_SIGN)
++ PK11_CALL(pkcs_C_SignUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++ else
++ PK11_CALL(pkcs_C_VerifyUpdate,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) data->base,
++ (CK_ULONG) data->length),
++ ISC_R_FAILURE);
++ return (ret);
++}
++
++static isc_result_t
++pkcs11rsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
++ CK_RV rv;
++ CK_ULONG siglen = 0;
++ isc_region_t r;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ PK11_RET(pkcs_C_SignFinal,
++ (pk11_ctx->session, NULL, &siglen),
++ DST_R_SIGNFAILURE);
++
++ isc_buffer_availableregion(sig, &r);
++
++ if (r.length < (unsigned int) siglen)
++ return (ISC_R_NOSPACE);
++
++ PK11_RET(pkcs_C_SignFinal,
++ (pk11_ctx->session, (CK_BYTE_PTR) r.base, &siglen),
++ DST_R_SIGNFAILURE);
++
++ isc_buffer_add(sig, (unsigned int) siglen);
++
++ err:
++ return (ret);
++}
++
++static isc_result_t
++pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
++ CK_RV rv;
++ pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ PK11_CALL(pkcs_C_VerifyFinal,
++ (pk11_ctx->session,
++ (CK_BYTE_PTR) sig->base,
++ (CK_ULONG) sig->length),
++ DST_R_VERIFYFAILURE);
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11rsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
++ pk11_object_t *rsa1, *rsa2;
++ CK_ATTRIBUTE *attr1, *attr2;
++
++ rsa1 = key1->keydata.pkey;
++ rsa2 = key2->keydata.pkey;
++
++ if ((rsa1 == NULL) && (rsa2 == NULL))
++ return (ISC_TRUE);
++ else if ((rsa1 == NULL) || (rsa2 == NULL))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(rsa1, CKA_MODULUS);
++ attr2 = pk11_attribute_bytype(rsa2, CKA_MODULUS);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(rsa1, CKA_PUBLIC_EXPONENT);
++ attr2 = pk11_attribute_bytype(rsa2, CKA_PUBLIC_EXPONENT);
++ if ((attr1 == NULL) && (attr2 == NULL))
++ return (ISC_TRUE);
++ else if ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
++ return (ISC_FALSE);
++
++ attr1 = pk11_attribute_bytype(rsa1, CKA_PRIVATE_EXPONENT);
++ attr2 = pk11_attribute_bytype(rsa2, CKA_PRIVATE_EXPONENT);
++ if (((attr1 != NULL) || (attr2 != NULL)) &&
++ ((attr1 == NULL) || (attr2 == NULL) ||
++ (attr1->ulValueLen != attr2->ulValueLen) ||
++ memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
++ return (ISC_FALSE);
++
++ if (!rsa1->ontoken && !rsa2->ontoken)
++ return (ISC_TRUE);
++ else if (rsa1->ontoken || rsa2->ontoken ||
++ (rsa1->object != rsa2->object))
++ return (ISC_FALSE);
++
++ return (ISC_TRUE);
++}
++
++static isc_result_t
++pkcs11rsa_generate(dst_key_t *key, int exp, void (*callback)(int)) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
++ CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
++ CK_ULONG bits = 0;
++ CK_BYTE pubexp[5];
++ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_RSA;
++ CK_ATTRIBUTE pubTemplate[] =
++ {
++ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) },
++ { CKA_PUBLIC_EXPONENT, &pubexp, (CK_ULONG) sizeof(pubexp) }
++ };
++ CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
++ CK_ATTRIBUTE privTemplate[] =
++ {
++ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ };
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *rsa;
++ pk11_context_t *pk11_ctx;
++ isc_result_t ret;
++ unsigned int i;
++
++ UNUSED(callback);
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ return (ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, pk11_get_best_token(OP_RSA));
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ bits = key->key_size;
++ if (exp == 0) {
++ /* RSA_F4 0x10001 */
++ pubexp[0] = 1;
++ pubexp[1] = 0;
++ pubexp[2] = 1;
++ pubTemplate[6].ulValueLen = 3;
++ } else {
++ /* F5 0x100000001 */
++ pubexp[0] = 1;
++ pubexp[1] = 0;
++ pubexp[2] = 0;
++ pubexp[3] = 0;
++ pubexp[4] = 1;
++ pubTemplate[6].ulValueLen = 5;
++ }
++
++ PK11_RET(pkcs_C_GenerateKeyPair,
++ (pk11_ctx->session, &mech,
++ pubTemplate, (CK_ULONG) 7,
++ privTemplate, (CK_ULONG) 7,
++ &pub, &priv),
++ DST_R_CRYPTOFAILURE);
++
++ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
++ if (rsa == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(rsa, 0, sizeof(*rsa));
++ key->keydata.pkey = rsa;
++ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
++ if (rsa->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(rsa->repr, 0, sizeof(*attr) * 8);
++ rsa->attrcnt = 8;
++
++ attr = rsa->repr;
++ attr[0].type = CKA_MODULUS;
++ attr[1].type = CKA_PUBLIC_EXPONENT;
++ attr[2].type = CKA_PRIVATE_EXPONENT;
++ attr[3].type = CKA_PRIME_1;
++ attr[4].type = CKA_PRIME_2;
++ attr[5].type = CKA_EXPONENT_1;
++ attr[6].type = CKA_EXPONENT_2;
++ attr[7].type = CKA_COEFFICIENT;
++
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 2),
++ DST_R_CRYPTOFAILURE);
++ for (i = 0; i <= 1; i++) {
++ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
++ if (attr[i].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr[i].pValue, 0, attr[i].ulValueLen);
++ }
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, pub, attr, 2),
++ DST_R_CRYPTOFAILURE);
++
++ attr += 2;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 6),
++ DST_R_CRYPTOFAILURE);
++ for (i = 0; i <= 5; i++) {
++ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
++ if (attr[i].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr[i].pValue, 0, attr[i].ulValueLen);
++ }
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, priv, attr, 6),
++ DST_R_CRYPTOFAILURE);
++
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11rsa_destroy(key);
++ if (priv != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
++ if (pub != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ret);
++}
++
++static isc_boolean_t
++pkcs11rsa_isprivate(const dst_key_t *key) {
++ pk11_object_t *rsa = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (rsa == NULL)
++ return (ISC_FALSE);
++ attr = pk11_attribute_bytype(rsa, CKA_PRIVATE_EXPONENT);
++ return (ISC_TF((attr != NULL) || rsa->ontoken));
++}
++
++static void
++pkcs11rsa_destroy(dst_key_t *key) {
++ pk11_object_t *rsa = key->keydata.pkey;
++ CK_ATTRIBUTE *attr;
++
++ if (rsa == NULL)
++ return;
++
++ INSIST((rsa->object == CK_INVALID_HANDLE) || rsa->ontoken);
++
++ for (attr = pk11_attribute_first(rsa);
++ attr != NULL;
++ attr = pk11_attribute_next(rsa, attr))
++ switch (attr->type) {
++ case CKA_LABEL:
++ case CKA_ID:
++ case CKA_MODULUS:
++ case CKA_PUBLIC_EXPONENT:
++ case CKA_PRIVATE_EXPONENT:
++ case CKA_PRIME_1:
++ case CKA_PRIME_2:
++ case CKA_EXPONENT_1:
++ case CKA_EXPONENT_2:
++ case CKA_COEFFICIENT:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (rsa->repr != NULL) {
++ memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ rsa->repr,
++ rsa->attrcnt * sizeof(*attr));
++ }
++ memset(rsa, 0, sizeof(*rsa));
++ isc_mem_put(key->mctx, rsa, sizeof(*rsa));
++ key->keydata.pkey = NULL;
++}
++
++static isc_result_t
++pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *rsa;
++ CK_ATTRIBUTE *attr;
++ isc_region_t r;
++ unsigned int e_bytes = 0, mod_bytes = 0;
++ CK_BYTE *exponent = NULL, *modulus = NULL;
++
++ REQUIRE(key->keydata.pkey != NULL);
++
++ rsa = key->keydata.pkey;
++
++ for (attr = pk11_attribute_first(rsa);
++ attr != NULL;
++ attr = pk11_attribute_next(rsa, attr))
++ switch (attr->type) {
++ case CKA_PUBLIC_EXPONENT:
++ exponent = (CK_BYTE *) attr->pValue;
++ e_bytes = (unsigned int) attr->ulValueLen;
++ break;
++ case CKA_MODULUS:
++ modulus = (CK_BYTE *) attr->pValue;
++ mod_bytes = (unsigned int) attr->ulValueLen;
++ break;
++ }
++ REQUIRE((exponent != NULL) && (modulus != NULL));
++
++ isc_buffer_availableregion(data, &r);
++
++ if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */
++ if (r.length < 1)
++ return (ISC_R_NOSPACE);
++ isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
++ isc_region_consume(&r, 1);
++ } else {
++ if (r.length < 3)
++ return (ISC_R_NOSPACE);
++ isc_buffer_putuint8(data, 0);
++ isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
++ isc_region_consume(&r, 3);
++ }
++
++ if (r.length < e_bytes + mod_bytes)
++ return (ISC_R_NOSPACE);
++
++ memcpy(r.base, exponent, e_bytes);
++ isc_region_consume(&r, e_bytes);
++ memcpy(r.base, modulus, mod_bytes);
++
++ isc_buffer_add(data, e_bytes + mod_bytes);
++
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
++ pk11_object_t *rsa;
++ isc_region_t r;
++ unsigned int e_bytes, mod_bytes;
++ CK_BYTE *exponent = NULL, *modulus = NULL;
++ CK_ATTRIBUTE *attr;
++
++ isc_buffer_remainingregion(data, &r);
++ if (r.length == 0)
++ return (ISC_R_SUCCESS);
++
++ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
++ if (rsa == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(rsa, 0, sizeof(*rsa));
++
++ if (r.length < 1) {
++ memset(rsa, 0, sizeof(*rsa));
++ isc_mem_put(key->mctx, rsa, sizeof(*rsa));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ e_bytes = *r.base++;
++ r.length--;
++
++ if (e_bytes == 0) {
++ if (r.length < 2) {
++ memset(rsa, 0, sizeof(*rsa));
++ isc_mem_put(key->mctx, rsa, sizeof(*rsa));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ e_bytes = ((*r.base++) << 8);
++ e_bytes += *r.base++;
++ r.length -= 2;
++ }
++
++ if (r.length < e_bytes) {
++ memset(rsa, 0, sizeof(*rsa));
++ isc_mem_put(key->mctx, rsa, sizeof(*rsa));
++ return (DST_R_INVALIDPUBLICKEY);
++ }
++ exponent = r.base;
++ r.base += e_bytes;
++ r.length -= e_bytes;
++ modulus = r.base;
++ mod_bytes = r.length;
++
++ key->key_size = pk11_numbits(modulus, mod_bytes);
++
++ isc_buffer_forward(data, r.length);
++
++ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
++ if (rsa->repr == NULL)
++ goto nomemory;
++ memset(rsa->repr, 0, sizeof(*attr) * 2);
++ rsa->attrcnt = 2;
++ attr = rsa->repr;
++ attr[0].type = CKA_MODULUS;
++ attr[0].pValue = isc_mem_get(key->mctx, mod_bytes);
++ if (attr[0].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[0].pValue, modulus, mod_bytes);
++ attr[0].ulValueLen = (CK_ULONG) mod_bytes;
++ attr[1].type = CKA_PUBLIC_EXPONENT;
++ attr[1].pValue = isc_mem_get(key->mctx, e_bytes);
++ if (attr[1].pValue == NULL)
++ goto nomemory;
++ memcpy(attr[1].pValue, exponent, e_bytes);
++ attr[1].ulValueLen = (CK_ULONG) e_bytes;
++
++ key->keydata.pkey = rsa;
++
++ return (ISC_R_SUCCESS);
++
++ nomemory:
++ for (attr = pk11_attribute_first(rsa);
++ attr != NULL;
++ attr = pk11_attribute_next(rsa, attr))
++ switch (attr->type) {
++ case CKA_MODULUS:
++ case CKA_PUBLIC_EXPONENT:
++ if (attr->pValue != NULL) {
++ memset(attr->pValue, 0, attr->ulValueLen);
++ isc_mem_put(key->mctx,
++ attr->pValue,
++ attr->ulValueLen);
++ }
++ break;
++ }
++ if (rsa->repr != NULL) {
++ memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr));
++ isc_mem_put(key->mctx,
++ rsa->repr,
++ rsa->attrcnt * sizeof(*attr));
++ }
++ memset(rsa, 0, sizeof(*rsa));
++ isc_mem_put(key->mctx, rsa, sizeof(*rsa));
++ return (ISC_R_NOMEMORY);
++}
++
++static isc_result_t
++pkcs11rsa_tofile(const dst_key_t *key, const char *directory) {
++ int i;
++ pk11_object_t *rsa;
++ CK_ATTRIBUTE *attr;
++ CK_ATTRIBUTE *modulus = NULL, *exponent = NULL;
++ CK_ATTRIBUTE *d = NULL, *p = NULL, *q = NULL;
++ CK_ATTRIBUTE *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
++ dst_private_t priv;
++ unsigned char *bufs[10];
++ isc_result_t result;
++
++ if (key->keydata.pkey == NULL)
++ return (DST_R_NULLKEY);
++
++ if (key->external) {
++ priv.nelements = 0;
++ return (dst__privstruct_writefile(key, &priv, directory));
++ }
++
++ rsa = key->keydata.pkey;
++
++ for (attr = pk11_attribute_first(rsa);
++ attr != NULL;
++ attr = pk11_attribute_next(rsa, attr))
++ switch (attr->type) {
++ case CKA_MODULUS:
++ modulus = attr;
++ break;
++ case CKA_PUBLIC_EXPONENT:
++ exponent = attr;
++ break;
++ case CKA_PRIVATE_EXPONENT:
++ d = attr;
++ break;
++ case CKA_PRIME_1:
++ p = attr;
++ break;
++ case CKA_PRIME_2:
++ q = attr;
++ break;
++ case CKA_EXPONENT_1:
++ dmp1 = attr;
++ break;
++ case CKA_EXPONENT_2:
++ dmq1 = attr;
++ break;
++ case CKA_COEFFICIENT:
++ iqmp = attr;
++ break;
++ }
++ if ((modulus == NULL) || (exponent == NULL))
++ return (DST_R_NULLKEY);
++
++ memset(bufs, 0, sizeof(bufs));
++
++ for (i = 0; i < 10; i++) {
++ bufs[i] = isc_mem_get(key->mctx, modulus->ulValueLen);
++ if (bufs[i] == NULL) {
++ result = ISC_R_NOMEMORY;
++ goto fail;
++ }
++ memset(bufs[i], 0, modulus->ulValueLen);
++ }
++
++ i = 0;
++
++ priv.elements[i].tag = TAG_RSA_MODULUS;
++ priv.elements[i].length = (unsigned short) modulus->ulValueLen;
++ memcpy(bufs[i], modulus->pValue, modulus->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++
++ priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
++ priv.elements[i].length = (unsigned short) exponent->ulValueLen;
++ memcpy(bufs[i], exponent->pValue, exponent->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++
++ if (d != NULL) {
++ priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
++ priv.elements[i].length = (unsigned short) d->ulValueLen;
++ memcpy(bufs[i], d->pValue, d->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++ }
++
++ if (p != NULL) {
++ priv.elements[i].tag = TAG_RSA_PRIME1;
++ priv.elements[i].length = (unsigned short) p->ulValueLen;
++ memcpy(bufs[i], p->pValue, p->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++ }
++
++ if (q != NULL) {
++ priv.elements[i].tag = TAG_RSA_PRIME2;
++ priv.elements[i].length = (unsigned short) q->ulValueLen;
++ memcpy(bufs[i], q->pValue, q->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++ }
++
++ if (dmp1 != NULL) {
++ priv.elements[i].tag = TAG_RSA_EXPONENT1;
++ priv.elements[i].length = (unsigned short) dmp1->ulValueLen;
++ memcpy(bufs[i], dmp1->pValue, dmp1->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++ }
++
++ if (dmq1 != NULL) {
++ priv.elements[i].tag = TAG_RSA_EXPONENT2;
++ priv.elements[i].length = (unsigned short) dmq1->ulValueLen;
++ memcpy(bufs[i], dmq1->pValue, dmq1->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++ }
++
++ if (iqmp != NULL) {
++ priv.elements[i].tag = TAG_RSA_COEFFICIENT;
++ priv.elements[i].length = (unsigned short) iqmp->ulValueLen;
++ memcpy(bufs[i], iqmp->pValue, iqmp->ulValueLen);
++ priv.elements[i].data = bufs[i];
++ i++;
++ }
++
++ if (key->engine != NULL) {
++ priv.elements[i].tag = TAG_RSA_ENGINE;
++ priv.elements[i].length = strlen(key->engine) + 1;
++ priv.elements[i].data = (unsigned char *)key->engine;
++ i++;
++ }
++
++ if (key->label != NULL) {
++ priv.elements[i].tag = TAG_RSA_LABEL;
++ priv.elements[i].length = strlen(key->label) + 1;
++ priv.elements[i].data = (unsigned char *)key->label;
++ i++;
++ }
++
++ priv.nelements = i;
++ result = dst__privstruct_writefile(key, &priv, directory);
++ fail:
++ for (i = 0; i < 10; i++) {
++ if (bufs[i] == NULL)
++ break;
++ memset(bufs[i], 0, modulus->ulValueLen);
++ isc_mem_put(key->mctx, bufs[i], modulus->ulValueLen);
++ }
++ return (result);
++}
++
++static isc_result_t
++pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label,
++ dst_key_t *pub)
++{
++ CK_RV rv;
++ CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE keyType = CKK_RSA;
++ CK_ATTRIBUTE searchTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_LABEL, NULL, 0 }
++ };
++ CK_ULONG cnt;
++ CK_ATTRIBUTE *attr;
++ CK_ATTRIBUTE *pubattr;
++ pk11_object_t *rsa;
++ pk11_object_t *pubrsa;
++ pk11_context_t *pk11_ctx = NULL;
++ isc_result_t ret;
++
++ if (label == NULL)
++ return (DST_R_NOENGINE);
++
++ rsa = key->keydata.pkey;
++ pubrsa = pub->keydata.pkey;
++
++ rsa->object = CK_INVALID_HANDLE;
++ rsa->ontoken = ISC_TRUE;
++ rsa->reqlogon = ISC_TRUE;
++ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
++ if (rsa->repr == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(rsa->repr, 0, sizeof(*attr) * 2);
++ rsa->attrcnt = 2;
++ attr = rsa->repr;
++
++ attr->type = CKA_MODULUS;
++ pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
++ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
++ attr->ulValueLen = pubattr->ulValueLen;
++ attr++;
++
++ attr->type = CKA_PUBLIC_EXPONENT;
++ pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
++ attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
++ if (attr->pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
++ attr->ulValueLen = pubattr->ulValueLen;
++
++ ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
++ rsa->reqlogon, NULL, rsa->slot);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ attr = pk11_attribute_bytype(rsa, CKA_LABEL);
++ if (attr == NULL) {
++ attr = pk11_attribute_bytype(rsa, CKA_ID);
++ INSIST(attr != NULL);
++ searchTemplate[3].type = CKA_ID;
++ }
++ searchTemplate[3].pValue = attr->pValue;
++ searchTemplate[3].ulValueLen = attr->ulValueLen;
++
++ PK11_RET(pkcs_C_FindObjectsInit,
++ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_FindObjects,
++ (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
++ DST_R_CRYPTOFAILURE);
++ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
++ if (cnt == 0)
++ DST_RET(ISC_R_NOTFOUND);
++ if (cnt > 1)
++ DST_RET(ISC_R_EXISTS);
++
++ if (engine != NULL) {
++ key->engine = isc_mem_strdup(key->mctx, engine);
++ if (key->engine == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ }
++
++ key->label = isc_mem_strdup(key->mctx, label);
++ if (key->label == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
++ INSIST(attr != NULL);
++ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ if (pk11_ctx != NULL) {
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ }
++
++ return (ret);
++}
++
++static isc_result_t
++rsa_check(pk11_object_t *rsa, pk11_object_t *pubrsa) {
++ CK_ATTRIBUTE *pubattr, *privattr;
++ CK_BYTE *priv_exp = NULL, *priv_mod = NULL;
++ CK_BYTE *pub_exp = NULL, *pub_mod = NULL;
++ unsigned int priv_explen = 0, priv_modlen = 0;
++ unsigned int pub_explen = 0, pub_modlen = 0;
++
++ REQUIRE(rsa != NULL && pubrsa != NULL);
++
++ privattr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
++ INSIST(privattr != NULL);
++ priv_exp = privattr->pValue;
++ priv_explen = privattr->ulValueLen;
++
++ pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
++ INSIST(pubattr != NULL);
++ pub_exp = pubattr->pValue;
++ pub_explen = pubattr->ulValueLen;
++
++ if (priv_exp != NULL) {
++ if (priv_explen != pub_explen)
++ return (DST_R_INVALIDPRIVATEKEY);
++ if (memcmp(priv_exp, pub_exp, pub_explen) != 0)
++ return (DST_R_INVALIDPRIVATEKEY);
++ } else {
++ privattr->pValue = pub_exp;
++ privattr->ulValueLen = pub_explen;
++ pubattr->pValue = NULL;
++ pubattr->ulValueLen = 0;
++ }
++
++ if (privattr->pValue == NULL)
++ return (DST_R_INVALIDPRIVATEKEY);
++
++ privattr = pk11_attribute_bytype(rsa, CKA_MODULUS);
++ INSIST(privattr != NULL);
++ priv_mod = privattr->pValue;
++ priv_modlen = privattr->ulValueLen;
++
++ pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
++ INSIST(pubattr != NULL);
++ pub_mod = pubattr->pValue;
++ pub_modlen = pubattr->ulValueLen;
++
++ if (priv_mod != NULL) {
++ if (priv_modlen != pub_modlen)
++ return (DST_R_INVALIDPRIVATEKEY);
++ if (memcmp(priv_mod, pub_mod, pub_modlen) != 0)
++ return (DST_R_INVALIDPRIVATEKEY);
++ } else {
++ privattr->pValue = pub_mod;
++ privattr->ulValueLen = pub_modlen;
++ pubattr->pValue = NULL;
++ pubattr->ulValueLen = 0;
++ }
++
++ if (privattr->pValue == NULL)
++ return (DST_R_INVALIDPRIVATEKEY);
++
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
++ dst_private_t priv;
++ isc_result_t ret;
++ int i;
++ pk11_object_t *rsa;
++ CK_ATTRIBUTE *attr;
++ isc_mem_t *mctx = key->mctx;
++ const char *engine = NULL, *label = NULL;
++
++ /* read private key file */
++ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ if (key->external) {
++ if (priv.nelements != 0)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++ if (pub == NULL)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ key->keydata.pkey = pub->keydata.pkey;
++ pub->keydata.pkey = NULL;
++ key->key_size = pub->key_size;
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++ }
++
++ for (i = 0; i < priv.nelements; i++) {
++ switch (priv.elements[i].tag) {
++ case TAG_RSA_ENGINE:
++ engine = (char *)priv.elements[i].data;
++ break;
++ case TAG_RSA_LABEL:
++ label = (char *)priv.elements[i].data;
++ break;
++ default:
++ break;
++ }
++ }
++ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
++ if (rsa == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(rsa, 0, sizeof(*rsa));
++ key->keydata.pkey = rsa;
++
++ /* Is this key is stored in a HSM? See if we can fetch it. */
++ if ((label != NULL) || (engine != NULL)) {
++ ret = pkcs11rsa_fetch(key, engine, label, pub);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++ }
++
++ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
++ if (rsa->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(rsa->repr, 0, sizeof(*attr) * 8);
++ rsa->attrcnt = 8;
++ attr = rsa->repr;
++ attr[0].type = CKA_MODULUS;
++ attr[1].type = CKA_PUBLIC_EXPONENT;
++ attr[2].type = CKA_PRIVATE_EXPONENT;
++ attr[3].type = CKA_PRIME_1;
++ attr[4].type = CKA_PRIME_2;
++ attr[5].type = CKA_EXPONENT_1;
++ attr[6].type = CKA_EXPONENT_2;
++ attr[7].type = CKA_COEFFICIENT;
++
++ for (i = 0; i < priv.nelements; i++) {
++ CK_BYTE *bn;
++
++ switch (priv.elements[i].tag) {
++ case TAG_RSA_ENGINE:
++ continue;
++ case TAG_RSA_LABEL:
++ continue;
++ default:
++ bn = isc_mem_get(key->mctx, priv.elements[i].length);
++ if (bn == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memcpy(bn,
++ priv.elements[i].data,
++ priv.elements[i].length);
++ }
++
++ switch (priv.elements[i].tag) {
++ case TAG_RSA_MODULUS:
++ attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_PUBLICEXPONENT:
++ attr = pk11_attribute_bytype(rsa,
++ CKA_PUBLIC_EXPONENT);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_PRIVATEEXPONENT:
++ attr = pk11_attribute_bytype(rsa,
++ CKA_PRIVATE_EXPONENT);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_PRIME1:
++ attr = pk11_attribute_bytype(rsa, CKA_PRIME_1);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_PRIME2:
++ attr = pk11_attribute_bytype(rsa, CKA_PRIME_2);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_EXPONENT1:
++ attr = pk11_attribute_bytype(rsa,
++ CKA_EXPONENT_1);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_EXPONENT2:
++ attr = pk11_attribute_bytype(rsa,
++ CKA_EXPONENT_2);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ case TAG_RSA_COEFFICIENT:
++ attr = pk11_attribute_bytype(rsa,
++ CKA_COEFFICIENT);
++ INSIST(attr != NULL);
++ attr->pValue = bn;
++ attr->ulValueLen = priv.elements[i].length;
++ break;
++ }
++ }
++
++ if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS)
++ DST_RET(DST_R_INVALIDPRIVATEKEY);
++
++ attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
++ INSIST(attr != NULL);
++ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
++
++ attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
++ INSIST(attr != NULL);
++ if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
++ DST_RET(ISC_R_RANGE);
++
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11rsa_destroy(key);
++ dst__privstruct_free(&priv, mctx);
++ memset(&priv, 0, sizeof(priv));
++ return (ret);
++}
++
++static isc_result_t
++pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
++ const char *pin)
++{
++ CK_RV rv;
++ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE keyType = CKK_RSA;
++ CK_ATTRIBUTE searchTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_LABEL, NULL, 0 }
++ };
++ CK_ULONG cnt;
++ CK_ATTRIBUTE *attr;
++ pk11_object_t *rsa;
++ pk11_context_t *pk11_ctx = NULL;
++ isc_result_t ret;
++ unsigned int i;
++
++ UNUSED(pin);
++
++ rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
++ if (rsa == NULL)
++ return (ISC_R_NOMEMORY);
++ memset(rsa, 0, sizeof(*rsa));
++ rsa->object = CK_INVALID_HANDLE;
++ rsa->ontoken = ISC_TRUE;
++ rsa->reqlogon = ISC_TRUE;
++ key->keydata.pkey = rsa;
++
++ rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
++ if (rsa->repr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(rsa->repr, 0, sizeof(*attr) * 2);
++ rsa->attrcnt = 2;
++ attr = rsa->repr;
++ attr[0].type = CKA_MODULUS;
++ attr[1].type = CKA_PUBLIC_EXPONENT;
++
++ ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
++ sizeof(*pk11_ctx));
++ if (pk11_ctx == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
++ rsa->reqlogon, NULL, rsa->slot);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++
++ attr = pk11_attribute_bytype(rsa, CKA_LABEL);
++ if (attr == NULL) {
++ attr = pk11_attribute_bytype(rsa, CKA_ID);
++ INSIST(attr != NULL);
++ searchTemplate[3].type = CKA_ID;
++ }
++ searchTemplate[3].pValue = attr->pValue;
++ searchTemplate[3].ulValueLen = attr->ulValueLen;
++
++ PK11_RET(pkcs_C_FindObjectsInit,
++ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_FindObjects,
++ (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
++ DST_R_CRYPTOFAILURE);
++ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
++ if (cnt == 0)
++ DST_RET(ISC_R_NOTFOUND);
++ if (cnt > 1)
++ DST_RET(ISC_R_EXISTS);
++
++ attr = rsa->repr;
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, hKey, attr, 2),
++ DST_R_CRYPTOFAILURE);
++ for (i = 0; i <= 1; i++) {
++ attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
++ if (attr[i].pValue == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ memset(attr[i].pValue, 0, attr[i].ulValueLen);
++ }
++ PK11_RET(pkcs_C_GetAttributeValue,
++ (pk11_ctx->session, hKey, attr, 2),
++ DST_R_CRYPTOFAILURE);
++
++ keyClass = CKO_PRIVATE_KEY;
++ PK11_RET(pkcs_C_FindObjectsInit,
++ (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
++ DST_R_CRYPTOFAILURE);
++ PK11_RET(pkcs_C_FindObjects,
++ (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
++ DST_R_CRYPTOFAILURE);
++ (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
++ if (cnt == 0)
++ DST_RET(ISC_R_NOTFOUND);
++ if (cnt > 1)
++ DST_RET(ISC_R_EXISTS);
++
++ if (engine != NULL) {
++ key->engine = isc_mem_strdup(key->mctx, engine);
++ if (key->engine == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ }
++
++ key->label = isc_mem_strdup(key->mctx, label);
++ if (key->label == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++
++ attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
++ INSIST(attr != NULL);
++ if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
++ DST_RET(ISC_R_RANGE);
++
++ attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
++ INSIST(attr != NULL);
++ key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
++
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++
++ return (ISC_R_SUCCESS);
++
++ err:
++ pkcs11rsa_destroy(key);
++ if (pk11_ctx != NULL) {
++ pk11_return_session(pk11_ctx);
++ memset(pk11_ctx, 0, sizeof(*pk11_ctx));
++ isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
++ }
++
++ return (ret);
++}
++
++static dst_func_t pkcs11rsa_functions = {
++ pkcs11rsa_createctx,
++ pkcs11rsa_createctx2,
++ pkcs11rsa_destroyctx,
++ pkcs11rsa_adddata,
++ pkcs11rsa_sign,
++ pkcs11rsa_verify,
++ NULL, /*%< verify2 */
++ NULL, /*%< computesecret */
++ pkcs11rsa_compare,
++ NULL, /*%< paramcompare */
++ pkcs11rsa_generate,
++ pkcs11rsa_isprivate,
++ pkcs11rsa_destroy,
++ pkcs11rsa_todns,
++ pkcs11rsa_fromdns,
++ pkcs11rsa_tofile,
++ pkcs11rsa_parse,
++ NULL, /*%< cleanup */
++ pkcs11rsa_fromlabel,
++ NULL, /*%< dump */
++ NULL, /*%< restore */
++};
++
++isc_result_t
++dst__pkcs11rsa_init(dst_func_t **funcp) {
++ REQUIRE(funcp != NULL);
++
++ if (*funcp == NULL)
++ *funcp = &pkcs11rsa_functions;
++ return (ISC_R_SUCCESS);
++}
++
++#else /* PKCS11CRYPTO */
++
++#include <isc/util.h>
++
++EMPTY_TRANSLATION_UNIT
++
++#endif /* PKCS11CRYPTO */
++/*! \file */
+diff -up bind-9.9.6/lib/dns/rdata/generic/dlv_32769.c.native_pkcs11 bind-9.9.6/lib/dns/rdata/generic/dlv_32769.c
+--- bind-9.9.6/lib/dns/rdata/generic/dlv_32769.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/rdata/generic/dlv_32769.c 2014-10-09 13:30:47.829302927 +0200
+@@ -28,6 +28,7 @@
+
+ #include <dns/ds.h>
+
++#include "dst_gost.h"
+
+ static inline isc_result_t
+ fromtext_dlv(ARGS_FROMTEXT) {
+@@ -81,9 +82,11 @@ fromtext_dlv(ARGS_FROMTEXT) {
+ case DNS_DSDIGEST_SHA256:
+ length = ISC_SHA256_DIGESTLENGTH;
+ break;
++#ifdef ISC_GOST_DIGESTLENGTH
+ case DNS_DSDIGEST_GOST:
+ length = ISC_GOST_DIGESTLENGTH;
+ break;
++#endif
+ case DNS_DSDIGEST_SHA384:
+ length = ISC_SHA384_DIGESTLENGTH;
+ break;
+@@ -168,8 +171,10 @@ fromwire_dlv(ARGS_FROMWIRE) {
+ sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
++#ifdef ISC_GOST_DIGESTLENGTH
+ (sr.base[3] == DNS_DSDIGEST_GOST &&
+ sr.length < 4 + ISC_GOST_DIGESTLENGTH) ||
++#endif
+ (sr.base[3] == DNS_DSDIGEST_SHA384 &&
+ sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
+ return (ISC_R_UNEXPECTEDEND);
+@@ -183,8 +188,10 @@ fromwire_dlv(ARGS_FROMWIRE) {
+ sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+ sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
++#ifdef ISC_GOST_DIGESTLENGTH
+ else if (sr.base[3] == DNS_DSDIGEST_GOST)
+ sr.length = 4 + ISC_GOST_DIGESTLENGTH;
++#endif
+ else if (sr.base[3] == DNS_DSDIGEST_SHA384)
+ sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
+
+@@ -236,9 +243,11 @@ fromstruct_dlv(ARGS_FROMSTRUCT) {
+ case DNS_DSDIGEST_SHA256:
+ REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH);
+ break;
++#ifdef ISC_GOST_DIGESTLENGTH
+ case DNS_DSDIGEST_GOST:
+ REQUIRE(dlv->length == ISC_GOST_DIGESTLENGTH);
+ break;
++#endif
+ case DNS_DSDIGEST_SHA384:
+ REQUIRE(dlv->length == ISC_SHA384_DIGESTLENGTH);
+ break;
+diff -up bind-9.9.6/lib/dns/rdata/generic/ds_43.c.native_pkcs11 bind-9.9.6/lib/dns/rdata/generic/ds_43.c
+--- bind-9.9.6/lib/dns/rdata/generic/ds_43.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/rdata/generic/ds_43.c 2014-10-09 13:30:47.830302928 +0200
+@@ -30,6 +30,8 @@
+
+ #include <dns/ds.h>
+
++#include "dst_gost.h"
++
+ static inline isc_result_t
+ fromtext_ds(ARGS_FROMTEXT) {
+ isc_token_t token;
+@@ -81,9 +83,11 @@ fromtext_ds(ARGS_FROMTEXT) {
+ case DNS_DSDIGEST_SHA256:
+ length = ISC_SHA256_DIGESTLENGTH;
+ break;
++#ifdef ISC_GOST_DIGESTLENGTH
+ case DNS_DSDIGEST_GOST:
+ length = ISC_GOST_DIGESTLENGTH;
+ break;
++#endif
+ case DNS_DSDIGEST_SHA384:
+ length = ISC_SHA384_DIGESTLENGTH;
+ break;
+@@ -168,8 +172,10 @@ fromwire_ds(ARGS_FROMWIRE) {
+ sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH) ||
++#ifdef ISC_GOST_DIGESTLENGTH
+ (sr.base[3] == DNS_DSDIGEST_GOST &&
+ sr.length < 4 + ISC_GOST_DIGESTLENGTH) ||
++#endif
+ (sr.base[3] == DNS_DSDIGEST_SHA384 &&
+ sr.length < 4 + ISC_SHA384_DIGESTLENGTH))
+ return (ISC_R_UNEXPECTEDEND);
+@@ -183,8 +189,10 @@ fromwire_ds(ARGS_FROMWIRE) {
+ sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+ sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
++#ifdef ISC_GOST_DIGESTLENGTH
+ else if (sr.base[3] == DNS_DSDIGEST_GOST)
+ sr.length = 4 + ISC_GOST_DIGESTLENGTH;
++#endif
+ else if (sr.base[3] == DNS_DSDIGEST_SHA384)
+ sr.length = 4 + ISC_SHA384_DIGESTLENGTH;
+
+@@ -236,9 +244,11 @@ fromstruct_ds(ARGS_FROMSTRUCT) {
+ case DNS_DSDIGEST_SHA256:
+ REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
+ break;
++#ifdef ISC_GOST_DIGESTLENGTH
+ case DNS_DSDIGEST_GOST:
+ REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH);
+ break;
++#endif
+ case DNS_DSDIGEST_SHA384:
+ REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH);
+ break;
+diff -up bind-9.9.6/lib/dns/tests/gost_test.c.native_pkcs11 bind-9.9.6/lib/dns/tests/gost_test.c
+--- bind-9.9.6/lib/dns/tests/gost_test.c.native_pkcs11 2014-10-09 13:30:47.831302930 +0200
++++ bind-9.9.6/lib/dns/tests/gost_test.c 2014-10-09 13:30:47.831302930 +0200
+@@ -0,0 +1,232 @@
++/*
++ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++/* ! \file */
++
++#include <config.h>
++
++#include <atf-c.h>
++
++#include <stdio.h>
++#include <string.h>
++
++#include <isc/util.h>
++#include <isc/string.h>
++
++#include "dnstest.h"
++
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
++
++#include "../dst_gost.h"
++
++/*
++ * Test data from Wikipedia GOST (hash function)
++ */
++
++unsigned char digest[ISC_GOST_DIGESTLENGTH];
++unsigned char buffer[1024];
++const char *s;
++char str[ISC_GOST_DIGESTLENGTH];
++int i = 0;
++
++isc_result_t
++tohexstr(unsigned char *d, unsigned int len, char *out);
++/*
++ * Precondition: a hexadecimal number in *d, the length of that number in len,
++ * and a pointer to a character array to put the output (*out).
++ * Postcondition: A String representation of the given hexadecimal number is
++ * placed into the array *out
++ *
++ * 'out' MUST point to an array of at least len / 2 + 1
++ *
++ * Return values: ISC_R_SUCCESS if the operation is sucessful
++ */
++
++isc_result_t
++tohexstr(unsigned char *d, unsigned int len, char *out) {
++
++ out[0]='\0';
++ char c_ret[] = "AA";
++ unsigned int i;
++ strcat(out, "0x");
++ for (i = 0; i < len; i++) {
++ sprintf(c_ret, "%02X", d[i]);
++ strcat(out, c_ret);
++ }
++ strcat(out, "\0");
++ return (ISC_R_SUCCESS);
++}
++
++
++#define TEST_INPUT(x) (x), sizeof(x)-1
++
++typedef struct hash_testcase {
++ const char *input;
++ size_t input_len;
++ const char *result;
++ int repeats;
++} hash_testcase_t;
++
++ATF_TC(isc_gost);
++ATF_TC_HEAD(isc_gost, tc) {
++ atf_tc_set_md_var(tc, "descr",
++ "GOST R 34.11-94 examples from Wikipedia");
++}
++ATF_TC_BODY(isc_gost, tc) {
++ isc_gost_t gost;
++ isc_result_t result;
++
++ UNUSED(tc);
++
++ /*
++ * These are the various test vectors. All of these are passed
++ * through the hash function and the results are compared to the
++ * result specified here.
++ */
++ hash_testcase_t testcases[] = {
++ /* Test 1 */
++ {
++ TEST_INPUT(""),
++ "0x981E5F3CA30C841487830F84FB433E1"
++ "3AC1101569B9C13584AC483234CD656C0",
++ 1
++ },
++ /* Test 2 */
++ {
++ TEST_INPUT("a"),
++ "0xE74C52DD282183BF37AF0079C9F7805"
++ "5715A103F17E3133CEFF1AACF2F403011",
++ 1
++ },
++ /* Test 3 */
++ {
++ TEST_INPUT("abc"),
++ "0xB285056DBF18D7392D7677369524DD1"
++ "4747459ED8143997E163B2986F92FD42C",
++ 1
++ },
++ /* Test 4 */
++ {
++ TEST_INPUT("message digest"),
++ "0xBC6041DD2AA401EBFA6E9886734174F"
++ "EBDB4729AA972D60F549AC39B29721BA0",
++ 1
++ },
++ /* Test 5 */
++ {
++ TEST_INPUT("The quick brown fox jumps "
++ "over the lazy dog"),
++ "0x9004294A361A508C586FE53D1F1B027"
++ "46765E71B765472786E4770D565830A76",
++ 1
++ },
++ /* Test 6 */
++ {
++ TEST_INPUT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcde"
++ "fghijklmnopqrstuvwxyz0123456789"),
++ "0x73B70A39497DE53A6E08C67B6D4DB85"
++ "3540F03E9389299D9B0156EF7E85D0F61",
++ 1
++ },
++ /* Test 7 */
++ {
++ TEST_INPUT("1234567890123456789012345678901"
++ "2345678901234567890123456789012"
++ "345678901234567890"),
++ "0x6BC7B38989B28CF93AE8842BF9D7529"
++ "05910A7528A61E5BCE0782DE43E610C90",
++ 1
++ },
++ /* Test 8 */
++ {
++ TEST_INPUT("This is message, length=32 bytes"),
++ "0x2CEFC2F7B7BDC514E18EA57FA74FF35"
++ "7E7FA17D652C75F69CB1BE7893EDE48EB",
++ 1
++ },
++ /* Test 9 */
++ {
++ TEST_INPUT("Suppose the original message "
++ "has length = 50 bytes"),
++ "0xC3730C5CBCCACF915AC292676F21E8B"
++ "D4EF75331D9405E5F1A61DC3130A65011",
++ 1
++ },
++ /* Test 10 */
++ {
++ TEST_INPUT("U") /* times 128 */,
++ "0x1C4AC7614691BBF427FA2316216BE8F"
++ "10D92EDFD37CD1027514C1008F649C4E8",
++ 128
++ },
++ /* Test 11 */
++ {
++ TEST_INPUT("a") /* times 1000000 */,
++ "0x8693287AA62F9478F7CB312EC0866B6"
++ "C4E4A0F11160441E8F4FFCD2715DD554F",
++ 1000000
++ },
++ { NULL, 0, NULL, 1 }
++ };
++
++ result = dns_test_begin(NULL, ISC_FALSE);
++ ATF_REQUIRE(result == ISC_R_SUCCESS);
++
++ hash_testcase_t *testcase = testcases;
++
++ while (testcase->input != NULL && testcase->result != NULL) {
++ result = isc_gost_init(&gost);
++ ATF_REQUIRE(result == ISC_R_SUCCESS);
++ for(i = 0; i < testcase->repeats; i++) {
++ result = isc_gost_update(&gost,
++ (const isc_uint8_t *) testcase->input,
++ testcase->input_len);
++ ATF_REQUIRE(result == ISC_R_SUCCESS);
++ }
++ result = isc_gost_final(&gost, digest);
++ ATF_REQUIRE(result == ISC_R_SUCCESS);
++ tohexstr(digest, ISC_GOST_DIGESTLENGTH, str);
++ ATF_CHECK_STREQ(str, testcase->result);
++
++ testcase++;
++ }
++
++ dns_test_end();
++}
++#else
++ATF_TC(untested);
++ATF_TC_HEAD(untested, tc) {
++ atf_tc_set_md_var(tc, "descr", "skipping gost test");
++}
++ATF_TC_BODY(untested, tc) {
++ UNUSED(tc);
++ atf_tc_skip("GOST hash not available");
++}
++#endif
++/*
++ * Main
++ */
++ATF_TP_ADD_TCS(tp) {
++#if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
++ ATF_TP_ADD_TC(tp, isc_gost);
++#else
++ ATF_TP_ADD_TC(tp, untested);
++#endif
++ return (atf_no_error());
++}
++
+diff -up bind-9.9.6/lib/dns/tests/Makefile.in.native_pkcs11 bind-9.9.6/lib/dns/tests/Makefile.in
+--- bind-9.9.6/lib/dns/tests/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/tests/Makefile.in 2014-10-09 13:30:47.830302928 +0200
+@@ -26,8 +26,9 @@ top_srcdir = @top_srcdir@
+
+ @BIND9_MAKE_INCLUDES@
+
+-CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} @DST_OPENSSL_INC@
+-CDEFINES = @USE_OPENSSL@ -DTESTS="\"${top_builddir}/lib/dns/tests/\""
++CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} ${ISC_INCLUDES} \
++ @DST_OPENSSL_INC@
++CDEFINES = @CRYPTO@ -DTESTS="\"${top_builddir}/lib/dns/tests/\""
+
+ ISCLIBS = ../../isc/libisc.@A@
+ ISCDEPLIBS = ../../isc/libisc.@A@
+diff -up bind-9.9.6/lib/dns/tkey.c.native_pkcs11 bind-9.9.6/lib/dns/tkey.c
+--- bind-9.9.6/lib/dns/tkey.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/tkey.c 2014-10-09 13:30:47.832302931 +0200
+@@ -45,8 +45,14 @@
+ #include <dst/dst.h>
+ #include <dst/gssapi.h>
+
++#include "dst_internal.h"
++
+ #define TKEY_RANDOM_AMOUNT 16
+
++#ifdef PKCS11CRYPTO
++#include <pk11/pk11.h>
++#endif
++
+ #define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+@@ -382,8 +388,8 @@ process_dhtkey(dns_message_t *msg, dns_n
+ if (randomdata == NULL)
+ goto failure;
+
+- result = isc_entropy_getdata(tctx->ectx, randomdata,
+- TKEY_RANDOM_AMOUNT, NULL, 0);
++ result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT,
++ ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ tkey_log("process_dhtkey: failed to obtain entropy: %s",
+ isc_result_totext(result));
+diff -up bind-9.9.6/lib/dns/tsig.c.native_pkcs11 bind-9.9.6/lib/dns/tsig.c
+--- bind-9.9.6/lib/dns/tsig.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/dns/tsig.c 2014-10-09 13:30:47.832302931 +0200
+@@ -946,8 +946,9 @@ dns_tsig_sign(dns_message_t *msg) {
+ isc_buffer_t headerbuf;
+ isc_uint16_t digestbits;
+
+- ret = dst_context_create2(key->key, mctx,
+- DNS_LOGCATEGORY_DNSSEC, &ctx);
++ ret = dst_context_create3(key->key, mctx,
++ DNS_LOGCATEGORY_DNSSEC,
++ ISC_TRUE, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+@@ -1345,8 +1346,9 @@ dns_tsig_verify(isc_buffer_t *source, dn
+ sig_r.base = tsig.signature;
+ sig_r.length = tsig.siglen;
+
+- ret = dst_context_create2(key, mctx,
+- DNS_LOGCATEGORY_DNSSEC, &ctx);
++ ret = dst_context_create3(key, mctx,
++ DNS_LOGCATEGORY_DNSSEC,
++ ISC_FALSE, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+@@ -1577,9 +1579,9 @@ tsig_verify_tcp(isc_buffer_t *source, dn
+ key = tsigkey->key;
+
+ if (msg->tsigctx == NULL) {
+- ret = dst_context_create2(key, mctx,
++ ret = dst_context_create3(key, mctx,
+ DNS_LOGCATEGORY_DNSSEC,
+- &msg->tsigctx);
++ ISC_FALSE, &msg->tsigctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_querystruct;
+
+diff -up bind-9.9.6/lib/export/dns/Makefile.in.native_pkcs11 bind-9.9.6/lib/export/dns/Makefile.in
+--- bind-9.9.6/lib/export/dns/Makefile.in.native_pkcs11 2014-10-09 13:29:59.149238302 +0200
++++ bind-9.9.6/lib/export/dns/Makefile.in 2014-10-09 13:30:47.833302932 +0200
+@@ -28,10 +28,10 @@ export_srcdir = @top_srcdir@/lib/export
+
+ @BIND9_MAKE_INCLUDES@
+
+-CINCLUDES = -I. -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \
++CINCLUDES = -I. -I${top_srcdir}/lib/dns -Iinclude ${DNS_INCLUDES} -I${export_srcdir}/isc/include \
+ ${ISC_INCLUDES} @DST_OPENSSL_INC@ @DST_GSSAPI_INC@
+
+-CDEFINES = -DUSE_MD5 @USE_OPENSSL@ @USE_GSSAPI@
++CDEFINES = -DUSE_MD5 @CRYPTO@ @USE_GSSAPI@
+
+ CWARNINGS =
+
+diff -up bind-9.9.6/lib/export/isc/Makefile.in.native_pkcs11 bind-9.9.6/lib/export/isc/Makefile.in
+--- bind-9.9.6/lib/export/isc/Makefile.in.native_pkcs11 2014-10-09 13:29:59.150238303 +0200
++++ bind-9.9.6/lib/export/isc/Makefile.in 2014-10-09 13:30:47.833302932 +0200
+@@ -27,7 +27,7 @@ CINCLUDES = -I${srcdir}/unix/include \
+ -I${srcdir}/@ISC_ARCH_DIR@/include \
+ -I${export_srcdir}/isc/include -I${srcdir}/include \
+ @ISC_OPENSSL_INC@
+-CDEFINES = @USE_OPENSSL@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \
++CDEFINES = @CRYPTO@ -DUSE_APPIMPREGISTER -DUSE_MEMIMPREGISTER \
+ -DUSE_SOCKETIMPREGISTER -DUSE_TASKIMPREGISTER \
+ -DUSE_TIMERIMPREGISTER
+ CWARNINGS =
+@@ -48,7 +48,8 @@ UNIXOBJS = @ISC_ISCIPV6_O@ \
+ unix/file.@O@ \
+ unix/fsaccess.@O@ \
+ unix/stdio.@O@ \
+- unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@
++ unix/stdtime.@O@ unix/strerror.@O@ unix/time.@O@ unix/entropy.@O@ \
++ unix/keyboard.@O@
+
+ NLSOBJS = nls/msgcat.@O@
+
+diff -up bind-9.9.6/lib/export/isc/unix/Makefile.in.native_pkcs11 bind-9.9.6/lib/export/isc/unix/Makefile.in
+--- bind-9.9.6/lib/export/isc/unix/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/export/isc/unix/Makefile.in 2014-10-09 13:30:47.834302934 +0200
+@@ -40,6 +40,8 @@ OBJS = @ISC_IPV6_O@ \
+ file.@O@ fsaccess.@O@ \
+ stdio.@O@ stdtime.@O@ strerror.@O@ \
+ time.@O@ \
++ entropy.@O@ \
++ keyboard.@O@ \
+ ${ISCDRIVEROBJS}
+
+ # Alphabetically
+@@ -51,6 +53,8 @@ SRCS = @ISC_IPV6_C@ \
+ file.c fsaccess.c \
+ stdio.c stdtime.c strerror.c \
+ time.c \
++ entropy.c \
++ keyboard.c \
+ ${ISCDRIVERSRCS}
+
+ SUBDIRS = include
+diff -up bind-9.9.6/lib/isc/entropy.c.native_pkcs11 bind-9.9.6/lib/isc/entropy.c
+--- bind-9.9.6/lib/isc/entropy.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/entropy.c 2014-10-09 13:30:47.835302935 +0200
+@@ -46,6 +46,9 @@
+ #include <isc/time.h>
+ #include <isc/util.h>
+
++#ifdef PKCS11CRYPTO
++#include <pk11/pk11.h>
++#endif
+
+ #define ENTROPY_MAGIC ISC_MAGIC('E', 'n', 't', 'e')
+ #define SOURCE_MAGIC ISC_MAGIC('E', 'n', 't', 's')
+@@ -1236,6 +1239,11 @@ isc_entropy_usebestsource(isc_entropy_t
+ use_keyboard == ISC_ENTROPY_KEYBOARDNO ||
+ use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
+
++#ifdef PKCS11CRYPTO
++ if (randomfile != NULL)
++ pk11_rand_seed_fromfile(randomfile);
++#endif
++
+ #ifdef PATH_RANDOMDEV
+ if (randomfile == NULL) {
+ randomfile = PATH_RANDOMDEV;
+diff -up bind-9.9.6/lib/isc/hmacmd5.c.native_pkcs11 bind-9.9.6/lib/isc/hmacmd5.c
+--- bind-9.9.6/lib/isc/hmacmd5.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/hmacmd5.c 2014-10-09 13:30:47.835302935 +0200
+@@ -33,6 +33,11 @@
+ #include <isc/types.h>
+ #include <isc/util.h>
+
++#if PKCS11CRYPTO || PKCS11CRYPTOWITHHMAC
++#include <pk11/internal.h>
++#include <pk11/pk11.h>
++#endif
++
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+
+ void
+@@ -60,6 +65,167 @@ isc_hmacmd5_sign(isc_hmacmd5_t *ctx, uns
+ HMAC_CTX_cleanup(ctx);
+ }
+
++#elif PKCS11CRYPTOWITHHMAC
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++void
++isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_MD5_HMAC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, (CK_ULONG) len }
++ };
++
++ DE_CONST(key, keyTemplate[5].pValue);
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ ctx->object = CK_INVALID_HANDLE;
++ PK11_FATALCHECK(pkcs_C_CreateObject,
++ (ctx->session, keyTemplate,
++ (CK_ULONG) 6, &ctx->object));
++ INSIST(ctx->object != CK_INVALID_HANDLE);
++ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
++}
++
++void
++isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
++ CK_BYTE garbage[ISC_MD5_DIGESTLENGTH];
++ CK_ULONG len = ISC_MD5_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++void
++isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_SignUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
++ CK_RV rv;
++ CK_ULONG len = ISC_MD5_DIGESTLENGTH;
++
++ PK11_FATALCHECK(pkcs_C_SignFinal,
++ (ctx->session, (CK_BYTE_PTR) digest, &len));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++#elif PKCS11CRYPTO
++
++#define PADLEN 64
++#define IPAD 0x36
++#define OPAD 0x5C
++
++void
++isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
++ unsigned char ipad[PADLEN];
++ unsigned int i;
++
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ RUNTIME_CHECK((ctx->key = pk11_mem_get(PADLEN)) != NULL);
++ if (len > PADLEN) {
++ CK_BYTE_PTR kPart;
++ CK_ULONG kl;
++
++ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
++ DE_CONST(key, kPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, kPart, (CK_ULONG) len));
++ kl = ISC_MD5_DIGESTLENGTH;
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (ctx->session, (CK_BYTE_PTR) ctx->key, &kl));
++ } else
++ memcpy(ctx->key, key, len);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
++ memset(ipad, IPAD, PADLEN);
++ for (i = 0; i < PADLEN; i++)
++ ipad[i] ^= ctx->key[i];
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, ipad, (CK_ULONG) PADLEN));
++}
++
++void
++isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
++ if (ctx->key != NULL)
++ pk11_mem_put(ctx->key, PADLEN);
++ ctx->key = NULL;
++ isc_md5_invalidate(ctx);
++}
++
++void
++isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
++ CK_ULONG len = ISC_MD5_DIGESTLENGTH;
++ CK_BYTE opad[PADLEN];
++ unsigned int i;
++
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (ctx->session, (CK_BYTE_PTR) digest,
++ (CK_ULONG_PTR) &len));
++ memset(opad, OPAD, PADLEN);
++ for (i = 0; i < PADLEN; i++)
++ opad[i] ^= ctx->key[i];
++ pk11_mem_put(ctx->key, PADLEN);
++ ctx->key = NULL;
++ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, opad, (CK_ULONG) PADLEN));
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, (CK_BYTE_PTR) digest, len));
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (ctx->session,
++ (CK_BYTE_PTR) digest,
++ (CK_ULONG_PTR) &len));
++ pk11_return_session(ctx);
++}
++
+ #else
+
+ #define PADLEN 64
+diff -up bind-9.9.6/lib/isc/hmacsha.c.native_pkcs11 bind-9.9.6/lib/isc/hmacsha.c
+--- bind-9.9.6/lib/isc/hmacsha.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/hmacsha.c 2014-10-09 13:30:47.836302936 +0200
+@@ -34,6 +34,11 @@
+ #include <isc/types.h>
+ #include <isc/util.h>
+
++#if PKCS11CRYPTO
++#include <pk11/internal.h>
++#include <pk11/pk11.h>
++#endif
++
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+
+ void
+@@ -191,6 +196,376 @@ isc_hmacsha512_sign(isc_hmacsha512_t *ct
+ memset(newdigest, 0, sizeof(newdigest));
+ }
+
++#elif PKCS11CRYPTO
++
++static CK_BBOOL truevalue = TRUE;
++static CK_BBOOL falsevalue = FALSE;
++
++void
++isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA_1_HMAC, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_SHA_1_HMAC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, (CK_ULONG) len }
++ };
++
++ DE_CONST(key, keyTemplate[5].pValue);
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ ctx->object = CK_INVALID_HANDLE;
++ PK11_FATALCHECK(pkcs_C_CreateObject,
++ (ctx->session, keyTemplate,
++ (CK_ULONG) 6, &ctx->object));
++ INSIST(ctx->object != CK_INVALID_HANDLE);
++ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
++}
++
++void
++isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
++ CK_BYTE garbage[ISC_SHA1_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA1_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++void
++isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_SignUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
++ CK_RV rv;
++ CK_BYTE newdigest[ISC_SHA1_DIGESTLENGTH];
++ CK_ULONG psl = ISC_SHA1_DIGESTLENGTH;
++
++ REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
++
++ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++ memcpy(digest, newdigest, len);
++ memset(newdigest, 0, sizeof(newdigest));
++}
++
++void
++isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA224_HMAC, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_SHA224_HMAC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, (CK_ULONG) len }
++ };
++
++ DE_CONST(key, keyTemplate[5].pValue);
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ ctx->object = CK_INVALID_HANDLE;
++ PK11_FATALCHECK(pkcs_C_CreateObject,
++ (ctx->session, keyTemplate,
++ (CK_ULONG) 6, &ctx->object));
++ INSIST(ctx->object != CK_INVALID_HANDLE);
++ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
++}
++
++void
++isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
++ CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA224_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++void
++isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_SignUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
++ CK_RV rv;
++ CK_BYTE newdigest[ISC_SHA224_DIGESTLENGTH];
++ CK_ULONG psl = ISC_SHA224_DIGESTLENGTH;
++
++ REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
++
++ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++ memcpy(digest, newdigest, len);
++ memset(newdigest, 0, sizeof(newdigest));
++}
++
++void
++isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA256_HMAC, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_SHA256_HMAC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, (CK_ULONG) len }
++ };
++
++ DE_CONST(key, keyTemplate[5].pValue);
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ ctx->object = CK_INVALID_HANDLE;
++ PK11_FATALCHECK(pkcs_C_CreateObject,
++ (ctx->session, keyTemplate,
++ (CK_ULONG) 6, &ctx->object));
++ INSIST(ctx->object != CK_INVALID_HANDLE);
++ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
++}
++
++void
++isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
++ CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA256_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++void
++isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_SignUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
++ CK_RV rv;
++ CK_BYTE newdigest[ISC_SHA256_DIGESTLENGTH];
++ CK_ULONG psl = ISC_SHA256_DIGESTLENGTH;
++
++ REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
++
++ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++ memcpy(digest, newdigest, len);
++ memset(newdigest, 0, sizeof(newdigest));
++}
++
++void
++isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA384_HMAC, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_SHA384_HMAC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, (CK_ULONG) len }
++ };
++
++ DE_CONST(key, keyTemplate[5].pValue);
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ ctx->object = CK_INVALID_HANDLE;
++ PK11_FATALCHECK(pkcs_C_CreateObject,
++ (ctx->session, keyTemplate,
++ (CK_ULONG) 6, &ctx->object));
++ INSIST(ctx->object != CK_INVALID_HANDLE);
++ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
++}
++
++void
++isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
++ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA384_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++void
++isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_SignUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
++ CK_RV rv;
++ CK_BYTE newdigest[ISC_SHA384_DIGESTLENGTH];
++ CK_ULONG psl = ISC_SHA384_DIGESTLENGTH;
++
++ REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
++
++ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++ memcpy(digest, newdigest, len);
++ memset(newdigest, 0, sizeof(newdigest));
++}
++
++void
++isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA512_HMAC, NULL, 0 };
++ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
++ CK_KEY_TYPE keyType = CKK_SHA512_HMAC;
++ CK_ATTRIBUTE keyTemplate[] =
++ {
++ { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
++ { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
++ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
++ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
++ { CKA_VALUE, NULL, (CK_ULONG) len }
++ };
++
++ DE_CONST(key, keyTemplate[5].pValue);
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ ctx->object = CK_INVALID_HANDLE;
++ PK11_FATALCHECK(pkcs_C_CreateObject,
++ (ctx->session, keyTemplate,
++ (CK_ULONG) 6, &ctx->object));
++ INSIST(ctx->object != CK_INVALID_HANDLE);
++ PK11_FATALCHECK(pkcs_C_SignInit, (ctx->session, &mech, ctx->object));
++}
++
++void
++isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
++ CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA512_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_SignFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++}
++
++void
++isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
++ unsigned int len)
++{
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_SignUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
++ CK_RV rv;
++ CK_BYTE newdigest[ISC_SHA512_DIGESTLENGTH];
++ CK_ULONG psl = ISC_SHA512_DIGESTLENGTH;
++
++ REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
++
++ PK11_FATALCHECK(pkcs_C_SignFinal, (ctx->session, newdigest, &psl));
++ if (ctx->object != CK_INVALID_HANDLE)
++ (void) pkcs_C_DestroyObject(ctx->session, ctx->object);
++ ctx->object = CK_INVALID_HANDLE;
++ pk11_return_session(ctx);
++ memcpy(digest, newdigest, len);
++ memset(newdigest, 0, sizeof(newdigest));
++}
++
+ #else
+
+ #define IPAD 0x36
+diff -up bind-9.9.6/lib/isc/include/isc/hmacmd5.h.native_pkcs11 bind-9.9.6/lib/isc/include/isc/hmacmd5.h
+--- bind-9.9.6/lib/isc/include/isc/hmacmd5.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/isc/hmacmd5.h 2014-10-09 13:30:47.837302938 +0200
+@@ -37,6 +37,11 @@
+
+ typedef HMAC_CTX isc_hmacmd5_t;
+
++#elif PKCS11CRYPTO
++#include <pk11/pk11.h>
++
++typedef pk11_context_t isc_hmacmd5_t;
++
+ #else
+
+ typedef struct {
+diff -up bind-9.9.6/lib/isc/include/isc/hmacsha.h.native_pkcs11 bind-9.9.6/lib/isc/include/isc/hmacsha.h
+--- bind-9.9.6/lib/isc/include/isc/hmacsha.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/isc/hmacsha.h 2014-10-09 13:30:47.837302938 +0200
+@@ -45,6 +45,15 @@ typedef HMAC_CTX isc_hmacsha256_t;
+ typedef HMAC_CTX isc_hmacsha384_t;
+ typedef HMAC_CTX isc_hmacsha512_t;
+
++#elif PKCS11CRYPTO
++#include <pk11/pk11.h>
++
++typedef pk11_context_t isc_hmacsha1_t;
++typedef pk11_context_t isc_hmacsha224_t;
++typedef pk11_context_t isc_hmacsha256_t;
++typedef pk11_context_t isc_hmacsha384_t;
++typedef pk11_context_t isc_hmacsha512_t;
++
+ #else
+
+ typedef struct {
+diff -up bind-9.9.6/lib/isc/include/isc/md5.h.native_pkcs11 bind-9.9.6/lib/isc/include/isc/md5.h
+--- bind-9.9.6/lib/isc/include/isc/md5.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/isc/md5.h 2014-10-09 13:30:47.837302938 +0200
+@@ -55,6 +55,11 @@
+
+ typedef EVP_MD_CTX isc_md5_t;
+
++#elif PKCS11CRYPTO
++#include <pk11/pk11.h>
++
++typedef pk11_context_t isc_md5_t;
++
+ #else
+
+ typedef struct {
+diff -up bind-9.9.6/lib/isc/include/isc/resultclass.h.native_pkcs11 bind-9.9.6/lib/isc/include/isc/resultclass.h
+--- bind-9.9.6/lib/isc/include/isc/resultclass.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/isc/resultclass.h 2014-10-09 13:30:47.838302939 +0200
+@@ -46,6 +46,6 @@
+ #define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4)
+ #define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5)
+ #define ISC_RESULTCLASS_DHCP ISC_RESULTCLASS_FROMNUM(6)
+-
++#define ISC_RESULTCLASS_PK11 ISC_RESULTCLASS_FROMNUM(7)
+
+ #endif /* ISC_RESULTCLASS_H */
+diff -up bind-9.9.6/lib/isc/include/isc/sha1.h.native_pkcs11 bind-9.9.6/lib/isc/include/isc/sha1.h
+--- bind-9.9.6/lib/isc/include/isc/sha1.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/isc/sha1.h 2014-10-09 13:30:47.838302939 +0200
+@@ -40,6 +40,11 @@
+
+ typedef EVP_MD_CTX isc_sha1_t;
+
++#elif PKCS11CRYPTO
++#include <pk11/pk11.h>
++
++typedef pk11_context_t isc_sha1_t;
++
+ #else
+
+ typedef struct {
+diff -up bind-9.9.6/lib/isc/include/isc/sha2.h.native_pkcs11 bind-9.9.6/lib/isc/include/isc/sha2.h
+--- bind-9.9.6/lib/isc/include/isc/sha2.h.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/isc/sha2.h 2014-10-09 13:30:47.838302939 +0200
+@@ -84,6 +84,12 @@
+ typedef EVP_MD_CTX isc_sha256_t;
+ typedef EVP_MD_CTX isc_sha512_t;
+
++#elif PKCS11CRYPTO
++#include <pk11/pk11.h>
++
++typedef pk11_context_t isc_sha256_t;
++typedef pk11_context_t isc_sha512_t;
++
+ #else
+
+ /*
+diff -up bind-9.9.6/lib/isc/include/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/include/Makefile.in
+--- bind-9.9.6/lib/isc/include/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/include/Makefile.in 2014-10-09 13:30:47.837302938 +0200
+@@ -19,7 +19,7 @@ srcdir = @srcdir@
+ VPATH = @srcdir@
+ top_srcdir = @top_srcdir@
+
+-SUBDIRS = isc
++SUBDIRS = isc pk11 pkcs11
+ TARGETS =
+
+ @BIND9_MAKE_RULES@
+diff -up bind-9.9.6/lib/isc/include/pk11/constants.h.native_pkcs11 bind-9.9.6/lib/isc/include/pk11/constants.h
+--- bind-9.9.6/lib/isc/include/pk11/constants.h.native_pkcs11 2014-10-09 13:30:47.838302939 +0200
++++ bind-9.9.6/lib/isc/include/pk11/constants.h 2014-10-09 13:30:47.838302939 +0200
+@@ -0,0 +1,107 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#ifndef PK11_CONSTANTS_H
++#define PK11_CONSTANTS_H 1
++
++/*! \file pk11/constants.h */
++
++/*%
++ * Static arrays of data used for key template initalization
++ */
++#ifdef WANT_ECC_CURVES
++static CK_BYTE pk11_ecc_prime256v1[] = {
++ 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
++};
++static CK_BYTE pk11_ecc_secp384r1[] = {
++ 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22
++};
++#endif
++
++#ifdef WANT_DH_PRIMES
++static CK_BYTE pk11_dh_bn2[] = { 2 };
++static CK_BYTE pk11_dh_bn768[] = {
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
++ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
++ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
++ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22,
++ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
++ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b,
++ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
++ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
++ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
++ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
++};
++static CK_BYTE pk11_dh_bn1024[] = {
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
++ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
++ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
++ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22,
++ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
++ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b,
++ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
++ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
++ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
++ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b,
++ 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
++ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5,
++ 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6,
++ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe6, 0x53, 0x81,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
++};
++static CK_BYTE pk11_dh_bn1536[] = {
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2, 0x34,
++ 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
++ 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74,
++ 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22,
++ 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
++ 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b,
++ 0x30, 0x2b, 0x0a, 0x6d, 0xf2, 0x5f, 0x14, 0x37,
++ 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
++ 0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6,
++ 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x37, 0xed, 0x6b,
++ 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
++ 0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5,
++ 0xae, 0x9f, 0x24, 0x11, 0x7c, 0x4b, 0x1f, 0xe6,
++ 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
++ 0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05,
++ 0x98, 0xda, 0x48, 0x36, 0x1c, 0x55, 0xd3, 0x9a,
++ 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
++ 0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96,
++ 0x1c, 0x62, 0xf3, 0x56, 0x20, 0x85, 0x52, 0xbb,
++ 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
++ 0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04,
++ 0xf1, 0x74, 0x6c, 0x08, 0xca, 0x23, 0x73, 0x27,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
++};
++#endif
++
++#ifdef WANT_GOST_PARAMS
++static CK_BYTE pk11_gost_a_paramset[] = {
++ 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01
++};
++static CK_BYTE pk11_gost_paramset[] = {
++ 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01
++};
++#endif
++
++#endif /* PK11_CONSTANTS_H */
+diff -up bind-9.9.6/lib/isc/include/pk11/internal.h.native_pkcs11 bind-9.9.6/lib/isc/include/pk11/internal.h
+--- bind-9.9.6/lib/isc/include/pk11/internal.h.native_pkcs11 2014-10-09 13:30:47.839302940 +0200
++++ bind-9.9.6/lib/isc/include/pk11/internal.h 2014-10-09 13:30:47.839302940 +0200
+@@ -0,0 +1,46 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++#ifndef PK11_INTERNAL_H
++#define PK11_INTERNAL_H 1
++
++/*! \file pk11/internal.h */
++
++ISC_LANG_BEGINDECLS
++
++const char *pk11_get_lib_name(void);
++
++void *pk11_mem_get(size_t size);
++
++void pk11_mem_put(void *ptr, size_t size);
++
++CK_SLOT_ID pk11_get_best_token(pk11_optype_t optype);
++
++unsigned int pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt);
++
++CK_ATTRIBUTE *pk11_attribute_first(const pk11_object_t *obj);
++
++CK_ATTRIBUTE *pk11_attribute_next(const pk11_object_t *obj,
++ CK_ATTRIBUTE *attr);
++
++CK_ATTRIBUTE *pk11_attribute_bytype(const pk11_object_t *obj,
++ CK_ATTRIBUTE_TYPE type);
++
++ISC_LANG_ENDDECLS
++
++#endif /* PK11_INTERNAL_H */
+diff -up bind-9.9.6/lib/isc/include/pk11/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/include/pk11/Makefile.in
+--- bind-9.9.6/lib/isc/include/pk11/Makefile.in.native_pkcs11 2014-10-09 13:30:47.838302939 +0200
++++ bind-9.9.6/lib/isc/include/pk11/Makefile.in 2014-10-09 13:30:47.838302939 +0200
+@@ -0,0 +1,38 @@
++# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++#
++# Permission to use, copy, modify, and/or distribute this software for any
++# purpose with or without fee is hereby granted, provided that the above
++# copyright notice and this permission notice appear in all copies.
++#
++# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++# PERFORMANCE OF THIS SOFTWARE.
++
++srcdir = @srcdir@
++VPATH = @srcdir@
++top_srcdir = @top_srcdir@
++
++@BIND9_VERSION@
++
++#
++# Only list headers that are to be installed and are not
++# machine generated. The latter are handled specially in the
++# install target below.
++#
++HEADERS = constants.h internal.h pk11.h result.h
++SUBDIRS =
++TARGETS =
++
++@BIND9_MAKE_RULES@
++
++installdirs:
++ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pk11
++
++install:: installdirs
++ for i in ${HEADERS}; do \
++ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/pk11 ; \
++ done
+diff -up bind-9.9.6/lib/isc/include/pk11/pk11.h.native_pkcs11 bind-9.9.6/lib/isc/include/pk11/pk11.h
+--- bind-9.9.6/lib/isc/include/pk11/pk11.h.native_pkcs11 2014-10-09 13:30:47.839302940 +0200
++++ bind-9.9.6/lib/isc/include/pk11/pk11.h 2014-10-09 13:30:47.839302940 +0200
+@@ -0,0 +1,295 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef PK11_PK11_H
++#define PK11_PK11_H 1
++
++/*! \file pk11/pk11.h */
++
++#include <isc/lang.h>
++#include <isc/magic.h>
++#include <isc/types.h>
++
++#define PK11_FATALCHECK(func, args) \
++ ((void) (((rv = (func) args) == CKR_OK) || \
++ ((pk11_error_fatalcheck)(__FILE__, __LINE__, #func, rv), 0)))
++
++#include <pkcs11/cryptoki.h>
++
++ISC_LANG_BEGINDECLS
++
++#define SES_MAGIC ISC_MAGIC('P','K','S','S')
++#define TOK_MAGIC ISC_MAGIC('P','K','T','K')
++
++#define VALID_SES(x) ISC_MAGIC_VALID(x, SES_MAGIC)
++#define VALID_TOK(x) ISC_MAGIC_VALID(x, TOK_MAGIC)
++
++typedef struct pk11_context pk11_context_t;
++
++struct pk11_object {
++ CK_OBJECT_HANDLE object;
++ CK_SLOT_ID slot;
++ CK_BBOOL ontoken;
++ CK_BBOOL reqlogon;
++ CK_BYTE attrcnt;
++ CK_ATTRIBUTE *repr;
++};
++
++struct pk11_context {
++ void *handle;
++ CK_SESSION_HANDLE session;
++ CK_BBOOL ontoken;
++ CK_OBJECT_HANDLE object;
++#ifndef PKCS11CRYPTOWITHHMAC
++ unsigned char *key;
++#endif
++};
++
++typedef struct pk11_object pk11_object_t;
++
++typedef enum {
++ OP_ANY = 0,
++ OP_RAND = 1,
++ OP_RSA = 2,
++ OP_DSA = 3,
++ OP_DH = 4,
++ OP_DIGEST = 5,
++ OP_EC = 6,
++ OP_GOST = 7,
++ OP_AES = 8,
++ OP_MAX = 9
++} pk11_optype_t;
++
++/*%
++ * Function prototypes
++ */
++
++void pk11_set_lib_name(const char *lib_name);
++/*%<
++ * Set the PKCS#11 provider (aka library) path/name.
++ */
++
++isc_result_t pk11_initialize(isc_mem_t *mctx, const char *engine);
++/*%<
++ * Initialize PKCS#11 device
++ *
++ * mctx: memory context to attach to pk11_mctx.
++ * engine: PKCS#11 provider (aka library) path/name.
++ *
++ * returns:
++ * ISC_R_SUCCESS
++ * PK11_R_NOPROVIDER: can't load the provider
++ * PK11_R_INITFAILED: C_Initialize() failed
++ * PK11_R_NORANDOMSERVICE: can't find required random service
++ * PK11_R_NODIGESTSERVICE: can't find required digest service
++ * PK11_R_NOAESSERVICE: can't find required AES service
++ */
++
++isc_result_t pk11_get_session(pk11_context_t *ctx,
++ pk11_optype_t optype,
++ isc_boolean_t need_services,
++ isc_boolean_t rw,
++ isc_boolean_t logon,
++ const char *pin,
++ CK_SLOT_ID slot);
++/*%<
++ * Initialize PKCS#11 device and acquire a session.
++ *
++ * need_services:
++ * if ISC_TRUE, this session requires full PKCS#11 API
++ * support including random and digest services, and
++ * the lack of these services will cause the session not
++ * to be initialized. If ISC_FALSE, the function will return
++ * an error code indicating the missing service, but the
++ * session will be usable for other purposes.
++ * rw: if ISC_TRUE, session will be read/write (useful for
++ * generating or destroying keys); otherwise read-only.
++ * login: indicates whether to log in to the device
++ * pin: optional PIN, overriding any PIN currently associated
++ * with the
++ * slot: device slot ID
++ */
++
++void pk11_return_session(pk11_context_t *ctx);
++/*%<
++ * Release an active PKCS#11 session for reuse.
++ */
++
++isc_result_t pk11_finalize(void);
++/*%<
++ * Shut down PKCS#11 device and free all sessions.
++ */
++
++isc_result_t pk11_rand_bytes(unsigned char *buf, int num);
++
++void pk11_rand_seed_fromfile(const char *randomfile);
++
++isc_result_t pk11_parse_uri(pk11_object_t *obj, const char *label,
++ isc_mem_t *mctx, pk11_optype_t optype);
++
++ISC_PLATFORM_NORETURN_PRE void
++pk11_error_fatalcheck(const char *file, int line,
++ const char *funcname, CK_RV rv)
++ISC_PLATFORM_NORETURN_POST;
++
++void pk11_dump_tokens(void);
++
++CK_RV
++pkcs_C_Initialize(CK_VOID_PTR pReserved);
++
++CK_RV
++pkcs_C_Finalize(CK_VOID_PTR pReserved);
++
++CK_RV
++pkcs_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
++ CK_ULONG_PTR pulCount);
++
++CK_RV
++pkcs_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo);
++
++CK_RV
++pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
++ CK_MECHANISM_INFO_PTR pInfo);
++
++CK_RV
++pkcs_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
++ CK_VOID_PTR pApplication,
++ CK_RV (*Notify) (CK_SESSION_HANDLE hSession,
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication),
++ CK_SESSION_HANDLE_PTR phSession);
++
++CK_RV
++pkcs_C_CloseSession(CK_SESSION_HANDLE hSession);
++
++CK_RV
++pkcs_C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
++ CK_CHAR_PTR pPin, CK_ULONG usPinLen);
++
++CK_RV
++pkcs_C_Logout(CK_SESSION_HANDLE hSession);
++
++CK_RV
++pkcs_C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
++ CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject);
++
++CK_RV
++pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject);
++
++CK_RV
++pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount);
++
++CK_RV
++pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount);
++
++CK_RV
++pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
++ CK_ULONG usCount);
++
++CK_RV
++pkcs_C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
++ CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount);
++
++CK_RV
++pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession);
++
++CK_RV
++pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hKey);
++
++CK_RV
++pkcs_C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
++ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
++ CK_ULONG_PTR pulEncryptedDataLen);
++
++CK_RV
++pkcs_C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism);
++
++CK_RV
++pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
++ CK_ULONG ulPartLen);
++
++CK_RV
++pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
++ CK_ULONG_PTR pulDigestLen);
++
++CK_RV
++pkcs_C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hKey);
++
++CK_RV
++pkcs_C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
++ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
++ CK_ULONG_PTR pulSignatureLen);
++
++CK_RV
++pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
++ CK_ULONG ulPartLen);
++
++CK_RV
++pkcs_C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
++ CK_ULONG_PTR pulSignatureLen);
++
++CK_RV
++pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hKey);
++
++CK_RV
++pkcs_C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
++ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
++ CK_ULONG ulSignatureLen);
++
++CK_RV
++pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
++ CK_ULONG ulPartLen);
++
++CK_RV
++pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
++ CK_ULONG ulSignatureLen);
++
++CK_RV
++pkcs_C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
++ CK_OBJECT_HANDLE_PTR phKey);
++
++CK_RV
++pkcs_C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_PTR pMechanism,
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
++ CK_ULONG usPublicKeyAttributeCount,
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
++ CK_ULONG usPrivateKeyAttributeCount,
++ CK_OBJECT_HANDLE_PTR phPrivateKey,
++ CK_OBJECT_HANDLE_PTR phPublicKey);
++
++CK_RV
++pkcs_C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
++ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey);
++
++CK_RV
++pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
++ CK_ULONG ulSeedLen);
++
++CK_RV
++pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData,
++ CK_ULONG ulRandomLen);
++
++ISC_LANG_ENDDECLS
++
++#endif /* PK11_PK11_H */
+diff -up bind-9.9.6/lib/isc/include/pk11/result.h.native_pkcs11 bind-9.9.6/lib/isc/include/pk11/result.h
+--- bind-9.9.6/lib/isc/include/pk11/result.h.native_pkcs11 2014-10-09 13:30:47.839302940 +0200
++++ bind-9.9.6/lib/isc/include/pk11/result.h 2014-10-09 13:30:47.839302940 +0200
+@@ -0,0 +1,56 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef PK11_RESULT_H
++#define PK11_RESULT_H 1
++
++/*! \file pk11/result.h */
++
++#include <isc/lang.h>
++#include <isc/resultclass.h>
++
++/*
++ * Nothing in this file truly depends on <isc/result.h>, but the
++ * PK11 result codes are considered to be publicly derived from
++ * the ISC result codes, so including this file buys you the ISC_R_
++ * namespace too.
++ */
++#include <isc/result.h> /* Contractual promise. */
++
++#define PK11_R_INITFAILED (ISC_RESULTCLASS_PK11 + 0)
++#define PK11_R_NOPROVIDER (ISC_RESULTCLASS_PK11 + 1)
++#define PK11_R_NORANDOMSERVICE (ISC_RESULTCLASS_PK11 + 2)
++#define PK11_R_NODIGESTSERVICE (ISC_RESULTCLASS_PK11 + 3)
++#define PK11_R_NOAESSERVICE (ISC_RESULTCLASS_PK11 + 4)
++
++#define PK11_R_NRESULTS 5 /* Number of results */
++
++ISC_LANG_BEGINDECLS
++
++LIBISC_EXTERNAL_DATA extern isc_msgcat_t *pk11_msgcat;
++
++void
++pk11_initmsgcat(void);
++
++const char *
++pk11_result_totext(isc_result_t);
++
++void
++pk11_result_register(void);
++
++ISC_LANG_ENDDECLS
++
++#endif /* PK11_RESULT_H */
+diff -up bind-9.9.6/lib/isc/include/pkcs11/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/include/pkcs11/Makefile.in
+--- bind-9.9.6/lib/isc/include/pkcs11/Makefile.in.native_pkcs11 2014-10-09 13:30:47.839302940 +0200
++++ bind-9.9.6/lib/isc/include/pkcs11/Makefile.in 2014-10-09 13:30:47.839302940 +0200
+@@ -0,0 +1,40 @@
++# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++#
++# Permission to use, copy, modify, and/or distribute this software for any
++# purpose with or without fee is hereby granted, provided that the above
++# copyright notice and this permission notice appear in all copies.
++#
++# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++# PERFORMANCE OF THIS SOFTWARE.
++
++# $Id: Makefile.in,v 1.7 2007/06/19 23:47:22 tbox Exp $
++
++srcdir = @srcdir@
++VPATH = @srcdir@
++top_srcdir = @top_srcdir@
++
++@BIND9_VERSION@
++
++#
++# Only list headers that are to be installed and are not
++# machine generated. The latter are handled specially in the
++# install target below.
++#
++HEADERS = pkcs11f.h pkcs11.h pkcs11t.h
++SUBDIRS =
++TARGETS =
++
++@BIND9_MAKE_RULES@
++
++installdirs:
++ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pkcs11
++
++install:: installdirs
++ for i in ${HEADERS}; do \
++ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/pkcs11 ; \
++ done
+diff -up bind-9.9.6/lib/isc/include/pkcs11/pkcs11f.h.native_pkcs11 bind-9.9.6/lib/isc/include/pkcs11/pkcs11f.h
+--- bind-9.9.6/lib/isc/include/pkcs11/pkcs11f.h.native_pkcs11 2014-10-09 13:30:47.840302942 +0200
++++ bind-9.9.6/lib/isc/include/pkcs11/pkcs11f.h 2014-10-09 13:30:47.840302942 +0200
+@@ -0,0 +1,912 @@
++/* pkcs11f.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This header file contains pretty much everything about all the */
++/* Cryptoki function prototypes. Because this information is */
++/* used for more than just declaring function prototypes, the */
++/* order of the functions appearing herein is important, and */
++/* should not be altered. */
++
++/* General-purpose */
++
++/* C_Initialize initializes the Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Initialize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
++ * cast to CK_C_INITIALIZE_ARGS_PTR
++ * and dereferenced */
++);
++#endif
++
++
++/* C_Finalize indicates that an application is done with the
++ * Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Finalize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
++);
++#endif
++
++
++/* C_GetInfo returns general information about Cryptoki. */
++CK_PKCS11_FUNCTION_INFO(C_GetInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_INFO_PTR pInfo /* location that receives information */
++);
++#endif
++
++
++/* C_GetFunctionList returns the function list. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
++ * function list */
++);
++#endif
++
++
++
++/* Slot and token management */
++
++/* C_GetSlotList obtains a list of slots in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_BBOOL tokenPresent, /* only slots with tokens? */
++ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
++ CK_ULONG_PTR pulCount /* receives number of slots */
++);
++#endif
++
++
++/* C_GetSlotInfo obtains information about a particular slot in
++ * the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the ID of the slot */
++ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
++);
++#endif
++
++
++/* C_GetTokenInfo obtains information about a particular token
++ * in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
++);
++#endif
++
++
++/* C_GetMechanismList obtains a list of mechanism types
++ * supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of token's slot */
++ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
++ CK_ULONG_PTR pulCount /* gets # of mechs. */
++);
++#endif
++
++
++/* C_GetMechanismInfo obtains information about a particular
++ * mechanism possibly supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_MECHANISM_TYPE type, /* type of mechanism */
++ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
++);
++#endif
++
++
++/* C_InitToken initializes a token. */
++CK_PKCS11_FUNCTION_INFO(C_InitToken)
++#ifdef CK_NEED_ARG_LIST
++/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
++ CK_ULONG ulPinLen, /* length in bytes of the PIN */
++ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
++);
++#endif
++
++
++/* C_InitPIN initializes the normal user's PIN. */
++CK_PKCS11_FUNCTION_INFO(C_InitPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
++ CK_ULONG ulPinLen /* length in bytes of the PIN */
++);
++#endif
++
++
++/* C_SetPIN modifies the PIN of the user who is logged in. */
++CK_PKCS11_FUNCTION_INFO(C_SetPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
++ CK_ULONG ulOldLen, /* length of the old PIN */
++ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
++ CK_ULONG ulNewLen /* length of the new PIN */
++);
++#endif
++
++
++
++/* Session management */
++
++/* C_OpenSession opens a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_OpenSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the slot's ID */
++ CK_FLAGS flags, /* from CK_SESSION_INFO */
++ CK_VOID_PTR pApplication, /* passed to callback */
++ CK_NOTIFY Notify, /* callback function */
++ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
++);
++#endif
++
++
++/* C_CloseSession closes a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CloseAllSessions closes all sessions with a token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID /* the token's slot */
++);
++#endif
++
++
++/* C_GetSessionInfo obtains information about the session. */
++CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_SESSION_INFO_PTR pInfo /* receives session info */
++);
++#endif
++
++
++/* C_GetOperationState obtains the state of the cryptographic operation
++ * in a session. */
++CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* gets state */
++ CK_ULONG_PTR pulOperationStateLen /* gets state length */
++);
++#endif
++
++
++/* C_SetOperationState restores the state of the cryptographic
++ * operation in a session. */
++CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* holds state */
++ CK_ULONG ulOperationStateLen, /* holds state length */
++ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
++ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
++);
++#endif
++
++
++/* C_Login logs a user into a token. */
++CK_PKCS11_FUNCTION_INFO(C_Login)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_USER_TYPE userType, /* the user type */
++ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
++ CK_ULONG ulPinLen /* the length of the PIN */
++);
++#endif
++
++
++/* C_Logout logs a user out from a token. */
++CK_PKCS11_FUNCTION_INFO(C_Logout)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Object management */
++
++/* C_CreateObject creates a new object. */
++CK_PKCS11_FUNCTION_INFO(C_CreateObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
++);
++#endif
++
++
++/* C_CopyObject copies an object, creating a new object for the
++ * copy. */
++CK_PKCS11_FUNCTION_INFO(C_CopyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
++);
++#endif
++
++
++/* C_DestroyObject destroys an object. */
++CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject /* the object's handle */
++);
++#endif
++
++
++/* C_GetObjectSize gets the size of an object in bytes. */
++CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ULONG_PTR pulSize /* receives size of object */
++);
++#endif
++
++
++/* C_GetAttributeValue obtains the value of one or more object
++ * attributes. */
++CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_SetAttributeValue modifies the value of one or more object
++ * attributes */
++CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_FindObjectsInit initializes a search for token and session
++ * objects that match a template. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
++ CK_ULONG ulCount /* attrs in search template */
++);
++#endif
++
++
++/* C_FindObjects continues a search for token and session
++ * objects that match a template, obtaining additional object
++ * handles. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjects)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
++ CK_ULONG ulMaxObjectCount, /* max handles to get */
++ CK_ULONG_PTR pulObjectCount /* actual # returned */
++);
++#endif
++
++
++/* C_FindObjectsFinal finishes a search for token and session
++ * objects. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Encryption and decryption */
++
++/* C_EncryptInit initializes an encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of encryption key */
++);
++#endif
++
++
++/* C_Encrypt encrypts single-part data. */
++CK_PKCS11_FUNCTION_INFO(C_Encrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pData, /* the plaintext data */
++ CK_ULONG ulDataLen, /* bytes of plaintext */
++ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptUpdate continues a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext data len */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptFinal finishes a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session handle */
++ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
++ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
++);
++#endif
++
++
++/* C_DecryptInit initializes a decryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of decryption key */
++);
++#endif
++
++
++/* C_Decrypt decrypts encrypted data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Decrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedData, /* ciphertext */
++ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
++ CK_BYTE_PTR pData, /* gets plaintext */
++ CK_ULONG_PTR pulDataLen /* gets p-text size */
++);
++#endif
++
++
++/* C_DecryptUpdate continues a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
++ CK_ULONG ulEncryptedPartLen, /* input length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* p-text size */
++);
++#endif
++
++
++/* C_DecryptFinal finishes a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pLastPart, /* gets plaintext */
++ CK_ULONG_PTR pulLastPartLen /* p-text size */
++);
++#endif
++
++
++
++/* Message digesting */
++
++/* C_DigestInit initializes a message-digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
++);
++#endif
++
++
++/* C_Digest digests data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Digest)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* data to be digested */
++ CK_ULONG ulDataLen, /* bytes of data to digest */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets digest length */
++);
++#endif
++
++
++/* C_DigestUpdate continues a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* data to be digested */
++ CK_ULONG ulPartLen /* bytes of data to be digested */
++);
++#endif
++
++
++/* C_DigestKey continues a multi-part message-digesting
++ * operation, by digesting the value of a secret key as part of
++ * the data already digested. */
++CK_PKCS11_FUNCTION_INFO(C_DigestKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hKey /* secret key to digest */
++);
++#endif
++
++
++/* C_DigestFinal finishes a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
++);
++#endif
++
++
++
++/* Signing and MACing */
++
++/* C_SignInit initializes a signature (private key encryption)
++ * operation, where the signature is (will be) an appendix to
++ * the data, and plaintext cannot be recovered from the
++ *signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of signature key */
++);
++#endif
++
++
++/* C_Sign signs (encrypts with private key) data in a single
++ * part, where the signature is (will be) an appendix to the
++ * data, and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Sign)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignUpdate continues a multiple-part signature operation,
++ * where the signature is (will be) an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* the data to sign */
++ CK_ULONG ulPartLen /* count of bytes to sign */
++);
++#endif
++
++
++/* C_SignFinal finishes a multiple-part signature operation,
++ * returning the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignRecoverInit initializes a signature operation, where
++ * the data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of the signature key */
++);
++#endif
++
++
++/* C_SignRecover signs data in a single operation, where the
++ * data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++
++/* Verifying signatures and MACs */
++
++/* C_VerifyInit initializes a verification operation, where the
++ * signature is an appendix to the data, and plaintext cannot
++ * cannot be recovered from the signature (e.g. DSA). */
++CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_Verify verifies a signature in a single-part operation,
++ * where the signature is an appendix to the data, and plaintext
++ * cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Verify)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* signed data */
++ CK_ULONG ulDataLen, /* length of signed data */
++ CK_BYTE_PTR pSignature, /* signature */
++ CK_ULONG ulSignatureLen /* signature length*/
++);
++#endif
++
++
++/* C_VerifyUpdate continues a multiple-part verification
++ * operation, where the signature is an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* signed data */
++ CK_ULONG ulPartLen /* length of signed data */
++);
++#endif
++
++
++/* C_VerifyFinal finishes a multiple-part verification
++ * operation, checking the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen /* signature length */
++);
++#endif
++
++
++/* C_VerifyRecoverInit initializes a signature verification
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_VerifyRecover verifies a signature in a single-part
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen, /* signature length */
++ CK_BYTE_PTR pData, /* gets signed data */
++ CK_ULONG_PTR pulDataLen /* gets signed data len */
++);
++#endif
++
++
++
++/* Dual-function cryptographic operations */
++
++/* C_DigestEncryptUpdate continues a multiple-part digesting
++ * and encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptDigestUpdate continues a multiple-part decryption and
++ * digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets plaintext len */
++);
++#endif
++
++
++/* C_SignEncryptUpdate continues a multiple-part signing and
++ * encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptVerifyUpdate continues a multiple-part decryption and
++ * verify operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets p-text length */
++);
++#endif
++
++
++
++/* Key management */
++
++/* C_GenerateKey generates a secret key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
++ CK_ULONG ulCount, /* # of attrs in template */
++ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
++);
++#endif
++
++
++/* C_GenerateKeyPair generates a public-key/private-key pair,
++ * creating new key objects. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session
++ * handle */
++ CK_MECHANISM_PTR pMechanism, /* key-gen
++ * mech. */
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
++ * for pub.
++ * key */
++ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
++ * attrs. */
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
++ * for priv.
++ * key */
++ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
++ * attrs. */
++ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
++ * key
++ * handle */
++ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
++ * priv. key
++ * handle */
++);
++#endif
++
++
++/* C_WrapKey wraps (i.e., encrypts) a key. */
++CK_PKCS11_FUNCTION_INFO(C_WrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
++ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
++ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
++ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
++ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
++);
++#endif
++
++
++/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
++ * key object. */
++CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
++ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
++ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
++ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++/* C_DeriveKey derives a key from a base key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
++ CK_OBJECT_HANDLE hBaseKey, /* base key */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++
++/* Random number generation */
++
++/* C_SeedRandom mixes additional seed material into the token's
++ * random number generator. */
++CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSeed, /* the seed material */
++ CK_ULONG ulSeedLen /* length of seed material */
++);
++#endif
++
++
++/* C_GenerateRandom generates random data. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR RandomData, /* receives the random data */
++ CK_ULONG ulRandomLen /* # of bytes to generate */
++);
++#endif
++
++
++
++/* Parallel function management */
++
++/* C_GetFunctionStatus is a legacy function; it obtains an
++ * updated status of a function running in parallel with an
++ * application. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CancelFunction is a legacy function; it cancels a function
++ * running in parallel. */
++CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Functions added in for Cryptoki Version 2.01 or later */
++
++/* C_WaitForSlotEvent waits for a slot event (token insertion,
++ * removal, etc.) to occur. */
++CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FLAGS flags, /* blocking/nonblocking flag */
++ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
++ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
++);
++#endif
+diff -up bind-9.9.6/lib/isc/include/pkcs11/pkcs11.h.native_pkcs11 bind-9.9.6/lib/isc/include/pkcs11/pkcs11.h
+--- bind-9.9.6/lib/isc/include/pkcs11/pkcs11.h.native_pkcs11 2014-10-09 13:30:47.839302940 +0200
++++ bind-9.9.6/lib/isc/include/pkcs11/pkcs11.h 2014-10-09 13:30:47.839302940 +0200
+@@ -0,0 +1,299 @@
++/* pkcs11.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++#ifndef _PKCS11_H_
++#define _PKCS11_H_ 1
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Before including this file (pkcs11.h) (or pkcs11t.h by
++ * itself), 6 platform-specific macros must be defined. These
++ * macros are described below, and typical definitions for them
++ * are also given. Be advised that these definitions can depend
++ * on both the platform and the compiler used (and possibly also
++ * on whether a Cryptoki library is linked statically or
++ * dynamically).
++ *
++ * In addition to defining these 6 macros, the packing convention
++ * for Cryptoki structures should be set. The Cryptoki
++ * convention on packing is that structures should be 1-byte
++ * aligned.
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, this might be done by using the following
++ * preprocessor directive before including pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(push, cryptoki, 1)
++ *
++ * and using the following preprocessor directive after including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(pop, cryptoki)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, this might be done by using
++ * the following preprocessor directive before including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(1)
++ *
++ * In a UNIX environment, you're on your own for this. You might
++ * not need to do (or be able to do!) anything.
++ *
++ *
++ * Now for the macros:
++ *
++ *
++ * 1. CK_PTR: The indirection string for making a pointer to an
++ * object. It can be used like this:
++ *
++ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, it might be defined by:
++ *
++ * #define CK_PTR far *
++ *
++ * In a typical UNIX environment, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ *
++ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
++ * an exportable Cryptoki library function definition out of a
++ * return type and a function name. It should be used in the
++ * following fashion to define the exposed Cryptoki functions in
++ * a Cryptoki library:
++ *
++ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * )
++ * {
++ * ...
++ * }
++ *
++ * If you're using Microsoft Developer Studio 5.0 to define a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllexport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to define a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
++ * an importable Cryptoki library function declaration out of a
++ * return type and a function name. It should be used in the
++ * following fashion:
++ *
++ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * );
++ *
++ * If you're using Microsoft Developer Studio 5.0 to declare a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllimport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to declare a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
++ * which makes a Cryptoki API function pointer declaration or
++ * function pointer type declaration out of a return type and a
++ * function name. It should be used in the following fashion:
++ *
++ * // Define funcPtr to be a pointer to a Cryptoki API function
++ * // taking arguments args and returning CK_RV.
++ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
++ *
++ * or
++ *
++ * // Define funcPtrType to be the type of a pointer to a
++ * // Cryptoki API function taking arguments args and returning
++ * // CK_RV, and then define funcPtr to be a variable of type
++ * // funcPtrType.
++ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
++ * funcPtrType funcPtr;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to access
++ * functions in a Win32 Cryptoki .dll, in might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __declspec(dllimport) (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to access functions in a Win16 Cryptoki .dll, it might
++ * be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __export _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
++ * a function pointer type for an application callback out of
++ * a return type for the callback and a name for the callback.
++ * It should be used in the following fashion:
++ *
++ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
++ *
++ * to declare a function pointer, myCallback, to a callback
++ * which takes arguments args and returns a CK_RV. It can also
++ * be used like this:
++ *
++ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
++ * myCallbackType myCallback;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to do Win32
++ * Cryptoki development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to do Win16 development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 6. NULL_PTR: This macro is the value of a NULL pointer.
++ *
++ * In any ANSI/ISO C environment (and in many others as well),
++ * this should best be defined by
++ *
++ * #ifndef NULL_PTR
++ * #define NULL_PTR 0
++ * #endif
++ */
++
++
++/* All the various Cryptoki types and #define'd values are in the
++ * file pkcs11t.h. */
++#include "pkcs11t.h"
++
++#define __PASTE(x,y) x##y
++
++
++/* ==============================================================
++ * Define the "extern" form of all the entry points.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ extern CK_DECLARE_FUNCTION(CK_RV, name)
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define the typedef form of all the entry points. That is, for
++ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
++ * a pointer to that kind of function.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define structed vector of entry points. A CK_FUNCTION_LIST
++ * contains a CK_VERSION indicating a library's Cryptoki version
++ * and then a whole slew of function pointers to the routines in
++ * the library. This type was declared, but not defined, in
++ * pkcs11t.h.
++ * ==============================================================
++ */
++
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ __PASTE(CK_,name) name;
++
++struct CK_FUNCTION_LIST {
++
++ CK_VERSION version; /* Cryptoki version */
++
++/* Pile all the function pointers into the CK_FUNCTION_LIST. */
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++};
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++#undef __PASTE
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff -up bind-9.9.6/lib/isc/include/pkcs11/pkcs11t.h.native_pkcs11 bind-9.9.6/lib/isc/include/pkcs11/pkcs11t.h
+--- bind-9.9.6/lib/isc/include/pkcs11/pkcs11t.h.native_pkcs11 2014-10-09 13:30:47.841302943 +0200
++++ bind-9.9.6/lib/isc/include/pkcs11/pkcs11t.h 2014-10-09 13:30:47.841302943 +0200
+@@ -0,0 +1,1977 @@
++/* pkcs11t.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* See top of pkcs11.h for information about the macros that
++ * must be defined and the structure-packing conventions that
++ * must be set before including this file. */
++
++#ifndef _PKCS11T_H_
++#define _PKCS11T_H_ 1
++
++#define CRYPTOKI_VERSION_MAJOR 2
++#define CRYPTOKI_VERSION_MINOR 30
++#define CRYPTOKI_VERSION_REVISION 0
++#define CRYPTOKI_VERSION_AMENDMENT 0
++
++#define CK_TRUE 1
++#define CK_FALSE 0
++
++#ifndef CK_DISABLE_TRUE_FALSE
++#ifndef FALSE
++#define FALSE CK_FALSE
++#endif
++
++#ifndef TRUE
++#define TRUE CK_TRUE
++#endif
++#endif
++
++/* an unsigned 8-bit value */
++typedef unsigned char CK_BYTE;
++
++/* an unsigned 8-bit character */
++typedef CK_BYTE CK_CHAR;
++
++/* an 8-bit UTF-8 character */
++typedef CK_BYTE CK_UTF8CHAR;
++
++/* a BYTE-sized Boolean flag */
++typedef CK_BYTE CK_BBOOL;
++
++/* an unsigned value, at least 32 bits long */
++typedef unsigned long int CK_ULONG;
++
++/* a signed value, the same size as a CK_ULONG */
++/* CK_LONG is new for v2.0 */
++typedef long int CK_LONG;
++
++/* at least 32 bits; each bit is a Boolean flag */
++typedef CK_ULONG CK_FLAGS;
++
++
++/* some special values for certain CK_ULONG variables */
++#define CK_UNAVAILABLE_INFORMATION (~0UL)
++#define CK_EFFECTIVELY_INFINITE 0
++
++
++typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++typedef CK_CHAR CK_PTR CK_CHAR_PTR;
++typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
++typedef CK_ULONG CK_PTR CK_ULONG_PTR;
++typedef void CK_PTR CK_VOID_PTR;
++
++/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
++typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
++
++
++/* The following value is always invalid if used as a session */
++/* handle or object handle */
++#define CK_INVALID_HANDLE 0
++
++
++typedef struct CK_VERSION {
++ CK_BYTE major; /* integer portion of version number */
++ CK_BYTE minor; /* 1/100ths portion of version number */
++} CK_VERSION;
++
++typedef CK_VERSION CK_PTR CK_VERSION_PTR;
++
++
++typedef struct CK_INFO {
++ /* manufacturerID and libraryDecription have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags; /* must be zero */
++
++ /* libraryDescription and libraryVersion are new for v2.0 */
++ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
++ CK_VERSION libraryVersion; /* version of library */
++} CK_INFO;
++
++typedef CK_INFO CK_PTR CK_INFO_PTR;
++
++
++/* CK_NOTIFICATION enumerates the types of notifications that
++ * Cryptoki provides to an application */
++/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_NOTIFICATION;
++#define CKN_SURRENDER 0
++
++/* The following notification is new for PKCS #11 v2.20 amendment 3 */
++#define CKN_OTP_CHANGED 1
++
++
++typedef CK_ULONG CK_SLOT_ID;
++
++typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
++
++
++/* CK_SLOT_INFO provides information about a slot */
++typedef struct CK_SLOT_INFO {
++ /* slotDescription and manufacturerID have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR slotDescription[64]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags;
++
++ /* hardwareVersion and firmwareVersion are new for v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++} CK_SLOT_INFO;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
++#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
++#define CKF_HW_SLOT 0x00000004 /* hardware slot */
++
++typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
++
++
++/* CK_TOKEN_INFO provides information about a token */
++typedef struct CK_TOKEN_INFO {
++ /* label, manufacturerID, and model have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR label[32]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_UTF8CHAR model[16]; /* blank padded */
++ CK_CHAR serialNumber[16]; /* blank padded */
++ CK_FLAGS flags; /* see below */
++
++ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
++ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
++ * changed from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulMaxSessionCount; /* max open sessions */
++ CK_ULONG ulSessionCount; /* sess. now open */
++ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
++ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
++ CK_ULONG ulMaxPinLen; /* in bytes */
++ CK_ULONG ulMinPinLen; /* in bytes */
++ CK_ULONG ulTotalPublicMemory; /* in bytes */
++ CK_ULONG ulFreePublicMemory; /* in bytes */
++ CK_ULONG ulTotalPrivateMemory; /* in bytes */
++ CK_ULONG ulFreePrivateMemory; /* in bytes */
++
++ /* hardwareVersion, firmwareVersion, and time are new for
++ * v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++ CK_CHAR utcTime[16]; /* time */
++} CK_TOKEN_INFO;
++
++/* The flags parameter is defined as follows:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RNG 0x00000001 /* has random #
++ * generator */
++#define CKF_WRITE_PROTECTED 0x00000002 /* token is
++ * write-
++ * protected */
++#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
++ * login */
++#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
++ * PIN is set */
++
++/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
++ * that means that *every* time the state of cryptographic
++ * operations of a session is successfully saved, all keys
++ * needed to continue those operations are stored in the state */
++#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
++
++/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
++ * that the token has some sort of clock. The time on that
++ * clock is returned in the token info structure */
++#define CKF_CLOCK_ON_TOKEN 0x00000040
++
++/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
++ * set, that means that there is some way for the user to login
++ * without sending a PIN through the Cryptoki library itself */
++#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
++
++/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
++ * that means that a single session with the token can perform
++ * dual simultaneous cryptographic operations (digest and
++ * encrypt; decrypt and digest; sign and encrypt; and decrypt
++ * and sign) */
++#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
++
++/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
++ * token has been initialized using C_InitializeToken or an
++ * equivalent mechanism outside the scope of PKCS #11.
++ * Calling C_InitializeToken when this flag is set will cause
++ * the token to be reinitialized. */
++#define CKF_TOKEN_INITIALIZED 0x00000400
++
++/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
++ * true, the token supports secondary authentication for
++ * private key objects. This flag is deprecated in v2.11 and
++ onwards. */
++#define CKF_SECONDARY_AUTHENTICATION 0x00000800
++
++/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect user login PIN has been entered at least once
++ * since the last successful authentication. */
++#define CKF_USER_PIN_COUNT_LOW 0x00010000
++
++/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect user PIN will it to become locked. */
++#define CKF_USER_PIN_FINAL_TRY 0x00020000
++
++/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
++ * user PIN has been locked. User login to the token is not
++ * possible. */
++#define CKF_USER_PIN_LOCKED 0x00040000
++
++/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the user PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
++
++/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect SO login PIN has been entered at least once since
++ * the last successful authentication. */
++#define CKF_SO_PIN_COUNT_LOW 0x00100000
++
++/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect SO PIN will it to become locked. */
++#define CKF_SO_PIN_FINAL_TRY 0x00200000
++
++/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
++ * PIN has been locked. SO login to the token is not possible.
++ */
++#define CKF_SO_PIN_LOCKED 0x00400000
++
++/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the SO PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
++
++/* CKF_ERROR_STATE if new for v2.30. If it is true,
++ * the token failed a FIPS 140-2 self-test and
++ * entered an error state. */
++#define CKF_ERROR_STATE 0x01000000
++
++typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
++
++
++/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
++ * identifies a session */
++typedef CK_ULONG CK_SESSION_HANDLE;
++
++typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
++
++
++/* CK_USER_TYPE enumerates the types of Cryptoki users */
++/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_USER_TYPE;
++/* Security Officer */
++#define CKU_SO 0
++/* Normal user */
++#define CKU_USER 1
++/* Context specific (added in v2.20) */
++#define CKU_CONTEXT_SPECIFIC 2
++
++/* CK_STATE enumerates the session states */
++/* CK_STATE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_STATE;
++#define CKS_RO_PUBLIC_SESSION 0
++#define CKS_RO_USER_FUNCTIONS 1
++#define CKS_RW_PUBLIC_SESSION 2
++#define CKS_RW_USER_FUNCTIONS 3
++#define CKS_RW_SO_FUNCTIONS 4
++
++
++/* CK_SESSION_INFO provides information about a session */
++typedef struct CK_SESSION_INFO {
++ CK_SLOT_ID slotID;
++ CK_STATE state;
++ CK_FLAGS flags; /* see below */
++
++ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulDeviceError; /* device-dependent error code */
++} CK_SESSION_INFO;
++
++/* The flags are defined in the following table:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RW_SESSION 0x00000002 /* session is r/w */
++#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
++
++typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
++
++
++/* CK_OBJECT_HANDLE is a token-specific identifier for an
++ * object */
++typedef CK_ULONG CK_OBJECT_HANDLE;
++
++typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
++
++
++/* CK_OBJECT_CLASS is a value that identifies the classes (or
++ * types) of objects that Cryptoki recognizes. It is defined
++ * as follows: */
++/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_OBJECT_CLASS;
++
++/* The following classes of objects are defined: */
++/* CKO_HW_FEATURE is new for v2.10 */
++/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
++/* CKO_MECHANISM is new for v2.20 */
++#define CKO_DATA 0x00000000
++#define CKO_CERTIFICATE 0x00000001
++#define CKO_PUBLIC_KEY 0x00000002
++#define CKO_PRIVATE_KEY 0x00000003
++#define CKO_SECRET_KEY 0x00000004
++#define CKO_HW_FEATURE 0x00000005
++#define CKO_DOMAIN_PARAMETERS 0x00000006
++#define CKO_MECHANISM 0x00000007
++
++/* CKO_OTP_KEY is new for PKCS #11 v2.20 amendment 1 */
++#define CKO_OTP_KEY 0x00000008
++
++#define CKO_VENDOR_DEFINED 0x80000000
++
++typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
++
++/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
++ * value that identifies the hardware feature type of an object
++ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
++typedef CK_ULONG CK_HW_FEATURE_TYPE;
++
++/* The following hardware feature types are defined */
++/* CKH_USER_INTERFACE is new for v2.20 */
++#define CKH_MONOTONIC_COUNTER 0x00000001
++#define CKH_CLOCK 0x00000002
++#define CKH_USER_INTERFACE 0x00000003
++#define CKH_VENDOR_DEFINED 0x80000000
++
++/* CK_KEY_TYPE is a value that identifies a key type */
++/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_KEY_TYPE;
++
++/* the following key types are defined: */
++#define CKK_RSA 0x00000000
++#define CKK_DSA 0x00000001
++#define CKK_DH 0x00000002
++
++/* CKK_ECDSA and CKK_KEA are new for v2.0 */
++/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
++#define CKK_ECDSA 0x00000003
++#define CKK_EC 0x00000003
++#define CKK_X9_42_DH 0x00000004
++#define CKK_KEA 0x00000005
++
++#define CKK_GENERIC_SECRET 0x00000010
++#define CKK_RC2 0x00000011
++#define CKK_RC4 0x00000012
++#define CKK_DES 0x00000013
++#define CKK_DES2 0x00000014
++#define CKK_DES3 0x00000015
++
++/* all these key types are new for v2.0 */
++#define CKK_CAST 0x00000016
++#define CKK_CAST3 0x00000017
++/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
++#define CKK_CAST5 0x00000018
++#define CKK_CAST128 0x00000018
++#define CKK_RC5 0x00000019
++#define CKK_IDEA 0x0000001A
++#define CKK_SKIPJACK 0x0000001B
++#define CKK_BATON 0x0000001C
++#define CKK_JUNIPER 0x0000001D
++#define CKK_CDMF 0x0000001E
++#define CKK_AES 0x0000001F
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKK_BLOWFISH 0x00000020
++#define CKK_TWOFISH 0x00000021
++
++/* SecurID, HOTP, and ACTI are new for PKCS #11 v2.20 amendment 1 */
++#define CKK_SECURID 0x00000022
++#define CKK_HOTP 0x00000023
++#define CKK_ACTI 0x00000024
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_CAMELLIA 0x00000025
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKK_ARIA 0x00000026
++
++/* From PKCS #11 v2.20 amendment 4 draft 2 */
++#define CKK_MD5_HMAC 0x00000027
++#define CKK_SHA_1_HMAC 0x00000028
++#define CKK_RIPEMD128_HMAC 0x00000029
++#define CKK_RIPEMD160_HMAC 0x0000002A
++#define CKK_SHA256_HMAC 0x0000002B
++#define CKK_SHA384_HMAC 0x0000002C
++#define CKK_SHA512_HMAC 0x0000002D
++#define CKK_SHA224_HMAC 0x0000002E
++
++/* From PKCS #11 v2.30 */
++#define CKK_SEED 0x0000002F
++#define CKK_GOSTR3410 0x00000030
++#define CKK_GOSTR3411 0x00000031
++#define CKK_GOST28147 0x00000032
++
++#define CKK_VENDOR_DEFINED 0x80000000
++
++
++/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
++ * type */
++/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_CERTIFICATE_TYPE;
++
++/* The following certificate types are defined: */
++/* CKC_X_509_ATTR_CERT is new for v2.10 */
++/* CKC_WTLS is new for v2.20 */
++#define CKC_X_509 0x00000000
++#define CKC_X_509_ATTR_CERT 0x00000001
++#define CKC_WTLS 0x00000002
++#define CKC_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
++ * type */
++/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_ATTRIBUTE_TYPE;
++
++/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
++ consists of an array of values. */
++#define CKF_ARRAY_ATTRIBUTE 0x40000000
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_FORMAT attribute */
++#define CK_OTP_FORMAT_DECIMAL 0
++#define CK_OTP_FORMAT_HEXADECIMAL 1
++#define CK_OTP_FORMAT_ALPHANUMERIC 2
++#define CK_OTP_FORMAT_BINARY 3
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1
++ and relates to the CKA_OTP_..._REQUIREMENT attributes */
++#define CK_OTP_PARAM_IGNORED 0
++#define CK_OTP_PARAM_OPTIONAL 1
++#define CK_OTP_PARAM_MANDATORY 2
++
++/* The following attribute types are defined: */
++#define CKA_CLASS 0x00000000
++#define CKA_TOKEN 0x00000001
++#define CKA_PRIVATE 0x00000002
++#define CKA_LABEL 0x00000003
++#define CKA_APPLICATION 0x00000010
++#define CKA_VALUE 0x00000011
++
++/* CKA_OBJECT_ID is new for v2.10 */
++#define CKA_OBJECT_ID 0x00000012
++
++#define CKA_CERTIFICATE_TYPE 0x00000080
++#define CKA_ISSUER 0x00000081
++#define CKA_SERIAL_NUMBER 0x00000082
++
++/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
++ * for v2.10 */
++#define CKA_AC_ISSUER 0x00000083
++#define CKA_OWNER 0x00000084
++#define CKA_ATTR_TYPES 0x00000085
++
++/* CKA_TRUSTED is new for v2.11 */
++#define CKA_TRUSTED 0x00000086
++
++/* CKA_CERTIFICATE_CATEGORY ...
++ * CKA_CHECK_VALUE are new for v2.20 */
++#define CKA_CERTIFICATE_CATEGORY 0x00000087
++#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
++#define CKA_URL 0x00000089
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
++/* One from v2.30? */
++#define CKA_NAME_HASH_ALGORITH 0x0000008C
++#define CKA_CHECK_VALUE 0x00000090
++
++#define CKA_KEY_TYPE 0x00000100
++#define CKA_SUBJECT 0x00000101
++#define CKA_ID 0x00000102
++#define CKA_SENSITIVE 0x00000103
++#define CKA_ENCRYPT 0x00000104
++#define CKA_DECRYPT 0x00000105
++#define CKA_WRAP 0x00000106
++#define CKA_UNWRAP 0x00000107
++#define CKA_SIGN 0x00000108
++#define CKA_SIGN_RECOVER 0x00000109
++#define CKA_VERIFY 0x0000010A
++#define CKA_VERIFY_RECOVER 0x0000010B
++#define CKA_DERIVE 0x0000010C
++#define CKA_START_DATE 0x00000110
++#define CKA_END_DATE 0x00000111
++#define CKA_MODULUS 0x00000120
++#define CKA_MODULUS_BITS 0x00000121
++#define CKA_PUBLIC_EXPONENT 0x00000122
++#define CKA_PRIVATE_EXPONENT 0x00000123
++#define CKA_PRIME_1 0x00000124
++#define CKA_PRIME_2 0x00000125
++#define CKA_EXPONENT_1 0x00000126
++#define CKA_EXPONENT_2 0x00000127
++#define CKA_COEFFICIENT 0x00000128
++#define CKA_PRIME 0x00000130
++#define CKA_SUBPRIME 0x00000131
++#define CKA_BASE 0x00000132
++
++/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
++#define CKA_PRIME_BITS 0x00000133
++#define CKA_SUBPRIME_BITS 0x00000134
++#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
++/* (To retain backwards-compatibility) */
++
++#define CKA_VALUE_BITS 0x00000160
++#define CKA_VALUE_LEN 0x00000161
++
++/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
++ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
++ * and CKA_EC_POINT are new for v2.0 */
++#define CKA_EXTRACTABLE 0x00000162
++#define CKA_LOCAL 0x00000163
++#define CKA_NEVER_EXTRACTABLE 0x00000164
++#define CKA_ALWAYS_SENSITIVE 0x00000165
++
++/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
++#define CKA_KEY_GEN_MECHANISM 0x00000166
++
++#define CKA_MODIFIABLE 0x00000170
++
++/* From v2.30? */
++#define CKA_COPYABLE 0x00000171
++
++/* CKA_ECDSA_PARAMS is deprecated in v2.11,
++ * CKA_EC_PARAMS is preferred. */
++#define CKA_ECDSA_PARAMS 0x00000180
++#define CKA_EC_PARAMS 0x00000180
++
++#define CKA_EC_POINT 0x00000181
++
++/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
++ * are new for v2.10. Deprecated in v2.11 and onwards. */
++#define CKA_SECONDARY_AUTH 0x00000200
++#define CKA_AUTH_PIN_FLAGS 0x00000201
++
++/* CKA_ALWAYS_AUTHENTICATE ...
++ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
++#define CKA_ALWAYS_AUTHENTICATE 0x00000202
++
++#define CKA_WRAP_WITH_TRUSTED 0x00000210
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++
++/* CKA_OTP... atttributes are new for PKCS #11 v2.20 amendment 3. */
++#define CKA_OTP_FORMAT 0x00000220
++#define CKA_OTP_LENGTH 0x00000221
++#define CKA_OTP_TIME_INTERVAL 0x00000222
++#define CKA_OTP_USER_FRIENDLY_MODE 0x00000223
++#define CKA_OTP_CHALLENGE_REQUIREMENT 0x00000224
++#define CKA_OTP_TIME_REQUIREMENT 0x00000225
++#define CKA_OTP_COUNTER_REQUIREMENT 0x00000226
++#define CKA_OTP_PIN_REQUIREMENT 0x00000227
++#define CKA_OTP_COUNTER 0x0000022E
++#define CKA_OTP_TIME 0x0000022F
++#define CKA_OTP_USER_IDENTIFIER 0x0000022A
++#define CKA_OTP_SERVICE_IDENTIFIER 0x0000022B
++#define CKA_OTP_SERVICE_LOGO 0x0000022C
++#define CKA_OTP_SERVICE_LOGO_TYPE 0x0000022D
++
++/* CKA_GOST... */
++#define CKA_GOSTR3410_PARAMS 0x00000250
++#define CKA_GOSTR3411_PARAMS 0x00000251
++#define CKA_GOST28147_PARAMS 0x00000252
++
++/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
++ * are new for v2.10 */
++#define CKA_HW_FEATURE_TYPE 0x00000300
++#define CKA_RESET_ON_INIT 0x00000301
++#define CKA_HAS_RESET 0x00000302
++
++/* The following attributes are new for v2.20 */
++#define CKA_PIXEL_X 0x00000400
++#define CKA_PIXEL_Y 0x00000401
++#define CKA_RESOLUTION 0x00000402
++#define CKA_CHAR_ROWS 0x00000403
++#define CKA_CHAR_COLUMNS 0x00000404
++#define CKA_COLOR 0x00000405
++#define CKA_BITS_PER_PIXEL 0x00000406
++#define CKA_CHAR_SETS 0x00000480
++#define CKA_ENCODING_METHODS 0x00000481
++#define CKA_MIME_TYPES 0x00000482
++#define CKA_MECHANISM_TYPE 0x00000500
++#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
++#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
++#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
++#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
++/* From v2.30? */
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++#define CKA_DERIVE_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000213)
++
++#define CKA_VENDOR_DEFINED 0x80000000
++
++/* CK_ATTRIBUTE is a structure that includes the type, length
++ * and value of an attribute */
++typedef struct CK_ATTRIBUTE {
++ CK_ATTRIBUTE_TYPE type;
++ CK_VOID_PTR pValue;
++
++ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulValueLen; /* in bytes */
++} CK_ATTRIBUTE;
++
++typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
++
++
++/* CK_DATE is a structure that defines a date */
++typedef struct CK_DATE{
++ CK_CHAR year[4]; /* the year ("1900" - "9999") */
++ CK_CHAR month[2]; /* the month ("01" - "12") */
++ CK_CHAR day[2]; /* the day ("01" - "31") */
++} CK_DATE;
++
++
++/* CK_MECHANISM_TYPE is a value that identifies a mechanism
++ * type */
++/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_MECHANISM_TYPE;
++
++/* the following mechanism types are defined: */
++#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
++#define CKM_RSA_PKCS 0x00000001
++#define CKM_RSA_9796 0x00000002
++#define CKM_RSA_X_509 0x00000003
++
++/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
++ * are new for v2.0. They are mechanisms which hash and sign */
++#define CKM_MD2_RSA_PKCS 0x00000004
++#define CKM_MD5_RSA_PKCS 0x00000005
++#define CKM_SHA1_RSA_PKCS 0x00000006
++
++/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
++ * CKM_RSA_PKCS_OAEP are new for v2.10 */
++#define CKM_RIPEMD128_RSA_PKCS 0x00000007
++#define CKM_RIPEMD160_RSA_PKCS 0x00000008
++#define CKM_RSA_PKCS_OAEP 0x00000009
++
++/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
++ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
++#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
++#define CKM_RSA_X9_31 0x0000000B
++#define CKM_SHA1_RSA_X9_31 0x0000000C
++#define CKM_RSA_PKCS_PSS 0x0000000D
++#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
++
++#define CKM_DSA_KEY_PAIR_GEN 0x00000010
++#define CKM_DSA 0x00000011
++#define CKM_DSA_SHA1 0x00000012
++/* Other DSAs */
++#define CKM_DSA_SHA224 0x00000013
++#define CKM_DSA_SHA256 0x00000014
++#define CKM_DSA_SHA384 0x00000015
++#define CKM_DSA_SHA512 0x00000016
++
++#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
++#define CKM_DH_PKCS_DERIVE 0x00000021
++
++/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
++ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
++ * v2.11 */
++#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
++#define CKM_X9_42_DH_DERIVE 0x00000031
++#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
++#define CKM_X9_42_MQV_DERIVE 0x00000033
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_RSA_PKCS 0x00000040
++#define CKM_SHA384_RSA_PKCS 0x00000041
++#define CKM_SHA512_RSA_PKCS 0x00000042
++#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
++#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
++#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
++
++/* SHA-224 RSA mechanisms are new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_RSA_PKCS 0x00000046
++#define CKM_SHA224_RSA_PKCS_PSS 0x00000047
++
++#define CKM_RC2_KEY_GEN 0x00000100
++#define CKM_RC2_ECB 0x00000101
++#define CKM_RC2_CBC 0x00000102
++#define CKM_RC2_MAC 0x00000103
++
++/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
++#define CKM_RC2_MAC_GENERAL 0x00000104
++#define CKM_RC2_CBC_PAD 0x00000105
++
++#define CKM_RC4_KEY_GEN 0x00000110
++#define CKM_RC4 0x00000111
++#define CKM_DES_KEY_GEN 0x00000120
++#define CKM_DES_ECB 0x00000121
++#define CKM_DES_CBC 0x00000122
++#define CKM_DES_MAC 0x00000123
++
++/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
++#define CKM_DES_MAC_GENERAL 0x00000124
++#define CKM_DES_CBC_PAD 0x00000125
++
++#define CKM_DES2_KEY_GEN 0x00000130
++#define CKM_DES3_KEY_GEN 0x00000131
++#define CKM_DES3_ECB 0x00000132
++#define CKM_DES3_CBC 0x00000133
++#define CKM_DES3_MAC 0x00000134
++
++/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
++ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
++ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0,
++ * CKM_DES3_CMAC_GENERAL and CKM_DES3_CMAC are from v2.30? */
++#define CKM_DES3_MAC_GENERAL 0x00000135
++#define CKM_DES3_CBC_PAD 0x00000136
++#define CKM_DES3_CMAC_GENERAL 0x00000137
++#define CKM_DES3_CMAC 0x00000138
++#define CKM_CDMF_KEY_GEN 0x00000140
++#define CKM_CDMF_ECB 0x00000141
++#define CKM_CDMF_CBC 0x00000142
++#define CKM_CDMF_MAC 0x00000143
++#define CKM_CDMF_MAC_GENERAL 0x00000144
++#define CKM_CDMF_CBC_PAD 0x00000145
++
++/* the following four DES mechanisms are new for v2.20 */
++#define CKM_DES_OFB64 0x00000150
++#define CKM_DES_OFB8 0x00000151
++#define CKM_DES_CFB64 0x00000152
++#define CKM_DES_CFB8 0x00000153
++
++#define CKM_MD2 0x00000200
++
++/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD2_HMAC 0x00000201
++#define CKM_MD2_HMAC_GENERAL 0x00000202
++
++#define CKM_MD5 0x00000210
++
++/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD5_HMAC 0x00000211
++#define CKM_MD5_HMAC_GENERAL 0x00000212
++
++#define CKM_SHA_1 0x00000220
++
++/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
++#define CKM_SHA_1_HMAC 0x00000221
++#define CKM_SHA_1_HMAC_GENERAL 0x00000222
++
++/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
++ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
++ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
++#define CKM_RIPEMD128 0x00000230
++#define CKM_RIPEMD128_HMAC 0x00000231
++#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
++#define CKM_RIPEMD160 0x00000240
++#define CKM_RIPEMD160_HMAC 0x00000241
++#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256 0x00000250
++#define CKM_SHA256_HMAC 0x00000251
++#define CKM_SHA256_HMAC_GENERAL 0x00000252
++
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224 0x00000255
++#define CKM_SHA224_HMAC 0x00000256
++#define CKM_SHA224_HMAC_GENERAL 0x00000257
++
++#define CKM_SHA384 0x00000260
++#define CKM_SHA384_HMAC 0x00000261
++#define CKM_SHA384_HMAC_GENERAL 0x00000262
++#define CKM_SHA512 0x00000270
++#define CKM_SHA512_HMAC 0x00000271
++#define CKM_SHA512_HMAC_GENERAL 0x00000272
++
++/* SecurID is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_SECURID_KEY_GEN 0x00000280
++#define CKM_SECURID 0x00000282
++
++/* HOTP is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_HOTP_KEY_GEN 0x00000290
++#define CKM_HOTP 0x00000291
++
++/* ACTI is new for PKCS #11 v2.20 amendment 1 */
++#define CKM_ACTI 0x000002A0
++#define CKM_ACTI_KEY_GEN 0x000002A1
++
++/* All of the following mechanisms are new for v2.0 */
++/* Note that CAST128 and CAST5 are the same algorithm */
++#define CKM_CAST_KEY_GEN 0x00000300
++#define CKM_CAST_ECB 0x00000301
++#define CKM_CAST_CBC 0x00000302
++#define CKM_CAST_MAC 0x00000303
++#define CKM_CAST_MAC_GENERAL 0x00000304
++#define CKM_CAST_CBC_PAD 0x00000305
++#define CKM_CAST3_KEY_GEN 0x00000310
++#define CKM_CAST3_ECB 0x00000311
++#define CKM_CAST3_CBC 0x00000312
++#define CKM_CAST3_MAC 0x00000313
++#define CKM_CAST3_MAC_GENERAL 0x00000314
++#define CKM_CAST3_CBC_PAD 0x00000315
++#define CKM_CAST5_KEY_GEN 0x00000320
++#define CKM_CAST128_KEY_GEN 0x00000320
++#define CKM_CAST5_ECB 0x00000321
++#define CKM_CAST128_ECB 0x00000321
++#define CKM_CAST5_CBC 0x00000322
++#define CKM_CAST128_CBC 0x00000322
++#define CKM_CAST5_MAC 0x00000323
++#define CKM_CAST128_MAC 0x00000323
++#define CKM_CAST5_MAC_GENERAL 0x00000324
++#define CKM_CAST128_MAC_GENERAL 0x00000324
++#define CKM_CAST5_CBC_PAD 0x00000325
++#define CKM_CAST128_CBC_PAD 0x00000325
++#define CKM_RC5_KEY_GEN 0x00000330
++#define CKM_RC5_ECB 0x00000331
++#define CKM_RC5_CBC 0x00000332
++#define CKM_RC5_MAC 0x00000333
++#define CKM_RC5_MAC_GENERAL 0x00000334
++#define CKM_RC5_CBC_PAD 0x00000335
++#define CKM_IDEA_KEY_GEN 0x00000340
++#define CKM_IDEA_ECB 0x00000341
++#define CKM_IDEA_CBC 0x00000342
++#define CKM_IDEA_MAC 0x00000343
++#define CKM_IDEA_MAC_GENERAL 0x00000344
++#define CKM_IDEA_CBC_PAD 0x00000345
++#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
++#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
++#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
++#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
++#define CKM_XOR_BASE_AND_DATA 0x00000364
++#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
++#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
++#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
++#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
++
++/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
++ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
++ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
++#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
++#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
++#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
++#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
++#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
++
++/* CKM_TLS_PRF is new for v2.20 */
++#define CKM_TLS_PRF 0x00000378
++
++#define CKM_SSL3_MD5_MAC 0x00000380
++#define CKM_SSL3_SHA1_MAC 0x00000381
++#define CKM_MD5_KEY_DERIVATION 0x00000390
++#define CKM_MD2_KEY_DERIVATION 0x00000391
++#define CKM_SHA1_KEY_DERIVATION 0x00000392
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_KEY_DERIVATION 0x00000393
++#define CKM_SHA384_KEY_DERIVATION 0x00000394
++#define CKM_SHA512_KEY_DERIVATION 0x00000395
++
++/* SHA-224 key derivation is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_SHA224_KEY_DERIVATION 0x00000396
++
++#define CKM_PBE_MD2_DES_CBC 0x000003A0
++#define CKM_PBE_MD5_DES_CBC 0x000003A1
++#define CKM_PBE_MD5_CAST_CBC 0x000003A2
++#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
++#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
++#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
++#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
++#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
++#define CKM_PBE_SHA1_RC4_128 0x000003A6
++#define CKM_PBE_SHA1_RC4_40 0x000003A7
++#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
++#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
++#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
++#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
++
++/* CKM_PKCS5_PBKD2 is new for v2.10 */
++#define CKM_PKCS5_PBKD2 0x000003B0
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
++
++/* WTLS mechanisms are new for v2.20 */
++#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
++#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
++#define CKM_WTLS_PRF 0x000003D3
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
++
++#define CKM_KEY_WRAP_LYNKS 0x00000400
++#define CKM_KEY_WRAP_SET_OAEP 0x00000401
++
++/* CKM_CMS_SIG is new for v2.20 */
++#define CKM_CMS_SIG 0x00000500
++
++/* CKM_KIP mechanisms are new for PKCS #11 v2.20 amendment 2 */
++#define CKM_KIP_DERIVE 0x00000510
++#define CKM_KIP_WRAP 0x00000511
++#define CKM_KIP_MAC 0x00000512
++
++/* Camellia is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_CAMELLIA_KEY_GEN 0x00000550
++#define CKM_CAMELLIA_ECB 0x00000551
++#define CKM_CAMELLIA_CBC 0x00000552
++#define CKM_CAMELLIA_MAC 0x00000553
++#define CKM_CAMELLIA_MAC_GENERAL 0x00000554
++#define CKM_CAMELLIA_CBC_PAD 0x00000555
++#define CKM_CAMELLIA_ECB_ENCRYPT_DATA 0x00000556
++#define CKM_CAMELLIA_CBC_ENCRYPT_DATA 0x00000557
++#define CKM_CAMELLIA_CTR 0x00000558
++
++/* ARIA is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_ARIA_KEY_GEN 0x00000560
++#define CKM_ARIA_ECB 0x00000561
++#define CKM_ARIA_CBC 0x00000562
++#define CKM_ARIA_MAC 0x00000563
++#define CKM_ARIA_MAC_GENERAL 0x00000564
++#define CKM_ARIA_CBC_PAD 0x00000565
++#define CKM_ARIA_ECB_ENCRYPT_DATA 0x00000566
++#define CKM_ARIA_CBC_ENCRYPT_DATA 0x00000567
++
++/* SEED is new from PKCS #11 v2.30? */
++#define CKM_SEED_KEY_GEN 0x00000650
++#define CKM_SEED_ECB 0x00000651
++#define CKM_SEED_CBC 0x00000652
++#define CKM_SEED_MAC 0x00000653
++#define CKM_SEED_MAC_GENERAL 0x00000654
++#define CKM_SEED_CBC_PAD 0x00000655
++#define CKM_SEED_ECB_ENCRYPT_DATA 0x00000656
++#define CKM_SEED_CBC_ENCRYPT_DATA 0x00000657
++
++/* Fortezza mechanisms */
++#define CKM_SKIPJACK_KEY_GEN 0x00001000
++#define CKM_SKIPJACK_ECB64 0x00001001
++#define CKM_SKIPJACK_CBC64 0x00001002
++#define CKM_SKIPJACK_OFB64 0x00001003
++#define CKM_SKIPJACK_CFB64 0x00001004
++#define CKM_SKIPJACK_CFB32 0x00001005
++#define CKM_SKIPJACK_CFB16 0x00001006
++#define CKM_SKIPJACK_CFB8 0x00001007
++#define CKM_SKIPJACK_WRAP 0x00001008
++#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
++#define CKM_SKIPJACK_RELAYX 0x0000100a
++#define CKM_KEA_KEY_PAIR_GEN 0x00001010
++#define CKM_KEA_KEY_DERIVE 0x00001011
++#define CKM_FORTEZZA_TIMESTAMP 0x00001020
++#define CKM_BATON_KEY_GEN 0x00001030
++#define CKM_BATON_ECB128 0x00001031
++#define CKM_BATON_ECB96 0x00001032
++#define CKM_BATON_CBC128 0x00001033
++#define CKM_BATON_COUNTER 0x00001034
++#define CKM_BATON_SHUFFLE 0x00001035
++#define CKM_BATON_WRAP 0x00001036
++
++/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
++ * CKM_EC_KEY_PAIR_GEN is preferred */
++#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
++#define CKM_EC_KEY_PAIR_GEN 0x00001040
++
++#define CKM_ECDSA 0x00001041
++#define CKM_ECDSA_SHA1 0x00001042
++
++/* From v2.30? */
++#define CKM_ECDSA_SHA224 0x00001043
++#define CKM_ECDSA_SHA256 0x00001044
++#define CKM_ECDSA_SHA384 0x00001045
++#define CKM_ECDSA_SHA512 0x00001046
++
++/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
++ * are new for v2.11 */
++#define CKM_ECDH1_DERIVE 0x00001050
++#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
++#define CKM_ECMQV_DERIVE 0x00001052
++
++#define CKM_JUNIPER_KEY_GEN 0x00001060
++#define CKM_JUNIPER_ECB128 0x00001061
++#define CKM_JUNIPER_CBC128 0x00001062
++#define CKM_JUNIPER_COUNTER 0x00001063
++#define CKM_JUNIPER_SHUFFLE 0x00001064
++#define CKM_JUNIPER_WRAP 0x00001065
++#define CKM_FASTHASH 0x00001070
++
++/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
++ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
++ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
++ * new for v2.11 */
++#define CKM_AES_KEY_GEN 0x00001080
++#define CKM_AES_ECB 0x00001081
++#define CKM_AES_CBC 0x00001082
++#define CKM_AES_MAC 0x00001083
++#define CKM_AES_MAC_GENERAL 0x00001084
++#define CKM_AES_CBC_PAD 0x00001085
++
++/* AES counter mode is new for PKCS #11 v2.20 amendment 3 */
++#define CKM_AES_CTR 0x00001086
++
++/* Missing CKM_AES_GCM and co! */
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKM_BLOWFISH_KEY_GEN 0x00001090
++#define CKM_BLOWFISH_CBC 0x00001091
++#define CKM_TWOFISH_KEY_GEN 0x00001092
++#define CKM_TWOFISH_CBC 0x00001093
++
++
++/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
++#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
++#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
++#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
++#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
++#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
++#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
++
++/* GOST mechanism from v2.30? */
++#define CKM_GOSTR3410_KEY_PAIR_GEN 0x00001200
++#define CKM_GOSTR3410 0x00001201
++#define CKM_GOSTR3410_WITH_GOSTR3411 0x00001202
++#define CKM_GOSTR3410_KEY_WRAP 0x00001203
++#define CKM_GOSTR3410_DERIVE 0x00001204
++#define CKM_GOSTR3411 0x00001210
++#define CKM_GOSTR3411_HMAC 0x00001211
++#define CKM_GOST28147_KEY_GEN 0x00001220
++#define CKM_GOST28147_ECB 0x00001221
++#define CKM_GOST28147 0x00001222
++#define CKM_GOST28147_MAC 0x00001223
++#define CKM_GOST28147_KEY_WRAP 0x00001224
++
++#define CKM_DSA_PARAMETER_GEN 0x00002000
++#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
++#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
++
++/* Missing AES_OFB and co, and RSA_PKCS 1_1 */
++
++#define CKM_VENDOR_DEFINED 0x80000000
++
++typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
++
++
++/* CK_MECHANISM is a structure that specifies a particular
++ * mechanism */
++typedef struct CK_MECHANISM {
++ CK_MECHANISM_TYPE mechanism;
++ CK_VOID_PTR pParameter;
++
++ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulParameterLen; /* in bytes */
++} CK_MECHANISM;
++
++typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
++
++
++/* CK_MECHANISM_INFO provides information about a particular
++ * mechanism */
++typedef struct CK_MECHANISM_INFO {
++ CK_ULONG ulMinKeySize;
++ CK_ULONG ulMaxKeySize;
++ CK_FLAGS flags;
++} CK_MECHANISM_INFO;
++
++/* The flags are defined as follows:
++ * Bit Flag Mask Meaning */
++#define CKF_HW 0x00000001 /* performed by HW */
++
++/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
++ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
++ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
++ * and CKF_DERIVE are new for v2.0. They specify whether or not
++ * a mechanism can be used for a particular task */
++#define CKF_ENCRYPT 0x00000100
++#define CKF_DECRYPT 0x00000200
++#define CKF_DIGEST 0x00000400
++#define CKF_SIGN 0x00000800
++#define CKF_SIGN_RECOVER 0x00001000
++#define CKF_VERIFY 0x00002000
++#define CKF_VERIFY_RECOVER 0x00004000
++#define CKF_GENERATE 0x00008000
++#define CKF_GENERATE_KEY_PAIR 0x00010000
++#define CKF_WRAP 0x00020000
++#define CKF_UNWRAP 0x00040000
++#define CKF_DERIVE 0x00080000
++
++/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
++ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
++ * describe a token's EC capabilities not available in mechanism
++ * information. */
++#define CKF_EC_F_P 0x00100000
++#define CKF_EC_F_2M 0x00200000
++#define CKF_EC_ECPARAMETERS 0x00400000
++#define CKF_EC_NAMEDCURVE 0x00800000
++#define CKF_EC_UNCOMPRESS 0x01000000
++#define CKF_EC_COMPRESS 0x02000000
++
++#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
++
++typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
++
++
++/* CK_RV is a value that identifies the return value of a
++ * Cryptoki function */
++/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_RV;
++
++#define CKR_OK 0x00000000
++#define CKR_CANCEL 0x00000001
++#define CKR_HOST_MEMORY 0x00000002
++#define CKR_SLOT_ID_INVALID 0x00000003
++
++/* CKR_FLAGS_INVALID was removed for v2.0 */
++
++/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
++#define CKR_GENERAL_ERROR 0x00000005
++#define CKR_FUNCTION_FAILED 0x00000006
++
++/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
++ * and CKR_CANT_LOCK are new for v2.01 */
++#define CKR_ARGUMENTS_BAD 0x00000007
++#define CKR_NO_EVENT 0x00000008
++#define CKR_NEED_TO_CREATE_THREADS 0x00000009
++#define CKR_CANT_LOCK 0x0000000A
++
++#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
++#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
++#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
++#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
++/* New CKR_COPY_PROHIBITED in v2.30? */
++#define CKR_COPY_PROHIBITED 0x0000001A
++#define CKR_DATA_INVALID 0x00000020
++#define CKR_DATA_LEN_RANGE 0x00000021
++#define CKR_DEVICE_ERROR 0x00000030
++#define CKR_DEVICE_MEMORY 0x00000031
++#define CKR_DEVICE_REMOVED 0x00000032
++#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
++#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
++#define CKR_FUNCTION_CANCELED 0x00000050
++#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
++
++/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
++#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
++
++#define CKR_KEY_HANDLE_INVALID 0x00000060
++
++/* CKR_KEY_SENSITIVE was removed for v2.0 */
++
++#define CKR_KEY_SIZE_RANGE 0x00000062
++#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
++
++/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
++ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
++ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
++ * v2.0 */
++#define CKR_KEY_NOT_NEEDED 0x00000064
++#define CKR_KEY_CHANGED 0x00000065
++#define CKR_KEY_NEEDED 0x00000066
++#define CKR_KEY_INDIGESTIBLE 0x00000067
++#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
++#define CKR_KEY_NOT_WRAPPABLE 0x00000069
++#define CKR_KEY_UNEXTRACTABLE 0x0000006A
++
++#define CKR_MECHANISM_INVALID 0x00000070
++#define CKR_MECHANISM_PARAM_INVALID 0x00000071
++
++/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
++ * were removed for v2.0 */
++#define CKR_OBJECT_HANDLE_INVALID 0x00000082
++#define CKR_OPERATION_ACTIVE 0x00000090
++#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
++#define CKR_PIN_INCORRECT 0x000000A0
++#define CKR_PIN_INVALID 0x000000A1
++#define CKR_PIN_LEN_RANGE 0x000000A2
++
++/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
++#define CKR_PIN_EXPIRED 0x000000A3
++#define CKR_PIN_LOCKED 0x000000A4
++
++#define CKR_SESSION_CLOSED 0x000000B0
++#define CKR_SESSION_COUNT 0x000000B1
++#define CKR_SESSION_HANDLE_INVALID 0x000000B3
++#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
++#define CKR_SESSION_READ_ONLY 0x000000B5
++#define CKR_SESSION_EXISTS 0x000000B6
++
++/* CKR_SESSION_READ_ONLY_EXISTS and
++ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
++#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
++#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
++
++#define CKR_SIGNATURE_INVALID 0x000000C0
++#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
++#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
++#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
++#define CKR_TOKEN_NOT_PRESENT 0x000000E0
++#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
++#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
++#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
++#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
++#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
++
++/* private extra values */
++#define CKR_LIBRARY_ALREADY_INITIALIZED 0x000000FD
++#define CKR_LIBRARY_FAILED_TO_LOAD 0x000000FE
++#define CKR_SYMBOL_RESOLUTION_FAILED 0x000000FF
++
++#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
++#define CKR_USER_NOT_LOGGED_IN 0x00000101
++#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
++#define CKR_USER_TYPE_INVALID 0x00000103
++
++/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
++ * are new to v2.01 */
++#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
++#define CKR_USER_TOO_MANY_TYPES 0x00000105
++
++#define CKR_WRAPPED_KEY_INVALID 0x00000110
++#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
++#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
++#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
++#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
++#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
++
++/* These are new to v2.0 */
++#define CKR_RANDOM_NO_RNG 0x00000121
++
++/* These are new to v2.11 */
++#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
++
++/* These are new to v2.0 */
++#define CKR_BUFFER_TOO_SMALL 0x00000150
++#define CKR_SAVED_STATE_INVALID 0x00000160
++#define CKR_INFORMATION_SENSITIVE 0x00000170
++#define CKR_STATE_UNSAVEABLE 0x00000180
++
++/* These are new to v2.01 */
++#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
++#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
++#define CKR_MUTEX_BAD 0x000001A0
++#define CKR_MUTEX_NOT_LOCKED 0x000001A1
++
++/* The following return values are new for PKCS #11 v2.20 amendment 3 */
++#define CKR_NEW_PIN_MODE 0x000001B0
++#define CKR_NEXT_OTP 0x000001B1
++
++/* New from v2.30? */
++#define CKR_EXCEEDED_MAX_ITERATIONS 0x000001B5
++#define CKR_FIPS_SELF_TEST_FAILED 0x000001B6
++#define CKR_LIBRARY_LOAD_FAILED 0x000001B7
++#define CKR_PIN_TOO_WEAK 0x000001B8
++#define CKR_PUBLIC_KEY_INVALID 0x000001B9
++
++/* This is new to v2.20 */
++#define CKR_FUNCTION_REJECTED 0x00000200
++
++#define CKR_VENDOR_DEFINED 0x80000000
++
++
++/* CK_NOTIFY is an application callback that processes events */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication /* passed to C_OpenSession */
++);
++
++
++/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
++ * version and pointers of appropriate types to all the
++ * Cryptoki functions */
++/* CK_FUNCTION_LIST is new for v2.0 */
++typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
++
++typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
++
++typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
++
++
++/* CK_CREATEMUTEX is an application callback for creating a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
++ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
++);
++
++
++/* CK_DESTROYMUTEX is an application callback for destroying a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_LOCKMUTEX is an application callback for locking a mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_UNLOCKMUTEX is an application callback for unlocking a
++ * mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_C_INITIALIZE_ARGS provides the optional arguments to
++ * C_Initialize */
++typedef struct CK_C_INITIALIZE_ARGS {
++ CK_CREATEMUTEX CreateMutex;
++ CK_DESTROYMUTEX DestroyMutex;
++ CK_LOCKMUTEX LockMutex;
++ CK_UNLOCKMUTEX UnlockMutex;
++ CK_FLAGS flags;
++ CK_VOID_PTR pReserved;
++} CK_C_INITIALIZE_ARGS;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
++#define CKF_OS_LOCKING_OK 0x00000002
++
++typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
++
++
++/* additional flags for parameters to functions */
++
++/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
++#define CKF_DONT_BLOCK 1
++
++/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
++ * Generation Function (MGF) applied to a message block when
++ * formatting a message block for the PKCS #1 OAEP encryption
++ * scheme. */
++typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
++
++typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
++
++/* The following MGFs are defined */
++/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
++ * are new for v2.20 */
++#define CKG_MGF1_SHA1 0x00000001
++#define CKG_MGF1_SHA256 0x00000002
++#define CKG_MGF1_SHA384 0x00000003
++#define CKG_MGF1_SHA512 0x00000004
++/* SHA-224 is new for PKCS #11 v2.20 amendment 3 */
++#define CKG_MGF1_SHA224 0x00000005
++
++/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
++ * of the encoding parameter when formatting a message block
++ * for the PKCS #1 OAEP encryption scheme. */
++typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
++
++typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
++
++/* The following encoding parameter sources are defined */
++#define CKZ_DATA_SPECIFIED 0x00000001
++
++/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
++ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_OAEP mechanism. */
++typedef struct CK_RSA_PKCS_OAEP_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
++ CK_VOID_PTR pSourceData;
++ CK_ULONG ulSourceDataLen;
++} CK_RSA_PKCS_OAEP_PARAMS;
++
++typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
++
++/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
++ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_PSS mechanism(s). */
++typedef struct CK_RSA_PKCS_PSS_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_ULONG sLen;
++} CK_RSA_PKCS_PSS_PARAMS;
++
++typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
++
++/* CK_EC_KDF_TYPE is new for v2.11. */
++typedef CK_ULONG CK_EC_KDF_TYPE;
++
++/* The following EC Key Derivation Functions are defined */
++#define CKD_NULL 0x00000001
++#define CKD_SHA1_KDF 0x00000002
++
++/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
++ * where each party contributes one key pair.
++ */
++typedef struct CK_ECDH1_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_ECDH1_DERIVE_PARAMS;
++
++typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
++
++
++/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
++typedef struct CK_ECDH2_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_ECDH2_DERIVE_PARAMS;
++
++typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_ECMQV_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_ECMQV_DERIVE_PARAMS;
++
++typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
++
++/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
++ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
++typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
++typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
++
++/* The following X9.42 DH key derivation functions are defined
++ (besides CKD_NULL already defined : */
++#define CKD_SHA1_KDF_ASN1 0x00000003
++#define CKD_SHA1_KDF_CONCATENATE 0x00000004
++
++/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
++ * contributes one key pair */
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_X9_42_DH1_DERIVE_PARAMS;
++
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
++
++/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
++ * mechanisms, where each party contributes two key pairs */
++typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_X9_42_DH2_DERIVE_PARAMS;
++
++typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_X9_42_MQV_DERIVE_PARAMS;
++
++typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
++
++/* CK_KEA_DERIVE_PARAMS provides the parameters to the
++ * CKM_KEA_DERIVE mechanism */
++/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
++typedef struct CK_KEA_DERIVE_PARAMS {
++ CK_BBOOL isSender;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pRandomB;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_KEA_DERIVE_PARAMS;
++
++typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
++
++
++/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
++ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
++ * holds the effective keysize */
++typedef CK_ULONG CK_RC2_PARAMS;
++
++typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
++
++
++/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
++ * mechanism */
++typedef struct CK_RC2_CBC_PARAMS {
++ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++
++ CK_BYTE iv[8]; /* IV for CBC mode */
++} CK_RC2_CBC_PARAMS;
++
++typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
++
++
++/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC2_MAC_GENERAL mechanism */
++/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC2_MAC_GENERAL_PARAMS {
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC2_MAC_GENERAL_PARAMS;
++
++typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC2_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
++ * CKM_RC5_MAC mechanisms */
++/* CK_RC5_PARAMS is new for v2.0 */
++typedef struct CK_RC5_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++} CK_RC5_PARAMS;
++
++typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
++
++
++/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
++ * mechanism */
++/* CK_RC5_CBC_PARAMS is new for v2.0 */
++typedef struct CK_RC5_CBC_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_BYTE_PTR pIv; /* pointer to IV */
++ CK_ULONG ulIvLen; /* length of IV in bytes */
++} CK_RC5_CBC_PARAMS;
++
++typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
++
++
++/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC5_MAC_GENERAL mechanism */
++/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC5_MAC_GENERAL_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC5_MAC_GENERAL_PARAMS;
++
++typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC5_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
++ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
++ * the MAC */
++/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
++
++typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
++
++/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
++typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[8];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pPassword;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPAndGLen;
++ CK_ULONG ulQLen;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pPrimeP;
++ CK_BYTE_PTR pBaseG;
++ CK_BYTE_PTR pSubprimeQ;
++} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
++
++typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
++ CK_SKIPJACK_PRIVATE_WRAP_PTR;
++
++
++/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_RELAYX mechanism */
++/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_RELAYX_PARAMS {
++ CK_ULONG ulOldWrappedXLen;
++ CK_BYTE_PTR pOldWrappedX;
++ CK_ULONG ulOldPasswordLen;
++ CK_BYTE_PTR pOldPassword;
++ CK_ULONG ulOldPublicDataLen;
++ CK_BYTE_PTR pOldPublicData;
++ CK_ULONG ulOldRandomLen;
++ CK_BYTE_PTR pOldRandomA;
++ CK_ULONG ulNewPasswordLen;
++ CK_BYTE_PTR pNewPassword;
++ CK_ULONG ulNewPublicDataLen;
++ CK_BYTE_PTR pNewPublicData;
++ CK_ULONG ulNewRandomLen;
++ CK_BYTE_PTR pNewRandomA;
++} CK_SKIPJACK_RELAYX_PARAMS;
++
++typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
++ CK_SKIPJACK_RELAYX_PARAMS_PTR;
++
++
++typedef struct CK_PBE_PARAMS {
++ CK_BYTE_PTR pInitVector;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pSalt;
++ CK_ULONG ulSaltLen;
++ CK_ULONG ulIteration;
++} CK_PBE_PARAMS;
++
++typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
++
++
++/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
++ * CKM_KEY_WRAP_SET_OAEP mechanism */
++/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
++typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
++ CK_BYTE bBC; /* block contents byte */
++ CK_BYTE_PTR pX; /* extra data */
++ CK_ULONG ulXLen; /* length of extra data in bytes */
++} CK_KEY_WRAP_SET_OAEP_PARAMS;
++
++typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
++ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_SSL3_RANDOM_DATA;
++
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_VERSION_PTR pVersion;
++} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hClientMacSecret;
++ CK_OBJECT_HANDLE hServerMacSecret;
++ CK_OBJECT_HANDLE hClientKey;
++ CK_OBJECT_HANDLE hServerKey;
++ CK_BYTE_PTR pIVClient;
++ CK_BYTE_PTR pIVServer;
++} CK_SSL3_KEY_MAT_OUT;
++
++typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_PARAMS {
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_BBOOL bIsExport;
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_SSL3_KEY_MAT_PARAMS;
++
++typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
++
++/* CK_TLS_PRF_PARAMS is new for version 2.20 */
++typedef struct CK_TLS_PRF_PARAMS {
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_TLS_PRF_PARAMS;
++
++typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
++
++/* WTLS is new for version 2.20 */
++typedef struct CK_WTLS_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_WTLS_RANDOM_DATA;
++
++typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
++
++typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_BYTE_PTR pVersion;
++} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
++
++typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++typedef struct CK_WTLS_PRF_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_WTLS_PRF_PARAMS;
++
++typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hMacSecret;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pIV;
++} CK_WTLS_KEY_MAT_OUT;
++
++typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_ULONG ulSequenceNumber;
++ CK_BBOOL bIsExport;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_WTLS_KEY_MAT_PARAMS;
++
++typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
++
++/* CMS is new for version 2.20 */
++typedef struct CK_CMS_SIG_PARAMS {
++ CK_OBJECT_HANDLE certificateHandle;
++ CK_MECHANISM_PTR pSigningMechanism;
++ CK_MECHANISM_PTR pDigestMechanism;
++ CK_UTF8CHAR_PTR pContentType;
++ CK_BYTE_PTR pRequestedAttributes;
++ CK_ULONG ulRequestedAttributesLen;
++ CK_BYTE_PTR pRequiredAttributes;
++ CK_ULONG ulRequiredAttributesLen;
++} CK_CMS_SIG_PARAMS;
++
++typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
++
++typedef struct CK_KEY_DERIVATION_STRING_DATA {
++ CK_BYTE_PTR pData;
++ CK_ULONG ulLen;
++} CK_KEY_DERIVATION_STRING_DATA;
++
++typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
++ CK_KEY_DERIVATION_STRING_DATA_PTR;
++
++
++/* The CK_EXTRACT_PARAMS is used for the
++ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
++ * of the base key should be used as the first bit of the
++ * derived key */
++/* CK_EXTRACT_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_EXTRACT_PARAMS;
++
++typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
++
++/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
++ * indicate the Pseudo-Random Function (PRF) used to generate
++ * key bits using PKCS #5 PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
++
++typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
++
++/* The following PRFs are defined in PKCS #5 v2.0. */
++#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
++
++
++/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
++ * source of the salt value when deriving a key using PKCS #5
++ * PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
++
++typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
++
++/* The following salt value sources are defined in PKCS #5 v2.0. */
++#define CKZ_SALT_SPECIFIED 0x00000001
++
++/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
++ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
++ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
++typedef struct CK_PKCS5_PBKD2_PARAMS {
++ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ CK_VOID_PTR pSaltSourceData;
++ CK_ULONG ulSaltSourceDataLen;
++ CK_ULONG iterations;
++ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ CK_VOID_PTR pPrfData;
++ CK_ULONG ulPrfDataLen;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG_PTR ulPasswordLen;
++} CK_PKCS5_PBKD2_PARAMS;
++
++typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
++
++/* All CK_OTP structs are new for PKCS #11 v2.20 amendment 3 */
++
++typedef CK_ULONG CK_OTP_PARAM_TYPE;
++typedef CK_OTP_PARAM_TYPE CK_PARAM_TYPE; /* B/w compatibility */
++
++typedef struct CK_OTP_PARAM {
++ CK_OTP_PARAM_TYPE type;
++ CK_VOID_PTR pValue;
++ CK_ULONG ulValueLen;
++} CK_OTP_PARAM;
++
++typedef CK_OTP_PARAM CK_PTR CK_OTP_PARAM_PTR;
++
++typedef struct CK_OTP_PARAMS {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_PARAMS;
++
++typedef CK_OTP_PARAMS CK_PTR CK_OTP_PARAMS_PTR;
++
++typedef struct CK_OTP_SIGNATURE_INFO {
++ CK_OTP_PARAM_PTR pParams;
++ CK_ULONG ulCount;
++} CK_OTP_SIGNATURE_INFO;
++
++typedef CK_OTP_SIGNATURE_INFO CK_PTR CK_OTP_SIGNATURE_INFO_PTR;
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CK_OTP_VALUE 0
++#define CK_OTP_PIN 1
++#define CK_OTP_CHALLENGE 2
++#define CK_OTP_TIME 3
++#define CK_OTP_COUNTER 4
++#define CK_OTP_FLAGS 5
++#define CK_OTP_OUTPUT_LENGTH 6
++#define CK_OTP_OUTPUT_FORMAT 7
++
++/* The following OTP-related defines are new for PKCS #11 v2.20 amendment 1 */
++#define CKF_NEXT_OTP 0x00000001
++#define CKF_EXCLUDE_TIME 0x00000002
++#define CKF_EXCLUDE_COUNTER 0x00000004
++#define CKF_EXCLUDE_CHALLENGE 0x00000008
++#define CKF_EXCLUDE_PIN 0x00000010
++#define CKF_USER_FRIENDLY_OTP 0x00000020
++
++/* CK_KIP_PARAMS is new for PKCS #11 v2.20 amendment 2 */
++typedef struct CK_KIP_PARAMS {
++ CK_MECHANISM_PTR pMechanism;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++} CK_KIP_PARAMS;
++
++typedef CK_KIP_PARAMS CK_PTR CK_KIP_PARAMS_PTR;
++
++/* CK_AES_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_AES_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_AES_CTR_PARAMS;
++
++typedef CK_AES_CTR_PARAMS CK_PTR CK_AES_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CTR_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CTR_PARAMS {
++ CK_ULONG ulCounterBits;
++ CK_BYTE cb[16];
++} CK_CAMELLIA_CTR_PARAMS;
++
++typedef CK_CAMELLIA_CTR_PARAMS CK_PTR CK_CAMELLIA_CTR_PARAMS_PTR;
++
++/* CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_CAMELLIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_ARIA_CBC_ENCRYPT_DATA_PARAMS is new for PKCS #11 v2.20 amendment 3 */
++typedef struct CK_ARIA_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_ARIA_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_ARIA_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_ARIA_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++#endif
+diff -up bind-9.9.6/lib/isc/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/Makefile.in
+--- bind-9.9.6/lib/isc/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/Makefile.in 2014-10-09 13:30:47.834302934 +0200
+@@ -23,16 +23,20 @@ top_srcdir = @top_srcdir@
+
+ @LIBISC_API@
+
++@BIND9_MAKE_INCLUDES@
++
++PROVIDER = @PKCS11_PROVIDER@
++
+ CINCLUDES = -I${srcdir}/unix/include \
+ -I${srcdir}/@ISC_THREAD_DIR@/include \
+ -I${srcdir}/@ISC_ARCH_DIR@/include \
+ -I./include \
+- -I${srcdir}/include @ISC_OPENSSL_INC@
+-CDEFINES = @USE_OPENSSL@
++ -I${srcdir}/include @ISC_OPENSSL_INC@ ${DNS_INCLUDES}
++CDEFINES = @CRYPTO@ -DPK11_LIB_LOCATION=\"${PROVIDER}\"
+ CWARNINGS =
+
+ # Alphabetically
+-UNIXOBJS = @ISC_ISCIPV6_O@ \
++UNIXOBJS = @ISC_ISCIPV6_O@ @ISC_ISCPK11_API_O@ \
+ unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \
+ unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \
+ unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@O@ \
+@@ -50,7 +54,7 @@ WIN32OBJS = win32/condition.@O@ win32/d
+ win32/thread.@O@ win32/time.@O@
+
+ # Alphabetically
+-OBJS = @ISC_EXTRA_OBJS@ \
++OBJS = @ISC_EXTRA_OBJS@ @ISC_PK11_O@ @ISC_PK11_RESULT_O@ \
+ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \
+ bitstring.@O@ buffer.@O@ bufferlist.@O@ commandline.@O@ \
+ error.@O@ event.@O@ \
+@@ -69,7 +73,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
+ SYMTBLOBJS = backtrace-emptytbl.@O@
+
+ # Alphabetically
+-SRCS = @ISC_EXTRA_SRCS@ \
++SRCS = @ISC_EXTRA_SRCS@ @ISC_PK11_C@ @ISC_PK11_RESULT_C@ \
+ assertions.c backtrace.c base32.c base64.c bitstring.c \
+ buffer.c bufferlist.c commandline.c error.c event.c \
+ heap.c hex.c hmacmd5.c hmacsha.c \
+diff -up bind-9.9.6/lib/isc/md5.c.native_pkcs11 bind-9.9.6/lib/isc/md5.c
+--- bind-9.9.6/lib/isc/md5.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/md5.c 2014-10-09 13:30:47.841302943 +0200
+@@ -41,6 +41,12 @@
+ #include <isc/platform.h>
+ #include <isc/string.h>
+ #include <isc/types.h>
++
++#if PKCS11CRYPTO
++#include <pk11/internal.h>
++#include <pk11/pk11.h>
++#endif
++
+ #include <isc/util.h>
+
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+@@ -65,6 +71,50 @@ isc_md5_final(isc_md5_t *ctx, unsigned c
+ EVP_DigestFinal(ctx, digest, NULL);
+ }
+
++#elif PKCS11CRYPTO
++
++void
++isc_md5_init(isc_md5_t *ctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
++
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
++}
++
++void
++isc_md5_invalidate(isc_md5_t *ctx) {
++ CK_BYTE garbage[ISC_MD5_DIGESTLENGTH];
++ CK_ULONG len = ISC_MD5_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(ctx);
++}
++
++void
++isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
++ CK_RV rv;
++ CK_ULONG len = ISC_MD5_DIGESTLENGTH;
++
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (ctx->session, (CK_BYTE_PTR) digest, &len));
++ pk11_return_session(ctx);
++}
++
+ #else
+
+ static void
+diff -up bind-9.9.6/lib/isc/pk11.c.native_pkcs11 bind-9.9.6/lib/isc/pk11.c
+--- bind-9.9.6/lib/isc/pk11.c.native_pkcs11 2014-10-09 13:30:47.842302944 +0200
++++ bind-9.9.6/lib/isc/pk11.c 2014-10-09 13:30:47.842302944 +0200
+@@ -0,0 +1,1327 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/*
++ * Portions copyright (c) 2008 Nominet UK. 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 ``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 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.
++ */
++
++/*
++ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++/*
++ * This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/*
++ * ====================================================================
++ * 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).
++ *
++ */
++
++/* $Id$ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <isc/log.h>
++#include <isc/mem.h>
++#include <isc/once.h>
++#include <isc/platform.h>
++#include <isc/stdio.h>
++#include <isc/thread.h>
++#include <isc/util.h>
++
++#include <dst/result.h>
++
++#include <pk11/pk11.h>
++#include <pk11/internal.h>
++#include <pk11/result.h>
++
++#include <pkcs11/cryptoki.h>
++#include <pkcs11/pkcs11.h>
++
++#define PINLEN 32
++
++#ifndef PK11_NO_LOGERR
++#define PK11_NO_LOGERR 1
++#endif
++
++static isc_once_t once = ISC_ONCE_INIT;
++static isc_mem_t *pk11_mctx = NULL;
++static isc_int32_t allocsize = 0;
++static isc_boolean_t initialized = ISC_FALSE;
++
++typedef struct pk11_session pk11_session_t;
++typedef struct pk11_token pk11_token_t;
++typedef ISC_LIST(pk11_session_t) pk11_sessionlist_t;
++
++struct pk11_session {
++ unsigned int magic;
++ CK_SESSION_HANDLE session;
++ ISC_LINK(pk11_session_t) link;
++ pk11_token_t *token;
++};
++
++struct pk11_token {
++ unsigned int magic;
++ unsigned int operations;
++ ISC_LINK(pk11_token_t) link;
++ CK_SLOT_ID slotid;
++ pk11_sessionlist_t sessions;
++ isc_boolean_t logged;
++ char name[32];
++ char manuf[32];
++ char model[16];
++ char serial[16];
++ char pin[PINLEN];
++};
++static ISC_LIST(pk11_token_t) tokens;
++
++static pk11_token_t *rand_token;
++static pk11_token_t *best_rsa_token;
++static pk11_token_t *best_dsa_token;
++static pk11_token_t *best_dh_token;
++static pk11_token_t *digest_token;
++static pk11_token_t *best_ec_token;
++static pk11_token_t *best_gost_token;
++static pk11_token_t *aes_token;
++
++static isc_result_t free_all_sessions(void);
++static isc_result_t free_session_list(pk11_sessionlist_t *slist);
++static isc_result_t setup_session(pk11_session_t *sp,
++ pk11_token_t *token,
++ isc_boolean_t rw);
++static void choose_slots(void);
++static isc_result_t token_login(pk11_session_t *sp);
++static char *percent_decode(char *x, size_t *len);
++static isc_boolean_t pk11strcmp(const char *x, size_t lenx,
++ const char *y, size_t leny);
++static CK_ATTRIBUTE *push_attribute(pk11_object_t *obj,
++ isc_mem_t *mctx,
++ size_t len);
++
++static isc_mutex_t alloclock;
++static isc_mutex_t sessionlock;
++
++static pk11_sessionlist_t actives;
++
++static CK_C_INITIALIZE_ARGS pk11_init_args = {
++ NULL_PTR, /* CreateMutex */
++ NULL_PTR, /* DestroyMutex */
++ NULL_PTR, /* LockMutex */
++ NULL_PTR, /* UnlockMutex */
++ CKF_OS_LOCKING_OK, /* flags */
++ NULL_PTR, /* pReserved */
++};
++
++#ifndef PK11_LIB_LOCATION
++#define PK11_LIB_LOCATION "unknown_provider"
++#endif
++
++#ifndef WIN32
++static const char *lib_name = PK11_LIB_LOCATION;
++#else
++static const char *lib_name = PK11_LIB_LOCATION ".dll";
++#endif
++
++void
++pk11_set_lib_name(const char *name) {
++ lib_name = name;
++}
++
++const char *
++pk11_get_lib_name(void) {
++ return (lib_name);
++}
++
++static void
++initialize(void) {
++ char *pk11_provider;
++
++ RUNTIME_CHECK(isc_mutex_init(&alloclock) == ISC_R_SUCCESS);
++ RUNTIME_CHECK(isc_mutex_init(&sessionlock) == ISC_R_SUCCESS);
++
++ pk11_provider = getenv("PKCS11_PROVIDER");
++ if (pk11_provider != NULL)
++ lib_name = pk11_provider;
++}
++
++void *
++pk11_mem_get(size_t size) {
++ void *ptr;
++
++ LOCK(&alloclock);
++ if (pk11_mctx != NULL)
++ ptr = isc_mem_get(pk11_mctx, size);
++ else {
++ ptr = malloc(size);
++ if (ptr != NULL)
++ allocsize += (int)size;
++ }
++ UNLOCK(&alloclock);
++
++ if (ptr != NULL)
++ memset(ptr, 0, size);
++ return (ptr);
++}
++
++void
++pk11_mem_put(void *ptr, size_t size) {
++ if (ptr != NULL)
++ memset(ptr, 0, size);
++ LOCK(&alloclock);
++ if (pk11_mctx != NULL)
++ isc_mem_put(pk11_mctx, ptr, size);
++ else {
++ if (ptr != NULL)
++ allocsize -= (int)size;
++ free(ptr);
++ }
++ UNLOCK(&alloclock);
++}
++
++isc_result_t
++pk11_initialize(isc_mem_t *mctx, const char *engine) {
++ isc_result_t result;
++ CK_RV rv;
++
++ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
++
++ LOCK(&alloclock);
++ if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0))
++ isc_mem_attach(mctx, &pk11_mctx);
++ if (initialized) {
++ UNLOCK(&alloclock);
++ return (ISC_R_SUCCESS);
++ } else {
++ LOCK(&sessionlock);
++ initialized = ISC_TRUE;
++ UNLOCK(&alloclock);
++ }
++
++ ISC_LIST_INIT(tokens);
++ ISC_LIST_INIT(actives);
++
++ if (engine != NULL)
++ lib_name = engine;
++
++ /* Initialize the CRYPTOKI library */
++ rv = pkcs_C_Initialize((CK_VOID_PTR) &pk11_init_args);
++
++ if (rv == 0xfe) {
++ result = PK11_R_NOPROVIDER;
++ goto unlock;
++ }
++ if (rv != CKR_OK) {
++ result = PK11_R_INITFAILED;
++ goto unlock;
++ }
++
++ choose_slots();
++#ifdef PKCS11CRYPTO
++ if (rand_token == NULL) {
++ result = PK11_R_NORANDOMSERVICE;
++ goto unlock;
++ }
++ if (digest_token == NULL) {
++ result = PK11_R_NODIGESTSERVICE;
++ goto unlock;
++ }
++#if defined(ISC_PLATFORM_USESIT) && defined(AES_SIT)
++ if (aes_token == NULL) {
++ result = PK11_R_NOAESSERVICE;
++ goto unlock;
++ }
++#endif
++#endif /* PKCS11CRYPTO */
++ result = ISC_R_SUCCESS;
++ unlock:
++ UNLOCK(&sessionlock);
++ return (result);
++}
++
++isc_result_t
++pk11_finalize(void) {
++ pk11_token_t *token, *next;
++ isc_result_t ret;
++
++ ret = free_all_sessions();
++ (void) pkcs_C_Finalize(NULL_PTR);
++ token = ISC_LIST_HEAD(tokens);
++ while (token != NULL) {
++ next = ISC_LIST_NEXT(token, link);
++ ISC_LIST_UNLINK(tokens, token, link);
++ if (token == rand_token)
++ rand_token = NULL;
++ if (token == best_rsa_token)
++ best_rsa_token = NULL;
++ if (token == best_dsa_token)
++ best_dsa_token = NULL;
++ if (token == best_dh_token)
++ best_dh_token = NULL;
++ if (token == digest_token)
++ digest_token = NULL;
++ if (token == best_ec_token)
++ best_ec_token = NULL;
++ if (token == best_gost_token)
++ best_gost_token = NULL;
++ if (token == aes_token)
++ aes_token = NULL;
++ pk11_mem_put(token, sizeof(*token));
++ token = next;
++ }
++ if (pk11_mctx != NULL)
++ isc_mem_detach(&pk11_mctx);
++ initialized = ISC_FALSE;
++ return (ret);
++}
++
++isc_result_t
++pk11_rand_bytes(unsigned char *buf, int num) {
++ isc_result_t ret;
++ CK_RV rv;
++ pk11_context_t ctx;
++
++ ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE,
++ ISC_FALSE, NULL, 0);
++ if ((ret != ISC_R_SUCCESS) &&
++ (ret != PK11_R_NODIGESTSERVICE) &&
++ (ret != PK11_R_NOAESSERVICE))
++ return (ret);
++ RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE);
++ rv = pkcs_C_GenerateRandom(ctx.session,
++ (CK_BYTE_PTR) buf, (CK_ULONG) num);
++ pk11_return_session(&ctx);
++ if (rv == CKR_OK)
++ return (ISC_R_SUCCESS);
++ else
++ return (DST_R_CRYPTOFAILURE);
++}
++
++#define SEEDSIZE 1024
++
++static CK_BYTE seed[SEEDSIZE];
++
++void
++pk11_rand_seed_fromfile(const char *randomfile) {
++ pk11_context_t ctx;
++ FILE *stream = NULL;
++ size_t cc = 0;
++ isc_result_t ret;
++
++ ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE,
++ ISC_FALSE, NULL, 0);
++ if ((ret != ISC_R_SUCCESS) &&
++ (ret != PK11_R_NODIGESTSERVICE) &&
++ (ret != PK11_R_NOAESSERVICE))
++ return;
++ RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE);
++ ret = isc_stdio_open(randomfile, "r", &stream);
++ if (ret != ISC_R_SUCCESS)
++ goto cleanup;
++ ret = isc_stdio_read(seed, 1, SEEDSIZE, stream, &cc);
++ if (ret!= ISC_R_SUCCESS)
++ goto cleanup;
++ ret = isc_stdio_close(stream);
++ stream = NULL;
++ if (ret!= ISC_R_SUCCESS)
++ goto cleanup;
++ (void) pkcs_C_SeedRandom(ctx.session, seed, (CK_ULONG) cc);
++
++ cleanup:
++ if (stream != NULL)
++ (void) isc_stdio_close(stream);
++ pk11_return_session(&ctx);
++}
++
++isc_result_t
++pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype,
++ isc_boolean_t need_services, isc_boolean_t rw,
++ isc_boolean_t logon, const char *pin, CK_SLOT_ID slot)
++{
++ pk11_token_t *token = NULL;
++ pk11_sessionlist_t *freelist;
++ pk11_session_t *sp;
++ isc_result_t ret;
++#ifdef PKCS11CRYPTO
++ isc_result_t service_ret = ISC_R_SUCCESS;
++#else
++ UNUSED(need_services);
++#endif
++
++ memset(ctx, 0, sizeof(pk11_context_t));
++ ctx->handle = NULL;
++ ctx->session = CK_INVALID_HANDLE;
++
++ ret = pk11_initialize(NULL, NULL);
++#ifdef PKCS11CRYPTO
++ if (ret == PK11_R_NORANDOMSERVICE ||
++ ret == PK11_R_NODIGESTSERVICE ||
++ ret == PK11_R_NOAESSERVICE) {
++ if (need_services)
++ return (ret);
++ service_ret = ret;
++ }
++ else
++#endif /* PKCS11CRYPTO */
++ if (ret != ISC_R_SUCCESS)
++ return (ret);
++
++ LOCK(&sessionlock);
++ /* wait for initialization to finish */
++ UNLOCK(&sessionlock);
++
++ switch(optype) {
++#ifdef PKCS11CRYPTO
++ case OP_RAND:
++ token = rand_token;
++ break;
++ case OP_DIGEST:
++ token = digest_token;
++ break;
++ case OP_AES:
++ token = aes_token;
++ break;
++ case OP_ANY:
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link))
++ if (token->slotid == slot)
++ break;
++ break;
++#endif
++ default:
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link))
++ if (token->slotid == slot)
++ break;
++#ifdef PKCS11CRYPTO
++ if ((token == NULL) ||
++ ((token->operations & (1 << optype)) == 0))
++ return (ISC_R_NOTFOUND);
++#endif
++ break;
++ }
++ if (token == NULL)
++ return (ISC_R_NOTFOUND);
++
++ /* Override the token's PIN */
++ if (logon && pin != NULL && *pin != '\0') {
++ memset(token->pin, 0, PINLEN);
++ strncpy(token->pin, pin, PINLEN);
++ }
++
++ freelist = &token->sessions;
++
++ LOCK(&sessionlock);
++ sp = ISC_LIST_HEAD(*freelist);
++ if (sp != NULL) {
++ ISC_LIST_UNLINK(*freelist, sp, link);
++ ISC_LIST_APPEND(actives, sp, link);
++ UNLOCK(&sessionlock);
++ if (logon)
++ ret = token_login(sp);
++ ctx->handle = sp;
++ ctx->session = sp->session;
++ return (ret);
++ }
++ UNLOCK(&sessionlock);
++
++ sp = pk11_mem_get(sizeof(*sp));
++ if (sp == NULL)
++ return (ISC_R_NOMEMORY);
++ sp->magic = SES_MAGIC;
++ sp->token = token;
++ sp->session = CK_INVALID_HANDLE;
++ ISC_LINK_INIT(sp, link);
++ ret = setup_session(sp, token, rw);
++ if ((ret == ISC_R_SUCCESS) && logon)
++ ret = token_login(sp);
++ LOCK(&sessionlock);
++ ISC_LIST_APPEND(actives, sp, link);
++ UNLOCK(&sessionlock);
++ ctx->handle = sp;
++ ctx->session = sp->session;
++#ifdef PKCS11CRYPTO
++ if (ret == ISC_R_SUCCESS)
++ ret = service_ret;
++#endif
++ return (ret);
++}
++
++void
++pk11_return_session(pk11_context_t *ctx) {
++ pk11_session_t *sp = (pk11_session_t *) ctx->handle;
++
++ if (sp == NULL)
++ return;
++ ctx->handle = NULL;
++ ctx->session = CK_INVALID_HANDLE;
++
++ LOCK(&sessionlock);
++ ISC_LIST_UNLINK(actives, sp, link);
++ UNLOCK(&sessionlock);
++ if (sp->session == CK_INVALID_HANDLE) {
++ pk11_mem_put(sp, sizeof(*sp));
++ return;
++ }
++
++ LOCK(&sessionlock);
++ ISC_LIST_APPEND(sp->token->sessions, sp, link);
++ UNLOCK(&sessionlock);
++}
++
++static isc_result_t
++free_all_sessions(void) {
++ pk11_token_t *token;
++ isc_result_t ret = ISC_R_SUCCESS;
++ isc_result_t oret;
++
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link)) {
++ oret = free_session_list(&token->sessions);
++ if (oret != ISC_R_SUCCESS)
++ ret = oret;
++ }
++ if (!ISC_LIST_EMPTY(actives)) {
++ ret = ISC_R_ADDRINUSE;
++ oret = free_session_list(&actives);
++ if (oret != ISC_R_SUCCESS)
++ ret = oret;
++ }
++ return (ret);
++}
++
++static isc_result_t
++free_session_list(pk11_sessionlist_t *slist) {
++ pk11_session_t *sp;
++ CK_RV rv;
++ isc_result_t ret;
++
++ ret = ISC_R_SUCCESS;
++ LOCK(&sessionlock);
++ while (!ISC_LIST_EMPTY(*slist)) {
++ sp = ISC_LIST_HEAD(*slist);
++ UNLOCK(&sessionlock);
++ if (sp->session != CK_INVALID_HANDLE) {
++ rv = pkcs_C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ ret = DST_R_CRYPTOFAILURE;
++ }
++ LOCK(&sessionlock);
++ ISC_LIST_UNLINK(*slist, sp, link);
++ pk11_mem_put(sp, sizeof(*sp));
++ }
++ UNLOCK(&sessionlock);
++
++ return (ret);
++}
++
++static isc_result_t
++setup_session(pk11_session_t *sp, pk11_token_t *token,
++ isc_boolean_t rw)
++{
++ CK_RV rv;
++ CK_FLAGS flags = CKF_SERIAL_SESSION;
++
++ if (rw)
++ flags += CKF_RW_SESSION;
++
++ rv = pkcs_C_OpenSession(token->slotid, flags, NULL_PTR,
++ NULL_PTR, &sp->session);
++ if (rv != CKR_OK)
++ return (DST_R_CRYPTOFAILURE);
++ return (ISC_R_SUCCESS);
++}
++
++static isc_result_t
++token_login(pk11_session_t *sp) {
++ CK_RV rv;
++ pk11_token_t *token = sp->token;
++ isc_result_t ret = ISC_R_SUCCESS;
++
++ LOCK(&sessionlock);
++ if (!token->logged) {
++ rv = pkcs_C_Login(sp->session, CKU_USER,
++ (CK_UTF8CHAR_PTR) token->pin,
++ (CK_ULONG) strlen(token->pin));
++ if (rv != CKR_OK) {
++ ret = ISC_R_NOPERM;
++#if PK11_NO_LOGERR
++ pk11_error_fatalcheck(__FILE__, __LINE__,
++ "pkcs_C_Login", rv);
++#endif
++ } else
++ token->logged = ISC_TRUE;
++ }
++ UNLOCK(&sessionlock);
++ return (ret);
++}
++
++static void
++choose_slots(void) {
++ CK_MECHANISM_INFO mechInfo;
++ CK_TOKEN_INFO tokenInfo;
++ CK_RV rv;
++ CK_SLOT_ID slot;
++ CK_SLOT_ID_PTR slotList;
++ CK_ULONG slotCount;
++ pk11_token_t *token;
++ unsigned int i;
++
++ slotCount = 0;
++ PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount));
++ /* it's not an error if we didn't find any providers */
++ if (slotCount == 0)
++ return;
++ slotList = pk11_mem_get(sizeof(CK_SLOT_ID_PTR) * slotCount);
++ RUNTIME_CHECK(slotList != NULL);
++ PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount));
++
++ for (i = 0; i < slotCount; i++) {
++ slot = slotList[i];
++
++ rv = pkcs_C_GetTokenInfo(slot, &tokenInfo);
++ if (rv != CKR_OK)
++ continue;
++ token = pk11_mem_get(sizeof(*token));
++ RUNTIME_CHECK(token != NULL);
++ token->magic = TOK_MAGIC;
++ token->slotid = slot;
++ ISC_LINK_INIT(token, link);
++ ISC_LIST_INIT(token->sessions);
++ memmove(token->name, tokenInfo.label, 32);
++ memmove(token->manuf, tokenInfo.manufacturerID, 32);
++ memmove(token->model, tokenInfo.model, 16);
++ memmove(token->serial, tokenInfo.serialNumber, 16);
++ ISC_LIST_APPEND(tokens, token, link);
++ if ((tokenInfo.flags & CKF_RNG) == 0)
++ goto try_rsa;
++ token->operations |= 1 << OP_RAND;
++ if (rand_token == NULL)
++ rand_token = token;
++
++ try_rsa:
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
++ goto try_dsa;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_RSA_PKCS,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_dsa;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_dsa;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_RSA_PKCS,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_dsa;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_RSA_PKCS,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_dsa;
++ token->operations |= 1 << OP_RSA;
++ if (best_rsa_token == NULL)
++ best_rsa_token = token;
++
++ try_dsa:
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0))
++ goto try_dh;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_KEY_PAIR_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
++ goto try_dh;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_SHA1, &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_dh;
++ token->operations |= 1 << OP_DSA;
++ if (best_dsa_token == NULL)
++ best_dsa_token = token;
++
++ try_dh:
++#ifdef notdef
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_PARAMETER_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0))
++ goto try_digest;
++#endif
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_KEY_PAIR_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
++ goto try_digest;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_DERIVE,
++ &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DERIVE) == 0))
++ goto try_digest;
++ token->operations |= 1 << OP_DH;
++ if (best_dh_token == NULL)
++ best_dh_token = token;
++
++ try_digest:
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ continue;
++#ifdef PKCS11CRYPTOWITHHMAC
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
++ continue;
++#endif
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384_HMAC, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
++ continue;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_HMAC, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
++ continue;
++ token->operations |= 1 << OP_DIGEST;
++ if (digest_token == NULL)
++ digest_token = token;
++
++ /* ECDSA requires digest */
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
++ goto try_gost;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_ECDSA, &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_gost;
++ token->operations |= 1 << OP_EC;
++ if (best_ec_token == NULL)
++ best_ec_token = token;
++
++ try_gost:
++ /* does GOST require digest too? */
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3411, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
++ goto try_aes;
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3410_KEY_PAIR_GEN,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
++ goto try_aes;
++ rv = pkcs_C_GetMechanismInfo(slot,
++ CKM_GOSTR3410_WITH_GOSTR3411,
++ &mechInfo);
++ if ((rv != CKR_OK) ||
++ ((mechInfo.flags & CKF_SIGN) == 0) ||
++ ((mechInfo.flags & CKF_VERIFY) == 0))
++ goto try_aes;
++ token->operations |= 1 << OP_GOST;
++ if (best_gost_token == NULL)
++ best_gost_token = token;
++
++ try_aes:
++ rv = pkcs_C_GetMechanismInfo(slot, CKM_AES_ECB, &mechInfo);
++ if ((rv != CKR_OK) || ((mechInfo.flags & CKF_ENCRYPT) == 0))
++ continue;
++ token->operations |= 1 << OP_AES;
++ if (aes_token == NULL)
++ aes_token = token;
++ }
++
++ if (slotList != NULL)
++ pk11_mem_put(slotList, sizeof(CK_SLOT_ID_PTR) * slotCount);
++}
++
++CK_SLOT_ID
++pk11_get_best_token(pk11_optype_t optype) {
++ pk11_token_t *token = NULL;
++
++ switch (optype) {
++ case OP_RAND:
++ token = rand_token;
++ break;
++ case OP_RSA:
++ token = best_rsa_token;
++ break;
++ case OP_DSA:
++ token = best_dsa_token;
++ break;
++ case OP_DH:
++ token = best_dh_token;
++ break;
++ case OP_DIGEST:
++ token = digest_token;
++ break;
++ case OP_EC:
++ token = best_ec_token;
++ break;
++ case OP_GOST:
++ token = best_gost_token;
++ break;
++ case OP_AES:
++ token = aes_token;
++ break;
++ default:
++ break;
++ }
++ if (token == NULL)
++ return (0);
++ return (token->slotid);
++}
++
++unsigned int
++pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) {
++ unsigned int bitcnt, i;
++ CK_BYTE top;
++
++ if (bytecnt == 0)
++ return (0);
++ bitcnt = bytecnt * 8;
++ for (i = 0; i < bytecnt; i++) {
++ top = data[i];
++ if (top == 0) {
++ bitcnt -= 8;
++ continue;
++ }
++ if (top & 0x80)
++ return (bitcnt);
++ if (top & 0x40)
++ return (bitcnt - 1);
++ if (top & 0x20)
++ return (bitcnt - 2);
++ if (top & 0x10)
++ return (bitcnt - 3);
++ if (top & 0x08)
++ return (bitcnt - 4);
++ if (top & 0x04)
++ return (bitcnt - 5);
++ if (top & 0x02)
++ return (bitcnt - 6);
++ if (top & 0x01)
++ return (bitcnt - 7);
++ break;
++ }
++ INSIST(0);
++}
++
++CK_ATTRIBUTE *
++pk11_attribute_first(const pk11_object_t *obj) {
++ return (obj->repr);
++}
++
++CK_ATTRIBUTE *
++pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr) {
++ CK_ATTRIBUTE *next;
++
++ next = attr + 1;
++ if ((next - obj->repr) >= obj->attrcnt)
++ return (NULL);
++ return (next);
++}
++
++CK_ATTRIBUTE *
++pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type) {
++ CK_ATTRIBUTE *attr;
++
++ for(attr = pk11_attribute_first(obj);
++ attr != NULL;
++ attr = pk11_attribute_next(obj, attr))
++ if (attr->type == type)
++ return (attr);
++ return (NULL);
++}
++
++static char *
++percent_decode(char *x, size_t *len) {
++ char *p, *c;
++ unsigned char v;
++
++ INSIST(len != NULL);
++
++ for (p = c = x; p[0] != '\0'; p++, c++) {
++ switch (p[0]) {
++ case '%':
++ v = 0;
++ switch (p[1]) {
++ case '0':
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '8':
++ case '9':
++ v = (p[1] - '0') << 4;
++ break;
++ case 'A':
++ case 'B':
++ case 'C':
++ case 'D':
++ case 'E':
++ case 'F':
++ v = (p[1] - 'A' + 10) << 4;
++ break;
++ case 'a':
++ case 'b':
++ case 'c':
++ case 'd':
++ case 'e':
++ case 'f':
++ v = (p[1] - 'a' + 10) << 4;
++ break;
++ default:
++ return (NULL);
++ }
++ switch (p[2]) {
++ case '0':
++ case '1':
++ case '2':
++ case '3':
++ case '4':
++ case '5':
++ case '6':
++ case '7':
++ case '8':
++ case '9':
++ v |= (p[2] - '0') & 0x0f;
++ break;
++ case 'A':
++ case 'B':
++ case 'C':
++ case 'D':
++ case 'E':
++ case 'F':
++ v = (p[2] - 'A' + 10) & 0x0f;
++ break;
++ case 'a':
++ case 'b':
++ case 'c':
++ case 'd':
++ case 'e':
++ case 'f':
++ v = (p[2] - 'a' + 10) & 0x0f;
++ break;
++ default:
++ return (NULL);
++ }
++ p += 2;
++ *c = (char) v;
++ (*len)++;
++ break;
++ default:
++ *c = *p;
++ (*len)++;
++ }
++ }
++ return (x);
++}
++
++static isc_boolean_t
++pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny) {
++ char buf[32];
++
++ INSIST((leny == 32) || (leny == 16));
++
++ memset(buf, ' ', 32);
++ if (lenx > leny)
++ lenx = leny;
++ memmove(buf, x, lenx);
++ return (ISC_TF(memcmp(buf, y, leny) == 0));
++}
++
++static CK_ATTRIBUTE *
++push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len) {
++ CK_ATTRIBUTE *old = obj->repr;
++ CK_ATTRIBUTE *attr;
++ CK_BYTE cnt = obj->attrcnt;
++
++ obj->repr = isc_mem_get(mctx, (cnt + 1) * sizeof(*attr));
++ if (obj->repr == NULL) {
++ obj->repr = old;
++ return (NULL);
++ }
++ memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
++ memmove(obj->repr, old, cnt * sizeof(*attr));
++ attr = obj->repr + cnt;
++ attr->ulValueLen = (CK_ULONG) len;
++ attr->pValue = isc_mem_get(mctx, len);
++ if (attr->pValue == NULL) {
++ memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
++ isc_mem_put(mctx, obj->repr, (cnt + 1) * sizeof(*attr));
++ obj->repr = old;
++ return (NULL);
++ }
++ memset(attr->pValue, 0, len);
++ if (old != NULL) {
++ memset(old, 0, cnt * sizeof(*attr));
++ isc_mem_put(mctx, old, cnt * sizeof(*attr));
++ }
++ obj->attrcnt++;
++ return (attr);
++}
++
++#define DST_RET(a) { ret = a; goto err; }
++
++isc_result_t
++pk11_parse_uri(pk11_object_t *obj, const char *label,
++ isc_mem_t *mctx, pk11_optype_t optype)
++{
++ CK_ATTRIBUTE *attr;
++ pk11_token_t *token = NULL;
++ char *uri, *p, *a, *na, *v;
++ size_t len, l;
++ FILE *stream = NULL;
++ char pin[PINLEN];
++ isc_boolean_t gotpin = ISC_FALSE;
++ isc_result_t ret;
++
++ /* get values to work on */
++ len = strlen(label) + 1;
++ uri = isc_mem_get(mctx, len);
++ if (uri == NULL)
++ return (ISC_R_NOMEMORY);
++ memmove(uri, label, len);
++
++ /* get the URI scheme */
++ p = strchr(uri, ':');
++ if (p == NULL)
++ DST_RET(PK11_R_NOPROVIDER);
++ *p++ = '\0';
++ if (strcmp(uri, "pkcs11") != 0)
++ DST_RET(PK11_R_NOPROVIDER);
++
++ /* get attributes */
++ for (na = p; na != NULL;) {
++ a = na;
++ p = strchr(a, ';');
++ if (p == NULL) {
++ /* last attribute */
++ na = NULL;
++ } else {
++ *p++ = '\0';
++ na = p;
++ }
++ p = strchr(a, '=');
++ if (p != NULL) {
++ *p++ = '\0';
++ v = p;
++ } else
++ v = a;
++ l = 0;
++ v = percent_decode(v, &l);
++ if (v == NULL)
++ DST_RET(PK11_R_NOPROVIDER);
++ if ((a == v) || (strcmp(a, "object") == 0)) {
++ /* object: CKA_LABEL */
++ attr = pk11_attribute_bytype(obj, CKA_LABEL);
++ if (attr != NULL)
++ DST_RET(PK11_R_NOPROVIDER);
++ attr = push_attribute(obj, mctx, l);
++ if (attr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ attr->type = CKA_LABEL;
++ memmove(attr->pValue, v, l);
++ } else if (strcmp(a, "token") == 0) {
++ /* token: CK_TOKEN_INFO label */
++ if (token == NULL)
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link))
++ if (pk11strcmp(v, l, token->name, 32))
++ break;
++ } else if (strcmp(a, "manufacturer") == 0) {
++ /* manufacturer: CK_TOKEN_INFO manufacturerID */
++ if (token == NULL)
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link))
++ if (pk11strcmp(v, l, token->manuf, 32))
++ break;
++ } else if (strcmp(a, "serial") == 0) {
++ /* serial: CK_TOKEN_INFO serialNumber */
++ if (token == NULL)
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link))
++ if (pk11strcmp(v, l, token->serial, 16))
++ break;
++ } else if (strcmp(a, "model") == 0) {
++ /* model: CK_TOKEN_INFO model */
++ if (token == NULL)
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link))
++ if (pk11strcmp(v, l, token->model, 16))
++ break;
++ } else if (strcmp(a, "library-manufacturer") == 0) {
++ /* ignored */
++ } else if (strcmp(a, "library-description") == 0) {
++ /* ignored */
++ } else if (strcmp(a, "library-version") == 0) {
++ /* ignored */
++ } else if (strcmp(a, "object-type") == 0) {
++ /* object-type: CKA_CLASS */
++ /* only private makes sense */
++ if (strcmp(v, "private") != 0)
++ DST_RET(PK11_R_NOPROVIDER);
++ } else if (strcmp(a, "id") == 0) {
++ /* id: CKA_ID */
++ attr = pk11_attribute_bytype(obj, CKA_ID);
++ if (attr != NULL)
++ DST_RET(PK11_R_NOPROVIDER);
++ attr = push_attribute(obj, mctx, l);
++ if (attr == NULL)
++ DST_RET(ISC_R_NOMEMORY);
++ attr->type = CKA_ID;
++ memmove(attr->pValue, v, l);
++ } else if (strcmp(a, "pin-source") == 0) {
++ /* pin-source: PIN */
++ ret = isc_stdio_open(v, "r", &stream);
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++ memset(pin, 0, PINLEN);
++ ret = isc_stdio_read(pin, 1, PINLEN - 1, stream, NULL);
++ if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF))
++ goto err;
++ ret = isc_stdio_close(stream);
++ stream = NULL;
++ if (ret != ISC_R_SUCCESS)
++ goto err;
++ gotpin = ISC_TRUE;
++ } else
++ DST_RET(PK11_R_NOPROVIDER);
++ }
++
++ if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) &&
++ (pk11_attribute_bytype(obj, CKA_ID) == NULL))
++ DST_RET(ISC_R_NOTFOUND);
++
++ if (token == NULL) {
++ if (optype == OP_RSA)
++ token = best_rsa_token;
++ else if (optype == OP_DSA)
++ token = best_dsa_token;
++ else if (optype == OP_DH)
++ token = best_dh_token;
++ else if (optype == OP_EC)
++ token = best_ec_token;
++ }
++ if (token == NULL)
++ DST_RET(ISC_R_NOTFOUND);
++ obj->slot = token->slotid;
++ if (gotpin) {
++ memmove(token->pin, pin, PINLEN);
++ obj->reqlogon = ISC_TRUE;
++ }
++
++ ret = ISC_R_SUCCESS;
++
++ err:
++ if (stream != NULL)
++ (void) isc_stdio_close(stream);
++ isc_mem_put(mctx, uri, len);
++ return (ret);
++}
++
++void
++pk11_error_fatalcheck(const char *file, int line,
++ const char *funcname, CK_RV rv)
++{
++ isc_error_fatal(file, line, "%s: Error = 0x%.8lX\n", funcname, rv);
++}
++
++void
++pk11_dump_tokens(void)
++{
++ pk11_token_t *token;
++ isc_boolean_t first;
++
++ printf("DEFAULTS\n");
++ printf("\trand_token=%p\n", rand_token);
++ printf("\tbest_rsa_token=%p\n", best_rsa_token);
++ printf("\tbest_dsa_token=%p\n", best_dsa_token);
++ printf("\tbest_dh_token=%p\n", best_dh_token);
++ printf("\tdigest_token=%p\n", digest_token);
++ printf("\tbest_ec_token=%p\n", best_ec_token);
++ printf("\tbest_gost_token=%p\n", best_gost_token);
++ printf("\taes_token=%p\n", aes_token);
++
++ for (token = ISC_LIST_HEAD(tokens);
++ token != NULL;
++ token = ISC_LIST_NEXT(token, link)) {
++ printf("\nTOKEN\n");
++ printf("\taddress=%p\n", token);
++ printf("\tslotID=%lu\n", token->slotid);
++ printf("\tlabel=%.32s\n", token->name);
++ printf("\tmanufacturerID=%.32s\n", token->manuf);
++ printf("\tmodel=%.16s\n", token->model);
++ printf("\tserialNumber=%.16s\n", token->serial);
++ printf("\tsupported operations=0x%x (", token->operations);
++ first = ISC_TRUE;
++ if (token->operations & (1 << OP_RAND)) {
++ if (!first)
++ printf(",");
++ first = ISC_FALSE;
++ printf("RAND");
++ }
++ if (token->operations & (1 << OP_RSA)) {
++ if (!first)
++ printf(",");
++ first = ISC_FALSE;
++ printf("RSA");
++ }
++ if (token->operations & (1 << OP_DSA)) {
++ if (!first)
++ printf(",");
++ first = ISC_FALSE;
++ printf("DSA");
++ }
++ if (token->operations & (1 << OP_DH)) {
++ if (!first)
++ printf(",");
++ first = ISC_FALSE;
++ printf("DH");
++ }
++ if (token->operations & (1 << OP_DIGEST)) {
++ if (!first)
++ printf(",");
++ first = ISC_FALSE;
++ printf("DIGEST");
++ }
++ if (token->operations & (1 << OP_EC)) {
++ if (!first)
++ printf(",");
++ first = ISC_FALSE;
++ printf("EC");
++ }
++ printf(")\n");
++ }
++}
+diff -up bind-9.9.6/lib/isc/pk11_result.c.native_pkcs11 bind-9.9.6/lib/isc/pk11_result.c
+--- bind-9.9.6/lib/isc/pk11_result.c.native_pkcs11 2014-10-09 13:30:47.842302944 +0200
++++ bind-9.9.6/lib/isc/pk11_result.c 2014-10-09 13:30:47.842302944 +0200
+@@ -0,0 +1,85 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <config.h>
++#include <stddef.h>
++
++#include <isc/once.h>
++#include <isc/msgcat.h>
++#include <isc/util.h>
++
++#include <pk11/result.h>
++
++LIBISC_EXTERNAL_DATA isc_msgcat_t * pk11_msgcat = NULL;
++
++static isc_once_t msgcat_once = ISC_ONCE_INIT;
++
++static const char *text[PK11_R_NRESULTS] = {
++ "PKCS#11 initialization failed", /*%< 0 */
++ "no PKCS#11 provider", /*%< 1 */
++ "PKCS#11 provider has no random service", /*%< 2 */
++ "PKCS#11 provider has no digest service", /*%< 3 */
++ "PKCS#11 provider has no AES service", /*%< 4 */
++};
++
++#define PK11_RESULT_RESULTSET 2
++
++static isc_once_t once = ISC_ONCE_INIT;
++
++static void
++open_msgcat(void) {
++ isc_msgcat_open("libpk11.cat", &pk11_msgcat);
++}
++
++void
++pk11_initmsgcat(void) {
++
++ /*
++ * Initialize the PKCS#11 support's message catalog,
++ * pk11_msgcat, if it has not already been initialized.
++ */
++
++ RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS);
++}
++
++static void
++initialize_action(void) {
++ isc_result_t result;
++
++ result = isc_result_register(ISC_RESULTCLASS_PK11, PK11_R_NRESULTS,
++ text, pk11_msgcat, PK11_RESULT_RESULTSET);
++ if (result != ISC_R_SUCCESS)
++ UNEXPECTED_ERROR(__FILE__, __LINE__,
++ "isc_result_register() failed: %u", result);
++}
++
++static void
++initialize(void) {
++ pk11_initmsgcat();
++ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
++}
++
++const char *
++pk11_result_totext(isc_result_t result) {
++ initialize();
++
++ return (isc_result_totext(result));
++}
++
++void
++pk11_result_register(void) {
++ initialize();
++}
+diff -up bind-9.9.6/lib/isc/sha1.c.native_pkcs11 bind-9.9.6/lib/isc/sha1.c
+--- bind-9.9.6/lib/isc/sha1.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/sha1.c 2014-10-09 13:30:47.842302944 +0200
+@@ -44,8 +44,12 @@
+ #include <isc/types.h>
+ #include <isc/util.h>
+
+-#ifdef ISC_PLATFORM_OPENSSLHASH
++#if PKCS11CRYPTO
++#include <pk11/internal.h>
++#include <pk11/pk11.h>
++#endif
+
++#ifdef ISC_PLATFORM_OPENSSLHASH
+ void
+ isc_sha1_init(isc_sha1_t *context)
+ {
+@@ -77,6 +81,50 @@ isc_sha1_final(isc_sha1_t *context, unsi
+ EVP_DigestFinal(context, digest, NULL);
+ }
+
++#elif PKCS11CRYPTO
++
++void
++isc_sha1_init(isc_sha1_t *ctx) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA_1, NULL, 0 };
++
++ RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
++}
++
++void
++isc_sha1_invalidate(isc_sha1_t *ctx) {
++ CK_BYTE garbage[ISC_SHA1_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA1_DIGESTLENGTH;
++
++ if (ctx->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(ctx->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(ctx);
++}
++
++void
++isc_sha1_update(isc_sha1_t *ctx, const unsigned char *buf, unsigned int len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ DE_CONST(buf, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (ctx->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_sha1_final(isc_sha1_t *ctx, unsigned char *digest) {
++ CK_RV rv;
++ CK_ULONG len = ISC_SHA1_DIGESTLENGTH;
++
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (ctx->session, (CK_BYTE_PTR) digest, &len));
++ pk11_return_session(ctx);
++}
++
+ #else
+
+ #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+diff -up bind-9.9.6/lib/isc/sha2.c.native_pkcs11 bind-9.9.6/lib/isc/sha2.c
+--- bind-9.9.6/lib/isc/sha2.c.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/sha2.c 2014-10-09 13:30:47.843302946 +0200
+@@ -63,6 +63,11 @@
+ #include <isc/string.h>
+ #include <isc/util.h>
+
++#if PKCS11CRYPTO
++#include <pk11/internal.h>
++#include <pk11/pk11.h>
++#endif
++
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+
+ void
+@@ -219,6 +224,272 @@ isc_sha384_final(isc_uint8_t digest[], i
+ }
+ }
+
++#elif PKCS11CRYPTO
++
++void
++isc_sha224_init(isc_sha224_t *context) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA224, NULL, 0 };
++
++ if (context == (isc_sha224_t *)0) {
++ return;
++ }
++ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech));
++}
++
++void
++isc_sha224_invalidate(isc_sha224_t *context) {
++ CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA224_DIGESTLENGTH;
++
++ if (context->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(context);
++}
++
++void
++isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ if (len == 0U) {
++ /* Calling with no data is valid - we do nothing */
++ return;
++ }
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha224_t *)0 && data != (isc_uint8_t*)0);
++
++ DE_CONST(data, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (context->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
++ CK_RV rv;
++ CK_ULONG len = ISC_SHA224_DIGESTLENGTH;
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha224_t *)0);
++
++ /* If no digest buffer is passed, we don't bother doing this: */
++ if (digest != (isc_uint8_t*)0) {
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (context->session,
++ (CK_BYTE_PTR) digest,
++ &len));
++ } else {
++ CK_BYTE garbage[ISC_SHA224_DIGESTLENGTH];
++
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ }
++ pk11_return_session(context);
++}
++
++void
++isc_sha256_init(isc_sha256_t *context) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA256, NULL, 0 };
++
++ if (context == (isc_sha256_t *)0) {
++ return;
++ }
++ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech));
++}
++
++void
++isc_sha256_invalidate(isc_sha256_t *context) {
++ CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA256_DIGESTLENGTH;
++
++ if (context->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(context);
++}
++
++void
++isc_sha256_update(isc_sha256_t *context, const isc_uint8_t* data, size_t len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ if (len == 0U) {
++ /* Calling with no data is valid - we do nothing */
++ return;
++ }
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha256_t *)0 && data != (isc_uint8_t*)0);
++
++ DE_CONST(data, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (context->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
++ CK_RV rv;
++ CK_ULONG len = ISC_SHA256_DIGESTLENGTH;
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha256_t *)0);
++
++ /* If no digest buffer is passed, we don't bother doing this: */
++ if (digest != (isc_uint8_t*)0) {
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (context->session,
++ (CK_BYTE_PTR) digest,
++ &len));
++ } else {
++ CK_BYTE garbage[ISC_SHA256_DIGESTLENGTH];
++
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ }
++ pk11_return_session(context);
++}
++
++void
++isc_sha512_init(isc_sha512_t *context) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA512, NULL, 0 };
++
++ if (context == (isc_sha512_t *)0) {
++ return;
++ }
++ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech));
++}
++
++void
++isc_sha512_invalidate(isc_sha512_t *context) {
++ CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA512_DIGESTLENGTH;
++
++ if (context->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(context);
++}
++
++void
++isc_sha512_update(isc_sha512_t *context, const isc_uint8_t* data, size_t len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ if (len == 0U) {
++ /* Calling with no data is valid - we do nothing */
++ return;
++ }
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha512_t *)0 && data != (isc_uint8_t*)0);
++
++ DE_CONST(data, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (context->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
++ CK_RV rv;
++ CK_ULONG len = ISC_SHA512_DIGESTLENGTH;
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha512_t *)0);
++
++ /* If no digest buffer is passed, we don't bother doing this: */
++ if (digest != (isc_uint8_t*)0) {
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (context->session,
++ (CK_BYTE_PTR) digest,
++ &len));
++ } else {
++ CK_BYTE garbage[ISC_SHA512_DIGESTLENGTH];
++
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ }
++ pk11_return_session(context);
++}
++
++void
++isc_sha384_init(isc_sha384_t *context) {
++ CK_RV rv;
++ CK_MECHANISM mech = { CKM_SHA384, NULL, 0 };
++
++ if (context == (isc_sha384_t *)0) {
++ return;
++ }
++ RUNTIME_CHECK(pk11_get_session(context, OP_DIGEST, ISC_TRUE, ISC_FALSE,
++ ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
++ PK11_FATALCHECK(pkcs_C_DigestInit, (context->session, &mech));
++}
++
++void
++isc_sha384_invalidate(isc_sha384_t *context) {
++ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH];
++ CK_ULONG len = ISC_SHA384_DIGESTLENGTH;
++
++ if (context->handle == NULL)
++ return;
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ pk11_return_session(context);
++}
++
++void
++isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
++ CK_RV rv;
++ CK_BYTE_PTR pPart;
++
++ if (len == 0U) {
++ /* Calling with no data is valid - we do nothing */
++ return;
++ }
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha384_t *)0 && data != (isc_uint8_t*)0);
++
++ DE_CONST(data, pPart);
++ PK11_FATALCHECK(pkcs_C_DigestUpdate,
++ (context->session, pPart, (CK_ULONG) len));
++}
++
++void
++isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
++ CK_RV rv;
++ CK_ULONG len = ISC_SHA384_DIGESTLENGTH;
++
++ /* Sanity check: */
++ REQUIRE(context != (isc_sha384_t *)0);
++
++ /* If no digest buffer is passed, we don't bother doing this: */
++ if (digest != (isc_uint8_t*)0) {
++ PK11_FATALCHECK(pkcs_C_DigestFinal,
++ (context->session,
++ (CK_BYTE_PTR) digest,
++ &len));
++ } else {
++ CK_BYTE garbage[ISC_SHA384_DIGESTLENGTH];
++
++ (void) pkcs_C_DigestFinal(context->session, garbage, &len);
++ memset(garbage, 0, sizeof(garbage));
++ }
++ pk11_return_session(context);
++}
++
+ #else
+
+ /*
+@@ -1312,6 +1583,8 @@ isc_sha224_end(isc_sha224_t *context, ch
+ } else {
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
++#elif PKCS11CRYPTO
++ pk11_return_session(context);
+ #else
+ memset(context, 0, sizeof(*context));
+ #endif
+@@ -1351,6 +1624,8 @@ isc_sha256_end(isc_sha256_t *context, ch
+ } else {
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
++#elif PKCS11CRYPTO
++ pk11_return_session(context);
+ #else
+ memset(context, 0, sizeof(*context));
+ #endif
+@@ -1390,6 +1665,8 @@ isc_sha512_end(isc_sha512_t *context, ch
+ } else {
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
++#elif PKCS11CRYPTO
++ pk11_return_session(context);
+ #else
+ memset(context, 0, sizeof(*context));
+ #endif
+@@ -1429,6 +1706,8 @@ isc_sha384_end(isc_sha384_t *context, ch
+ } else {
+ #ifdef ISC_PLATFORM_OPENSSLHASH
+ EVP_MD_CTX_cleanup(context);
++#elif PKCS11CRYPTO
++ pk11_return_session(context);
+ #else
+ memset(context, 0, sizeof(*context));
+ #endif
+diff -up bind-9.9.6/lib/isc/unix/include/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/unix/include/Makefile.in
+--- bind-9.9.6/lib/isc/unix/include/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/unix/include/Makefile.in 2014-10-09 13:30:47.843302946 +0200
+@@ -19,7 +19,7 @@ srcdir = @srcdir@
+ VPATH = @srcdir@
+ top_srcdir = @top_srcdir@
+
+-SUBDIRS = isc
++SUBDIRS = isc pkcs11
+ TARGETS =
+
+ @BIND9_MAKE_RULES@
+diff -up bind-9.9.6/lib/isc/unix/include/pkcs11/cryptoki.h.native_pkcs11 bind-9.9.6/lib/isc/unix/include/pkcs11/cryptoki.h
+--- bind-9.9.6/lib/isc/unix/include/pkcs11/cryptoki.h.native_pkcs11 2014-10-09 13:30:47.843302946 +0200
++++ bind-9.9.6/lib/isc/unix/include/pkcs11/cryptoki.h 2014-10-09 13:30:47.843302946 +0200
+@@ -0,0 +1,66 @@
++/* cryptoki.h include file for PKCS #11. */
++/*
++ * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
++ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
++ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
++ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++/* $Revision: 1.3 $ */
++
++/*
++ * Portions Copyright RSA Security Inc.
++ *
++ * License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This is a sample file containing the top level include directives
++ * for building Unix Cryptoki libraries and applications.
++ */
++
++#ifndef ___CRYPTOKI_H_INC___
++#define ___CRYPTOKI_H_INC___
++
++#define CK_PTR *
++
++#define CK_DEFINE_FUNCTION(returnType, name) \
++ returnType name
++
++#define CK_DECLARE_FUNCTION(returnType, name) \
++ returnType name
++
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ returnType (* name)
++
++#define CK_CALLBACK_FUNCTION(returnType, name) \
++ returnType (* name)
++
++/* NULL is in unistd.h */
++#include <unistd.h>
++#define NULL_PTR NULL
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++#include <pkcs11/pkcs11.h>
++
++#endif /* ___CRYPTOKI_H_INC___ */
+diff -up bind-9.9.6/lib/isc/unix/include/pkcs11/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/unix/include/pkcs11/Makefile.in
+--- bind-9.9.6/lib/isc/unix/include/pkcs11/Makefile.in.native_pkcs11 2014-10-09 13:30:47.843302946 +0200
++++ bind-9.9.6/lib/isc/unix/include/pkcs11/Makefile.in 2014-10-09 13:30:47.843302946 +0200
+@@ -0,0 +1,33 @@
++# Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++#
++# Permission to use, copy, modify, and/or distribute this software for any
++# purpose with or without fee is hereby granted, provided that the above
++# copyright notice and this permission notice appear in all copies.
++#
++# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++# PERFORMANCE OF THIS SOFTWARE.
++
++# $Id: Makefile.in,v 1.4 2007/06/19 23:47:23 tbox Exp $
++
++srcdir = @srcdir@
++VPATH = @srcdir@
++top_srcdir = @top_srcdir@
++
++HEADERS = cryptoki.h
++SUBDIRS =
++TARGETS =
++
++@BIND9_MAKE_RULES@
++
++installdirs:
++ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/pkcs11
++
++install:: installdirs
++ for i in ${HEADERS}; do \
++ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/pkcs11 ; \
++ done
+diff -up bind-9.9.6/lib/isc/unix/Makefile.in.native_pkcs11 bind-9.9.6/lib/isc/unix/Makefile.in
+--- bind-9.9.6/lib/isc/unix/Makefile.in.native_pkcs11 2014-09-16 21:27:20.000000000 +0200
++++ bind-9.9.6/lib/isc/unix/Makefile.in 2014-10-09 13:30:47.843302946 +0200
+@@ -29,14 +29,14 @@ CDEFINES =
+ CWARNINGS =
+
+ # Alphabetically
+-OBJS = @ISC_IPV6_O@ \
++OBJS = @ISC_IPV6_O@ @ISC_PK11_API_O@ \
+ app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \
+ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \
+ os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
+ strerror.@O@ syslog.@O@ time.@O@
+
+ # Alphabetically
+-SRCS = @ISC_IPV6_C@ \
++SRCS = @ISC_IPV6_C@ @ISC_PK11_API_C@ \
+ app.c dir.c entropy.c errno2result.c file.c \
+ fsaccess.c interfaceiter.c keyboard.c net.c \
+ os.c resource.c socket.c stdio.c stdtime.c \
+diff -up bind-9.9.6/lib/isc/unix/pk11_api.c.native_pkcs11 bind-9.9.6/lib/isc/unix/pk11_api.c
+--- bind-9.9.6/lib/isc/unix/pk11_api.c.native_pkcs11 2014-10-09 13:30:47.844302947 +0200
++++ bind-9.9.6/lib/isc/unix/pk11_api.c 2014-10-09 13:30:47.844302947 +0200
+@@ -0,0 +1,673 @@
++/*
++ * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
++ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
++ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
++ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
++ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
++ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
++ * PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/* $Id$ */
++
++/*! \file */
++
++#include <config.h>
++
++#include <string.h>
++#include <dlfcn.h>
++
++#include <isc/log.h>
++#include <isc/mem.h>
++#include <isc/once.h>
++#include <isc/stdio.h>
++#include <isc/thread.h>
++#include <isc/util.h>
++
++#include <pkcs11/cryptoki.h>
++#include <pkcs11/pkcs11.h>
++
++#define KEEP_PKCS11_NAMES
++#include <pk11/pk11.h>
++#include <pk11/internal.h>
++
++static void *hPK11 = NULL;
++
++CK_RV
++pkcs_C_Initialize(CK_VOID_PTR pReserved) {
++ CK_C_Initialize sym;
++
++ if (hPK11 != NULL)
++ return (CKR_LIBRARY_ALREADY_INITIALIZED);
++
++ hPK11 = dlopen(pk11_get_lib_name(), RTLD_NOW);
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ sym = (CK_C_Initialize)dlsym(hPK11, "C_Initialize");
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(pReserved);
++}
++
++CK_RV
++pkcs_C_Finalize(CK_VOID_PTR pReserved) {
++ CK_C_Finalize sym;
++ CK_RV rv;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ sym = (CK_C_Finalize)dlsym(hPK11, "C_Finalize");
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ rv = (*sym)(pReserved);
++ if ((rv == CKR_OK) && (dlclose(hPK11) != 0))
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ hPK11 = NULL;
++ return (rv);
++}
++
++CK_RV
++pkcs_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
++ CK_ULONG_PTR pulCount)
++{
++ static CK_C_GetSlotList sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GetSlotList)dlsym(hPK11, "C_GetSlotList");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(tokenPresent, pSlotList, pulCount);
++}
++
++CK_RV
++pkcs_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) {
++ static CK_C_GetTokenInfo sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GetTokenInfo)dlsym(hPK11, "C_GetTokenInfo");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(slotID, pInfo);
++}
++
++CK_RV
++pkcs_C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
++ CK_MECHANISM_INFO_PTR pInfo)
++{
++ static CK_C_GetMechanismInfo sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GetMechanismInfo)dlsym(hPK11,
++ "C_GetMechanismInfo");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(slotID, type, pInfo);
++}
++
++CK_RV
++pkcs_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
++ CK_VOID_PTR pApplication,
++ CK_RV (*Notify) (CK_SESSION_HANDLE hSession,
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication),
++ CK_SESSION_HANDLE_PTR phSession)
++{
++ static CK_C_OpenSession sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ hPK11 = dlopen(pk11_get_lib_name(), RTLD_NOW);
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_OpenSession)dlsym(hPK11, "C_OpenSession");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(slotID, flags, pApplication, Notify, phSession);
++}
++
++CK_RV
++pkcs_C_CloseSession(CK_SESSION_HANDLE hSession) {
++ static CK_C_CloseSession sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_CloseSession)dlsym(hPK11, "C_CloseSession");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession);
++}
++
++CK_RV
++pkcs_C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
++ CK_CHAR_PTR pPin, CK_ULONG usPinLen)
++{
++ static CK_C_Login sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_Login)dlsym(hPK11, "C_Login");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, userType, pPin, usPinLen);
++}
++
++CK_RV
++pkcs_C_Logout(CK_SESSION_HANDLE hSession) {
++ static CK_C_Logout sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_Logout)dlsym(hPK11, "C_Logout");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession);
++}
++
++CK_RV
++pkcs_C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
++ CK_ULONG usCount, CK_OBJECT_HANDLE_PTR phObject)
++{
++ static CK_C_CreateObject sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_CreateObject)dlsym(hPK11, "C_CreateObject");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pTemplate, usCount, phObject);
++}
++
++CK_RV
++pkcs_C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
++ static CK_C_DestroyObject sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_DestroyObject)dlsym(hPK11, "C_DestroyObject");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, hObject);
++}
++
++CK_RV
++pkcs_C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount)
++{
++ static CK_C_GetAttributeValue sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GetAttributeValue)dlsym(hPK11,
++ "C_GetAttributeValue");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, hObject, pTemplate, usCount);
++}
++
++CK_RV
++pkcs_C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG usCount)
++{
++ static CK_C_SetAttributeValue sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_SetAttributeValue)dlsym(hPK11,
++ "C_SetAttributeValue");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, hObject, pTemplate, usCount);
++}
++
++CK_RV
++pkcs_C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
++ CK_ULONG usCount)
++{
++ static CK_C_FindObjectsInit sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_FindObjectsInit)dlsym(hPK11, "C_FindObjectsInit");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pTemplate, usCount);
++}
++
++CK_RV
++pkcs_C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
++ CK_ULONG usMaxObjectCount, CK_ULONG_PTR pusObjectCount)
++{
++ static CK_C_FindObjects sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_FindObjects)dlsym(hPK11, "C_FindObjects");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, phObject, usMaxObjectCount, pusObjectCount);
++}
++
++CK_RV
++pkcs_C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
++{
++ static CK_C_FindObjectsFinal sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_FindObjectsFinal)dlsym(hPK11,
++ "C_FindObjectsFinal");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession);
++}
++
++CK_RV
++pkcs_C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hKey)
++{
++ static CK_C_EncryptInit sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_EncryptInit)dlsym(hPK11, "C_EncryptInit");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pMechanism, hKey);
++}
++
++CK_RV
++pkcs_C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
++ CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
++ CK_ULONG_PTR pulEncryptedDataLen)
++{
++ static CK_C_Encrypt sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_Encrypt)dlsym(hPK11, "C_Encrypt");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pData, ulDataLen,
++ pEncryptedData, pulEncryptedDataLen);
++}
++
++CK_RV
++pkcs_C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) {
++ static CK_C_DigestInit sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_DigestInit)dlsym(hPK11, "C_DigestInit");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pMechanism);
++}
++
++CK_RV
++pkcs_C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
++ CK_ULONG ulPartLen)
++{
++ static CK_C_DigestUpdate sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_DigestUpdate)dlsym(hPK11, "C_DigestUpdate");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pPart, ulPartLen);
++}
++
++CK_RV
++pkcs_C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
++ CK_ULONG_PTR pulDigestLen)
++{
++ static CK_C_DigestFinal sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_DigestFinal)dlsym(hPK11, "C_DigestFinal");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pDigest, pulDigestLen);
++}
++
++CK_RV
++pkcs_C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hKey)
++{
++ static CK_C_SignInit sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_SignInit)dlsym(hPK11, "C_SignInit");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pMechanism, hKey);
++}
++
++CK_RV
++pkcs_C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
++ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
++ CK_ULONG_PTR pulSignatureLen)
++{
++ static CK_C_Sign sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_Sign)dlsym(hPK11, "C_Sign");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pData, ulDataLen, pSignature, pulSignatureLen);
++}
++
++CK_RV
++pkcs_C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
++ CK_ULONG ulPartLen)
++{
++ static CK_C_SignUpdate sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_SignUpdate)dlsym(hPK11, "C_SignUpdate");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pPart, ulPartLen);
++}
++
++CK_RV
++pkcs_C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
++ CK_ULONG_PTR pulSignatureLen)
++{
++ static CK_C_SignFinal sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_SignFinal)dlsym(hPK11, "C_SignFinal");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pSignature, pulSignatureLen);
++}
++
++CK_RV
++pkcs_C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hKey)
++{
++ static CK_C_VerifyInit sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_VerifyInit)dlsym(hPK11, "C_VerifyInit");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pMechanism, hKey);
++}
++
++CK_RV
++pkcs_C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
++ CK_ULONG ulDataLen, CK_BYTE_PTR pSignature,
++ CK_ULONG ulSignatureLen)
++{
++ static CK_C_Verify sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_Verify)dlsym(hPK11, "C_Verify");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pData, ulDataLen, pSignature, ulSignatureLen);
++}
++
++CK_RV
++pkcs_C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
++ CK_ULONG ulPartLen)
++{
++ static CK_C_VerifyUpdate sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_VerifyUpdate)dlsym(hPK11, "C_VerifyUpdate");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pPart, ulPartLen);
++}
++
++CK_RV
++pkcs_C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
++ CK_ULONG ulSignatureLen)
++{
++ static CK_C_VerifyFinal sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_VerifyFinal)dlsym(hPK11, "C_VerifyFinal");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pSignature, ulSignatureLen);
++}
++
++CK_RV
++pkcs_C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
++ CK_OBJECT_HANDLE_PTR phKey)
++{
++ static CK_C_GenerateKey sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GenerateKey)dlsym(hPK11, "C_GenerateKey");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pMechanism, pTemplate, ulCount, phKey);
++}
++
++CK_RV
++pkcs_C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_PTR pMechanism,
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate,
++ CK_ULONG usPublicKeyAttributeCount,
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
++ CK_ULONG usPrivateKeyAttributeCount,
++ CK_OBJECT_HANDLE_PTR phPrivateKey,
++ CK_OBJECT_HANDLE_PTR phPublicKey)
++{
++ static CK_C_GenerateKeyPair sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GenerateKeyPair)dlsym(hPK11, "C_GenerateKeyPair");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession,
++ pMechanism,
++ pPublicKeyTemplate,
++ usPublicKeyAttributeCount,
++ pPrivateKeyTemplate,
++ usPrivateKeyAttributeCount,
++ phPrivateKey,
++ phPublicKey);
++}
++
++CK_RV
++pkcs_C_DeriveKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
++ CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate,
++ CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey)
++{
++ static CK_C_DeriveKey sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_DeriveKey)dlsym(hPK11, "C_DeriveKey");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession,
++ pMechanism,
++ hBaseKey,
++ pTemplate,
++ ulAttributeCount,
++ phKey);
++}
++
++CK_RV
++pkcs_C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
++ CK_ULONG ulSeedLen)
++{
++ static CK_C_SeedRandom sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_SeedRandom)dlsym(hPK11, "C_SeedRandom");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, pSeed, ulSeedLen);
++}
++
++CK_RV
++pkcs_C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData,
++ CK_ULONG ulRandomLen)
++{
++ static CK_C_GenerateRandom sym = NULL;
++ static void *pPK11 = NULL;
++
++ if (hPK11 == NULL)
++ return (CKR_LIBRARY_FAILED_TO_LOAD);
++ if ((sym == NULL) || (hPK11 != pPK11)) {
++ pPK11 = hPK11;
++ sym = (CK_C_GenerateRandom)dlsym(hPK11, "C_GenerateRandom");
++ }
++ if (sym == NULL)
++ return (CKR_SYMBOL_RESOLUTION_FAILED);
++ return (*sym)(hSession, RandomData, ulRandomLen);
++}
diff --git a/bind.spec b/bind.spec
index 32e6e26..c56f65b 100644
--- a/bind.spec
+++ b/bind.spec
@@ -11,11 +11,7 @@
%{?!bind_uid: %global bind_uid 25}
%{?!bind_gid: %global bind_gid 25}
%{?!GSSTSIG: %global GSSTSIG 1}
-%if 0%{?rhel}
-%{?!PKCS11: %global PKCS11 0}
-%else
%{?!PKCS11: %global PKCS11 1}
-%endif
%{?!DEVEL: %global DEVEL 1}
%{?!developer: %global developer 0}
%global bind_dir /var/named
@@ -28,7 +24,7 @@ Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
Name: bind
License: ISC
Version: 9.9.6
-Release: 1%{?PATCHVER:.%{PATCHVER}}%{?PREVER:.%{PREVER}}%{?dist}
+Release: 2%{?PATCHVER:.%{PATCHVER}}%{?PREVER:.%{PREVER}}%{?dist}
Epoch: 32
Url: http://www.isc.org/products/BIND/
Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -60,6 +56,7 @@ Source43: named.rwtab
Source44: named-chroot-setup.service
Source45: named-sdb-chroot-setup.service
Source46: named-setup-rndc.service
+Source47: named-pkcs11.service
# Common patches
Patch10: bind-9.5-PIE.patch
@@ -69,7 +66,6 @@ Patch87: bind-9.5-parallel-build.patch
Patch101:bind-96-old-api.patch
Patch102:bind-95-rh452060.patch
Patch106:bind93-rh490837.patch
-Patch107:bind97-dist-pkcs11.patch
Patch109:bind97-rh478718.patch
Patch110:bind97-rh570851.patch
Patch111:bind97-exportlib.patch
@@ -83,6 +79,9 @@ Patch131:bind-9.9.1-P2-multlib-conflict.patch
Patch133:bind99-rh640538.patch
Patch134:bind97-rh669163.patch
Patch135:bind99-rh985918.patch
+# Native PKCS#11 functionality from 9.10
+Patch136:bind-9.9-native-pkcs11.patch
+Patch137:bind-9.9-dist-native-pkcs11.patch
# SDB patches
Patch11: bind-9.3.2b2-sdbsrc.patch
@@ -136,14 +135,47 @@ tools for verifying that the DNS server is operating properly.
%if %{PKCS11}
%package pkcs11
-Summary: Bind PKCS#11 tools for using DNSSEC
+Summary: Bind with native PKCS#11 functionality for crypto
Group: System Environment/Daemons
-Requires: engine_pkcs11 opensc
+Requires: systemd-units
+Requires: bind%{?_isa} = %{epoch}:%{version}-%{release}
+Requires: bind-pkcs11-libs%{?_isa} = %{epoch}:%{version}-%{release}
%description pkcs11
+This is a version of BIND server built with native PKCS#11 functionality.
+It is important to have SoftHSM v2+ installed and some token initialized.
+For other supported HSM modules please check the BIND documentation.
+
+%package pkcs11-utils
+Summary: Bind tools with native PKCS#11 for using DNSSEC
+Group: System Environment/Daemons
+Requires: bind-pkcs11-libs%{?_isa} = %{epoch}:%{version}-%{release}
+Obsoletes: bind-pkcs11 < 32:9.9.4-16.P2
+
+%description pkcs11-utils
This is a set of PKCS#11 utilities that when used together create rsa
-keys in a PKCS11 keystore, such as provided by opencryptoki. The keys
-will have a label of "zone,zsk|ksk,xxx" and an id of the keytag in hex.
+keys in a PKCS11 keystore. Also utilities for working with DNSSEC
+compiled with native PKCS#11 functionality are included.
+
+%package pkcs11-libs
+Summary: Bind libraries compiled with native PKCS#11
+Group: System Environment/Daemons
+Requires: engine_pkcs11
+Requires: bind-license = %{epoch}:%{version}-%{release}
+Requires: bind-libs%{?_isa} = %{epoch}:%{version}-%{release}
+
+%description pkcs11-libs
+This is a set of BIND libraries (dns, isc) compiled with native PKCS#11
+functionality.
+
+%package pkcs11-devel
+Summary: Development files for Bind libraries compiled with native PKCS#11
+Group: System Environment/Daemons
+Requires: bind-pkcs11-libs%{?_isa} = %{epoch}:%{version}-%{release}
+
+%description pkcs11-devel
+This a set of development files for BIND libraries (dns, isc) compiled
+with native PKCS#11 functionality.
%endif
%if %{SDB}
@@ -152,6 +184,7 @@ Summary: BIND server with database backends and DLZ support
Group: System Environment/Daemons
Requires: bind
Requires: systemd-units
+Requires: bind%{?_isa} = %{epoch}:%{version}-%{release}
Requires: bind-libs%{?_isa} = %{epoch}:%{version}-%{release}
%description sdb
@@ -237,8 +270,8 @@ Group: System Environment/Daemons
Prefix: %{chroot_prefix}
Requires(post): grep
Requires(preun):grep
-Requires: bind%{?_isa} = %{epoch}:%{version}-%{release}
Requires: systemd-units
+Requires: bind%{?_isa} = %{epoch}:%{version}-%{release}
%description chroot
This package contains a tree of files which can be used as a
@@ -249,7 +282,7 @@ Based on the code from Jan "Yenya" Kasprzak <kas@fi.muni.cz>
%package sdb-chroot
Summary: A chroot runtime environment for the ISC BIND DNS server, named-sdb(8)
Group: System Environment/Daemons
-Prefix: %{chroot_prefix}
+Prefix: %{chroot_sdb_prefix}
Requires: bind-sdb%{?_isa} = %{epoch}:%{version}-%{release}
Requires: systemd-units
@@ -275,7 +308,6 @@ Based on the code from Jan "Yenya" Kasprzak <kas@fi.muni.cz>
%patch102 -p1 -b .rh452060
%patch106 -p0 -b .rh490837
-%patch107 -p1 -b .dist-pkcs11
%patch109 -p1 -b .rh478718
%patch110 -p1 -b .rh570851
%patch111 -p1 -b .exportlib
@@ -288,6 +320,17 @@ popd
%patch125 -p1 -b .buildfix
%patch130 -p1 -b .libdb
%patch131 -p1 -b .multlib-conflict
+%patch136 -p1 -b .native_pkcs11
+
+%if %{PKCS11}
+cp -r bin/named{,-pkcs11}
+cp -r bin/dnssec{,-pkcs11}
+cp -r lib/isc{,-pkcs11}
+cp -r lib/dns{,-pkcs11}
+cp -r lib/export/isc{,-pkcs11}
+cp -r lib/export/dns{,-pkcs11}
+%patch137 -p1 -b .dist_pkcs11
+%endif
%if %{SDB}
%patch101 -p1 -b .old-api
@@ -314,6 +357,7 @@ cp -fp contrib/sdb/pgsql/zonetodb.c bin/sdb_tools
cp -fp contrib/sdb/sqlite/zone2sqlite.c bin/sdb_tools
%patch12 -p1 -b .sdb
%endif
+
%if %{SDB}
%patch17 -p1 -b .fix_sdb_ldap
%endif
@@ -359,7 +403,8 @@ libtoolize -c -f; aclocal -I libtool.m4 --force; autoconf -f
--with-export-includedir=%{_includedir} \
--includedir=%{_includedir}/bind9 \
%if %{PKCS11}
- --with-pkcs11=%{_libdir}/pkcs11/PKCS11_API.so \
+ --enable-native-pkcs11 \
+ --with-pkcs11=%{_libdir}/pkcs11/libsofthsm2.so \
%endif
%if %{SDB}
--with-dlopen=yes \
@@ -485,6 +530,10 @@ install -m 644 %{SOURCE40} ${RPM_BUILD_ROOT}%{_unitdir}
install -m 644 %{SOURCE45} ${RPM_BUILD_ROOT}%{_unitdir}
%endif
+%if %{PKCS11}
+install -m 644 %{SOURCE47} ${RPM_BUILD_ROOT}%{_unitdir}
+%endif
+
mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir}
install -m 755 %{SOURCE41} ${RPM_BUILD_ROOT}%{_libexecdir}/setup-named-chroot.sh
install -m 755 %{SOURCE42} ${RPM_BUILD_ROOT}%{_libexecdir}/generate-rndc-key.sh
@@ -527,6 +576,22 @@ install -m 644 %{SOURCE33} ${RPM_BUILD_ROOT}%{_mandir}/man1/zonetodb.1
install -m 644 %{SOURCE34} ${RPM_BUILD_ROOT}%{_mandir}/man1/zone2sqlite.1
%endif
+# PKCS11 versions manpages
+%if %{PKCS11}
+pushd ${RPM_BUILD_ROOT}%{_mandir}/man8
+ln -s named.8.gz named-pkcs11.8.gz
+ln -s dnssec-checkds.8.gz dnssec-checkds-pkcs11.8.gz
+ln -s dnssec-coverage.8.gz dnssec-coverage-pkcs11.8.gz
+ln -s dnssec-dsfromkey.8.gz dnssec-dsfromkey-pkcs11.8.gz
+ln -s dnssec-keyfromlabel.8.gz dnssec-keyfromlabel-pkcs11.8.gz
+ln -s dnssec-keygen.8.gz dnssec-keygen-pkcs11.8.gz
+ln -s dnssec-revoke.8.gz dnssec-revoke-pkcs11.8.gz
+ln -s dnssec-settime.8.gz dnssec-settime-pkcs11.8.gz
+ln -s dnssec-signzone.8.gz dnssec-signzone-pkcs11.8.gz
+ln -s dnssec-verify.8.gz dnssec-verify-pkcs11.8.gz
+popd
+%endif
+
# Ghost config files:
touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/named.log
@@ -599,6 +664,20 @@ fi
%systemd_postun_with_restart named-sdb.service
%endif
+%if %{PKCS11}
+%post pkcs11
+# Initial installation
+%systemd_post named-pkcs11.service
+
+%preun pkcs11
+# Package removal, not upgrade
+%systemd_preun named-pkcs11.service
+
+%postun pkcs11
+# Package upgrade, not uninstall
+%systemd_postun_with_restart named-pkcs11.service
+%endif
+
%triggerpostun -n bind -- bind <= 32:9.5.0-20.b1
if [ "$1" -gt 0 ]; then
[ -e /etc/rndc.key ] && chown root:named /etc/rndc.key
@@ -801,6 +880,7 @@ rm -rf ${RPM_BUILD_ROOT}
%{_sbindir}/genrandom
%{_sbindir}/nsec3hash
%{_sbindir}/dnssec*
+%exclude %{_sbindir}/dnssec*pkcs11
%{_sbindir}/isc-hmac-fixup
%{_sbindir}/named-checkzone
%{_sbindir}/named-compilezone
@@ -813,6 +893,7 @@ rm -rf ${RPM_BUILD_ROOT}
%{_mandir}/man8/genrandom.8*
%{_mandir}/man8/nsec3hash.8*
%{_mandir}/man8/dnssec*.8*
+%exclude %{_mandir}/man8/dnssec*-pkcs11.8*
%{_mandir}/man8/isc-hmac-fixup.8*
%{_mandir}/man8/named-checkzone.8*
%{_mandir}/man8/named-compilezone.8*
@@ -828,6 +909,7 @@ rm -rf ${RPM_BUILD_ROOT}
%{_libdir}/libisccfg.so
%{_libdir}/liblwres.so
%{_includedir}/bind9
+%exclude %{_includedir}/bind9/pkcs11
%{_mandir}/man1/isc-config.sh.1*
%{_mandir}/man1/bind9-config.1*
%{_mandir}/man3/lwres*
@@ -910,14 +992,43 @@ rm -rf ${RPM_BUILD_ROOT}
%if %{PKCS11}
%files pkcs11
%defattr(-,root,root,-)
-%doc COPYRIGHT
+%{_sbindir}/named-pkcs11
+%{_unitdir}/named-pkcs11.service
+%{_mandir}/man8/named-pkcs11.8*
+
+%files pkcs11-utils
+%defattr(-,root,root,-)
+%{_sbindir}/dnssec*pkcs11
%{_sbindir}/pkcs11-destroy
%{_sbindir}/pkcs11-keygen
%{_sbindir}/pkcs11-list
-%{_mandir}/man8/pkcs11*
+%{_sbindir}/pkcs11-tokens
+%{_mandir}/man8/pkcs11*.8*
+%{_mandir}/man8/dnssec*-pkcs11.8*
+
+%files pkcs11-libs
+%defattr(-,root,root,-)
+%{_libdir}/libdns-pkcs11.so.104*
+%{_libdir}/libisc-pkcs11.so.95*
+%{_libdir}/libdns-pkcs11-export.so.104*
+%{_libdir}/libisc-pkcs11-export.so.95*
+
+%files pkcs11-devel
+%defattr(-,root,root,-)
+%{_includedir}/bind9/pkcs11
+%{_libdir}/libdns-pkcs11.so
+%{_libdir}/libisc-pkcs11.so
+%{_libdir}/libdns-pkcs11-export.so
+%{_libdir}/libisc-pkcs11-export.so
+
%endif
%changelog
+* Tue Oct 14 2014 Tomas Hozza <thozza@redhat.com> - 32:9.9.6-2
+- Added native PKCS#11 functionality (#1097752)
+- bind-sdb now requires bind due to configuration and other utilities
+- bind-pkcs11 now requires bind due to configuration and other utilities
+
* Thu Oct 02 2014 Tomas Hozza <thozza@redhat.com> - 32:9.9.6-1
- Update to 9.9.6
- drop merged patches and rebase some of existing patches
diff --git a/bind97-dist-pkcs11.patch b/bind97-dist-pkcs11.patch
deleted file mode 100644
index cf8c9f0..0000000
--- a/bind97-dist-pkcs11.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff -up bind-9.7.0b1/configure.in.dist-pkcs11 bind-9.7.0b1/configure.in
---- bind-9.7.0b1/configure.in.dist-pkcs11 2009-11-03 11:37:25.481430279 +0100
-+++ bind-9.7.0b1/configure.in 2009-11-03 11:41:04.573930858 +0100
-@@ -721,15 +721,16 @@ AC_ARG_WITH(pkcs11,
- case "$use_pkcs11" in
- no|'')
- AC_MSG_RESULT(disabled)
-- USE_PKCS11=''
- PKCS11_TOOLS=''
- ;;
- yes|*)
- AC_MSG_RESULT(using OpenSSL with PKCS11 support)
-- USE_PKCS11='-DUSE_PKCS11'
- PKCS11_TOOLS=pkcs11
- ;;
- esac
-+# We don't want to automatically load engine because it needs to have openct,
-+# opencryptoki and friends installed.
-+USE_PKCS11=''
- AC_SUBST(USE_PKCS11)
- AC_SUBST(PKCS11_TOOLS)
-
diff --git a/named-pkcs11.service b/named-pkcs11.service
new file mode 100644
index 0000000..7c53f48
--- /dev/null
+++ b/named-pkcs11.service
@@ -0,0 +1,26 @@
+[Unit]
+Description=Berkeley Internet Name Domain (DNS) with native PKCS#11
+Wants=nss-lookup.target
+Wants=network-online.target
+Wants=named-setup-rndc.service
+Before=nss-lookup.target
+After=network-online.target
+After=named-setup-rndc.service
+
+[Service]
+Type=forking
+EnvironmentFile=-/etc/sysconfig/named
+Environment=KRB5_KTNAME=/etc/named.keytab
+PIDFile=/run/named/named.pid
+
+ExecStartPre=/usr/sbin/named-checkconf -z /etc/named.conf
+ExecStart=/usr/sbin/named-pkcs11 -u named $OPTIONS
+
+ExecReload=/bin/sh -c '/usr/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID'
+
+ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID'
+
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target