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