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