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