Properly detect the presence of TA
[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 #include <tz-backend/tz-context.h>
32
33 #include <tee_client_api.h>
34 #include <km_ta_defines.h>
35
36 #include <sstream>
37 #include <fstream>
38 #include <iomanip>
39
40 namespace CKM {
41 namespace Crypto {
42
43 namespace {
44
45 template <typename T>
46 std::string ValueToString(const T& value)
47 {
48         std::stringstream str;
49         // we need to re-cast because otherwise stringstream
50         // will write our value incorrectly
51         str << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex
52                 << static_cast<uint64_t>(value);
53         return str.str();
54 }
55
56 CryptoBackend chooseCryptoBackend(DataType data,
57                                   const Policy &policy,
58                                   bool encrypted)
59 {
60         // user directly point proper backend - we will not discuss with it
61         if (policy.backend == CKM::PolicyBackend::FORCE_SOFTWARE)
62                 return CryptoBackend::OpenSSL;
63
64         // user directly point proper backend - we will not discuss with it
65         if (policy.backend == CKM::PolicyBackend::FORCE_HARDWARE)
66                 return CryptoBackend::TrustZone;
67
68         // For now only software backend supports device encyption key
69         // TODO tz-backend could support the master key, but it would require
70         //      hardcoding a known key ID and querying TA whether the key is
71         //      reachable
72         if (encrypted)
73                 return CryptoBackend::OpenSSL;
74
75         // Only software backend allows for key export
76         if (policy.extractable)
77                 return CryptoBackend::OpenSSL;
78
79         // Use TrustZone only with symmetric keys until asymmetric
80         // cryptography is implemented
81         if (!data.isSKey())
82                 return CryptoBackend::OpenSSL;
83
84         try {
85                 LogDebug("Trying to open TA session...");
86                 TZ::Internals::TrustZoneContext::Instance();
87         } catch (const Exc::Crypto::InternalError& e) {
88                 LogDebug("...failed. Selecting SW backend.");
89                 return CryptoBackend::OpenSSL;
90         }
91
92         LogDebug("...succeeded. Selecting TZ backend.");
93         return CryptoBackend::TrustZone;
94 }
95
96 } // namespace
97
98 Decider::Decider()
99         : m_swStore(new SW::Store(CryptoBackend::OpenSSL))
100         , m_tzStore(new TZ::Store(CryptoBackend::TrustZone))
101 {
102 }
103
104 GStore &Decider::getStore(const Token &token) const
105 {
106         return getStore(token.backendId);
107 };
108
109 GStore &Decider::getStore(CryptoBackend cryptoBackend) const
110 {
111         GStore *gStore = NULL;
112
113         if (cryptoBackend == CryptoBackend::OpenSSL)
114                 gStore = m_swStore.get();
115
116         if (cryptoBackend == CryptoBackend::TrustZone)
117                 gStore = m_tzStore.get();
118
119         if (gStore)
120                 return *gStore;
121
122         ThrowErr(Exc::Crypto::InternalError,
123                          "Backend not available. BackendId: ", (int)cryptoBackend);
124 }
125
126 GStore &Decider::getStore(DataType data, const Policy &policy, bool encrypted) const
127 {
128         return getStore(chooseCryptoBackend(data, policy, encrypted));
129 }
130
131 } // namespace Crypto
132 } // namespace CKM
133