summaryrefslogtreecommitdiffstats
path: root/bin/tests/pkcs11
diff options
context:
space:
mode:
Diffstat (limited to 'bin/tests/pkcs11')
-rw-r--r--bin/tests/pkcs11/Makefile.in32
-rw-r--r--bin/tests/pkcs11/README15
-rw-r--r--bin/tests/pkcs11/benchmarks/Makefile.in74
-rw-r--r--bin/tests/pkcs11/benchmarks/create.c264
-rw-r--r--bin/tests/pkcs11/benchmarks/find.c230
-rw-r--r--bin/tests/pkcs11/benchmarks/genrsa.c296
-rw-r--r--bin/tests/pkcs11/benchmarks/login.c251
-rw-r--r--bin/tests/pkcs11/benchmarks/privrsa.c332
-rw-r--r--bin/tests/pkcs11/benchmarks/pubrsa.c278
-rw-r--r--bin/tests/pkcs11/benchmarks/session.c218
-rw-r--r--bin/tests/pkcs11/benchmarks/sha1.c217
-rw-r--r--bin/tests/pkcs11/benchmarks/sign.c336
-rw-r--r--bin/tests/pkcs11/benchmarks/verify.c285
13 files changed, 2828 insertions, 0 deletions
diff --git a/bin/tests/pkcs11/Makefile.in b/bin/tests/pkcs11/Makefile.in
new file mode 100644
index 0000000..56024c4
--- /dev/null
+++ b/bin/tests/pkcs11/Makefile.in
@@ -0,0 +1,32 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# 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 https://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@
+
+CINCLUDES = ${ISC_INCLUDES}
+CDEFINES =
+
+ISCLIBS = ../../../lib/isc/libisc.@A@ @NO_LIBTOOL_ISCLIBS@
+
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS = benchmarks
+
+@BIND9_MAKE_RULES@
+
+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..8101efc
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/Makefile.in
@@ -0,0 +1,74 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# 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 https://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@
+
+CINCLUDES = ${ISC_INCLUDES}
+CDEFINES =
+
+ISCLIBS = ../../../../lib/isc/libisc.@A@ @NO_LIBTOOL_ISCLIBS@
+
+LIBS = ${ISCLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = session@EXEEXT@ login@EXEEXT@ \
+ create@EXEEXT@ find@EXEEXT@ \
+ pubrsa@EXEEXT@ privrsa@EXEEXT@ genrsa@EXEEXT@ \
+ sign@EXEEXT@ verify@EXEEXT@
+
+SRCS = session.c login.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}
+
+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..2f1c365
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/create.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 handles */
+ 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 = getpass("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..e43fb68
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/find.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 = getpass("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..062fa69
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/genrsa.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 handles */
+ 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 = getpass("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..70dd0a1
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/login.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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/internal.h>
+#include <pk11/pk11.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 *)getpass("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..bd6911e
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/privrsa.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 handles */
+ 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 = getpass("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..1036df7
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/pubrsa.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 handles */
+ 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 = getpass("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/session.c b/bin/tests/pkcs11/benchmarks/session.c
new file mode 100644
index 0000000..69f823f
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/session.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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/internal.h>
+#include <pk11/pk11.h>
+
+#ifndef HAVE_CLOCK_GETTIME
+
+#include <sys/time.h>
+
+#ifndef CLOCK_REALTIME
+#define CLOCK_REALTIME 0
+#endif /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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..17a5662
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sha1.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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..0a2bed7
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/sign.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 = getpass("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..a2f1c29
--- /dev/null
+++ b/bin/tests/pkcs11/benchmarks/verify.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://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 <inttypes.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 /* ifndef CLOCK_REALTIME */
+
+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 == 0) {
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = (long)tv.tv_usec * 1000;
+ }
+ return (result);
+}
+#endif /* ifndef HAVE_CLOCK_GETTIME */
+
+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 = getpass("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);
+ error = 1;
+ }
+ }
+
+ pk11_return_session(&pctx);
+ (void)pk11_finalize();
+
+ exit(error);
+}