Turn backends into Decider members
[platform/core/security/key-manager.git] / src / manager / crypto / platform / decider.cpp
index 995a6e7..9540509 100644 (file)
+/*
+ *  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.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under 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 <crypto-backend.h>
+
 #include <platform/decider.h>
 
-#include <sw-backend/store.h>
+#include <generic-backend/exception.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 {
+
+template <typename T>
+std::string ValueToString(const T& value)
+{
+       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();
+}
+
+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");
+       }
+
+       // user directly point proper backend - we will not discuss with it
+       if (params[0].policy.backend == CKM::PolicyBackend::FORCE_SOFTWARE)
+               return CryptoBackend::OpenSSL;
+
+       // 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;
+       }
+
+       LogDebug("...succeeded. Selecting TZ backend.");
+       return CryptoBackend::TrustZone;
+
+#else // TZ_BACKEND_ENABLED
+    (void) params;
+    return CryptoBackend::OpenSSL;
+#endif // TZ_BACKEND_ENABLED
+}
+
+} // namespace
+
 Decider::Decider()
-  : m_store(new SW::Store)
-{}
+       : m_swStore(CryptoBackend::OpenSSL)
+#ifdef TZ_BACKEND_ENABLED
+       , m_tzStore(CryptoBackend::TrustZone)
+#endif
+{
+}
 
-GStoreShPtr Decider::getStore(const Token &) {
-    // This the place where we should choose backend bases on token information.
-    return m_store;
+GStore &Decider::getStore(const Token &token)
+{
+       return getStore(token.backendId);
 };
 
+GStore &Decider::getStore(CryptoBackend cryptoBackend)
+{
+       GStore *gStore = NULL;
+
+       if (cryptoBackend == CryptoBackend::OpenSSL)
+               gStore = &m_swStore;
+#ifdef TZ_BACKEND_ENABLED
+       if (cryptoBackend == CryptoBackend::TrustZone)
+               gStore = &m_tzStore;
+#endif
+       if (gStore)
+               return *gStore;
+
+       ThrowErr(Exc::Crypto::InternalError,
+                        "Backend not available. BackendId: ", (int)cryptoBackend);
+}
+
+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(params));
+}
+
 } // namespace Crypto
 } // namespace CKM