1 /*
2 **
3 ** Copyright 2020, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 #include "OmapiTransport.h"
18
19 #include <arpa/inet.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/socket.h>
23 #include <unistd.h>
24 #include <vector>
25
26 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
27 #include <android-base/logging.h>
28
29 namespace keymint::javacard {
30 using ::aidl::android::hardware::security::keymint::ErrorCode;
31
32 constexpr uint8_t KEYMINT_APPLET_AID[] = {0xA0, 0x00, 0x00, 0x00, 0x62, 0x03,
33 0x02, 0x0C, 0x01, 0x01, 0x01};
34 std::string const ESE_READER_PREFIX = "eSE";
35 constexpr const char omapiServiceName[] = "android.se.omapi.ISecureElementService/default";
36
37 class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {};
38
initialize()39 keymaster_error_t OmapiTransport::initialize() {
40
41 LOG(DEBUG) << "Initialize the secure element connection";
42
43 // Get OMAPI vendor stable service handler
44 ::ndk::SpAIBinder ks2Binder(AServiceManager_checkService(omapiServiceName));
45 omapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder);
46
47 if (omapiSeService == nullptr) {
48 LOG(ERROR) << "Failed to start omapiSeService null";
49 return static_cast<keymaster_error_t>(ErrorCode::HARDWARE_NOT_YET_AVAILABLE);
50 }
51
52 int size = sizeof(KEYMINT_APPLET_AID) / sizeof(KEYMINT_APPLET_AID[0]);
53 // reset readers, clear readers if already existing
54 if (mVSReaders.size() > 0) {
55 closeConnection();
56 }
57
58 std::vector<std::string> readers = {};
59 // Get available readers
60 auto status = omapiSeService->getReaders(&readers);
61 if (!status.isOk()) {
62 LOG(ERROR) << "getReaders failed to get available readers: " << status.getMessage();
63 return static_cast<keymaster_error_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
64 }
65
66 // Get SE readers handlers
67 for (auto readerName : readers) {
68 std::shared_ptr<::aidl::android::se::omapi::ISecureElementReader> reader;
69 status = omapiSeService->getReader(readerName, &reader);
70 if (!status.isOk()) {
71 LOG(ERROR) << "getReader for " << readerName.c_str()
72 << " Failed: " << status.getMessage();
73 return static_cast<keymaster_error_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
74 }
75 mVSReaders[readerName] = reader;
76 }
77
78 // Find eSE reader, as of now assumption is only eSE available on device
79 LOG(DEBUG) << "Finding eSE reader";
80 eSEReader = nullptr;
81 if (mVSReaders.size() > 0) {
82 for (const auto& [name, reader] : mVSReaders) {
83 if (name.find(ESE_READER_PREFIX, 0) != std::string::npos) {
84 LOG(DEBUG) << "eSE reader found: " << name;
85 eSEReader = reader;
86 break;
87 }
88 }
89 }
90
91 if (eSEReader == nullptr) {
92 LOG(ERROR) << "secure element reader " << ESE_READER_PREFIX << " not found";
93 return static_cast<keymaster_error_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
94 }
95
96 bool isSecureElementPresent = false;
97 auto res = eSEReader->isSecureElementPresent(&isSecureElementPresent);
98 if (!res.isOk()) {
99 eSEReader = nullptr;
100 LOG(ERROR) << "isSecureElementPresent error: " << res.getMessage();
101 return static_cast<keymaster_error_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
102 }
103 if (!isSecureElementPresent) {
104 LOG(ERROR) << "secure element not found";
105 eSEReader = nullptr;
106 return static_cast<keymaster_error_t>(ErrorCode::HARDWARE_TYPE_UNAVAILABLE);
107 }
108
109 status = eSEReader->openSession(&session);
110 if (!status.isOk()) {
111 LOG(ERROR) << "openSession error: " << status.getMessage();
112 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
113 }
114 if (session == nullptr) {
115 LOG(ERROR) << "Could not open session null";
116 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
117 }
118
119 std::vector<uint8_t> aid(KEYMINT_APPLET_AID, KEYMINT_APPLET_AID + size);
120 auto mSEListener = ndk::SharedRefBase::make<SEListener>();
121 status = session->openLogicalChannel(aid, 0x00, mSEListener, &channel);
122 if (!status.isOk()) {
123 LOG(ERROR) << "openLogicalChannel error: " << status.getMessage();
124 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
125 }
126 if (channel == nullptr) {
127 LOG(ERROR) << "Could not open channel null";
128 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
129 }
130
131 return KM_ERROR_OK;
132 }
133
internalTransmitApdu(std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,std::vector<uint8_t> apdu,std::vector<uint8_t> & transmitResponse)134 bool OmapiTransport::internalTransmitApdu(
135 std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
136 std::vector<uint8_t> apdu, std::vector<uint8_t>& transmitResponse) {
137
138 LOG(DEBUG) << "internalTransmitApdu: trasmitting data to secure element";
139 if (reader == nullptr) {
140 LOG(ERROR) << "eSE reader is null";
141 return false;
142 }
143
144 bool result = true;
145 auto res = ndk::ScopedAStatus::ok();
146 if (session != nullptr) {
147 res = session->isClosed(&result);
148 if (!res.isOk()) {
149 LOG(ERROR) << "isClosed error: " << res.getMessage();
150 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
151 }
152 }
153 if (result) {
154 res = reader->openSession(&session);
155 if (!res.isOk()) {
156 LOG(ERROR) << "openSession error: " << res.getMessage();
157 return false;
158 }
159 if (session == nullptr) {
160 LOG(ERROR) << "Could not open session null";
161 return false;
162 }
163 }
164
165 result = true;
166 if (channel != nullptr) {
167 res = channel->isClosed(&result);
168 if (!res.isOk()) {
169 LOG(ERROR) << "isClosed error: " << res.getMessage();
170 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
171 }
172 }
173
174 int size = sizeof(KEYMINT_APPLET_AID) / sizeof(KEYMINT_APPLET_AID[0]);
175 std::vector<uint8_t> aid(KEYMINT_APPLET_AID, KEYMINT_APPLET_AID + size);
176 if (result) {
177 auto mSEListener = ndk::SharedRefBase::make<SEListener>();
178 res = session->openLogicalChannel(aid, 0x00, mSEListener, &channel);
179 if (!res.isOk()) {
180 LOG(ERROR) << "openLogicalChannel error: " << res.getMessage();
181 return false;
182 }
183 if (channel == nullptr) {
184 LOG(ERROR) << "Could not open channel null";
185 return false;
186 }
187 }
188
189 std::vector<uint8_t> selectResponse = {};
190 res = channel->getSelectResponse(&selectResponse);
191 if (!res.isOk()) {
192 LOG(ERROR) << "getSelectResponse error: " << res.getMessage();
193 return false;
194 }
195
196 if ((selectResponse.size() < 2) ||
197 ((selectResponse[selectResponse.size() - 1] & 0xFF) != 0x00) ||
198 ((selectResponse[selectResponse.size() - 2] & 0xFF) != 0x90)) {
199 LOG(ERROR) << "Failed to select the Applet.";
200 return false;
201 }
202
203 res = channel->transmit(apdu, &transmitResponse);
204
205 LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
206 << " Message: " << res.getMessage();
207 if (!res.isOk()) {
208 LOG(ERROR) << "transmit error: " << res.getMessage();
209 return false;
210 }
211
212 return true;
213 }
214
openConnection()215 keymaster_error_t OmapiTransport::openConnection() {
216
217 // if already conection setup done, no need to initialise it again.
218 if (isConnected()) {
219 return KM_ERROR_OK;
220 }
221 return initialize();
222 }
223
sendData(const vector<uint8_t> & inData,vector<uint8_t> & output)224 keymaster_error_t OmapiTransport::sendData(const vector<uint8_t>& inData, vector<uint8_t>& output) {
225
226 if (!isConnected()) {
227 // Try to initialize connection to eSE
228 LOG(INFO) << "Failed to send data, try to initialize connection SE connection";
229 auto res = initialize();
230 if (res != KM_ERROR_OK) {
231 LOG(ERROR) << "Failed to send data, initialization not completed";
232 closeConnection();
233 return res;
234 }
235 }
236
237 if (eSEReader != nullptr) {
238 LOG(DEBUG) << "Sending apdu data to secure element: " << ESE_READER_PREFIX;
239 if (internalTransmitApdu(eSEReader, inData, output)) {
240 return KM_ERROR_OK;
241 } else {
242 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
243 }
244 } else {
245 LOG(ERROR) << "secure element reader " << ESE_READER_PREFIX << " not found";
246 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
247 }
248 }
249
closeConnection()250 keymaster_error_t OmapiTransport::closeConnection() {
251 LOG(DEBUG) << "Closing all connections";
252 if (omapiSeService != nullptr) {
253 if (mVSReaders.size() > 0) {
254 for (const auto& [name, reader] : mVSReaders) {
255 reader->closeSessions();
256 }
257 mVSReaders.clear();
258 }
259 }
260 if (channel != nullptr) channel->close();
261 if (session != nullptr) session->close();
262 return KM_ERROR_OK;
263 }
264
isConnected()265 bool OmapiTransport::isConnected() {
266 // Check already initialization completed or not
267 if (omapiSeService != nullptr && eSEReader != nullptr) {
268 LOG(DEBUG) << "Connection initialization already completed";
269 return true;
270 }
271
272 LOG(DEBUG) << "Connection initialization not completed";
273 return false;
274 }
275
276 } // namespace keymint::javacard
277