/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/*
* @file decider.cpp
* @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
* @version 1.0
*/
#include <dpl/log/log.h>
#include <platform/decider.h>
#include <generic-backend/exception.h>
-#include <sw-backend/store.h>
-#include <tz-backend/store.h>
+
+#ifdef TZ_BACKEND_ENABLED
+#include <tz-backend/tz-context.h>
+
+#include <tee_client_api.h>
+#include <km_ta_defines.h>
+#endif // TZ_BACKEND_ENABLED
+
+#include <sstream>
+#include <fstream>
+#include <iomanip>
namespace CKM {
namespace Crypto {
namespace {
-CryptoBackend chooseCryptoBackend(DataType dataType, bool exportable,
- bool encrypted)
+
+template <typename T>
+std::string ValueToString(const T& value)
{
- // Only software backend supports device encyption key
- if (encrypted)
- return CryptoBackend::OpenSSL;
+ std::stringstream str;
+ // we need to re-cast because otherwise stringstream
+ // will write our value incorrectly
+ str << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex
+ << static_cast<uint64_t>(value);
+ return str.str();
+}
- // The list of items that MUST be support by OpenSSL
- if (dataType.isCertificate())
- return CryptoBackend::OpenSSL;
+CryptoBackend chooseCryptoBackend(const DataParams& params)
+{
+#ifdef TZ_BACKEND_ENABLED
+ if (params.size() != 1 && params.size() != 2) {
+ ThrowErr(Exc::Crypto::InternalError, "Invalid number of key parameters provided to decider");
+ }
- if (dataType.isBinaryData())
+ // user directly point proper backend - we will not discuss with it
+ if (params[0].policy.backend == CKM::PolicyBackend::FORCE_SOFTWARE)
return CryptoBackend::OpenSSL;
- if (exportable)
+ // user directly point proper backend - we will not discuss with it
+ if (params[0].policy.backend == CKM::PolicyBackend::FORCE_HARDWARE)
+ return CryptoBackend::TrustZone;
+
+ if (params.size() == 1) {
+ // For now only software backend supports device encyption key
+ // TODO tz-backend could support the master key, but it would require
+ // hardcoding a known key ID and querying TA whether the key is
+ // reachable
+ if (params[0].encrypted) {
+ return CryptoBackend::OpenSSL;
+ }
+
+ // tz-backend allows only for data binary export
+ if (params[0].policy.extractable && !params[0].data.isBinaryData()) {
+ return CryptoBackend::OpenSSL;
+ }
+
+ // Use TrustZone only with symmetric keys or unencrypted binary
+ // data until asymmetric cryptography is implemented
+ if (!params[0].data.isSKey() && !params[0].data.isBinaryData()) {
+ return CryptoBackend::OpenSSL;
+ }
+ } else if (params.size() == 2) {
+ // extractable private key can only be handled by OpenSSL
+ if (params[0].policy.extractable) {
+ return CryptoBackend::OpenSSL;
+ }
+
+ // ECDSA algorithm is unsupported by GP API 1.0
+ if (params[0].data.isEllipticCurve() || params[1].data.isEllipticCurve()) {
+ return CryptoBackend::OpenSSL;
+ }
+ }
+
+ try {
+ LogDebug("Trying to open TA session...");
+ TZ::Internals::TrustZoneContext::Instance();
+ } catch (const Exc::Crypto::InternalError& e) {
+ LogDebug("...failed. Selecting SW backend.");
return CryptoBackend::OpenSSL;
+ }
- // This is the place where we can use trust zone backend
- // Examples:
- //
- // if (dataType.isKeyPrivate())
- // return CryptoBackend::TrustZone;
+ LogDebug("...succeeded. Selecting TZ backend.");
+ return CryptoBackend::TrustZone;
- // This item does not met Trust Zone requirements. Let's use software backend
- return CryptoBackend::OpenSSL;
+#else // TZ_BACKEND_ENABLED
+ (void) params;
+ return CryptoBackend::OpenSSL;
+#endif // TZ_BACKEND_ENABLED
}
+
} // namespace
Decider::Decider()
- : m_swStore(new SW::Store(CryptoBackend::OpenSSL))
- , m_tzStore(new TZ::Store(CryptoBackend::TrustZone))
+ : m_swStore(CryptoBackend::OpenSSL)
+#ifdef TZ_BACKEND_ENABLED
+ , m_tzStore(CryptoBackend::TrustZone)
+#endif
{
}
-GStore &Decider::getStore(const Token &token) const
+GStore &Decider::getStore(const Token &token)
{
return getStore(token.backendId);
};
-GStore &Decider::getStore(CryptoBackend cryptoBackend) const
+GStore &Decider::getStore(CryptoBackend cryptoBackend)
{
GStore *gStore = NULL;
if (cryptoBackend == CryptoBackend::OpenSSL)
- gStore = m_swStore.get();
-
+ gStore = &m_swStore;
+#ifdef TZ_BACKEND_ENABLED
if (cryptoBackend == CryptoBackend::TrustZone)
- gStore = m_tzStore.get();
-
+ gStore = &m_tzStore;
+#endif
if (gStore)
return *gStore;
"Backend not available. BackendId: ", (int)cryptoBackend);
}
-GStore &Decider::getStore(DataType data, bool exportable, bool encrypted) const
+GStore &Decider::getStore(DataType data, const Policy &policy, bool encrypted)
+{
+ DataParams params{
+ DataParam(data, policy, encrypted)
+ };
+
+ return getStore(chooseCryptoBackend(params));
+}
+
+GStore &Decider::getStore(const DataParams& params)
{
- return getStore(chooseCryptoBackend(data, exportable, encrypted));
+ return getStore(chooseCryptoBackend(params));
}
} // namespace Crypto