Add backend field in policy
[platform/core/security/key-manager.git] / src / manager / crypto / platform / decider.cpp
1 /*
2  *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16 /*
17  * @file       decider.cpp
18  * @author     BartÅ‚omiej Grzelewski (b.grzelewski@samsung.com)
19  * @author     Lukasz Kostyra (l.kostyra@samsung.com)
20  * @version    1.0
21  */
22 #include <dpl/log/log.h>
23
24 #include <crypto-backend.h>
25
26 #include <platform/decider.h>
27
28 #include <generic-backend/exception.h>
29 #include <sw-backend/store.h>
30 #include <tz-backend/store.h>
31
32 #include <tee_client_api.h>
33 #include <km_ta_defines.h>
34
35 #include <sstream>
36 #include <fstream>
37 #include <iomanip>
38
39 namespace CKM {
40 namespace Crypto {
41
42 namespace {
43
44 const std::string TA_STORE_PATH = "/usr/lib/tastore";
45
46 template <typename T>
47 std::string ValueToString(const T& value)
48 {
49         std::stringstream str;
50         // we need to re-cast because otherwise stringstream
51         // will write our value incorrectly
52         str << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex
53                 << static_cast<uint64_t>(value);
54         return str.str();
55 }
56
57 std::string convertTeecUUIDToString(TEEC_UUID uuid)
58 {
59         std::string uuidStr;
60         uuidStr += ValueToString(uuid.timeLow);
61         uuidStr += ValueToString(uuid.timeMid);
62         uuidStr += ValueToString(uuid.timeHiAndVersion);
63         for (auto& c: uuid.clockSeqAndNode)
64                 uuidStr += ValueToString(c);
65
66         return uuidStr;
67 }
68
69 CryptoBackend chooseCryptoBackend(DataType data,
70                                   const Policy &policy,
71                                   bool encrypted)
72 {
73         // user directly point proper backend - we will not discuss with it
74         if (policy.backend == CKM::PolicyBackend::FORCE_SOFTWARE)
75                 return CryptoBackend::OpenSSL;
76
77         // user directly point proper backend - we will not discuss with it
78         if (policy.backend == CKM::PolicyBackend::FORCE_HARDWARE)
79                 return CryptoBackend::TrustZone;
80
81         // For now only software backend supports device encyption key
82         // TODO tz-backend could support the master key, but it would require
83         //      hardcoding a known key ID and querying TA whether the key is
84         //      reachable
85         if (encrypted)
86                 return CryptoBackend::OpenSSL;
87
88         // Only software backend allows for key export
89         if (policy.extractable)
90                 return CryptoBackend::OpenSSL;
91
92         // Use TrustZone only with symmetric keys until asymmetric
93         // cryptography is implemented
94         if (!data.isSKey())
95                 return CryptoBackend::OpenSSL;
96
97         // Check if key-manager TA exists
98         std::string taUUIDStr = convertTeecUUIDToString(KM_TA_UUID);
99
100         LogDebug("Checking for " << TA_STORE_PATH << "/" << taUUIDStr);
101         std::ifstream taFile(TA_STORE_PATH + "/" + taUUIDStr);
102         if (taFile)
103                 return CryptoBackend::TrustZone;
104
105         // no TA available - fallback to OpenSSL
106         return CryptoBackend::OpenSSL;
107 }
108
109 } // namespace
110
111 Decider::Decider()
112         : m_swStore(new SW::Store(CryptoBackend::OpenSSL))
113         , m_tzStore(new TZ::Store(CryptoBackend::TrustZone))
114 {
115 }
116
117 GStore &Decider::getStore(const Token &token) const
118 {
119         return getStore(token.backendId);
120 };
121
122 GStore &Decider::getStore(CryptoBackend cryptoBackend) const
123 {
124         GStore *gStore = NULL;
125
126         if (cryptoBackend == CryptoBackend::OpenSSL)
127                 gStore = m_swStore.get();
128
129         if (cryptoBackend == CryptoBackend::TrustZone)
130                 gStore = m_tzStore.get();
131
132         if (gStore)
133                 return *gStore;
134
135         ThrowErr(Exc::Crypto::InternalError,
136                          "Backend not available. BackendId: ", (int)cryptoBackend);
137 }
138
139 GStore &Decider::getStore(DataType data, const Policy &policy, bool encrypted) const
140 {
141         return getStore(chooseCryptoBackend(data, policy, encrypted));
142 }
143
144 } // namespace Crypto
145 } // namespace CKM
146