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