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