1 /******************************************************************************
2  *
3  *  Copyright 2020-2023 NXP
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 #define LOG_TAG "weaver-transport-impl"
20 #include <TransportFactory.h>
21 #include <cutils/properties.h>
22 #include <vector>
23 #include <weaver_transport-impl.h>
24 #include <weaver_utils.h>
25 
26 #define MAX_RETRY_COUNT 12
27 #define RETRY_DELAY_INTERVAL_SEC 1
28 #define PROP_SYSBOOT_COMPLETED "sys.boot_completed"
29 #define SYSBOOT_COMPLETED_VALUE 1
30 #define IS_APPLET_SELECTION_FAILED(resp)                                       \
31   (!resp.empty() && resp[0] == APP_NOT_FOUND_SW1 &&                            \
32    resp[1] == APP_NOT_FOUND_SW2)
33 
34 WeaverTransportImpl *WeaverTransportImpl::s_instance = NULL;
35 std::once_flag WeaverTransportImpl::s_instanceFlag;
36 
37 /* Applet ID to be use for communication */
38 std::vector<std::vector<uint8_t>> kAppletId;
39 
40 /* Interface instance of libese-transport library */
41 static std::unique_ptr<se_transport::TransportFactory> pTransportFactory =
42     nullptr;
43 
44 /**
45  * \brief static inline function to get lib-ese-transport interface instance
46  */
47 static inline std::unique_ptr<se_transport::TransportFactory> &
getTransportFactoryInstance()48 getTransportFactoryInstance() {
49   if (pTransportFactory == nullptr) {
50     pTransportFactory = std::unique_ptr<se_transport::TransportFactory>(
51         new se_transport::TransportFactory(false, kAppletId[0]));
52     pTransportFactory->openConnection();
53   }
54   return pTransportFactory;
55 }
56 
57 /**
58  * \brief static function to get the singleton instance of WeaverTransportImpl
59  * class
60  *
61  * \retval instance of WeaverTransportImpl.
62  */
getInstance()63 WeaverTransportImpl *WeaverTransportImpl::getInstance() {
64   /* call_once c++11 api which executes the passed function ptr exactly once,
65    * even if called concurrently, from several threads
66    */
67   std::call_once(s_instanceFlag, &WeaverTransportImpl::createInstance);
68   return s_instance;
69 }
70 
71 /* Private function to create the instance of self class
72  * Same will be used for std::call_once
73  */
createInstance()74 void WeaverTransportImpl::createInstance() {
75   LOG_D(TAG, "Entry");
76   s_instance = new WeaverTransportImpl;
77   LOG_D(TAG, "Exit");
78 }
79 
80 /**
81  * \brief Function to initialize Weaver Transport Interface
82  *
83  * \param[in]    aid -  applet id to be set to transport interface
84  *
85  * \retval This function return true in case of success
86  *         In case of failure returns false.
87  */
Init(std::vector<std::vector<uint8_t>> aid)88 bool WeaverTransportImpl::Init(std::vector<std::vector<uint8_t>> aid) {
89   LOG_D(TAG, "Entry");
90   kAppletId = std::move(aid);
91   LOG_D(TAG, "Exit");
92   return true;
93 }
94 
95 /**
96  * \brief Function to open applet connection
97  *
98  * \param[in]    data -         command for open applet
99  * \param[out]   resp -         response from applet
100  *
101  * \retval This function return true in case of success
102  *         In case of failure returns false.
103  */
OpenApplet(std::vector<uint8_t> data,std::vector<uint8_t> & resp)104 bool WeaverTransportImpl::OpenApplet(std::vector<uint8_t> data,
105                                      std::vector<uint8_t> &resp) {
106   LOG_D(TAG, "Entry");
107   bool status = true;
108   UNUSED(data);
109   UNUSED(resp);
110   // Since libese_transport opens channel as part of send only so open applet is
111   // not required
112   LOG_D(TAG, "Exit");
113   return status;
114 }
115 
116 /**
117  * \brief Function to close applet connection
118  *
119  * \retval This function return true in case of success
120  *         In case of failure returns false.
121  */
CloseApplet()122 bool WeaverTransportImpl::CloseApplet() {
123   LOG_D(TAG, "Entry");
124   // Close the Applet Channel if opened
125   bool status = getTransportFactoryInstance()->closeConnection();
126   LOG_D(TAG, "Exit");
127   return status;
128 }
129 
130 /**
131  * \brief Private wrapper function to send apdu.
132  * It will try with alternate aids if sending is failed.
133  *
134  * \param[in]    data -         command to be send to applet
135  * \param[out]   resp -         response from applet
136  *
137  * \retval This function return true in case of success
138  *         In case of failure returns false.
139  */
sendInternal(std::vector<uint8_t> data,std::vector<uint8_t> & resp)140 bool WeaverTransportImpl::sendInternal(std::vector<uint8_t> data,
141                                        std::vector<uint8_t> &resp) {
142   bool status = false;
143   status =
144       getTransportFactoryInstance()->sendData(data.data(), data.size(), resp);
145   if (!status && IS_APPLET_SELECTION_FAILED(resp)) {
146     LOG_E(TAG, ": send Failed, trying with alternateAids");
147     // If Applet selection failed, try with alternate Aids
148     for (int i = 1; i < kAppletId.size(); i++) {
149       getTransportFactoryInstance()->setAppletAid(kAppletId[i]);
150       status = getTransportFactoryInstance()->sendData(data.data(), data.size(),
151                                                        resp);
152       if (status) {
153         return status;
154       }
155     }
156     if (!status) {
157       // None of alternate Aids success, Revert back to primary AID
158       getTransportFactoryInstance()->setAppletAid(kAppletId[0]);
159     }
160   }
161   return status;
162 }
163 
164 /**
165  * \brief Function to send commands to applet
166  *
167  * \param[in]    data -         command to be send to applet
168  * \param[out]   resp -         response from applet
169  *
170  * \retval This function return true in case of success
171  *         In case of failure returns false.
172  */
Send(std::vector<uint8_t> data,std::vector<uint8_t> & resp)173 bool WeaverTransportImpl::Send(std::vector<uint8_t> data,
174                                std::vector<uint8_t> &resp) {
175   LOG_D(TAG, "Entry");
176   int retry = 1;
177   bool status = false;
178   // Opens the channel with aid and transmit the data
179   do {
180     status = sendInternal(data, resp);
181     if (!status) {
182       if (!isDeviceBootCompleted()) {
183         LOG_D(TAG, ": Device boot not completed, no retry required");
184         break;
185       }
186       if (retry > MAX_RETRY_COUNT) {
187         LOG_E(TAG, ": completed max retries exit failure");
188       } else {
189         sleep(RETRY_DELAY_INTERVAL_SEC);
190         LOG_E(TAG, ": retry  %d/%d", retry, MAX_RETRY_COUNT);
191       }
192     }
193   } while ((!status) && (retry++ <= MAX_RETRY_COUNT));
194   LOG_D(TAG, "Exit");
195   return status;
196 }
197 
198 /**
199  * \brief Function to de-initialize Weaver Transport Interface
200  *
201  * \retval This function return true in case of success
202  *         In case of failure returns false.
203  */
DeInit()204 bool WeaverTransportImpl::DeInit() {
205   LOG_D(TAG, "Entry");
206   bool status = CloseApplet();
207   LOG_D(TAG, "Exit");
208   return status;
209 }
210 
211 /**
212  * \brief Function to determine if phone boot completed
213  *
214  * \retval This function return true in case of phone boot
215  *        completed and false in case not completed.
216  */
isDeviceBootCompleted()217 bool WeaverTransportImpl::isDeviceBootCompleted() {
218   if (property_get_int64(PROP_SYSBOOT_COMPLETED, 0) ==
219       SYSBOOT_COMPLETED_VALUE) {
220     return true;
221   }
222   return false;
223 }
224