1 /*
2 **
3 ** Copyright 2018, 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 /******************************************************************************
18 **
19 ** The original Work has been changed by NXP.
20 **
21 ** Licensed under the Apache License, Version 2.0 (the "License");
22 ** you may not use this file except in compliance with the License.
23 ** You may obtain a copy of the License at
24 **
25 ** http://www.apache.org/licenses/LICENSE-2.0
26 **
27 ** Unless required by applicable law or agreed to in writing, software
28 ** distributed under the License is distributed on an "AS IS" BASIS,
29 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30 ** See the License for the specific language governing permissions and
31 ** limitations under the License.
32 **
33 ** Copyright 2020-2021 NXP
34 **
35 *********************************************************************************/
36 #define LOG_TAG "OmapiTransport"
37
38 #include <android-base/logging.h>
39 #include <android-base/stringprintf.h>
40 #include <log/log.h>
41 #include <signal.h>
42 #include <iomanip>
43 #include <mutex>
44 #include <string>
45 #include <vector>
46
47 #include <AppletConnection.h>
48 #include <EseTransportUtils.h>
49 #include <SignalHandler.h>
50
51 using ::android::hardware::secure_element::V1_0::SecureElementStatus;
52 using ::android::hardware::secure_element::V1_0::LogicalChannelResponse;
53 using android::base::StringPrintf;
54
55 namespace keymint::javacard {
56
57 static bool isStrongBox = false; // true when linked with StrongBox HAL process
58 const std::vector<uint8_t> kStrongBoxAppletAID = {0xA0, 0x00, 0x00, 0x00, 0x62};
59
60 class SecureElementCallback : public ISecureElementHalCallback {
61 public:
onStateChange(bool state)62 Return<void> onStateChange(bool state) override {
63 mSEClientState = state;
64 return Void();
65 };
onStateChange_1_1(bool state,const hidl_string & reason)66 Return<void> onStateChange_1_1(bool state, const hidl_string& reason) override {
67 LOGD_OMAPI("connected =" << (state?"true " : "false " ) << "reason: " << reason);
68 mSEClientState = state;
69 return Void();
70 };
isClientConnected()71 bool isClientConnected() {
72 return mSEClientState;
73 }
74 private:
75 bool mSEClientState = false;
76 };
77
78 sp<SecureElementCallback> mCallback = nullptr;
79
80 class SEDeathRecipient : public android::hardware::hidl_death_recipient {
serviceDied(uint64_t,const android::wp<::android::hidl::base::V1_0::IBase> &)81 virtual void serviceDied(uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
82 LOG(ERROR) << "Secure Element Service died disconnecting SE HAL .....";
83 if(mCallback != nullptr) {
84 LOG(INFO) << "Changing state to disconnect ...";
85 mCallback->onStateChange(false);// Change state to disconnect
86 }
87 }
88 };
89
90 sp<SEDeathRecipient> mSEDeathRecipient = nullptr;
91
AppletConnection(const std::vector<uint8_t> & aid)92 AppletConnection::AppletConnection(const std::vector<uint8_t>& aid) : kAppletAID(aid) {
93 if (kAppletAID == kStrongBoxAppletAID) {
94 isStrongBox = true;
95 }
96 }
97
connectToSEService()98 bool AppletConnection::connectToSEService() {
99 if (!SignalHandler::getInstance()->isHandlerRegistered()) {
100 LOG(INFO) << "register signal handler";
101 SignalHandler::getInstance()->installHandler(this);
102 }
103 if (mSEClient != nullptr && mCallback->isClientConnected()) {
104 LOG(INFO) <<"Already connected";
105 return true;
106 }
107
108 uint8_t retry = 0;
109 bool status = false;
110 while (( mSEClient == nullptr ) && retry++ < MAX_GET_SERVICE_RETRY ){ // How long should we try before giving up !
111 mSEClient = ISecureElement::tryGetService("eSE1");
112
113 if(mSEClient == nullptr){
114 LOG(ERROR) << "failed to get eSE HAL service : retry after 1 sec , retry cnt = " << android::hardware::toString(retry) ;
115 }else {
116 LOG(INFO) << " !!! SuccessFully got Handle to eSE HAL service" ;
117 if (mCallback == nullptr) {
118 mCallback = new SecureElementCallback();
119 }
120 mSEDeathRecipient = new SEDeathRecipient();
121 mSEClient->init_1_1(mCallback);
122 mSEClient->linkToDeath(mSEDeathRecipient, 0/*cookie*/);
123 status = mCallback->isClientConnected();
124 break;
125 }
126 usleep(ONE_SEC);
127 }
128 return status;
129 }
130
selectApplet(std::vector<uint8_t> & resp,uint8_t p2)131 bool AppletConnection::selectApplet(std::vector<uint8_t>& resp, uint8_t p2) {
132 bool stat = false;
133 mSEClient->openLogicalChannel(
134 kAppletAID, p2, [&](LogicalChannelResponse selectResponse, SecureElementStatus status) {
135 if (status == SecureElementStatus::SUCCESS) {
136 resp = selectResponse.selectResponse;
137 mOpenChannel = selectResponse.channelNumber;
138 stat = true;
139 mSBAccessController.parseResponse(resp);
140 LOG(INFO) << "openLogicalChannel:" << toString(status) << " channelNumber ="
141 << ::android::hardware::toString(selectResponse.channelNumber) << " "
142 << selectResponse.selectResponse;
143 }
144 });
145 return stat;
146 }
prepareErrorRepsponse(std::vector<uint8_t> & resp)147 void prepareErrorRepsponse(std::vector<uint8_t>& resp){
148 resp.clear();
149 resp.push_back(0xFF);
150 resp.push_back(0xFF);
151 }
openChannelToApplet(std::vector<uint8_t> & resp)152 bool AppletConnection::openChannelToApplet(std::vector<uint8_t>& resp) {
153 bool ret = false;
154 uint8_t retry = 0;
155 if (mCallback == nullptr || !mCallback->isClientConnected()) {
156 mSEClient = nullptr;
157 mOpenChannel = -1;
158 if (!connectToSEService()) {
159 LOG(ERROR) << "Not connected to eSE Service";
160 return ret;
161 }
162 }
163 if (isChannelOpen()) {
164 LOG(INFO) << "channel Already opened";
165 return true;
166 }
167 if (isStrongBox) {
168 if (!mSBAccessController.isSelectAllowed()) {
169 prepareErrorRepsponse(resp);
170 return false;
171 }
172 do {
173 if (selectApplet(resp, SELECT_P2_VALUE_0) || selectApplet(resp, SELECT_P2_VALUE_2)) {
174 ret = true;
175 break;
176 }
177 LOG(INFO) << " openChannelToApplet retry after 2 secs";
178 usleep(2 * ONE_SEC);
179 } while (++retry < MAX_RETRY_COUNT);
180 } else {
181 ret = selectApplet(resp, 0x0);
182 }
183
184 return ret;
185 }
186
transmit(std::vector<uint8_t> & CommandApdu,std::vector<uint8_t> & output)187 bool AppletConnection::transmit(std::vector<uint8_t>& CommandApdu , std::vector<uint8_t>& output){
188 hidl_vec<uint8_t> cmd = CommandApdu;
189 cmd[0] |= mOpenChannel ;
190 LOGD_OMAPI("Channel number " << ::android::hardware::toString(mOpenChannel));
191
192 if (mSEClient == nullptr) return false;
193 if (isStrongBox) {
194 if (!mSBAccessController.isOperationAllowed(CommandApdu[APDU_INS_OFFSET])) {
195 std::vector<uint8_t> ins;
196 ins.push_back(CommandApdu[APDU_INS_OFFSET]);
197 LOG(ERROR) << "command Ins:" << ins << " not allowed";
198 prepareErrorRepsponse(output);
199 return false;
200 }
201 }
202 // block any fatal signal delivery
203 SignalHandler::getInstance()->blockSignals();
204
205 mSEClient->transmit(cmd, [&](hidl_vec<uint8_t> result) {
206 output = result;
207 LOG(INFO) << "received response size = " << ::android::hardware::toString(result.size()) << " data = " << result;
208 });
209
210 // un-block signal delivery
211 SignalHandler::getInstance()->unblockSignals();
212 return true;
213 }
214
getSessionTimeout()215 int AppletConnection::getSessionTimeout() {
216 return mSBAccessController.getSessionTimeout();
217 }
218
close()219 bool AppletConnection::close() {
220 std::lock_guard<std::mutex> lock(channel_mutex_);
221 if (mSEClient == nullptr) {
222 LOG(ERROR) << "Channel couldn't be closed mSEClient handle is null";
223 return false;
224 }
225 if(mOpenChannel < 0){
226 LOG(INFO) << "Channel is already closed";
227 return true;
228 }
229 SecureElementStatus status = mSEClient->closeChannel(mOpenChannel);
230 if (status != SecureElementStatus::SUCCESS) {
231 /*
232 * reason could be SE reset or HAL deinit triggered from other client
233 * which anyway closes all the opened channels
234 */
235 LOG(ERROR) << "closeChannel failed";
236 mOpenChannel = -1;
237 return true;
238 }
239 LOG(INFO) << "Channel closed";
240 mOpenChannel = -1;
241 return true;
242 }
243
isChannelOpen()244 bool AppletConnection::isChannelOpen() {
245 std::lock_guard<std::mutex> lock(channel_mutex_);
246 if(mCallback == nullptr || !mCallback->isClientConnected()) {
247 return false;
248 }
249 return mOpenChannel >= 0;
250 }
251
252 } // namespace keymint::javacard
253