summaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/bin/util
diff options
context:
space:
mode:
authorNingSun <ning.sun@intel.com>2018-02-08 08:34:03 -0800
committerNingSun <ning.sun@intel.com>2018-02-08 09:14:52 -0800
commit0c89b3ccba7c9b7332ab67ae1936aff51ca62367 (patch)
tree70c1b1d160d4c6d0a83395ca9a87c1264d0d3439 /SoftHSMv2/src/bin/util
parent945613b4db4e07f75d2bc7463db580ddfaa700fd (diff)
Initial sshsm project structure
Issue-ID: AAF-94 Change-Id: I5e82fff418e7567b161acf9b98013a9b85ffc5b4 Signed-off-by: NingSun <ning.sun@intel.com>
Diffstat (limited to 'SoftHSMv2/src/bin/util')
-rw-r--r--SoftHSMv2/src/bin/util/Makefile.am40
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp704
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.h142
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp790
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.h142
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.1259
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.cpp1318
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util.h77
8 files changed, 3472 insertions, 0 deletions
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