• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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