summaryrefslogtreecommitdiffstats
path: root/bin/tests/pkcs11
diff options
context:
space:
mode:
Diffstat (limited to 'bin/tests/pkcs11')
-rw-r--r--bin/tests/pkcs11/Makefile.in44
-rw-r--r--bin/tests/pkcs11/README15
-rw-r--r--bin/tests/pkcs11/benchmarks/Makefile.in83
-rw-r--r--bin/tests/pkcs11/benchmarks/create.c263
-rw-r--r--bin/tests/pkcs11/benchmarks/find.c232
-rw-r--r--bin/tests/pkcs11/benchmarks/genrsa.c298
-rw-r--r--bin/tests/pkcs11/benchmarks/login.c252
-rw-r--r--bin/tests/pkcs11/benchmarks/privrsa.c363
-rw-r--r--bin/tests/pkcs11/benchmarks/pubrsa.c284
-rw-r--r--bin/tests/pkcs11/benchmarks/random.c194
-rw-r--r--bin/tests/pkcs11/benchmarks/session.c216
-rw-r--r--bin/tests/pkcs11/benchmarks/sha1.c217
-rw-r--r--bin/tests/pkcs11/benchmarks/sign.c371
-rw-r--r--bin/tests/pkcs11/benchmarks/verify.c295
-rw-r--r--bin/tests/pkcs11/pkcs11-hmacmd5.c327
-rw-r--r--bin/tests/pkcs11/pkcs11-md5sum.c230
16 files changed, 3684 insertions, 0 deletions
diff --git a/bin/tests/pkcs11/Makefile.in b/bin/tests/pkcs11/Makefile.in
new file mode 100644
index 0000000..73e0596
--- /dev/null
+++ b/bin/tests/pkcs11/Makefile.in
@@ -0,0 +1,44 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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@ @ISC_OPENSSL_LIBS@
+
+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/README b/bin/tests/pkcs11/README
new file mode 100644
index 0000000..2b594d9
--- /dev/null
+++ b/bin/tests/pkcs11/README
@@ -0,0 +1,15 @@
+"pkcs11-hmacmd5" is here to check for the presence of a known bug in
+the Thales nCipher PKCS#11 provider library. To test for the bug, use
+pkcs11-hmacmd5 to hash a test vector from RFC 2104, and determine
+whether the resulting digest is is correct. For instance:
+
+ echo -n "Hi There" | \
+ ./pkcs11-hmacmd5 -p <PIN> -k '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'
+
+...must return "9294727a3638bb1c13f48ef8158bfc9d".
+
+If any other value is returned, then the provider library is buggy,
+and theflag PK11_MD5_HMAC_REPLACE must be defined in
+lib/isc/include/pk11/site.h
+However, if the correct value is returned, then it is safe to turn
+off PK11_MD5_HMAC_REPLACE. (It is on by default.)
diff --git a/bin/tests/pkcs11/benchmarks/Makefile.in b/bin/tests/pkcs11/benchmarks/Makefile.in
new file mode 100644
index 0000000..15f5460
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/Makefile.in
@@ -0,0 +1,83 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+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@ @ISC_OPENSSL_LIBS@
+
+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..683aa40
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/create.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* create [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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, true, true,
+ 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..08d065a
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/find.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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 <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, false,
+ 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..c642586
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/genrsa.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* genrsa [-m module] [-s $slot] [-p pin] [-t] [-b bits] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, true,
+ 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..280e983
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/login.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* login [-m module] [-s $slot] [-p pin] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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..791a9a0
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/privrsa.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* privrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, true,
+ 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..9a40b53
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/pubrsa.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* pubrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, true,
+ 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..144cfa8
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/random.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* 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/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, false,
+ 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..2b576f3
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/session.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* session [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/internal.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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..cc8ca45
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sha1.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* sha1 [-m module] [-s $slot] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/pk11.h>
+#include <pk11/result.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, false,
+ 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..e9cdd6b
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sign.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* signrsa [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, true,
+ 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..b04b777
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/verify.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/* verify [-m module] [-s $slot] [-p pin] [-t] [-n count] */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.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
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif
+
+static int clock_gettime(int32_t id, struct timespec *tp);
+
+static int
+clock_gettime(int32_t id, struct timespec *tp)
+{
+ struct timeval tv;
+ int result;
+
+ UNUSED(id);
+
+ 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ 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, false, true,
+ 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..ba4adb1
--- /dev/null
+++ b/bin/tests/pkcs11/pkcs11-hmacmd5.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * 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 <stdbool.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/print.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;
+ bool logon = 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'n':
+ logon = 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, false, 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..56f3a61
--- /dev/null
+++ b/bin/tests/pkcs11/pkcs11-md5sum.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * 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 <stdbool.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/print.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;
+ bool logon = 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':
+ slot = atoi(isc_commandline_argument);
+ op_type = OP_ANY;
+ break;
+ case 'n':
+ logon = 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, false, 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);
+}