aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/crypto/BotanAES.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/crypto/BotanAES.cpp')
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanAES.cpp354
1 files changed, 354 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/crypto/BotanAES.cpp b/SoftHSMv2/src/lib/crypto/BotanAES.cpp
new file mode 100644
index 0000000..0c67a09
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanAES.cpp
@@ -0,0 +1,354 @@
+/*
+ * 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.
+ */
+
+/*****************************************************************************
+ BotanAES.cpp
+
+ Botan AES implementation
+ *****************************************************************************/
+
+#include "config.h"
+#include "BotanAES.h"
+#include <algorithm>
+#include <botan/rfc3394.h>
+#include <botan/version.h>
+
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+#include <botan/libstate.h>
+#endif
+
+// Wrap/Unwrap keys
+bool BotanAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
+{
+ // Check key bit length; AES only supports 128, 192 or 256 bit keys
+ if ((key->getBitLen() != 128) &&
+ (key->getBitLen() != 192) &&
+ (key->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());
+
+ return false;
+ }
+
+ // Determine the wrapping mode
+ if (mode == SymWrap::AES_KEYWRAP)
+ {
+ // RFC 3394 AES key wrap
+ if (in.size() < 16)
+ {
+ ERROR_MSG("key data to wrap too small");
+
+ return false;
+ }
+ if ((in.size() % 8) != 0)
+ {
+ ERROR_MSG("key data to wrap not aligned");
+
+ return false;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> data(in.size());
+ memcpy(data.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> wrapped;
+#else
+ Botan::MemoryVector<Botan::byte> data(in.size());
+ memcpy(data.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> wrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ wrapped = Botan::rfc3394_keywrap(data, botanKey, af);
+ }
+#else
+ try
+ {
+ wrapped = Botan::rfc3394_keywrap(data, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key wrap failed");
+
+ return false;
+ }
+ out.resize(wrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], wrapped.data(), out.size());
+#else
+ memcpy(&out[0], wrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ else if (mode == SymWrap::AES_KEYWRAP_PAD)
+ {
+ // RFC 5649 AES key wrap with pad
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> data(in.size());
+ memcpy(data.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> wrapped;
+#else
+ Botan::MemoryVector<Botan::byte> data(in.size());
+ memcpy(data.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> wrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ wrapped = Botan::rfc5649_keywrap(data, botanKey, af);
+ }
+#else
+ try
+ {
+ wrapped = Botan::rfc5649_keywrap(data, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key wrap failed");
+
+ return false;
+ }
+ out.resize(wrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], wrapped.data(), out.size());
+#else
+ memcpy(&out[0], wrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#endif
+ else
+ {
+ ERROR_MSG("unknown AES key wrap mode %i", mode);
+
+ return false;
+ }
+}
+
+bool BotanAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out)
+{
+ // Check key bit length; AES only supports 128, 192 or 256 bit keys
+ if ((key->getBitLen() != 128) &&
+ (key->getBitLen() != 192) &&
+ (key->getBitLen() != 256))
+ {
+ ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen());
+
+ return false;
+ }
+
+ // Determine the unwrapping mode
+ if (mode == SymWrap::AES_KEYWRAP)
+ {
+ // RFC 3394 AES key wrap
+ if (in.size() < 24)
+ {
+ ERROR_MSG("key data to unwrap too small");
+
+ return false;
+ }
+ if ((in.size() % 8) != 0)
+ {
+ ERROR_MSG("key data to unwrap not aligned");
+
+ return false;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> unwrapped;
+#else
+ Botan::MemoryVector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> unwrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ unwrapped = Botan::rfc3394_keyunwrap(wrapped, botanKey, af);
+ }
+#else
+ try
+ {
+ unwrapped = Botan::rfc3394_keyunwrap(wrapped, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key unwrap failed");
+
+ return false;
+ }
+ out.resize(unwrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], unwrapped.data(), out.size());
+#else
+ memcpy(&out[0], unwrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#ifdef HAVE_AES_KEY_WRAP_PAD
+ else if (mode == SymWrap::AES_KEYWRAP_PAD)
+ {
+ // RFC 5649 AES key wrap with wrap
+ if (in.size() < 16)
+ {
+ ERROR_MSG("key data to unwrap too small");
+
+ return false;
+ }
+ if ((in.size() % 8) != 0)
+ {
+ ERROR_MSG("key data to unwrap not aligned");
+
+ return false;
+ }
+
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ Botan::secure_vector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.data(), in.const_byte_str(), in.size());
+ Botan::secure_vector<Botan::byte> unwrapped;
+#else
+ Botan::MemoryVector<Botan::byte> wrapped(in.size());
+ memcpy(wrapped.begin(), in.const_byte_str(), in.size());
+ Botan::SecureVector<Botan::byte> unwrapped;
+#endif
+ Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size());
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
+ Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory();
+ try
+ {
+ unwrapped = Botan::rfc5649_keyunwrap(wrapped, botanKey, af);
+ }
+#else
+ try
+ {
+ unwrapped = Botan::rfc5649_keyunwrap(wrapped, botanKey);
+ }
+#endif
+ catch (...)
+ {
+ ERROR_MSG("AES key unwrap failed");
+
+ return false;
+ }
+ out.resize(unwrapped.size());
+#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0)
+ memcpy(&out[0], unwrapped.data(), out.size());
+#else
+ memcpy(&out[0], unwrapped.begin(), out.size());
+#endif
+
+ return true;
+ }
+#endif
+ else
+ {
+ ERROR_MSG("unknown AES key wrap mode %i", mode);
+
+ return false;
+ }
+}
+
+std::string BotanAES::getCipher() const
+{
+ std::string algo;
+ std::string mode;
+ std::string padding;
+
+ if (currentKey == NULL) return "";
+
+ // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys
+ switch (currentKey->getBitLen())
+ {
+ case 128:
+ algo = "AES-128";
+ break;
+ case 192:
+ algo = "AES-192";
+ break;
+ case 256:
+ algo = "AES-256";
+ break;
+ default:
+ ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen());
+
+ return "";
+ }
+
+ // Determine the cipher mode
+ switch (currentCipherMode)
+ {
+ case SymMode::CBC:
+ mode = "CBC";
+ break;
+ case SymMode::CTR:
+ return algo + "/CTR-BE";
+ case SymMode::ECB:
+ mode = "ECB";
+ break;
+#ifdef WITH_AES_GCM
+ case SymMode::GCM:
+ return algo + "/GCM(" + std::to_string(currentTagBytes) + ")";
+#endif
+ default:
+ ERROR_MSG("Invalid AES cipher mode %i", currentCipherMode);
+
+ return "";
+ }
+
+ // Check padding mode
+ if (currentPaddingMode)
+ {
+ padding = "PKCS7";
+ }
+ else
+ {
+ padding = "NoPadding";
+ }
+
+ return algo + "/" + mode + "/" + padding;
+}
+
+size_t BotanAES::getBlockSize() const
+{
+ // The block size is 128 bits
+ return 128 >> 3;
+}
+