Modify decider logic
[platform/core/security/key-manager.git] / src / manager / crypto / platform / decider.cpp
1 /*
2  *  Copyright (c) 2015-2021 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
30 #ifdef TZ_BACKEND_ENABLED
31 #include <tz-backend/tz-context.h>
32 #endif // TZ_BACKEND_ENABLED
33
34 namespace CKM {
35 namespace Crypto {
36
37 Decider::Decider()
38         : m_swStore(CryptoBackend::OpenSSL)
39 #ifdef TZ_BACKEND_ENABLED
40         , m_tzStore(CryptoBackend::TrustZone)
41 #endif
42 {
43 }
44
45 GStore* Decider::getStore(const CryptoBackend &backendId)
46 {
47         GStore *gStore = nullptr;
48
49         if (backendId == CryptoBackend::OpenSSL)
50                 gStore = &m_swStore;
51 #ifdef TZ_BACKEND_ENABLED
52         if (backendId == CryptoBackend::TrustZone)
53                 gStore = &m_tzStore;
54 #endif
55         return gStore;
56 }
57
58 GStore &Decider::getStore(const Token &token)
59 {
60         auto store = getStore(token.backendId);
61         if (store != nullptr)
62                 return *store;
63
64         ThrowErr(Exc::Crypto::InternalError,
65                  "Backend not available. BackendId: ",
66                  static_cast<int>(token.backendId));
67 }
68
69 GStore* Decider::tryBackend(CryptoBackend backend)
70 {
71         switch(backend) {
72         case CryptoBackend::OpenSSL:
73                 return &m_swStore;
74         case CryptoBackend::TrustZone:
75 #ifdef TZ_BACKEND_ENABLED
76                 try {
77                         LogDebug("Trying to open TA session...");
78                         TZ::Internals::TrustZoneContext::Instance();
79                         LogDebug("...succeeded. Selecting TZ backend.");
80                         return &m_tzStore;
81                 } catch (const Exc::Crypto::InternalError& e) {
82                         LogDebug("...failed.");
83                 }
84 #endif
85         default:
86                 break;
87         }
88         return nullptr;
89 }
90
91 /*
92  * operation encrypted type   extractable backend
93  * ----------------------------------------------
94  * import    FALSE     binary *           TZ/SW
95  *                     skey   FALSE       TZ/SW
96  *                     skey   TRUE        SW
97  *                     akey   FALSE       TZ/SW
98  *                     akey   TRUE        SW
99  *                     cert   *           SW
100  * ----------------------------------------------
101  * import    TRUE      binary *           TZ
102  *                     skey   FALSE       TZ
103  *                     skey   TRUE        NONE
104  *                     akey   FALSE       TZ
105  *                     akey   TRUE        NONE
106  *                     cert   *           NONE
107  * ----------------------------------------------
108  * generate  N/A       binary *           TZ/SW
109  *                     skey   FALSE       TZ/SW
110  *                     skey   TRUE        SW
111  *                     akey   FALSE       TZ/SW
112  *                     akey   TRUE        SW
113  *                     cert   *           NONE
114  */
115 std::deque<CryptoBackend> Decider::getCompatibleBackends(DataType data,
116                                                          const Policy &policy,
117                                                          bool import,
118                                                          bool encrypted)
119 {
120         std::deque<CryptoBackend> backends;
121
122         auto addSW = [&]{
123                 if (policy.backend != CKM::PolicyBackend::FORCE_HARDWARE)
124                         backends.push_back(CryptoBackend::OpenSSL);
125         };
126
127         auto addTZ = [&]{
128 #ifdef TZ_BACKEND_ENABLED
129                 if (policy.backend != CKM::PolicyBackend::FORCE_SOFTWARE)
130                         backends.push_front(CryptoBackend::TrustZone);
131 #endif
132         };
133
134         if (import) {
135                 if (!encrypted)
136                         addSW();
137
138                 if (data.isBinaryData() || (data.isKey() && !policy.extractable))
139                         addTZ();
140         } else { // generate/derive
141                 assert(!encrypted);
142
143                 if (!data.isCertificate() && !data.isChainCert()) {
144                         addSW();
145
146                         if (data.isBinaryData() || !policy.extractable)
147                                 addTZ();
148                 }
149         }
150         return backends;
151 }
152
153 GStore &Decider::getStore(DataType data, const Policy &policy, bool import, bool encrypted)
154 {
155         auto backends = getCompatibleBackends(data, policy, import, encrypted);
156         if (backends.empty())
157                 ThrowErr(Exc::Crypto::InputParam, "No backend supports this operation.");
158
159         for (auto id : backends) {
160                 auto backend = tryBackend(id);
161                 if (backend != nullptr)
162                         return *backend;
163         }
164         ThrowErr(Exc::Crypto::InternalError, "Failed to connect to a compatible backend.");
165 }
166
167 bool Decider::checkStore(CryptoBackend requestedBackend,
168                          DataType data,
169                          const Policy &policy,
170                          bool import,
171                          bool encrypted)
172 {
173         auto backends = getCompatibleBackends(data, policy, import, encrypted);
174         for (auto id : backends) {
175                 if (id == requestedBackend)
176                         return true;
177         }
178         return false;
179 }
180
181 } // namespace Crypto
182 } // namespace CKM
183