From e9ef042fc45d2004c99dd7642d5032fd5832b270 Mon Sep 17 00:00:00 2001
From: Tomas Hozza <thozza@redhat.com>
Date: Thu, 21 May 2015 10:52:03 +0200
Subject: [PATCH] native PKCS#11
Signed-off-by: Tomas Hozza <thozza@redhat.com>
---
acconfig.h | 7 +-
bin/check/Makefile.in | 3 +-
bin/dig/Makefile.in | 13 +-
bin/dig/dighost.c | 11 +-
bin/dnssec/Makefile.in | 3 +-
bin/dnssec/dnssec-dsfromkey.c | 9 +-
bin/dnssec/dnssec-importkey.c | 93 +-
bin/dnssec/dnssec-importkey.docbook | 58 +-
bin/dnssec/dnssec-keyfromlabel.c | 31 +-
bin/dnssec/dnssec-keyfromlabel.docbook | 43 +-
bin/dnssec/dnssec-keygen.c | 21 +-
bin/dnssec/dnssec-keygen.docbook | 13 +-
bin/dnssec/dnssec-revoke.c | 14 +-
bin/dnssec/dnssec-revoke.docbook | 11 +-
bin/dnssec/dnssec-settime.c | 14 +-
bin/dnssec/dnssec-settime.docbook | 11 +-
bin/dnssec/dnssec-signzone.c | 14 +-
bin/dnssec/dnssec-signzone.docbook | 15 +-
bin/dnssec/dnssec-verify.c | 14 +-
bin/dnssec/dnssec-verify.docbook | 17 +
bin/dnssec/dnssectool.c | 2 +-
bin/named/Makefile.in | 2 +-
bin/named/include/named/globals.h | 4 +-
bin/named/main.c | 6 +
bin/named/named.docbook | 16 +-
bin/named/server.c | 9 +-
bin/nsupdate/Makefile.in | 6 +-
bin/pkcs11/Makefile.in | 67 +-
bin/pkcs11/pkcs11-destroy.8 | 10 +-
bin/pkcs11/pkcs11-destroy.c | 153 +-
bin/pkcs11/pkcs11-destroy.docbook | 19 +-
bin/pkcs11/pkcs11-destroy.html | 22 +-
bin/pkcs11/pkcs11-keygen.8 | 69 +-
bin/pkcs11/pkcs11-keygen.c | 687 +++++++--
bin/pkcs11/pkcs11-keygen.docbook | 115 +-
bin/pkcs11/pkcs11-keygen.html | 90 +-
bin/pkcs11/pkcs11-list.c | 118 +-
bin/pkcs11/pkcs11-tokens.8 | 51 +
bin/pkcs11/pkcs11-tokens.c | 106 ++
bin/pkcs11/pkcs11-tokens.docbook | 86 ++
bin/pkcs11/pkcs11-tokens.html | 58 +
bin/rndc/Makefile.in | 3 +-
bin/tests/Makefile.in | 76 +-
bin/tests/dst/dst_test.c | 7 +-
bin/tests/dst/t_dst.c | 14 +-
bin/tests/pkcs11/Makefile.in | 49 +
bin/tests/pkcs11/benchmarks/Makefile.in | 79 +
bin/tests/pkcs11/benchmarks/create.c | 260 ++++
bin/tests/pkcs11/benchmarks/find.c | 227 +++
bin/tests/pkcs11/benchmarks/genrsa.c | 295 ++++
bin/tests/pkcs11/benchmarks/login.c | 249 ++++
bin/tests/pkcs11/benchmarks/privrsa.c | 360 +++++
bin/tests/pkcs11/benchmarks/pubrsa.c | 281 ++++
bin/tests/pkcs11/benchmarks/random.c | 192 +++
bin/tests/pkcs11/benchmarks/session.c | 213 +++
bin/tests/pkcs11/benchmarks/sha1.c | 214 +++
bin/tests/pkcs11/benchmarks/sign.c | 368 +++++
bin/tests/pkcs11/benchmarks/verify.c | 292 ++++
bin/tests/pkcs11/pkcs11-hmacmd5.c | 332 +++++
bin/tests/pkcs11/pkcs11-md5sum.c | 235 +++
bin/tests/system/autosign/prereq.sh | 3 +-
bin/tests/system/cleanpkcs11.sh | 6 +-
bin/tests/system/conf.sh.in | 8 +-
bin/tests/system/dnssec/prereq.sh | 3 +-
bin/tests/system/ecdsa/prereq.sh.in | 15 +-
bin/tests/system/gost/prereq.sh.in | 15 +-
bin/tests/system/inline/clean.sh | 2 +-
bin/tests/system/metadata/prereq.sh | 3 +-
bin/tests/system/pending/prereq.sh | 23 +-
bin/tests/system/pkcs11/clean.sh | 5 +-
bin/tests/system/pkcs11/ns1/named.conf | 10 +-
bin/tests/system/pkcs11/setup.sh | 64 +-
bin/tests/system/pkcs11/tests.sh | 72 +-
bin/tests/system/pkcs11ssl/clean.sh | 20 +
bin/tests/system/pkcs11ssl/ns1/example.db.in | 29 +
bin/tests/system/pkcs11ssl/ns1/named.conf | 52 +
bin/tests/system/pkcs11ssl/prereq.sh | 34 +
bin/tests/system/pkcs11ssl/setup.sh | 46 +
bin/tests/system/pkcs11ssl/tests.sh | 71 +
bin/tests/system/pkcs11ssl/usepkcs11 | 1 +
bin/tests/system/rsabigexponent/Makefile.in | 2 +-
bin/tests/system/rsabigexponent/bigkey.c | 18 +-
bin/tests/system/rsabigexponent/prereq.sh | 3 +-
bin/tests/system/smartsign/prereq.sh | 3 +-
bin/tests/system/tkey/keycreate.c | 1 +
bin/tests/system/tkey/prereq.sh | 3 +-
config.h.in | 19 +-
configure.in | 383 ++++-
doc/arm/pkcs11.xml | 694 +++++----
lib/dns/Makefile.in | 16 +-
lib/dns/dnssec.c | 12 +-
lib/dns/ds.c | 44 +-
lib/dns/dst_api.c | 73 +-
lib/dns/dst_gost.h | 57 +
lib/dns/dst_internal.h | 28 +-
lib/dns/dst_parse.c | 36 +-
lib/dns/dst_parse.h | 6 +-
lib/dns/dst_pkcs11.h | 43 +
lib/dns/dst_result.c | 3 +-
lib/dns/gssapi_link.c | 1 +
lib/dns/hmac_link.c | 47 +-
lib/dns/include/dst/dst.h | 10 +
lib/dns/include/dst/result.h | 3 +-
lib/dns/openssldh_link.c | 7 +
lib/dns/openssldsa_link.c | 36 +-
lib/dns/opensslecdsa_link.c | 73 +-
lib/dns/opensslgost_link.c | 180 ++-
lib/dns/opensslrsa_link.c | 35 +-
lib/dns/pkcs11.c | 50 +
lib/dns/pkcs11dh_link.c | 1140 +++++++++++++++
lib/dns/pkcs11dsa_link.c | 1130 +++++++++++++++
lib/dns/pkcs11ecdsa_link.c | 1189 ++++++++++++++++
lib/dns/pkcs11gost_link.c | 949 +++++++++++++
lib/dns/pkcs11rsa_link.c | 1583 +++++++++++++++++++++
lib/dns/rdata/generic/dlv_32769.c | 9 +
lib/dns/rdata/generic/ds_43.c | 10 +
lib/dns/tests/Makefile.in | 14 +-
lib/dns/tests/gost_test.c | 232 +++
lib/dns/tkey.c | 10 +-
lib/dns/tsig.c | 14 +-
lib/export/dns/Makefile.in | 4 +-
lib/export/isc/Makefile.in | 5 +-
lib/export/isc/unix/Makefile.in | 4 +
lib/isc/Makefile.in | 14 +-
lib/isc/entropy.c | 8 +
lib/isc/hmacmd5.c | 166 +++
lib/isc/hmacsha.c | 375 +++++
lib/isc/include/Makefile.in | 2 +-
lib/isc/include/isc/hmacmd5.h | 5 +
lib/isc/include/isc/hmacsha.h | 9 +
lib/isc/include/isc/md5.h | 5 +
lib/isc/include/isc/resultclass.h | 2 +-
lib/isc/include/isc/sha1.h | 5 +
lib/isc/include/isc/sha2.h | 6 +
lib/isc/include/pk11/Makefile.in | 38 +
lib/isc/include/pk11/constants.h | 107 ++
lib/isc/include/pk11/internal.h | 46 +
lib/isc/include/pk11/pk11.h | 295 ++++
lib/isc/include/pk11/result.h | 56 +
lib/isc/include/pkcs11/Makefile.in | 40 +
lib/isc/include/pkcs11/pkcs11.h | 299 ++++
lib/isc/include/pkcs11/pkcs11f.h | 912 ++++++++++++
lib/isc/include/pkcs11/pkcs11t.h | 1977 ++++++++++++++++++++++++++
lib/isc/md5.c | 50 +
lib/isc/pk11.c | 1327 +++++++++++++++++
lib/isc/pk11_result.c | 85 ++
lib/isc/sha1.c | 50 +-
lib/isc/sha2.c | 279 ++++
lib/isc/unix/Makefile.in | 4 +-
lib/isc/unix/include/Makefile.in | 2 +-
lib/isc/unix/include/pkcs11/Makefile.in | 33 +
lib/isc/unix/include/pkcs11/cryptoki.h | 66 +
lib/isc/unix/pk11_api.c | 673 +++++++++
153 files changed, 20271 insertions(+), 1183 deletions(-)
create mode 100644 bin/pkcs11/pkcs11-tokens.8
create mode 100644 bin/pkcs11/pkcs11-tokens.c
create mode 100644 bin/pkcs11/pkcs11-tokens.docbook
create mode 100644 bin/pkcs11/pkcs11-tokens.html
create mode 100644 bin/tests/pkcs11/Makefile.in
create mode 100644 bin/tests/pkcs11/benchmarks/Makefile.in
create mode 100644 bin/tests/pkcs11/benchmarks/create.c
create mode 100644 bin/tests/pkcs11/benchmarks/find.c
create mode 100644 bin/tests/pkcs11/benchmarks/genrsa.c
create mode 100644 bin/tests/pkcs11/benchmarks/login.c
create mode 100644 bin/tests/pkcs11/benchmarks/privrsa.c
create mode 100644 bin/tests/pkcs11/benchmarks/pubrsa.c
create mode 100644 bin/tests/pkcs11/benchmarks/random.c
create mode 100644 bin/tests/pkcs11/benchmarks/session.c
create mode 100644 bin/tests/pkcs11/benchmarks/sha1.c
create mode 100644 bin/tests/pkcs11/benchmarks/sign.c
create mode 100644 bin/tests/pkcs11/benchmarks/verify.c
create mode 100644 bin/tests/pkcs11/pkcs11-hmacmd5.c
create mode 100644 bin/tests/pkcs11/pkcs11-md5sum.c
create mode 100644 bin/tests/system/pkcs11ssl/clean.sh
create mode 100644 bin/tests/system/pkcs11ssl/ns1/example.db.in
create mode 100644 bin/tests/system/pkcs11ssl/ns1/named.conf
create mode 100644 bin/tests/system/pkcs11ssl/prereq.sh
create mode 100644 bin/tests/system/pkcs11ssl/setup.sh
create mode 100644 bin/tests/system/pkcs11ssl/tests.sh
create mode 100644 bin/tests/system/pkcs11ssl/usepkcs11
create mode 100644 lib/dns/dst_gost.h
create mode 100644 lib/dns/dst_pkcs11.h
create mode 100644 lib/dns/pkcs11.c
create mode 100644 lib/dns/pkcs11dh_link.c
create mode 100644 lib/dns/pkcs11dsa_link.c
create mode 100644 lib/dns/pkcs11ecdsa_link.c
create mode 100644 lib/dns/pkcs11gost_link.c
create mode 100644 lib/dns/pkcs11rsa_link.c
create mode 100644 lib/dns/tests/gost_test.c
create mode 100644 lib/isc/include/pk11/Makefile.in
create mode 100644 lib/isc/include/pk11/constants.h
create mode 100644 lib/isc/include/pk11/internal.h
create mode 100644 lib/isc/include/pk11/pk11.h
create mode 100644 lib/isc/include/pk11/result.h
create mode 100644 lib/isc/include/pkcs11/Makefile.in
create mode 100644 lib/isc/include/pkcs11/pkcs11.h
create mode 100644 lib/isc/include/pkcs11/pkcs11f.h
create mode 100644 lib/isc/include/pkcs11/pkcs11t.h
create mode 100644 lib/isc/pk11.c
create mode 100644 lib/isc/pk11_result.c
create mode 100644 lib/isc/unix/include/pkcs11/Makefile.in
create mode 100644 lib/isc/unix/include/pkcs11/cryptoki.h
create mode 100644 lib/isc/unix/pk11_api.c
diff --git a/acconfig.h b/acconfig.h
index 3d412d9..c8e832a 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -132,14 +132,11 @@ int sigwait(const unsigned int *set, int *sig);
/** 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 --git a/bin/check/Makefile.in b/bin/check/Makefile.in
index c191605..d585480 100644
--- a/bin/check/Makefile.in
+++ b/bin/check/Makefile.in
@@ -75,7 +75,8 @@ named-checkconf@EXEEXT@: named-checkconf.@O@ check-tool.@O@ ${ISCDEPLIBS} \
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 --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
index 3864e06..43dd061 100644
--- a/bin/dig/Makefile.in
+++ b/bin/dig/Makefile.in
@@ -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.@A@
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 --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index e2bb110..5c03d95 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -105,6 +105,10 @@
#include <dig/dig.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#if ! defined(NS_INADDRSZ)
#define NS_INADDRSZ 4
#endif
@@ -1347,6 +1351,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;
@@ -1403,8 +1412,6 @@ setup_libs(void) {
result = isc_mutex_init(&lookup_lock);
check_result(result, "isc_mutex_init");
-
- dns_result_register();
}
/*%
diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in
index ecb0fae..64e1846 100644
--- a/bin/dnssec/Makefile.in
+++ b/bin/dnssec/Makefile.in
@@ -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 --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c
index bfedae8..df616ac 100644
--- a/bin/dnssec/dnssec-dsfromkey.c
+++ b/bin/dnssec/dnssec-dsfromkey.c
@@ -49,6 +49,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
#ifndef PATH_MAX
@@ -370,6 +374,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;
@@ -448,7 +455,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 --git a/bin/dnssec/dnssec-importkey.c b/bin/dnssec/dnssec-importkey.c
index 00f9200..73166c4 100644
--- a/bin/dnssec/dnssec-importkey.c
+++ b/bin/dnssec/dnssec-importkey.c
@@ -47,6 +47,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
#ifndef PATH_MAX
@@ -61,7 +65,9 @@ static dns_fixedname_t fixed;
static dns_name_t *name = NULL;
static isc_mem_t *mctx = NULL;
static isc_boolean_t setpub = ISC_FALSE, setdel = ISC_FALSE;
+static isc_boolean_t setttl = ISC_FALSE;
static isc_stdtime_t pub = 0, del = 0;
+static dns_ttl_t ttl = 0;
static isc_result_t
initname(char *setname) {
@@ -190,9 +196,10 @@ static void
emit(const char *dir, dns_rdata_t *rdata) {
isc_result_t result;
char keystr[DST_KEY_FORMATSIZE];
- char newname[1024];
+ char pubname[1024];
+ char priname[1024];
isc_buffer_t buf;
- dst_key_t *key = NULL;
+ dst_key_t *key = NULL, *tmp = NULL;
isc_buffer_init(&buf, rdata->data, rdata->length);
isc_buffer_add(&buf, rdata->length);
@@ -201,18 +208,36 @@ emit(const char *dir, dns_rdata_t *rdata) {
fatal("dst_key_fromdns: %s", isc_result_totext(result));
}
- dst_key_setexternal(key, ISC_TRUE);
- if (setpub)
- dst_key_settime(key, DST_TIME_PUBLISH, pub);
- if (setdel)
- dst_key_settime(key, DST_TIME_DELETE, del);
-
- isc_buffer_init(&buf, newname, sizeof(newname));
+ isc_buffer_init(&buf, pubname, sizeof(pubname));
result = dst_key_buildfilename(key, DST_TYPE_PUBLIC, dir, &buf);
if (result != ISC_R_SUCCESS) {
fatal("Failed to build public key filename: %s",
isc_result_totext(result));
}
+ isc_buffer_init(&buf, priname, sizeof(priname));
+ result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("Failed to build private key filename: %s",
+ isc_result_totext(result));
+ }
+
+ result = dst_key_fromfile(dst_key_name(key), dst_key_id(key),
+ dst_key_alg(key),
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ dir, mctx, &tmp);
+ if (result == ISC_R_SUCCESS) {
+ if (dst_key_isprivate(tmp) && !dst_key_isexternal(tmp))
+ fatal("Private key already exists in %s", priname);
+ dst_key_free(&tmp);
+ }
+
+ dst_key_setexternal(key, ISC_TRUE);
+ if (setpub)
+ dst_key_settime(key, DST_TIME_PUBLISH, pub);
+ if (setdel)
+ dst_key_settime(key, DST_TIME_DELETE, del);
+ if (setttl)
+ dst_key_setttl(key, ttl);
result = dst_key_tofile(key, DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
dir);
@@ -221,8 +246,7 @@ emit(const char *dir, dns_rdata_t *rdata) {
fatal("Failed to write key %s: %s", keystr,
isc_result_totext(result));
}
-
- printf("%s\n", newname);
+ printf("%s\n", pubname);
isc_buffer_clear(&buf);
result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, dir, &buf);
@@ -230,7 +254,7 @@ emit(const char *dir, dns_rdata_t *rdata) {
fatal("Failed to build private key filename: %s",
isc_result_totext(result));
}
- printf("%s\n", newname);
+ printf("%s\n", priname);
dst_key_free(&key);
}
@@ -240,13 +264,21 @@ usage(void) ISC_PLATFORM_NORETURN_POST;
static void
usage(void) {
fprintf(stderr, "Usage:\n");
- fprintf(stderr, " %s options [-K dir] file\n\n", program);
+ fprintf(stderr, " %s options [-K dir] keyfile\n\n", program);
+ fprintf(stderr, " %s options -f file [keyname]\n\n", program);
fprintf(stderr, "Version: %s\n", VERSION);
fprintf(stderr, "Options:\n");
- fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -f file: read key from zone file\n");
fprintf(stderr, " -K <directory>: directory in which to store "
- "the keyset files\n");
- fprintf(stderr, " -f file: read keyset from zone file\n");
+ "the key files\n");
+ fprintf(stderr, " -L ttl: set default key TTL\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -h: print usage and exit\n");
+ fprintf(stderr, "Timing options:\n");
+ fprintf(stderr, " -P date/[+-]offset/none: set/unset key "
+ "publication date\n");
+ fprintf(stderr, " -D date/[+-]offset/none: set/unset key "
+ "deletion date\n");
exit (-1);
}
@@ -274,15 +306,19 @@ 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;
- while ((ch = isc_commandline_parse(argc, argv, "D:f:hK:P:v:")) != -1) {
+#define CMDLINE_FLAGS "D:f:hK:L:P:v:"
+ while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
- case 'D':
- if (setdel)
- fatal("-D specified more than once");
+ case 'D':
+ if (setdel)
+ fatal("-D specified more than once");
setdel = ISC_TRUE;
del = strtotime(isc_commandline_argument, now, now);
@@ -292,9 +328,16 @@ main(int argc, char **argv) {
if (strlen(dir) == 0U)
fatal("directory must be non-empty string");
break;
- case 'P':
- if (setpub)
- fatal("-P specified more than once");
+ case 'L':
+ if (strcmp(isc_commandline_argument, "none") == 0)
+ ttl = 0;
+ else
+ ttl = strtottl(isc_commandline_argument);
+ setttl = ISC_TRUE;
+ break;
+ case 'P':
+ if (setpub)
+ fatal("-P specified more than once");
setpub = ISC_TRUE;
pub = strtotime(isc_commandline_argument, now, now);
@@ -346,8 +389,8 @@ main(int argc, char **argv) {
dns_rdataset_init(&rdataset);
if (filename != NULL) {
- if (argc < isc_commandline_index + 1 && filename != NULL) {
- /* using zone name as the zone file name */
+ if (argc < isc_commandline_index + 1) {
+ /* using filename as zone name */
namestr = filename;
} else
namestr = argv[isc_commandline_index];
diff --git a/bin/dnssec/dnssec-importkey.docbook b/bin/dnssec/dnssec-importkey.docbook
index b8d160c..853db30 100644
--- a/bin/dnssec/dnssec-importkey.docbook
+++ b/bin/dnssec/dnssec-importkey.docbook
@@ -44,22 +44,45 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>dnssec-importkey</command>
- <arg><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
<arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
<arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
<arg><option>-h</option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
- <arg><option>keyname</option></arg>
+ <arg choice="req"><option>keyfile</option></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>dnssec-importkey</command>
+ <arg choice="req"><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-K <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-L <replaceable class="parameter">ttl</replaceable></option></arg>
+ <arg><option>-P <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-D <replaceable class="parameter">date/offset</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>dnsname</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para><command>dnssec-importkey</command>
- read a DNSKEY record and generated a .key/.private key pair.
- Publication (<option>-P</option>) and deletions (<option>-D</option>)
- times can be set for the key.
+ reads a public DNSKEY record and generates a pair of
+ .key/.private files. The DNSKEY record may be read from an
+ existing .key file, in which case a corresponding .private file
+ will be generated, or it may be read from any other file or
+ from the standard input, in which case both .key and .private
+ files will be generated.
+ </para>
+ <para>
+ The newly-created .private file does <emphasis>not</command>
+ contain private key data, and cannot be used for signing.
+ However, having a .private file makes it possible to set
+ publication (<option>-P</option>) and deletion
+ (<option>-D</option>) times for the key, which means the
+ public key can be added to and removed from the DNSKEY RRset
+ on schedule even if the true private key is stored offline.
</para>
</refsect1>
@@ -70,9 +93,16 @@
<varlistentry>
<term>-f <replaceable class="parameter">filename</replaceable></term>
<listitem>
- <para>
- Filename to read the key from.
- </para>
+ <para>
+ Zone file mode: instead of a public keyfile name, the argument
+ is the DNS domain name of a zone master file, which can be read
+ from <option>file</option>. If the domain name is the same as
+ <option>file</option>, then it may be omitted.
+ </para>
+ <para>
+ If <option>file</option> is set to <literal>"-"</literal>, then
+ the zone data is read from the standard input.
+ </para>
</listitem>
</varlistentry>
@@ -93,7 +123,7 @@
into a DNSKEY RR. If the key is imported into a zone,
this is the TTL that will be used for it, unless there was
already a DNSKEY RRset in place, in which case the existing TTL
- would take precedence. importkey the default TTL to
+ would take precedence. Setting the default TTL to
<literal>0</literal> or <literal>none</literal> removes it.
</para>
</listitem>
@@ -160,6 +190,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 --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c
index 3ad00d7..cc212e1 100644
--- a/bin/dnssec/dnssec-keyfromlabel.c
+++ b/bin/dnssec/dnssec-keyfromlabel.c
@@ -43,6 +43,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
#define MAX_RSA 4096 /* should be long enough... */
@@ -76,10 +80,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 "
@@ -116,7 +125,7 @@ main(int argc, char **argv) {
char *nametype = NULL, *type = NULL;
const char *directory = NULL;
#ifdef USE_PKCS11
- const char *engine = "pkcs11";
+ const char *engine = PKCS11_ENGINE;
#else
const char *engine = NULL;
#endif
@@ -161,6 +170,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;
@@ -334,16 +346,15 @@ main(int argc, char **argv) {
if (argc > isc_commandline_index + 1)
fatal("extraneous arguments");
- if (strchr(label, ':') == NULL &&
- engine != NULL && strlen(engine) != 0U) {
+ if (strchr(label, ':') == NULL) {
char *l;
int len;
- len = strlen(label) + strlen(engine) + 2;
+ len = strlen(label) + 8;
l = isc_mem_allocate(mctx, len);
if (l == NULL)
fatal("cannot allocate memory");
- snprintf(l, len, "%s:%s", engine, label);
+ snprintf(l, len, "pkcs11:%s", label);
isc_mem_free(mctx, label);
label = l;
}
@@ -460,7 +471,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) {
@@ -468,7 +479,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 --git a/bin/dnssec/dnssec-keyfromlabel.docbook b/bin/dnssec/dnssec-keyfromlabel.docbook
index 0dd3c0e..c48a100 100644
--- a/bin/dnssec/dnssec-keyfromlabel.docbook
+++ b/bin/dnssec/dnssec-keyfromlabel.docbook
@@ -133,8 +133,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>
@@ -143,9 +150,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>
@@ -429,7 +459,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 --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c
index 7061829..97b96ee 100644
--- a/bin/dnssec/dnssec-keygen.c
+++ b/bin/dnssec/dnssec-keygen.c
@@ -58,6 +58,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
#define MAX_RSA 4096 /* should be long enough... */
@@ -119,10 +123,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 "
@@ -134,7 +143,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");
@@ -223,7 +231,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
@@ -250,6 +258,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 --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook
index bc50c02..4c693eb 100644
--- a/bin/dnssec/dnssec-keygen.docbook
+++ b/bin/dnssec/dnssec-keygen.docbook
@@ -224,10 +224,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 --git a/bin/dnssec/dnssec-revoke.c b/bin/dnssec/dnssec-revoke.c
index 7b11581..7b5aaee 100644
--- a/bin/dnssec/dnssec-revoke.c
+++ b/bin/dnssec/dnssec-revoke.c
@@ -38,6 +38,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
const char *program = "dnssec-revoke";
@@ -53,7 +57,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
@@ -76,7 +83,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
@@ -100,6 +107,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 --git a/bin/dnssec/dnssec-revoke.docbook b/bin/dnssec/dnssec-revoke.docbook
index 4062f5e..0c1dd4e 100644
--- a/bin/dnssec/dnssec-revoke.docbook
+++ b/bin/dnssec/dnssec-revoke.docbook
@@ -109,8 +109,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 --git a/bin/dnssec/dnssec-settime.c b/bin/dnssec/dnssec-settime.c
index 108d803..c71cac7 100644
--- a/bin/dnssec/dnssec-settime.c
+++ b/bin/dnssec/dnssec-settime.c
@@ -41,6 +41,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
const char *program = "dnssec-settime";
@@ -57,7 +61,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
@@ -119,7 +126,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
@@ -165,6 +172,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 --git a/bin/dnssec/dnssec-settime.docbook b/bin/dnssec/dnssec-settime.docbook
index bc6870b..3540bf2 100644
--- a/bin/dnssec/dnssec-settime.docbook
+++ b/bin/dnssec/dnssec-settime.docbook
@@ -153,8 +153,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 --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c
index 83456a7..128c753 100644
--- a/bin/dnssec/dnssec-signzone.c
+++ b/bin/dnssec/dnssec-signzone.c
@@ -86,6 +86,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
#ifndef PATH_MAX
@@ -2938,7 +2942,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
@@ -3033,7 +3040,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
@@ -3085,6 +3092,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 --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook
index e427fc1..c46f43c 100644
--- a/bin/dnssec/dnssec-signzone.docbook
+++ b/bin/dnssec/dnssec-signzone.docbook
@@ -176,10 +176,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 --git a/bin/dnssec/dnssec-verify.c b/bin/dnssec/dnssec-verify.c
index 682896c..817e380 100644
--- a/bin/dnssec/dnssec-verify.c
+++ b/bin/dnssec/dnssec-verify.c
@@ -69,6 +69,10 @@
#include <dst/dst.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
#include "dnssectool.h"
const char *program = "dnssec-verify";
@@ -137,7 +141,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
@@ -156,7 +163,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 --git a/bin/dnssec/dnssec-verify.docbook b/bin/dnssec/dnssec-verify.docbook
index 0835df1..875f3ed 100644
--- a/bin/dnssec/dnssec-verify.docbook
+++ b/bin/dnssec/dnssec-verify.docbook
@@ -78,6 +78,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 --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c
index 5f5f7d8..c68ae69 100644
--- a/bin/dnssec/dnssectool.c
+++ b/bin/dnssec/dnssectool.c
@@ -319,7 +319,7 @@ strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
isc_result_t result;
const char *orig = str;
char *endp;
- int n;
+ size_t n;
if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
return ((isc_stdtime_t) 0);
diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in
index 68c42a8..cd65777 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@ @USE_OPENSSL@
+CDEFINES = @CONTRIB_DLZ@ @USE_PKCS11@ @PKCS11_ENGINE@ @CRYPTO@
CWARNINGS =
diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h
index cbc14d8..aad462d 100644
--- a/bin/named/include/named/globals.h
+++ b/bin/named/include/named/globals.h
@@ -146,8 +146,8 @@ EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR
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 --git a/bin/named/main.c b/bin/named/main.c
index 15905ef..a00687f 100644
--- a/bin/named/main.c
+++ b/bin/named/main.c
@@ -51,6 +51,9 @@
#include <dns/view.h>
#include <dst/result.h>
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
#include <dlz/dlz_dlopen_driver.h>
@@ -1081,6 +1084,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 --git a/bin/named/named.docbook b/bin/named/named.docbook
index 1f08e19..8f46aac 100644
--- a/bin/named/named.docbook
+++ b/bin/named/named.docbook
@@ -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 --git a/bin/named/server.c b/bin/named/server.c
index 56df6bf..227c646 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -6215,6 +6215,11 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
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");
@@ -6231,10 +6236,6 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
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 --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in
index 09e6c14..e258ffc 100644
--- a/bin/nsupdate/Makefile.in
+++ b/bin/nsupdate/Makefile.in
@@ -46,9 +46,11 @@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
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 --git a/bin/pkcs11/Makefile.in b/bin/pkcs11/Makefile.in
index 407d977..15d3fb5 100644
--- a/bin/pkcs11/Makefile.in
+++ b/bin/pkcs11/Makefile.in
@@ -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@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+
+DEPLIBS = ${ISCDEPLIBS}
# if FORCE_STATIC_PROVIDER: LIBS = ${PROVIDER}
-LIBS = -ldl
+LIBS = ${ISCLIBS} @LIBS@
-SUBDIRS =
+SUBDIRS = benchmarks
-TARGETS = pkcs11-keygen@EXEEXT@ pkcs11-list@EXEEXT@ \
- pkcs11-destroy@EXEEXT@
-SRCS = pkcs11-keygen.c pkcs11-list.c pkcs11-destroy.c
+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-keygen.8 pkcs11-list.8 pkcs11-destroy.8
-HTMLPAGES = pkcs11-keygen.html pkcs11-list.html pkcs11-destroy.html
+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 --git a/bin/pkcs11/pkcs11-destroy.8 b/bin/pkcs11/pkcs11-destroy.8
index aff35b3..25323ca 100644
--- a/bin/pkcs11/pkcs11-destroy.8
+++ b/bin/pkcs11/pkcs11-destroy.8
@@ -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, identified by their
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 PIN is provided on the command line,
\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 --git a/bin/pkcs11/pkcs11-destroy.c b/bin/pkcs11/pkcs11-destroy.c
index 0f46a89..2905395 100644
--- a/bin/pkcs11/pkcs11-destroy.c
+++ b/bin/pkcs11/pkcs11-destroy.c
@@ -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 --git a/bin/pkcs11/pkcs11-destroy.docbook b/bin/pkcs11/pkcs11-destroy.docbook
index b4c2048..45c0208 100644
--- a/bin/pkcs11/pkcs11-destroy.docbook
+++ b/bin/pkcs11/pkcs11-destroy.docbook
@@ -37,6 +37,7 @@
<docinfo>
<copyright>
<year>2009</year>
+ <year>2014</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
@@ -51,6 +52,7 @@
<arg choice="plain">-l <replaceable class="parameter">label</replaceable></arg>
</group>
<arg><option>-p <replaceable class="parameter">PIN</replaceable></option></arg>
+ <arg><option>-w <replaceable class="parameter">seconds</replaceable></option></arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -62,9 +64,9 @@
<option>label</option>.
</para>
<para>
- 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.
</para>
</refsect1>
@@ -119,6 +121,17 @@
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>-w <replaceable class="parameter">seconds</replaceable></term>
+ <listitem>
+ <para>
+ Specify how long to pause before carrying out key destruction.
+ The default is five seconds. If set to <literal>0</literal>,
+ destruction will be immediate.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/bin/pkcs11/pkcs11-destroy.html b/bin/pkcs11/pkcs11-destroy.html
index afc6e36..899b3e9 100644
--- a/bin/pkcs11/pkcs11-destroy.html
+++ b/bin/pkcs11/pkcs11-destroy.html
@@ -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 --git a/bin/pkcs11/pkcs11-keygen.8 b/bin/pkcs11/pkcs11-keygen.8
index 568e862..53de464 100644
--- a/bin/pkcs11/pkcs11-keygen.8
+++ b/bin/pkcs11/pkcs11-keygen.8
@@ -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 --git a/bin/pkcs11/pkcs11-keygen.c b/bin/pkcs11/pkcs11-keygen.c
index 1ffb343..cc91776 100644
--- a/bin/pkcs11/pkcs11-keygen.c
+++ b/bin/pkcs11/pkcs11-keygen.c
@@ -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;
+ 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;
- while ((c = getopt(argc, argv, ":Pm:s:b:ei:l:p:")) != -1) {
+#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 --git a/bin/pkcs11/pkcs11-keygen.docbook b/bin/pkcs11/pkcs11-keygen.docbook
index 7c4ba08..d62ba2f 100644
--- a/bin/pkcs11/pkcs11-keygen.docbook
+++ b/bin/pkcs11/pkcs11-keygen.docbook
@@ -18,25 +18,26 @@
-->
<!-- $Id: pkcs11-keygen.docbook,v 1.3 2009/10/05 12:23:11 fdupont Exp $ -->
-<refentry id="man.pkcs11-keygen">
+<refentry id="man.pkcs11-ecgen">
<refentryinfo>
- <date>Sep 18, 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>
<copyright>
<year>2009</year>
+ <year>2014</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
@@ -44,14 +45,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 +63,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 +72,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 +185,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 +203,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 --git a/bin/pkcs11/pkcs11-keygen.html b/bin/pkcs11/pkcs11-keygen.html
index 41378fc..c7fdecf 100644
--- a/bin/pkcs11/pkcs11-keygen.html
+++ b/bin/pkcs11/pkcs11-keygen.html
@@ -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> — generate RSA keys on a PKCS#11 device</p>
+<p><span class="application">pkcs11-keygen</span> — 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 --git a/bin/pkcs11/pkcs11-list.c b/bin/pkcs11/pkcs11-list.c
index 336bf41..bc6ad28 100644
--- a/bin/pkcs11/pkcs11-list.c
+++ b/bin/pkcs11/pkcs11-list.c
@@ -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 --git a/bin/pkcs11/pkcs11-tokens.8 b/bin/pkcs11/pkcs11-tokens.8
new file mode 100644
index 0000000..7c2be83
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.8
@@ -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 --git a/bin/pkcs11/pkcs11-tokens.c b/bin/pkcs11/pkcs11-tokens.c
new file mode 100644
index 0000000..ff4e030
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.c
@@ -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 --git a/bin/pkcs11/pkcs11-tokens.docbook b/bin/pkcs11/pkcs11-tokens.docbook
new file mode 100644
index 0000000..44dc7cd
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.docbook
@@ -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 "—">]>
+<!--
+ - 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 --git a/bin/pkcs11/pkcs11-tokens.html b/bin/pkcs11/pkcs11-tokens.html
new file mode 100644
index 0000000..45d7243
--- /dev/null
+++ b/bin/pkcs11/pkcs11-tokens.html
@@ -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> — 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 --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in
index f6100df..bc0657a 100644
--- a/bin/rndc/Makefile.in
+++ b/bin/rndc/Makefile.in
@@ -45,7 +45,8 @@ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
LIBS = ${ISCLIBS} @LIBS@
NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@
-RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS}
+RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} \
+ ${DNSDEPLIBS} ${ISCDEPLIBS}
CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in
index bc040a3..2020bf4 100644
--- a/bin/tests/Makefile.in
+++ b/bin/tests/Makefile.in
@@ -42,7 +42,7 @@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
LIBS = @LIBS@
SUBDIRS = atomic db dst master mem hashes names net rbt resolver \
- sockaddr tasks timers system
+ sockaddr tasks timers system @PKCS11_TOOLS@
# Test programs that are built by default:
# cfg_test is needed for regenerating doc/misc/options
@@ -173,139 +173,139 @@ backtrace_test@EXEEXT@: backtrace_test_nosymtbl@EXEEXT@
nsecify@EXEEXT@: nsecify.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsecify.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
byaddr_test@EXEEXT@: byaddr_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byaddr_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
byname_test@EXEEXT@: byname_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byname_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
lex_test@EXEEXT@: lex_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lex_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
lfsr_test@EXEEXT@: lfsr_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lfsr_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
log_test@EXEEXT@: log_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ log_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
name_test@EXEEXT@: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ name_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
hash_test@EXEEXT@: hash_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ hash_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
entropy_test@EXEEXT@: entropy_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
entropy2_test@EXEEXT@: entropy2_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy2_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
sock_test@EXEEXT@: sock_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sock_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
sym_test@EXEEXT@: sym_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sym_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
task_test@EXEEXT@: task_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ task_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
shutdown_test@EXEEXT@: shutdown_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ shutdown_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
timer_test@EXEEXT@: timer_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ timer_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
ratelimiter_test@EXEEXT@: ratelimiter_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ratelimiter_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rdata_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
wire_test@EXEEXT@: wire_test.@O@ printmsg.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ wire_test.@O@ printmsg.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
master_test@EXEEXT@: master_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ master_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ db_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
compress_test@EXEEXT@: compress_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ compress_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
mempool_test@EXEEXT@: mempool_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ mempool_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
serial_test@EXEEXT@: serial_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ serial_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
zone_test@EXEEXT@: zone_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zone_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
fsaccess_test@EXEEXT@: fsaccess_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ fsaccess_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
inter_test@EXEEXT@: inter_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ inter_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
keyboard_test@EXEEXT@: keyboard_test.@O@ ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ keyboard_test.@O@ \
${ISCLIBS} ${LIBS}
-
+
lwresconf_test@EXEEXT@: lwresconf_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwresconf_test.@O@ \
${LWRESLIBS} ${ISCLIBS} ${LIBS}
-
+
lwres_test@EXEEXT@: lwres_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwres_test.@O@ \
- ${LWRESLIBS} ${ISCLIBS} ${LIBS}
-
-gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS}
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+ gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxbn_test.@O@ \
${LWRESLIBS} ${ISCLIBS} ${LIBS}
-
-gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS}
+
+ gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxba_test.@O@ \
${LWRESLIBS} ${ISCLIBS} ${LIBS}
-
+
sig0_test@EXEEXT@: sig0_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sig0_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
-
+
cfg_test@EXEEXT@: cfg_test.@O@ ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
${LIBTOOL_MODE_LINK} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ cfg_test.@O@ \
${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS}
diff --git a/bin/tests/dst/dst_test.c b/bin/tests/dst/dst_test.c
index bf305d8..240dc6f 100644
--- a/bin/tests/dst/dst_test.c
+++ b/bin/tests/dst/dst_test.c
@@ -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 --git a/bin/tests/dst/t_dst.c b/bin/tests/dst/t_dst.c
index e431c95..59c7835 100644
--- a/bin/tests/dst/t_dst.c
+++ b/bin/tests/dst/t_dst.c
@@ -108,7 +108,8 @@ use(dst_key_t *key, isc_mem_t *mctx, isc_result_t exp_result, int *nfails) {
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),
@@ -137,7 +138,8 @@ use(dst_key_t *key, isc_mem_t *mctx, isc_result_t exp_result, int *nfails) {
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));
@@ -783,7 +785,9 @@ t2_sigchk(char *datapath, char *sigpath, char *keyname,
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));
@@ -849,7 +853,9 @@ t2_sigchk(char *datapath, char *sigpath, char *keyname,
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 --git a/bin/tests/pkcs11/Makefile.in b/bin/tests/pkcs11/Makefile.in
new file mode 100644
index 0000000..0a6281f
--- /dev/null
+++ b/bin/tests/pkcs11/Makefile.in
@@ -0,0 +1,49 @@
+# Copyright (C) 2009, 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.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+PROVIDER = @PKCS11_PROVIDER@
+
+CINCLUDES = ${ISC_INCLUDES}
+
+CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\"
+
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS = benchmarks
+
+TARGETS = pkcs11-md5sum@EXEEXT@ pkcs11-hmacmd5@EXEEXT@
+SRCS = pkcs11-md5sum.c pkcs11-hmacmd5.c
+
+@BIND9_MAKE_RULES@
+
+pkcs11-md5sum@EXEEXT@: @srcdir@/pkcs11-md5sum.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/pkcs11-md5sum.c ${LIBS}
+
+pkcs11-hmacmd5@EXEEXT@: @srcdir@/pkcs11-hmacmd5.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \
+ -o $@ @srcdir@/pkcs11-hmacmd5.c ${LIBS}
+
+test:
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/pkcs11/benchmarks/Makefile.in b/bin/tests/pkcs11/benchmarks/Makefile.in
new file mode 100644
index 0000000..cd0347c
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/Makefile.in
@@ -0,0 +1,79 @@
+# 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$
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+PROVIDER = @PKCS11_PROVIDER@
+
+CINCLUDES = ${ISC_INCLUDES}
+
+CDEFINES = -DPK11_LIB_LOCATION=\"${PROVIDER}\"
+
+ISCLIBS = ../../../../lib/isc/libisc.@A@
+
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = session@EXEEXT@ login@EXEEXT@ random@EXEEXT@ \
+ sha1@EXEEXT@ create@EXEEXT@ find@EXEEXT@ \
+ pubrsa@EXEEXT@ privrsa@EXEEXT@ genrsa@EXEEXT@ \
+ sign@EXEEXT@ verify@EXEEXT@
+
+SRCS = session.c login.c random.c sha1.c create.c find.c \
+ pubrsa.c privrsa.c genrsa.c sign.c verify.c
+
+@BIND9_MAKE_RULES@
+
+session@EXEEXT@: @srcdir@/session.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/session.c ${LIBS}
+
+login@EXEEXT@: @srcdir@/login.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/login.c ${LIBS}
+
+random@EXEEXT@: @srcdir@/random.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/random.c ${LIBS}
+
+sha1@EXEEXT@: @srcdir@/sha1.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/sha1.c ${LIBS}
+
+create@EXEEXT@: @srcdir@/create.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/create.c ${LIBS}
+
+find@EXEEXT@: @srcdir@/find.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/find.c ${LIBS}
+
+pubrsa@EXEEXT@: @srcdir@/pubrsa.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/pubrsa.c ${LIBS}
+
+privrsa@EXEEXT@: @srcdir@/privrsa.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/privrsa.c ${LIBS}
+
+genrsa@EXEEXT@: @srcdir@/genrsa.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/genrsa.c ${LIBS}
+
+sign@EXEEXT@: @srcdir@/sign.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/sign.c ${LIBS}
+
+verify@EXEEXT@: @srcdir@/verify.c
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o $@ @srcdir@/verify.c ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/pkcs11/benchmarks/create.c b/bin/tests/pkcs11/benchmarks/create.c
new file mode 100644
index 0000000..d0d8c77
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/create.c
@@ -0,0 +1,260 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE buf[1024];
+char label[16];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE *hKey;
+ CK_OBJECT_CLASS kClass = CKO_DATA;
+ CK_ULONG len = sizeof(buf);
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
+ { CKA_VALUE, buf, (CK_ULONG) sizeof(buf) }
+ };
+ pk11_context_t pctx;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tcreate [-m module] [-s slot] [-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ hKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hKey[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, OP_ANY, ISC_TRUE, ISC_TRUE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ /* Randomize the buffer */
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_objects;
+ }
+
+ if (ontoken)
+ kTemplate[1].pValue = &truevalue;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; i < count; i++) {
+ (void) snprintf(label, sizeof(label), "obj%u", i);
+ kTemplate[3].ulValueLen = strlen(label);
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 5, &hKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_CreateObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_objects;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u created objects in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g created objects/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ for (i = 0; i < count; i++) {
+ /* Destroy objects */
+ if (hKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, hKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(hKey);
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/find.c b/bin/tests/pkcs11/benchmarks/find.c
new file mode 100644
index 0000000..e22b17e
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/find.c
@@ -0,0 +1,227 @@
+/*
+ * 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) 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.
+ */
+
+/* find [-m module] [-s $slot] [-p pin] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE label[] = "foo??bar!!";
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ATTRIBUTE sTemplate[] =
+ {
+ { CKA_LABEL, label, (CK_ULONG) sizeof(label) },
+ };
+ CK_OBJECT_HANDLE sKey = CK_INVALID_HANDLE;
+ CK_ULONG found = 0;
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tfind [-m module] [-s slot] [-p pin] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; !error && (i < count); i++) {
+ rv = pkcs_C_FindObjectsInit(hSession, sTemplate, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjectsInit[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+
+ rv = pkcs_C_FindObjects(hSession, &sKey, 1, &found);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjects[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ /* no break here! */
+ }
+
+ rv = pkcs_C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_FindObjectsFinal[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u object searches in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g object searches/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/genrsa.c b/bin/tests/pkcs11/benchmarks/genrsa.c
new file mode 100644
index 0000000..e9d3c2a
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/genrsa.c
@@ -0,0 +1,295 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* genrsa [-m module] [-s $slot] [-p pin] [-t] [-b bits] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
+ CK_OBJECT_HANDLE *pubKey;
+ CK_OBJECT_HANDLE *privKey;
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
+ CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ULONG bits = 1024;
+ CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
+ CK_ATTRIBUTE pubTemplate[] =
+ {
+ { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { 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, exponent, (CK_ULONG) sizeof(exponent) }
+ };
+ CK_ATTRIBUTE privTemplate[] =
+ {
+ { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tb:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'b':
+ bits = (CK_ULONG)atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tgenrsa [-m module] [-s slot] [-p pin] "
+ "[-t] [-b bits] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ pubKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (pubKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ privKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (privKey == NULL) {
+ free(pubKey);
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++) {
+ pubKey[i] = CK_INVALID_HANDLE;
+ privKey[i] = CK_INVALID_HANDLE;
+ }
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (ontoken) {
+ pubTemplate[2].pValue = &truevalue;
+ privTemplate[2].pValue = &truevalue;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_keys;
+ }
+
+ for (i = 0; i < count; i++) {
+ rv = pkcs_C_GenerateKeyPair(hSession, &mech,
+ pubTemplate, 7,
+ privTemplate, 5,
+ &pubKey[i], &privKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GenerateKeyPair[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_keys;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_keys;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u generated RSA in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g generated RSA/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_keys:
+ for (i = 0; i < count; i++) {
+ /* Destroy keys */
+ if (pubKey[i] == CK_INVALID_HANDLE)
+ goto destroy_priv;
+ rv = pkcs_C_DestroyObject(hSession, pubKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[pub%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ destroy_priv:
+ if (privKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, privKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[priv%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(pubKey);
+ free(privKey);
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/login.c b/bin/tests/pkcs11/benchmarks/login.c
new file mode 100644
index 0000000..fe597fa
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/login.c
@@ -0,0 +1,249 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* login [-m module] [-s $slot] [-p pin] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/internal.h>
+
+#if !(defined(HAVE_GETPASSPHRASE) || (defined (__SVR4) && defined (__sun)))
+#define getpassphrase(x) getpass(x)
+#endif
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE *hSession;
+ CK_UTF8CHAR *pin = NULL;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i, j;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)isc_commandline_argument;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tlogin [-m module] [-s slot] [-p pin] [-n count]\n");
+ exit(1);
+ }
+
+ /* allocate sessions */
+ hSession = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hSession == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hSession[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+
+ rv = pkcs_C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ if (rv == 0xfe)
+ fprintf(stderr,
+ "Can't load or link module \"%s\"\n",
+ pk11_get_lib_name());
+ else
+ fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
+ free(hSession);
+ exit(1);
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_program;
+ }
+
+ /* loop */
+ for (i = 0; i < count; i++) {
+ /* Open sessions */
+ rv = pkcs_C_OpenSession(slot, CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_OpenSession[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+
+ /* Logon */
+ rv = pkcs_C_Login(hSession[i], CKU_USER,
+ pin, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_Login[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+
+ /* Logoff */
+ rv = pkcs_C_Logout(hSession[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_Logout[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_program;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u logins in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g logins/s\n",
+ i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ for (j = 0; j < i; j++) {
+ if (hSession[j] == CK_INVALID_HANDLE)
+ continue;
+ /* Close sessions */
+ rv = pkcs_C_CloseSession(hSession[j]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_CloseSession[%u]: Error = 0x%.8lX\n",
+ j, rv);
+ errflg = 1;
+ }
+ }
+
+ exit_program:
+ free(hSession);
+
+ rv = pkcs_C_Finalize(NULL_PTR);
+ if (rv != CKR_OK)
+ fprintf(stderr, "C_Finalize: Error = 0x%.8lX\n", rv);
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/privrsa.c b/bin/tests/pkcs11/benchmarks/privrsa.c
new file mode 100644
index 0000000..c50d8d2
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/privrsa.c
@@ -0,0 +1,360 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* privrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 };
+CK_BYTE privexp[] = {
+ 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02,
+ 0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33,
+ 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e,
+ 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63,
+ 0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b,
+ 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d,
+ 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e,
+ 0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea,
+ 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c,
+ 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7,
+ 0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc,
+ 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd,
+ 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f,
+ 0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d,
+ 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52,
+ 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c,
+ 0x41
+};
+CK_BYTE prime1[] = {
+ 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde,
+ 0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58,
+ 0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f,
+ 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36,
+ 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5,
+ 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1,
+ 0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed,
+ 0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8,
+ 0x21
+};
+CK_BYTE prime2[] = {
+ 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9,
+ 0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa,
+ 0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e,
+ 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab,
+ 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21,
+ 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88,
+ 0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36,
+ 0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0,
+ 0xdf
+};
+CK_BYTE exp_1[] = {
+ 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35,
+ 0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13,
+ 0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a,
+ 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f,
+ 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21,
+ 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42,
+ 0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f,
+ 0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1
+};
+CK_BYTE exp_2[] = {
+ 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c,
+ 0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb,
+ 0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb,
+ 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9,
+ 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24,
+ 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a,
+ 0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c,
+ 0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64,
+ 0x7f
+};
+CK_BYTE coeff[] = {
+ 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b,
+ 0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94,
+ 0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04,
+ 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5,
+ 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9,
+ 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5,
+ 0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67,
+ 0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9,
+ 0x8c
+};
+
+char label[16];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE *hKey;
+ CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) },
+ { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) },
+ { CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) },
+ { CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) },
+ { CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) },
+ { CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) },
+ { CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) }
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tprivrsa [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ hKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hKey[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ free(hKey);
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; i < count; i++) {
+ (void) snprintf(label, sizeof(label), "obj%u", i);
+ kTemplate[4].ulValueLen = strlen(label);
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 14, &hKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_CreateObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_objects;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u private RSA keys in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g private RSA keys/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ for (i = 0; i < count; i++) {
+ /* Destroy objects */
+ if (hKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, hKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(hKey);
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/pubrsa.c b/bin/tests/pkcs11/benchmarks/pubrsa.c
new file mode 100644
index 0000000..b27a999
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/pubrsa.c
@@ -0,0 +1,281 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* pubrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
+
+char label[16];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_OBJECT_HANDLE *hKey;
+ CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_LABEL, (CK_BYTE_PTR) label, (CK_ULONG) sizeof(label) },
+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tpubrsa [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Allocate hanles */
+ hKey = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hKey == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hKey[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ free(hKey);
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_objects;
+ }
+
+ for (i = 0; i < count; i++) {
+ (void) snprintf(label, sizeof(label), "obj%u", i);
+ kTemplate[4].ulValueLen = strlen(label);
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 8, &hKey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_CreateObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_objects;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_objects;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u public RSA keys in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g public RSA keys/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_objects:
+ for (i = 0; i < count; i++) {
+ /* Destroy objects */
+ if (hKey[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_DestroyObject(hSession, hKey[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_DestroyObject[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ free(hKey);
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/random.c b/bin/tests/pkcs11/benchmarks/random.c
new file mode 100644
index 0000000..10d6db0
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/random.c
@@ -0,0 +1,192 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* random [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE buf[1024];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ULONG len = sizeof(buf);
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RAND;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ count = atoi(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,
+ "\trandom [-m module] [-s slot] [-n count]\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_type, ISC_FALSE, ISC_FALSE,
+ ISC_FALSE, NULL, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ hSession = pctx.session;
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_session;
+ }
+
+ for (i = 0; i < count; i++) {
+ /* Get random bytes */
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GenerateRandom[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_session;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%uK random bytes in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g random bytes/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/session.c b/bin/tests/pkcs11/benchmarks/session.c
new file mode 100644
index 0000000..74bd63a
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/session.c
@@ -0,0 +1,213 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* session [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/internal.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE *hSession;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tsession [-m module] [-s slot] [-n count]\n");
+ exit(1);
+ }
+
+ /* Allocate sessions */
+ hSession = (CK_SESSION_HANDLE *)
+ malloc(count * sizeof(CK_SESSION_HANDLE));
+ if (hSession == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ for (i = 0; i < count; i++)
+ hSession[i] = CK_INVALID_HANDLE;
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ rv = pkcs_C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ if (rv == 0xfe)
+ fprintf(stderr,
+ "Can't load or link module \"%s\"\n",
+ pk11_get_lib_name());
+ else
+ fprintf(stderr, "C_Initialize: Error = 0x%.8lX\n", rv);
+ free(hSession);
+ exit(1);
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_program;
+ }
+
+ /* loop */
+ for (i = 0; i < count; i++) {
+ /* Open sessions */
+ rv = pkcs_C_OpenSession(slot, CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_OpenSession[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ if (i == 0)
+ goto exit_program;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_program;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u sessions in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g sessions/s\n",
+ i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ for (i = 0; i < count; i++) {
+ /* Close sessions */
+ if (hSession[i] == CK_INVALID_HANDLE)
+ continue;
+ rv = pkcs_C_CloseSession(hSession[i]);
+ if ((rv != CKR_OK) && !errflg) {
+ fprintf(stderr,
+ "C_CloseSession[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ errflg = 1;
+ }
+ }
+
+ exit_program:
+ free(hSession);
+
+ rv = pkcs_C_Finalize(NULL_PTR);
+ if (rv != CKR_OK)
+ fprintf(stderr, "C_Finalize: Error = 0x%.8lX\n", rv);
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/sha1.c b/bin/tests/pkcs11/benchmarks/sha1.c
new file mode 100644
index 0000000..756aadb
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sha1.c
@@ -0,0 +1,214 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* sha1 [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE buf[1024];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_MECHANISM mech = { CKM_SHA_1, NULL, 0 };
+ CK_ULONG len = sizeof(buf);
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_DIGEST;
+ char *lib_name = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:n:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tssha1 [-m module] [-s slot] [-n count]\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_type, ISC_FALSE, ISC_FALSE,
+ ISC_FALSE, NULL, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ hSession = pctx.session;
+
+ /* Randomize the buffer */
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_session;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_session;
+ }
+
+ /* Initialize Digest */
+ rv = pkcs_C_DigestInit(hSession, &mech);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DigestInit: Error = 0x%.8lX\n", rv);
+ goto exit_session;
+ }
+
+
+ for (i = 0; i < count; i++) {
+ /* Digest buffer */
+ rv = pkcs_C_DigestUpdate(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DigestUpdate[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ /* Finalize Digest (unconditionally) */
+ len = 20U;
+ rv = pkcs_C_DigestFinal(hSession, buf, &len);
+ if ((rv != CKR_OK) && !error)
+ fprintf(stderr, "C_DigestFinal: Error = 0x%.8lX\n", rv);
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_session;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%uK digested bytes in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g digested bytes/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/sign.c b/bin/tests/pkcs11/benchmarks/sign.c
new file mode 100644
index 0000000..8425ba9
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sign.c
@@ -0,0 +1,368 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* signrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE pubexp[] = { 0x01, 0x00, 0x01 };
+CK_BYTE privexp[] = {
+ 0x00, 0xae, 0x02, 0xf1, 0x47, 0xa8, 0x07, 0x02,
+ 0xb8, 0xf1, 0xd6, 0x92, 0x03, 0xee, 0x50, 0x33,
+ 0xab, 0x67, 0x9e, 0x3b, 0xb1, 0x57, 0xc7, 0x3e,
+ 0xc4, 0x86, 0x46, 0x61, 0xf1, 0xf8, 0xb6, 0x63,
+ 0x9f, 0x91, 0xe6, 0x3f, 0x44, 0xb8, 0x77, 0x1b,
+ 0xbe, 0x4c, 0x3c, 0xb8, 0x9f, 0xf7, 0x45, 0x7d,
+ 0xbf, 0x4f, 0xef, 0x3b, 0xcc, 0xda, 0x1a, 0x4e,
+ 0x34, 0xa8, 0x40, 0xea, 0x51, 0x72, 0x8a, 0xea,
+ 0x47, 0x06, 0x04, 0xd0, 0x62, 0x31, 0xa0, 0x6c,
+ 0x09, 0x60, 0xf9, 0xc7, 0x95, 0x88, 0x4a, 0xd7,
+ 0x19, 0xce, 0x89, 0x08, 0x87, 0x14, 0xef, 0xcc,
+ 0x0a, 0xef, 0x72, 0xb9, 0x21, 0xf5, 0xf0, 0xcd,
+ 0x6d, 0xe5, 0xfa, 0x15, 0x7f, 0xae, 0x33, 0x9f,
+ 0x26, 0xac, 0x2e, 0x52, 0x02, 0x07, 0xfb, 0x1d,
+ 0x4b, 0xec, 0x9a, 0x6b, 0x3b, 0x26, 0x1f, 0x52,
+ 0xfc, 0x47, 0xf8, 0x66, 0x33, 0xfa, 0x50, 0x6c,
+ 0x41
+};
+CK_BYTE prime1[] = {
+ 0x00, 0xe8, 0x98, 0xeb, 0xa1, 0xf0, 0xce, 0xde,
+ 0xc2, 0x74, 0x01, 0x18, 0x2b, 0xd3, 0x8f, 0x58,
+ 0xcd, 0xe9, 0x8e, 0x97, 0xbe, 0xfe, 0xe8, 0x6f,
+ 0xd6, 0x0c, 0x0a, 0x47, 0xf8, 0x56, 0x84, 0x36,
+ 0x15, 0xe6, 0x75, 0x1c, 0x69, 0x48, 0x8b, 0xf5,
+ 0x0f, 0x84, 0xd2, 0x60, 0x8b, 0xa2, 0x2a, 0xa1,
+ 0xeb, 0xed, 0xbe, 0x2d, 0xe9, 0x41, 0x0b, 0xed,
+ 0x17, 0x7c, 0xd3, 0xa6, 0x35, 0x6e, 0xa6, 0xd8,
+ 0x21
+};
+CK_BYTE prime2[] = {
+ 0x00, 0xca, 0x15, 0x6a, 0x43, 0x5e, 0x83, 0xc9,
+ 0x09, 0xeb, 0x14, 0x1e, 0x46, 0x46, 0x97, 0xfa,
+ 0xfa, 0x3c, 0x61, 0x7e, 0xc1, 0xf8, 0x8c, 0x5e,
+ 0xcb, 0xbf, 0xe4, 0xb9, 0x78, 0x7f, 0x4f, 0xab,
+ 0x82, 0x15, 0x53, 0xaa, 0x04, 0xee, 0x11, 0x21,
+ 0x2e, 0x23, 0x08, 0xa0, 0x14, 0x6d, 0x3a, 0x88,
+ 0xe6, 0xf8, 0xbe, 0x61, 0x38, 0x99, 0xca, 0x36,
+ 0x0d, 0x3e, 0x42, 0x0f, 0x63, 0x4d, 0x73, 0xf0,
+ 0xdf
+};
+CK_BYTE exp_1[] = {
+ 0x66, 0x2d, 0xb7, 0x65, 0xbe, 0x99, 0xc2, 0x35,
+ 0xfe, 0x2b, 0xf4, 0xe8, 0x5b, 0xd9, 0xdf, 0x13,
+ 0x26, 0x04, 0xe4, 0x18, 0x9d, 0x76, 0x92, 0x9a,
+ 0x9f, 0x53, 0x6c, 0xe6, 0x65, 0x6b, 0x53, 0x2f,
+ 0x2f, 0xbc, 0x46, 0xac, 0xe1, 0x97, 0xca, 0x21,
+ 0xf5, 0x21, 0x4e, 0x14, 0x49, 0x3b, 0x1d, 0x42,
+ 0xbd, 0x80, 0x0c, 0x3f, 0x29, 0xba, 0x09, 0x7f,
+ 0x85, 0xf0, 0x9c, 0x55, 0x60, 0xb4, 0x9e, 0xc1
+};
+CK_BYTE exp_2[] = {
+ 0x00, 0x87, 0x22, 0x74, 0xf1, 0xe2, 0x15, 0x3c,
+ 0x6d, 0xde, 0x7e, 0x90, 0x94, 0x2c, 0x06, 0xdb,
+ 0xb5, 0x54, 0x85, 0x59, 0xcf, 0x7a, 0x56, 0xdb,
+ 0xd9, 0x62, 0x54, 0x20, 0x56, 0xdc, 0xc3, 0xb9,
+ 0x0b, 0xff, 0x18, 0xf8, 0x7b, 0xdd, 0x7b, 0x24,
+ 0xf6, 0x06, 0x45, 0x71, 0x4e, 0xd7, 0x90, 0x2a,
+ 0x16, 0x52, 0x46, 0x75, 0x1a, 0xf5, 0x74, 0x8c,
+ 0x5a, 0xa4, 0xc4, 0x66, 0x27, 0xe0, 0x96, 0x64,
+ 0x7f
+};
+CK_BYTE coeff[] = {
+ 0x00, 0xd0, 0x1f, 0xb3, 0x47, 0x40, 0x93, 0x8b,
+ 0x99, 0xd7, 0xb5, 0xc6, 0x09, 0x82, 0x65, 0x94,
+ 0x9d, 0x56, 0x0a, 0x05, 0x55, 0x7d, 0x93, 0x04,
+ 0xa4, 0x26, 0xee, 0x42, 0x86, 0xa3, 0xf1, 0xd5,
+ 0x7a, 0x42, 0x84, 0x3c, 0x21, 0x96, 0x9a, 0xd9,
+ 0x36, 0xd4, 0x62, 0x01, 0xb0, 0x8b, 0x77, 0xe5,
+ 0xcc, 0x1b, 0xd2, 0x12, 0xd2, 0x9c, 0x89, 0x67,
+ 0x0c, 0x00, 0x09, 0x56, 0x8c, 0x33, 0x57, 0xf9,
+ 0x8c
+};
+
+CK_BYTE buf[1024];
+CK_BYTE sig[128];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ULONG len;
+ CK_ULONG slen;
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS kClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, pubexp, (CK_ULONG) sizeof(pubexp) },
+ { CKA_PRIVATE_EXPONENT, privexp, (CK_ULONG) sizeof(privexp) },
+ { CKA_PRIME_1, prime1, (CK_ULONG) sizeof(prime1) },
+ { CKA_PRIME_2, prime2, (CK_ULONG) sizeof(prime2) },
+ { CKA_EXPONENT_1, exp_1, (CK_ULONG) sizeof(exp_1) },
+ { CKA_EXPONENT_2, exp_2, (CK_ULONG) sizeof(exp_2) },
+ { CKA_COEFFICIENT, coeff, (CK_ULONG) sizeof(coeff) }
+ };
+ CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tsign [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ /* Create the private RSA key */
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 13, &hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
+ goto exit_key;
+ }
+
+ /* Randomize the buffer */
+ len = (CK_ULONG) sizeof(buf);
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_key;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_key;
+ }
+
+ for (i = 0; i < count; i++) {
+ /* Initialize Sign */
+ rv = pkcs_C_SignInit(hSession, &mech, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_SignInit[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+
+ /* Perform Sign */
+ slen = (CK_ULONG) sizeof(sig);
+ rv = pkcs_C_Sign(hSession, buf, len, sig, &slen);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_Sign[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_key;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u RSA signs in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g RSA signs/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_key:
+ if (hKey != CK_INVALID_HANDLE) {
+ rv = pkcs_C_DestroyObject(hSession, hKey);
+ if (rv != CKR_OK)
+ fprintf(stderr,
+ "C_DestroyObject: Error = 0x%.8lX\n",
+ rv);
+ }
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/benchmarks/verify.c b/bin/tests/pkcs11/benchmarks/verify.c
new file mode 100644
index 0000000..0a8f2c2
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/verify.c
@@ -0,0 +1,292 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/* verify [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#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
+
+#ifndef HAVE_CLOCK_GETTIME
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ result = gettimeofday(&tv, NULL);
+ if (result)
+ return (result);
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long) tv.tv_usec * 1000;
+ return (result);
+}
+#endif
+
+CK_BYTE modulus[] = {
+ 0x00, 0xb7, 0x9c, 0x1f, 0x05, 0xa3, 0xc2, 0x99,
+ 0x44, 0x82, 0x20, 0x78, 0x43, 0x7f, 0x5f, 0x3b,
+ 0x10, 0xd7, 0x9e, 0x61, 0x42, 0xd2, 0x7a, 0x90,
+ 0x50, 0x8a, 0x99, 0x33, 0xe7, 0xca, 0xc8, 0x5f,
+ 0x16, 0x1c, 0x56, 0xf8, 0xc1, 0x06, 0x2f, 0x96,
+ 0xe7, 0x54, 0xf2, 0x85, 0x89, 0x41, 0x36, 0xf5,
+ 0x4c, 0xa4, 0x0d, 0x62, 0xd3, 0x42, 0x51, 0x6b,
+ 0x9f, 0xdc, 0x36, 0xcb, 0xad, 0x56, 0xf4, 0xbd,
+ 0x2a, 0x60, 0x33, 0xb1, 0x7a, 0x99, 0xad, 0x08,
+ 0x9f, 0x95, 0xe8, 0xe5, 0x14, 0xd9, 0x68, 0x79,
+ 0xca, 0x4e, 0x72, 0xeb, 0xfb, 0x2c, 0xf1, 0x45,
+ 0xd3, 0x33, 0x65, 0xe7, 0xc5, 0x11, 0xdd, 0xe7,
+ 0x09, 0x83, 0x13, 0xd5, 0x17, 0x1b, 0xf4, 0xbd,
+ 0x49, 0xdd, 0x8a, 0x3c, 0x3c, 0xf7, 0xa1, 0x5d,
+ 0x7b, 0xb4, 0xd3, 0x80, 0x25, 0xf4, 0x05, 0x8f,
+ 0xbc, 0x2c, 0x2a, 0x47, 0xff, 0xd1, 0xc8, 0x34,
+ 0xbf
+};
+CK_BYTE exponent[] = { 0x01, 0x00, 0x01 };
+
+CK_BYTE buf[1024];
+CK_BYTE sig[128];
+
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
+ CK_ULONG len;
+ CK_ULONG slen;
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS kClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE kType = CKK_RSA;
+ CK_ATTRIBUTE kTemplate[] =
+ {
+ { CKA_CLASS, &kClass, (CK_ULONG) sizeof(kClass) },
+ { CKA_KEY_TYPE, &kType, (CK_ULONG) sizeof(kType) },
+ { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
+ { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
+ { CKA_MODULUS, modulus, (CK_ULONG) sizeof(modulus) },
+ { CKA_PUBLIC_EXPONENT, exponent, (CK_ULONG) sizeof(exponent) }
+ };
+ CK_MECHANISM mech = { CKM_SHA1_RSA_PKCS, NULL, 0 };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_RSA;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ int c, errflg = 0;
+ int ontoken = 0;
+ unsigned int count = 1000;
+ unsigned int i;
+ struct timespec starttime;
+ struct timespec endtime;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:p:tn:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 't':
+ ontoken = 1;
+ break;
+ case 'n':
+ count = atoi(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,
+ "\tverify [-m module] [-s slot] [-p pin] "
+ "[-t] [-n count]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_TRUE,
+ ISC_TRUE, (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NODIGESTSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ /* Create the private RSA key */
+ if (ontoken)
+ kTemplate[2].pValue = &truevalue;
+
+ rv = pkcs_C_CreateObject(hSession, kTemplate, 7, &hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_key;
+ }
+
+ /* Randomize the buffer */
+ len = (CK_ULONG) sizeof(buf);
+ rv = pkcs_C_GenerateRandom(hSession, buf, len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateRandom: Error = 0x%.8lX\n", rv);
+ goto exit_key;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &starttime) < 0) {
+ perror("clock_gettime(start)");
+ goto exit_key;
+ }
+
+ for (i = 0; i < count; i++) {
+ /* Initialize Verify */
+ rv = pkcs_C_VerifyInit(hSession, &mech, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_VerifyInit[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+
+ /* Perform Verify */
+ slen = (CK_ULONG) sizeof(sig);
+ rv = pkcs_C_Verify(hSession, buf, len, sig, slen);
+ if ((rv != CKR_OK) && (rv != CKR_SIGNATURE_INVALID)) {
+ fprintf(stderr,
+ "C_Verify[%u]: Error = 0x%.8lX\n",
+ i, rv);
+ error = 1;
+ break;
+ }
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &endtime) < 0) {
+ perror("clock_gettime(end)");
+ goto exit_key;
+ }
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_nsec -= starttime.tv_nsec;
+ while (endtime.tv_nsec < 0) {
+ endtime.tv_sec -= 1;
+ endtime.tv_nsec += 1000000000;
+ }
+ printf("%u RSA verify in %ld.%09lds\n", i,
+ endtime.tv_sec, endtime.tv_nsec);
+ if (i > 0)
+ printf("%g RSA verify/s\n",
+ 1024 * i / ((double) endtime.tv_sec +
+ (double) endtime.tv_nsec / 1000000000.));
+
+ exit_key:
+ if (hKey != CK_INVALID_HANDLE) {
+ rv = pkcs_C_DestroyObject(hSession, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DestroyObject: Error = 0x%.8lX\n",
+ rv);
+ errflg = 1;
+ }
+ }
+
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/pkcs11-hmacmd5.c b/bin/tests/pkcs11/pkcs11-hmacmd5.c
new file mode 100644
index 0000000..00a1df1
--- /dev/null
+++ b/bin/tests/pkcs11/pkcs11-hmacmd5.c
@@ -0,0 +1,332 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/*
+ * pkcs11-hmacmd5
+ *
+ * Prints the MD5 HMAC of the standard input, using the PKCS#11 device.
+ *
+ * Usage:
+ * pkcs11-hmacmd5 [-m module] [-s $slot] [-n] [-p $pin]
+ * -m: PKCS#11 provider module. This must be the full
+ * path to a shared library object implementing the
+ * PKCS#11 API for a device.
+ * -s: Slot
+ * -p: PIN
+ * -n: don't log in to the PKCS#11 device
+ * -k: key name for the HMAC
+ */
+
+/*! \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/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
+
+/* Define static key template values */
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+#define BLOCKSIZE 32768
+
+char buffer[BLOCKSIZE + 72];
+char digest[16];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mech = { CKM_MD5_HMAC, NULL, 0 };
+ CK_ULONG len;
+ CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
+ 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, 0 }
+ };
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_DIGEST;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ isc_boolean_t logon = ISC_TRUE;
+ int c, errflg = 0;
+ char *key = NULL;
+ size_t sum = 0;
+ unsigned int i;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:np:k:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ logon = ISC_FALSE;
+ break;
+ case 'p':
+ pin = isc_commandline_argument;
+ break;
+ case 'k':
+ key = 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 || (key == NULL)) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr,
+ "\tpkcs11-hmacmd5 [-m module] [-s slot] "
+ "[-n|-p pin] -k key\n");
+ exit(1);
+ }
+
+ /* Decode the key */
+ for (i = 0; i < BLOCKSIZE / 2; i++) {
+ switch (c = *key++) {
+ case 0:
+ goto key_done;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if ((i & 1) == 0)
+ buffer[i >> 1] = (c - '0') << 4;
+ else
+ buffer[i >> 1] |= c - '0';
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ if ((i & 1) == 0)
+ buffer[i >> 1] = (c - 'A' + 10) << 4;
+ else
+ buffer[i >> 1] |= c - 'A' + 10;
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ if ((i & 1) == 0)
+ buffer[i >> 1] = (c - 'a' + 10) << 4;
+ else
+ buffer[i >> 1] |= c - 'a' + 10;
+ break;
+ default:
+ fprintf(stderr, "Not hexdigit '%c' in key\n", c);
+ exit(1);
+ }
+ }
+ key_done:
+ if ((i & 1) != 0) {
+ fprintf(stderr, "Even number of hexdigits in key\n");
+ exit(1);
+ }
+ len = i >> 1;
+ keyTemplate[5].pValue = buffer;
+ keyTemplate[5].ulValueLen = (CK_ULONG) len;
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (logon && pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, logon,
+ (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ rv = pkcs_C_CreateObject(hSession, keyTemplate, (CK_ULONG) 6, &hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ if (hKey == CK_INVALID_HANDLE) {
+ fprintf(stderr, "C_CreateObject failed\n");
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = pkcs_C_SignInit(hSession, &mech, hKey);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_SignInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_sign;
+ }
+
+ for (;;) {
+ size_t n;
+
+ for (;;) {
+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stdin);
+ sum += n;
+ if (sum == BLOCKSIZE)
+ break;
+ if (n == 0) {
+ if (ferror(stdin)) {
+ fprintf(stderr, "fread failed\n");
+ error = 1;
+ goto exit_sign;
+ }
+ goto partial_block;
+ }
+ if (feof(stdin))
+ goto partial_block;
+ }
+
+ rv = pkcs_C_SignUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) BLOCKSIZE);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_SignUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_sign;
+ }
+ }
+
+partial_block:
+ if (sum > 0) {
+ rv = pkcs_C_SignUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) sum);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_SignUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_sign;
+ }
+ }
+
+ len = 16;
+ rv = pkcs_C_SignFinal(hSession, (CK_BYTE_PTR) digest, &len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_SignFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_sign;
+ }
+ if (len != 16) {
+ fprintf(stderr, "C_SignFinal: bad length = %lu\n", len);
+ error = 1;
+ }
+
+ for (i = 0; i < 16; i++)
+ printf("%02x", digest[i] & 0xff);
+ printf("\n");
+
+ exit_sign:
+ rv = pkcs_C_DestroyObject(hSession, hKey);
+ if ((error == 0) && (rv != CKR_OK)) {
+ fprintf(stderr, "C_DestroyObject: Error = 0x%.8lX\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/pkcs11/pkcs11-md5sum.c b/bin/tests/pkcs11/pkcs11-md5sum.c
new file mode 100644
index 0000000..fd50648
--- /dev/null
+++ b/bin/tests/pkcs11/pkcs11-md5sum.c
@@ -0,0 +1,235 @@
+/*
+ * 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) 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.
+ */
+
+/* $Id$ */
+
+/*
+ * pkcs11-md5sum
+ *
+ * Prints the MD5 checksum of the standard input, using the PKCS#11 device.
+ *
+ * Usage:
+ * pkcs11-md5sum [-m module] [-s $slot] [-n] [-p $pin]
+ * -m: PKCS#11 provider module. This must be the full
+ * path to a shared library object implementing the
+ * PKCS#11 API for a device.
+ * -s: Slot
+ * -p: PIN
+ * -n: don't log in to the PKCS#11 device
+ */
+
+/*! \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/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
+
+#define BLOCKSIZE 32768
+
+char buffer[BLOCKSIZE + 72];
+char digest[16];
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
+ CK_ULONG len;
+ pk11_context_t pctx;
+ pk11_optype_t op_type = OP_DIGEST;
+ char *lib_name = NULL;
+ char *pin = NULL;
+ int error = 0;
+ isc_boolean_t logon = ISC_TRUE;
+ int c, errflg = 0;
+ size_t sum = 0;
+ unsigned int i;
+
+ while ((c = isc_commandline_parse(argc, argv, ":m:s:np:")) != -1) {
+ switch (c) {
+ case 'm':
+ lib_name = isc_commandline_argument;
+ break;
+ case 's':
+ op_type = OP_ANY;
+ slot = atoi(isc_commandline_argument);
+ break;
+ case 'n':
+ logon = ISC_FALSE;
+ break;
+ case 'p':
+ pin = 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-md5sum [-m module] [-s slot] [-n|-p pin]\n");
+ exit(1);
+ }
+
+ pk11_result_register();
+
+ /* Initialize the CRYPTOKI library */
+ if (lib_name != NULL)
+ pk11_set_lib_name(lib_name);
+
+ if (logon && pin == NULL)
+ pin = getpassphrase("Enter Pin: ");
+
+ result = pk11_get_session(&pctx, op_type, ISC_FALSE, ISC_FALSE, logon,
+ (const char *) pin, slot);
+ if ((result != ISC_R_SUCCESS) &&
+ (result != PK11_R_NORANDOMSERVICE) &&
+ (result != PK11_R_NOAESSERVICE)) {
+ fprintf(stderr, "Error initializing PKCS#11: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+
+ if (pin != NULL)
+ memset(pin, 0, strlen((char *)pin));
+
+ hSession = pctx.session;
+
+ rv = pkcs_C_DigestInit(hSession, &mech);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DigestInit: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ for (;;) {
+ size_t n;
+
+ for (;;) {
+ n = fread(buffer + sum, 1, BLOCKSIZE - sum, stdin);
+ sum += n;
+ if (sum == BLOCKSIZE)
+ break;
+ if (n == 0) {
+ if (ferror(stdin)) {
+ fprintf(stderr, "fread failed\n");
+ error = 1;
+ goto exit_session;
+ }
+ goto partial_block;
+ }
+ if (feof(stdin))
+ goto partial_block;
+ }
+
+ rv = pkcs_C_DigestUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) BLOCKSIZE);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DigestUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_session;
+ }
+ }
+
+partial_block:
+ if (sum > 0) {
+ rv = pkcs_C_DigestUpdate(hSession, (CK_BYTE_PTR) buffer,
+ (CK_ULONG) sum);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_DigestUpdate: Error = 0x%.8lX\n",
+ rv);
+ error = 1;
+ goto exit_session;
+ }
+ }
+
+ len = 16;
+ rv = pkcs_C_DigestFinal(hSession, (CK_BYTE_PTR) digest, &len);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DigestFinal: Error = 0x%.8lX\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ if (len != 16) {
+ fprintf(stderr, "C_DigestFinal: bad length = %lu\n", len);
+ error = 1;
+ }
+
+ for (i = 0; i < 16; i++)
+ printf("%02x", digest[i] & 0xff);
+ printf("\n");
+
+ exit_session:
+ pk11_return_session(&pctx);
+ (void) pk11_finalize();
+
+ exit(error);
+}
diff --git a/bin/tests/system/autosign/prereq.sh b/bin/tests/system/autosign/prereq.sh
index 34cd4a1..53807a2 100644
--- a/bin/tests/system/autosign/prereq.sh
+++ b/bin/tests/system/autosign/prereq.sh
@@ -25,6 +25,7 @@ if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1
then
rm -f Kfoo*
else
- echo "I:This test requires that --with-openssl was used." >&2
+ echo "I:This test requires cryptography" >&2
+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
exit 1
fi
diff --git a/bin/tests/system/cleanpkcs11.sh b/bin/tests/system/cleanpkcs11.sh
index e1cbc6f..ba541ed 100644
--- a/bin/tests/system/cleanpkcs11.sh
+++ b/bin/tests/system/cleanpkcs11.sh
@@ -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 --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in
index d6e902f..c40e8f1 100644
--- a/bin/tests/system/conf.sh.in
+++ b/bin/tests/system/conf.sh.in
@@ -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
@@ -63,7 +63,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin
database dlv dlvauto dlz dlzexternal dname dns64 dnssec ecdsa
formerr forward glue gost ixfr inline limits logfileconfig
lwresd masterfile masterformat metadata notify nsupdate pending
- pkcs11 redirect resolver rndc rpz rrl rrsetorder rsabigexponent
+ @PKCS11_TEST@ redirect resolver rndc rpz rrl rrsetorder rsabigexponent
smartsign sortlist spf staticstub stub tkey tsig tsiggss unknown
upforwd verify views wildcard xfer xferquota zero zonechecks"
diff --git a/bin/tests/system/dnssec/prereq.sh b/bin/tests/system/dnssec/prereq.sh
index cb7c0c7..113e372 100644
--- a/bin/tests/system/dnssec/prereq.sh
+++ b/bin/tests/system/dnssec/prereq.sh
@@ -23,6 +23,7 @@ if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1
then
rm -f Kfoo*
else
- echo "I:This test requires that --with-openssl was used." >&2
+ echo "I:This test requires cryptography" >&2
+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
exit 1
fi
diff --git a/bin/tests/system/ecdsa/prereq.sh.in b/bin/tests/system/ecdsa/prereq.sh.in
index 434b53c..4214a30 100644
--- a/bin/tests/system/ecdsa/prereq.sh.in
+++ b/bin/tests/system/ecdsa/prereq.sh.in
@@ -16,9 +16,16 @@
# $Id$
-OPENSSL_ECDSA="@OPENSSL_ECDSA@"
-if test -z "$OPENSSL_ECDSA"
-then
- echo "I:This test requires a openssl version with ecdsa support." >&2
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+../../../tools/genrandom 400 random.data
+
+fail=0
+$KEYGEN -q -a ecdsap256sha256 test > /dev/null 2>&1 || fail=1
+rm -f Ktest* random.data
+
+if [ $fail != 0 ]
+ then
+ echo "I:This test requires support for ECDSA cryptography." >&2
exit 255
fi
diff --git a/bin/tests/system/gost/prereq.sh.in b/bin/tests/system/gost/prereq.sh.in
index 98ec507..0e4079e 100644
--- a/bin/tests/system/gost/prereq.sh.in
+++ b/bin/tests/system/gost/prereq.sh.in
@@ -16,9 +16,16 @@
# $Id: prereq.sh.in,v 1.4 2010/12/27 13:38:43 marka Exp $
-OPENSSL_GOST="@OPENSSL_GOST@"
-if test -z "$OPENSSL_GOST"
-then
- echo "I:This test requires a openssl version with gost support." >&2
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+../../../tools/genrandom 400 random.data
+
+fail=0
+$KEYGEN -q -a eccgost test > /dev/null 2>&1 || fail=1
+rm -f Ktest* random.data
+
+if [ $fail != 0 ]
+ then
+ echo "I:This test requires support for GOST cryptography." >&2
exit 255
fi
diff --git a/bin/tests/system/inline/clean.sh b/bin/tests/system/inline/clean.sh
index dae21e5..b6dda0b 100644
--- a/bin/tests/system/inline/clean.sh
+++ b/bin/tests/system/inline/clean.sh
@@ -74,7 +74,7 @@ rm -f ns5/bits.bk.signed
rm -f ns5/bits.bk.signed.jnl
rm -f */*.jbk
rm -f random.data
-rm -f dig.out.ns*.test*
+rm -f dig.out.ns*
rm -f signing.out*
rm -f freeze.test*
rm -f thaw.test*
diff --git a/bin/tests/system/metadata/prereq.sh b/bin/tests/system/metadata/prereq.sh
index b7ce1ea..006bcf5 100644
--- a/bin/tests/system/metadata/prereq.sh
+++ b/bin/tests/system/metadata/prereq.sh
@@ -22,6 +22,7 @@ if $KEYGEN -q -r random.data foo > /dev/null 2>&1
then
rm -f Kfoo*
else
- echo "I:This test requires that --with-openssl was used." >&2
+ echo "I:This test requires cryptography" >&2
+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
exit 1
fi
diff --git a/bin/tests/system/pending/prereq.sh b/bin/tests/system/pending/prereq.sh
index 0b6998e..f0848d7 100644
--- a/bin/tests/system/pending/prereq.sh
+++ b/bin/tests/system/pending/prereq.sh
@@ -16,12 +16,25 @@
# $Id: prereq.sh,v 1.3 2009/11/18 23:48:06 tbox Exp $
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
../../../tools/genrandom 400 random.data
-if $KEYGEN -q -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1
-then
- rm -f Kfoo*
+rsafail=0 eccfail=0
+
+$KEYGEN -q -r random.data foo > /dev/null 2>&1 || rsafail=1
+rm -f Kfoo*
+
+$KEYGEN -q -a ECDSAP256SHA256 -r random.data foo > /dev/null 2>&1 || eccfail=1
+rm -f Kfoo*
+
+if [ $rsafail = 0 -a $eccfail = 0 ]; then
+ echo both > supported
+elif [ $rsafail = 1 -a $eccfail = 1 ]; then
+ echo "I:This test requires PKCS#11 support for either RSA or ECDSA cryptography." >&2
+ exit 255
+elif [ $rsafail = 0 ]; then
+ echo rsaonly > supported
else
- echo "I:This test requires that --with-openssl was used." >&2
- exit 1
+ echo ecconly > supported
fi
diff --git a/bin/tests/system/pkcs11/clean.sh b/bin/tests/system/pkcs11/clean.sh
index d7a557b..29d0149 100644
--- a/bin/tests/system/pkcs11/clean.sh
+++ b/bin/tests/system/pkcs11/clean.sh
@@ -17,5 +17,6 @@
# $Id: clean.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $
rm -f K* ns1/K* keyset-* dsset-* ns1/*.db ns1/*.signed ns1/*.jnl
-rm -f dig.out random.data
-rm -f ns1/key ns1/named.memstats
+rm -f dig.out random.data pin
+rm -f ns1/*.key ns1/named.memstats
+rm -f supported
diff --git a/bin/tests/system/pkcs11/ns1/named.conf b/bin/tests/system/pkcs11/ns1/named.conf
index 09a850f..48b8adf 100644
--- a/bin/tests/system/pkcs11/ns1/named.conf
+++ b/bin/tests/system/pkcs11/ns1/named.conf
@@ -39,8 +39,14 @@ controls {
inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
};
-zone "example." {
+zone "rsa.example." {
+ type master;
+ file "rsa.example.db.signed";
+ allow-update { any; };
+};
+
+zone "ecc.example." {
type master;
- file "example.db.signed";
+ file "ecc.example.db.signed";
allow-update { any; };
};
diff --git a/bin/tests/system/pkcs11/setup.sh b/bin/tests/system/pkcs11/setup.sh
index c044d75..a17a83d 100644
--- a/bin/tests/system/pkcs11/setup.sh
+++ b/bin/tests/system/pkcs11/setup.sh
@@ -21,21 +21,59 @@ SYSTEMTESTTOP=..
RANDFILE=random.data
-zone=example
infile=ns1/example.db.in
-zonefile=ns1/example.db
-$PK11GEN -b 1024 -l robie-zsk1 -i 01
-$PK11GEN -b 1024 -l robie-zsk2 -i 02
-$PK11GEN -b 2048 -l robie-ksk
+/bin/echo -n ${HSMPIN:-1234}> pin
+PWD=`pwd`
-zsk1=`$KEYFRLAB -a RSASHA1 -l robie-zsk1 example`
-zsk2=`$KEYFRLAB -a RSASHA1 -l robie-zsk2 example`
-ksk=`$KEYFRLAB -a RSASHA1 -f ksk -l robie-ksk example`
+supported=`cat supported`
-cat $infile $zsk1.key $ksk.key > $zonefile
-$SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err
-rm -f signer.err
+zone=rsa.example
+zonefile=ns1/rsa.example.db
+if [ "$supported" != "ecconly" ]; then
+ $PK11GEN -a RSA -b 1024 -l robie-rsa-zsk1 -i 01
+ $PK11GEN -a RSA -b 1024 -l robie-rsa-zsk2 -i 02
+ $PK11GEN -a RSA -b 2048 -l robie-rsa-ksk
+
+ rsazsk1=`$KEYFRLAB -a RSASHA1 \
+ -l "object=robie-rsa-zsk1;pin-source=$PWD/pin" rsa.example`
+ rsazsk2=`$KEYFRLAB -a RSASHA1 \
+ -l "object=robie-rsa-zsk2;pin-source=$PWD/pin" rsa.example`
+ rsaksk=`$KEYFRLAB -a RSASHA1 -f ksk \
+ -l "object=robie-rsa-ksk;pin-source=$PWD/pin" rsa.example`
+
+ cat $infile $rsazsk1.key $rsaksk.key > $zonefile
+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+ cp $rsazsk2.key ns1/rsa.key
+ mv Krsa* ns1
+else
+ # RSA not available and will not be tested; make a placeholder
+ cp $infile ${zonefile}.signed
+fi
+
+zone=ecc.example
+zonefile=ns1/ecc.example.db
+if [ "$supported" != "rsaonly" ]; then
+ $PK11GEN -a ECC -b 256 -l robie-ecc-zsk1 -i 03
+ $PK11GEN -a ECC -b 256 -l robie-ecc-zsk2 -i 04
+ $PK11GEN -a ECC -b 384 -l robie-ecc-ksk
-cp $zsk2.key ns1/key
-mv Kexample* ns1
+ ecczsk1=`$KEYFRLAB -a ECDSAP256SHA256 \
+ -l "object=robie-ecc-zsk1;pin-source=$PWD/pin" ecc.example`
+ ecczsk2=`$KEYFRLAB -a ECDSAP256SHA256 \
+ -l "object=robie-ecc-zsk2;pin-source=$PWD/pin" ecc.example`
+ eccksk=`$KEYFRLAB -a ECDSAP384SHA384 -f ksk \
+ -l "object=robie-ecc-ksk;pin-source=$PWD/pin" ecc.example`
+
+ cat $infile $ecczsk1.key $eccksk.key > $zonefile
+ $SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+ cp $ecczsk2.key ns1/ecc.key
+ mv Kecc* ns1
+else
+ # ECC not available and will not be tested; make a placeholder
+ cp $infile ${zonefile}.signed
+fi
+
+rm -f signer.err
diff --git a/bin/tests/system/pkcs11/tests.sh b/bin/tests/system/pkcs11/tests.sh
index 4694afc..01f1523 100644
--- a/bin/tests/system/pkcs11/tests.sh
+++ b/bin/tests/system/pkcs11/tests.sh
@@ -26,47 +26,59 @@ DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
status=0
ret=0
-zonefile=ns1/example.db
+supported=`cat supported`
+case $supported in
+ rsaonly) algs="rsa" ;;
+ ecconly) algs="ecc" ;;
+ both) algs="rsa ecc" ;;
+esac
-echo "I:testing PKCS#11 key generation"
+for alg in $algs; do
+ zonefile=ns1/$alg.example.db
+ echo "I:testing PKCS#11 key generation ($alg)"
+ count=`$PK11LIST | grep robie-$alg-ksk | wc -l`
+ if [ $count != 2 ]; then echo "I:failed"; status=1; fi
-count=`$PK11LIST | grep robie-ksk | wc -l`
-if [ $count != 2 ]; then echo "I:failed"; status=1; fi
+ echo "I:testing offline signing with PKCS#11 keys ($alg)"
-echo "I:testing offline signing with PKCS#11 keys"
+ count=`grep RRSIG $zonefile.signed | wc -l`
+ if [ $count != 12 ]; then echo "I:failed"; status=1; fi
-count=`grep RRSIG $zonefile.signed | wc -l`
-if [ $count != 12 ]; then echo "I:failed"; status=1; fi
+ echo "I:testing inline signing with PKCS#11 keys ($alg)"
-echo "I:testing inline signing with PKCS#11 keys"
+ $NSUPDATE > /dev/null <<END || status=1
-$NSUPDATE > /dev/null <<END || status=1
server 10.53.0.1 5300
ttl 300
-zone example.
-update add `grep -v ';' ns1/key`
+zone $alg.example.
+update add `grep -v ';' ns1/${alg}.key`
send
END
-echo "I:waiting 20 seconds for key changes to take effect"
-sleep 20
-
-$DIG $DIGOPTS ns.example. @10.53.0.1 a > dig.out || ret=1
-if [ $ret != 0 ]; then echo "I:failed"; fi
-status=`expr $status + $ret`
-count=`grep RRSIG dig.out | wc -l`
-if [ $count != 4 ]; then echo "I:failed"; status=1; fi
-
-echo "I:testing PKCS#11 key destroy"
-
-ret=0
-$PK11DEL -l robie-zsk1 || ret=1
-$PK11DEL -i 02 || ret=1
-if [ $ret != 0 ]; then echo "I:failed"; fi
-status=`expr $status + $ret`
-count=`$PK11LIST | grep robie-zsk | wc -l`
-if [ $count != 0 ]; then echo "I:failed"; fi
-status=`expr $status + $count`
+ echo "I:waiting 20 seconds for key changes to take effect"
+ sleep 20
+
+ $DIG $DIGOPTS ns.$alg.example. @10.53.0.1 a > dig.out || ret=1
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+ count=`grep RRSIG dig.out | wc -l`
+ if [ $count != 4 ]; then echo "I:failed"; status=1; fi
+
+ echo "I:testing PKCS#11 key destroy ($alg)"
+ ret=0
+ $PK11DEL -l robie-$alg-ksk -w0 > /dev/null 2>&1 || ret=1
+ $PK11DEL -l robie-$alg-zsk1 -w0 > /dev/null 2>&1 || ret=1
+ case $alg in
+ rsa) id=02 ;;
+ ecc) id=04 ;;
+ esac
+ $PK11DEL -i $id -w0 > /dev/null 2>&1 || ret=1
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+ count=`$PK11LIST | grep robie-$alg | wc -l`
+ if [ $count != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $count`
+done
echo "I:exit status: $status"
exit $status
diff --git a/bin/tests/system/pkcs11ssl/clean.sh b/bin/tests/system/pkcs11ssl/clean.sh
new file mode 100644
index 0000000..14ec725
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) 2010, 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.
+
+rm -f K* ns1/K* keyset-* dsset-* ns1/*.db ns1/*.signed ns1/*.jnl
+rm -f dig.out random.data pin
+rm -f ns1/*.key ns1/named.memstats
+rm -f supported
diff --git a/bin/tests/system/pkcs11ssl/ns1/example.db.in b/bin/tests/system/pkcs11ssl/ns1/example.db.in
new file mode 100644
index 0000000..7166fa8
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/ns1/example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) 2010 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: example.db.in,v 1.3 2010/06/08 23:50:24 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
+
diff --git a/bin/tests/system/pkcs11ssl/ns1/named.conf b/bin/tests/system/pkcs11ssl/ns1/named.conf
new file mode 100644
index 0000000..90b8117
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/ns1/named.conf
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 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: named.conf,v 1.3 2010/06/08 23:50:24 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "rsa.example." {
+ type master;
+ file "rsa.example.db.signed";
+ allow-update { any; };
+};
+
+zone "ecc.example." {
+ type master;
+ file "ecc.example.db.signed";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/pkcs11ssl/prereq.sh b/bin/tests/system/pkcs11ssl/prereq.sh
new file mode 100644
index 0000000..b5133f4
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/prereq.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Copyright (C) 2010, 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: prereq.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+../../../tools/genrandom 400 random.data
+
+echo rsaonly > supported
+exit 0
+
+rsafail=0 eccfail=0
+
+$KEYGEN -q -r random.data foo > /dev/null 2>&1 || rsafail=1
+rm -f Kfoo*
+
+if [ $rsafail = 1 ]; then
+ echo "I:This test requires OpenSSL built with PKCS#11 support." >&2
+ exit 255
+fi
diff --git a/bin/tests/system/pkcs11ssl/setup.sh b/bin/tests/system/pkcs11ssl/setup.sh
new file mode 100644
index 0000000..c13b275
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/setup.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# 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.
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=random.data
+infile=ns1/example.db.in
+
+/bin/echo -n ${HSMPIN:-1234}> pin
+PWD=`pwd`
+
+zone=rsa.example
+zonefile=ns1/rsa.example.db
+
+$PK11GEN -a RSA -b 1024 -l robie-rsa-zsk1 -i 01
+$PK11GEN -a RSA -b 1024 -l robie-rsa-zsk2 -i 02
+$PK11GEN -a RSA -b 2048 -l robie-rsa-ksk
+
+rsazsk1=`$KEYFRLAB -a RSASHA1 \
+ -l "robie-rsa-zsk1" rsa.example`
+rsazsk2=`$KEYFRLAB -a RSASHA1 \
+ -l "robie-rsa-zsk2" rsa.example`
+rsaksk=`$KEYFRLAB -a RSASHA1 -f ksk \
+ -l "robie-rsa-ksk" rsa.example`
+
+cat $infile $rsazsk1.key $rsaksk.key > $zonefile
+$SIGNER -a -P -g -r $RANDFILE -o $zone $zonefile \
+ > /dev/null 2> signer.err || cat signer.err
+cp $rsazsk2.key ns1/rsa.key
+mv Krsa* ns1
+
+rm -f signer.err
diff --git a/bin/tests/system/pkcs11ssl/tests.sh b/bin/tests/system/pkcs11ssl/tests.sh
new file mode 100644
index 0000000..7785d5a
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/tests.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright (C) 2010, 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: tests.sh,v 1.3 2010/06/08 23:50:24 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=random.data
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+status=0
+ret=0
+
+alg=rsa
+zonefile=ns1/rsa.example.db
+echo "I:testing PKCS#11 key generation (rsa)"
+count=`$PK11LIST | grep robie-rsa-ksk | wc -l`
+if [ $count != 2 ]; then echo "I:failed"; status=1; fi
+
+echo "I:testing offline signing with PKCS#11 keys (rsa)"
+
+count=`grep RRSIG $zonefile.signed | wc -l`
+if [ $count != 12 ]; then echo "I:failed"; status=1; fi
+
+echo "I:testing inline signing with PKCS#11 keys (rsa)"
+
+$NSUPDATE > /dev/null <<END || status=1
+server 10.53.0.1 5300
+ttl 300
+zone rsa.example.
+update add `grep -v ';' ns1/${alg}.key`
+send
+END
+
+echo "I:waiting 20 seconds for key changes to take effect"
+sleep 20
+
+$DIG $DIGOPTS ns.rsa.example. @10.53.0.1 a > dig.out || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+count=`grep RRSIG dig.out | wc -l`
+if [ $count != 4 ]; then echo "I:failed"; status=1; fi
+
+echo "I:testing PKCS#11 key destroy (rsa)"
+ret=0
+$PK11DEL -l robie-rsa-ksk -w0 > /dev/null 2>&1 || ret=1
+$PK11DEL -l robie-rsa-zsk1 -w0 > /dev/null 2>&1 || ret=1
+$PK11DEL -i $id -w0 > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+count=`$PK11LIST | grep robie-rsa | wc -l`
+if [ $count != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $count`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/pkcs11ssl/usepkcs11 b/bin/tests/system/pkcs11ssl/usepkcs11
new file mode 100644
index 0000000..ef46412
--- /dev/null
+++ b/bin/tests/system/pkcs11ssl/usepkcs11
@@ -0,0 +1 @@
+This test relies on PKCS#11!
diff --git a/bin/tests/system/rsabigexponent/Makefile.in b/bin/tests/system/rsabigexponent/Makefile.in
index d32eb15..ce8958b 100644
--- a/bin/tests/system/rsabigexponent/Makefile.in
+++ b/bin/tests/system/rsabigexponent/Makefile.in
@@ -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 --git a/bin/tests/system/rsabigexponent/bigkey.c b/bin/tests/system/rsabigexponent/bigkey.c
index aa2e8ec..436254c 100644
--- a/bin/tests/system/rsabigexponent/bigkey.c
+++ b/bin/tests/system/rsabigexponent/bigkey.c
@@ -16,7 +16,7 @@
/* $Id$ */
-#ifdef OPENSSL
+#if defined(OPENSSL) || defined(PKCS11CRYPTO)
#include <config.h>
#include <stdio.h>
@@ -44,8 +44,16 @@
#include <dst/dst.h>
#include <dst/result.h>
+#ifdef OPENSSL
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER <= 0x00908000L
+#define USE_FIX_KEY_FILES
+#endif
+#else
+#define USE_FIX_KEY_FILES
+#endif
+
+#ifdef USE_FIX_KEY_FILES
/*
* Use a fixed key file pair if OpenSSL doesn't support > 32 bit exponents.
@@ -235,16 +243,16 @@ main(int argc, char **argv) {
}
#endif
-#else /* OPENSSL */
+#else /* OPENSSL || PKCS11CRYPTO */
#include <stdio.h>
#include <stdlib.h>
int
-main(int argc, char **argv) {
- fprintf(stderr, "Compiled without OpenSSL\n");
+main() {
+ fprintf(stderr, "Compiled without Crypto\n");
exit(1);
}
-#endif /* OPENSSL */
+#endif /* OPENSSL || PKCS11CRYPTO */
/*! \file */
diff --git a/bin/tests/system/rsabigexponent/prereq.sh b/bin/tests/system/rsabigexponent/prereq.sh
index 8edbf1d..6259fb6 100644
--- a/bin/tests/system/rsabigexponent/prereq.sh
+++ b/bin/tests/system/rsabigexponent/prereq.sh
@@ -22,6 +22,7 @@ if ./bigkey > /dev/null 2>&1
then
rm -f Kexample.*
else
- echo "I:This test requires that --with-openssl was used." >&2
+ echo "I:This test requires cryptography" >&2
+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
exit 1
fi
diff --git a/bin/tests/system/smartsign/prereq.sh b/bin/tests/system/smartsign/prereq.sh
index e47b769..9ed2fa8 100644
--- a/bin/tests/system/smartsign/prereq.sh
+++ b/bin/tests/system/smartsign/prereq.sh
@@ -22,6 +22,7 @@ if $KEYGEN -q -r random.data foo > /dev/null 2>&1
then
rm -f Kfoo*
else
- echo "I:This test requires that --with-openssl was used." >&2
+ echo "I:This test requires cryptography" >&2
+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
exit 1
fi
diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c
index ff2c2ee..af17582 100644
--- a/bin/tests/system/tkey/keycreate.c
+++ b/bin/tests/system/tkey/keycreate.c
@@ -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 --git a/bin/tests/system/tkey/prereq.sh b/bin/tests/system/tkey/prereq.sh
index fca4a27..66295fe 100644
--- a/bin/tests/system/tkey/prereq.sh
+++ b/bin/tests/system/tkey/prereq.sh
@@ -23,6 +23,7 @@ if $KEYGEN -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1
then
rm -f foo*
else
- echo "I:This test requires that --with-openssl was used." >&2
+ echo "I:This test requires cryptography" >&2
+ echo "I:--with-openssl, or --with-pkcs11 and --enable-native-pkcs11" >&2
exit 1
fi
diff --git a/config.h.in b/config.h.in
index 4139e1d..f2eb59a 100644
--- a/config.h.in
+++ b/config.h.in
@@ -132,14 +132,11 @@ int sigwait(const unsigned int *set, int *sig);
/** 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
@@ -187,6 +184,9 @@ int sigwait(const unsigned int *set, int *sig);
/* 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
@@ -292,6 +292,12 @@ int sigwait(const unsigned int *set, int *sig);
/* 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 `readline' function. */
#undef HAVE_READLINE
@@ -418,6 +424,9 @@ int sigwait(const unsigned int *set, int *sig);
(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 --git a/configure.in b/configure.in
index 8a06905..24eafb7 100644
--- a/configure.in
+++ b/configure.in
@@ -640,25 +640,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=""
@@ -666,7 +717,7 @@ case "$use_openssl" in
;;
auto)
DST_OPENSSL_INC=""
- USE_OPENSSL=""
+ CRYPTO=""
OPENSSLGOSTLINKOBJS=""
OPENSSLGOSTLINKSRS=""
OPENSSLLINKOBJS=""
@@ -676,6 +727,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
@@ -697,7 +753,7 @@ If you don't want OpenSSL, use --without-openssl])
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=""
@@ -733,6 +789,7 @@ If you don't want OpenSSL, use --without-openssl])
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"
@@ -839,8 +896,7 @@ 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
yes)
case "$have_ecdsa" in
@@ -869,6 +925,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>
@@ -896,8 +961,7 @@ 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
yes)
case "$have_gost" in
@@ -910,7 +974,7 @@ int main() {
*)
case "$have_gost" in
yes|no) ;;
- *) AC_MSG_ERROR([need --with-gost=[[yes or no]]]) ;;
+ *) AC_MSG_ERROR([need --with-gost=[[yes, no, raw or asn1]]]) ;;
esac
;;
esac
@@ -938,7 +1002,6 @@ esac
# it as needed) if it is found.
#
-AC_SUBST(USE_OPENSSL)
AC_SUBST(DST_OPENSSL_INC)
AC_SUBST(OPENSSLGOSTLINKOBJS)
AC_SUBST(OPENSSLGOSTLINKSRCS)
@@ -958,7 +1021,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
@@ -973,6 +1036,41 @@ 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'
+ 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=
+ ;;
+esac
+
#
# PKCS11 (aka crypto hardware) support
#
@@ -980,25 +1078,102 @@ 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
@@ -1006,13 +1181,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]]],
@@ -1245,6 +1484,21 @@ case "$use_randomdev" in
esac
#
+# Only check dsa signature generation on these platforms when performing
+# system tests.
+#
+CHECK_DSA=0
+if grep "#define PATH_RANDOMDEV " confdefs.h > /dev/null
+then
+ case "$host" in
+ *darwin*|*freebsd*)
+ CHECK_DSA=1
+ ;;
+ esac
+fi
+AC_SUBST(CHECK_DSA)
+
+#
# Do we have arc4random() ?
#
AC_CHECK_FUNC(arc4random, AC_DEFINE(HAVE_ARC4RANDOM))
@@ -1633,41 +1887,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'
- 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=
- ;;
-esac
-
#
# enable/disable dumping stack backtrace. Also check if the system supports
# glibc-compatible backtrace() function.
@@ -3419,6 +3638,9 @@ BIND9_CONFIGARGS="`echo $BIND9_CONFIGARGS | sed 's/^ //'`"
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"
@@ -3728,6 +3950,8 @@ AC_CONFIG_FILES([
bin/tests/mem/Makefile
bin/tests/names/Makefile
bin/tests/net/Makefile
+ bin/tests/pkcs11/Makefile
+ bin/tests/pkcs11/benchmarks/Makefile
bin/tests/rbt/Makefile
bin/tests/resolver/Makefile
bin/tests/sockaddr/Makefile
@@ -3811,11 +4035,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
@@ -3885,12 +4112,8 @@ test "$use_pkcs11" = "no" || echo " PKCS#11/Cryptoki support (--with-pkcs11)"
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
@@ -3923,24 +4146,28 @@ test "$enable_filter" = "yes" || \
test "$use_gssapi" = "no" && echo " GSS-API (--with-gssapi)"
test "$want_backtrace" = "yes" || \
echo " Print backtrace on crash (--enable-backtrace)"
-test "$use_pkcs11" = "no" && echo " PKCS#11/Cryptoki support (--with-pkcs11)"
-test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \
- echo " IPv6 support (--enable-ipv6)"
-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 "$use_pkcs11" = "no" && echo " PKCS#11/Cryptoki support (--with-pkcs11)"
+test "$enable_ipv6" = "no" -o "$found_ipv6" = "no" && \
+ echo " IPv6 support (--enable-ipv6)"
test "X$PYTHON" = "X" && echo " Python tools (--with-python)"
test "X$libxml2_libs" = "X" && echo " XML statistics (--with-libxml2)"
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 --git a/doc/arm/pkcs11.xml b/doc/arm/pkcs11.xml
index b4e22bb..5388a29 100644
--- a/doc/arm/pkcs11.xml
+++ b/doc/arm/pkcs11.xml
@@ -20,162 +20,259 @@
<!-- $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 — 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 — 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>The modified OpenSSL code is included in the BIND 9 release,
- in the form of a context diff against the latest verions of
- OpenSSL. OpenSSL 0.9.8, 1.0.0 and 1.0.1 are supported; there are
- separate diffs for each version. In the examples to follow,
- we use OpenSSL 0.9.8, but the same methods work with OpenSSL 1.0.0
- and 1.0.1.
+ <para>
+ The modified OpenSSL code is included in the BIND 9 release,
+ in the form of a context diff against the latest verions of
+ OpenSSL. OpenSSL 0.9.8, 1.0.0, and 1.0.1 are supported; there are
+ separate diffs for each version. In the examples to follow,
+ we use OpenSSL 0.9.8, but the same methods work with OpenSSL
+ 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
- is expected to change.</note>
+ 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>
+ 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.8s \
- < bind9/bin/pkcs11/openssl-0.9.8s-patch</userinput>
+ <para>Apply the patch from the BIND 9 release:</para>
+ <screen>
+$ <userinput>patch -p1 -d openssl-0.9.8y \
+ < 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>
+ <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>
@@ -185,25 +282,31 @@ $ <userinput> export SOFTHSM_CONF=/opt/pkcs11/softhsm.conf </userinput>
$ <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>
@@ -211,29 +314,31 @@ $ <userinput>./Configure linux-x86_64 -pthread \
<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 \
@@ -244,8 +349,10 @@ $ <userinput>./configure CC="gcc -m32" --enable-threads \
<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 \
@@ -253,11 +360,13 @@ $ <userinput>./configure CC="cc -xarch=amd64" --enable-threads \
--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 -->
@@ -266,63 +375,85 @@ $ <userinput>./configure CC="cc -xarch=amd64" --enable-threads \
$ <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>
@@ -333,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:
@@ -383,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
- <engine>" 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 —
- for troubleshooting purposes, or because the HSM is unavailable
- — 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
+ <engine>" 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 —
+ for troubleshooting purposes, or because the HSM is unavailable
+ — 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
@@ -423,22 +580,25 @@ $ <userinput>dnssec-signzone -E '' -S example.net</userinput>
[ pkcs11_section ]
PIN = <replaceable><PLACE PIN HERE></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 --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in
index 0c5e93b..41fac95 100644
--- a/lib/dns/Makefile.in
+++ b/lib/dns/Makefile.in
@@ -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@ openssldh_link.@O@ openssldsa_link.@O@ \
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 --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
index cf97404..00a0080 100644
--- a/lib/dns/dnssec.c
+++ b/lib/dns/dnssec.c
@@ -275,7 +275,8 @@ dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
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_rdataset_t *set, dst_key_t *key,
}
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 *msg, dst_key_t *key) {
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 *source, dns_message_t *msg,
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 --git a/lib/dns/ds.c b/lib/dns/ds.c
index e72ecbb..b51476b 100644
--- a/lib/dns/ds.c
+++ b/lib/dns/ds.c
@@ -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_rdata_t *key,
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_rdata_t *key,
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_rdata_t *key,
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 --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
index 6416273..d96473f 100644
--- a/lib/dns/dst_api.c
+++ b/lib/dns/dst_api.c
@@ -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_entropy_t *ectx,
#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_entropy_t *ectx,
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_mem_t *mctx,
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_mem_t *mctx,
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 int len, isc_boolean_t pseudo) {
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 int len, isc_boolean_t pseudo) {
unsigned int
dst__entropy_status(void) {
-#ifdef BIND9
+#ifndef PKCS11CRYPTO
#ifdef GSSAPI
unsigned int flags = dst_entropy_flags;
isc_result_t ret;
diff --git a/lib/dns/dst_gost.h b/lib/dns/dst_gost.h
new file mode 100644
index 0000000..37a4200
--- /dev/null
+++ b/lib/dns/dst_gost.h
@@ -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 --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h
index 49ca424..b15135e 100644
--- a/lib/dns/dst_internal.h
+++ b/lib/dns/dst_internal.h
@@ -84,6 +84,12 @@ typedef struct dst_hmacsha256_key dst_hmacsha256_key_t;
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 dst_func **funcp);
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 --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
index 6348cc1..ec622d9 100644
--- a/lib/dns/dst_parse.c
+++ b/lib/dns/dst_parse.c
@@ -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, isc_boolean_t external) {
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 --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h
index f048bf0..a8a5641 100644
--- a/lib/dns/dst_parse.h
+++ b/lib/dns/dst_parse.h
@@ -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 --git a/lib/dns/dst_pkcs11.h b/lib/dns/dst_pkcs11.h
new file mode 100644
index 0000000..1c35b6b
--- /dev/null
+++ b/lib/dns/dst_pkcs11.h
@@ -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 --git a/lib/dns/dst_result.c b/lib/dns/dst_result.c
index 30aa1fa..79fa7d3 100644
--- a/lib/dns/dst_result.c
+++ b/lib/dns/dst_result.c
@@ -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 --git a/lib/dns/gssapi_link.c b/lib/dns/gssapi_link.c
index 5ad81cd..1c35959 100644
--- a/lib/dns/gssapi_link.c
+++ b/lib/dns/gssapi_link.c
@@ -358,6 +358,7 @@ gssapi_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
static dst_func_t gssapi_functions = {
gssapi_create_signverify_ctx,
+ NULL, /*%< createctx2 */
gssapi_destroy_signverify_ctx,
gssapi_adddata,
gssapi_sign,
diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c
index 1f1a0ca..7a56c79 100644
--- a/lib/dns/hmac_link.c
+++ b/lib/dns/hmac_link.c
@@ -282,6 +282,9 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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) {
@@ -310,6 +313,7 @@ hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t hmacmd5_functions = {
hmacmd5_createctx,
+ NULL, /*%< createctx2 */
hmacmd5_destroyctx,
hmacmd5_adddata,
hmacmd5_sign,
@@ -528,6 +532,9 @@ hmacsha1_tofile(const dst_key_t *key, const char *directory) {
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;
@@ -559,8 +566,11 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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,
@@ -587,6 +597,7 @@ hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t hmacsha1_functions = {
hmacsha1_createctx,
+ NULL, /*%< createctx2 */
hmacsha1_destroyctx,
hmacsha1_adddata,
hmacsha1_sign,
@@ -807,6 +818,9 @@ hmacsha224_tofile(const dst_key_t *key, const char *directory) {
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;
@@ -838,6 +852,9 @@ hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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) {
@@ -866,6 +883,7 @@ hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t hmacsha224_functions = {
hmacsha224_createctx,
+ NULL, /*%< createctx2 */
hmacsha224_destroyctx,
hmacsha224_adddata,
hmacsha224_sign,
@@ -1086,6 +1104,9 @@ hmacsha256_tofile(const dst_key_t *key, const char *directory) {
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;
@@ -1117,8 +1138,11 @@ hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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,
@@ -1145,6 +1169,7 @@ hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t hmacsha256_functions = {
hmacsha256_createctx,
+ NULL, /*%< createctx2 */
hmacsha256_destroyctx,
hmacsha256_adddata,
hmacsha256_sign,
@@ -1365,6 +1390,9 @@ hmacsha384_tofile(const dst_key_t *key, const char *directory) {
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;
@@ -1396,8 +1424,11 @@ hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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,
@@ -1424,6 +1455,7 @@ hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t hmacsha384_functions = {
hmacsha384_createctx,
+ NULL, /*%< createctx2 */
hmacsha384_destroyctx,
hmacsha384_adddata,
hmacsha384_sign,
@@ -1644,6 +1676,9 @@ hmacsha512_tofile(const dst_key_t *key, const char *directory) {
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;
@@ -1675,8 +1710,11 @@ hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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,
@@ -1703,6 +1741,7 @@ hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t hmacsha512_functions = {
hmacsha512_createctx,
+ NULL, /*%< createctx2 */
hmacsha512_destroyctx,
hmacsha512_adddata,
hmacsha512_sign,
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
index 1fdce4c..bdbd269 100644
--- a/lib/dns/include/dst/dst.h
+++ b/lib/dns/include/dst/dst.h
@@ -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 --git a/lib/dns/include/dst/result.h b/lib/dns/include/dst/result.h
index 00640a1..cf9428f 100644
--- a/lib/dns/include/dst/result.h
+++ b/lib/dns/include/dst/result.h
@@ -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 --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c
index 36b8a41..55752da 100644
--- a/lib/dns/openssldh_link.c
+++ b/lib/dns/openssldh_link.c
@@ -463,6 +463,9 @@ openssldh_tofile(const dst_key_t *key, const char *directory) {
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_t *lexer, dst_key_t *pub) {
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 --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c
index a24baae..fd6e91e 100644
--- a/lib/dns/openssldsa_link.c
+++ b/lib/dns/openssldsa_link.c
@@ -522,7 +522,7 @@ openssldsa_tofile(const dst_key_t *key, const char *directory) {
if (key->keydata.dsa == NULL)
return (DST_R_NULLKEY);
-
+
if (key->external) {
priv.nelements = 0;
return (dst__privstruct_writefile(key, &priv, directory));
@@ -573,20 +573,31 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
isc_mem_t *mctx = key->mctx;
#define DST_RET(a) {ret = a; goto err;}
- UNUSED(pub);
-
/* 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 = DSA_new();
if (dsa == NULL)
DST_RET(ISC_R_NOMEMORY);
dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
key->keydata.dsa = dsa;
- for (i=0; i < priv.nelements; i++) {
+ for (i = 0; i < priv.nelements; i++) {
BIGNUM *bn;
bn = BN_bin2bn(priv.elements[i].data,
priv.elements[i].length, NULL);
@@ -612,22 +623,8 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
}
}
dst__privstruct_free(&priv, mctx);
-
- if (key->external) {
- if (pub == NULL)
- DST_RET(DST_R_INVALIDPRIVATEKEY);
- dsa->q = pub->keydata.dsa->q;
- pub->keydata.dsa->q = NULL;
- dsa->p = pub->keydata.dsa->p;
- pub->keydata.dsa->p = NULL;
- dsa->g = pub->keydata.dsa->g;
- pub->keydata.dsa->g = NULL;
- dsa->pub_key = pub->keydata.dsa->pub_key;
- pub->keydata.dsa->pub_key = NULL;
- }
-
+ memset(&priv, 0, sizeof(priv));
key->key_size = BN_num_bits(dsa->p);
-
return (ISC_R_SUCCESS);
err:
@@ -639,6 +636,7 @@ openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
static dst_func_t openssldsa_functions = {
openssldsa_createctx,
+ NULL, /*%< createctx2 */
openssldsa_destroyctx,
openssldsa_adddata,
openssldsa_sign,
diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c
index 7eff9a0..c64cc55 100644
--- a/lib/dns/opensslecdsa_link.c
+++ b/lib/dns/opensslecdsa_link.c
@@ -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, const char *directory) {
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_lex_t *lexer, dst_key_t *pub) {
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_lex_t *lexer, dst_key_t *pub) {
static dst_func_t opensslecdsa_functions = {
opensslecdsa_createctx,
+ NULL, /*%< createctx2 */
opensslecdsa_destroyctx,
opensslecdsa_adddata,
opensslecdsa_sign,
diff --git a/lib/dns/opensslgost_link.c b/lib/dns/opensslgost_link.c
index 325a7c0..9b4ff55 100644
--- a/lib/dns/opensslgost_link.c
+++ b/lib/dns/opensslgost_link.c
@@ -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_buffer_t *data) {
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, const char *directory) {
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, const char *directory) {
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 --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c
index 894c7ae..1edeb8d 100644
--- a/lib/dns/opensslrsa_link.c
+++ b/lib/dns/opensslrsa_link.c
@@ -1196,6 +1196,24 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
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_t *lexer, dst_key_t *pub) {
}
#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_t *lexer, dst_key_t *pub) {
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_t *lexer, dst_key_t *pub) {
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, const char *engine, const char *label,
static dst_func_t opensslrsa_functions = {
opensslrsa_createctx,
+ NULL, /*%< createctx2 */
opensslrsa_destroyctx,
opensslrsa_adddata,
opensslrsa_sign,
diff --git a/lib/dns/pkcs11.c b/lib/dns/pkcs11.c
new file mode 100644
index 0000000..7aa15fa
--- /dev/null
+++ b/lib/dns/pkcs11.c
@@ -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 --git a/lib/dns/pkcs11dh_link.c b/lib/dns/pkcs11dh_link.c
new file mode 100644
index 0000000..87afc02
--- /dev/null
+++ b/lib/dns/pkcs11dh_link.c
@@ -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 --git a/lib/dns/pkcs11dsa_link.c b/lib/dns/pkcs11dsa_link.c
new file mode 100644
index 0000000..6c8e46c
--- /dev/null
+++ b/lib/dns/pkcs11dsa_link.c
@@ -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 --git a/lib/dns/pkcs11ecdsa_link.c b/lib/dns/pkcs11ecdsa_link.c
new file mode 100644
index 0000000..4f56050
--- /dev/null
+++ b/lib/dns/pkcs11ecdsa_link.c
@@ -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 --git a/lib/dns/pkcs11gost_link.c b/lib/dns/pkcs11gost_link.c
new file mode 100644
index 0000000..c03b285
--- /dev/null
+++ b/lib/dns/pkcs11gost_link.c
@@ -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 --git a/lib/dns/pkcs11rsa_link.c b/lib/dns/pkcs11rsa_link.c
new file mode 100644
index 0000000..010d4b6
--- /dev/null
+++ b/lib/dns/pkcs11rsa_link.c
@@ -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 --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c
index 5751ad8..732abdb 100644
--- a/lib/dns/rdata/generic/dlv_32769.c
+++ b/lib/dns/rdata/generic/dlv_32769.c
@@ -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 --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c
index dd47c8d..fc7f126 100644
--- a/lib/dns/rdata/generic/ds_43.c
+++ b/lib/dns/rdata/generic/ds_43.c
@@ -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 --git a/lib/dns/tests/Makefile.in b/lib/dns/tests/Makefile.in
index db47476..3b19784 100644
--- a/lib/dns/tests/Makefile.in
+++ b/lib/dns/tests/Makefile.in
@@ -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@
@@ -37,13 +38,13 @@ DNSDEPLIBS = ../libdns.@A@
LIBS = @LIBS@ @ATFLIBS@
OBJS = dnstest.@O@
-SRCS = dnstest.c master_test.c dbiterator_test.c time_test.c \
+SRCS = dnstest.c gost_test.c master_test.c dbiterator_test.c time_test.c \
private_test.c update_test.c zonemgr_test.c zt_test.c \
dbdiff_test.c dispatch_test.c nsec3_test.c \
rdataset_test.c rdata_test.c
SUBDIRS =
-TARGETS = master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \
+TARGETS = gost_test@EXEEXT@ master_test@EXEEXT@ dbiterator_test@EXEEXT@ time_test@EXEEXT@ \
private_test@EXEEXT@ update_test@EXEEXT@ zonemgr_test@EXEEXT@ \
zt_test@EXEEXT@ dbversion_test@EXEEXT@ dbdiff_test@EXEEXT@ \
dispatch_test@EXEEXT@ nsec3_test@EXEEXT@ \
@@ -123,6 +124,11 @@ dispatch_test@EXEEXT@: dispatch_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
dispatch_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
+gost_test@EXEEXT@: gost_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ gost_test.@O@ dnstest.@O@ ${DNSLIBS} \
+ ${ISCLIBS} ${LIBS}
+
unit::
sh ${top_srcdir}/unit/unittest.sh
diff --git a/lib/dns/tests/gost_test.c b/lib/dns/tests/gost_test.c
new file mode 100644
index 0000000..0dd9e55
--- /dev/null
+++ b/lib/dns/tests/gost_test.c
@@ -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 --git a/lib/dns/tkey.c b/lib/dns/tkey.c
index 161c188..20c98e5 100644
--- a/lib/dns/tkey.c
+++ b/lib/dns/tkey.c
@@ -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_name_t *signer, dns_name_t *name,
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 --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index c7768f4..3239bff 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.c
@@ -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, dns_message_t *msg,
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, dns_message_t *msg) {
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 --git a/lib/export/dns/Makefile.in b/lib/export/dns/Makefile.in
index 1e4540f..e10bf59 100644
--- a/lib/export/dns/Makefile.in
+++ b/lib/export/dns/Makefile.in
@@ -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 --git a/lib/export/isc/Makefile.in b/lib/export/isc/Makefile.in
index 62e5acd..a5f8bd0 100644
--- a/lib/export/isc/Makefile.in
+++ b/lib/export/isc/Makefile.in
@@ -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 --git a/lib/export/isc/unix/Makefile.in b/lib/export/isc/unix/Makefile.in
index 1873202..a904615 100644
--- a/lib/export/isc/unix/Makefile.in
+++ b/lib/export/isc/unix/Makefile.in
@@ -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 --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in
index eb718fd..df62ec9 100644
--- a/lib/isc/Makefile.in
+++ b/lib/isc/Makefile.in
@@ -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/dir.@O@ win32/file.@O@ \
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@ \
counter.@O@ error.@O@ event.@O@ \
@@ -68,7 +72,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 counter.c \
error.c event.c heap.c hex.c hmacmd5.c hmacsha.c \
diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c
index da9e81f..ae882d8 100644
--- a/lib/isc/entropy.c
+++ b/lib/isc/entropy.c
@@ -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 *ectx, isc_entropysource_t **source,
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 --git a/lib/isc/hmacmd5.c b/lib/isc/hmacmd5.c
index 4c4046d..79ec24a 100644
--- a/lib/isc/hmacmd5.c
+++ b/lib/isc/hmacmd5.c
@@ -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, unsigned char *digest) {
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 --git a/lib/isc/hmacsha.c b/lib/isc/hmacsha.c
index 3870963..9b79bc7 100644
--- a/lib/isc/hmacsha.c
+++ b/lib/isc/hmacsha.c
@@ -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 *ctx, unsigned char *digest, size_t len) {
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 --git a/lib/isc/include/Makefile.in b/lib/isc/include/Makefile.in
index 70c165e..c92ad45 100644
--- a/lib/isc/include/Makefile.in
+++ b/lib/isc/include/Makefile.in
@@ -19,7 +19,7 @@ srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
-SUBDIRS = isc
+SUBDIRS = isc pk11 pkcs11
TARGETS =
@BIND9_MAKE_RULES@
diff --git a/lib/isc/include/isc/hmacmd5.h b/lib/isc/include/isc/hmacmd5.h
index 9ecad45..e008328 100644
--- a/lib/isc/include/isc/hmacmd5.h
+++ b/lib/isc/include/isc/hmacmd5.h
@@ -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 --git a/lib/isc/include/isc/hmacsha.h b/lib/isc/include/isc/hmacsha.h
index 1d0e184..c223897 100644
--- a/lib/isc/include/isc/hmacsha.h
+++ b/lib/isc/include/isc/hmacsha.h
@@ -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 --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h
index dfa586d..a2e00b3 100644
--- a/lib/isc/include/isc/md5.h
+++ b/lib/isc/include/isc/md5.h
@@ -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 --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h
index d91e800..44b0eb4 100644
--- a/lib/isc/include/isc/resultclass.h
+++ b/lib/isc/include/isc/resultclass.h
@@ -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 --git a/lib/isc/include/isc/sha1.h b/lib/isc/include/isc/sha1.h
index 313ff96..f11a783 100644
--- a/lib/isc/include/isc/sha1.h
+++ b/lib/isc/include/isc/sha1.h
@@ -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 --git a/lib/isc/include/isc/sha2.h b/lib/isc/include/isc/sha2.h
index 439bbb9..14faa6e 100644
--- a/lib/isc/include/isc/sha2.h
+++ b/lib/isc/include/isc/sha2.h
@@ -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 --git a/lib/isc/include/pk11/Makefile.in b/lib/isc/include/pk11/Makefile.in
new file mode 100644
index 0000000..744c40e
--- /dev/null
+++ b/lib/isc/include/pk11/Makefile.in
@@ -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 --git a/lib/isc/include/pk11/constants.h b/lib/isc/include/pk11/constants.h
new file mode 100644
index 0000000..e1e0581
--- /dev/null
+++ b/lib/isc/include/pk11/constants.h
@@ -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 --git a/lib/isc/include/pk11/internal.h b/lib/isc/include/pk11/internal.h
new file mode 100644
index 0000000..14bef3c
--- /dev/null
+++ b/lib/isc/include/pk11/internal.h
@@ -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 --git a/lib/isc/include/pk11/pk11.h b/lib/isc/include/pk11/pk11.h
new file mode 100644
index 0000000..964a2a7
--- /dev/null
+++ b/lib/isc/include/pk11/pk11.h
@@ -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 --git a/lib/isc/include/pk11/result.h b/lib/isc/include/pk11/result.h
new file mode 100644
index 0000000..f624140
--- /dev/null
+++ b/lib/isc/include/pk11/result.h
@@ -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 --git a/lib/isc/include/pkcs11/Makefile.in b/lib/isc/include/pkcs11/Makefile.in
new file mode 100644
index 0000000..6e98688
--- /dev/null
+++ b/lib/isc/include/pkcs11/Makefile.in
@@ -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 --git a/lib/isc/include/pkcs11/pkcs11.h b/lib/isc/include/pkcs11/pkcs11.h
new file mode 100644
index 0000000..9261e1e
--- /dev/null
+++ b/lib/isc/include/pkcs11/pkcs11.h
@@ -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 --git a/lib/isc/include/pkcs11/pkcs11f.h b/lib/isc/include/pkcs11/pkcs11f.h
new file mode 100644
index 0000000..dec6315
--- /dev/null
+++ b/lib/isc/include/pkcs11/pkcs11f.h
@@ -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 --git a/lib/isc/include/pkcs11/pkcs11t.h b/lib/isc/include/pkcs11/pkcs11t.h
new file mode 100644
index 0000000..92a80bb
--- /dev/null
+++ b/lib/isc/include/pkcs11/pkcs11t.h
@@ -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 --git a/lib/isc/md5.c b/lib/isc/md5.c
index 7c6419b..2e3cf9a 100644
--- a/lib/isc/md5.c
+++ b/lib/isc/md5.c
@@ -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 char *digest) {
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 --git a/lib/isc/pk11.c b/lib/isc/pk11.c
new file mode 100644
index 0000000..015bff2
--- /dev/null
+++ b/lib/isc/pk11.c
@@ -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 --git a/lib/isc/pk11_result.c b/lib/isc/pk11_result.c
new file mode 100644
index 0000000..0ada753
--- /dev/null
+++ b/lib/isc/pk11_result.c
@@ -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 --git a/lib/isc/sha1.c b/lib/isc/sha1.c
index cce9603..caa721e 100644
--- a/lib/isc/sha1.c
+++ b/lib/isc/sha1.c
@@ -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, unsigned char *digest) {
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 --git a/lib/isc/sha2.c b/lib/isc/sha2.c
index db2e349..d7e0cf6 100644
--- a/lib/isc/sha2.c
+++ b/lib/isc/sha2.c
@@ -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[], isc_sha384_t *context) {
}
}
+#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, char buffer[]) {
} 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, char buffer[]) {
} 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, char buffer[]) {
} 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, char buffer[]) {
} else {
#ifdef ISC_PLATFORM_OPENSSLHASH
EVP_MD_CTX_cleanup(context);
+#elif PKCS11CRYPTO
+ pk11_return_session(context);
#else
memset(context, 0, sizeof(*context));
#endif
diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in
index c1411cb..0595fa2 100644
--- a/lib/isc/unix/Makefile.in
+++ b/lib/isc/unix/Makefile.in
@@ -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 --git a/lib/isc/unix/include/Makefile.in b/lib/isc/unix/include/Makefile.in
index 46c243e..354e6c8 100644
--- a/lib/isc/unix/include/Makefile.in
+++ b/lib/isc/unix/include/Makefile.in
@@ -19,7 +19,7 @@ srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
-SUBDIRS = isc
+SUBDIRS = isc pkcs11
TARGETS =
@BIND9_MAKE_RULES@
diff --git a/lib/isc/unix/include/pkcs11/Makefile.in b/lib/isc/unix/include/pkcs11/Makefile.in
new file mode 100644
index 0000000..8b175f4
--- /dev/null
+++ b/lib/isc/unix/include/pkcs11/Makefile.in
@@ -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 --git a/lib/isc/unix/include/pkcs11/cryptoki.h b/lib/isc/unix/include/pkcs11/cryptoki.h
new file mode 100644
index 0000000..7dc48b0
--- /dev/null
+++ b/lib/isc/unix/include/pkcs11/cryptoki.h
@@ -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 --git a/lib/isc/unix/pk11_api.c b/lib/isc/unix/pk11_api.c
new file mode 100644
index 0000000..9ccb959
--- /dev/null
+++ b/lib/isc/unix/pk11_api.c
@@ -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);
+}
--
2.1.0