aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp')
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp281
1 files changed, 281 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp
new file mode 100644
index 0000000..7c91b54
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDPrivateKey.cpp
+
+ OpenSSL EDDSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "OSSLEDPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/x509.h>
+
+#define X25519_KEYLEN 32
+#define X448_KEYLEN 57
+
+#define PREFIXLEN 16
+
+// Prefixes
+const unsigned char x25519_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04, 0x20
+};
+
+const unsigned char x448_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x6f, 0x04, 0x22, 0x04, 0x20
+};
+
+const unsigned char ed25519_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20
+};
+
+const unsigned char ed448_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x71, 0x04, 0x22, 0x04, 0x20
+};
+
+// Constructors
+OSSLEDPrivateKey::OSSLEDPrivateKey()
+{
+ nid = NID_undef;
+ pkey = NULL;
+}
+
+OSSLEDPrivateKey::OSSLEDPrivateKey(const EVP_PKEY* inPKEY)
+{
+ nid = NID_undef;
+ pkey = NULL;
+
+ setFromOSSL(inPKEY);
+}
+
+// Destructor
+OSSLEDPrivateKey::~OSSLEDPrivateKey()
+{
+ EVP_PKEY_free(pkey);
+}
+
+// The type
+/*static*/ const char* OSSLEDPrivateKey::type = "OpenSSL EDDSA Private Key";
+
+// Get the base point order length
+unsigned long OSSLEDPrivateKey::getOrderLength() const
+{
+ if (nid == NID_ED25519)
+ return X25519_KEYLEN;
+ if (nid == NID_ED448)
+ return X448_KEYLEN;
+ return 0;
+}
+
+// Set from OpenSSL representation
+void OSSLEDPrivateKey::setFromOSSL(const EVP_PKEY* inPKEY)
+{
+ nid = EVP_PKEY_id(inPKEY);
+ if (nid == NID_undef)
+ {
+ return;
+ }
+ ByteString inEC = OSSL::oid2ByteString(nid);
+ EDPrivateKey::setEC(inEC);
+
+ // i2d_PrivateKey incorrectly does not const the key argument?!
+ EVP_PKEY* key = const_cast<EVP_PKEY*>(inPKEY);
+ int len = i2d_PrivateKey(key, NULL);
+ if (len <= 0)
+ {
+ ERROR_MSG("Could not encode EDDSA private key");
+ return;
+ }
+ ByteString der;
+ der.resize(len);
+ unsigned char *p = &der[0];
+ i2d_PrivateKey(key, &p);
+ ByteString inK;
+ switch (nid) {
+ case NID_X25519:
+ case NID_ED25519:
+ if (len != (X25519_KEYLEN + PREFIXLEN))
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN + PREFIXLEN, len);
+ return;
+ }
+ inK.resize(X25519_KEYLEN);
+ memcpy(&inK[0], &der[PREFIXLEN], X25519_KEYLEN);
+ break;
+ case NID_X448:
+ case NID_ED448:
+ if (len != (X448_KEYLEN + PREFIXLEN))
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN + PREFIXLEN, len);
+ return;
+ }
+ inK.resize(X448_KEYLEN);
+ memcpy(&inK[0], &der[PREFIXLEN], X448_KEYLEN);
+ break;
+ default:
+ return;
+ }
+ setK(inK);
+}
+
+// Check if the key is of the given type
+bool OSSLEDPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EDDSA private key components
+void OSSLEDPrivateKey::setK(const ByteString& inK)
+{
+ EDPrivateKey::setK(inK);
+
+ if (pkey)
+ {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+}
+
+
+// Setters for the EDDSA public key components
+void OSSLEDPrivateKey::setEC(const ByteString& inEC)
+{
+ EDPrivateKey::setEC(inEC);
+
+ nid = OSSL::byteString2oid(inEC);
+ if (pkey)
+ {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLEDPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ EVP_PKEY* key = getOSSLKey();
+ if (key == NULL) return der;
+ PKCS8_PRIV_KEY_INFO* p8 = EVP_PKEY2PKCS8(key);
+ if (p8 == NULL) return der;
+ int len = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL);
+ if (len <= 0)
+ {
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return der;
+ }
+ der.resize(len);
+ unsigned char* p = &der[0];
+ i2d_PKCS8_PRIV_KEY_INFO(p8, &p);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLEDPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ int len = ber.size();
+ if (len <= 0) return false;
+ const unsigned char* p = ber.const_byte_str();
+ PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
+ if (p8 == NULL) return false;
+ EVP_PKEY* key = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (key == NULL) return false;
+ setFromOSSL(key);
+ EVP_PKEY_free(key);
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+EVP_PKEY* OSSLEDPrivateKey::getOSSLKey()
+{
+ if (pkey == NULL) createOSSLKey();
+
+ return pkey;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLEDPrivateKey::createOSSLKey()
+{
+ if (pkey != NULL) return;
+
+ ByteString der;
+ switch (nid) {
+ case NID_X25519:
+ if (k.size() != X25519_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X25519_KEYLEN);
+ memcpy(&der[0], x25519_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X25519_KEYLEN);
+ break;
+ case NID_ED25519:
+ if (k.size() != X25519_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X25519_KEYLEN);
+ memcpy(&der[0], ed25519_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X25519_KEYLEN);
+ break;
+ case NID_X448:
+ if (k.size() != X448_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X448_KEYLEN);
+ memcpy(&der[0], x448_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X448_KEYLEN);
+ break;
+ case NID_ED448:
+ if (k.size() != X448_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X448_KEYLEN);
+ memcpy(&der[0], ed448_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X448_KEYLEN);
+ break;
+ default:
+ return;
+ }
+ const unsigned char *p = &der[0];
+ pkey = d2i_PrivateKey(nid, NULL, &p, (long)der.size());
+}
+#endif