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