aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/bin
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/bin')
-rw-r--r--SoftHSMv2/src/bin/Makefile.am4
-rw-r--r--SoftHSMv2/src/bin/dump/Makefile.am3
-rw-r--r--SoftHSMv2/src/bin/dump/tables.h5
-rw-r--r--SoftHSMv2/src/bin/keyconv/Makefile.am27
-rw-r--r--SoftHSMv2/src/bin/keyconv/base64.c311
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp227
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp261
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.163
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp351
-rw-r--r--SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h134
-rw-r--r--SoftHSMv2/src/bin/migrate/Makefile.am3
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp57
-rw-r--r--SoftHSMv2/src/bin/migrate/softhsm2-migrate.h2
-rw-r--r--SoftHSMv2/src/bin/util/Makefile.am3
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp178
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-botan.h34
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp200
-rw-r--r--SoftHSMv2/src/bin/util/softhsm2-util-ossl.h29
18 files changed, 1869 insertions, 23 deletions
diff --git a/SoftHSMv2/src/bin/Makefile.am b/SoftHSMv2/src/bin/Makefile.am
index b4a4f57..18d5586 100644
--- a/SoftHSMv2/src/bin/Makefile.am
+++ b/SoftHSMv2/src/bin/Makefile.am
@@ -1,9 +1,9 @@
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
-SUBDIRS = common util dump
+SUBDIRS = common keyconv util dump
if BUILD_MIGRATE
SUBDIRS += migrate
endif
-#EXTRA_DIST =
+EXTRA_DIST = $(srcdir)/CMakeLists.txt
diff --git a/SoftHSMv2/src/bin/dump/Makefile.am b/SoftHSMv2/src/bin/dump/Makefile.am
index c70d6f6..64bfa8c 100644
--- a/SoftHSMv2/src/bin/dump/Makefile.am
+++ b/SoftHSMv2/src/bin/dump/Makefile.am
@@ -20,5 +20,6 @@ softhsm2_dump_db_SOURCES = softhsm2-dump-db.cpp
softhsm2_dump_db_LDADD = @SQLITE3_LIBS@ @YIELD_LIB@
-EXTRA_DIST = $(srcdir)/*.h \
+EXTRA_DIST = $(srcdir)/CMakeLists.txt \
+ $(srcdir)/*.h \
softhsm2-dump-db.1
diff --git a/SoftHSMv2/src/bin/dump/tables.h b/SoftHSMv2/src/bin/dump/tables.h
index 76d64fb..e6db516 100644
--- a/SoftHSMv2/src/bin/dump/tables.h
+++ b/SoftHSMv2/src/bin/dump/tables.h
@@ -88,7 +88,7 @@ void fill_CKA_table(std::map<unsigned long, std::string> &t)
t[CKA_SUBPRIME] = "CKA_SUBPRIME";
t[CKA_BASE] = "CKA_BASE";
t[CKA_PRIME_BITS] = "CKA_PRIME_BITS";
- t[CKA_SUBPRIME_BITS] = "CKA_SUBPRIME_BITS";
+ t[CKA_SUB_PRIME_BITS] = "CKA_SUB_PRIME_BITS";
t[CKA_VALUE_BITS] = "CKA_VALUE_BITS";
t[CKA_VALUE_LEN] = "CKA_VALUE_LEN";
t[CKA_EXTRACTABLE] = "CKA_EXTRACTABLE";
@@ -476,6 +476,8 @@ void fill_CKM_table(std::map<unsigned long, std::string> &t)
t[CKM_AES_KEY_WRAP_PAD] = "CKM_AES_KEY_WRAP_PAD";
t[CKM_RSA_PKCS_TPM_1_1] = "CKM_RSA_PKCS_TPM_1_1";
t[CKM_RSA_PKCS_OAEP_TPM_1_1] = "CKM_RSA_PKCS_OAEP_TPM_1_1";
+ t[CKM_EC_EDWARDS_KEY_PAIR_GEN] = "CKM_EC_EDWARDS_KEY_PAIR_GEN";
+ t[CKM_EDDSA] = "CKM_EDDSA";
}
void fill_CKO_table(std::map<unsigned long, std::string> &t)
@@ -541,6 +543,7 @@ void fill_CKK_table(std::map<unsigned long, std::string> &t)
t[CKK_GOSTR3410] = "CKK_GOSTR3410";
t[CKK_GOSTR3411] = "CKK_GOSTR3411";
t[CKK_GOST28147] = "CKK_GOST28147";
+ t[CKK_EC_EDWARDS] = "CKK_EC_EDWARDS";
}
void fill_CKC_table(std::map<unsigned long, std::string> &t)
diff --git a/SoftHSMv2/src/bin/keyconv/Makefile.am b/SoftHSMv2/src/bin/keyconv/Makefile.am
new file mode 100644
index 0000000..5565017
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/Makefile.am
@@ -0,0 +1,27 @@
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+AM_CPPFLAGS = -I$(srcdir)/../../lib/crypto \
+ @CRYPTO_INCLUDES@
+
+dist_man_MANS = softhsm2-keyconv.1
+
+bin_PROGRAMS = softhsm2-keyconv
+
+softhsm2_keyconv_SOURCES = softhsm2-keyconv.cpp \
+ base64.c
+softhsm2_keyconv_LDADD = @CRYPTO_LIBS@
+
+# Compile with OpenSSL support
+if WITH_OPENSSL
+softhsm2_keyconv_SOURCES += softhsm2-keyconv-ossl.cpp \
+ ../../lib/crypto/OSSLComp.cpp
+endif
+
+# Compile with Botan support
+if WITH_BOTAN
+softhsm2_keyconv_SOURCES += softhsm2-keyconv-botan.cpp
+endif
+
+EXTRA_DIST = $(srcdir)/CMakeLists.txt \
+ $(srcdir)/*.h \
+ $(srcdir)/*.cpp
diff --git a/SoftHSMv2/src/bin/keyconv/base64.c b/SoftHSMv2/src/bin/keyconv/base64.c
new file mode 100644
index 0000000..3eb1201
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/base64.c
@@ -0,0 +1,311 @@
+/* $OpenBSD: base64.c,v 1.3 2002/06/09 08:13:07 todd Exp $ */
+
+/*
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$ISC: base64.c,v 8.6 1999/01/08 19:25:18 vixie Exp $";
+#endif /* not lint */
+
+#include <sys/types.h>
+#ifndef _WIN32
+#include <sys/param.h>
+#include <sys/socket.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(unsigned char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ unsigned char input[3];
+ unsigned char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(char const *src, unsigned char *target, size_t targsize) {
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp
new file mode 100644
index 0000000..cb5700f
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-botan.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-keyconv-botan.cpp
+
+ Code specific for Botan
+ *****************************************************************************/
+
+#include <config.h>
+#define KEYCONV_BOTAN
+#include "softhsm2-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <botan/init.h>
+#include <botan/auto_rng.h>
+#include <botan/pkcs8.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/bigint.h>
+#include <botan/version.h>
+
+// Init Botan
+void crypto_init()
+{
+ Botan::LibraryInitializer::initialize();
+}
+
+// Final Botan
+void crypto_final()
+{
+ Botan::LibraryInitializer::deinitialize();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigE, bigP, bigQ, bigN, bigD;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigE = Botan::BigInt((Botan::byte*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size);
+ bigP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size);
+ bigQ = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size);
+ bigN = Botan::BigInt((Botan::byte*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size);
+ bigD = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34)
+ priv_key = new Botan::RSA_PrivateKey(bigP, bigQ, bigE, bigD, bigN);
+#else
+ priv_key = new Botan::RSA_PrivateKey(*rng, bigP, bigQ, bigE, bigD, bigN);
+#endif
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (!priv_file.is_open())
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, std::chrono::milliseconds(300), "PBE-PKCS5v15(MD5,DES/CBC)");
+#else
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+#endif
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch(std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ int result = 0;
+ Botan::Private_Key* priv_key = NULL;
+ Botan::AutoSeeded_RNG* rng = NULL;
+ Botan::BigInt bigDP, bigDQ, bigDG, bigDX;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ bigDP = Botan::BigInt((Botan::byte*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size);
+ bigDQ = Botan::BigInt((Botan::byte*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size);
+ bigDG = Botan::BigInt((Botan::byte*)pkey[TAG_BASE].big, pkey[TAG_BASE].size);
+ bigDX = Botan::BigInt((Botan::byte*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size);
+
+ rng = new Botan::AutoSeeded_RNG();
+
+ try
+ {
+ priv_key = new Botan::DSA_PrivateKey(*rng, Botan::DL_Group(bigDP, bigDQ, bigDG), bigDX);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not extract the private key from the file.\n");
+ delete rng;
+ return 1;
+ }
+
+ std::ofstream priv_file(out_path);
+ if (!priv_file.is_open())
+ {
+ fprintf(stderr, "ERROR: Could not open file for output.\n");
+ delete rng;
+ delete priv_key;
+ return 1;
+ }
+
+ try
+ {
+ if (file_pin == NULL)
+ {
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key);
+ }
+ else
+ {
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, std::chrono::milliseconds(300), "PBE-PKCS5v15(MD5,DES/CBC)");
+#else
+ priv_file << Botan::PKCS8::PEM_encode(*priv_key, *rng, file_pin, "PBE-PKCS5v15(MD5,DES/CBC)");
+#endif
+ }
+
+ printf("The key has been written to %s\n", out_path);
+ }
+ catch (std::exception& e)
+ {
+ fprintf(stderr, "%s\n", e.what());
+ fprintf(stderr, "ERROR: Could not write to file.\n");
+ result = 1;
+ }
+
+ delete rng;
+ delete priv_key;
+ priv_file.close();
+
+ return result;
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp
new file mode 100644
index 0000000..a5cd8eb
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv-ossl.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ softhsm2-keyconv-ossl.cpp
+
+ Code specific for OpenSSL
+ *****************************************************************************/
+
+#include <config.h>
+#define KEYCONV_OSSL
+#include "softhsm2-keyconv.h"
+#include "OSSLComp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/dsa.h>
+#include <openssl/rsa.h>
+
+// Init OpenSSL
+void crypto_init()
+{
+ OpenSSL_add_all_algorithms();
+#ifdef WITH_FIPS
+ if (!FIPS_mode_set(1))
+ {
+ fprintf(stderr, "ERROR: can't enter into FIPS mode.\n");
+ exit(0);
+ }
+#endif
+}
+
+// Final OpenSSL
+void crypto_final()
+{
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+}
+
+// Save the RSA key as a PKCS#8 file
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ RSA* rsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_MODULUS].size <= 0 ||
+ pkey[TAG_PUBEXP].size <= 0 ||
+ pkey[TAG_PRIVEXP].size <= 0 ||
+ pkey[TAG_PRIME1].size <= 0 ||
+ pkey[TAG_PRIME2].size <= 0 ||
+ pkey[TAG_EXP1].size <= 0 ||
+ pkey[TAG_EXP2].size <= 0 ||
+ pkey[TAG_COEFF].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ rsa = RSA_new();
+ BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME1].big, pkey[TAG_PRIME1].size, NULL);
+ BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_PRIME2].big, pkey[TAG_PRIME2].size, NULL);
+ BIGNUM* bn_d = BN_bin2bn((unsigned char*)pkey[TAG_PRIVEXP].big, pkey[TAG_PRIVEXP].size, NULL);
+ BIGNUM* bn_n = BN_bin2bn((unsigned char*)pkey[TAG_MODULUS].big, pkey[TAG_MODULUS].size, NULL);
+ BIGNUM* bn_e = BN_bin2bn((unsigned char*)pkey[TAG_PUBEXP].big, pkey[TAG_PUBEXP].size, NULL);
+ BIGNUM* bn_dmp1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP1].big, pkey[TAG_EXP1].size, NULL);
+ BIGNUM* bn_dmq1 = BN_bin2bn((unsigned char*)pkey[TAG_EXP2].big, pkey[TAG_EXP2].size, NULL);
+ BIGNUM* bn_iqmp = BN_bin2bn((unsigned char*)pkey[TAG_COEFF].big, pkey[TAG_COEFF].size, NULL);
+ RSA_set0_factors(rsa, bn_p, bn_q);
+ RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp);
+ RSA_set0_key(rsa, bn_n, bn_e, bn_d);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert RSA to EVP_PKEY
+ if (!EVP_PKEY_set1_RSA(ossl_pkey, rsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert RSA key to EVP_PKEY.\n");
+ RSA_free(rsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ RSA_free(rsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
+
+// Save the DSA key as a PKCS#8 file
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey)
+{
+ DSA* dsa = NULL;
+ EVP_PKEY* ossl_pkey = NULL;
+ PKCS8_PRIV_KEY_INFO* p8inf = NULL;
+ BIO* out = NULL;
+ X509_SIG* p8 = NULL;
+ int result = 0;
+
+ // See if the key material was found.
+ if
+ (
+ pkey[TAG_PRIME].size <= 0 ||
+ pkey[TAG_SUBPRIME].size <= 0 ||
+ pkey[TAG_BASE].size <= 0 ||
+ pkey[TAG_PRIVVAL].size <= 0 ||
+ pkey[TAG_PUBVAL].size <= 0
+ )
+ {
+ fprintf(stderr, "ERROR: Some parts of the key material is missing in the input file.\n");
+ return 1;
+ }
+
+ dsa = DSA_new();
+ BIGNUM* bn_p = BN_bin2bn((unsigned char*)pkey[TAG_PRIME].big, pkey[TAG_PRIME].size, NULL);
+ BIGNUM* bn_q = BN_bin2bn((unsigned char*)pkey[TAG_SUBPRIME].big, pkey[TAG_SUBPRIME].size, NULL);
+ BIGNUM* bn_g = BN_bin2bn((unsigned char*)pkey[TAG_BASE].big, pkey[TAG_BASE].size, NULL);
+ BIGNUM* bn_priv_key = BN_bin2bn((unsigned char*)pkey[TAG_PRIVVAL].big, pkey[TAG_PRIVVAL].size, NULL);
+ BIGNUM* bn_pub_key = BN_bin2bn((unsigned char*)pkey[TAG_PUBVAL].big, pkey[TAG_PUBVAL].size, NULL);
+
+ DSA_set0_pqg(dsa, bn_p, bn_q, bn_g);
+ DSA_set0_key(dsa, bn_pub_key, bn_priv_key);
+
+ ossl_pkey = EVP_PKEY_new();
+
+ // Convert DSA to EVP_PKEY
+ if (!EVP_PKEY_set1_DSA(ossl_pkey, dsa))
+ {
+ fprintf(stderr, "ERROR: Could not convert DSA key to EVP_PKEY.\n");
+ DSA_free(dsa);
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ DSA_free(dsa);
+
+ // Convert EVP_PKEY to PKCS#8
+ if (!(p8inf = EVP_PKEY2PKCS8(ossl_pkey)))
+ {
+ fprintf(stderr, "ERROR: Could not convert EVP_PKEY to PKCS#8.\n");
+ EVP_PKEY_free(ossl_pkey);
+ return 1;
+ }
+ EVP_PKEY_free(ossl_pkey);
+
+ // Open output file
+ if (!(out = BIO_new_file (out_path, "wb")))
+ {
+ fprintf(stderr, "ERROR: Could not open the output file.\n");
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return 1;
+ }
+
+ // Write to disk
+ if (file_pin == NULL)
+ {
+ PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
+ printf("The key has been written to %s\n", out_path);
+ }
+ else
+ {
+ // Encrypt p8
+ if (!(p8 = PKCS8_encrypt(NID_pbeWithMD5AndDES_CBC, NULL,
+ file_pin, strlen(file_pin), NULL,
+ 0, PKCS12_DEFAULT_ITER, p8inf)))
+ {
+ fprintf(stderr, "ERROR: Could not encrypt the PKCS#8 file\n");
+ result = 1;
+ }
+ else
+ {
+ PEM_write_bio_PKCS8(out, p8);
+ X509_SIG_free(p8);
+ printf("The key has been written to %s\n", out_path);
+ }
+ }
+
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ BIO_free_all(out);
+
+ return result;
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1 b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1
new file mode 100644
index 0000000..b716bc8
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.1
@@ -0,0 +1,63 @@
+.TH SOFTHSM2-KEYCONV 1 "20 March 2014" "SoftHSM"
+.SH NAME
+softhsm2-keyconv \- converting from BIND to PKCS#8 key file format
+.SH SYNOPSIS
+.B softhsm2-keyconv
+.B \-\-in
+.I path
+.B \-\-out
+.I path
+.RB [ \-\-pin
+.IR PIN ]
+.SH DESCRIPTION
+.B softhsm2-keyconv
+can convert BIND .private-key files to the PKCS#8 file format.
+This is so that you can import the PKCS#8 file into
+libsofthsm using the command
+.BR softhsm2\-util .
+If you have another file format, then
+.B openssl
+probably can help you to convert it into the PKCS#8 file format.
+.SH OPTIONS
+.B \-\-help\fR, \fB\-h\fR
+Shows the help screen.
+.TP
+.B \-\-in \fIpath\fR
+The
+.I path
+to the input file.
+.TP
+.B \-\-out \fIpath\fR
+The
+.I path
+to the output file.
+.TP
+.B \-\-pin \fIPIN\fR
+The
+.I PIN
+will be used to encrypt the PKCS#8 file.
+If not given then the PKCS#8 file will be unencrypted.
+.TP
+.B \-\-version\fR, \fB\-v\fR
+Show the version info.
+.SH EXAMPLES
+The following command can be used to convert a BIND .private-key file to a PKCS#8 file:
+.LP
+.RS
+.nf
+softhsm2-keyconv \-\-in Kexample.com.+007+05474.private \\
+.ti +0.7i
+\-\-out rsa.pem
+.fi
+.RE
+.LP
+.SH AUTHORS
+Written by Rickard Bellgrim, Francis Dupont, René Post, and Roland van Rijswijk.
+.SH "SEE ALSO"
+.IR softhsm2-migrate (1),
+.IR softhsm2-util (1),
+.IR softhsm2.conf (5),
+.IR openssl (1),
+.IR named (1),
+.IR dnssec-keygen (1),
+.IR dnssec-signzone (1)
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp
new file mode 100644
index 0000000..aeb75c3
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/************************************************************
+*
+* softhsm2-keyconv
+*
+* This program is for converting from BIND .private-key
+* format to PKCS#8 key file format. So that keys can be
+* imported from BIND to SoftHSM.
+*
+* Some of the design/code is from keyconv.c written by
+* Hakan Olsson and Jakob Schlyter in 2000 and 2001.
+*
+************************************************************/
+
+#include <config.h>
+#include "softhsm2-keyconv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define open _open
+#define close _close
+#endif
+#include <iostream>
+#include <fstream>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void usage()
+{
+ printf("Converting from BIND .private-key format to PKCS#8 key file format.\n");
+ printf("Usage: softhsm2-keyconv [OPTIONS]\n");
+ printf("Options:\n");
+ printf(" -h Shows this help screen.\n");
+ printf(" --help Shows this help screen.\n");
+ printf(" --in <path> The path to the input file.\n");
+ printf(" --out <path> The path to the output file.\n");
+ printf(" --pin <PIN> To encrypt PKCS#8 file. Optional.\n");
+ printf(" -v Show version info.\n");
+ printf(" --version Show version info.\n");
+}
+
+// Give a number to each option
+enum {
+ OPT_HELP = 0x100,
+ OPT_IN,
+ OPT_OUT,
+ OPT_PIN,
+ OPT_VERSION
+};
+
+// Define the options
+static const struct option long_options[] = {
+ { "help", 0, NULL, OPT_HELP },
+ { "in", 1, NULL, OPT_IN },
+ { "out", 1, NULL, OPT_OUT },
+ { "pin", 1, NULL, OPT_PIN },
+ { "version", 0, NULL, OPT_VERSION },
+ { NULL, 0, NULL, 0 }
+};
+
+int main(int argc, char* argv[])
+{
+ int option_index = 0;
+ int opt, result;
+
+ char* in_path = NULL;
+ char* out_path = NULL;
+ char* file_pin = NULL;
+
+ if (argc == 1)
+ {
+ usage();
+ exit(0);
+ }
+
+ while ((opt = getopt_long(argc, argv, "hv", long_options, &option_index)) != -1)
+ {
+ switch (opt)
+ {
+ case OPT_IN:
+ in_path = optarg;
+ break;
+ case OPT_OUT:
+ out_path = optarg;
+ break;
+ case OPT_PIN:
+ file_pin = optarg;
+ break;
+ case OPT_VERSION:
+ case 'v':
+ printf("%s\n", PACKAGE_VERSION);
+ exit(0);
+ break;
+ case OPT_HELP:
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ // We should convert to PKCS#8
+ result = to_pkcs8(in_path, out_path, file_pin);
+
+ return result;
+}
+
+// Convert from BIND to PKCS#8
+int to_pkcs8(char* in_path, char* out_path, char* file_pin)
+{
+ FILE* file_pointer = NULL;
+ char line[MAX_LINE], data[MAX_LINE];
+ char* value_pointer = NULL;
+ int lineno = 0, m, n, error = 0, found, algorithm = DNS_KEYALG_ERROR, data_length;
+ uint32_t bitfield = 0;
+ key_material_t pkey[TAG_MAX];
+
+ if (in_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the input file must be supplied. Use --in <path>\n");
+ return 1;
+ }
+
+ if (out_path == NULL)
+ {
+ fprintf(stderr, "ERROR: A path to the output file must be supplied. Use --out <path>\n");
+ return 1;
+ }
+
+ file_pointer = fopen(in_path, "r");
+ if (file_pointer == NULL)
+ {
+ fprintf(stderr, "ERROR: Could not open input file %.100s for reading.\n", in_path);
+ return 1;
+ }
+
+ // Loop over all of the lines
+ while (fgets(line, MAX_LINE, file_pointer) != NULL)
+ {
+ lineno++;
+
+ // Find the current text field in the BIND file.
+ for (m = 0, found = -1; found == -1 && file_tags[m]; m++)
+ {
+ if (strncasecmp(line, file_tags[m], strlen(file_tags[m])) == 0)
+ {
+ found = m;
+ }
+ }
+
+ // The text files is not recognized.
+ if (found == -1)
+ {
+ fprintf(stderr, "ERROR: Unrecognized input line %i\n", lineno);
+ fprintf(stderr, "ERROR: --> %s", line);
+ continue;
+ }
+
+ // Point to the data for this text field.
+ value_pointer = line + strlen(file_tags[found]) + 1;
+
+ // Continue if we are at the end of the string
+ if (*value_pointer == 0)
+ {
+ continue;
+ }
+
+ // Check that we do not get duplicates.
+ if (bitfield & (1 << found))
+ {
+ fprintf(stderr, "ERROR: Duplicate \"%s\" field, line %i - ignored\n",
+ file_tags[found], lineno);
+ continue;
+ }
+ bitfield |= (1 << found);
+
+ // Handle the data for this text field.
+ switch (found)
+ {
+ case TAG_VERSION:
+ if (sscanf(value_pointer, "v%i.%i", &m, &n) != 2)
+ {
+ fprintf(stderr, "ERROR: Invalid/unknown version string "
+ "(%.100s).\n", value_pointer);
+ error = 1;
+ break;
+ }
+ if (m > FILE_MAJOR_VERSION || (m == FILE_MAJOR_VERSION && n > FILE_MINOR_VERSION))
+ {
+ fprintf(stderr, "ERROR: Cannot parse this version of file format, "
+ "v%i.%i.\n", m, n);
+ error = 1;
+ }
+ break;
+ case TAG_ALGORITHM:
+ algorithm = strtol(value_pointer, NULL, 10);
+ break;
+ // RSA
+ case TAG_MODULUS:
+ case TAG_PUBEXP:
+ case TAG_PRIVEXP:
+ case TAG_PRIME1:
+ case TAG_PRIME2:
+ case TAG_EXP1:
+ case TAG_EXP2:
+ case TAG_COEFF:
+ // DSA
+ case TAG_PRIME:
+ case TAG_SUBPRIME:
+ case TAG_BASE:
+ case TAG_PRIVVAL:
+ case TAG_PUBVAL:
+ data_length = b64_pton(value_pointer, (unsigned char*)data, MAX_LINE);
+ if (data_length == -1)
+ {
+ error = 1;
+ fprintf(stderr, "ERROR: Could not parse the base64 string on line %i.\n", lineno);
+ }
+ else
+ {
+ pkey[found].big = malloc(data_length);
+ if (!pkey[found].big)
+ {
+ fprintf(stderr, "ERROR: Could not allocate memory.\n");
+ error = 1;
+ break;
+ }
+ memcpy(pkey[found].big, data, data_length);
+ pkey[found].size = data_length;
+ }
+ break;
+ // Do not need these
+ case TAG_CREATED:
+ case TAG_PUBLISH:
+ case TAG_ACTIVATE:
+ default:
+ break;
+ }
+ }
+
+ fclose(file_pointer);
+
+ // Something went wrong. Clean up and quit.
+ if (error)
+ {
+ free_key_material(pkey);
+ return error;
+ }
+
+ // Create and set file permissions if the file does not exist.
+ int fd = open(out_path, O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1)
+ {
+ fprintf(stderr, "ERROR: Could not open the output file: %s (errno %i)\n",
+ out_path, errno);
+ free_key_material(pkey);
+ return 1;
+ }
+ ::close(fd);
+
+ crypto_init();
+
+ // Save the the key to the disk
+ switch (algorithm)
+ {
+ case DNS_KEYALG_ERROR:
+ fprintf(stderr, "ERROR: The algorithm %i was not given in the file.\n",
+ algorithm);
+ error = 1;
+ break;
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_RSASHA1_NSEC3_SHA1:
+ case DNS_KEYALG_RSASHA256:
+ case DNS_KEYALG_RSASHA512:
+ error = save_rsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_DSA_NSEC3_SHA1:
+ error = save_dsa_pkcs8(out_path, file_pin, pkey);
+ break;
+ case DNS_KEYALG_ECC:
+ case DNS_KEYALG_ECC_GOST:
+ default:
+ fprintf(stderr, "ERROR: The algorithm %i is not supported.\n",
+ algorithm);
+ error = 1;
+ break;
+ }
+
+ crypto_final();
+ free_key_material(pkey);
+
+ return error;
+}
+
+// Free allocated memory
+void free_key_material(key_material_t* pkey)
+{
+ int i;
+
+ if (!pkey)
+ {
+ return;
+ }
+
+ for (i = 0; i < TAG_MAX; i++)
+ {
+ if (pkey[i].big)
+ {
+ free(pkey[i].big);
+ }
+ }
+}
diff --git a/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h
new file mode 100644
index 0000000..fdeb719
--- /dev/null
+++ b/SoftHSMv2/src/bin/keyconv/softhsm2-keyconv.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SOFTHSM_V2_SOFTHSM2_KEYCONV_H
+#define _SOFTHSM_V2_SOFTHSM2_KEYCONV_H 1
+
+#include <stdlib.h>
+
+typedef struct key_material_t {
+ unsigned long size;
+ void* big;
+ key_material_t() {
+ size = 0;
+ big = NULL;
+ }
+} key_material_t;
+
+// Main functions
+
+void usage();
+int to_pkcs8(char* in_path, char* out_path, char* file_pin);
+
+// Support functions
+
+int save_rsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+int save_dsa_pkcs8(char* out_path, char* file_pin, key_material_t* pkey);
+void free_key_material(key_material_t* pkey);
+void crypto_init();
+void crypto_final();
+
+// base64.c prototypes
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int b64_pton(const char* , unsigned char*, size_t);
+int b64_ntop(const unsigned char*, size_t, char*, size_t);
+#ifdef __cplusplus
+}
+#endif
+
+// The BIND file version number.
+#define FILE_MAJOR_VERSION 1
+#define FILE_MINOR_VERSION 3
+
+// Key algorithm number
+#define DNS_KEYALG_ERROR -1
+#define DNS_KEYALG_RSAMD5 1
+#define DNS_KEYALG_DSA 3
+#define DNS_KEYALG_ECC 4
+#define DNS_KEYALG_RSASHA1 5
+#define DNS_KEYALG_DSA_NSEC3_SHA1 6
+#define DNS_KEYALG_RSASHA1_NSEC3_SHA1 7
+#define DNS_KEYALG_RSASHA256 8
+#define DNS_KEYALG_RSASHA512 10
+#define DNS_KEYALG_ECC_GOST 12
+
+// Maximum number of lines / line length
+#define MAX_LINE 4096
+
+// The text fields supported
+#if !defined(KEYCONV_BOTAN) && !defined(KEYCONV_OSSL)
+static const char* file_tags[] = {
+ "Private-key-format:",
+ "Algorithm:",
+ "Modulus:",
+ "PublicExponent:",
+ "PrivateExponent:",
+ "Prime1:",
+ "Prime2:",
+ "Exponent1:",
+ "Exponent2:",
+ "Coefficient:",
+ "Prime(p):",
+ "Private_value(x):",
+ "Public_value(y):",
+ "Subprime(q):",
+ "Base(g):",
+ "Created:",
+ "Publish:",
+ "Activate:",
+ NULL
+};
+#endif
+
+// The number of each text field.
+// Must match the tags above.
+enum FILE_TAGS {
+ TAG_VERSION = 0,
+ TAG_ALGORITHM,
+ TAG_MODULUS,
+ TAG_PUBEXP,
+ TAG_PRIVEXP,
+ TAG_PRIME1,
+ TAG_PRIME2,
+ TAG_EXP1,
+ TAG_EXP2,
+ TAG_COEFF,
+ TAG_PRIME,
+ TAG_PRIVVAL,
+ TAG_PUBVAL,
+ TAG_SUBPRIME,
+ TAG_BASE,
+ TAG_CREATED,
+ TAG_PUBLISH,
+ TAG_ACTIVATE,
+ // So we know how long this list is
+ TAG_MAX
+};
+
+#endif /* _SOFTHSM_V2_SOFTHSM2_KEYCONV_H */
diff --git a/SoftHSMv2/src/bin/migrate/Makefile.am b/SoftHSMv2/src/bin/migrate/Makefile.am
index 020c6a7..d903764 100644
--- a/SoftHSMv2/src/bin/migrate/Makefile.am
+++ b/SoftHSMv2/src/bin/migrate/Makefile.am
@@ -17,4 +17,5 @@ softhsm2_migrate_SOURCES = softhsm2-migrate.cpp \
softhsm2_migrate_LDADD = @SQLITE3_LIBS@ \
@YIELD_LIB@
-EXTRA_DIST = $(srcdir)/*.h
+EXTRA_DIST = $(srcdir)/CMakeLists.txt \
+ $(srcdir)/*.h
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
index 0e6dc90..3ce04eb 100644
--- a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.cpp
@@ -503,9 +503,18 @@ CK_KEY_TYPE getKeyType(CK_OBJECT_HANDLE objectRef)
CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
- if (pValue != NULL_PTR && length == sizeof(CK_KEY_TYPE))
+ if (pValue != NULL_PTR)
{
- retVal = *(CK_KEY_TYPE*)pValue;
+ // 32/64-bit DB on 32/64-bit system
+ if (length == sizeof(CK_KEY_TYPE))
+ {
+ retVal = *(CK_KEY_TYPE*)pValue;
+ }
+ // 32-bit DB on 64-bit system (LP64)
+ else if (length == sizeof(unsigned int))
+ {
+ retVal = *(unsigned int*)pValue;
+ }
}
}
@@ -535,9 +544,18 @@ CK_OBJECT_CLASS getObjectClass(CK_OBJECT_HANDLE objectRef)
CK_VOID_PTR pValue = (CK_VOID_PTR)sqlite3_column_blob(select_an_attribute_sql, 0);
CK_ULONG length = sqlite3_column_int(select_an_attribute_sql, 1);
- if (pValue != NULL_PTR && length == sizeof(CK_OBJECT_CLASS))
+ if (pValue != NULL_PTR)
{
- retVal = *(CK_OBJECT_CLASS*)pValue;
+ // 32/64-bit DB on 32/64-bit system
+ if (length == sizeof(CK_OBJECT_CLASS))
+ {
+ retVal = *(CK_OBJECT_CLASS*)pValue;
+ }
+ // 32-bit DB on 64-bit system (LP64)
+ else if (length == sizeof(unsigned int))
+ {
+ retVal = *(unsigned int*)pValue;
+ }
}
}
@@ -617,10 +635,15 @@ int dbRSAPub2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HAND
int i;
CK_OBJECT_HANDLE hKey;
CK_RV rv;
+ CK_OBJECT_CLASS ckClass = CKO_PUBLIC_KEY;
+ CK_KEY_TYPE ckType = CKK_RSA;
+ // All required CK_ULONG attributes have known/fixed values.
+ // So no need read them from the DB and no need to handle
+ // convertion from 32-bit to 64-bit.
CK_ATTRIBUTE pubTemplate[] = {
- { CKA_CLASS, NULL, 0 },
- { CKA_KEY_TYPE, NULL, 0 },
+ { CKA_CLASS, &ckClass, sizeof(ckClass) },
+ { CKA_KEY_TYPE, &ckType, sizeof(ckType) },
{ CKA_TOKEN, NULL, 0 },
{ CKA_PRIVATE, NULL, 0 },
{ CKA_MODIFIABLE, NULL, 0 },
@@ -638,12 +661,12 @@ int dbRSAPub2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HAND
{ CKA_PUBLIC_EXPONENT, NULL, 0 }
};
- for (i = 0; i < 17; i++)
+ for (i = 2; i < 17; i++)
{
result = getAttribute(objectID, &pubTemplate[i]);
if (result)
{
- freeTemplate(pubTemplate, 17);
+ freeTemplate(pubTemplate, 2, 17);
return 1;
}
}
@@ -660,7 +683,7 @@ int dbRSAPub2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HAND
printf("Object %lu has been migrated\n", objectID);
}
- freeTemplate(pubTemplate, 17);
+ freeTemplate(pubTemplate, 2, 17);
return result;
}
@@ -672,9 +695,13 @@ int dbRSAPriv2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HAN
int i;
CK_OBJECT_HANDLE hKey;
CK_RV rv;
+ CK_OBJECT_CLASS ckClass = CKO_PRIVATE_KEY;
+ // All required CK_ULONG attributes have known/fixed values.
+ // So no need read them from the DB and no need to handle
+ // convertion from 32-bit to 64-bit.
CK_ATTRIBUTE privTemplate[] = {
- { CKA_CLASS, NULL, 0 },
+ { CKA_CLASS, &ckClass, sizeof(ckClass) },
{ CKA_TOKEN, NULL, 0 },
{ CKA_PRIVATE, NULL, 0 },
{ CKA_MODIFIABLE, NULL, 0 },
@@ -703,12 +730,12 @@ int dbRSAPriv2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HAN
// { CKA_COEFFICIENT, NULL, 0 }
};
- for (i = 0; i < 23; i++)
+ for (i = 1; i < 23; i++)
{
result = getAttribute(objectID, &privTemplate[i]);
if (result)
{
- freeTemplate(privTemplate, 23);
+ freeTemplate(privTemplate, 1, 23);
return 1;
}
}
@@ -725,7 +752,7 @@ int dbRSAPriv2session(sqlite3* /*db*/, CK_OBJECT_HANDLE objectID, CK_SESSION_HAN
printf("Object %lu has been migrated\n", objectID);
}
- freeTemplate(privTemplate, 23);
+ freeTemplate(privTemplate, 1, 23);
return result;
}
@@ -782,13 +809,13 @@ int getAttribute(CK_OBJECT_HANDLE objectRef, CK_ATTRIBUTE* attTemplate)
}
// Free allocated memory in the template
-void freeTemplate(CK_ATTRIBUTE* attTemplate, int size)
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int startIndex, int size)
{
int i;
if (!attTemplate) return;
- for (i = 0; i < size; i++)
+ for (i = startIndex; i < size; i++)
{
if(attTemplate[i].pValue)
{
diff --git a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
index 1b5a066..a02221c 100644
--- a/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
+++ b/SoftHSMv2/src/bin/migrate/softhsm2-migrate.h
@@ -49,7 +49,7 @@ int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession);
int db2session(sqlite3* db, CK_SESSION_HANDLE hSession, int noPublicKey);
int dbRSAPub2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
int dbRSAPriv2session(sqlite3* db, CK_OBJECT_HANDLE objectID, CK_SESSION_HANDLE hSession);
-void freeTemplate(CK_ATTRIBUTE* attTemplate, int size);
+void freeTemplate(CK_ATTRIBUTE* attTemplate, int startIndex, int size);
// Database functions
diff --git a/SoftHSMv2/src/bin/util/Makefile.am b/SoftHSMv2/src/bin/util/Makefile.am
index a552e14..788ea87 100644
--- a/SoftHSMv2/src/bin/util/Makefile.am
+++ b/SoftHSMv2/src/bin/util/Makefile.am
@@ -36,5 +36,6 @@ if WITH_BOTAN
softhsm2_util_SOURCES += softhsm2-util-botan.cpp
endif
-EXTRA_DIST = $(srcdir)/*.h \
+EXTRA_DIST = $(srcdir)/CMakeLists.txt \
+ $(srcdir)/*.h \
$(srcdir)/*.cpp
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
index cecc0ce..c7b1da3 100644
--- a/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.cpp
@@ -47,6 +47,7 @@
#include <botan/bigint.h>
#include <botan/version.h>
#include <botan/der_enc.h>
+#include <botan/oids.h>
#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
#include <botan/libstate.h>
@@ -162,6 +163,10 @@ int crypto_import_key_pair
#ifdef WITH_ECC
Botan::ECDSA_PrivateKey* ecdsa = NULL;
#endif
+#ifdef WITH_EDDSA
+ Botan::Curve25519_PrivateKey* x25519 = NULL;
+ Botan::Ed25519_PrivateKey* ed25519 = NULL;
+#endif
if (pkey->algo_name().compare("RSA") == 0)
{
@@ -177,6 +182,16 @@ int crypto_import_key_pair
ecdsa = dynamic_cast<Botan::ECDSA_PrivateKey*>(pkey);
}
#endif
+#ifdef WITH_EDDSA
+ else if (pkey->algo_name().compare("Curve25519") == 0)
+ {
+ x25519 = dynamic_cast<Botan::Curve25519_PrivateKey*>(pkey);
+ }
+ else if (pkey->algo_name().compare("Ed25519") == 0)
+ {
+ ed25519 = dynamic_cast<Botan::Ed25519_PrivateKey*>(pkey);
+ }
+#endif
else
{
fprintf(stderr, "ERROR: %s is not a supported algorithm.\n",
@@ -201,6 +216,16 @@ int crypto_import_key_pair
result = crypto_save_ecdsa(hSession, label, objID, objIDLen, noPublicKey, ecdsa);
}
#endif
+#ifdef WITH_EDDSA
+ else if (x25519)
+ {
+ result = crypto_save_eddsa(hSession, label, objID, objIDLen, noPublicKey, x25519, 0);
+ }
+ else if (ed25519)
+ {
+ result = crypto_save_eddsa(hSession, label, objID, objIDLen, noPublicKey, 0, ed25519);
+ }
+#endif
else
{
fprintf(stderr, "ERROR: Could not get the key material.\n");
@@ -702,3 +727,156 @@ void crypto_free_ecdsa(ecdsa_key_material_t* keyMat)
free(keyMat);
}
#endif
+
+#ifdef WITH_EDDSA
+// Save the key data in PKCS#11
+int crypto_save_eddsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ Botan::Curve25519_PrivateKey* x25519,
+ Botan::Ed25519_PrivateKey* ed25519
+)
+{
+ eddsa_key_material_t* keyMat = crypto_malloc_eddsa(x25519, ed25519);
+ 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_EDWARDS;
+ 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->derOID, keyMat->sizeOID },
+ { CKA_EC_POINT, keyMat->bigA, keyMat->sizeA },
+ };
+ 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->derOID, keyMat->sizeOID },
+ { CKA_VALUE, keyMat->bigK, keyMat->sizeK }
+ };
+
+ 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_eddsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_eddsa(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
+eddsa_key_material_t* crypto_malloc_eddsa
+(
+ Botan::Curve25519_PrivateKey* x25519,
+ Botan::Ed25519_PrivateKey* ed25519
+ )
+{
+ if ((x25519 == NULL) && (ed25519 == NULL))
+ {
+ return NULL;
+ }
+
+ eddsa_key_material_t* keyMat = (eddsa_key_material_t*)malloc(sizeof(eddsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ Botan::OID oid;
+ if (x25519) oid = Botan::OIDS::lookup("Curve25519");
+ if (ed25519) oid = Botan::OIDS::lookup("Ed25519");
+ if (oid.empty())
+ {
+ return NULL;
+ }
+
+ Botan::secure_vector<Botan::byte> derOID;
+ derOID = Botan::DER_Encoder().encode(oid).get_contents();
+
+ memset(keyMat, 0, sizeof(*keyMat));
+ keyMat->sizeOID = derOID.size();
+ keyMat->derOID = (CK_VOID_PTR)malloc(keyMat->sizeOID);
+
+ std::vector<Botan::byte> pub;
+ if (x25519) pub = x25519->public_value();
+ if (ed25519) pub = ed25519->get_public_key();
+ keyMat->sizeA = pub.size();
+ keyMat->bigA = (CK_VOID_PTR)malloc(keyMat->sizeA);
+
+ Botan::secure_vector<Botan::byte> priv;
+ if (x25519) priv = x25519->get_x();
+ if (ed25519)
+ {
+ priv = ed25519->get_private_key();
+ priv.resize(32);
+ }
+ keyMat->sizeK = priv.size();
+ keyMat->bigK = (CK_VOID_PTR)malloc(keyMat->sizeK);
+
+ if (!keyMat->derOID || !keyMat->bigK || !keyMat->bigA)
+ {
+ crypto_free_eddsa(keyMat);
+ return NULL;
+ }
+
+ memcpy(keyMat->derOID, derOID.data(), keyMat->sizeOID);
+ memcpy(keyMat->bigA, pub.data(), keyMat->sizeA);
+ memcpy(keyMat->bigK, priv.data(), keyMat->sizeK);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_eddsa(eddsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->derOID) free(keyMat->derOID);
+ if (keyMat->bigK) free(keyMat->bigK);
+ if (keyMat->bigA) free(keyMat->bigA);
+ free(keyMat);
+}
+#endif
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-botan.h b/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
index 8cd4a5e..6ad7664 100644
--- a/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-botan.h
@@ -38,6 +38,12 @@
#ifdef WITH_ECC
#include <botan/ecdsa.h>
#endif
+#ifdef WITH_EDDSA
+#include <botan/curve25519.h>
+#include <botan/ed25519.h>
+// #include <botan/curve448.h>
+// #include <botan/ed448.h>
+#endif
typedef struct rsa_key_material_t {
CK_ULONG sizeE;
@@ -120,6 +126,25 @@ typedef struct ecdsa_key_material_t {
} ecdsa_key_material_t;
#endif
+#ifdef WITH_EDDSA
+typedef struct eddsa_key_material_t {
+ CK_ULONG sizeOID;
+ CK_ULONG sizeK;
+ CK_ULONG sizeA;
+ CK_VOID_PTR derOID;
+ CK_VOID_PTR bigK;
+ CK_VOID_PTR bigA;
+ eddsa_key_material_t() {
+ sizeOID = 0;
+ sizeK = 0;
+ sizeA = 0;
+ derOID = NULL_PTR;
+ bigK = NULL_PTR;
+ bigA = NULL_PTR;
+ }
+} eddsa_key_material_t;
+#endif
+
Botan::Private_Key* crypto_read_file(char* filePath, char* filePIN);
// RSA
@@ -139,4 +164,11 @@ 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
+// EDDSA
+#ifdef WITH_EDDSA
+int crypto_save_eddsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, Botan::Curve25519_PrivateKey* x25519, Botan::Ed25519_PrivateKey* ed25519);
+eddsa_key_material_t* crypto_malloc_eddsa(Botan::Curve25519_PrivateKey* x25519, Botan::Ed25519_PrivateKey* ed25519);
+void crypto_free_eddsa(eddsa_key_material_t* keyMat);
+#endif
+
+#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_BOTAN_H
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
index fedfd28..e56dfba 100644
--- a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.cpp
@@ -46,6 +46,7 @@
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pkcs12.h>
+#include <openssl/objects.h>
// Init OpenSSL
void crypto_init()
@@ -146,6 +147,9 @@ int crypto_import_key_pair
#ifdef WITH_ECC
EC_KEY* ecdsa = NULL;
#endif
+#ifdef WITH_EDDSA
+ EVP_PKEY* eddsa = NULL;
+#endif
switch (EVP_PKEY_type(EVP_PKEY_id(pkey)))
{
@@ -160,6 +164,15 @@ int crypto_import_key_pair
ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
break;
#endif
+#ifdef WITH_EDDSA
+ case NID_X25519:
+ case NID_ED25519:
+ case NID_X448:
+ case NID_ED448:
+ EVP_PKEY_up_ref(pkey);
+ eddsa = pkey;
+ break;
+#endif
default:
fprintf(stderr, "ERROR: Cannot handle this algorithm.\n");
EVP_PKEY_free(pkey);
@@ -187,6 +200,13 @@ int crypto_import_key_pair
EC_KEY_free(ecdsa);
}
#endif
+#ifdef WITH_EDDSA
+ else if (eddsa)
+ {
+ result = crypto_save_eddsa(hSession, label, objID, objIDLen, noPublicKey, eddsa);
+ EVP_PKEY_free(eddsa);
+ }
+#endif
else
{
fprintf(stderr, "ERROR: Could not get the key material.\n");
@@ -788,3 +808,183 @@ void crypto_free_ecdsa(ecdsa_key_material_t* keyMat)
}
#endif
+
+#ifdef WITH_EDDSA
+
+// Save the key data in PKCS#11
+int crypto_save_eddsa
+(
+ CK_SESSION_HANDLE hSession,
+ char* label,
+ char* objID,
+ size_t objIDLen,
+ int noPublicKey,
+ EVP_PKEY* eddsa
+)
+{
+ eddsa_key_material_t* keyMat = crypto_malloc_eddsa(eddsa);
+ 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_EDWARDS;
+ 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->derOID, keyMat->sizeOID },
+ { CKA_EC_POINT, keyMat->bigA, keyMat->sizeA },
+ };
+ 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->derOID, keyMat->sizeOID },
+ { CKA_VALUE, keyMat->bigK, keyMat->sizeK }
+ };
+
+ 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_eddsa(keyMat);
+ return 1;
+ }
+
+ rv = p11->C_CreateObject(hSession, pubTemplate, 10, &hKey2);
+ crypto_free_eddsa(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
+
+#define X25519_KEYLEN 32
+#define X448_KEYLEN 57
+
+#define PUBPREFIXLEN 12
+#define PRIVPREFIXLEN 16
+
+eddsa_key_material_t* crypto_malloc_eddsa(EVP_PKEY* pkey)
+{
+ int result;
+ int len;
+ unsigned char *buf;
+
+ if (pkey == NULL)
+ {
+ return NULL;
+ }
+
+ eddsa_key_material_t* keyMat = (eddsa_key_material_t*)malloc(sizeof(eddsa_key_material_t));
+ if (keyMat == NULL)
+ {
+ return NULL;
+ }
+
+ int nid = EVP_PKEY_id(pkey);
+ memset(keyMat, 0, sizeof(*keyMat));
+ keyMat->sizeOID = i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL);
+ keyMat->derOID = (CK_VOID_PTR)malloc(keyMat->sizeOID);
+
+ switch (nid) {
+ case NID_X25519:
+ case NID_ED25519:
+ keyMat->sizeK = X25519_KEYLEN;
+ keyMat->sizeA = X25519_KEYLEN;
+ break;
+ case NID_X448:
+ case NID_ED448:
+ keyMat->sizeK = X448_KEYLEN;
+ keyMat->sizeA = X448_KEYLEN;
+ break;
+ default:
+ crypto_free_eddsa(keyMat);
+ return NULL;
+ }
+ keyMat->bigK = (CK_VOID_PTR)malloc(keyMat->sizeK);
+ keyMat->bigA = (CK_VOID_PTR)malloc(keyMat->sizeA);
+ if (!keyMat->derOID || !keyMat->bigK || !keyMat->bigA)
+ {
+ crypto_free_eddsa(keyMat);
+ return NULL;
+ }
+
+ unsigned char *p = (unsigned char*) keyMat->derOID;
+ result = i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p);
+ if (result <= 0)
+ {
+ crypto_free_eddsa(keyMat);
+ return NULL;
+ }
+
+ len = i2d_PUBKEY(pkey, NULL);
+ if (((CK_ULONG) len != PUBPREFIXLEN + keyMat->sizeA) ||
+ ((buf = (unsigned char*) malloc(len)) == NULL))
+ {
+ crypto_free_eddsa(keyMat);
+ return NULL;
+ }
+ p = buf;
+ i2d_PUBKEY(pkey, &p);
+ memcpy(keyMat->bigA, buf + PUBPREFIXLEN, keyMat->sizeA);
+ free(buf);
+
+ len = i2d_PrivateKey(pkey, NULL);
+ if (((CK_ULONG) len != PRIVPREFIXLEN + keyMat->sizeK) ||
+ ((buf = (unsigned char*) malloc(len)) == NULL))
+ {
+ crypto_free_eddsa(keyMat);
+ return NULL;
+ }
+ p = buf;
+ i2d_PrivateKey(pkey, &p);
+ memcpy(keyMat->bigK, buf + PRIVPREFIXLEN, keyMat->sizeK);
+ free(buf);
+
+ return keyMat;
+}
+
+// Free the memory of the key
+void crypto_free_eddsa(eddsa_key_material_t* keyMat)
+{
+ if (keyMat == NULL) return;
+ if (keyMat->derOID) free(keyMat->derOID);
+ if (keyMat->bigK) free(keyMat->bigK);
+ if (keyMat->bigA) free(keyMat->bigA);
+ free(keyMat);
+}
+
+#endif
diff --git a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
index 7a2a31a..8fac612 100644
--- a/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
+++ b/SoftHSMv2/src/bin/util/softhsm2-util-ossl.h
@@ -38,6 +38,9 @@
#ifdef WITH_ECC
#include <openssl/ec.h>
#endif
+#ifdef WITH_EDDSA
+#include <openssl/evp.h>
+#endif
typedef struct rsa_key_material_t {
CK_ULONG sizeE;
@@ -120,6 +123,25 @@ typedef struct ecdsa_key_material_t {
} ecdsa_key_material_t;
#endif
+#ifdef WITH_EDDSA
+typedef struct eddsa_key_material_t {
+ CK_ULONG sizeOID;
+ CK_ULONG sizeK;
+ CK_ULONG sizeA;
+ CK_VOID_PTR derOID;
+ CK_VOID_PTR bigK;
+ CK_VOID_PTR bigA;
+ eddsa_key_material_t() {
+ sizeOID = 0;
+ sizeK = 0;
+ sizeA = 0;
+ derOID = NULL_PTR;
+ bigK = NULL_PTR;
+ bigA = NULL_PTR;
+ }
+} eddsa_key_material_t;
+#endif
+
EVP_PKEY* crypto_read_file(char* filePath, char* filePIN);
// RSA
@@ -139,4 +161,11 @@ ecdsa_key_material_t* crypto_malloc_ecdsa(EC_KEY* ecdsa);
void crypto_free_ecdsa(ecdsa_key_material_t* keyMat);
#endif
+#ifdef WITH_EDDSA
+// EDDSA
+int crypto_save_eddsa(CK_SESSION_HANDLE hSession, char* label, char* objID, size_t objIDLen, int noPublicKey, EVP_PKEY* eddsa);
+eddsa_key_material_t* crypto_malloc_eddsa(EVP_PKEY* eddsa);
+void crypto_free_eddsa(eddsa_key_material_t* keyMat);
+#endif
+
#endif // !_SOFTHSM_V2_SOFTHSM2_UTIL_OSSL_H