1 /******************************************************************************
2  *
3  *  Copyright 2020-2021 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 #include "OsuHalExtn.h"
19 #include <ese_config.h>
20 
21 #define LOG_TAG "OsuHalExtn"
22 #include <log/log.h>
23 
24 #define DEFAULT_MAX_WTX_COUNT 60
25 
26 const static hidl_vec<uint8_t> OSU_AID = {0x4F, 0x70, 0x80, 0x13, 0x04,
27                                           0xDE, 0xAD, 0xBE, 0xEF};
28 const static uint8_t defaultSelectAid[] = {0x00, 0xA4, 0x04, 0x00, 0x00};
29 
30 /*******************************************************************************
31 **
32 ** Function:    OsuHalExtn::isOsuMode
33 **
34 ** Description: Check, update and return current mode for below SE HAL API
35 **              requests openBasicChannel() and transmit()
36 **
37 ** Returns:     OsuApduMode(NON_OSU_MODE, OSU_PROP_MODE, OSU_RST_MODE,
38 **              OSU_BLOCKED_MODE, OSU_GP_MODE)
39 **
40 *******************************************************************************/
isOsuMode(const hidl_vec<uint8_t> & evt,uint8_t type,phNxpEse_data * pCmdData)41 OsuHalExtn::OsuApduMode OsuHalExtn::isOsuMode(const hidl_vec<uint8_t>& evt,
42                                               uint8_t type,
43                                               phNxpEse_data* pCmdData) {
44   OsuApduMode osuSubState = (isAppOSUMode ? OSU_PROP_MODE : NON_OSU_MODE);
45 
46   switch (type) {
47     case OPENBASIC:
48       /*
49        * update & return OSU_PROP_MODE if OpenBasicChannel AID request matches
50        * OSU_AID
51        */
52       if (!memcmp(&evt[0], &OSU_AID[0], OSU_AID.size())) {
53         isAppOSUMode = true;
54         osuSubState = OSU_PROP_MODE;
55         ALOGD("Dedicated mode is set !!!!!!!!!!!!!!!!!");
56       } else if (isOsuMode()) {
57         // OpenBasic channel requests with non OSU_AID are not allowed/blocked
58         osuSubState = OSU_BLOCKED_MODE;
59         ALOGE("Non OSU AID Not allowed");
60       }
61       break;
62     case TRANSMIT:
63       memcpy(pCmdData->p_data, evt.data(), evt.size());
64       if (isOsuMode()) {
65         /*
66          * Process transmit request(unwrap APDU, proprietary actions) in OSU
67          * mode
68          */
69         osuSubState =
70             checkTransmit(pCmdData->p_data, evt.size(), &pCmdData->len);
71       } else {
72         pCmdData->len = evt.size();
73         osuSubState = NON_OSU_MODE;
74       }
75       break;
76   }
77   return osuSubState;
78 }
79 
80 /*******************************************************************************
81 **
82 ** Function:    OsuHalExtn::isOsuMode
83 **
84 ** Description: Check, update and return current mode for below SE HAL API
85 **              requests init(), openLogicalChannel() and closeChannel()
86 **
87 ** Returns:     true(OSU)/false(normal)
88 **
89 *******************************************************************************/
isOsuMode(uint8_t type,uint8_t channel)90 bool OsuHalExtn::isOsuMode(uint8_t type, uint8_t channel) {
91   switch (type) {
92     case INIT:
93       checkAndUpdateOsuMode();
94       break;
95     case OPENLOGICAL:
96       // No action, only return current mode
97       break;
98     case CLOSE:
99       /*
100        * If in OSU mode close basic channel is called
101        * clear osu APP and update JCOP mode
102        */
103       if (channel == ISO7816_BASIC_CHANNEL && isOsuMode()) {
104         if (phNxpEse_doResetProtection(false) != ESESTATUS_SUCCESS) {
105           ALOGE("Disable Reset Protection Failed");
106         }
107         phNxpEse_setWtxCountLimit(RESET_APP_WTX_COUNT);
108         isAppOSUMode = false;
109         ALOGD("Setting to normal mode!!!");
110       }
111       break;
112   }
113   return isOsuMode();
114 }
115 
116 /*******************************************************************************
117 **
118 ** Function:    OsuHalExtn::checkAndUpdateOsuMode
119 **
120 ** Description: Check and update current JCOP mode OSU/Normal
121 **
122 ** Returns:     None
123 **
124 *******************************************************************************/
checkAndUpdateOsuMode()125 void OsuHalExtn::checkAndUpdateOsuMode() {
126   isJcopOSUMode = (phNxpEse_GetOsMode() == OSU_MODE);
127 }
128 
129 /*******************************************************************************
130 **
131 ** Function:    OsuHalExtn::getInstance
132 **
133 ** Description: get class singleton object
134 **
135 ** Returns:     OsuHalExtn
136 **
137 *******************************************************************************/
getInstance()138 OsuHalExtn& OsuHalExtn::getInstance() {
139   static OsuHalExtn manager;
140   return manager;
141 }
142 
143 /*******************************************************************************
144 **
145 ** Function:    OsuHalExtn::OsuHalExtn()
146 **
147 ** Description: class constructor
148 **
149 ** Returns:     none
150 **
151 *******************************************************************************/
OsuHalExtn()152 OsuHalExtn::OsuHalExtn() noexcept {
153   isAppOSUMode = false;
154   isJcopOSUMode = false;
155 }
156 
157 /*******************************************************************************
158 **
159 ** Function:    OsuHalExtn::~OsuHalExtn()
160 **
161 ** Description: class destructor
162 **
163 ** Returns:     none
164 **
165 *******************************************************************************/
~OsuHalExtn()166 OsuHalExtn::~OsuHalExtn() {}
167 
168 /*******************************************************************************
169 **
170 ** Function:    OsuHalExtn::isOsuMode()
171 **
172 ** Description: Returns current JCOP mode
173 **
174 ** Returns:     true(OSU)/false(Normal)
175 **
176 *******************************************************************************/
isOsuMode()177 bool OsuHalExtn::isOsuMode() { return (isAppOSUMode || isJcopOSUMode); }
178 
179 /*******************************************************************************
180 **
181 ** Function:    OsuHalExtn::checkTransmit
182 **
183 ** Description: Process transmit request in OSU mode
184 **              1) Unwrap proprietary APDU's to native commands
185 **              2) Block unexpected command request in OSU Mode
186 **              3) Perform hard reset on receiving proprietary reset APDU
187 **
188 ** Returns:     OsuApduMode
189 **
190 *******************************************************************************/
checkTransmit(uint8_t * input,size_t length,uint32_t * outLength)191 OsuHalExtn::OsuApduMode OsuHalExtn::checkTransmit(uint8_t* input, size_t length,
192                                                   uint32_t* outLength) {
193   OsuHalExtn::OsuApduMode halMode = NON_OSU_MODE;
194 
195   /*
196    * 1) Transmit request on logical channels(ISO7816_CLA_CHN_MASK)shall be
197    *    blocked in OSU mode
198    * 2) Empty/Default GP card manager select from OMAPI shall
199    *    be blocked in OSU Mode
200    */
201   if (((*input & ISO7816_CLA_CHN_MASK) != ISO7816_BASIC_CHANNEL) ||
202       (isJcopOSUMode && (length == ISO7816_SHORT_APDU_HEADER &&
203                          !memcmp(input, defaultSelectAid, length)))) {
204     phNxpEse_free(input);
205     input = nullptr;
206     halMode = OSU_BLOCKED_MODE;
207   } else if ((*input == OSU_PROP_CLA) &&
208              (*(input + ISO7816_INS_OFFSET) == OSU_PROP_INS) &&
209              (*(input + ISO7816_P1_OFFSET) != OSU_PROP_RST_P1)) {
210     /*
211      * 1) Unwrap GP command to native commands
212      * 2) Check APDU type short/extended before unwrapping
213      */
214     ALOGD("checkTransmit in OSU_PROP_MODE");
215     if (*(input + ISO7816_LC_OFFSET) != 0) {
216       if (length > ISO7816_SHORT_APDU_HEADER) {
217         *outLength = length - ISO7816_SHORT_APDU_HEADER;
218         memcpy(input, input + ISO7816_SHORT_APDU_HEADER,
219                length - ISO7816_SHORT_APDU_HEADER);
220       } else {
221         *outLength = 0;
222         ALOGE("checkTransmit input data length is incorrect");
223       }
224     } else {
225       if (length > ISO7816_EXTENDED_APDU_HEADER) {
226         *outLength = length - ISO7816_EXTENDED_APDU_HEADER;
227         memcpy(input, input + ISO7816_EXTENDED_APDU_HEADER,
228                length - ISO7816_EXTENDED_APDU_HEADER);
229       } else {
230         *outLength = 0;
231         ALOGE("checkTransmit input data length is incorrect");
232       }
233     }
234     halMode = OSU_PROP_MODE;
235   } else if ((*input == OSU_PROP_CLA) &&
236              (*(input + ISO7816_INS_OFFSET) == OSU_PROP_INS) &&
237              (*(input + ISO7816_P1_OFFSET) == OSU_PROP_RST_P1)) {
238     // eSE hard reset on receiving proprietary reset APDU
239     ALOGD("checkTransmit in OSU_PROP_RST_INS");
240     if (phNxpEse_SetEndPoint_Cntxt(0) != ESESTATUS_SUCCESS) {
241       ALOGE("phNxpEse_SetEndPoint_Cntxt failed!!!");
242     }
243     phNxpEse_resetJcopUpdate();
244     if (phNxpEse_ResetEndPoint_Cntxt(0) != ESESTATUS_SUCCESS) {
245       ALOGE("phNxpEse_ResetEndPoint_Cntxt failed!!!");
246     }
247     // Update mode after eSE reset
248     checkAndUpdateOsuMode();
249     phNxpEse_free(input);
250     input = nullptr;
251     halMode = OSU_RST_MODE;
252   } else {
253     // Process remaining OSU commands
254     *outLength = length;
255     halMode = OSU_GP_MODE;
256   }
257   return halMode;
258 }
259 
260 /*******************************************************************************
261 **
262 ** Function:    OsuHalExtn::getOSUMaxWtxCount
263 **
264 ** Description: Read OSU_MAX_WTX_COUNT from config file allowed when in OSU
265 **              mode
266 **
267 ** Returns:     Return maximum WTX count
268 **
269 *******************************************************************************/
getOSUMaxWtxCount()270 unsigned long int OsuHalExtn::getOSUMaxWtxCount() {
271   return EseConfig::getUnsigned(NAME_NXP_OSU_MAX_WTX_COUNT,
272                                 DEFAULT_MAX_WTX_COUNT);
273 }
274