aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/bin
diff options
context:
space:
mode:
authorNingSun <ning.sun@intel.com>2018-02-08 08:34:03 -0800
committerNingSun <ning.sun@intel.com>2018-02-08 09:14:52 -0800
commit0c89b3ccba7c9b7332ab67ae1936aff51ca62367 (patch)
tree70c1b1d160d4c6d0a83395ca9a87c1264d0d3439 /SoftHSMv2/src/bin
parent945613b4db4e07f75d2bc7463db580ddfaa700fd (diff)
Initial sshsm project structure
Issue-ID: AAF-94 Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4 Signed-off-by: NingSun <ning.sun@intel.com>
Diffstat (limited to 'SoftHSMv2/src/bin')
-rw-r--r--SoftHSMv2/src/bin/Makefile.am10
-rw-r--r--SoftHSMv2/src/bin/common/Makefile.am3
-rw-r--r--SoftHSMv2/src/bin/common/findslot.cpp372
-rw-r--r--SoftHSMv2/src/bin/common/findslot.h42
-rw-r--r--SoftHSMv2/src/bin/common/getpw.cpp207
-rw-r--r--SoftHSMv2/src/bin/common/getpw.h40
-rw-r--r--SoftHSMv2/src/bin/common/library.cpp145
-rw-r--r--SoftHSMv2/src/bin/common/library.h42
-rw-r--r--SoftHSMv2/src/bin/dump/Makefile.am24
-rw-r--r--SoftHSMv2/src/bin/dump/common.h506
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-db.118
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp968
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-file.118
-rw-r--r--SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp537
-rw-r--r--SoftHSMv2/src/bin/dump/tables.h554
-rw-r--r--SoftHSMv2/src/bin/keyconv/Makefile.am26
-rw-r--r--SoftHSMv2/src/bin/keyconv/base64.c311
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp227
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp261
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.163
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp351
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h134
-rw-r--r--SoftHSMv2/src/bin/migrate/Makefile.am20
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.167
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp798
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.h68
-rw-r--r--SoftHSMv2/src/bin/util/Makefile.am40
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp704
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.h142
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp790
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.h142
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.1259
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.cpp1318
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.h77
-rw-r--r--SoftHSMv2/src/bin/win32/getopt.cpp520
-rw-r--r--SoftHSMv2/src/bin/win32/getopt.h101
-rw-r--r--SoftHSMv2/src/bin/win32/getpassphase.cpp35
37 files changed, 9940 insertions, 0 deletions
diff --git a/SoftHSMv2/src/bin/Makefile.am b/SoftHSMv2/src/bin/Makefile.am
new file mode 100644
index 0000000..354c272
--- /dev/null
+++ b/SoftHSMv2/src/bin/Makefile.am
@@ -0,0 +1,10 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+SUBDIRS = common keyconv util dump
+
+if BUILD_MIGRATE
+SUBDIRS += migrate
+endif
+
+EXTRA_DIST = $(srcdir)/win32/*.cpp \
+ $(srcdir)/win32/*.h
diff --git a/SoftHSMv2/src/bin/common/Makefile.am b/SoftHSMv2/src/bin/common/Makefile.am
new file mode 100644
index 0000000..e3a2b24
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/Makefile.am
@@ -0,0 +1,3 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/bin/common/findslot.cpp b/SoftHSMv2/src/bin/common/findslot.cpp
new file mode 100644
index 0000000..5936db7
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/findslot.cpp
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2016 SURFnet bv
+ * 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.
+ */
+
+/*****************************************************************************
+ findslot.cpp
+
+ Helper function to find the slot
+ *****************************************************************************/
+
+#include <config.h>
+#include "findslot.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern CK_FUNCTION_LIST_PTR p11;
+
+// Find the slot/token
+int findSlot(char* slot, char* serial, char* token, bool freeToken, CK_SLOT_ID& slotID)
+{
+ if (slot != NULL)
+ {
+ int slotNumber = atoi(slot);
+ if (slotNumber < 0)
+ {
+ fprintf(stderr, "ERROR: The slot number is negative.\n");
+ return 1;
+ }
+
+ slotID = slotNumber;
+ return 0;
+ }
+
+ if (serial == NULL && token == NULL && freeToken == false)
+ {
+ fprintf(stderr, "ERROR: A slot/token must be supplied. "
+ "Use --slot <number>, --serial <serial>, "
+ "--token <label>, or --free\n");
+ return 1;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedSerial[16];
+ CK_UTF8CHAR paddedToken[32];
+ if (serial != NULL)
+ {
+ size_t inSize = strlen(serial);
+ size_t outSize = sizeof(paddedSerial);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --serial is too long.\n");
+ return 1;
+ }
+ memset(paddedSerial, ' ', outSize);
+ memcpy(paddedSerial, serial, inSize);
+ }
+ if (token != NULL)
+ {
+ size_t inSize = strlen(token);
+ size_t outSize = sizeof(paddedToken);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --token is too long.\n");
+ return 1;
+ }
+ memset(paddedToken, ' ', outSize);
+ memcpy(paddedToken, token, inSize);
+ }
+
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (pSlotList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ size_t counter = 0;
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ free(pSlotList);
+ return 1;
+ }
+
+ if (freeToken)
+ {
+ if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0)
+ {
+ printf("Slot %lu has a free/uninitialized token.\n", pSlotList[i]);
+ slotID = pSlotList[i];
+ free(pSlotList);
+ return 0;
+ }
+ }
+ else
+ {
+ if (serial != NULL && token == NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0)
+ {
+ printf("Found slot %lu with matching serial.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial == NULL && token != NULL &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial != NULL && token != NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0 &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching serial and token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ }
+ }
+
+ free(pSlotList);
+
+ if (counter == 1) return 0;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching slots/tokens.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a slot/token using --serial, --token, or --free.\n");
+ return 1;
+}
+
+// Find the slot/token
+int findSlot(char* slot, char* serial, char* token, CK_SLOT_ID& slotID)
+{
+ if (slot != NULL)
+ {
+ int slotNumber = atoi(slot);
+ if (slotNumber < 0)
+ {
+ fprintf(stderr, "ERROR: The slot number is negative.\n");
+ return 1;
+ }
+
+ slotID = slotNumber;
+ return 0;
+ }
+
+ if (serial == NULL && token == NULL)
+ {
+ fprintf(stderr, "ERROR: A slot/token must be supplied. "
+ "Use --slot <number>, --serial <serial>, "
+ "or --token <label>\n");
+ return 1;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedSerial[16];
+ CK_UTF8CHAR paddedToken[32];
+ if (serial != NULL)
+ {
+ size_t inSize = strlen(serial);
+ size_t outSize = sizeof(paddedSerial);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --serial is too long.\n");
+ return 1;
+ }
+ memset(paddedSerial, ' ', outSize);
+ memcpy(paddedSerial, serial, inSize);
+ }
+ if (token != NULL)
+ {
+ size_t inSize = strlen(token);
+ size_t outSize = sizeof(paddedToken);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --token is too long.\n");
+ return 1;
+ }
+ memset(paddedToken, ' ', outSize);
+ memcpy(paddedToken, token, inSize);
+ }
+
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (pSlotList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ size_t counter = 0;
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ free(pSlotList);
+ return 1;
+ }
+
+ if (serial != NULL && token == NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0)
+ {
+ printf("Found slot %lu with matching serial.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial == NULL && token != NULL &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ if (serial != NULL && token != NULL &&
+ memcmp(tokenInfo.serialNumber, paddedSerial, sizeof(paddedSerial)) == 0 &&
+ memcmp(tokenInfo.label, paddedToken, sizeof(paddedToken)) == 0)
+ {
+ printf("Found slot %lu with matching serial and token label.\n",
+ pSlotList[i]);
+ slotID = pSlotList[i];
+ counter++;
+ }
+ }
+
+ free(pSlotList);
+
+ if (counter == 1) return 0;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching slots/tokens.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a slot/token using --serial, or --token\n");
+ return 1;
+}
+
+// Find the slot/token
+int findSlot(CK_TOKEN_INFO tokenInfo, CK_SLOT_ID& slotID)
+{
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_TRUE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (pSlotList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ size_t counter = 0;
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_TOKEN_INFO currentTokenInfo;
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &currentTokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ free(pSlotList);
+ return 1;
+ }
+
+ if (memcmp(currentTokenInfo.serialNumber, tokenInfo.serialNumber, sizeof(tokenInfo.serialNumber)) == 0 &&
+ memcmp(currentTokenInfo.label, tokenInfo.label, sizeof(tokenInfo.label)) == 0)
+ {
+ slotID = pSlotList[i];
+ counter++;
+ }
+ }
+
+ free(pSlotList);
+
+ if (counter == 1) return 0;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching slots/tokens.\n");
+ return 1;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a slot/token using --serial, or --token\n");
+ return 1;
+}
diff --git a/SoftHSMv2/src/bin/common/findslot.h b/SoftHSMv2/src/bin/common/findslot.h
new file mode 100644
index 0000000..f8a7ba6
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/findslot.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 SURFnet bv
+ * 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.
+ */
+
+/*****************************************************************************
+ findslot.h
+
+ Helper function to find the slot number
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_FINDSLOT_H
+#define _SOFTHSM_V2_BIN_FINDSLOT_H
+
+#include "cryptoki.h"
+
+int findSlot(char* slot, char* serial, char* token, bool freeToken, CK_SLOT_ID& slotID);
+int findSlot(char* slot, char* serial, char* token, CK_SLOT_ID& slotID);
+int findSlot(CK_TOKEN_INFO tokenInfo, CK_SLOT_ID& slotID);
+
+#endif // !_SOFTHSM_V2_BIN_FINDSLOT_H
diff --git a/SoftHSMv2/src/bin/common/getpw.cpp b/SoftHSMv2/src/bin/common/getpw.cpp
new file mode 100644
index 0000000..938abd5
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/getpw.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ getpw.cpp
+
+ Helper function to get a password from the user
+ *****************************************************************************/
+
+#include <config.h>
+#include "getpw.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <termios.h>
+#include <signal.h>
+#endif
+
+#ifndef _WIN32
+// Remember the signal number
+static volatile sig_atomic_t signo;
+
+void sighandler(int s)
+{
+ signo = s;
+}
+#endif
+
+int getpin(const char* prompt, char* buffer, size_t size)
+{
+ if (prompt == NULL || buffer == NULL || size < 1)
+ return -1;
+
+ printf("%s", prompt);
+
+#ifdef _WIN32
+ HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode;
+
+ // Save current console mode
+ if (!GetConsoleMode(hstdin, &mode))
+ return -1;
+
+ // Update the console mode
+ if (hstdin == INVALID_HANDLE_VALUE || !(SetConsoleMode(hstdin, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)))
+ return -1;
+#else
+ struct termios new_attr, old_attr;
+
+ // Get current terminal attributes
+ if (tcgetattr(STDIN_FILENO, &old_attr) < 0)
+ return -1;
+
+ // Save the mode flags
+ new_attr = old_attr;
+
+ // Update the mode flags
+ new_attr.c_lflag &= ~ICANON;
+ new_attr.c_lflag &= ~ECHO;
+
+ // Handle the SIGINT signal
+ signo = 0;
+ struct sigaction osa, sa;
+ sigaction(SIGINT, NULL, &osa);
+ if (osa.sa_handler != SIG_IGN)
+ {
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = sighandler;
+ sigaction(SIGINT, &sa, &osa);
+ }
+
+ // Set the new terminal attributes
+ if (tcsetattr(STDIN_FILENO, 0, &new_attr) < 0)
+ return -1;
+#endif
+
+ size_t nread = 0;
+ int ch = 0;
+ while ((ch = getchar()) != '\n' && ch != EOF)
+ {
+ // Check buffer size
+ if ((nread+2) > size)
+ continue;
+
+ putchar('*');
+ buffer[nread] = ch;
+ nread++;
+ }
+
+ putchar('\n');
+ buffer[nread] = '\0';
+
+#ifdef _WIN32
+ // Restore the console mode
+ if (!SetConsoleMode(hstdin, mode))
+ return -1;
+#else
+ // Restore terminal
+ if (tcsetattr(STDIN_FILENO, 0, &old_attr) < 0)
+ return -1;
+
+ // Restore the signal
+ sigaction(SIGINT, &osa, NULL);
+ if (signo)
+ raise(signo);
+#endif
+
+ return nread;
+}
+
+// Get a password from the user
+int getPW(char* pin, char* newPIN, CK_ULONG userType)
+{
+ char password1[MAX_PIN_LEN+1];
+ char password2[MAX_PIN_LEN+1];
+ size_t size = MAX_PIN_LEN+1;
+ int length = 0;
+
+ // Check if the user has provided a password
+ if (pin)
+ {
+ length = strlen(pin);
+ // Save the PIN if it has the correct length
+ if (length >= MIN_PIN_LEN && length <= MAX_PIN_LEN)
+ memcpy(password1, pin, length+1);
+ }
+
+ while (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
+ {
+ if (userType == CKU_SO)
+ {
+ printf("=== SO PIN (%i-%i characters) ===\n",
+ MIN_PIN_LEN, MAX_PIN_LEN);
+ length = getpin("Please enter SO PIN: ",
+ password1, size);
+ }
+ else
+ {
+ printf("=== User PIN (%i-%i characters) ===\n",
+ MIN_PIN_LEN, MAX_PIN_LEN);
+ length = getpin("Please enter user PIN: ",
+ password1, size);
+ }
+
+ if (length < 0)
+ return 1;
+ if (length < MIN_PIN_LEN || length > MAX_PIN_LEN)
+ {
+ fprintf(stderr, "ERROR: The length of the PIN is out of range.\n");
+ length = 0;
+ continue;
+ }
+
+ if (userType == CKU_SO)
+ {
+ length = getpin("Please reenter SO PIN: ",
+ password2, size);
+ }
+ else
+ {
+ length = getpin("Please reenter user PIN: ",
+ password2, size);
+ }
+
+ if (length < 0)
+ return 1;
+ if (strcmp(password1, password2))
+ {
+ fprintf(stderr, "ERROR: The entered PINs are not equal.\n");
+ length = 0;
+ continue;
+ }
+ }
+
+ memcpy(newPIN, password1, length+1);
+ return 0;
+}
diff --git a/SoftHSMv2/src/bin/common/getpw.h b/SoftHSMv2/src/bin/common/getpw.h
new file mode 100644
index 0000000..1ca15a5
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/getpw.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ getpw.h
+
+ Helper function to get a password from the user
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_GETPW_H
+#define _SOFTHSM_V2_BIN_GETPW_H
+
+#include "cryptoki.h"
+
+int getPW(char* pin, char* newPIN, CK_ULONG userType);
+
+#endif // !_SOFTHSM_V2_BIN_GETPW_H
diff --git a/SoftHSMv2/src/bin/common/library.cpp b/SoftHSMv2/src/bin/common/library.cpp
new file mode 100644
index 0000000..af0dd93
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/library.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ library.cpp
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#include <config.h>
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_DLOPEN)
+#include <dlfcn.h>
+#endif
+
+// Load the PKCS#11 library
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle,
+ char **pErrMsg)
+{
+ CK_C_GetFunctionList pGetFunctionList = NULL;
+
+#if defined(HAVE_LOADLIBRARY)
+ HINSTANCE hDLL = NULL;
+ DWORD dw = NULL;
+ static char errMsg[100];
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ hDLL = LoadLibraryA(module);
+ }
+ else
+ {
+ hDLL = LoadLibraryA(DEFAULT_PKCS11_LIB);
+ }
+
+ if (hDLL == NULL)
+ {
+ // Failed to load the PKCS #11 library
+ dw = GetLastError();
+ snprintf((char*)errMsg, sizeof(errMsg), "LoadLibraryA failed: 0x%08X", dw);
+ *pErrMsg = errMsg;
+ return NULL;
+ }
+ else
+ {
+ *pErrMsg = NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hDLL, "C_GetFunctionList");
+ if (pGetFunctionList == NULL)
+ {
+ dw = GetLastError();
+ snprintf((char*)errMsg, sizeof(errMsg), "getProcAddress failed: 0x%08X", dw);
+ *pErrMsg = errMsg;
+ FreeLibrary(hDLL);
+ return NULL;
+ }
+
+ // Store the handle so we can FreeLibrary it later
+ *moduleHandle = hDLL;
+
+#elif defined(HAVE_DLOPEN)
+ void* pDynLib = NULL;
+
+ // Load PKCS #11 library
+ if (module)
+ {
+ pDynLib = dlopen(module, RTLD_NOW | RTLD_LOCAL);
+ }
+ else
+ {
+ pDynLib = dlopen(DEFAULT_PKCS11_LIB, RTLD_NOW | RTLD_LOCAL);
+ }
+
+ *pErrMsg = dlerror();
+ if (pDynLib == NULL || *pErrMsg != NULL)
+ {
+ if (pDynLib != NULL) dlclose(pDynLib);
+
+ // Failed to load the PKCS #11 library
+ return NULL;
+ }
+
+ // Retrieve the entry point for C_GetFunctionList
+ pGetFunctionList = (CK_C_GetFunctionList) dlsym(pDynLib, "C_GetFunctionList");
+
+ // Store the handle so we can dlclose it later
+ *pErrMsg = dlerror();
+ if (*pErrMsg != NULL)
+ {
+ dlclose(pDynLib);
+
+ // An error occured during dlsym()
+ return NULL;
+ }
+
+ *moduleHandle = pDynLib;
+#else
+ fprintf(stderr, "ERROR: Not compiled with library support.\n");
+
+ return NULL;
+#endif
+
+ return pGetFunctionList;
+}
+
+void unloadLibrary(void* moduleHandle)
+{
+ if (moduleHandle)
+ {
+#if defined(HAVE_LOADLIBRARY)
+ FreeLibrary((HMODULE) moduleHandle);
+#elif defined(HAVE_DLOPEN)
+ dlclose(moduleHandle);
+#endif
+ }
+}
diff --git a/SoftHSMv2/src/bin/common/library.h b/SoftHSMv2/src/bin/common/library.h
new file mode 100644
index 0000000..6c6b3e4
--- /dev/null
+++ b/SoftHSMv2/src/bin/common/library.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ library.h
+
+ Support function for handling PKCS#11 libraries
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BIN_LIBRARY_H
+#define _SOFTHSM_V2_BIN_LIBRARY_H
+
+#include "cryptoki.h"
+
+CK_C_GetFunctionList loadLibrary(char* module, void** moduleHandle,
+ char **pErrMsg);
+void unloadLibrary(void* moduleHandle);
+
+#endif // !_SOFTHSM_V2_BIN_LIBRARY_H
diff --git a/SoftHSMv2/src/bin/dump/Makefile.am b/SoftHSMv2/src/bin/dump/Makefile.am
new file mode 100644
index 0000000..c70d6f6
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/Makefile.am
@@ -0,0 +1,24 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib \
+ -I$(srcdir)/../../lib/object_store \
+ -I$(srcdir)/../../lib/pkcs11 \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm2-dump-file.1
+
+bin_PROGRAMS = softhsm2-dump-file
+
+if BUILD_OBJECTSTORE_BACKEND_DB
+dist_man_MANS += softhsm2-dump-db.1
+bin_PROGRAMS += softhsm2-dump-db
+endif
+
+softhsm2_dump_file_SOURCES = softhsm2-dump-file.cpp
+
+softhsm2_dump_db_SOURCES = softhsm2-dump-db.cpp
+
+softhsm2_dump_db_LDADD = @SQLITE3_LIBS@ @YIELD_LIB@
+
+EXTRA_DIST = $(srcdir)/*.h \
+ softhsm2-dump-db.1
diff --git a/SoftHSMv2/src/bin/dump/common.h b/SoftHSMv2/src/bin/dump/common.h
new file mode 100644
index 0000000..d38b924
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/common.h
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ common.h
+
+ Common definitions for SoftHSMv2 dump.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_COMMON_H
+#define _SOFTHSM_V2_COMMON_H
+
+#include <config.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <map>
+#include <set>
+#include <string>
+#include <stdexcept>
+#include <vector>
+#include "tables.h"
+
+// Table of attribute types
+std::map<unsigned long, std::string> CKA_table;
+
+// Dump an attribute type
+void dumpCKA(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKA_table.empty())
+ {
+ fill_CKA_table(CKA_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKA_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKA_VENDOR_DEFINED)
+ {
+ cka &= ~CKA_VENDOR_DEFINED;
+ printf("CKA_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of mechanism types
+std::map<unsigned long, std::string> CKM_table;
+
+// Dump a mechanism type
+void dumpCKM(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKM_table.empty())
+ {
+ fill_CKM_table(CKM_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKM_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKM_VENDOR_DEFINED)
+ {
+ cka &= ~CKM_VENDOR_DEFINED;
+ printf("CKM_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of object classes
+std::map<unsigned long, std::string> CKO_table;
+
+// Dump a object class
+void dumpCKO(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKO_table.empty())
+ {
+ fill_CKO_table(CKO_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKO_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKO_VENDOR_DEFINED)
+ {
+ cka &= ~CKO_VENDOR_DEFINED;
+ printf("CKO_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of hw feature types
+std::map<unsigned long, std::string> CKH_table;
+
+// Dump a hw feature type
+void dumpCKH(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKH_table.empty())
+ {
+ fill_CKH_table(CKH_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKH_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKH_VENDOR_DEFINED)
+ {
+ cka &= ~CKH_VENDOR_DEFINED;
+ printf("CKH_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of key types
+std::map<unsigned long, std::string> CKK_table;
+
+// Dump a key type
+void dumpCKK(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKK_table.empty())
+ {
+ fill_CKK_table(CKK_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKK_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKK_VENDOR_DEFINED)
+ {
+ cka &= ~CKK_VENDOR_DEFINED;
+ printf("CKK_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Table of certificate types
+std::map<unsigned long, std::string> CKC_table;
+
+// Dump a certificate type
+void dumpCKC(unsigned long cka, int size)
+{
+ // Lazy fill
+ if (CKC_table.empty())
+ {
+ fill_CKC_table(CKC_table);
+ }
+ std::string msg;
+ try
+ {
+ msg = CKC_table.at(cka);
+ printf("%.*s", size, msg.c_str());
+ }
+ catch (const std::out_of_range&)
+ {
+ if (cka & CKC_VENDOR_DEFINED)
+ {
+ cka &= ~CKC_VENDOR_DEFINED;
+ printf("CKC_VENDOR_DEFINED | 0x%lx", cka);
+ }
+ else
+ {
+ printf("unknown 0x%lx", cka);
+ }
+ }
+}
+
+// Dump a PKCS#11 integer type
+void dumpCKx(uint64_t cka, uint64_t value, int size)
+{
+ if ((uint32_t)value == (uint32_t)~0)
+ {
+ printf("CK_UNAVAILABLE_INFORMATION");
+ return;
+ }
+
+ switch ((unsigned long) cka)
+ {
+ case CKA_CLASS:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow object class");
+ break;
+ }
+ dumpCKO((unsigned long) value, size);
+ break;
+ case CKA_CERTIFICATE_TYPE:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow certificate type");
+ break;
+ }
+ dumpCKC((unsigned long) value, size);
+ break;
+ case CKA_KEY_TYPE:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow key type");
+ break;
+ }
+ dumpCKK((unsigned long) value, size);
+ break;
+ case CKA_KEY_GEN_MECHANISM:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow mechanism type");
+ break;
+ }
+ dumpCKM((unsigned long) value, size);
+ break;
+ case CKA_HW_FEATURE_TYPE:
+ if ((uint64_t)((uint32_t)value) != value)
+ {
+ printf("overflow hw feature type");
+ break;
+ }
+ dumpCKH((unsigned long) value, size);
+ break;
+ default:
+ printf("CK_ULONG %lu(0x%lx)",
+ (unsigned long) value,
+ (unsigned long) value);
+ break;
+ }
+}
+
+// Dump a boolean (in fact unsigned 8 bit long) value, true is 0xff
+void dumpBool(uint8_t value, bool inArray = false)
+{
+ printf("%02hhx %s", value, inArray ? " " : "");
+ switch (value)
+ {
+ case 0:
+ printf("FALSE");
+ break;
+ case 0xff:
+ printf("TRUE");
+ break;
+ default:
+ printf("(invalid) TRUE");
+ break;
+ }
+}
+
+// Dump a boolean (in fact unsigned 8 bit long) value, true is 1
+void dumpBool1(uint8_t value, bool inArray = false)
+{
+ printf("%02hhx %s", value, inArray ? " " : "");
+ switch (value)
+ {
+ case 0:
+ printf("FALSE");
+ break;
+ case 1:
+ printf("TRUE");
+ break;
+ default:
+ printf("(invalid) TRUE");
+ break;
+ }
+}
+
+// Dump an unsigned 64 bit long value
+void dumpULong(uint64_t value, bool inArray = false)
+{
+ for (int i = 56; i >= 0; i -= 8)
+ {
+ uint8_t v;
+ v = (value >> i) & 0xff;
+ printf("%02hhx ", v);
+ }
+ if (inArray)
+ {
+ printf(" ");
+ }
+}
+
+// Dump an unsigned 32 bit long value
+void dumpU32(uint32_t value, bool inArray = false)
+{
+ for (int i = 24; i >= 0; i -= 8)
+ {
+ uint8_t v;
+ v = (value >> i) & 0xff;
+ printf("%02hhx ", v);
+ }
+ printf(" ");
+ if (inArray)
+ {
+ printf(" ");
+ }
+}
+
+// Dump a byte string (aka uint8_t vector) value
+void dumpBytes(const std::vector<uint8_t>& value, bool inArray = false)
+{
+ size_t len = value.size();
+ size_t i = 0;
+ while (i + 8 <= len)
+ {
+ for (size_t j = 0; j < 8; j++)
+ {
+ printf("%02hhx ", value[i + j]);
+ }
+ if (inArray)
+ {
+ printf(" ");
+ }
+ printf("<");
+ for (size_t j = 0; j < 8; j++)
+ {
+ uint8_t c = value[i + j];
+ if (isgraph((int) c) == 0)
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("%c", (int) c);
+ }
+ }
+ printf(">\n");
+ i += 8;
+ }
+ len -= i;
+ if (len == 0)
+ {
+ return;
+ }
+
+ for (size_t j = 0; j < len; j++)
+ {
+ printf("%02hhx ", value[i + j]);
+ }
+ for (size_t j = len; j < 8; j++)
+ {
+ printf(" ");
+ }
+ if (inArray)
+ {
+ printf(" ");
+ }
+ printf("<");
+ for (size_t j = 0; j < len; j++)
+ {
+ uint8_t c = value[i + j];
+ if (isgraph((int) c) == 0)
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("%c", (int) c);
+ }
+ }
+ for (size_t j =len; j < 8; j++)
+ {
+ printf(" ");
+ }
+ printf(">\n");
+}
+
+// Attribute (in an array) template
+template<typename T, typename K, typename I>
+class AttributeTK
+{
+public:
+ T type;
+ K kind;
+
+ uint8_t boolValue;
+ I ulongValue;
+ std::vector<uint8_t> bytestrValue;
+ std::set<I> mechSetValue;
+
+ // Dump an array (in fact an Attribute vector) value
+ void dumpType() const;
+ void dumpKind() const;
+ void dumpBoolValue() const;
+ void dumpULongValue(I value) const;
+ bool isBoolean() const;
+ bool isInteger() const;
+ bool isBinary() const;
+ bool isMechSet() const;
+ void dump() const {
+ dumpType();
+ if ((sizeof(type) > 4) &&
+ ((uint64_t)((uint32_t)type) != type))
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 47);
+ printf("\n");
+ }
+
+ dumpKind();
+ if (isBoolean())
+ {
+ printf("boolean attribute\n");
+ dumpBoolValue();
+ printf("\n");
+ }
+ else if (isInteger())
+ {
+ printf("unsigned long attribute\n");
+ dumpULongValue(ulongValue);
+ dumpCKx(type, ulongValue, 47);
+ printf("\n");
+ }
+ else if (isBinary())
+ {
+ printf("byte string attribute\n");
+ I size = bytestrValue.size();
+ dumpULongValue(size);
+ printf("(length %lu)\n", (unsigned long) size);
+ dumpBytes(bytestrValue, true);
+ }
+ else if (isMechSet())
+ {
+ printf("mechanism set attribute\n");
+ I size = mechSetValue.size();
+ dumpULongValue(size);
+ printf("(length %lu)\n", (unsigned long) size);
+ for (typename std::set<I>::const_iterator i = mechSetValue.begin(); i != mechSetValue.end(); ++i)
+ {
+ dumpULongValue(*i);
+ dumpCKM(*i, 47);
+ printf("\n");
+ }
+ }
+ else
+ {
+ printf("unknown attribute format\n");
+ }
+ }
+};
+
+#endif // !_SOFTHSM_V2_COMMON_H
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-db.1 b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.1
new file mode 100644
index 0000000..00f455b
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.1
@@ -0,0 +1,18 @@
+.TH SOFTHSM2-DUMP-DB 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-dump-db \- SoftHSM database dump
+.SH SYNOPSIS
+.PP
+.B softhsm2-dump-db
+.I path
+.SH DESCRIPTION
+.B softhsm2-dump
+is a tool that can dump SoftHSM v2 database for debugging purposes.
+.LP
+.SH OPTIONS
+.TP
+.B \fIpath\fR
+The SoftHSM v2 database file that is going to be dumped.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp
new file mode 100644
index 0000000..f55a9db
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-db.cpp
@@ -0,0 +1,968 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-dump-db.cpp
+
+ This program can be used for dumping SoftHSM v2 database.
+ *****************************************************************************/
+
+#include <config.h>
+
+#include <sched.h>
+#include <sqlite3.h>
+#include <string.h>
+
+#include "common.h"
+
+// Attribute types in database arrays
+enum AttributeKind
+{
+ akUnknown,
+ akBoolean,
+ akInteger,
+ akBinary,
+ akArray
+};
+
+// Attribute specialization
+typedef AttributeTK<CK_ATTRIBUTE_TYPE, AttributeKind, unsigned long> Attribute;
+
+template<>
+bool Attribute::isBoolean() const
+{
+ return kind == akBoolean;
+}
+
+template<>
+bool Attribute::isInteger() const
+{
+ return kind == akInteger;
+}
+
+template<>
+bool Attribute::isBinary() const
+{
+ return kind == akBinary;
+}
+
+template<>
+bool Attribute::isMechSet() const
+{
+ // Mechanism sets are stored as binary in the database
+ return false;
+}
+
+template<>
+void Attribute::dumpType() const
+{
+ if (sizeof(type) == 4)
+ {
+ dumpU32((uint32_t)type, true);
+ }
+ else
+ {
+ dumpULong(type, true);
+ }
+}
+
+template<>
+void Attribute::dumpKind() const
+{
+ dumpU32((uint32_t) kind, true);
+}
+
+template<>
+void Attribute::dumpBoolValue() const
+{
+ dumpBool1(boolValue, true);
+}
+
+template<>
+void Attribute::dumpULongValue(unsigned long value) const
+{
+ if (sizeof(unsigned long) == 4)
+ {
+ dumpU32(value, true);
+ }
+ else
+ {
+ dumpULong(value, true);
+ }
+}
+
+// dumpArray specialization
+typedef std::vector<Attribute> va_type;
+
+void dumpArray(const va_type& value)
+{
+ for (va_type::const_iterator attr = value.begin(); attr != value.end(); ++attr)
+ attr->dump();
+}
+
+// Get a boolean (in fact unsigned 8 bit long) value
+bool getBool(sqlite3* db, long long oid, long long id, uint64_t& type, uint8_t& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_boolean where object_id=? and id=?;";
+
+ value = 0;
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find boolean attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read boolean attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ value = sqlite3_column_int(sql, 1);
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Get an unsigned 64 bit long value
+bool getULong(sqlite3* db, long long oid, long long id, uint64_t& type, uint64_t& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_integer where object_id=? and id=?;";
+
+ value = 0ULL;
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find integer attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read integer attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ value = sqlite3_column_int64(sql, 1);
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Get a byte string (aka uint8_t vector) value
+bool getBytes(sqlite3* db, long long oid, long long id, uint64_t& type, std::vector<uint8_t>& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_binary where object_id=? and id=?;";
+ size_t len;
+ const uint8_t* val;
+
+ value.clear();
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find binary attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read binary attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ len = sqlite3_column_bytes(sql, 1);
+ val = (const uint8_t*) sqlite3_column_blob(sql, 1);
+ for (size_t i = 0; i < len; ++i)
+ {
+ value.push_back(val[i]);
+ }
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Get an array (aka Attribute vector) value
+bool getArray(sqlite3* db, long long oid, long long id, uint64_t& type, std::vector<Attribute>& value)
+{
+ int rv;
+ sqlite3_stmt* sql = NULL;
+ std::string command = "select type,value from attribute_array where object_id=? and id=?;";
+ size_t len;
+ const uint8_t* val;
+
+ value.clear();
+
+ rv = sqlite3_prepare_v2(db, command.c_str(), -1, &sql, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr,
+ "can't find array attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ rv = sqlite3_bind_int64(sql, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ sqlite3_bind_int64(sql, 2, id);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the attribute id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ while ((rv = sqlite3_step(sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr,
+ "can't read array attribute id=%lld object=%lld: %d(%s)\n",
+ id, oid, rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sql);
+ return false;
+ }
+ type = sqlite3_column_int64(sql, 0);
+ len = sqlite3_column_bytes(sql, 1);
+ val = (const uint8_t*) sqlite3_column_blob(sql, 1);
+
+// CK_ATTRIBUTE_TYPE type, AttributeKind kind
+// bool -> int, integer -> unsigned long, binary -> unsigned long + vector
+
+ for (size_t pos = 0; pos < len; )
+ {
+ // finished?
+ if (pos == len) break;
+
+ Attribute attr;
+
+ if (pos + sizeof(attr.type) > len)
+ {
+ fprintf(stderr, "overflow array item type\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.type, val + pos, sizeof(attr.type));
+ pos += sizeof(attr.type);
+
+ if (pos + sizeof(attr.kind) > len)
+ {
+ fprintf(stderr, "overflow array item kind\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.kind, val + pos, sizeof(attr.kind));
+ pos += sizeof(attr.kind);
+
+ if (attr.kind == akBoolean)
+ {
+ if (pos + sizeof(attr.boolValue) > len)
+ {
+ fprintf(stderr, "overflow array boolean item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.boolValue, val + pos, sizeof(attr.boolValue));
+ pos += sizeof(attr.boolValue);
+ }
+ else if (attr.kind == akInteger)
+ {
+ if (pos + sizeof(attr.ulongValue) > len)
+ {
+ fprintf(stderr, "overflow array integer item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&attr.ulongValue, val + pos, sizeof(attr.ulongValue));
+ pos += sizeof(attr.ulongValue);
+ }
+ else if (attr.kind == akBinary)
+ {
+ unsigned long size;
+ if (pos + sizeof(size) > len)
+ {
+ fprintf(stderr, "overflow array binary item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ memcpy(&size, val + pos, sizeof(size));
+ pos += sizeof(size);
+
+ if (pos + size > len)
+ {
+ fprintf(stderr, "overflow array binary item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+ attr.bytestrValue.resize(size);
+ for (unsigned long i = 0; i < size; ++i)
+ {
+ attr.bytestrValue[i] = val[pos + i];
+ }
+ pos += size;
+ }
+ else
+ {
+ fprintf(stderr, "unknown array item\n");
+ sqlite3_finalize(sql);
+ return false;
+ }
+
+ value.push_back(attr);
+ }
+ sqlite3_finalize(sql);
+
+ return true;
+}
+
+// Dump boolean attributes of an object
+void dump_booleans(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_boolean where object_id=?;";
+ std::string commandid = "select id from attribute_boolean where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu boolean attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ uint8_t value;
+ if (!getBool(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+
+ dumpBool1(value);
+ printf("\n");
+ }
+}
+
+// Dump integer attributes of an object
+void dump_integers(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_integer where object_id=?;";
+ std::string commandid = "select id from attribute_integer where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu integer attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ uint64_t value;
+ if (!getULong(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+ dumpULong(value);
+ dumpCKx(type, value, 48);
+ printf("\n");
+ }
+}
+
+// Dump binary attributes of an object
+void dump_binaries(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_binary where object_id=?;";
+ std::string commandid = "select id from attribute_binary where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu binary attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ std::vector<uint8_t> value;
+ if (!getBytes(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+ dumpULong((uint64_t) value.size());
+ printf("(length %lu)\n", (unsigned long) value.size());
+ dumpBytes(value);
+ }
+}
+
+// Dump array attributes of an object
+void dump_arrays(sqlite3* db, long long oid)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from attribute_array where object_id=?;";
+ std::string commandid = "select id from attribute_array where object_id=?;";
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlcnt, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ if (count == 0)
+ return;
+
+ printf("%lu array attributes for object %lld\n", count, oid);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ rv = sqlite3_bind_int64(sqlid, 1, oid);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't bind the object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long id = sqlite3_column_int64(sqlid, 0);
+
+ uint64_t type;
+ std::vector<Attribute> value;
+ if (!getArray(db, oid, id, type, value))
+ {
+ return;
+ }
+ dumpULong(type);
+ if ((uint64_t)((uint32_t)type) != type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) type, 48);
+ printf("\n");
+ }
+ dumpULong((uint64_t) value.size());
+ printf("(length %lu)\n", (unsigned long) value.size());
+ dumpArray(value);
+ }
+}
+
+// Dump an object
+void dump_object(sqlite3* db, long long oid)
+{
+ printf("dump object id=%lld\n", oid);
+ dump_booleans(db, oid);
+ dump_integers(db, oid);
+ dump_binaries(db, oid);
+ dump_arrays(db, oid);
+}
+
+// Core function
+void dump(sqlite3* db)
+{
+ int rv;
+ unsigned long count;
+ sqlite3_stmt* sqlcnt = NULL;
+ sqlite3_stmt* sqlid = NULL;
+ std::string commandcnt = "select count(id) from object;";
+ std::string commandid = "select id from object;";
+
+ rv = sqlite3_prepare_v2(db, commandcnt.c_str(), -1, &sqlcnt, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ while ((rv = sqlite3_step(sqlcnt)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlcnt);
+ return;
+ }
+ count = sqlite3_column_int(sqlcnt, 0);
+ sqlite3_finalize(sqlcnt);
+ printf("%lu objects\n", count);
+
+ rv = sqlite3_prepare_v2(db, commandid.c_str(), -1, &sqlid, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't count the object table: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ while (count-- > 0) {
+ while ((rv = sqlite3_step(sqlid)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+ if (rv != SQLITE_ROW)
+ {
+ if (rv != SQLITE_DONE)
+ {
+ fprintf(stderr,
+ "can't get next object id: %d(%s)\n",
+ rv, sqlite3_errmsg(db));
+ }
+ sqlite3_finalize(sqlid);
+ return;
+ }
+ long long oid = sqlite3_column_int64(sqlid, 0);
+ dump_object(db, oid);
+ }
+}
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM dump tool. From SoftHSM v2 database.\n");
+ printf("Usage: softhsm2-dump-db path\n");
+}
+
+// Check the existence of a table
+void check_table_exist(sqlite3* db, std::string name)
+{
+ int rv;
+ std::string command = "select count(id) from " + name + ";";
+
+ rv = sqlite3_exec(db, command.c_str(), NULL, NULL, NULL);
+ if (rv != SQLITE_OK)
+ {
+ fprintf(stderr, "can't find '%s' table\n", name.c_str());
+ sqlite3_close(db);
+ exit(0);
+ }
+}
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int rv;
+ sqlite3* db = NULL;
+
+ if (argc != 2)
+ {
+ usage();
+ exit(0);
+ }
+
+ rv = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, NULL);
+ if (rv != SQLITE_OK)
+ {
+ if (db == NULL)
+ {
+ fprintf(stderr,
+ "can't open database file %s\n",
+ argv[1]);
+ }
+ else
+ {
+ fprintf(stderr,
+ "can't open database file %s: %d(%s)\n",
+ argv[1],
+ rv,
+ sqlite3_errmsg(db));
+ }
+ sqlite3_close(db);
+ exit(0);
+ }
+
+ // No user version to check
+
+ check_table_exist(db, "object");
+ check_table_exist(db, "attribute_boolean");
+ check_table_exist(db, "attribute_integer");
+ check_table_exist(db, "attribute_binary");
+ check_table_exist(db, "attribute_array");
+
+ printf("Dump of object file \"%s\"\n", argv[1]);
+ dump(db);
+ sqlite3_close(db);
+ exit(1);
+}
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-file.1 b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.1
new file mode 100644
index 0000000..5167f70
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.1
@@ -0,0 +1,18 @@
+.TH SOFTHSM2-DUMP-FILE 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-dump-file \- SoftHSM object file dump
+.SH SYNOPSIS
+.PP
+.B softhsm2-dump-file
+.I path
+.SH DESCRIPTION
+.B softhsm2-dump-file
+is a tool that can dump SoftHSM v2 object file for debugging purposes.
+.LP
+.SH OPTIONS
+.TP
+.B \fIpath\fR
+The SoftHSM v2 object file that is going to be dumped.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
diff --git a/SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp
new file mode 100644
index 0000000..994f67e
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/softhsm2-dump-file.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-dump-file.cpp
+
+ This program can be used for dumping SoftHSM v2 object files.
+ *****************************************************************************/
+
+#include <config.h>
+
+#include "common.h"
+
+// Attribute types on disk
+#define BOOLEAN_ATTR 0x1
+#define ULONG_ATTR 0x2
+#define BYTES_ATTR 0x3
+#define ATTRMAP_ATTR 0x4
+#define MECHSET_ATTR 0x5
+
+// Maximum byte string length (1Gib)
+#define MAX_BYTES 0x3fffffff
+
+typedef AttributeTK<uint64_t, uint64_t, uint64_t> Attribute;
+
+// Attribute specialization
+template<>
+bool Attribute::isBoolean() const
+{
+ return kind == BOOLEAN_ATTR;
+}
+
+template<>
+bool Attribute::isInteger() const
+{
+ return kind == ULONG_ATTR;
+}
+
+template<>
+bool Attribute::isBinary() const
+{
+ return kind == BYTES_ATTR;
+}
+
+template<>
+bool Attribute::isMechSet() const
+{
+ return kind == MECHSET_ATTR;
+}
+
+template<>
+void Attribute::dumpType() const
+{
+ dumpULong(type, true);
+}
+
+template<>
+void Attribute::dumpKind() const
+{
+ dumpULong(kind, true);
+}
+
+template<>
+void Attribute::dumpBoolValue() const
+{
+ dumpBool(boolValue, true);
+}
+
+template<>
+void Attribute::dumpULongValue(uint64_t value) const
+{
+ dumpULong(value, true);
+}
+
+// dumpMap specialization
+typedef std::vector<Attribute> va_type;
+
+void dumpMap(const va_type& value)
+{
+ for (va_type::const_iterator attr = value.begin(); attr != value.end(); ++attr)
+ attr->dump();
+}
+
+// Read a boolean (in fact unsigned 8 bit long) value
+bool readBool(FILE* stream, uint8_t& value)
+{
+ value = 0;
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ uint8_t v;
+ if (fread(&v, 1, 1, stream) != 1)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ value = v;
+ return true;
+}
+
+// Read an unsigned 64 bit long value
+bool readULong(FILE* stream, uint64_t& value)
+{
+ value = 0;
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ uint8_t v[8];
+ if (fread(v, 1, 8, stream) != 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ for (size_t i = 0; i < 8; i++)
+ {
+ value <<= 8;
+ value += v[i];
+ }
+ return true;
+}
+
+// Read a byte string (aka uint8_t vector) value
+bool readBytes(FILE* stream, std::vector<uint8_t>& value)
+{
+ size_t len = value.size();
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ if (fread(&value[0], 1, len, stream) != len)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ return true;
+}
+
+// Read a map (aka Attribute vector) value
+bool readMap(FILE* stream, uint64_t len, std::vector<Attribute>& value)
+{
+ fpos_t pos;
+ if (fgetpos(stream, &pos) != 0)
+ {
+ return false;
+ }
+ while (len != 0)
+ {
+ Attribute attr;
+
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, attr.type))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, attr.kind))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (attr.kind == BOOLEAN_ATTR)
+ {
+ if (len < 1)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 1;
+ if (!readBool(stream, attr.boolValue))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ }
+ else if (attr.kind == ULONG_ATTR)
+ {
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, attr.ulongValue))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+ }
+ else if (attr.kind == BYTES_ATTR)
+ {
+ uint64_t size;
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, size))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (len < size)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ attr.bytestrValue.resize((size_t)size);
+ if (!readBytes(stream, attr.bytestrValue))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= size;
+ }
+ else if (attr.kind == MECHSET_ATTR)
+ {
+ uint64_t size;
+ if (len < 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ if (!readULong(stream, size))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ len -= 8;
+
+ if (len < size * 8)
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+
+ for (unsigned long i = 0; i < size; i++)
+ {
+ uint64_t mech;
+ if (!readULong(stream, mech))
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+ attr.mechSetValue.insert(mech);
+ }
+ len -= size * 8;
+ }
+ else
+ {
+ (void) fsetpos(stream, &pos);
+ return false;
+ }
+
+ value.push_back(attr);
+ }
+
+ return true;
+}
+
+// Error case
+void corrupt(FILE* stream)
+{
+ uint8_t v;
+ for (size_t i = 0; i < 8; i++)
+ {
+ if (fread(&v, 1, 1, stream) != 1)
+ {
+ if (ferror(stream))
+ {
+ printf("get an error...\n");
+ }
+ return;
+ }
+ if (i != 0)
+ {
+ printf(" ");
+ }
+ printf("%02hhx", v);
+ }
+ if (fread(&v, 1, 1, stream) != 1)
+ {
+ if (ferror(stream))
+ {
+ printf("\nget an error...\n");
+ }
+ return;
+ }
+ printf("...\n");
+}
+
+// Core function
+void dump(FILE* stream)
+{
+ uint64_t gen;
+ if (!readULong(stream, gen))
+ {
+ if (feof(stream))
+ {
+ printf("empty file\n");
+ }
+ else
+ {
+ corrupt(stream);
+ }
+ return;
+ }
+ dumpULong(gen);
+ printf("generation %lu\n", (unsigned long) gen);
+
+ while (!feof(stream))
+ {
+ uint64_t p11type;
+ if (!readULong(stream, p11type))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(p11type);
+ if ((uint64_t)((uint32_t)p11type) != p11type)
+ {
+ printf("overflow attribute type\n");
+ }
+ else
+ {
+ dumpCKA((unsigned long) p11type, 48);
+ printf("\n");
+ }
+
+ uint64_t disktype;
+ if (!readULong(stream, disktype))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(disktype);
+ switch (disktype)
+ {
+ case BOOLEAN_ATTR:
+ printf("boolean attribute\n");
+ break;
+ case ULONG_ATTR:
+ printf("unsigned long attribute\n");
+ break;
+ case BYTES_ATTR:
+ printf("byte string attribute\n");
+ break;
+ case ATTRMAP_ATTR:
+ printf("attribute map attribute\n");
+ break;
+ case MECHSET_ATTR:
+ printf("mechanism set attribute\n");
+ break;
+ default:
+ printf("unknown attribute format\n");
+ break;
+ }
+
+ if (disktype == BOOLEAN_ATTR)
+ {
+ uint8_t value;
+ if (!readBool(stream, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpBool(value);
+ printf("\n");
+ }
+ else if (disktype == ULONG_ATTR)
+ {
+ uint64_t value;
+ if (!readULong(stream, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(value);
+ dumpCKx(p11type, value, 48);
+ printf("\n");
+ }
+ else if (disktype == BYTES_ATTR)
+ {
+ uint64_t len;
+ if (!readULong(stream, len))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(len);
+ if (len > MAX_BYTES)
+ {
+ printf("overflow length...\n");
+ return;
+ }
+ printf("(length %lu)\n", (unsigned long) len);
+
+ std::vector<uint8_t> value((size_t) len);
+ if (!readBytes(stream, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpBytes(value);
+ }
+ else if (disktype == ATTRMAP_ATTR)
+ {
+ uint64_t len;
+ if (!readULong(stream, len))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(len);
+ if (len > MAX_BYTES)
+ {
+ printf("overflow length...\n");
+ return;
+ }
+ printf("(length %lu)\n", (unsigned long) len);
+
+ std::vector<Attribute> value;
+ if (!readMap(stream, len, value))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpMap(value);
+ }
+ else if (disktype == MECHSET_ATTR)
+ {
+ uint64_t len;
+ if (!readULong(stream, len))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(len);
+ if (len > MAX_BYTES)
+ {
+ printf("overflow length...\n");
+ return;
+ }
+ printf("(length %lu)\n", (unsigned long) len);
+
+ for (unsigned long i = 0; i < len; i++)
+ {
+ uint64_t mech;
+ if (!readULong(stream, mech))
+ {
+ corrupt(stream);
+ return;
+ }
+ dumpULong(mech);
+ dumpCKM(mech, 48);
+ printf("\n");
+ }
+ }
+ else
+ {
+ corrupt(stream);
+ return;
+ }
+ }
+}
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM dump tool. From SoftHSM v2 object file.\n");
+ printf("Usage: softhsm2-dump-file path\n");
+}
+
+// The main function
+int main(int argc, char* argv[])
+{
+ FILE* stream;
+
+ if (argc != 2)
+ {
+ usage();
+ exit(0);
+ }
+
+ stream = fopen(argv[1], "r");
+ if (stream == NULL)
+ {
+ fprintf(stderr, "can't open object file %s\n", argv[1]);
+ exit(0);
+ }
+
+ printf("Dump of object file \"%s\"\n", argv[1]);
+ dump(stream);
+ exit(1);
+}
diff --git a/SoftHSMv2/src/bin/dump/tables.h b/SoftHSMv2/src/bin/dump/tables.h
new file mode 100644
index 0000000..76d64fb
--- /dev/null
+++ b/SoftHSMv2/src/bin/dump/tables.h
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2013 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ tables.h
+
+ Tables from PKCS#11 specs.
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_TABLES_H
+#define _SOFTHSM_V2_TABLES_H
+
+#include "OSAttributes.h"
+
+// Attribute types
+void fill_CKA_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKA_CLASS] = "CKA_CLASS";
+ t[CKA_TOKEN] = "CKA_TOKEN";
+ t[CKA_PRIVATE] = "CKA_PRIVATE";
+ t[CKA_LABEL] = "CKA_LABEL";
+ t[CKA_APPLICATION] = "CKA_APPLICATION";
+ t[CKA_VALUE] = "CKA_VALUE";
+ t[CKA_OBJECT_ID] = "CKA_OBJECT_ID";
+ t[CKA_CERTIFICATE_TYPE] = "CKA_CERTIFICATE_TYPE";
+ t[CKA_ISSUER] = "CKA_ISSUER";
+ t[CKA_SERIAL_NUMBER] = "CKA_SERIAL_NUMBER";
+ t[CKA_AC_ISSUER] = "CKA_AC_ISSUER";
+ t[CKA_OWNER] = "CKA_OWNER";
+ t[CKA_ATTR_TYPES] = "CKA_ATTR_TYPES";
+ t[CKA_TRUSTED] = "CKA_TRUSTED";
+ t[CKA_CERTIFICATE_CATEGORY] = "CKA_CERTIFICATE_CATEGORY";
+ t[CKA_JAVA_MIDP_SECURITY_DOMAIN] = "CKA_JAVA_MIDP_SECURITY_DOMAIN";
+ t[CKA_URL] = "CKA_URL";
+ t[CKA_HASH_OF_SUBJECT_PUBLIC_KEY] = "CKA_HASH_OF_SUBJECT_PUBLIC_KEY";
+ t[CKA_HASH_OF_ISSUER_PUBLIC_KEY] = "CKA_HASH_OF_ISSUER_PUBLIC_KEY";
+ t[CKA_NAME_HASH_ALGORITHM] = "CKA_NAME_HASH_ALGORITHM";
+ t[CKA_CHECK_VALUE] = "CKA_CHECK_VALUE";
+ t[CKA_KEY_TYPE] = "CKA_KEY_TYPE";
+ t[CKA_SUBJECT] = "CKA_SUBJECT";
+ t[CKA_ID] = "CKA_ID";
+ t[CKA_SENSITIVE] = "CKA_SENSITIVE";
+ t[CKA_ENCRYPT] = "CKA_ENCRYPT";
+ t[CKA_DECRYPT] = "CKA_DECRYPT";
+ t[CKA_WRAP] = "CKA_WRAP";
+ t[CKA_UNWRAP] = "CKA_UNWRAP";
+ t[CKA_SIGN] = "CKA_SIGN";
+ t[CKA_SIGN_RECOVER] = "CKA_SIGN_RECOVER";
+ t[CKA_VERIFY] = "CKA_VERIFY";
+ t[CKA_VERIFY_RECOVER] = "CKA_VERIFY_RECOVER";
+ t[CKA_DERIVE] = "CKA_DERIVE";
+ t[CKA_START_DATE] = "CKA_START_DATE";
+ t[CKA_END_DATE] = "CKA_END_DATE";
+ t[CKA_MODULUS] = "CKA_MODULUS";
+ t[CKA_MODULUS_BITS] = "CKA_MODULUS_BITS";
+ t[CKA_PUBLIC_EXPONENT] = "CKA_PUBLIC_EXPONENT";
+ t[CKA_PRIVATE_EXPONENT] = "CKA_PRIVATE_EXPONENT";
+ t[CKA_PRIME_1] = "CKA_PRIME_1";
+ t[CKA_PRIME_2] = "CKA_PRIME_2";
+ t[CKA_EXPONENT_1] = "CKA_EXPONENT_1";
+ t[CKA_EXPONENT_2] = "CKA_EXPONENT_2";
+ t[CKA_COEFFICIENT] = "CKA_COEFFICIENT";
+ t[CKA_PUBLIC_KEY_INFO] = "CKA_PUBLIC_KEY_INFO";
+ t[CKA_PRIME] = "CKA_PRIME";
+ t[CKA_SUBPRIME] = "CKA_SUBPRIME";
+ t[CKA_BASE] = "CKA_BASE";
+ t[CKA_PRIME_BITS] = "CKA_PRIME_BITS";
+ t[CKA_SUBPRIME_BITS] = "CKA_SUBPRIME_BITS";
+ t[CKA_VALUE_BITS] = "CKA_VALUE_BITS";
+ t[CKA_VALUE_LEN] = "CKA_VALUE_LEN";
+ t[CKA_EXTRACTABLE] = "CKA_EXTRACTABLE";
+ t[CKA_LOCAL] = "CKA_LOCAL";
+ t[CKA_NEVER_EXTRACTABLE] = "CKA_NEVER_EXTRACTABLE";
+ t[CKA_ALWAYS_SENSITIVE] = "CKA_ALWAYS_SENSITIVE";
+ t[CKA_KEY_GEN_MECHANISM] = "CKA_KEY_GEN_MECHANISM";
+ t[CKA_MODIFIABLE] = "CKA_MODIFIABLE";
+ t[CKA_COPYABLE] = "CKA_COPYABLE";
+ t[CKA_DESTROYABLE] = "CKA_DESTROYABLE";
+ t[CKA_EC_PARAMS] = "CKA_EC_PARAMS";
+ t[CKA_EC_POINT] = "CKA_EC_POINT";
+ t[CKA_SECONDARY_AUTH] = "CKA_SECONDARY_AUTH";
+ t[CKA_AUTH_PIN_FLAGS] = "CKA_AUTH_PIN_FLAGS";
+ t[CKA_ALWAYS_AUTHENTICATE] = "CKA_ALWAYS_AUTHENTICATE";
+ t[CKA_WRAP_WITH_TRUSTED] = "CKA_WRAP_WITH_TRUSTED";
+ t[CKA_WRAP_TEMPLATE] = "CKA_WRAP_TEMPLATE";
+ t[CKA_UNWRAP_TEMPLATE] = "CKA_UNWRAP_TEMPLATE";
+ t[CKA_DERIVE_TEMPLATE] = "CKA_DERIVE_TEMPLATE";
+ t[CKA_OTP_FORMAT] = "CKA_OTP_FORMAT";
+ t[CKA_OTP_LENGTH] = "CKA_OTP_LENGTH";
+ t[CKA_OTP_TIME_INTERVAL] = "CKA_OTP_TIME_INTERVAL";
+ t[CKA_OTP_USER_FRIENDLY_MODE] = "CKA_OTP_USER_FRIENDLY_MODE";
+ t[CKA_OTP_CHALLENGE_REQUIREMENT] = "CKA_OTP_CHALLENGE_REQUIREMENT";
+ t[CKA_OTP_TIME_REQUIREMENT] = "CKA_OTP_TIME_REQUIREMENT";
+ t[CKA_OTP_COUNTER_REQUIREMENT] = "CKA_OTP_COUNTER_REQUIREMENT";
+ t[CKA_OTP_PIN_REQUIREMENT] = "CKA_OTP_PIN_REQUIREMENT";
+ t[CKA_OTP_COUNTER] = "CKA_OTP_COUNTER";
+ t[CKA_OTP_TIME] = "CKA_OTP_TIME";
+ t[CKA_OTP_USER_IDENTIFIER] = "CKA_OTP_USER_IDENTIFIER";
+ t[CKA_OTP_SERVICE_IDENTIFIER] = "CKA_OTP_SERVICE_IDENTIFIER";
+ t[CKA_OTP_SERVICE_LOGO] = "CKA_OTP_SERVICE_LOGO";
+ t[CKA_OTP_SERVICE_LOGO_TYPE] = "CKA_OTP_SERVICE_LOGO_TYPE";
+ t[CKA_GOSTR3410_PARAMS] = "CKA_GOSTR3410_PARAMS";
+ t[CKA_GOSTR3411_PARAMS] = "CKA_GOSTR3411_PARAMS";
+ t[CKA_GOST28147_PARAMS] = "CKA_GOST28147_PARAMS";
+ t[CKA_HW_FEATURE_TYPE] = "CKA_HW_FEATURE_TYPE";
+ t[CKA_RESET_ON_INIT] = "CKA_RESET_ON_INIT";
+ t[CKA_HAS_RESET] = "CKA_HAS_RESET";
+ t[CKA_PIXEL_X] = "CKA_PIXEL_X";
+ t[CKA_PIXEL_Y] = "CKA_PIXEL_Y";
+ t[CKA_RESOLUTION] = "CKA_RESOLUTION";
+ t[CKA_CHAR_ROWS] = "CKA_CHAR_ROWS";
+ t[CKA_CHAR_COLUMNS] = "CKA_CHAR_COLUMNS";
+ t[CKA_COLOR] = "CKA_COLOR";
+ t[CKA_BITS_PER_PIXEL] = "CKA_BITS_PER_PIXEL";
+ t[CKA_CHAR_SETS] = "CKA_CHAR_SETS";
+ t[CKA_ENCODING_METHODS] = "CKA_ENCODING_METHODS";
+ t[CKA_MIME_TYPES] = "CKA_MIME_TYPES";
+ t[CKA_MECHANISM_TYPE] = "CKA_MECHANISM_TYPE";
+ t[CKA_REQUIRED_CMS_ATTRIBUTES] = "CKA_REQUIRED_CMS_ATTRIBUTES";
+ t[CKA_DEFAULT_CMS_ATTRIBUTES] = "CKA_DEFAULT_CMS_ATTRIBUTES";
+ t[CKA_SUPPORTED_CMS_ATTRIBUTES] = "CKA_SUPPORTED_CMS_ATTRIBUTES";
+ t[CKA_ALLOWED_MECHANISMS] = "CKA_ALLOWED_MECHANISMS";
+ // local extensions
+ t[CKA_VENDOR_SOFTHSM] = "CKA_VENDOR_SOFTHSM";
+ t[CKA_OS_TOKENLABEL] = "CKA_OS_TOKENLABEL";
+ t[CKA_OS_TOKENSERIAL] = "CKA_OS_TOKENSERIAL";
+ t[CKA_OS_TOKENFLAGS] = "CKA_OS_TOKENFLAGS";
+ t[CKA_OS_SOPIN] = "CKA_OS_SOPIN";
+ t[CKA_OS_USERPIN] = "CKA_OS_USERPIN";
+}
+
+void fill_CKM_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKM_RSA_PKCS_KEY_PAIR_GEN] = "CKM_RSA_PKCS_KEY_PAIR_GEN";
+ t[CKM_RSA_PKCS] = "CKM_RSA_PKCS";
+ t[CKM_RSA_9796] = "CKM_RSA_9796";
+ t[CKM_RSA_X_509] = "CKM_RSA_X_509";
+ t[CKM_MD2_RSA_PKCS] = "CKM_MD2_RSA_PKCS";
+ t[CKM_MD5_RSA_PKCS] = "CKM_MD5_RSA_PKCS";
+ t[CKM_SHA1_RSA_PKCS] = "CKM_SHA1_RSA_PKCS";
+ t[CKM_RIPEMD128_RSA_PKCS] = "CKM_RIPEMD128_RSA_PKCS";
+ t[CKM_RIPEMD160_RSA_PKCS] = "CKM_RIPEMD160_RSA_PKCS";
+ t[CKM_RSA_PKCS_OAEP] = "CKM_RSA_PKCS_OAEP";
+ t[CKM_RSA_X9_31_KEY_PAIR_GEN] = "CKM_RSA_X9_31_KEY_PAIR_GEN";
+ t[CKM_RSA_X9_31] = "CKM_RSA_X9_31";
+ t[CKM_SHA1_RSA_X9_31] = "CKM_SHA1_RSA_X9_31";
+ t[CKM_RSA_PKCS_PSS] = "CKM_RSA_PKCS_PSS";
+ t[CKM_SHA1_RSA_PKCS_PSS] = "CKM_SHA1_RSA_PKCS_PSS";
+ t[CKM_DSA_KEY_PAIR_GEN] = "CKM_DSA_KEY_PAIR_GEN";
+ t[CKM_DSA] = "CKM_DSA";
+ t[CKM_DSA_SHA1] = "CKM_DSA_SHA1";
+ t[CKM_DSA_SHA224] = "CKM_DSA_SHA224";
+ t[CKM_DSA_SHA256] = "CKM_DSA_SHA256";
+ t[CKM_DSA_SHA384] = "CKM_DSA_SHA384";
+ t[CKM_DSA_SHA512] = "CKM_DSA_SHA512";
+ t[CKM_DH_PKCS_KEY_PAIR_GEN] = "CKM_DH_PKCS_KEY_PAIR_GEN";
+ t[CKM_DH_PKCS_DERIVE] = "CKM_DH_PKCS_DERIVE";
+ t[CKM_X9_42_DH_KEY_PAIR_GEN] = "CKM_X9_42_DH_KEY_PAIR_GEN";
+ t[CKM_X9_42_DH_DERIVE] = "CKM_X9_42_DH_DERIVE";
+ t[CKM_X9_42_DH_HYBRID_DERIVE] = "CKM_X9_42_DH_HYBRID_DERIVE";
+ t[CKM_X9_42_MQV_DERIVE] = "CKM_X9_42_MQV_DERIVE";
+ t[CKM_SHA256_RSA_PKCS] = "CKM_SHA256_RSA_PKCS";
+ t[CKM_SHA384_RSA_PKCS] = "CKM_SHA384_RSA_PKCS";
+ t[CKM_SHA512_RSA_PKCS] = "CKM_SHA512_RSA_PKCS";
+ t[CKM_SHA256_RSA_PKCS_PSS] = "CKM_SHA256_RSA_PKCS_PSS";
+ t[CKM_SHA384_RSA_PKCS_PSS] = "CKM_SHA384_RSA_PKCS_PSS";
+ t[CKM_SHA512_RSA_PKCS_PSS] = "CKM_SHA512_RSA_PKCS_PSS";
+ t[CKM_SHA224_RSA_PKCS] = "CKM_SHA224_RSA_PKCS";
+ t[CKM_SHA224_RSA_PKCS_PSS] = "CKM_SHA224_RSA_PKCS_PSS";
+ t[CKM_SHA512_224] = "CKM_SHA512_224";
+ t[CKM_SHA512_224_HMAC] = "CKM_SHA512_224_HMAC";
+ t[CKM_SHA512_224_HMAC_GENERAL] = "CKM_SHA512_224_HMAC_GENERAL";
+ t[CKM_SHA512_224_KEY_DERIVATION] = "CKM_SHA512_224_KEY_DERIVATION";
+ t[CKM_SHA512_256] = "CKM_SHA512_256";
+ t[CKM_SHA512_256_HMAC] = "CKM_SHA512_256_HMAC";
+ t[CKM_SHA512_256_HMAC_GENERAL] = "CKM_SHA512_256_HMAC_GENERAL";
+ t[CKM_SHA512_256_KEY_DERIVATION] = "CKM_SHA512_256_KEY_DERIVATION";
+ t[CKM_SHA512_T] = "CKM_SHA512_T";
+ t[CKM_SHA512_T_HMAC] = "CKM_SHA512_T_HMAC";
+ t[CKM_SHA512_T_HMAC_GENERAL] = "CKM_SHA512_T_HMAC_GENERAL";
+ t[CKM_SHA512_T_KEY_DERIVATION] = "CKM_SHA512_T_KEY_DERIVATION";
+ t[CKM_RC2_KEY_GEN] = "CKM_RC2_KEY_GEN";
+ t[CKM_RC2_ECB] = "CKM_RC2_ECB";
+ t[CKM_RC2_CBC] = "CKM_RC2_CBC";
+ t[CKM_RC2_MAC] = "CKM_RC2_MAC";
+ t[CKM_RC2_MAC_GENERAL] = "CKM_RC2_MAC_GENERAL";
+ t[CKM_RC2_CBC_PAD] = "CKM_RC2_CBC_PAD";
+ t[CKM_RC4_KEY_GEN] = "CKM_RC4_KEY_GEN";
+ t[CKM_RC4] = "CKM_RC4";
+ t[CKM_DES_KEY_GEN] = "CKM_DES_KEY_GEN";
+ t[CKM_DES_ECB] = "CKM_DES_ECB";
+ t[CKM_DES_CBC] = "CKM_DES_CBC";
+ t[CKM_DES_MAC] = "CKM_DES_MAC";
+ t[CKM_DES_MAC_GENERAL] = "CKM_DES_MAC_GENERAL";
+ t[CKM_DES_CBC_PAD] = "CKM_DES_CBC_PAD";
+ t[CKM_DES2_KEY_GEN] = "CKM_DES2_KEY_GEN";
+ t[CKM_DES3_KEY_GEN] = "CKM_DES3_KEY_GEN";
+ t[CKM_DES3_ECB] = "CKM_DES3_ECB";
+ t[CKM_DES3_CBC] = "CKM_DES3_CBC";
+ t[CKM_DES3_MAC] = "CKM_DES3_MAC";
+ t[CKM_DES3_MAC_GENERAL] = "CKM_DES3_MAC_GENERAL";
+ t[CKM_DES3_CBC_PAD] = "CKM_DES3_CBC_PAD";
+ t[CKM_DES3_CMAC_GENERAL] = "CKM_DES3_CMAC_GENERAL";
+ t[CKM_DES3_CMAC] = "CKM_DES3_CMAC";
+ t[CKM_CDMF_KEY_GEN] = "CKM_CDMF_KEY_GEN";
+ t[CKM_CDMF_ECB] = "CKM_CDMF_ECB";
+ t[CKM_CDMF_CBC] = "CKM_CDMF_CBC";
+ t[CKM_CDMF_MAC] = "CKM_CDMF_MAC";
+ t[CKM_CDMF_MAC_GENERAL] = "CKM_CDMF_MAC_GENERAL";
+ t[CKM_CDMF_CBC_PAD] = "CKM_CDMF_CBC_PAD";
+ t[CKM_DES_OFB64] = "CKM_DES_OFB64";
+ t[CKM_DES_OFB8] = "CKM_DES_OFB8";
+ t[CKM_DES_CFB64] = "CKM_DES_CFB64";
+ t[CKM_DES_CFB8] = "CKM_DES_CFB8";
+ t[CKM_MD2] = "CKM_MD2";
+ t[CKM_MD2_HMAC] = "CKM_MD2_HMAC";
+ t[CKM_MD2_HMAC_GENERAL] = "CKM_MD2_HMAC_GENERAL";
+ t[CKM_MD5] = "CKM_MD5";
+ t[CKM_MD5_HMAC] = "CKM_MD5_HMAC";
+ t[CKM_MD5_HMAC_GENERAL] = "CKM_MD5_HMAC_GENERAL";
+ t[CKM_SHA_1] = "CKM_SHA_1";
+ t[CKM_SHA_1_HMAC] = "CKM_SHA_1_HMAC";
+ t[CKM_SHA_1_HMAC_GENERAL] = "CKM_SHA_1_HMAC_GENERAL";
+ t[CKM_RIPEMD128] = "CKM_RIPEMD128";
+ t[CKM_RIPEMD128_HMAC] = "CKM_RIPEMD128_HMAC";
+ t[CKM_RIPEMD128_HMAC_GENERAL] = "CKM_RIPEMD128_HMAC_GENERAL";
+ t[CKM_RIPEMD160] = "CKM_RIPEMD160";
+ t[CKM_RIPEMD160_HMAC] = "CKM_RIPEMD160_HMAC";
+ t[CKM_RIPEMD160_HMAC_GENERAL] = "CKM_RIPEMD160_HMAC_GENERAL";
+ t[CKM_SHA256] = "CKM_SHA256";
+ t[CKM_SHA256_HMAC] = "CKM_SHA256_HMAC";
+ t[CKM_SHA256_HMAC_GENERAL] = "CKM_SHA256_HMAC_GENERAL";
+ t[CKM_SHA224] = "CKM_SHA224";
+ t[CKM_SHA224_HMAC] = "CKM_SHA224_HMAC";
+ t[CKM_SHA224_HMAC_GENERAL] = "CKM_SHA224_HMAC_GENERAL";
+ t[CKM_SHA384] = "CKM_SHA384";
+ t[CKM_SHA384_HMAC] = "CKM_SHA384_HMAC";
+ t[CKM_SHA384_HMAC_GENERAL] = "CKM_SHA384_HMAC_GENERAL";
+ t[CKM_SHA512] = "CKM_SHA512";
+ t[CKM_SHA512_HMAC] = "CKM_SHA512_HMAC";
+ t[CKM_SHA512_HMAC_GENERAL] = "CKM_SHA512_HMAC_GENERAL";
+ t[CKM_SECURID_KEY_GEN] = "CKM_SECURID_KEY_GEN";
+ t[CKM_SECURID] = "CKM_SECURID";
+ t[CKM_HOTP_KEY_GEN] = "CKM_HOTP_KEY_GEN";
+ t[CKM_HOTP] = "CKM_HOTP";
+ t[CKM_ACTI] = "CKM_ACTI";
+ t[CKM_ACTI_KEY_GEN] = "CKM_ACTI_KEY_GEN";
+ t[CKM_CAST_KEY_GEN] = "CKM_CAST_KEY_GEN";
+ t[CKM_CAST_ECB] = "CKM_CAST_ECB";
+ t[CKM_CAST_CBC] = "CKM_CAST_CBC";
+ t[CKM_CAST_MAC] = "CKM_CAST_MAC";
+ t[CKM_CAST_MAC_GENERAL] = "CKM_CAST_MAC_GENERAL";
+ t[CKM_CAST_CBC_PAD] = "CKM_CAST_CBC_PAD";
+ t[CKM_CAST3_KEY_GEN] = "CKM_CAST3_KEY_GEN";
+ t[CKM_CAST3_ECB] = "CKM_CAST3_ECB";
+ t[CKM_CAST3_CBC] = "CKM_CAST3_CBC";
+ t[CKM_CAST3_MAC] = "CKM_CAST3_MAC";
+ t[CKM_CAST3_MAC_GENERAL] = "CKM_CAST3_MAC_GENERAL";
+ t[CKM_CAST3_CBC_PAD] = "CKM_CAST3_CBC_PAD";
+ t[CKM_CAST128_KEY_GEN] = "CKM_CAST128_KEY_GEN";
+ t[CKM_CAST128_ECB] = "CKM_CAST128_ECB";
+ t[CKM_CAST128_CBC] = "CKM_CAST128_CBC";
+ t[CKM_CAST128_MAC] = "CKM_CAST128_MAC";
+ t[CKM_CAST128_MAC_GENERAL] = "CKM_CAST128_MAC_GENERAL";
+ t[CKM_CAST128_CBC_PAD] = "CKM_CAST128_CBC_PAD";
+ t[CKM_RC5_KEY_GEN] = "CKM_RC5_KEY_GEN";
+ t[CKM_RC5_ECB] = "CKM_RC5_ECB";
+ t[CKM_RC5_CBC] = "CKM_RC5_CBC";
+ t[CKM_RC5_MAC] = "CKM_RC5_MAC";
+ t[CKM_RC5_MAC_GENERAL] = "CKM_RC5_MAC_GENERAL";
+ t[CKM_RC5_CBC_PAD] = "CKM_RC5_CBC_PAD";
+ t[CKM_IDEA_KEY_GEN] = "CKM_IDEA_KEY_GEN";
+ t[CKM_IDEA_ECB] = "CKM_IDEA_ECB";
+ t[CKM_IDEA_CBC] = "CKM_IDEA_CBC";
+ t[CKM_IDEA_MAC] = "CKM_IDEA_MAC";
+ t[CKM_IDEA_MAC_GENERAL] = "CKM_IDEA_MAC_GENERAL";
+ t[CKM_IDEA_CBC_PAD] = "CKM_IDEA_CBC_PAD";
+ t[CKM_GENERIC_SECRET_KEY_GEN] = "CKM_GENERIC_SECRET_KEY_GEN";
+ t[CKM_CONCATENATE_BASE_AND_KEY] = "CKM_CONCATENATE_BASE_AND_KEY";
+ t[CKM_CONCATENATE_BASE_AND_DATA] = "CKM_CONCATENATE_BASE_AND_DATA";
+ t[CKM_CONCATENATE_DATA_AND_BASE] = "CKM_CONCATENATE_DATA_AND_BASE";
+ t[CKM_XOR_BASE_AND_DATA] = "CKM_XOR_BASE_AND_DATA";
+ t[CKM_EXTRACT_KEY_FROM_KEY] = "CKM_EXTRACT_KEY_FROM_KEY";
+ t[CKM_SSL3_PRE_MASTER_KEY_GEN] = "CKM_SSL3_PRE_MASTER_KEY_GEN";
+ t[CKM_SSL3_MASTER_KEY_DERIVE] = "CKM_SSL3_MASTER_KEY_DERIVE";
+ t[CKM_SSL3_KEY_AND_MAC_DERIVE] = "CKM_SSL3_KEY_AND_MAC_DERIVE";
+ t[CKM_SSL3_MASTER_KEY_DERIVE_DH] = "CKM_SSL3_MASTER_KEY_DERIVE_DH";
+ t[CKM_TLS_PRE_MASTER_KEY_GEN] = "CKM_TLS_PRE_MASTER_KEY_GEN";
+ t[CKM_TLS_MASTER_KEY_DERIVE] = "CKM_TLS_MASTER_KEY_DERIVE";
+ t[CKM_TLS_KEY_AND_MAC_DERIVE] = "CKM_TLS_KEY_AND_MAC_DERIVE";
+ t[CKM_TLS_MASTER_KEY_DERIVE_DH] = "CKM_TLS_MASTER_KEY_DERIVE_DH";
+ t[CKM_TLS_PRF] = "CKM_TLS_PRF";
+ t[CKM_SSL3_MD5_MAC] = "CKM_SSL3_MD5_MAC";
+ t[CKM_SSL3_SHA1_MAC] = "CKM_SSL3_SHA1_MAC";
+ t[CKM_MD5_KEY_DERIVATION] = "CKM_MD5_KEY_DERIVATION";
+ t[CKM_MD2_KEY_DERIVATION] = "CKM_MD2_KEY_DERIVATION";
+ t[CKM_SHA1_KEY_DERIVATION] = "CKM_SHA1_KEY_DERIVATION";
+ t[CKM_SHA256_KEY_DERIVATION] = "CKM_SHA256_KEY_DERIVATION";
+ t[CKM_SHA384_KEY_DERIVATION] = "CKM_SHA384_KEY_DERIVATION";
+ t[CKM_SHA512_KEY_DERIVATION] = "CKM_SHA512_KEY_DERIVATION";
+ t[CKM_SHA224_KEY_DERIVATION] = "CKM_SHA224_KEY_DERIVATION";
+ t[CKM_PBE_MD2_DES_CBC] = "CKM_PBE_MD2_DES_CBC";
+ t[CKM_PBE_MD5_DES_CBC] = "CKM_PBE_MD5_DES_CBC";
+ t[CKM_PBE_MD5_CAST_CBC] = "CKM_PBE_MD5_CAST_CBC";
+ t[CKM_PBE_MD5_CAST3_CBC] = "CKM_PBE_MD5_CAST3_CBC";
+ t[CKM_PBE_MD5_CAST128_CBC] = "CKM_PBE_MD5_CAST128_CBC";
+ t[CKM_PBE_SHA1_CAST128_CBC] = "CKM_PBE_SHA1_CAST128_CBC";
+ t[CKM_PBE_SHA1_RC4_128] = "CKM_PBE_SHA1_RC4_128";
+ t[CKM_PBE_SHA1_RC4_40] = "CKM_PBE_SHA1_RC4_40";
+ t[CKM_PBE_SHA1_DES3_EDE_CBC] = "CKM_PBE_SHA1_DES3_EDE_CBC";
+ t[CKM_PBE_SHA1_DES2_EDE_CBC] = "CKM_PBE_SHA1_DES2_EDE_CBC";
+ t[CKM_PBE_SHA1_RC2_128_CBC] = "CKM_PBE_SHA1_RC2_128_CBC";
+ t[CKM_PBE_SHA1_RC2_40_CBC] = "CKM_PBE_SHA1_RC2_40_CBC";
+ t[CKM_PKCS5_PBKD2] = "CKM_PKCS5_PBKD2";
+ t[CKM_PBA_SHA1_WITH_SHA1_HMAC] = "CKM_PBA_SHA1_WITH_SHA1_HMAC";
+ t[CKM_WTLS_PRE_MASTER_KEY_GEN] = "CKM_WTLS_PRE_MASTER_KEY_GEN";
+ t[CKM_WTLS_MASTER_KEY_DERIVE] = "CKM_WTLS_MASTER_KEY_DERIVE";
+ t[CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC] = "CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC";
+ t[CKM_WTLS_PRF] = "CKM_WTLS_PRF";
+ t[CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE] = "CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE";
+ t[CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE] = "CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE";
+ t[CKM_TLS10_MAC_SERVER] = "CKM_TLS10_MAC_SERVER";
+ t[CKM_TLS10_MAC_CLIENT] = "CKM_TLS10_MAC_CLIENT";
+ t[CKM_TLS12_MAC] = "CKM_TLS12_MAC";
+ t[CKM_TLS12_KDF] = "CKM_TLS12_KDF";
+ t[CKM_TLS12_MASTER_KEY_DERIVE] = "CKM_TLS12_MASTER_KEY_DERIVE";
+ t[CKM_TLS12_KEY_AND_MAC_DERIVE] = "CKM_TLS12_KEY_AND_MAC_DERIVE";
+ t[CKM_TLS12_MASTER_KEY_DERIVE_DH] = "CKM_TLS12_MASTER_KEY_DERIVE_DH";
+ t[CKM_TLS12_KEY_SAFE_DERIVE] = "CKM_TLS12_KEY_SAFE_DERIVE";
+ t[CKM_TLS_MAC] = "CKM_TLS_MAC";
+ t[CKM_TLS_KDF] = "CKM_TLS_KDF";
+ t[CKM_KEY_WRAP_LYNKS] = "CKM_KEY_WRAP_LYNKS";
+ t[CKM_KEY_WRAP_SET_OAEP] = "CKM_KEY_WRAP_SET_OAEP";
+ t[CKM_CMS_SIG] = "CKM_CMS_SIG";
+ t[CKM_KIP_DERIVE] = "CKM_KIP_DERIVE";
+ t[CKM_KIP_WRAP] = "CKM_KIP_WRAP";
+ t[CKM_KIP_MAC] = "CKM_KIP_MAC";
+ t[CKM_CAMELLIA_KEY_GEN] = "CKM_CAMELLIA_KEY_GEN";
+ t[CKM_CAMELLIA_ECB] = "CKM_CAMELLIA_ECB";
+ t[CKM_CAMELLIA_CBC] = "CKM_CAMELLIA_CBC";
+ t[CKM_CAMELLIA_MAC] = "CKM_CAMELLIA_MAC";
+ t[CKM_CAMELLIA_MAC_GENERAL] = "CKM_CAMELLIA_MAC_GENERAL";
+ t[CKM_CAMELLIA_CBC_PAD] = "CKM_CAMELLIA_CBC_PAD";
+ t[CKM_CAMELLIA_ECB_ENCRYPT_DATA] = "CKM_CAMELLIA_ECB_ENCRYPT_DATA";
+ t[CKM_CAMELLIA_CBC_ENCRYPT_DATA] = "CKM_CAMELLIA_CBC_ENCRYPT_DATA";
+ t[CKM_CAMELLIA_CTR] = "CKM_CAMELLIA_CTR";
+ t[CKM_ARIA_KEY_GEN] = "CKM_ARIA_KEY_GEN";
+ t[CKM_ARIA_ECB] = "CKM_ARIA_ECB";
+ t[CKM_ARIA_CBC] = "CKM_ARIA_CBC";
+ t[CKM_ARIA_MAC] = "CKM_ARIA_MAC";
+ t[CKM_ARIA_MAC_GENERAL] = "CKM_ARIA_MAC_GENERAL";
+ t[CKM_ARIA_CBC_PAD] = "CKM_ARIA_CBC_PAD";
+ t[CKM_ARIA_ECB_ENCRYPT_DATA] = "CKM_ARIA_ECB_ENCRYPT_DATA";
+ t[CKM_ARIA_CBC_ENCRYPT_DATA] = "CKM_ARIA_CBC_ENCRYPT_DATA";
+ t[CKM_SEED_KEY_GEN] = "CKM_SEED_KEY_GEN";
+ t[CKM_SEED_ECB] = "CKM_SEED_ECB";
+ t[CKM_SEED_CBC] = "CKM_SEED_CBC";
+ t[CKM_SEED_MAC] = "CKM_SEED_MAC";
+ t[CKM_SEED_MAC_GENERAL] = "CKM_SEED_MAC_GENERAL";
+ t[CKM_SEED_CBC_PAD] = "CKM_SEED_CBC_PAD";
+ t[CKM_SEED_ECB_ENCRYPT_DATA] = "CKM_SEED_ECB_ENCRYPT_DATA";
+ t[CKM_SEED_CBC_ENCRYPT_DATA] = "CKM_SEED_CBC_ENCRYPT_DATA";
+ t[CKM_SKIPJACK_KEY_GEN] = "CKM_SKIPJACK_KEY_GEN";
+ t[CKM_SKIPJACK_ECB64] = "CKM_SKIPJACK_ECB64";
+ t[CKM_SKIPJACK_CBC64] = "CKM_SKIPJACK_CBC64";
+ t[CKM_SKIPJACK_OFB64] = "CKM_SKIPJACK_OFB64";
+ t[CKM_SKIPJACK_CFB64] = "CKM_SKIPJACK_CFB64";
+ t[CKM_SKIPJACK_CFB32] = "CKM_SKIPJACK_CFB32";
+ t[CKM_SKIPJACK_CFB16] = "CKM_SKIPJACK_CFB16";
+ t[CKM_SKIPJACK_CFB8] = "CKM_SKIPJACK_CFB8";
+ t[CKM_SKIPJACK_WRAP] = "CKM_SKIPJACK_WRAP";
+ t[CKM_SKIPJACK_PRIVATE_WRAP] = "CKM_SKIPJACK_PRIVATE_WRAP";
+ t[CKM_SKIPJACK_RELAYX] = "CKM_SKIPJACK_RELAYX";
+ t[CKM_KEA_KEY_PAIR_GEN] = "CKM_KEA_KEY_PAIR_GEN";
+ t[CKM_KEA_KEY_DERIVE] = "CKM_KEA_KEY_DERIVE";
+ t[CKM_FORTEZZA_TIMESTAMP] = "CKM_FORTEZZA_TIMESTAMP";
+ t[CKM_BATON_KEY_GEN] = "CKM_BATON_KEY_GEN";
+ t[CKM_BATON_ECB128] = "CKM_BATON_ECB128";
+ t[CKM_BATON_ECB96] = "CKM_BATON_ECB96";
+ t[CKM_BATON_CBC128] = "CKM_BATON_CBC128";
+ t[CKM_BATON_COUNTER] = "CKM_BATON_COUNTER";
+ t[CKM_BATON_SHUFFLE] = "CKM_BATON_SHUFFLE";
+ t[CKM_BATON_WRAP] = "CKM_BATON_WRAP";
+ t[CKM_EC_KEY_PAIR_GEN] = "CKM_EC_KEY_PAIR_GEN";
+ t[CKM_ECDSA] = "CKM_ECDSA";
+ t[CKM_ECDSA_SHA1] = "CKM_ECDSA_SHA1";
+ t[CKM_ECDSA_SHA224] = "CKM_ECDSA_SHA224";
+ t[CKM_ECDSA_SHA256] = "CKM_ECDSA_SHA256";
+ t[CKM_ECDSA_SHA384] = "CKM_ECDSA_SHA384";
+ t[CKM_ECDSA_SHA512] = "CKM_ECDSA_SHA512";
+ t[CKM_ECDH1_DERIVE] = "CKM_ECDH1_DERIVE";
+ t[CKM_ECDH1_COFACTOR_DERIVE] = "CKM_ECDH1_COFACTOR_DERIVE";
+ t[CKM_ECMQV_DERIVE] = "CKM_ECMQV_DERIVE";
+ t[CKM_ECDH_AES_KEY_WRAP] = "CKM_ECDH_AES_KEY_WRAP";
+ t[CKM_RSA_AES_KEY_WRAP] = "CKM_RSA_AES_KEY_WRAP";
+ t[CKM_JUNIPER_KEY_GEN] = "CKM_JUNIPER_KEY_GEN";
+ t[CKM_JUNIPER_ECB128] = "CKM_JUNIPER_ECB128";
+ t[CKM_JUNIPER_CBC128] = "CKM_JUNIPER_CBC128";
+ t[CKM_JUNIPER_COUNTER] = "CKM_JUNIPER_COUNTER";
+ t[CKM_JUNIPER_SHUFFLE] = "CKM_JUNIPER_SHUFFLE";
+ t[CKM_JUNIPER_WRAP] = "CKM_JUNIPER_WRAP";
+ t[CKM_FASTHASH] = "CKM_FASTHASH";
+ t[CKM_AES_KEY_GEN] = "CKM_AES_KEY_GEN";
+ t[CKM_AES_ECB] = "CKM_AES_ECB";
+ t[CKM_AES_CBC] = "CKM_AES_CBC";
+ t[CKM_AES_MAC] = "CKM_AES_MAC";
+ t[CKM_AES_MAC_GENERAL] = "CKM_AES_MAC_GENERAL";
+ t[CKM_AES_CBC_PAD] = "CKM_AES_CBC_PAD";
+ t[CKM_AES_CTR] = "CKM_AES_CTR";
+ t[CKM_AES_GCM] = "CKM_AES_GCM";
+ t[CKM_AES_CCM] = "CKM_AES_CCM";
+ t[CKM_AES_CTS] = "CKM_AES_CTS";
+ t[CKM_AES_CMAC] = "CKM_AES_CMAC";
+ t[CKM_AES_CMAC_GENERAL] = "CKM_AES_CMAC_GENERAL";
+ t[CKM_AES_XCBC_MAC] = "CKM_AES_XCBC_MAC";
+ t[CKM_AES_XCBC_MAC_96] = "CKM_AES_XCBC_MAC_96";
+ t[CKM_AES_GMAC] = "CKM_AES_GMAC";
+ t[CKM_BLOWFISH_KEY_GEN] = "CKM_BLOWFISH_KEY_GEN";
+ t[CKM_BLOWFISH_CBC] = "CKM_BLOWFISH_CBC";
+ t[CKM_TWOFISH_KEY_GEN] = "CKM_TWOFISH_KEY_GEN";
+ t[CKM_TWOFISH_CBC] = "CKM_TWOFISH_CBC";
+ t[CKM_BLOWFISH_CBC_PAD] = "CKM_BLOWFISH_CBC_PAD";
+ t[CKM_TWOFISH_CBC_PAD] = "CKM_TWOFISH_CBC_PAD";
+ t[CKM_DES_ECB_ENCRYPT_DATA] = "CKM_DES_ECB_ENCRYPT_DATA";
+ t[CKM_DES_CBC_ENCRYPT_DATA] = "CKM_DES_CBC_ENCRYPT_DATA";
+ t[CKM_DES3_ECB_ENCRYPT_DATA] = "CKM_DES3_ECB_ENCRYPT_DATA";
+ t[CKM_DES3_CBC_ENCRYPT_DATA] = "CKM_DES3_CBC_ENCRYPT_DATA";
+ t[CKM_AES_ECB_ENCRYPT_DATA] = "CKM_AES_ECB_ENCRYPT_DATA";
+ t[CKM_AES_CBC_ENCRYPT_DATA] = "CKM_AES_CBC_ENCRYPT_DATA";
+ t[CKM_GOSTR3410_KEY_PAIR_GEN] = "CKM_GOSTR3410_KEY_PAIR_GEN";
+ t[CKM_GOSTR3410] = "CKM_GOSTR3410";
+ t[CKM_GOSTR3410_WITH_GOSTR3411] = "CKM_GOSTR3410_WITH_GOSTR3411";
+ t[CKM_GOSTR3410_KEY_WRAP] = "CKM_GOSTR3410_KEY_WRAP";
+ t[CKM_GOSTR3410_DERIVE] = "CKM_GOSTR3410_DERIVE";
+ t[CKM_GOSTR3411] = "CKM_GOSTR3411";
+ t[CKM_GOSTR3411_HMAC] = "CKM_GOSTR3411_HMAC";
+ t[CKM_GOST28147_KEY_GEN] = "CKM_GOST28147_KEY_GEN";
+ t[CKM_GOST28147_ECB] = "CKM_GOST28147_ECB";
+ t[CKM_GOST28147] = "CKM_GOST28147";
+ t[CKM_GOST28147_MAC] = "CKM_GOST28147_MAC";
+ t[CKM_GOST28147_KEY_WRAP] = "CKM_GOST28147_KEY_WRAP";
+ t[CKM_DSA_PARAMETER_GEN] = "CKM_DSA_PARAMETER_GEN";
+ t[CKM_DH_PKCS_PARAMETER_GEN] = "CKM_DH_PKCS_PARAMETER_GEN";
+ t[CKM_X9_42_DH_PARAMETER_GEN] = "CKM_X9_42_DH_PARAMETER_GEN";
+ t[CKM_DSA_PROBABLISTIC_PARAMETER_GEN] = "CKM_DSA_PROBABLISTIC_PARAMETER_GEN";
+ t[CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN] = "CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN";
+ t[CKM_AES_OFB] = "CKM_AES_OFB";
+ t[CKM_AES_CFB64] = "CKM_AES_CFB64";
+ t[CKM_AES_CFB8] = "CKM_AES_CFB8";
+ t[CKM_AES_CFB128] = "CKM_AES_CFB128";
+ t[CKM_AES_CFB1] = "CKM_AES_CFB1";
+ t[CKM_AES_KEY_WRAP] = "CKM_AES_KEY_WRAP";
+ t[CKM_AES_KEY_WRAP_PAD] = "CKM_AES_KEY_WRAP_PAD";
+ t[CKM_RSA_PKCS_TPM_1_1] = "CKM_RSA_PKCS_TPM_1_1";
+ t[CKM_RSA_PKCS_OAEP_TPM_1_1] = "CKM_RSA_PKCS_OAEP_TPM_1_1";
+}
+
+void fill_CKO_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKO_DATA] = "CKO_DATA";
+ t[CKO_CERTIFICATE] = "CKO_CERTIFICATE";
+ t[CKO_PUBLIC_KEY] = "CKO_PUBLIC_KEY";
+ t[CKO_PRIVATE_KEY] = "CKO_PRIVATE_KEY";
+ t[CKO_SECRET_KEY] = "CKO_SECRET_KEY";
+ t[CKO_HW_FEATURE] = "CKO_HW_FEATURE";
+ t[CKO_DOMAIN_PARAMETERS] = "CKO_DOMAIN_PARAMETERS";
+ t[CKO_MECHANISM] = "CKO_MECHANISM";
+ t[CKO_OTP_KEY] = "CKO_OTP_KEY";
+}
+
+void fill_CKH_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKH_MONOTONIC_COUNTER] = "CKH_MONOTONIC_COUNTER";
+ t[CKH_CLOCK] = "CKH_CLOCK";
+ t[CKH_USER_INTERFACE] = "CKH_USER_INTERFACE";
+}
+
+void fill_CKK_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKK_RSA] = "CKK_RSA";
+ t[CKK_DSA] = "CKK_DSA";
+ t[CKK_DH] = "CKK_DH";
+ t[CKK_EC] = "CKK_EC";
+ t[CKK_X9_42_DH] = "CKK_X9_42_DH";
+ t[CKK_KEA] = "CKK_KEA";
+ t[CKK_GENERIC_SECRET] = "CKK_GENERIC_SECRET";
+ t[CKK_RC2] = "CKK_RC2";
+ t[CKK_RC4] = "CKK_RC4";
+ t[CKK_DES] = "CKK_DES";
+ t[CKK_DES2] = "CKK_DES2";
+ t[CKK_DES3] = "CKK_DES3";
+ t[CKK_CAST] = "CKK_CAST";
+ t[CKK_CAST3] = "CKK_CAST3";
+ t[CKK_CAST128] = "CKK_CAST128";
+ t[CKK_RC5] = "CKK_RC5";
+ t[CKK_IDEA] = "CKK_IDEA";
+ t[CKK_SKIPJACK] = "CKK_SKIPJACK";
+ t[CKK_BATON] = "CKK_BATON";
+ t[CKK_JUNIPER] = "CKK_JUNIPER";
+ t[CKK_CDMF] = "CKK_CDMF";
+ t[CKK_AES] = "CKK_AES";
+ t[CKK_BLOWFISH] = "CKK_BLOWFISH";
+ t[CKK_TWOFISH] = "CKK_TWOFISH";
+ t[CKK_SECURID] = "CKK_SECURID";
+ t[CKK_HOTP] = "CKK_HOTP";
+ t[CKK_ACTI] = "CKK_ACTI";
+ t[CKK_CAMELLIA] = "CKK_CAMELLIA";
+ t[CKK_ARIA] = "CKK_ARIA";
+ t[CKK_MD5_HMAC] = "CKK_MD5_HMAC";
+ t[CKK_SHA_1_HMAC] = "CKK_SHA_1_HMAC";
+ t[CKK_RIPEMD128_HMAC] = "CKK_RIPEMD128_HMAC";
+ t[CKK_RIPEMD160_HMAC] = "CKK_RIPEMD160_HMAC";
+ t[CKK_SHA256_HMAC] = "CKK_SHA256_HMAC";
+ t[CKK_SHA384_HMAC] = "CKK_SHA384_HMAC";
+ t[CKK_SHA512_HMAC] = "CKK_SHA512_HMAC";
+ t[CKK_SHA224_HMAC] = "CKK_SHA224_HMAC";
+ t[CKK_SEED] = "CKK_SEED";
+ t[CKK_GOSTR3410] = "CKK_GOSTR3410";
+ t[CKK_GOSTR3411] = "CKK_GOSTR3411";
+ t[CKK_GOST28147] = "CKK_GOST28147";
+}
+
+void fill_CKC_table(std::map<unsigned long, std::string> &t)
+{
+ t[CKC_X_509] = "CKC_X_509";
+ t[CKC_X_509_ATTR_CERT] = "CKC_X_509_ATTR_CERT";
+ t[CKC_WTLS] = "CKC_WTLS";
+ t[CKC_OPENPGP] = "CKC_OPENPGP";
+}
+
+#endif // !_SOFTHSM_V2_TABLES_H
diff --git a/SoftHSMv2/src/bin/keyconv/Makefile.am b/SoftHSMv2/src/bin/keyconv/Makefile.am
new file mode 100644
index 0000000..b4268c2
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/Makefile.am
@@ -0,0 +1,26 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/crypto \
+ @CRYPTO_INCLUDES@
+
+dist_man_MANS = softhsm2-keyconv.1
+
+bin_PROGRAMS = softhsm2-keyconv
+
+softhsm2_keyconv_SOURCES = softhsm2-keyconv.cpp \
+ base64.c
+softhsm2_keyconv_LDADD = @CRYPTO_LIBS@
+
+# Compile with OpenSSL support
+if WITH_OPENSSL
+softhsm2_keyconv_SOURCES += softhsm2-keyconv-ossl.cpp \
+ ../../lib/crypto/OSSLComp.cpp
+endif
+
+# Compile with Botan support
+if WITH_BOTAN
+softhsm2_keyconv_SOURCES += softhsm2-keyconv-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/SoftHSMv2/src/bin/keyconv/base64.c b/SoftHSMv2/src/bin/keyconv/base64.c
new file mode 100644
index 0000000..3eb1201
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/base64.c
@@ -0,0 +1,311 @@
+/* $OpenBSD: base64.c,v 1.3 2002/06/09 08:13:07 todd Exp $ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$ISC: base64.c,v 8.6 1999/01/08 19:25:18 vixie Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/param.h>
+#include <sys/socket.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(unsigned char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ unsigned char input[3];
+ unsigned char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(char const *src, unsigned char *target, size_t targsize) {
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp
new file mode 100644
index 0000000..cb5700f
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-keyconv-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#define KEYCONV_BOTAN
+#include "softhsm2-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/bigint.h>
+#include <botan/version.h>
+
+// Init Botan
+void crypto_init()
+{
+ Botan::LibraryInitializer::initialize();
+}
+
+// Final Botan
+void crypto_final()
+{
+ Botan::LibraryInitializer::deinitialize();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigE, bigP, bigQ, bigN, bigD;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigE = Botan::BigInt((Botan::byte*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size);
+ bigP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size);
+ bigQ = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size);
+ bigN = Botan::BigInt((Botan::byte*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size);
+ bigD = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
+ priv_key = new Botan::RSA_PrivateKey(bigP, bigQ, bigE, bigD, bigN);
+#else
+ priv_key = new Botan::RSA_PrivateKey(*rng, bigP, bigQ, bigE, bigD, bigN);
+#endif
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (!priv_file.is_open())
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, std::chrono::milliseconds(300), "PBE-PKCS5v15(MD5,DES/CBC)");
+#else
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+#endif
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigDP, bigDQ, bigDG, bigDX;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigDP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size);
+ bigDQ = Botan::BigInt((Botan::byte*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size);
+ bigDG = Botan::BigInt((Botan::byte*)pkey[TAG_BASE].big, pkey[TAG_BASE].size);
+ bigDX = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+ priv_key = new Botan::DSA_PrivateKey(*rng, Botan::DL_Group(bigDP, bigDQ, bigDG), bigDX);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (!priv_file.is_open())
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, std::chrono::milliseconds(300), "PBE-PKCS5v15(MD5,DES/CBC)");
+#else
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+#endif
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp
new file mode 100644
index 0000000..a5cd8eb
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-keyconv-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#define KEYCONV_OSSL
+#include "softhsm2-keyconv.h"
+#include "OSSLComp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ OpenSSL_add_all_algorithms();
+#ifdef WITH_FIPS
+ if (!FIPS_mode_set(1))
+ {
+ fprintf(stderr, "ERROR: can't enter into FIPS mode.\n");
+ exit(0);
+ }
+#endif
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ RSA* rsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0 ||
+ pkey[TAG_EXP1].size <= 0 ||
+ pkey[TAG_EXP2].size <= 0 ||
+ pkey[TAG_COEFF].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ rsa = RSA_new();
+ BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size, NULL);
+ BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size, NULL);
+ BIGNUM* bn_d = BN_bin2bn((unsigned char*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size, NULL);
+ BIGNUM* bn_n = BN_bin2bn((unsigned char*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size, NULL);
+ BIGNUM* bn_e = BN_bin2bn((unsigned char*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size, NULL);
+ BIGNUM* bn_dmp1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP1].big, pkey[TAG_EXP1].size, NULL);
+ BIGNUM* bn_dmq1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP2].big, pkey[TAG_EXP2].size, NULL);
+ BIGNUM* bn_iqmp = BN_bin2bn((unsigned char*)pkey[TAG_COEFF].big, pkey[TAG_COEFF].size, NULL);
+ RSA_set0_factors(rsa, bn_p, bn_q);
+ RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp);
+ RSA_set0_key(rsa, bn_n, bn_e, bn_d);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert RSA to EVP_PKEY
+ if (!EVP_PKEY_set1_RSA(ossl_pkey, rsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert RSA key to EVP_PKEY.\n");
+ RSA_free(rsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ RSA_free(rsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ DSA* dsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0 ||
+ pkey[TAG_PUBVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ dsa = DSA_new();
+ BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size, NULL);
+ BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size, NULL);
+ BIGNUM* bn_g = BN_bin2bn((unsigned char*)pkey[TAG_BASE].big, pkey[TAG_BASE].size, NULL);
+ BIGNUM* bn_priv_key = BN_bin2bn((unsigned char*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size, NULL);
+ BIGNUM* bn_pub_key = BN_bin2bn((unsigned char*)pkey[TAG_PUBVAL].big, pkey[TAG_PUBVAL].size, NULL);
+
+ DSA_set0_pqg(dsa, bn_p, bn_q, bn_g);
+ DSA_set0_key(dsa, bn_pub_key, bn_priv_key);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert DSA to EVP_PKEY
+ if (!EVP_PKEY_set1_DSA(ossl_pkey, dsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert DSA key to EVP_PKEY.\n");
+ DSA_free(dsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ DSA_free(dsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1 b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1
new file mode 100644
index 0000000..b716bc8
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1
@@ -0,0 +1,63 @@
+.TH SOFTHSM2-KEYCONV 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-keyconv \- converting from BIND to PKCS#8 key file format
+.SH SYNOPSIS
+.B softhsm2-keyconv
+.B \-\-in
+.I path
+.B \-\-out
+.I path
+.RB [ \-\-pin
+.IR PIN ]
+.SH DESCRIPTION
+.B softhsm2-keyconv
+can convert BIND .private-key files to the PKCS#8 file format.
+This is so that you can import the PKCS#8 file into
+libsofthsm using the command
+.BR softhsm2\-util .
+If you have another file format, then
+.B openssl
+probably can help you to convert it into the PKCS#8 file format.
+.SH OPTIONS
+.B \-\-help\fR, \fB\-h\fR
+Shows the help screen.
+.TP
+.B \-\-in \fIpath\fR
+The
+.I path
+to the input file.
+.TP
+.B \-\-out \fIpath\fR
+The
+.I path
+to the output file.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+will be used to encrypt the PKCS#8 file.
+If not given then the PKCS#8 file will be unencrypted.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLES
+The following command can be used to convert a BIND .private-key file to a PKCS#8 file:
+.LP
+.RS
+.nf
+softhsm2-keyconv \-\-in Kexample.com.+007+05474.private \\
+.ti +0.7i
+\-\-out rsa.pem
+.fi
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.SH "SEE ALSO"
+.IR softhsm2-migrate (1),
+.IR softhsm2-util (1),
+.IR softhsm2.conf (5),
+.IR openssl (1),
+.IR named (1),
+.IR dnssec-keygen (1),
+.IR dnssec-signzone (1)
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp
new file mode 100644
index 0000000..aeb75c3
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/************************************************************
+*
+* softhsm2-keyconv
+*
+* This program is for converting from BIND .private-key
+* format to PKCS#8 key file format. So that keys can be
+* imported from BIND to SoftHSM.
+*
+* Some of the design/code is from keyconv.c written by
+* Hakan Olsson and Jakob Schlyter in 2000 and 2001.
+*
+************************************************************/
+
+#include <config.h>
+#include "softhsm2-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define open _open
+#define close _close
+#endif
+#include <iostream>
+#include <fstream>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void usage()
+{
+ printf("Converting from BIND .private-key format to PKCS#8 key file format.\n");
+ printf("Usage: softhsm2-keyconv [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --in <path> The path to the input file.\n");
+ printf(" --out <path> The path to the output file.\n");
+ printf(" --pin <PIN> To encrypt PKCS#8 file. Optional.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Give a number to each option
+enum {
+ OPT_HELP = 0x100,
+ OPT_IN,
+ OPT_OUT,
+ OPT_PIN,
+ OPT_VERSION
+};
+
+// Define the options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "in", 1, NULL, OPT_IN },
+ { "out", 1, NULL, OPT_OUT },
+ { "pin", 1, NULL, OPT_PIN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt, result;
+
+ char* in_path = NULL;
+ char* out_path = NULL;
+ char* file_pin = NULL;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_IN:
+ in_path = optarg;
+ break;
+ case OPT_OUT:
+ out_path = optarg;
+ break;
+ case OPT_PIN:
+ file_pin = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // We should convert to PKCS#8
+ result = to_pkcs8(in_path, out_path, file_pin);
+
+ return result;
+}
+
+// Convert from BIND to PKCS#8
+int to_pkcs8(char* in_path, char* out_path, char* file_pin)
+{
+ FILE* file_pointer = NULL;
+ char line[MAX_LINE], data[MAX_LINE];
+ char* value_pointer = NULL;
+ int lineno = 0, m, n, error = 0, found, algorithm = DNS_KEYALG_ERROR, data_length;
+ uint32_t bitfield = 0;
+ key_material_t pkey[TAG_MAX];
+
+ if (in_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the input file must be supplied. Use --in <path>\n");
+ return 1;
+ }
+
+ if (out_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the output file must be supplied. Use --out <path>\n");
+ return 1;
+ }
+
+ file_pointer = fopen(in_path, "r");
+ if (file_pointer == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open input file %.100s for reading.\n", in_path);
+ return 1;
+ }
+
+ // Loop over all of the lines
+ while (fgets(line, MAX_LINE, file_pointer) != NULL)
+ {
+ lineno++;
+
+ // Find the current text field in the BIND file.
+ for (m = 0, found = -1; found == -1 && file_tags[m]; m++)
+ {
+ if (strncasecmp(line, file_tags[m], strlen(file_tags[m])) == 0)
+ {
+ found = m;
+ }
+ }
+
+ // The text files is not recognized.
+ if (found == -1)
+ {
+ fprintf(stderr, "ERROR: Unrecognized input line %i\n", lineno);
+ fprintf(stderr, "ERROR: --> %s", line);
+ continue;
+ }
+
+ // Point to the data for this text field.
+ value_pointer = line + strlen(file_tags[found]) + 1;
+
+ // Continue if we are at the end of the string
+ if (*value_pointer == 0)
+ {
+ continue;
+ }
+
+ // Check that we do not get duplicates.
+ if (bitfield & (1 << found))
+ {
+ fprintf(stderr, "ERROR: Duplicate \"%s\" field, line %i - ignored\n",
+ file_tags[found], lineno);
+ continue;
+ }
+ bitfield |= (1 << found);
+
+ // Handle the data for this text field.
+ switch (found)
+ {
+ case TAG_VERSION:
+ if (sscanf(value_pointer, "v%i.%i", &m, &n) != 2)
+ {
+ fprintf(stderr, "ERROR: Invalid/unknown version string "
+ "(%.100s).\n", value_pointer);
+ error = 1;
+ break;
+ }
+ if (m > FILE_MAJOR_VERSION || (m == FILE_MAJOR_VERSION && n > FILE_MINOR_VERSION))
+ {
+ fprintf(stderr, "ERROR: Cannot parse this version of file format, "
+ "v%i.%i.\n", m, n);
+ error = 1;
+ }
+ break;
+ case TAG_ALGORITHM:
+ algorithm = strtol(value_pointer, NULL, 10);
+ break;
+ // RSA
+ case TAG_MODULUS:
+ case TAG_PUBEXP:
+ case TAG_PRIVEXP:
+ case TAG_PRIME1:
+ case TAG_PRIME2:
+ case TAG_EXP1:
+ case TAG_EXP2:
+ case TAG_COEFF:
+ // DSA
+ case TAG_PRIME:
+ case TAG_SUBPRIME:
+ case TAG_BASE:
+ case TAG_PRIVVAL:
+ case TAG_PUBVAL:
+ data_length = b64_pton(value_pointer, (unsigned char*)data, MAX_LINE);
+ if (data_length == -1)
+ {
+ error = 1;
+ fprintf(stderr, "ERROR: Could not parse the base64 string on line %i.\n", lineno);
+ }
+ else
+ {
+ pkey[found].big = malloc(data_length);
+ if (!pkey[found].big)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ error = 1;
+ break;
+ }
+ memcpy(pkey[found].big, data, data_length);
+ pkey[found].size = data_length;
+ }
+ break;
+ // Do not need these
+ case TAG_CREATED:
+ case TAG_PUBLISH:
+ case TAG_ACTIVATE:
+ default:
+ break;
+ }
+ }
+
+ fclose(file_pointer);
+
+ // Something went wrong. Clean up and quit.
+ if (error)
+ {
+ free_key_material(pkey);
+ return error;
+ }
+
+ // Create and set file permissions if the file does not exist.
+ int fd = open(out_path, O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ {
+ fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+ out_path, errno);
+ free_key_material(pkey);
+ return 1;
+ }
+ ::close(fd);
+
+ crypto_init();
+
+ // Save the the key to the disk
+ switch (algorithm)
+ {
+ case DNS_KEYALG_ERROR:
+ fprintf(stderr, "ERROR: The algorithm %i was not given in the file.\n",
+ algorithm);
+ error = 1;
+ break;
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_RSASHA1_NSEC3_SHA1:
+ case DNS_KEYALG_RSASHA256:
+ case DNS_KEYALG_RSASHA512:
+ error = save_rsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_DSA_NSEC3_SHA1:
+ error = save_dsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_ECC:
+ case DNS_KEYALG_ECC_GOST:
+ default:
+ fprintf(stderr, "ERROR: The algorithm %i is not supported.\n",
+ algorithm);
+ error = 1;
+ break;
+ }
+
+ crypto_final();
+ free_key_material(pkey);
+
+ return error;
+}
+
+// Free allocated memory
+void free_key_material(key_material_t* pkey)
+{
+ int i;
+
+ if (!pkey)
+ {
+ return;
+ }
+
+ for (i = 0; i < TAG_MAX; i++)
+ {
+ if (pkey[i].big)
+ {
+ free(pkey[i].big);
+ }
+ }
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h
new file mode 100644
index 0000000..fdeb719
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_KEYCONV_H
+#define _SOFTHSM_V2_SOFTHSM2_KEYCONV_H 1
+
+#include <stdlib.h>
+
+typedef struct key_material_t {
+ unsigned long size;
+ void* big;
+ key_material_t() {
+ size = 0;
+ big = NULL;
+ }
+} key_material_t;
+
+// Main functions
+
+void usage();
+int to_pkcs8(char* in_path, char* out_path, char* file_pin);
+
+// Support functions
+
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+void free_key_material(key_material_t* pkey);
+void crypto_init();
+void crypto_final();
+
+// base64.c prototypes
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int b64_pton(const char* , unsigned char*, size_t);
+int b64_ntop(const unsigned char*, size_t, char*, size_t);
+#ifdef __cplusplus
+}
+#endif
+
+// The BIND file version number.
+#define FILE_MAJOR_VERSION 1
+#define FILE_MINOR_VERSION 3
+
+// Key algorithm number
+#define DNS_KEYALG_ERROR -1
+#define DNS_KEYALG_RSAMD5 1
+#define DNS_KEYALG_DSA 3
+#define DNS_KEYALG_ECC 4
+#define DNS_KEYALG_RSASHA1 5
+#define DNS_KEYALG_DSA_NSEC3_SHA1 6
+#define DNS_KEYALG_RSASHA1_NSEC3_SHA1 7
+#define DNS_KEYALG_RSASHA256 8
+#define DNS_KEYALG_RSASHA512 10
+#define DNS_KEYALG_ECC_GOST 12
+
+// Maximum number of lines / line length
+#define MAX_LINE 4096
+
+// The text fields supported
+#if !defined(KEYCONV_BOTAN) && !defined(KEYCONV_OSSL)
+static const char* file_tags[] = {
+ "Private-key-format:",
+ "Algorithm:",
+ "Modulus:",
+ "PublicExponent:",
+ "PrivateExponent:",
+ "Prime1:",
+ "Prime2:",
+ "Exponent1:",
+ "Exponent2:",
+ "Coefficient:",
+ "Prime(p):",
+ "Private_value(x):",
+ "Public_value(y):",
+ "Subprime(q):",
+ "Base(g):",
+ "Created:",
+ "Publish:",
+ "Activate:",
+ NULL
+};
+#endif
+
+// The number of each text field.
+// Must match the tags above.
+enum FILE_TAGS {
+ TAG_VERSION = 0,
+ TAG_ALGORITHM,
+ TAG_MODULUS,
+ TAG_PUBEXP,
+ TAG_PRIVEXP,
+ TAG_PRIME1,
+ TAG_PRIME2,
+ TAG_EXP1,
+ TAG_EXP2,
+ TAG_COEFF,
+ TAG_PRIME,
+ TAG_PRIVVAL,
+ TAG_PUBVAL,
+ TAG_SUBPRIME,
+ TAG_BASE,
+ TAG_CREATED,
+ TAG_PUBLISH,
+ TAG_ACTIVATE,
+ // So we know how long this list is
+ TAG_MAX
+};
+
+#endif /* _SOFTHSM_V2_SOFTHSM2_KEYCONV_H */
diff --git a/SoftHSMv2/src/bin/migrate/Makefile.am b/SoftHSMv2/src/bin/migrate/Makefile.am
new file mode 100644
index 0000000..020c6a7
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/Makefile.am
@@ -0,0 +1,20 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/pkcs11 \
+ -I$(srcdir)/../common \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm2-migrate.1
+
+bin_PROGRAMS = softhsm2-migrate
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+softhsm2_migrate_SOURCES = softhsm2-migrate.cpp \
+ ../common/findslot.cpp \
+ ../common/getpw.cpp \
+ ../common/library.cpp
+softhsm2_migrate_LDADD = @SQLITE3_LIBS@ \
+ @YIELD_LIB@
+
+EXTRA_DIST = $(srcdir)/*.h
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.1 b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.1
new file mode 100644
index 0000000..65dc00c
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.1
@@ -0,0 +1,67 @@
+.TH SOFTHSM2-MIGRATE 1 "20 April 2016" "SoftHSM"
+.SH NAME
+softhsm2-migrate \- SoftHSM v1 migration tool
+.SH SYNOPSIS
+.PP
+.B softhsm2-migrate \-\-db
+.I path
+.B \-\-token
+.I label
+.RB [ \-\-pin
+.I PIN
+.B \-\-no\-public\-key]
+.SH DESCRIPTION
+.B softhsm2-migrate
+is a tool that can migrate SoftHSM v1 databases to PKCS#11.
+The default HSM is SoftHSM v2, but can be used with other
+PKCS#11 libraries by using the option
+.B \-\-module
+.LP
+.SH OPTIONS
+.TP
+.B \-\-db \fIpath\fR
+The SoftHSM v1 database that is going to be migrated.
+The location of the token database can be found in
+the configuration file for SoftHSM v1.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
+.TP
+.B \-\-module \fIpath\fR
+Use another PKCS#11 library than SoftHSM.
+.TP
+.B \-\-no\-public\-key
+Do not migrate the public key.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+for the normal user.
+.TP
+.B \-\-serial \fInumber\fR
+Will use the token with a matching serial number.
+.TP
+.B \-\-slot \fInumber\fR
+The database will be migrated to this slot.
+.TP
+.B \-\-token \fIlabel\fR
+Will use the token with a matching token label.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLE
+.LP
+A token database can be migrated with the following command:
+.LP
+.RS
+.nf
+softhsm2-migrate \-\-db /home/user/token.db \-\-token mytoken
+.fi
+.RE
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.LP
+.SH "SEE ALSO"
+.IR softhsm2-keyconv (1),
+.IR softhsm2-util (1),
+.IR softhsm2.conf (5)
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
new file mode 100644
index 0000000..0e6dc90
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
@@ -0,0 +1,798 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-migrate.cpp
+
+ This program can be used for migrating SoftHSM v1 databases to any
+ PKCS#11 library. The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm2-migrate.h"
+#include "findslot.h"
+#include "getpw.h"
+#include "library.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+#include <iostream>
+#include <fstream>
+#include <sched.h>
+
+#ifdef _WIN32
+#define sched_yield() SleepEx(0, 0)
+#endif
+
+// Display the usage
+void usage()
+{
+ printf("SoftHSM migration tool. From SoftHSM v1 database to PKCS#11.\n");
+ printf("Usage: softhsm2-migrate [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --db <path> The SoftHSM v1 database that is going to be migrated.\n");
+ printf(" --module <path> Use another PKCS#11 library than SoftHSM.\n");
+ printf(" --no-public-key Do not migrate the public key.\n");
+ printf(" --pin <PIN> The PIN for the normal user.\n");
+ printf(" --serial <number> Will use the token with a matching serial number.\n");
+ printf(" --slot <number> The slot where the token is located.\n");
+ printf(" --token <label> Will use the token with a matching token label.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Enumeration of the long options
+enum {
+ OPT_HELP = 0x100,
+ OPT_DB,
+ OPT_MODULE,
+ OPT_NO_PUBLIC_KEY,
+ OPT_PIN,
+ OPT_SERIAL,
+ OPT_SLOT,
+ OPT_TOKEN,
+ OPT_VERSION
+};
+
+// Text representation of the long options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "db", 1, NULL, OPT_DB },
+ { "module", 1, NULL, OPT_MODULE },
+ { "no-public-key", 0, NULL, OPT_NO_PUBLIC_KEY },
+ { "pin", 1, NULL, OPT_PIN },
+ { "serial", 1, NULL, OPT_SERIAL },
+ { "slot", 1, NULL, OPT_SLOT },
+ { "token" , 1, NULL, OPT_TOKEN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+CK_FUNCTION_LIST_PTR p11;
+
+// Prepared statements
+sqlite3_stmt* select_an_attribute_sql = NULL;
+sqlite3_stmt* select_object_ids_sql = NULL;
+sqlite3_stmt* count_object_id_sql = NULL;
+
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt;
+
+ char* dbPath = NULL;
+ char* userPIN = NULL;
+ char* module = NULL;
+ char* slot = NULL;
+ char* serial = NULL;
+ char* token = NULL;
+ char *errMsg = NULL;
+ int noPublicKey = 0;
+
+ int result = 0;
+ CK_RV rv;
+
+ moduleHandle = NULL;
+ p11 = NULL;
+ CK_SLOT_ID slotID = 0;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_DB:
+ dbPath = optarg;
+ break;
+ case OPT_SLOT:
+ slot = optarg;
+ break;
+ case OPT_SERIAL:
+ serial = optarg;
+ break;
+ case OPT_TOKEN:
+ token = optarg;
+ break;
+ case OPT_MODULE:
+ module = optarg;
+ break;
+ case OPT_NO_PUBLIC_KEY:
+ noPublicKey = 1;
+ break;
+ case OPT_PIN:
+ userPIN = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // Get a pointer to the function list for PKCS#11 library
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(module, &moduleHandle, &errMsg);
+ if (pGetFunctionList == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not load the PKCS#11 library/module: %s\n", errMsg);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+
+ // Load the function list
+ (*pGetFunctionList)(&p11);
+
+ // Initialize the library
+ rv = p11->C_Initialize(NULL_PTR);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the PKCS#11 library/module: %s\n", module ? module : DEFAULT_PKCS11_LIB);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+
+ // Get the slotID
+ result = findSlot(slot, serial, token, slotID);
+
+ if (!result)
+ {
+ // Migrate the database
+ result = migrate(dbPath, slotID, userPIN, noPublicKey);
+ }
+
+ // Finalize the library
+ p11->C_Finalize(NULL_PTR);
+ unloadLibrary(moduleHandle);
+
+ return result;
+}
+
+// Migrate the database
+int migrate(char* dbPath, CK_SLOT_ID slotID, char* userPIN, int noPublicKey)
+{
+ CK_SESSION_HANDLE hSession;
+ sqlite3* db = NULL;
+ int result;
+
+ if (dbPath == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the database must be supplied. "
+ "Use --db <path>\n");
+ return 1;
+ }
+
+ // Open the database
+ db = openDB(dbPath);
+ if (db == NULL)
+ {
+ return 1;
+ }
+
+ // Connect to the PKCS#11 library
+ result = openP11(slotID, userPIN, &hSession);
+ if (result)
+ {
+ sqlite3_close(db);
+ return result;
+ }
+
+ // Prepare the statements
+ if (prepStatements(db))
+ {
+ fprintf(stderr, "ERROR: Could not prepare the statements\n");
+ finalStatements();
+ sqlite3_close(db);
+ return 1;
+ }
+
+ // Start the migration
+ result = db2session(db, hSession, noPublicKey);
+
+ // Finalize the statements
+ finalStatements();
+
+ sqlite3_close(db);
+
+ if (result)
+ {
+ fprintf(stderr, "ERROR: Unable to migrate all of the objects.\n");
+ }
+ else
+ {
+ printf("The database has been migrated to the new HSM\n");
+ }
+
+ return result;
+}
+
+// Prepare the statements
+int prepStatements(sqlite3* db)
+{
+ select_an_attribute_sql = NULL;
+ select_object_ids_sql = NULL;
+ count_object_id_sql = NULL;
+
+ const char select_an_attribute_str[] = "SELECT value,length FROM Attributes WHERE objectID = ? AND type = ?;";
+ const char select_object_ids_str[] = "SELECT objectID FROM Objects;";
+ const char count_object_id_str[] = "SELECT COUNT(objectID) FROM Objects;";
+
+ if
+ (
+ sqlite3_prepare_v2(db, select_an_attribute_str, -1, &select_an_attribute_sql, NULL) ||
+ sqlite3_prepare_v2(db, select_object_ids_str, -1, &select_object_ids_sql, NULL) ||
+ sqlite3_prepare_v2(db, count_object_id_str, -1, &count_object_id_sql, NULL)
+ )
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+// Finalize the statements
+void finalStatements()
+{
+ if (select_an_attribute_sql) sqlite3_finalize(select_an_attribute_sql);
+ if (select_object_ids_sql) sqlite3_finalize(select_object_ids_sql);
+ if (count_object_id_sql) sqlite3_finalize(count_object_id_sql);
+}
+
+// Open a connection to a valid SoftHSM v1 database
+sqlite3* openDB(char* dbPath)
+{
+ int result;
+ sqlite3* db = NULL;
+ sqlite3_stmt* pragStatem = NULL;
+ int dbVersion;
+
+ // Open the database
+ result = sqlite3_open(dbPath, &db);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: Could not open token database. "
+ "Probably wrong path or privileges: %s\n", dbPath);
+ return NULL;
+ }
+
+ // Check the schema version
+ if (sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &pragStatem, NULL))
+ {
+ fprintf(stderr, "ERROR: Could not prepare a SQL statement\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+ if (sqlite3_step(pragStatem) == SQLITE_ROW)
+ {
+ dbVersion = sqlite3_column_int(pragStatem, 0);
+ sqlite3_finalize(pragStatem);
+
+ if (dbVersion != 100)
+ {
+ fprintf(stderr, "ERROR: Wrong database schema version: %s\n", dbPath);
+ sqlite3_close(db);
+ return NULL;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: The token database has not been initialized by SoftHSM\n");
+ sqlite3_finalize(pragStatem);
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Token table exist
+ result = sqlite3_exec(db, "SELECT COUNT(variableID) FROM Token;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Token table is missing the in database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Objects table exist
+ result = sqlite3_exec(db, "SELECT COUNT(objectID) FROM Objects;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Objects table is missing the in database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ // Check that the Attributes table exist
+ result = sqlite3_exec(db, "SELECT COUNT(attributeID) FROM Attributes;", NULL, NULL, NULL);
+ if (result)
+ {
+ fprintf(stderr, "ERROR: The Attributes table is missing in the database\n");
+ sqlite3_close(db);
+ return NULL;
+ }
+
+ return db;
+}
+
+// Connect and login to the token
+int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+ CK_RV rv;
+
+ rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ return 1;
+ }
+
+ // Get the password
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ return 1;
+ }
+
+ rv = p11->C_Login(*hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+// Migrate the database to the session
+int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey)
+{
+ CK_ULONG objectCount;
+ int result = 0, rv;
+ CK_OBJECT_HANDLE* objects = NULL;
+ CK_OBJECT_CLASS ckClass;
+
+ // Get all objects
+ objects = getObjects(db, &objectCount);
+ if (objects == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not find any objects in the database.\n");
+ return 1;
+ }
+
+ // Loop over all objects
+ for (unsigned i = 0; i < objectCount; i++)
+ {
+ ckClass = getObjectClass(objects[i]);
+
+ switch (ckClass)
+ {
+ case CKO_PUBLIC_KEY:
+ if (noPublicKey) continue;
+ if (getKeyType(objects[i]) != CKK_RSA)
+ {
+ fprintf(stderr, "ERROR: Cannot export object %lu. Only supporting RSA keys. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ }
+ rv = dbRSAPub2session(db, objects[i], hSession);
+ if (rv) result = 1;
+ break;
+ case CKO_PRIVATE_KEY:
+ if (getKeyType(objects[i]) != CKK_RSA)
+ {
+ fprintf(stderr, "ERROR: Cannot export object %lu. Only supporting RSA keys. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ }
+ rv = dbRSAPriv2session(db, objects[i], hSession);
+ if (rv) result = 1;
+ break;
+ case CKO_VENDOR_DEFINED:
+ fprintf(stderr, "ERROR: Could not get the class of object %lu. "
+ "Continuing.\n", objects[i]);
+ result = 1;
+ break;
+ default:
+ fprintf(stderr, "ERROR: Not supporting class %lu in object %lu. "
+ "Continuing.\n", ckClass, objects[i]);
+ result = 1;
+ break;
+ }
+ }
+
+ free(objects);
+
+ return result;
+}
+
+// Get the key type from key objects
+CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef)
+{
+ int retSQL = 0;
+ CK_KEY_TYPE retVal = CKK_VENDOR_DEFINED;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, CKA_KEY_TYPE);
+
+ // Get result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (pValue != NULL_PTR && length == sizeof(CK_KEY_TYPE))
+ {
+ retVal = *(CK_KEY_TYPE*)pValue;
+ }
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Get the class of the object
+CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef)
+{
+ int retSQL = 0;
+ CK_OBJECT_CLASS retVal = CKO_VENDOR_DEFINED;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, CKA_CLASS);
+
+ // Get the result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (pValue != NULL_PTR && length == sizeof(CK_OBJECT_CLASS))
+ {
+ retVal = *(CK_OBJECT_CLASS*)pValue;
+ }
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Get all object IDs
+CK_OBJECT_HANDLE* getObjects(sqlite3* /*db*/, CK_ULONG* objectCount)
+{
+ CK_ULONG objectsInDB;
+ CK_ULONG counter = 0;
+ CK_OBJECT_HANDLE* objectRefs = NULL;
+ int retSQL = 0;
+
+ *objectCount = 0;
+
+ // Find out how many objects we have.
+ while ((retSQL = sqlite3_step(count_object_id_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ if (retSQL != SQLITE_ROW)
+ {
+ fprintf(stderr, "ERROR: Could not count the number of objects in the database\n");
+ sqlite3_reset(count_object_id_sql);
+ return NULL;
+ }
+
+ // Get the number of objects
+ objectsInDB = sqlite3_column_int(count_object_id_sql, 0);
+ sqlite3_reset(count_object_id_sql);
+
+ if (!objectsInDB)
+ {
+ fprintf(stderr, "ERROR: There are not objects in the database\n");
+ return NULL;
+ }
+
+ // Create the object-reference buffer
+ objectRefs = (CK_OBJECT_HANDLE*)malloc(objectsInDB * sizeof(CK_OBJECT_HANDLE));
+ if (objectRefs == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory\n");
+ return NULL;
+ }
+
+ // Get all the object ids
+ while
+ (
+ ((retSQL = sqlite3_step(select_object_ids_sql)) == SQLITE_BUSY || retSQL == SQLITE_ROW) &&
+ counter < objectsInDB
+ )
+ {
+ if(retSQL == SQLITE_BUSY)
+ {
+ sched_yield();
+ continue;
+ }
+
+ objectRefs[counter++] = sqlite3_column_int(select_object_ids_sql, 0);
+ }
+
+ *objectCount = counter;
+
+ sqlite3_reset(select_object_ids_sql);
+
+ return objectRefs;
+}
+
+// Extract the information about the public RSA key and save it in the token
+int dbRSAPub2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession)
+{
+ int result = 0;
+ int i;
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv;
+
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_START_DATE, NULL, 0 },
+ { CKA_END_DATE, NULL, 0 },
+ { CKA_DERIVE, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_ENCRYPT, NULL, 0 },
+ { CKA_VERIFY, NULL, 0 },
+ { CKA_VERIFY_RECOVER, NULL, 0 },
+ { CKA_WRAP, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 }
+ };
+
+ for (i = 0; i < 17; i++)
+ {
+ result = getAttribute(objectID, &pubTemplate[i]);
+ if (result)
+ {
+ freeTemplate(pubTemplate, 17);
+ return 1;
+ }
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 17, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR %X: Could not save the public key in the token. "
+ "Skipping object %lu\n", (unsigned int)rv, objectID);
+ result = 1;
+ }
+ else
+ {
+ printf("Object %lu has been migrated\n", objectID);
+ }
+
+ freeTemplate(pubTemplate, 17);
+
+ return result;
+}
+
+// Extract the information about the private RSA key and save it in the token
+int dbRSAPriv2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession)
+{
+ int result = 0;
+ int i;
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv;
+
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, NULL, 0 },
+ { CKA_TOKEN, NULL, 0 },
+ { CKA_PRIVATE, NULL, 0 },
+ { CKA_MODIFIABLE, NULL, 0 },
+ { CKA_LABEL, NULL, 0 },
+ { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_ID, NULL, 0 },
+ { CKA_START_DATE, NULL, 0 },
+ { CKA_END_DATE, NULL, 0 },
+ { CKA_DERIVE, NULL, 0 },
+ { CKA_SUBJECT, NULL, 0 },
+ { CKA_SENSITIVE, NULL, 0 },
+ { CKA_DECRYPT, NULL, 0 },
+ { CKA_SIGN, NULL, 0 },
+ { CKA_SIGN_RECOVER, NULL, 0 },
+ { CKA_UNWRAP, NULL, 0 },
+ { CKA_EXTRACTABLE, NULL, 0 },
+ { CKA_WRAP_WITH_TRUSTED, NULL, 0 },
+ { CKA_MODULUS, NULL, 0 },
+ { CKA_PUBLIC_EXPONENT, NULL, 0 },
+ { CKA_PRIVATE_EXPONENT, NULL, 0 },
+ { CKA_PRIME_1, NULL, 0 },
+ { CKA_PRIME_2, NULL, 0 }
+// SoftHSM v1 did not store these values
+// { CKA_EXPONENT_1, NULL, 0 },
+// { CKA_EXPONENT_2, NULL, 0 },
+// { CKA_COEFFICIENT, NULL, 0 }
+ };
+
+ for (i = 0; i < 23; i++)
+ {
+ result = getAttribute(objectID, &privTemplate[i]);
+ if (result)
+ {
+ freeTemplate(privTemplate, 23);
+ return 1;
+ }
+ }
+
+ rv = p11->C_CreateObject(hSession, privTemplate, 23, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR %X: Could not save the private key in the token. "
+ "Skipping object %lu\n", (unsigned int)rv, objectID);
+ result = 1;
+ }
+ else
+ {
+ printf("Object %lu has been migrated\n", objectID);
+ }
+
+ freeTemplate(privTemplate, 23);
+
+ return result;
+}
+
+// Get the value of the given attribute
+int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate)
+{
+ int retSQL = 0;
+ int retVal = 0;
+
+ sqlite3_bind_int(select_an_attribute_sql, 1, objectRef);
+ sqlite3_bind_int(select_an_attribute_sql, 2, attTemplate->type);
+
+ // Get result
+ while ((retSQL = sqlite3_step(select_an_attribute_sql)) == SQLITE_BUSY)
+ {
+ sched_yield();
+ }
+
+ // Get the attribute
+ if (retSQL == SQLITE_ROW)
+ {
+ CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
+ CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
+
+ if (length)
+ {
+ attTemplate->pValue = malloc(length);
+ if (!attTemplate->pValue)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory. "
+ "Skipping object %lu\n", objectRef);
+ retVal = 1;
+ }
+ else
+ {
+ // Copy data
+ memcpy(attTemplate->pValue, pValue, length);
+ }
+ }
+
+ attTemplate->ulValueLen = length;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Do not have attribute %lu. "
+ "Skipping object %lu\n", attTemplate->type, objectRef);
+ retVal = 1;
+ }
+
+ sqlite3_reset(select_an_attribute_sql);
+
+ return retVal;
+}
+
+// Free allocated memory in the template
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int size)
+{
+ int i;
+
+ if (!attTemplate) return;
+
+ for (i = 0; i < size; i++)
+ {
+ if(attTemplate[i].pValue)
+ {
+ free(attTemplate[i].pValue);
+ }
+ }
+}
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
new file mode 100644
index 0000000..1b5a066
--- /dev/null
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-migrate.h
+
+ This program can be used for migrating SoftHSM v1 databases to any
+ PKCS#11 library. The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_MIGRATE_H
+#define _SOFTHSM_V2_SOFTHSM2_MIGRATE_H
+
+#include "cryptoki.h"
+#include <sqlite3.h>
+
+// Main functions
+
+void usage();
+int migrate(char* dbPath, CK_SLOT_ID slotID, char* userPIN, int noPublicKey);
+
+// Support functions
+
+sqlite3* openDB(char* dbPath);
+int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession);
+int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey);
+int dbRSAPub2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
+int dbRSAPriv2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int size);
+
+// Database functions
+
+CK_OBJECT_HANDLE* getObjects(sqlite3* db, CK_ULONG* objectCount);
+CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef);
+CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef);
+int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate);
+int prepStatements(sqlite3* db);
+void finalStatements();
+
+// Library
+
+static void* moduleHandle;
+extern CK_FUNCTION_LIST_PTR p11;
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_MIGRATE_H
diff --git a/SoftHSMv2/src/bin/util/Makefile.am b/SoftHSMv2/src/bin/util/Makefile.am
new file mode 100644
index 0000000..a552e14
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/Makefile.am
@@ -0,0 +1,40 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../common \
+ -I$(srcdir)/../../lib/ \
+ -I$(srcdir)/../../lib/common \
+ -I$(srcdir)/../../lib/crypto \
+ -I$(srcdir)/../../lib/data_mgr \
+ -I$(srcdir)/../../lib/object_store \
+ -I$(srcdir)/../../lib/pkcs11 \
+ @CRYPTO_INCLUDES@ \
+ @SQLITE3_INCLUDES@
+
+dist_man_MANS = softhsm2-util.1
+
+bin_PROGRAMS = softhsm2-util
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+softhsm2_util_SOURCES = softhsm2-util.cpp \
+ ../common/findslot.cpp \
+ ../common/getpw.cpp \
+ ../common/library.cpp
+
+softhsm2_util_LDADD = @CRYPTO_LIBS@ \
+ @SQLITE3_LIBS@ \
+ ../../lib/libsofthsm_convarch.la
+
+# Compile with support of OpenSSL
+if WITH_OPENSSL
+softhsm2_util_SOURCES += softhsm2-util-ossl.cpp \
+ ../../lib/crypto/OSSLComp.cpp
+endif
+
+# Compile with support of Botan
+if WITH_BOTAN
+softhsm2_util_SOURCES += softhsm2-util-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
new file mode 100644
index 0000000..cecc0ce
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-util-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#define UTIL_BOTAN
+#include "softhsm2-util.h"
+#include "softhsm2-util-botan.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/bigint.h>
+#include <botan/version.h>
+#include <botan/der_enc.h>
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/libstate.h>
+bool wasInitialized = false;
+#endif
+
+// Init Botan
+void crypto_init()
+{
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ // The PKCS#11 library might be using Botan
+ // Check if it has already initialized Botan
+ if (Botan::Global_State_Management::global_state_exists())
+ {
+ wasInitialized = true;
+ }
+
+ if (!wasInitialized)
+ {
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+ }
+#else
+ Botan::LibraryInitializer::initialize("thread_safe=true");
+#endif
+}
+
+// Final Botan
+void crypto_final()
+{
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ if (!wasInitialized)
+ {
+ Botan::LibraryInitializer::deinitialize();
+ }
+#else
+ Botan::LibraryInitializer::deinitialize();
+#endif
+}
+
+// Import a aes secret key from given path
+int crypto_import_aes_key
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* label,
+ char* objID,
+ size_t objIDLen
+)
+{
+ const size_t cMaxAesKeySize = 1024 + 1; // including null-character
+ char aesKeyValue[cMaxAesKeySize];
+ FILE* fp = fopen(filePath, "rb");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open the secret key file.\n");
+ return 1;
+ }
+ if (fgets(aesKeyValue, cMaxAesKeySize, fp) == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not read the secret key file.\n");
+ fclose(fp);
+ return 1;
+ }
+ fclose(fp);
+
+ CK_BBOOL ckTrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE keyTemplate[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_VALUE, &aesKeyValue, strlen(aesKeyValue) }
+ };
+
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv = p11->C_CreateObject(hSession, keyTemplate, 9, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the secret key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+// Import a key pair from given path
+int crypto_import_key_pair
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* filePIN,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey
+)
+{
+ Botan::Private_Key* pkey = crypto_read_file(filePath, filePIN);
+ if (pkey == NULL)
+ {
+ return 1;
+ }
+
+ Botan::RSA_PrivateKey* rsa = NULL;
+ Botan::DSA_PrivateKey* dsa = NULL;
+#ifdef WITH_ECC
+ Botan::ECDSA_PrivateKey* ecdsa = NULL;
+#endif
+
+ if (pkey->algo_name().compare("RSA") == 0)
+ {
+ rsa = dynamic_cast<Botan::RSA_PrivateKey*>(pkey);
+ }
+ else if (pkey->algo_name().compare("DSA") == 0)
+ {
+ dsa = dynamic_cast<Botan::DSA_PrivateKey*>(pkey);
+ }
+#ifdef WITH_ECC
+ else if (pkey->algo_name().compare("ECDSA") == 0)
+ {
+ ecdsa = dynamic_cast<Botan::ECDSA_PrivateKey*>(pkey);
+ }
+#endif
+ else
+ {
+ fprintf(stderr, "ERROR: %s is not a supported algorithm.\n",
+ pkey->algo_name().c_str());
+ delete pkey;
+ return 1;
+ }
+
+ int result = 0;
+
+ if (rsa)
+ {
+ result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa);
+ }
+ else if (dsa)
+ {
+ result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa);
+ }
+#ifdef WITH_ECC
+ else if (ecdsa)
+ {
+ result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa);
+ }
+#endif
+ else
+ {
+ fprintf(stderr, "ERROR: Could not get the key material.\n");
+ result = 1;
+ }
+
+ delete pkey;
+ return result;
+}
+
+// Read the key from file
+Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN)
+{
+ if (filePath == NULL)
+ {
+ return NULL;
+ }
+
+ Botan::AutoSeeded_RNG* rng = new Botan::AutoSeeded_RNG();
+ Botan::Private_Key* pkey = NULL;
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ if (filePIN == NULL)
+ {
+ pkey = Botan::PKCS8::load_key(std::string(filePath), *rng);
+ }
+ else
+ {
+ pkey = Botan::PKCS8::load_key(std::string(filePath), *rng, std::string(filePIN));
+ }
+#else
+ if (filePIN == NULL)
+ {
+ pkey = Botan::PKCS8::load_key(filePath, *rng);
+ }
+ else
+ {
+ pkey = Botan::PKCS8::load_key(filePath, *rng, filePIN);
+ }
+#endif
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Perhaps wrong path to file, wrong file format, "
+ "or wrong PIN to file (--file-pin <PIN>).\n");
+ delete rng;
+ return NULL;
+ }
+ delete rng;
+
+ return pkey;
+}
+
+// Save the key data in PKCS#11
+int crypto_save_rsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::RSA_PrivateKey* rsa
+)
+{
+ rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa);
+ if (!keyMat)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_WRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_UNWRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN },
+ { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD },
+ { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP },
+ { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 },
+ { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 },
+ { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_rsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_rsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* rsa)
+{
+ if (rsa == NULL)
+ {
+ return NULL;
+ }
+
+ rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeE = rsa->get_e().bytes();
+ keyMat->sizeN = rsa->get_n().bytes();
+ keyMat->sizeD = rsa->get_d().bytes();
+ keyMat->sizeP = rsa->get_p().bytes();
+ keyMat->sizeQ = rsa->get_q().bytes();
+ keyMat->sizeDMP1 = rsa->get_d1().bytes();
+ keyMat->sizeDMQ1 = rsa->get_d2().bytes();
+ keyMat->sizeIQMP = rsa->get_c().bytes();
+
+ keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE);
+ keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1);
+ keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1);
+ keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP);
+
+ if
+ (
+ !keyMat->bigE ||
+ !keyMat->bigN ||
+ !keyMat->bigD ||
+ !keyMat->bigP ||
+ !keyMat->bigQ ||
+ !keyMat->bigDMP1 ||
+ !keyMat->bigDMQ1 ||
+ !keyMat->bigIQMP
+ )
+ {
+ crypto_free_rsa(keyMat);
+ return NULL;
+ }
+
+ rsa->get_e().binary_encode((Botan::byte*)keyMat->bigE);
+ rsa->get_n().binary_encode((Botan::byte*)keyMat->bigN);
+ rsa->get_d().binary_encode((Botan::byte*)keyMat->bigD);
+ rsa->get_p().binary_encode((Botan::byte*)keyMat->bigP);
+ rsa->get_q().binary_encode((Botan::byte*)keyMat->bigQ);
+ rsa->get_d1().binary_encode((Botan::byte*)keyMat->bigDMP1);
+ rsa->get_d2().binary_encode((Botan::byte*)keyMat->bigDMQ1);
+ rsa->get_c().binary_encode((Botan::byte*)keyMat->bigIQMP);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_rsa(rsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigE) free(keyMat->bigE);
+ if (keyMat->bigN) free(keyMat->bigN);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigDMP1) free(keyMat->bigDMP1);
+ if (keyMat->bigDMQ1) free(keyMat->bigDMQ1);
+ if (keyMat->bigIQMP) free(keyMat->bigIQMP);
+ free(keyMat);
+}
+
+// Save the key data in PKCS#11
+int crypto_save_dsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::DSA_PrivateKey* dsa
+)
+{
+ dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigY, keyMat->sizeY }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigX, keyMat->sizeX }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_dsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2);
+ crypto_free_dsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* dsa)
+{
+ if (dsa == NULL)
+ {
+ return NULL;
+ }
+
+ dsa_key_material_t *keyMat = (dsa_key_material_t *)malloc(sizeof(dsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeP = dsa->group_p().bytes();
+ keyMat->sizeQ = dsa->group_q().bytes();
+ keyMat->sizeG = dsa->group_g().bytes();
+ keyMat->sizeX = dsa->get_x().bytes();
+ keyMat->sizeY = dsa->get_y().bytes();
+
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG);
+ keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX);
+ keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY);
+
+ if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY)
+ {
+ crypto_free_dsa(keyMat);
+ return NULL;
+ }
+
+ dsa->group_p().binary_encode((Botan::byte*)keyMat->bigP);
+ dsa->group_q().binary_encode((Botan::byte*)keyMat->bigQ);
+ dsa->group_g().binary_encode((Botan::byte*)keyMat->bigG);
+ dsa->get_x().binary_encode((Botan::byte*)keyMat->bigX);
+ dsa->get_y().binary_encode((Botan::byte*)keyMat->bigY);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_dsa(dsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigG) free(keyMat->bigG);
+ if (keyMat->bigX) free(keyMat->bigX);
+ if (keyMat->bigY) free(keyMat->bigY);
+ free(keyMat);
+}
+
+#ifdef WITH_ECC
+// Save the key data in PKCS#11
+int crypto_save_ecdsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::ECDSA_PrivateKey* ecdsa
+)
+{
+ ecdsa_key_material_t* keyMat = crypto_malloc_ecdsa(ecdsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_ECDSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_EC_POINT, keyMat->derQ, keyMat->sizeQ }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_VALUE, keyMat->bigD, keyMat->sizeD }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 13, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_ecdsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_ecdsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the Botan key to binary
+ecdsa_key_material_t* crypto_malloc_ecdsa(Botan::ECDSA_PrivateKey* ecdsa)
+{
+ if (ecdsa == NULL)
+ {
+ return NULL;
+ }
+
+ ecdsa_key_material_t *keyMat = (ecdsa_key_material_t *)malloc(sizeof(ecdsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ std::vector<Botan::byte> derEC = ecdsa->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ Botan::secure_vector<Botan::byte> derPoint;
+#else
+ Botan::SecureVector<Botan::byte> derEC = ecdsa->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID);
+ Botan::SecureVector<Botan::byte> derPoint;
+#endif
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> repr = Botan::EC2OSP(ecdsa->public_point(),
+ Botan::PointGFp::UNCOMPRESSED);
+#else
+ Botan::SecureVector<Botan::byte> repr = Botan::EC2OSP(ecdsa->public_point(),
+ Botan::PointGFp::UNCOMPRESSED);
+#endif
+
+ derPoint = Botan::DER_Encoder()
+ .encode(repr, Botan::OCTET_STRING)
+ .get_contents();
+ }
+ catch (...)
+ {
+ return NULL;
+ }
+
+ keyMat->sizeParams = derEC.size();
+ keyMat->sizeD = ecdsa->private_value().bytes();
+ keyMat->sizeQ = derPoint.size();
+
+ keyMat->derParams = (CK_VOID_PTR)malloc(keyMat->sizeParams);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+
+ if (!keyMat->derParams || !keyMat->bigD || !keyMat->derQ)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ memcpy(keyMat->derParams, &derEC[0], derEC.size());
+ ecdsa->private_value().binary_encode((Botan::byte*)keyMat->bigD);
+ memcpy(keyMat->derQ, &derPoint[0], derPoint.size());
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->derParams) free(keyMat->derParams);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->derQ) free(keyMat->derQ);
+ free(keyMat);
+}
+#endif
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.h b/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
new file mode 100644
index 0000000..8cd4a5e
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-util-botan.h
+
+ Header file for Botan implemented
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_UTIL_BOTAN_H
+#define _SOFTHSM_V2_SOFTHSM2_UTIL_BOTAN_H
+
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#ifdef WITH_ECC
+#include <botan/ecdsa.h>
+#endif
+
+typedef struct rsa_key_material_t {
+ CK_ULONG sizeE;
+ CK_ULONG sizeN;
+ CK_ULONG sizeD;
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeDMP1;
+ CK_ULONG sizeDMQ1;
+ CK_ULONG sizeIQMP;
+ CK_VOID_PTR bigE;
+ CK_VOID_PTR bigN;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigDMP1;
+ CK_VOID_PTR bigDMQ1;
+ CK_VOID_PTR bigIQMP;
+ rsa_key_material_t() {
+ sizeE = 0;
+ sizeN = 0;
+ sizeD = 0;
+ sizeP = 0;
+ sizeQ = 0;
+ sizeDMP1 = 0;
+ sizeDMQ1 = 0;
+ sizeIQMP = 0;
+ bigE = NULL_PTR;
+ bigN = NULL_PTR;
+ bigD = NULL_PTR;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigDMP1 = NULL_PTR;
+ bigDMQ1 = NULL_PTR;
+ bigIQMP = NULL_PTR;
+ }
+} rsa_key_material_t;
+
+typedef struct dsa_key_material_t {
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeG;
+ CK_ULONG sizeX;
+ CK_ULONG sizeY;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigG;
+ CK_VOID_PTR bigX;
+ CK_VOID_PTR bigY;
+ dsa_key_material_t() {
+ sizeP = 0;
+ sizeQ = 0;
+ sizeG = 0;
+ sizeX = 0;
+ sizeY = 0;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigG = NULL_PTR;
+ bigX = NULL_PTR;
+ bigY = NULL_PTR;
+ }
+} dsa_key_material_t;
+
+#ifdef WITH_ECC
+typedef struct ecdsa_key_material_t {
+ CK_ULONG sizeParams;
+ CK_ULONG sizeD;
+ CK_ULONG sizeQ;
+ CK_VOID_PTR derParams;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR derQ;
+ ecdsa_key_material_t() {
+ sizeParams = 0;
+ sizeD = 0;
+ sizeQ = 0;
+ derParams = NULL_PTR;
+ bigD = NULL_PTR;
+ derQ = NULL_PTR;
+ }
+} ecdsa_key_material_t;
+#endif
+
+Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN);
+
+// RSA
+int crypto_save_rsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::RSA_PrivateKey* rsa);
+rsa_key_material_t* crypto_malloc_rsa(Botan::RSA_PrivateKey* rsa);
+void crypto_free_rsa(rsa_key_material_t* keyMat);
+
+// DSA
+int crypto_save_dsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::DSA_PrivateKey* dsa);
+dsa_key_material_t* crypto_malloc_dsa(Botan::DSA_PrivateKey* dsa);
+void crypto_free_dsa(dsa_key_material_t* keyMat);
+
+// ECDSA
+#ifdef WITH_ECC
+int crypto_save_ecdsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::ECDSA_PrivateKey* ecdsa);
+ecdsa_key_material_t* crypto_malloc_ecdsa(Botan::ECDSA_PrivateKey* ecdsa);
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat);
+#endif
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
new file mode 100644
index 0000000..fedfd28
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
@@ -0,0 +1,790 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-util-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#define UTIL_OSSL
+#include "softhsm2-util.h"
+#include "softhsm2-util-ossl.h"
+#include "OSSLComp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ // We do not need to do this one
+ // OpenSSL_add_all_algorithms();
+#ifdef WITH_FIPS
+ // The PKCS#11 library might be using a FIPS capable OpenSSL
+ if (FIPS_mode())
+ return;
+ if (!FIPS_mode_set(1))
+ {
+ fprintf(stderr, "ERROR: can't enter into FIPS mode.\n");
+ exit(0);
+ }
+#endif
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ // EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+int crypto_import_aes_key
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* label,
+ char* objID,
+ size_t objIDLen
+)
+{
+ const size_t cMaxAesKeySize = 1024 + 1; // including null-character
+ char aesKeyValue[cMaxAesKeySize];
+ FILE* fp = fopen(filePath, "rb");
+ if (fp == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open the secret key file.\n");
+ return 1;
+ }
+ if (fgets(aesKeyValue, cMaxAesKeySize, fp) == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not read the secret key file.\n");
+ fclose(fp);
+ return 1;
+ }
+ fclose(fp);
+
+ CK_BBOOL ckTrue = CK_TRUE;
+ CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
+ CK_KEY_TYPE keyType = CKK_AES;
+ CK_ATTRIBUTE keyTemplate[] = {
+ { CKA_CLASS, &keyClass, sizeof(keyClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_VALUE, &aesKeyValue, strlen(aesKeyValue) }
+ };
+
+ CK_OBJECT_HANDLE hKey;
+ CK_RV rv = p11->C_CreateObject(hSession, keyTemplate, 9, &hKey);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the secret key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+// Import a key pair from given path
+int crypto_import_key_pair
+(
+ CK_SESSION_HANDLE hSession,
+ char* filePath,
+ char* filePIN,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey
+)
+{
+ EVP_PKEY* pkey = crypto_read_file(filePath, filePIN);
+ if (pkey == NULL)
+ {
+ return 1;
+ }
+
+ RSA* rsa = NULL;
+ DSA* dsa = NULL;
+#ifdef WITH_ECC
+ EC_KEY* ecdsa = NULL;
+#endif
+
+ switch (EVP_PKEY_type(EVP_PKEY_id(pkey)))
+ {
+ case EVP_PKEY_RSA:
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ break;
+ case EVP_PKEY_DSA:
+ dsa = EVP_PKEY_get1_DSA(pkey);
+ break;
+#ifdef WITH_ECC
+ case EVP_PKEY_EC:
+ ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
+ break;
+#endif
+ default:
+ fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
+ EVP_PKEY_free(pkey);
+ return 1;
+ break;
+ }
+ EVP_PKEY_free(pkey);
+
+ int result = 0;
+
+ if (rsa)
+ {
+ result = crypto_save_rsa(hSession, label, objID, objIDLen, noPublicKey, rsa);
+ RSA_free(rsa);
+ }
+ else if (dsa)
+ {
+ result = crypto_save_dsa(hSession, label, objID, objIDLen, noPublicKey, dsa);
+ DSA_free(dsa);
+ }
+#ifdef WITH_ECC
+ else if (ecdsa)
+ {
+ result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa);
+ EC_KEY_free(ecdsa);
+ }
+#endif
+ else
+ {
+ fprintf(stderr, "ERROR: Could not get the key material.\n");
+ result = 1;
+ }
+
+ return result;
+}
+
+// Read the key from file
+EVP_PKEY* crypto_read_file(char* filePath, char* filePIN)
+{
+ BIO* in = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ EVP_PKEY* pkey = NULL;
+ X509_SIG* p8 = NULL;
+
+ if (!(in = BIO_new_file(filePath, "rb")))
+ {
+ fprintf(stderr, "ERROR: Could open the PKCS#8 file: %s\n", filePath);
+ return NULL;
+ }
+
+ // The PKCS#8 file is encrypted
+ if (filePIN)
+ {
+ p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (!p8)
+ {
+ fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
+ "Maybe the file is not encrypted.\n");
+ return NULL;
+ }
+
+ p8inf = PKCS8_decrypt(p8, filePIN, strlen(filePIN));
+ X509_SIG_free(p8);
+
+ if (!p8inf)
+ {
+ fprintf(stderr, "ERROR: Could not decrypt the PKCS#8 file. "
+ "Maybe wrong PIN to file (--file-pin <PIN>)\n");
+ return NULL;
+ }
+ }
+ else
+ {
+ p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
+ BIO_free(in);
+
+ if (!p8inf)
+ {
+ fprintf(stderr, "ERROR: Could not read the PKCS#8 file. "
+ "Maybe it is encypted (--file-pin <PIN>)\n");
+ return NULL;
+ }
+ }
+
+ // Convert the PKCS#8 to OpenSSL
+ pkey = EVP_PKCS82PKEY(p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ if (!pkey)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key.\n");
+ return NULL;
+ }
+
+ return pkey;
+}
+
+// Save the key data in PKCS#11
+int crypto_save_rsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ RSA* rsa
+)
+{
+ rsa_key_material_t* keyMat = crypto_malloc_rsa(rsa);
+ if (!keyMat)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_RSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_WRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) },
+ { CKA_UNWRAP, &ckTrue, sizeof(ckTrue) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PUBLIC_EXPONENT, keyMat->bigE, keyMat->sizeE },
+ { CKA_MODULUS, keyMat->bigN, keyMat->sizeN },
+ { CKA_PRIVATE_EXPONENT, keyMat->bigD, keyMat->sizeD },
+ { CKA_PRIME_1, keyMat->bigP, keyMat->sizeP },
+ { CKA_PRIME_2, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_EXPONENT_1, keyMat->bigDMP1, keyMat->sizeDMP1 },
+ { CKA_EXPONENT_2, keyMat->bigDMQ1, keyMat->sizeDMQ1 },
+ { CKA_COEFFICIENT, keyMat->bigIQMP, keyMat->sizeIQMP }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 19, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_rsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_rsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+rsa_key_material_t* crypto_malloc_rsa(RSA* rsa)
+{
+ if (rsa == NULL)
+ {
+ return NULL;
+ }
+
+ rsa_key_material_t* keyMat = (rsa_key_material_t*)malloc(sizeof(rsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ const BIGNUM* bn_e = NULL;
+ const BIGNUM* bn_n = NULL;
+ const BIGNUM* bn_d = NULL;
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_dmp1 = NULL;
+ const BIGNUM* bn_dmq1 = NULL;
+ const BIGNUM* bn_iqmp = NULL;
+ RSA_get0_factors(rsa, &bn_p, &bn_q);
+ RSA_get0_crt_params(rsa, &bn_dmp1, &bn_dmq1, &bn_iqmp);
+ RSA_get0_key(rsa, &bn_n, &bn_e, &bn_d);
+
+ keyMat->sizeE = BN_num_bytes(bn_e);
+ keyMat->sizeN = BN_num_bytes(bn_n);
+ keyMat->sizeD = BN_num_bytes(bn_d);
+ keyMat->sizeP = BN_num_bytes(bn_p);
+ keyMat->sizeQ = BN_num_bytes(bn_q);
+ keyMat->sizeDMP1 = BN_num_bytes(bn_dmp1);
+ keyMat->sizeDMQ1 = BN_num_bytes(bn_dmq1);
+ keyMat->sizeIQMP = BN_num_bytes(bn_iqmp);
+
+ keyMat->bigE = (CK_VOID_PTR)malloc(keyMat->sizeE);
+ keyMat->bigN = (CK_VOID_PTR)malloc(keyMat->sizeN);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigDMP1 = (CK_VOID_PTR)malloc(keyMat->sizeDMP1);
+ keyMat->bigDMQ1 = (CK_VOID_PTR)malloc(keyMat->sizeDMQ1);
+ keyMat->bigIQMP = (CK_VOID_PTR)malloc(keyMat->sizeIQMP);
+
+ if
+ (
+ !keyMat->bigE ||
+ !keyMat->bigN ||
+ !keyMat->bigD ||
+ !keyMat->bigP ||
+ !keyMat->bigQ ||
+ !keyMat->bigDMP1 ||
+ !keyMat->bigDMQ1 ||
+ !keyMat->bigIQMP
+ )
+ {
+ crypto_free_rsa(keyMat);
+ return NULL;
+ }
+
+ BN_bn2bin(bn_e, (unsigned char*)keyMat->bigE);
+ BN_bn2bin(bn_n, (unsigned char*)keyMat->bigN);
+ BN_bn2bin(bn_d, (unsigned char*)keyMat->bigD);
+ BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP);
+ BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ);
+ BN_bn2bin(bn_dmp1, (unsigned char*)keyMat->bigDMP1);
+ BN_bn2bin(bn_dmq1, (unsigned char*)keyMat->bigDMQ1);
+ BN_bn2bin(bn_iqmp, (unsigned char*)keyMat->bigIQMP);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_rsa(rsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigE) free(keyMat->bigE);
+ if (keyMat->bigN) free(keyMat->bigN);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigDMP1) free(keyMat->bigDMP1);
+ if (keyMat->bigDMQ1) free(keyMat->bigDMQ1);
+ if (keyMat->bigIQMP) free(keyMat->bigIQMP);
+ free(keyMat);
+}
+
+// Save the key data in PKCS#11
+int crypto_save_dsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ DSA* dsa
+)
+{
+ dsa_key_material_t* keyMat = crypto_malloc_dsa(dsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_DSA;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigY, keyMat->sizeY }
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_PRIME, keyMat->bigP, keyMat->sizeP },
+ { CKA_SUBPRIME, keyMat->bigQ, keyMat->sizeQ },
+ { CKA_BASE, keyMat->bigG, keyMat->sizeG },
+ { CKA_VALUE, keyMat->bigX, keyMat->sizeX }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 15, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_dsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 12, &hKey2);
+ crypto_free_dsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+dsa_key_material_t* crypto_malloc_dsa(DSA* dsa)
+{
+ if (dsa == NULL)
+ {
+ return NULL;
+ }
+
+ dsa_key_material_t* keyMat = (dsa_key_material_t*)malloc(sizeof(dsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ const BIGNUM* bn_p = NULL;
+ const BIGNUM* bn_q = NULL;
+ const BIGNUM* bn_g = NULL;
+ const BIGNUM* bn_priv_key = NULL;
+ const BIGNUM* bn_pub_key = NULL;
+ DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g);
+ DSA_get0_key(dsa, &bn_pub_key, &bn_priv_key);
+
+ keyMat->sizeP = BN_num_bytes(bn_p);
+ keyMat->sizeQ = BN_num_bytes(bn_q);
+ keyMat->sizeG = BN_num_bytes(bn_g);
+ keyMat->sizeX = BN_num_bytes(bn_priv_key);
+ keyMat->sizeY = BN_num_bytes(bn_pub_key);
+
+ keyMat->bigP = (CK_VOID_PTR)malloc(keyMat->sizeP);
+ keyMat->bigQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ keyMat->bigG = (CK_VOID_PTR)malloc(keyMat->sizeG);
+ keyMat->bigX = (CK_VOID_PTR)malloc(keyMat->sizeX);
+ keyMat->bigY = (CK_VOID_PTR)malloc(keyMat->sizeY);
+
+ if (!keyMat->bigP || !keyMat->bigQ || !keyMat->bigG || !keyMat->bigX || !keyMat->bigY)
+ {
+ crypto_free_dsa(keyMat);
+ return NULL;
+ }
+
+ BN_bn2bin(bn_p, (unsigned char*)keyMat->bigP);
+ BN_bn2bin(bn_q, (unsigned char*)keyMat->bigQ);
+ BN_bn2bin(bn_g, (unsigned char*)keyMat->bigG);
+ BN_bn2bin(bn_priv_key, (unsigned char*)keyMat->bigX);
+ BN_bn2bin(bn_pub_key, (unsigned char*)keyMat->bigY);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_dsa(dsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->bigP) free(keyMat->bigP);
+ if (keyMat->bigQ) free(keyMat->bigQ);
+ if (keyMat->bigG) free(keyMat->bigG);
+ if (keyMat->bigX) free(keyMat->bigX);
+ if (keyMat->bigY) free(keyMat->bigY);
+ free(keyMat);
+}
+
+#ifdef WITH_ECC
+
+// Save the key data in PKCS#11
+int crypto_save_ecdsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ EC_KEY* ecdsa
+)
+{
+ ecdsa_key_material_t* keyMat = crypto_malloc_ecdsa(ecdsa);
+ if (keyMat == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not convert the key material to binary information.\n");
+ return 1;
+ }
+
+ CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY, privClass = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE keyType = CKK_EC;
+ CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE, ckToken = CK_TRUE;
+ if (noPublicKey)
+ {
+ ckToken = CK_FALSE;
+ }
+ CK_ATTRIBUTE pubTemplate[] = {
+ { CKA_CLASS, &pubClass, sizeof(pubClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_TOKEN, &ckToken, sizeof(ckToken) },
+ { CKA_VERIFY, &ckTrue, sizeof(ckTrue) },
+ { CKA_ENCRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_WRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_EC_POINT, keyMat->derQ, keyMat->sizeQ },
+ };
+ CK_ATTRIBUTE privTemplate[] = {
+ { CKA_CLASS, &privClass, sizeof(privClass) },
+ { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
+ { CKA_LABEL, label, strlen(label) },
+ { CKA_ID, objID, objIDLen },
+ { CKA_SIGN, &ckTrue, sizeof(ckTrue) },
+ { CKA_DECRYPT, &ckFalse, sizeof(ckFalse) },
+ { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) },
+ { CKA_SENSITIVE, &ckTrue, sizeof(ckTrue) },
+ { CKA_TOKEN, &ckTrue, sizeof(ckTrue) },
+ { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) },
+ { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) },
+ { CKA_EC_PARAMS, keyMat->derParams, keyMat->sizeParams },
+ { CKA_VALUE, keyMat->bigD, keyMat->sizeD }
+ };
+
+ CK_OBJECT_HANDLE hKey1, hKey2;
+ CK_RV rv = p11->C_CreateObject(hSession, privTemplate, 13, &hKey1);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not save the private key in the token. "
+ "Maybe the algorithm is not supported.\n");
+ crypto_free_ecdsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_ecdsa(keyMat);
+
+ if (rv != CKR_OK)
+ {
+ p11->C_DestroyObject(hSession, hKey1);
+ fprintf(stderr, "ERROR: Could not save the public key in the token.\n");
+ return 1;
+ }
+
+ printf("The key pair has been imported.\n");
+
+ return 0;
+}
+
+// Convert the OpenSSL key to binary
+ecdsa_key_material_t* crypto_malloc_ecdsa(EC_KEY* ec_key)
+{
+ int result;
+
+ if (ec_key == NULL)
+ {
+ return NULL;
+ }
+
+ ecdsa_key_material_t* keyMat = (ecdsa_key_material_t*)malloc(sizeof(ecdsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ const BIGNUM *d = EC_KEY_get0_private_key(ec_key);
+ const EC_GROUP *group = EC_KEY_get0_group(ec_key);
+ const EC_POINT *point = EC_KEY_get0_public_key(ec_key);
+
+ keyMat->sizeParams = i2d_ECPKParameters(group, NULL);
+ keyMat->sizeD = BN_num_bytes(d);
+
+ keyMat->derParams = (CK_VOID_PTR)malloc(keyMat->sizeParams);
+ keyMat->bigD = (CK_VOID_PTR)malloc(keyMat->sizeD);
+ keyMat->derQ = NULL;
+
+ if (!keyMat->derParams || !keyMat->bigD)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ /*
+ * i2d functions increment the pointer, so we have to use a
+ * sacrificial pointer
+ */
+ unsigned char *derParams = (unsigned char*) keyMat->derParams;
+ result = i2d_ECPKParameters(group, &derParams);
+ if (result == 0)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+ BN_bn2bin(d, (unsigned char*)keyMat->bigD);
+
+ size_t point_length = EC_POINT_point2oct(group,
+ point,
+ POINT_CONVERSION_UNCOMPRESSED,
+ NULL,
+ 0,
+ NULL);
+
+ // Definite, short
+ if (point_length <= 0x7f)
+ {
+ keyMat->sizeQ = 2 + point_length;
+ keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ if (!keyMat->derQ)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ unsigned char *derQ = (unsigned char *)keyMat->derQ;
+ derQ[0] = V_ASN1_OCTET_STRING;
+ derQ[1] = point_length & 0x7f;
+ result = EC_POINT_point2oct(group,
+ point,
+ POINT_CONVERSION_UNCOMPRESSED,
+ &derQ[2],
+ point_length,
+ NULL);
+ if (result == 0)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+ }
+ // Definite, long
+ else
+ {
+ // Count significate bytes
+ size_t bytes = sizeof(size_t);
+ for(; bytes > 0; bytes--)
+ {
+ size_t value = point_length >> ((bytes - 1) * 8);
+ if (value & 0xFF) break;
+ }
+
+ keyMat->sizeQ = 2 + bytes + point_length;
+ keyMat->derQ = (CK_VOID_PTR)malloc(keyMat->sizeQ);
+ if (!keyMat->derQ)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+
+ unsigned char *derQ = (unsigned char *)keyMat->derQ;
+ derQ[0] = V_ASN1_OCTET_STRING;
+ derQ[1] = 0x80 | bytes;
+
+ size_t len = point_length;
+ for (size_t i = 1; i <= bytes; i++)
+ {
+ derQ[2+bytes-i] = (unsigned char) (len & 0xFF);
+ len >>= 8;
+ }
+
+ result = EC_POINT_point2oct(group,
+ point,
+ POINT_CONVERSION_UNCOMPRESSED,
+ &derQ[2+bytes],
+ point_length,
+ NULL);
+ if (result == 0)
+ {
+ crypto_free_ecdsa(keyMat);
+ return NULL;
+ }
+ }
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->derParams) free(keyMat->derParams);
+ if (keyMat->bigD) free(keyMat->bigD);
+ if (keyMat->derQ) free(keyMat->derQ);
+ free(keyMat);
+}
+
+#endif
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
new file mode 100644
index 0000000..7a2a31a
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-util-ossl.h
+
+ Header file for OpenSSL implemented
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
+#define _SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#ifdef WITH_ECC
+#include <openssl/ec.h>
+#endif
+
+typedef struct rsa_key_material_t {
+ CK_ULONG sizeE;
+ CK_ULONG sizeN;
+ CK_ULONG sizeD;
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeDMP1;
+ CK_ULONG sizeDMQ1;
+ CK_ULONG sizeIQMP;
+ CK_VOID_PTR bigE;
+ CK_VOID_PTR bigN;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigDMP1;
+ CK_VOID_PTR bigDMQ1;
+ CK_VOID_PTR bigIQMP;
+ rsa_key_material_t() {
+ sizeE = 0;
+ sizeN = 0;
+ sizeD = 0;
+ sizeP = 0;
+ sizeQ = 0;
+ sizeDMP1 = 0;
+ sizeDMQ1 = 0;
+ sizeIQMP = 0;
+ bigE = NULL_PTR;
+ bigN = NULL_PTR;
+ bigD = NULL_PTR;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigDMP1 = NULL_PTR;
+ bigDMQ1 = NULL_PTR;
+ bigIQMP = NULL_PTR;
+ }
+} rsa_key_material_t;
+
+typedef struct dsa_key_material_t {
+ CK_ULONG sizeP;
+ CK_ULONG sizeQ;
+ CK_ULONG sizeG;
+ CK_ULONG sizeX;
+ CK_ULONG sizeY;
+ CK_VOID_PTR bigP;
+ CK_VOID_PTR bigQ;
+ CK_VOID_PTR bigG;
+ CK_VOID_PTR bigX;
+ CK_VOID_PTR bigY;
+ dsa_key_material_t() {
+ sizeP = 0;
+ sizeQ = 0;
+ sizeG = 0;
+ sizeX = 0;
+ sizeY = 0;
+ bigP = NULL_PTR;
+ bigQ = NULL_PTR;
+ bigG = NULL_PTR;
+ bigX = NULL_PTR;
+ bigY = NULL_PTR;
+ }
+} dsa_key_material_t;
+
+#ifdef WITH_ECC
+typedef struct ecdsa_key_material_t {
+ CK_ULONG sizeParams;
+ CK_ULONG sizeD;
+ CK_ULONG sizeQ;
+ CK_VOID_PTR derParams;
+ CK_VOID_PTR bigD;
+ CK_VOID_PTR derQ;
+ ecdsa_key_material_t() {
+ sizeParams = 0;
+ sizeD = 0;
+ sizeQ = 0;
+ derParams = NULL_PTR;
+ bigD = NULL_PTR;
+ derQ = NULL_PTR;
+ }
+} ecdsa_key_material_t;
+#endif
+
+EVP_PKEY* crypto_read_file(char* filePath, char* filePIN);
+
+// RSA
+int crypto_save_rsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, RSA* rsa);
+rsa_key_material_t* crypto_malloc_rsa(RSA* rsa);
+void crypto_free_rsa(rsa_key_material_t* keyMat);
+
+// DSA
+int crypto_save_dsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, DSA* dsa);
+dsa_key_material_t* crypto_malloc_dsa(DSA* dsa);
+void crypto_free_dsa(dsa_key_material_t* keyMat);
+
+#ifdef WITH_ECC
+// ECDSA
+int crypto_save_ecdsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, EC_KEY* ecdsa);
+ecdsa_key_material_t* crypto_malloc_ecdsa(EC_KEY* ecdsa);
+void crypto_free_ecdsa(ecdsa_key_material_t* keyMat);
+#endif
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util.1 b/SoftHSMv2/src/bin/util/softhsm2-util.1
new file mode 100644
index 0000000..1998226
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util.1
@@ -0,0 +1,259 @@
+.TH SOFTHSM2-UTIL 1 "22 September 2017" "SoftHSM"
+.SH NAME
+softhsm2-util \- support tool for libsofthsm2
+.SH SYNOPSIS
+.B softhsm2-util \-\-show-slots
+.PP
+.B softhsm2-util \-\-init-token
+.B \-\-free
+.B \-\-label
+.I text
+\\
+.ti +0.7i
+.RB [ \-\-so-pin
+.I PIN
+.B \-\-pin
+.IR PIN ]
+.PP
+.B softhsm2-util \-\-import
+.I path
+.RB [ \-\-file-pin
+.IR PIN ]
+.B \-\-token
+.I label
+\\
+.ti +0.7i
+.RB [ \-\-pin
+.I PIN
+.B \-\-no\-public\-key]
+.B \-\-label
+.I text
+.B \-\-id
+.I hex
+.PP
+.B softhsm2-util \-\-import
+.I path
+.B \-\-aes
+.B \-\-token
+.I label
+\\
+.ti +0.7i
+.RB [ \-\-pin
+.I PIN]
+.B \-\-label
+.I text
+.B \-\-id
+.I hex
+.PP
+.B softhsm2-util \-\-delete\-token
+.B \-\-token
+.I text
+.SH DESCRIPTION
+.B softhsm2-util
+is a support tool mainly for libsofthsm2. It can also
+be used with other PKCS#11 libraries by using the option
+.B \-\-module
+.PP
+Read the sections below to get more information on
+the libsofthsm2 and PKCS#11.
+Most applications assumes that the token they want
+to use is already initialized.
+It is then up to the user
+to initialize the PKCS#11 token.
+This is done by using the PKCS#11 interface,
+but instead of writing your own
+tool you can use the
+.B softhsm2-util
+tool.
+.PP
+Keys are usually created directly in the token,
+but the user may want to use an existing key pair.
+Keys can be imported to a token by using the PKCS#11 interface,
+but this tool can also be used if the
+user has the key pair in a PKCS#8 file.
+If you need to convert keys from
+BIND .private-key format over to PKCS#8,
+one can
+use
+.BR softhsm2-keyconv .
+.LP
+The libary
+.BR libsofthsm2 ,
+known as SoftHSM, provides cryptographic functionality
+by using the PKCS#11 API.
+It was developed as a part of the OpenDNSSEC project,
+thus designed to meet the requirements
+of OpenDNSSEC,
+but can also work together with other
+software that want to use the functionality
+of the PKCS#11 API.
+.PP
+SoftHSM is a software implementation of a generic cryptographic device with a PKCS#11 interface.
+These devices are often called tokens.
+Read in the manual softhsm2.conf(5) on how to create these
+tokens and how they are added to a slot in SoftHSM.
+.LP
+The
+.B PKCS#11
+API
+can be used to handle and store cryptographic keys.
+This interface
+specifies how to communicate with cryptographic devices such as HSMs
+(Hardware Security Modules) and smart cards.
+The purpose of these devices
+is, among others,
+to generate cryptographic keys and sign information without
+revealing private-key material to the outside world.
+They are often designed
+to perform well on these specific tasks
+compared to ordinary processes in a normal computer.
+.LP
+.SH ACTIONS
+.TP
+.B \-\-delete\-token
+Delete the token at a given slot.
+Use with
+.BR \-\-token
+or
+.BR \-\-serial .
+Any content in token will be erased.
+.TP
+.B \-\-help\fR, \fB\-h\fR
+Show the help information.
+.TP
+.B \-\-import \fIpath\fR
+Import a key pair from the given
+.IR path .
+The file must be in PKCS#8-format.
+.br
+Use with
+.BR \-\-slot
+or
+.BR \-\-token
+or
+.BR \-\-serial ,
+.BR \-\-file-pin ,
+.BR \-\-pin ,
+.BR \-\-no\-public\-key ,
+.BR \-\-label ,
+and
+.BR \-\-id .
+.br
+Can also be used with
+.BR \-\-aes
+to use file as is and import it as AES.
+.TP
+.B \-\-init-token
+Initialize the token at a given slot, token label or token serial.
+If the token is already initialized then this command
+will reinitialize it, thus erasing all the objects in the token.
+The matching Security Officer (SO) PIN must also
+be provided when doing reinitialization.
+Initialized tokens will be reassigned to another slot (based on
+the token serial number).
+.br
+Use with
+.BR \-\-slot
+or
+.BR \-\-token
+or
+.BR \-\-serial
+or
+.BR \-\-free ,
+.BR \-\-label ,
+.BR \-\-so-pin ,
+and
+.BR \-\-pin .
+.LP
+.TP
+.B \-\-show-slots
+Display all the available slots and their current status.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH OPTIONS
+.TP
+.B \-\-aes
+Used to tell import to use file as is and import it as AES.
+.TP
+.B \-\-file-pin \fIPIN\fR
+The
+.I PIN
+will be used to decrypt the PKCS#8 file.
+If not given then the PKCS#8 file is assumed to be unencrypted.
+.TP
+.B \-\-force
+Use this option to override the warnings and force the given action.
+.TP
+.B \-\-free
+Use the first free/uninitialized token.
+.TP
+.B \-\-id \fIhex\fR
+Choose an ID of the key pair.
+The ID is in hexadecimal with a variable length.
+Use with
+.B \-\-force
+when importing a key pair if the ID already exists.
+.TP
+.B \-\-label \fItext\fR
+Defines the
+.I label
+of the object or the token that will be set.
+.TP
+.B \-\-module \fIpath\fR
+Use another PKCS#11 library than SoftHSM.
+.TP
+.B \-\-no\-public\-key
+Do not import the public key.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+for the normal user.
+.TP
+.B \-\-serial \fInumber\fR
+Will use the token with a matching serial number.
+.TP
+.B \-\-slot \fInumber\fR
+The slot where the token is located.
+.TP
+.B \-\-so-pin \fIPIN\fR
+The
+.I PIN
+for the Security Officer (SO).
+.TP
+.B \-\-token \fIlabel\fR
+Will use the token with a matching token label.
+.SH EXAMPLES
+.LP
+The token can be initialized using this command:
+.LP
+.RS
+.nf
+softhsm2-util \-\-init-token \-\-slot 1 \-\-label "mytoken"
+.fi
+.RE
+.LP
+A key pair can be imported using the softhsm tool where you specify the path
+to the key file, slot number, label and ID of the new objects, and the
+user PIN.
+The file must be in PKCS#8 format.
+.LP
+.RS
+.nf
+softhsm2-util \-\-import key1.pem \-\-token "mytoken" \-\-label "My key" \\
+.ti +0.7i
+\-\-id A1B2 \-\-pin 123456
+.fi
+(Add, \-\-file-pin
+.IR PIN ,
+if the key file is encrypted.)
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.LP
+.SH "SEE ALSO"
+.IR softhsm2-keyconv (1),
+.IR softhsm2-migrate (1),
+.IR softhsm2.conf (5)
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util.cpp b/SoftHSMv2/src/bin/util/softhsm2-util.cpp
new file mode 100644
index 0000000..465df4a
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util.cpp
@@ -0,0 +1,1318 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-util.cpp
+
+ This program can be used for interacting with HSMs using PKCS#11.
+ The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#include <config.h>
+#include "softhsm2-util.h"
+#include "findslot.h"
+#include "getpw.h"
+#include "library.h"
+#include "log.h"
+#include "Configuration.h"
+#include "SimpleConfigLoader.h"
+#include "Directory.h"
+#include "MutexFactory.h"
+#include "ObjectStoreToken.h"
+#include "OSPathSep.h"
+
+#if defined(WITH_OPENSSL)
+#include "OSSLCryptoFactory.h"
+#else
+#include "BotanCryptoFactory.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#else
+#include <direct.h>
+#include <io.h>
+#endif
+#include <iostream>
+#include <fstream>
+
+// Initialise the one-and-only instance
+
+#ifdef HAVE_CXX11
+
+std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
+std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
+#if defined(WITH_OPENSSL)
+std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
+#else
+std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
+#endif
+
+#else
+
+std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
+std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
+#if defined(WITH_OPENSSL)
+std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
+#else
+std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
+#endif
+
+#endif
+
+// Display the usage
+void usage()
+{
+ printf("Support tool for PKCS#11\n");
+ printf("Usage: softhsm2-util [ACTION] [OPTIONS]\n");
+ printf("Action:\n");
+ printf(" --delete-token Delete the token at a given slot.\n");
+ printf(" Use with --token or --serial.\n");
+ printf(" WARNING: Any content in token will be erased.\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --import <path> Import a key pair from the given path.\n");
+ printf(" The file must be in PKCS#8-format.\n");
+ printf(" Use with --slot or --token or --serial, --file-pin,\n");
+ printf(" --label, --id, --no-public-key, and --pin.\n");
+ printf(" --init-token Initialize the token at a given slot.\n");
+ printf(" Use with --slot or --token or --serial or --free,\n");
+ printf(" --label, --so-pin, and --pin.\n");
+ printf(" WARNING: Any content in token will be erased.\n");
+ printf(" --show-slots Display all the available slots.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+ printf("Options:\n");
+ printf(" --aes Used to tell import to use file as is and import it as AES.\n");
+ printf(" --file-pin <PIN> Supply a PIN if the file is encrypted.\n");
+ printf(" --force Used to override a warning.\n");
+ printf(" --free Use the first free/uninitialized token.\n");
+ printf(" --id <hex> Defines the ID of the object. Hexadecimal characters.\n");
+ printf(" Use with --force if multiple key pairs may share\n");
+ printf(" the same ID.\n");
+ printf(" --label <text> Defines the label of the object or the token.\n");
+ printf(" --module <path> Use another PKCS#11 library than SoftHSM.\n");
+ printf(" --no-public-key Do not import the public key.\n");
+ printf(" --pin <PIN> The PIN for the normal user.\n");
+ printf(" --serial <number> Will use the token with a matching serial number.\n");
+ printf(" --slot <number> The slot where the token is located.\n");
+ printf(" --so-pin <PIN> The PIN for the Security Officer (SO).\n");
+ printf(" --token <label> Will use the token with a matching token label.\n");
+}
+
+// Enumeration of the long options
+enum {
+ OPT_DELETE_TOKEN = 0x100,
+ OPT_FILE_PIN,
+ OPT_FORCE,
+ OPT_FREE,
+ OPT_HELP,
+ OPT_ID,
+ OPT_IMPORT,
+ OPT_INIT_TOKEN,
+ OPT_LABEL,
+ OPT_MODULE,
+ OPT_NO_PUBLIC_KEY,
+ OPT_PIN,
+ OPT_SERIAL,
+ OPT_SHOW_SLOTS,
+ OPT_SLOT,
+ OPT_SO_PIN,
+ OPT_TOKEN,
+ OPT_VERSION,
+ OPT_AES
+};
+
+// Text representation of the long options
+static const struct option long_options[] = {
+ { "delete-token", 0, NULL, OPT_DELETE_TOKEN },
+ { "file-pin", 1, NULL, OPT_FILE_PIN },
+ { "force", 0, NULL, OPT_FORCE },
+ { "free", 0, NULL, OPT_FREE },
+ { "help", 0, NULL, OPT_HELP },
+ { "id", 1, NULL, OPT_ID },
+ { "import", 1, NULL, OPT_IMPORT },
+ { "init-token", 0, NULL, OPT_INIT_TOKEN },
+ { "label", 1, NULL, OPT_LABEL },
+ { "module", 1, NULL, OPT_MODULE },
+ { "no-public-key", 0, NULL, OPT_NO_PUBLIC_KEY },
+ { "pin", 1, NULL, OPT_PIN },
+ { "serial", 1, NULL, OPT_SERIAL },
+ { "show-slots", 0, NULL, OPT_SHOW_SLOTS },
+ { "slot", 1, NULL, OPT_SLOT },
+ { "so-pin", 1, NULL, OPT_SO_PIN },
+ { "token", 1, NULL, OPT_TOKEN },
+ { "version", 0, NULL, OPT_VERSION },
+ { "aes", 0, NULL, OPT_AES },
+ { NULL, 0, NULL, 0 }
+};
+
+CK_FUNCTION_LIST_PTR p11;
+
+// The main function
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt;
+
+ char* inPath = NULL;
+ char* soPIN = NULL;
+ char* userPIN = NULL;
+ char* filePIN = NULL;
+ char* label = NULL;
+ char* module = NULL;
+ char* objectID = NULL;
+ char* slot = NULL;
+ char* serial = NULL;
+ char* token = NULL;
+ char* errMsg = NULL;
+ int forceExec = 0;
+ bool freeToken = false;
+ int noPublicKey = 0;
+ bool importAES = false;
+
+ int doInitToken = 0;
+ int doShowSlots = 0;
+ int doImport = 0;
+ int doDeleteToken = 0;
+ int action = 0;
+ bool needP11 = false;
+ int rv = 0;
+ CK_SLOT_ID slotID = 0;
+
+ moduleHandle = NULL;
+ p11 = NULL;
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_SHOW_SLOTS:
+ doShowSlots = 1;
+ action++;
+ needP11 = true;
+ break;
+ case OPT_INIT_TOKEN:
+ doInitToken = 1;
+ action++;
+ needP11 = true;
+ break;
+ case OPT_IMPORT:
+ doImport = 1;
+ action++;
+ inPath = optarg;
+ needP11 = true;
+ break;
+ case OPT_AES:
+ importAES = true;
+ break;
+ case OPT_DELETE_TOKEN:
+ doDeleteToken = 1;
+ action++;
+ break;
+ case OPT_SLOT:
+ slot = optarg;
+ break;
+ case OPT_LABEL:
+ label = optarg;
+ break;
+ case OPT_SERIAL:
+ serial = optarg;
+ break;
+ case OPT_TOKEN:
+ token = optarg;
+ break;
+ case OPT_MODULE:
+ module = optarg;
+ break;
+ case OPT_NO_PUBLIC_KEY:
+ noPublicKey = 1;
+ break;
+ case OPT_ID:
+ objectID = optarg;
+ break;
+ case OPT_SO_PIN:
+ soPIN = optarg;
+ break;
+ case OPT_PIN:
+ userPIN = optarg;
+ break;
+ case OPT_FILE_PIN:
+ filePIN = optarg;
+ break;
+ case OPT_FORCE:
+ forceExec = 1;
+ break;
+ case OPT_FREE:
+ freeToken = true;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // No action given, display the usage.
+ if (action != 1)
+ {
+ usage();
+ exit(1);
+ }
+
+ if (needP11)
+ {
+ // Check the basic setup of SoftHSM
+ if (!checkSetup())
+ {
+ fprintf(stderr, "ERROR: Please verify that the SoftHSM configuration is correct.\n");
+ exit(1);
+ }
+
+ // Get a pointer to the function list for PKCS#11 library
+ CK_C_GetFunctionList pGetFunctionList = loadLibrary(module, &moduleHandle, &errMsg);
+ if (!pGetFunctionList)
+ {
+ fprintf(stderr, "ERROR: Could not load the PKCS#11 library/module: %s\n", errMsg);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+
+ // Load the function list
+ (*pGetFunctionList)(&p11);
+
+ // Initialize the library
+ CK_RV p11rv = p11->C_Initialize(NULL_PTR);
+ if (p11rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the PKCS#11 library/module: %s\n", module ? module : DEFAULT_PKCS11_LIB);
+ fprintf(stderr, "ERROR: Please check log files for additional information.\n");
+ exit(1);
+ }
+ }
+
+ // We should create the token.
+ if (doInitToken)
+ {
+ // Get the slotID
+ rv = findSlot(slot, serial, token, freeToken, slotID);
+ if (!rv)
+ {
+ rv = initToken(slotID, label, soPIN, userPIN);
+ }
+ }
+
+ // Show all available slots
+ if (!rv && doShowSlots)
+ {
+ rv = showSlots();
+ }
+
+ // Import a key pair from the given path
+ if (!rv && doImport)
+ {
+ // Get the slotID
+ rv = findSlot(slot, serial, token, slotID);
+ if (!rv)
+ {
+ rv = importAES ? importSecretKey(inPath, slotID, userPIN, label, objectID)
+ : importKeyPair(inPath, filePIN, slotID, userPIN, label, objectID, forceExec, noPublicKey);
+ }
+ }
+
+ // We should delete the token.
+ if (!rv && doDeleteToken)
+ {
+ if (deleteToken(serial, token))
+ {
+ rv = 0;
+ }
+ else
+ {
+ rv = 1;
+ }
+ }
+
+ // Finalize the library
+ if (needP11)
+ {
+ p11->C_Finalize(NULL_PTR);
+ unloadLibrary(moduleHandle);
+ }
+
+ return rv;
+}
+
+// Check the basic setup of SoftHSM
+bool checkSetup()
+{
+ // Initialize the SoftHSM internal functions
+ if (!initSoftHSM())
+ {
+ finalizeSoftHSM();
+ return false;
+ }
+
+ std::string basedir = Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR);
+
+ // Try open the token directory
+ Directory storeDir(basedir);
+ if (!storeDir.isValid())
+ {
+ fprintf(stderr, "ERROR: Failed to enumerate object store in %s\n", basedir.c_str());
+ finalizeSoftHSM();
+ return false;
+ }
+
+ finalizeSoftHSM();
+ return true;
+}
+
+// Initialize the token
+int initToken(CK_SLOT_ID slotID, char* label, char* soPIN, char* userPIN)
+{
+ char so_pin_copy[MAX_PIN_LEN+1];
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the token must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (strlen(label) > 32)
+ {
+ fprintf(stderr, "ERROR: The token label must not have a length "
+ "greater than 32 chars.\n");
+ return 1;
+ }
+
+ // Get the passwords
+ if (getPW(soPIN, so_pin_copy, CKU_SO) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get SO PIN\n");
+ return 1;
+ }
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ return 1;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedLabel[32];
+ memset(paddedLabel, ' ', sizeof(paddedLabel));
+ memcpy(paddedLabel, label, strlen(label));
+
+ CK_RV rv = p11->C_InitToken(slotID, (CK_UTF8CHAR_PTR)so_pin_copy, strlen(so_pin_copy), paddedLabel);
+
+ switch (rv)
+ {
+ case CKR_OK:
+ break;
+ case CKR_SLOT_ID_INVALID:
+ fprintf(stderr, "CKR_SLOT_ID_INVALID: Slot %lu does not exist.\n", slotID);
+ return 1;
+ break;
+ case CKR_PIN_INCORRECT:
+ fprintf(stderr, "CKR_PIN_INCORRECT: The given SO PIN does not match the "
+ "one in the token. Needed when reinitializing the token.\n");
+ return 1;
+ break;
+ case CKR_TOKEN_NOT_PRESENT:
+ fprintf(stderr, "CKR_TOKEN_NOT_PRESENT: The token is not present. "
+ "Please read the HSM manual for further assistance.\n");
+ return 1;
+ break;
+ default:
+ fprintf(stderr, "ERROR rv=0x%08X: Could not initialize the token.\n", (unsigned int)rv);
+ fprintf(stderr, "Please check log files for additional information.\n");
+ return 1;
+ break;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not open a session with the library.\n");
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_SO, (CK_UTF8CHAR_PTR)so_pin_copy, strlen(so_pin_copy));
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ return 1;
+ }
+
+ rv = p11->C_InitPIN(hSession, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the user PIN.\n");
+ return 1;
+ }
+
+ // Get the token info
+ CK_TOKEN_INFO tokenInfo;
+ rv = p11->C_GetTokenInfo(slotID, &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the initialized token in slot %lu.\n", slotID);
+ return 1;
+ }
+
+ // Reload the library
+ p11->C_Finalize(NULL_PTR);
+ rv = p11->C_Initialize(NULL_PTR);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not initialize the library.\n");
+ return 1;
+ }
+
+ // Get the slotID
+ CK_SLOT_ID newSlotID;
+ if (findSlot(tokenInfo, newSlotID))
+ {
+ return 1;
+ }
+
+ if (slotID == newSlotID)
+ {
+ printf("The token has been initialized on slot %lu\n", newSlotID);
+ }
+ else
+ {
+ printf("The token has been initialized and is reassigned to slot %lu\n", newSlotID);
+ }
+
+ return 0;
+}
+
+// Delete the token
+bool deleteToken(char* serial, char* token)
+{
+ if (serial == NULL && token == NULL)
+ {
+ fprintf(stderr, "ERROR: A token must be supplied. "
+ "Use --serial <serial> or --token <label>\n");
+ return false;
+ }
+
+ // Initialize the SoftHSM internal functions
+ if (!initSoftHSM())
+ {
+ finalizeSoftHSM();
+ return false;
+ }
+
+ bool rv = true;
+ std::string basedir = Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR);
+ std::string tokendir;
+
+ rv = findTokenDirectory(basedir, tokendir, serial, token);
+
+ if (rv)
+ {
+ std::string fulldir = basedir;
+ if (fulldir.find_last_of(OS_PATHSEP) != (fulldir.size()-1))
+ {
+ fulldir += OS_PATHSEP + tokendir;
+ }
+ else
+ {
+ fulldir += tokendir;
+ }
+
+ rv = rmdir(fulldir);
+ if (rv)
+ {
+ printf("The token (%s) has been deleted.\n", fulldir.c_str());
+ }
+ }
+
+ finalizeSoftHSM();
+
+ return rv;
+}
+
+bool initSoftHSM()
+{
+ // Not using threading
+ MutexFactory::i()->disable();
+
+ // Initiate SecureMemoryRegistry
+ if (SecureMemoryRegistry::i() == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not initiate SecureMemoryRegistry.\n");
+ return false;
+ }
+
+ // Build the CryptoFactory
+ if (CryptoFactory::i() == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not initiate CryptoFactory.\n");
+ return false;
+ }
+
+#ifdef WITH_FIPS
+ // Check the FIPS status
+ if (!CryptoFactory::i()->getFipsSelfTestStatus())
+ {
+ fprintf(stderr, "ERROR: FIPS self test failed.\n");
+ return false;
+ }
+#endif
+
+ // Load the configuration
+ if (!Configuration::i()->reload(SimpleConfigLoader::i()))
+ {
+ fprintf(stderr, "ERROR: Could not load the SoftHSM configuration.\n");
+ return false;
+ }
+
+ // Configure the log level
+ if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
+ {
+ fprintf(stderr, "ERROR: Could not configure the log level.\n");
+ return false;
+ }
+
+ // Configure object store storage backend used by all tokens.
+ if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
+ {
+ fprintf(stderr, "ERROR: Could not select token backend.\n");
+ return false;
+ }
+
+ return true;
+}
+
+void finalizeSoftHSM()
+{
+ CryptoFactory::reset();
+ SecureMemoryRegistry::reset();
+}
+
+// Find the token directory
+bool findTokenDirectory(std::string basedir, std::string& tokendir, char* serial, char* label)
+{
+ if (serial == NULL && label == NULL)
+ {
+ return false;
+ }
+
+ // Load the variables
+ CK_UTF8CHAR paddedSerial[16];
+ CK_UTF8CHAR paddedLabel[32];
+ if (serial != NULL)
+ {
+ size_t inSize = strlen(serial);
+ size_t outSize = sizeof(paddedSerial);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --serial is too long.\n");
+ return false;
+ }
+ memset(paddedSerial, ' ', outSize);
+ memcpy(paddedSerial, serial, inSize);
+ }
+ if (label != NULL)
+ {
+ size_t inSize = strlen(label);
+ size_t outSize = sizeof(paddedLabel);
+ if (inSize > outSize)
+ {
+ fprintf(stderr, "ERROR: --token is too long.\n");
+ return false;
+ }
+ memset(paddedLabel, ' ', outSize);
+ memcpy(paddedLabel, label, inSize);
+ }
+
+ // Find all tokens in the specified path
+ Directory storeDir(basedir);
+
+ if (!storeDir.isValid())
+ {
+ fprintf(stderr, "Failed to enumerate object store in %s\n", basedir.c_str());
+
+ return false;
+ }
+
+ // Assume that all subdirectories are tokens
+ std::vector<std::string> dirs = storeDir.getSubDirs();
+
+ ByteString tokenLabel;
+ ByteString tokenSerial;
+ CK_UTF8CHAR paddedTokenSerial[16];
+ CK_UTF8CHAR paddedTokenLabel[32];
+ size_t counter = 0;
+ for (std::vector<std::string>::iterator i = dirs.begin(); i != dirs.end(); i++)
+ {
+ memset(paddedTokenSerial, ' ', sizeof(paddedTokenSerial));
+ memset(paddedTokenLabel, ' ', sizeof(paddedTokenLabel));
+
+ // Create a token instance
+ ObjectStoreToken* token = ObjectStoreToken::accessToken(basedir, *i);
+
+ if (!token->isValid())
+ {
+ delete token;
+ continue;
+ }
+
+ if (token->getTokenLabel(tokenLabel) && tokenLabel.size() <= sizeof(paddedTokenLabel))
+ {
+ strncpy((char*) paddedTokenLabel, (char*) tokenLabel.byte_str(), tokenLabel.size());
+ }
+ if (token->getTokenSerial(tokenSerial) && tokenSerial.size() <= sizeof(paddedTokenSerial))
+ {
+ strncpy((char*) paddedTokenSerial, (char*) tokenSerial.byte_str(), tokenSerial.size());
+ }
+
+ if (serial != NULL && label == NULL &&
+ memcmp(paddedTokenSerial, paddedSerial, sizeof(paddedSerial)) == 0)
+ {
+ printf("Found token (%s) with matching serial.\n", i->c_str());
+ tokendir = i->c_str();
+ counter++;
+ }
+ if (serial == NULL && label != NULL &&
+ memcmp(paddedTokenLabel, paddedLabel, sizeof(paddedLabel)) == 0)
+ {
+ printf("Found token (%s) with matching token label.\n", i->c_str());
+ tokendir = i->c_str();
+ counter++;
+ }
+ if (serial != NULL && label != NULL &&
+ memcmp(paddedTokenSerial, paddedSerial, sizeof(paddedSerial)) == 0 &&
+ memcmp(paddedTokenLabel, paddedLabel, sizeof(paddedLabel)) == 0)
+ {
+ printf("Found token (%s) with matching serial and token label.\n", i->c_str());
+ tokendir = i->c_str();
+ counter++;
+ }
+
+ delete token;
+ }
+
+ if (counter == 1) return true;
+ if (counter > 1)
+ {
+ fprintf(stderr, "ERROR: Found multiple matching tokens.\n");
+ return false;
+ }
+
+ fprintf(stderr, "ERROR: Could not find a token using --serial or --token.\n");
+ return false;
+}
+
+
+// Delete a directory
+bool rmdir(std::string path)
+{
+ bool rv = true;
+
+#ifndef _WIN32
+ // Enumerate the directory
+ DIR* dir = opendir(path.c_str());
+
+ if (dir == NULL)
+ {
+ fprintf(stderr, "ERROR: Failed to open directory %s\n", path.c_str());
+ return false;
+ }
+
+ // Enumerate the directory
+ struct dirent* entry = NULL;
+
+ while ((entry = readdir(dir)) != NULL)
+ {
+ bool handled = false;
+
+ // Check if this is the . or .. entry
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
+ {
+ continue;
+ }
+
+ // Convert the name of the entry to a C++ string
+ std::string name(entry->d_name);
+ std::string fullPath = path + OS_PATHSEP + name;
+
+#if defined(_DIRENT_HAVE_D_TYPE) && defined(_BSD_SOURCE)
+ // Determine the type of the entry
+ switch(entry->d_type)
+ {
+ case DT_DIR:
+ // This is a directory
+ rv = rmdir(fullPath);
+ handled = true;
+ break;
+ case DT_REG:
+ // This is a regular file
+ rv = rm(fullPath);
+ handled = true;
+ break;
+ default:
+ break;
+ }
+#endif
+
+ if (rv == false)
+ break;
+
+ if (!handled)
+ {
+ // The entry type has to be determined using lstat
+ struct stat entryStatus;
+
+ if (!lstat(fullPath.c_str(), &entryStatus))
+ {
+ if (S_ISDIR(entryStatus.st_mode))
+ {
+ // This is a directory
+ rv = rmdir(fullPath);
+ }
+ else if (S_ISREG(entryStatus.st_mode))
+ {
+ // This is a regular file
+ rv = rm(fullPath);
+ }
+ }
+
+ if (rv == false)
+ break;
+ }
+ }
+
+ // Close the directory
+ closedir(dir);
+#else
+ // Enumerate the directory
+ std::string pattern;
+ intptr_t h;
+ struct _finddata_t fi;
+
+ if ((path.back() == '/') || (path.back() == '\\'))
+ pattern = path + "*";
+ else
+ pattern = path + "/*";
+ memset(&fi, 0, sizeof(fi));
+ h = _findfirst(pattern.c_str(), &fi);
+ if (h == -1)
+ {
+ // empty directory
+ if (errno == ENOENT)
+ goto finished;
+
+ fprintf(stderr, "ERROR: Failed to open directory %s\n", path.c_str());
+
+ return false;
+ }
+
+ // scan files & subdirs
+ do
+ {
+ // Check if this is the . or .. entry
+ if (!strcmp(fi.name, ".") || !strcmp(fi.name, ".."))
+ continue;
+
+ std::string fullPath = path + OS_PATHSEP + fi.name;
+ if ((fi.attrib & _A_SUBDIR) == 0)
+ {
+ // This is a regular file
+ rv = rm(fullPath);
+ }
+ else
+ {
+ // This is a directory
+ rv = rmdir(fullPath);
+ }
+
+ memset(&fi, 0, sizeof(fi));
+
+ if (rv == false)
+ break;
+ } while (_findnext(h, &fi) == 0);
+
+ (void) _findclose(h);
+
+ finished:
+#endif
+
+ if (rv == false)
+ return false;
+
+ int result;
+#ifndef _WIN32
+ result = ::rmdir(path.c_str());
+#else
+ result = _rmdir(path.c_str());
+#endif
+
+ if (result != 0)
+ {
+ fprintf(stderr, "ERROR: Could not delete the directory: %s\n", path.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Delete a file
+bool rm(std::string path)
+{
+ int result;
+
+#ifndef _WIN32
+ result = ::remove(path.c_str());
+#else
+ result = _unlink(path.c_str());
+#endif
+
+ if (result != 0)
+ {
+ fprintf(stderr, "ERROR: Could not delete the file: %s\n", path.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Show what slots are available
+int showSlots()
+{
+ CK_ULONG ulSlotCount;
+ CK_RV rv = p11->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the number of slots.\n");
+ return 1;
+ }
+
+ CK_SLOT_ID_PTR pSlotList = (CK_SLOT_ID_PTR) malloc(ulSlotCount*sizeof(CK_SLOT_ID));
+ if (!pSlotList)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return 1;
+ }
+
+ rv = p11->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the slot list.\n");
+ free(pSlotList);
+ return 1;
+ }
+
+ printf("Available slots:\n");
+
+ for (CK_ULONG i = 0; i < ulSlotCount; i++)
+ {
+ CK_SLOT_INFO slotInfo;
+ CK_TOKEN_INFO tokenInfo;
+
+ rv = p11->C_GetSlotInfo(pSlotList[i], &slotInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about slot %lu.\n", pSlotList[i]);
+ continue;
+ }
+
+ printf("Slot %lu\n", pSlotList[i]);
+ printf(" Slot info:\n");
+ printf(" Description: %.*s\n", 64, slotInfo.slotDescription);
+ printf(" Manufacturer ID: %.*s\n", 32, slotInfo.manufacturerID);
+ printf(" Hardware version: %i.%i\n", slotInfo.hardwareVersion.major,
+ slotInfo.hardwareVersion.minor);
+ printf(" Firmware version: %i.%i\n", slotInfo.firmwareVersion.major,
+ slotInfo.firmwareVersion.minor);
+ printf(" Token present: ");
+ if ((slotInfo.flags & CKF_TOKEN_PRESENT) == 0)
+ {
+ printf("no\n");
+ continue;
+ }
+
+ printf("yes\n");
+ printf(" Token info:\n");
+
+ rv = p11->C_GetTokenInfo(pSlotList[i], &tokenInfo);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get info about the token in slot %lu.\n",
+ pSlotList[i]);
+ continue;
+ }
+
+ printf(" Manufacturer ID: %.*s\n", 32, tokenInfo.manufacturerID);
+ printf(" Model: %.*s\n", 16, tokenInfo.model);
+ printf(" Hardware version: %i.%i\n", tokenInfo.hardwareVersion.major,
+ tokenInfo.hardwareVersion.minor);
+ printf(" Firmware version: %i.%i\n", tokenInfo.firmwareVersion.major,
+ tokenInfo.firmwareVersion.minor);
+ printf(" Serial number: %.*s\n", 16, tokenInfo.serialNumber);
+ printf(" Initialized: ");
+ if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == 0)
+ {
+ printf("no\n");
+ }
+ else
+ {
+ printf("yes\n");
+ }
+
+ printf(" User PIN init.: ");
+ if ((tokenInfo.flags & CKF_USER_PIN_INITIALIZED) == 0)
+ {
+ printf("no\n");
+ }
+ else
+ {
+ printf("yes\n");
+ }
+
+ printf(" Label: %.*s\n", 32, tokenInfo.label);
+
+ }
+
+ free(pSlotList);
+
+ return 0;
+}
+
+// Import a key pair from given path
+int importKeyPair
+(
+ char* filePath,
+ char* filePIN,
+ CK_SLOT_ID slotID,
+ char* userPIN,
+ char* label,
+ char* objectID,
+ int forceExec,
+ int noPublicKey
+)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the object must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (objectID == NULL)
+ {
+ fprintf(stderr, "ERROR: An ID for the object must be supplied. "
+ "Use --id <hex>\n");
+ return 1;
+ }
+
+ size_t objIDLen = 0;
+ char* objID = hexStrToBin(objectID, strlen(objectID), &objIDLen);
+ if (objID == NULL)
+ {
+ fprintf(stderr, "Please edit --id <hex> to correct error.\n");
+ return 1;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ free(objID);
+ return 1;
+ }
+
+ // Get the password
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ free(objID);
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ free(objID);
+ return 1;
+ }
+
+ CK_OBJECT_HANDLE oHandle = searchObject(hSession, objID, objIDLen);
+ if (oHandle != CK_INVALID_HANDLE && forceExec == 0)
+ {
+ free(objID);
+ fprintf(stderr, "ERROR: The ID is already assigned to another object. "
+ "Use --force to override this message.\n");
+ return 1;
+ }
+
+ crypto_init();
+ int result = crypto_import_key_pair(hSession, filePath, filePIN, label, objID, objIDLen, noPublicKey);
+ crypto_final();
+
+ free(objID);
+
+ return result;
+}
+
+// Import a secret key from given path
+int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* label, char* objectID)
+{
+ char user_pin_copy[MAX_PIN_LEN+1];
+
+ if (label == NULL)
+ {
+ fprintf(stderr, "ERROR: A label for the object must be supplied. "
+ "Use --label <text>\n");
+ return 1;
+ }
+
+ if (objectID == NULL)
+ {
+ fprintf(stderr, "ERROR: An ID for the object must be supplied. "
+ "Use --id <hex>\n");
+ return 1;
+ }
+
+ size_t objIDLen = 0;
+ char* objID = hexStrToBin(objectID, strlen(objectID), &objIDLen);
+ if (objID == NULL)
+ {
+ fprintf(stderr, "Please edit --id <hex> to correct error.\n");
+ return 1;
+ }
+
+ // Get the password
+ if (getPW(userPIN, user_pin_copy, CKU_USER) != 0)
+ {
+ fprintf(stderr, "ERROR: Could not get user PIN\n");
+ return 1;
+ }
+
+ CK_SESSION_HANDLE hSession;
+ CK_RV rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_SLOT_ID_INVALID)
+ {
+ fprintf(stderr, "ERROR: The given slot does not exist.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not open a session on the given slot.\n");
+ }
+ return 1;
+ }
+
+ rv = p11->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy));
+ if (rv != CKR_OK)
+ {
+ if (rv == CKR_PIN_INCORRECT) {
+ fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n");
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Could not log in on the token.\n");
+ }
+ return 1;
+ }
+
+ crypto_init();
+ int result = crypto_import_aes_key(hSession, filePath, label, objID, objIDLen);
+ crypto_final();
+
+ return result;
+}
+
+// Convert a char array of hexadecimal characters into a binary representation
+char* hexStrToBin(char* objectID, int idLength, size_t* newLen)
+{
+ char* bytes = NULL;
+
+ if (idLength < 2 || idLength % 2 != 0)
+ {
+ fprintf(stderr, "ERROR: Invalid length on hex string.\n");
+ return NULL;
+ }
+
+ for (int i = 0; i < idLength; i++)
+ {
+ if (hexdigit_to_int(objectID[i]) == -1)
+ {
+ fprintf(stderr, "ERROR: Invalid character in hex string.\n");
+ return NULL;
+ }
+ }
+
+ *newLen = idLength / 2;
+ bytes = (char*) malloc(*newLen);
+ if (bytes == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ return NULL;
+ }
+
+ for (size_t i = 0; i < *newLen; i++)
+ {
+ bytes[i] = hexdigit_to_int(objectID[2*i]) * 16 +
+ hexdigit_to_int(objectID[2*i+1]);
+ }
+
+ return bytes;
+}
+
+// Return the integer value of a hexadecimal character
+int hexdigit_to_int(char ch)
+{
+ switch (ch)
+ {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ default:
+ return -1;
+ }
+}
+
+// Search for an object
+CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen)
+{
+ if (objID == NULL)
+ {
+ return CK_INVALID_HANDLE;
+ }
+
+ CK_OBJECT_CLASS oClass = CKO_PRIVATE_KEY;
+ CK_OBJECT_HANDLE hObject = CK_INVALID_HANDLE;
+ CK_ULONG objectCount = 0;
+
+ CK_ATTRIBUTE objTemplate[] = {
+ { CKA_CLASS, &oClass, sizeof(oClass) },
+ { CKA_ID, objID, objIDLen }
+ };
+
+ CK_RV rv = p11->C_FindObjectsInit(hSession, objTemplate, 2);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not prepare the object search.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ rv = p11->C_FindObjects(hSession, &hObject, 1, &objectCount);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not get the search results.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ rv = p11->C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK)
+ {
+ fprintf(stderr, "ERROR: Could not finalize the search.\n");
+ return CK_INVALID_HANDLE;
+ }
+
+ if (objectCount == 0)
+ {
+ return CK_INVALID_HANDLE;
+ }
+
+ return hObject;
+}
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util.h b/SoftHSMv2/src/bin/util/softhsm2-util.h
new file mode 100644
index 0000000..3c49314
--- /dev/null
+++ b/SoftHSMv2/src/bin/util/softhsm2-util.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * 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.
+ */
+
+/*****************************************************************************
+ softhsm2-util.h
+
+ This program can be used for interacting with HSMs using PKCS#11.
+ The default library is the libsofthsm2.so
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_UTIL_H
+#define _SOFTHSM_V2_SOFTHSM2_UTIL_H
+
+#include "cryptoki.h"
+#include <string>
+
+// Main functions
+
+void usage();
+bool checkSetup();
+int initToken(CK_SLOT_ID slotID, char* label, char* soPIN, char* userPIN);
+bool deleteToken(char* serial, char* token);
+bool findTokenDirectory(std::string basedir, std::string& tokendir, char* serial, char* label);
+bool rmdir(std::string path);
+bool rm(std::string path);
+int showSlots();
+int importKeyPair(char* filePath, char* filePIN, CK_SLOT_ID slotID, char* userPIN, char* objectLabel, char* objectID, int forceExec, int noPublicKey);
+int importSecretKey(char* filePath, CK_SLOT_ID slotID, char* userPIN, char* label, char* objectID);
+int crypto_import_key_pair(CK_SESSION_HANDLE hSession, char* filePath, char* filePIN, char* label, char* objID, size_t objIDLen, int noPublicKey);
+int crypto_import_aes_key(CK_SESSION_HANDLE hSession, char* filePath, char* label, char* objID, size_t objIDLen);
+
+// Support functions
+
+void crypto_init();
+void crypto_final();
+
+/// SoftHSM internal funtions
+bool initSoftHSM();
+void finalizeSoftHSM();
+
+/// Hex
+char* hexStrToBin(char* objectID, int idLength, size_t* newLen);
+int hexdigit_to_int(char ch);
+
+/// Library
+#if !defined(UTIL_BOTAN) && !defined(UTIL_OSSL)
+static void* moduleHandle;
+#endif
+extern CK_FUNCTION_LIST_PTR p11;
+
+/// PKCS#11 support
+CK_OBJECT_HANDLE searchObject(CK_SESSION_HANDLE hSession, char* objID, size_t objIDLen);
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_H
diff --git a/SoftHSMv2/src/bin/win32/getopt.cpp b/SoftHSMv2/src/bin/win32/getopt.cpp
new file mode 100644
index 0000000..dfeabe2
--- /dev/null
+++ b/SoftHSMv2/src/bin/win32/getopt.cpp
@@ -0,0 +1,520 @@
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+
+/* Windows needs warnx(). We change the definition though:
+ * 1. (another) global is defined, opterrmsg, which holds the error message
+ * 2. errors are always printed out on stderr w/o the program name
+ * Note that opterrmsg always gets set no matter what opterr is set to. The
+ * error message will not be printed if opterr is 0 as usual.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+extern char opterrmsg[128];
+char opterrmsg[128]; /* last error message is stored here */
+
+static void warnx(int print_error, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (fmt != NULL)
+ _vsnprintf(opterrmsg, 128, fmt, ap);
+ else
+ opterrmsg[0]='\0';
+ va_end(ap);
+ if (print_error) {
+ fprintf(stderr, opterrmsg);
+ fprintf(stderr, "\n");
+ }
+}
+
+#endif /*_WIN32*/
+
+/* not part of the original file */
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+
+#if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
+#define REPLACE_GETOPT
+#endif
+
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#if !HAVE_GETOPT_LONG
+#define IGNORE_FIRST (*options == '-' || *options == '+')
+#define PRINT_ERROR ((opterr) && ((*options != ':') \
+ || (IGNORE_FIRST && options[1] != ':')))
+#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
+#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
+/* XXX: GNU ignores PC if *options == '-' */
+#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((IGNORE_FIRST && options[1] == ':') \
+ || (*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define EMSG ""
+
+static int getopt_internal(int, char * const *, const char *);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return b;
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end,
+ int opt_end, char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ _DIAGASSERT(nargv != NULL);
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ * Returns -2 if -- is found (can be long option or end of options marker).
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options)
+{
+ char *oli; /* option letter list index */
+ int optchar;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ optarg = NULL;
+
+ /*
+ * XXX Some programs (like rsyncd) expect to be able to
+ * XXX re-initialize optind to 0 and have getopt_long(3)
+ * XXX properly function again. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = 1;
+
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((*(place = nargv[optind]) != '-')
+ || (place[1] == '\0')) { /* found non-option */
+ place = EMSG;
+ if (IN_ORDER) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return INORDER;
+ }
+ if (!PERMUTE) {
+ /*
+ * if no permutation wanted, stop parsing
+ * at first non-option
+ */
+ return -1;
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+ if (place[1] && *++place == '-') { /* found "--" */
+ place++;
+ return -2;
+ }
+ }
+ if ((optchar = (int)*place++) == (int)':' ||
+ (oli = (char *) strchr(options + (IGNORE_FIRST ? 1 : 0),
+ optchar)) == NULL) {
+ /* option letter unknown or ':' */
+ if (!*place)
+ ++optind;
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+#else
+ warnx(PRINT_ERROR, illoptchar, optchar);
+#endif
+ optopt = optchar;
+ return BADCH;
+ }
+ if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
+ /* XXX: what if no long options provided (called by getopt)? */
+ if (*place)
+ return -2;
+
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+#else
+ warnx(PRINT_ERROR, recargchar, optchar);
+#endif
+ optopt = optchar;
+ return BADARG;
+ } else /* white space */
+ place = nargv[optind];
+ /*
+ * Handle -W arg the same as --arg (which causes getopt to
+ * stop parsing).
+ */
+ return -2;
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ /* XXX: disable test for :: if PC? (GNU doesn't) */
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+#else
+ warnx(PRINT_ERROR, recargchar, optchar);
+#endif
+ optopt = optchar;
+ return BADARG;
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return optchar;
+}
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the real getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ ++optind;
+ /*
+ * We found an option (--), so if we skipped non-options,
+ * we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end, optind,
+ nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ retval = -1;
+ }
+ return retval;
+}
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc,
+ char * const *nargv,
+ const char *options,
+ const struct option *long_options,
+ int *idx)
+{
+ int retval;
+
+ _DIAGASSERT(nargv != NULL);
+ _DIAGASSERT(options != NULL);
+ _DIAGASSERT(long_options != NULL);
+ /* idx may be NULL */
+
+ if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, match;
+
+ current_argv = place;
+ match = -1;
+
+ optind++;
+ place = EMSG;
+
+ if (*current_argv == '\0') { /* found "--" */
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return -1;
+ }
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) ==
+ (unsigned)current_argv_len) {
+ /* exact match */
+ match = i;
+ break;
+ }
+ if (match == -1) /* partial match */
+ match = i;
+ else {
+ /* ambiguous abbreviation */
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(ambig, (int)current_argv_len,
+ current_argv);
+#else
+ warnx(PRINT_ERROR, ambig, (int)current_argv_len,
+ current_argv);
+#endif
+ optopt = 0;
+ return BADCH;
+ }
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(noarg, (int)current_argv_len,
+ current_argv);
+#else
+ warnx(PRINT_ERROR, noarg, (int)current_argv_len,
+ current_argv);
+#endif
+ /*
+ * XXX: GNU sets optopt to val regardless of
+ * flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ return BADARG;
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use
+ * next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':'
+ * indicates no error should be generated
+ */
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(recargstring, current_argv);
+#else
+ warnx(PRINT_ERROR, recargstring, current_argv);
+#endif
+ /*
+ * XXX: GNU sets optopt to val regardless
+ * of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return BADARG;
+ }
+ } else { /* unknown option */
+#ifndef _WIN32
+ if (PRINT_ERROR)
+ warnx(illoptstring, current_argv);
+#else
+ warnx(PRINT_ERROR, illoptstring, current_argv);
+#endif
+ optopt = 0;
+ return BADCH;
+ }
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ retval = 0;
+ } else
+ retval = long_options[match].val;
+ if (idx)
+ *idx = match;
+ }
+ return retval;
+}
+#endif /* !GETOPT_LONG */
diff --git a/SoftHSMv2/src/bin/win32/getopt.h b/SoftHSMv2/src/bin/win32/getopt.h
new file mode 100644
index 0000000..f6b65a5
--- /dev/null
+++ b/SoftHSMv2/src/bin/win32/getopt.h
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+#ifdef _WIN32
+/* from <sys/cdefs.h> */
+# ifdef __cplusplus
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+# define __P(args) args
+#endif
+
+/*#ifndef _WIN32
+#include <sys/cdefs.h>
+#include <unistd.h>
+#endif*/
+
+/*
+ * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
+ */
+#if !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE)
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+struct option {
+ /* name of long option */
+ const char *name;
+ /*
+ * one of no_argument, required_argument, and optional_argument:
+ * whether option takes an argument
+ */
+ int has_arg;
+ /* if not NULL, set *flag to val when option found */
+ int *flag;
+ /* if flag not NULL, value to set *flag to; else return value */
+ int val;
+};
+
+__BEGIN_DECLS
+int getopt_long __P((int, char * const *, const char *,
+ const struct option *, int *));
+__END_DECLS
+#endif
+
+#ifdef _WIN32
+/* These are global getopt variables */
+__BEGIN_DECLS
+
+extern int opterr, /* if error message should be printed */
+ optind, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+extern char* optarg; /* argument associated with option */
+
+/* Original getopt */
+int getopt __P((int, char * const *, const char *));
+
+__END_DECLS
+#endif
+
+#endif /* !_GETOPT_H_ */
diff --git a/SoftHSMv2/src/bin/win32/getpassphase.cpp b/SoftHSMv2/src/bin/win32/getpassphase.cpp
new file mode 100644
index 0000000..9d8aaca
--- /dev/null
+++ b/SoftHSMv2/src/bin/win32/getpassphase.cpp
@@ -0,0 +1,35 @@
+/* WIN32 getpassphrase */
+
+#include <config.h>
+#include <stdio.h>
+
+char *
+getpassphrase(const char *prompt) {
+ static char buf[128];
+ HANDLE h;
+ DWORD cc, mode;
+ int cnt;
+
+ h = GetStdHandle(STD_INPUT_HANDLE);
+ fputs(prompt, stderr);
+ fflush(stderr);
+ fflush(stdout);
+ FlushConsoleInputBuffer(h);
+ GetConsoleMode(h, &mode);
+ SetConsoleMode(h, ENABLE_PROCESSED_INPUT);
+
+ for (cnt = 0; cnt < sizeof(buf) - 1; cnt++)
+ {
+ ReadFile(h, buf + cnt, 1, &cc, NULL);
+ if (buf[cnt] == '\r')
+ break;
+ fputc('*', stdout);
+ fflush(stderr);
+ fflush(stdout);
+ }
+
+ SetConsoleMode(h, mode);
+ buf[cnt] = '\0';
+ fputs("\n", stderr);
+ return (buf);
+}