Initial sshsm project structure

Issue-ID: AAF-94
Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4
Signed-off-by: NingSun <ning.sun@intel.com>
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);
+}