1 /******************************************************************************
2 *
3 * Copyright 2018 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 #define LOG_TAG "LSClient"
19
20 #include <cutils/properties.h>
21 #include <dirent.h>
22 #include <errno.h>
23 #include <log/log.h>
24 #include <openssl/evp.h>
25 #include <pthread.h>
26 #include <stdlib.h>
27 #include <iomanip>
28 #include <sstream>
29 #include <string>
30
31 #include "LsClient.h"
32 #include "LsLib.h"
33
34 uint8_t datahex(char c);
35 unsigned char* getHASH(uint8_t* buffer, size_t buffSize);
36 extern bool ese_debug_enabled;
37
38 #define ls_script_source_prefix "/vendor/etc/loaderservice_updater_"
39 #define ls_script_source_suffix ".lss"
40 #define ls_script_output_prefix \
41 "/data/vendor/secure_element/loaderservice_updater_out_"
42 #define ls_script_output_suffix ".txt"
43 const size_t HASH_DATA_LENGTH = 21;
44 const uint16_t HASH_STATUS_INDEX = 20;
45 const uint8_t LS_MAX_COUNT = 10;
46 const uint8_t LS_DOWNLOAD_SUCCESS = 0x00;
47 const uint8_t LS_DOWNLOAD_FAILED = 0x01;
48
49 class LSInfo {
50 public:
51 uint8_t m_status;
52 uint8_t m_version;
53 uint8_t m_mode;
54 uint8_t m_slot1_status;
55 uint8_t m_slot1_hash;
56 uint8_t m_slot2_status;
57 uint8_t m_slot2_hash;
58 };
59
60 static LSC_onCompletedCallback mCallback = nullptr;
61 static void* mCallbackParams = NULL;
62
63 void* performLSDownload_thread(void* data);
64 static void getLSScriptSourcePrefix(std::string& prefix);
65 static int compareLSHash(uint8_t* hash, uint8_t length);
66 static std::string printLSStatus(int status);
67 static std::string dumpLsInfo(LSInfo* info);
68
compareLSHash(uint8_t * hash,uint8_t length)69 static int compareLSHash(uint8_t* hash, uint8_t length) {
70 uint8_t ls253UpdaterScriptHash[HASH_DATA_LENGTH - 1] = {
71 0x65, 0x80, 0xFB, 0xA0, 0xCA, 0x59, 0xAE, 0x6C, 0x71, 0x6B,
72 0x15, 0xB1, 0xBD, 0xB1, 0x2C, 0x04, 0x29, 0x14, 0x8A, 0x8F};
73 uint8_t ls253AppletScriptHash[HASH_DATA_LENGTH - 1] = {
74 0x71, 0x7B, 0x8D, 0x0C, 0xEA, 0xE7, 0xEC, 0xC1, 0xCF, 0x47,
75 0x33, 0x10, 0xFE, 0x8E, 0x52, 0x5D, 0xB1, 0x43, 0x9B, 0xDE};
76 uint8_t lsFactoryScript1Hash[HASH_DATA_LENGTH - 1] = {
77 0x4A, 0xD0, 0x37, 0xD0, 0x44, 0x5B, 0x78, 0x55, 0x17, 0x5E,
78 0xFD, 0x87, 0x9C, 0xF1, 0x74, 0xBA, 0x77, 0xAD, 0x03, 0x62};
79 uint8_t lsFactoryScript2Hash[HASH_DATA_LENGTH - 1] = {
80 0xA9, 0xDB, 0x03, 0x53, 0xC2, 0xD7, 0xF8, 0xFC, 0x84, 0x37,
81 0xAF, 0xB9, 0x53, 0x06, 0x27, 0x9D, 0xE9, 0x68, 0x45, 0xEF};
82 uint8_t lsFactoryScript3Hash[HASH_DATA_LENGTH - 1] = {
83 0xA9, 0xAE, 0x5E, 0x66, 0x92, 0x8F, 0x70, 0xBD, 0x0A, 0xC7,
84 0x20, 0x8A, 0x6A, 0xBB, 0x63, 0xB3, 0xCA, 0x05, 0x58, 0xC1};
85 uint8_t lsFactoryScript4Hash[HASH_DATA_LENGTH - 1] = {
86 0x64, 0x73, 0x56, 0xAE, 0x58, 0x27, 0x6C, 0x07, 0x4B, 0xBA,
87 0x64, 0x7E, 0x6E, 0xC1, 0x97, 0xC8, 0x57, 0x17, 0x6E, 0x2D};
88 uint8_t* hashList[6] = {lsFactoryScript1Hash, lsFactoryScript2Hash,
89 lsFactoryScript3Hash, lsFactoryScript4Hash,
90 ls253UpdaterScriptHash, ls253AppletScriptHash};
91
92 if (length != HASH_DATA_LENGTH - 1) {
93 return 0xFF;
94 }
95 for (int i = 0; i < 6; i++) {
96 if (0 == memcmp(hash, hashList[i], length)) {
97 return i + 1;
98 }
99 }
100 return 0xFF;
101 }
102
dumpLsInfo(LSInfo * info)103 static std::string dumpLsInfo(LSInfo* info) {
104 std::stringstream buff;
105 buff << std::setw(2) << std::setfill('0') << std::hex
106 << (int)(info->m_status);
107 buff << std::setw(2) << std::setfill('0') << std::hex
108 << (int)(info->m_version);
109 buff << std::setw(2) << std::setfill('0') << std::hex
110 << (int)(info->m_mode);
111 buff << std::setw(2) << std::setfill('0') << std::hex
112 << (int)(info->m_slot1_status);
113 buff << std::setw(2) << std::setfill('0') << std::hex
114 << (int)(info->m_slot1_hash);
115 buff << std::setw(2) << std::setfill('0') << std::hex
116 << (int)(info->m_slot2_status);
117 buff << std::setw(2) << std::setfill('0') << std::hex
118 << (int)(info->m_slot2_hash);
119 return buff.str();
120 }
121
getLSScriptSourcePrefix(std::string & prefix)122 void getLSScriptSourcePrefix(std::string& prefix) {
123 char source_path[PROPERTY_VALUE_MAX] = {0};
124 int len = property_get("vendor.ese.loader_script_path", source_path, "");
125 if (len > 0) {
126 FILE* fd = fopen(source_path, "rb");
127 if (fd != NULL) {
128 char c;
129 while (!feof(fd) && fread(&c, 1, 1, fd) == 1) {
130 if (c == ' ' || c == '\n' || c == '\r' || c == 0x00) break;
131 prefix.push_back(c);
132 }
133 fclose(fd);
134 } else {
135 ALOGD("%s Cannot open file %s\n", __func__, source_path);
136 }
137 }
138 if (prefix.empty()) {
139 prefix.assign(ls_script_source_prefix);
140 }
141 }
142
143 /*******************************************************************************
144 **
145 ** Function: LSC_Start
146 **
147 ** Description: Starts the LSC update with encrypted data privided in the
148 updater file
149 **
150 ** Returns: SUCCESS if ok.
151 **
152 *******************************************************************************/
LSC_Start(const char * name,const char * dest,uint8_t * pdata,uint16_t len,uint8_t * respSW)153 LSCSTATUS LSC_Start(const char* name, const char* dest, uint8_t* pdata,
154 uint16_t len, uint8_t* respSW) {
155 static const char fn[] = "LSC_Start";
156 LSCSTATUS status = LSCSTATUS_FAILED;
157 if (name != NULL) {
158 status = Perform_LSC(name, dest, pdata, len, respSW);
159 } else {
160 ALOGE("%s: LS script file is missing", fn);
161 }
162 ALOGD_IF(ese_debug_enabled, "%s: Exit; status=0x0%X", fn, status);
163 return status;
164 }
165
166 /*******************************************************************************
167 **
168 ** Function: LSC_doDownload
169 **
170 ** Description: Start LS download process
171 **
172 ** Returns: SUCCESS if ok
173 **
174 *******************************************************************************/
LSC_doDownload(LSC_onCompletedCallback callback,void * args)175 LSCSTATUS LSC_doDownload(LSC_onCompletedCallback callback, void* args) {
176 static const char fn[] = "LSC_doDownload";
177
178 mCallback = callback;
179 mCallbackParams = args;
180
181 LSCSTATUS status;
182 pthread_t thread;
183 pthread_attr_t attr;
184 pthread_attr_init(&attr);
185 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
186 if (pthread_create(&thread, &attr, &performLSDownload_thread, NULL) < 0) {
187 ALOGE("%s: Thread creation failed", fn);
188 status = LSCSTATUS_FAILED;
189 } else {
190 status = LSCSTATUS_SUCCESS;
191 }
192 pthread_attr_destroy(&attr);
193 return status;
194 }
195
196 /*******************************************************************************
197 **
198 ** Function: printLSStatus
199 **
200 ** Description: print LS applet state and Slot 1 & 2 data
201 **
202 ** Returns: LS status log
203 **
204 *******************************************************************************/
printLSStatus(int lsStatus)205 std::string printLSStatus(int lsStatus) {
206 ALOGD_IF(ese_debug_enabled, "%s enter ", __func__);
207
208 uint8_t slotHashBuffer[HASH_DATA_LENGTH] = {0};
209 uint16_t length = 0;
210 uint16_t lsVersion = 0;
211 uint8_t lsMode = 0;
212 std::stringstream outStream;
213 std::stringstream outHash;
214
215 LSInfo lsInfo;
216 memset(&lsInfo, 0xFF, sizeof(LSInfo));
217 lsInfo.m_status = lsStatus;
218
219 outStream << "\nCurrent LS info:";
220 /*Read LS applet mode*/
221 LSCSTATUS status = LSC_ReadLscInfo(&lsMode, &lsVersion);
222 if (status != LSCSTATUS_SUCCESS) {
223 outStream << dumpLsInfo(&lsInfo);
224 outStream << "\nFailed to access LS applet!\n";
225 return outStream.str();
226 }
227
228 ALOGI_IF(ese_debug_enabled, "LS applet version is %d.%d", (lsVersion >> 8),
229 (lsVersion & 0xFF));
230 if (lsMode == 2) {
231 ALOGI_IF(ese_debug_enabled, "LS is in UPDATE mode!");
232 }
233 lsInfo.m_version = lsVersion & 0xFF;
234 lsInfo.m_mode = lsMode;
235
236 /*Read the hash from slot 1*/
237 status = LSC_ReadLsHash(slotHashBuffer, &length, 1);
238 if (status != LSCSTATUS_SUCCESS) {
239 ALOGI_IF(ese_debug_enabled, "Failed to read Hash value from slot 1.");
240 outStream << dumpLsInfo(&lsInfo);
241 return outStream.str();
242 }
243 if (slotHashBuffer[HASH_DATA_LENGTH - 1] == LS_DOWNLOAD_SUCCESS) {
244 ALOGI_IF(ese_debug_enabled, "LS Slot 1 passed.");
245 lsInfo.m_slot1_status = LS_DOWNLOAD_SUCCESS;
246 } else {
247 ALOGI_IF(ese_debug_enabled, "LS Slot 1 failed.");
248 lsInfo.m_slot1_status = LS_DOWNLOAD_FAILED;
249 }
250 lsInfo.m_slot1_hash = compareLSHash(slotHashBuffer, HASH_DATA_LENGTH - 1);
251 if (lsInfo.m_slot1_hash == 0xFF) {
252 outHash << "\n slot 1 hash:\n";
253 for (int i = 0; i < HASH_DATA_LENGTH - 1; i++) {
254 outHash << std::setw(2) << std::setfill('0') << std::hex
255 << (int)slotHashBuffer[i];
256 }
257 }
258
259 /*Read the hash from slot 2*/
260 status = LSC_ReadLsHash(slotHashBuffer, &length, 2);
261 if (status != LSCSTATUS_SUCCESS) {
262 ALOGI_IF(ese_debug_enabled, "Failed to read Hash value from slot 1.");
263 outStream << dumpLsInfo(&lsInfo);
264 return outStream.str();
265 }
266 if (slotHashBuffer[HASH_DATA_LENGTH - 1] == LS_DOWNLOAD_SUCCESS) {
267 ALOGI_IF(ese_debug_enabled, "LS Slot 2 passed.");
268 lsInfo.m_slot2_status = LS_DOWNLOAD_SUCCESS;
269 } else {
270 ALOGI_IF(ese_debug_enabled, "LS Slot 2 failed.");
271 lsInfo.m_slot2_status = LS_DOWNLOAD_FAILED;
272 }
273 lsInfo.m_slot2_hash = compareLSHash(slotHashBuffer, HASH_DATA_LENGTH - 1);
274 if (lsInfo.m_slot2_hash == 0xFF) {
275 outHash << "\n slot 2 hash:\n";
276 for (int i = 0; i < HASH_DATA_LENGTH - 1; i++) {
277 outHash << std::setw(2) << std::setfill('0') << std::hex
278 << (int)slotHashBuffer[i];
279 }
280 }
281
282 outStream << dumpLsInfo(&lsInfo) << outHash.str();
283
284 ALOGD_IF(ese_debug_enabled, "%s exit\n", __func__);
285 return outStream.str();
286 }
287
288 /*******************************************************************************
289 **
290 ** Function: performLSDownload_thread
291 **
292 ** Description: Perform LS during hal init
293 **
294 ** Returns: None
295 **
296 *******************************************************************************/
performLSDownload_thread(void * data)297 void* performLSDownload_thread(__attribute__((unused)) void* data) {
298 ALOGD_IF(ese_debug_enabled, "%s enter ", __func__);
299 /*generated SHA-1 string for secureElementLS
300 This will remain constant as handled in secureElement HAL*/
301 char sha1[] = "6d583e84f2710e6b0f06beebc1a12a1083591373";
302 uint8_t hash[20] = {0};
303
304 for (int i = 0; i < 40; i = i + 2) {
305 hash[i / 2] =
306 (((datahex(sha1[i]) & 0x0F) << 4) | (datahex(sha1[i + 1]) & 0x0F));
307 }
308
309 uint8_t resSW[4] = {0x4e, 0x02, 0x69, 0x87};
310
311 std::string sourcePath;
312 std::string sourcePrefix;
313 std::string outPath;
314 int index = 1;
315 LSCSTATUS status = LSCSTATUS_SUCCESS;
316 Lsc_HashInfo_t lsHashInfo;
317
318 getLSScriptSourcePrefix(sourcePrefix);
319 do {
320 /*Open the script file from specified location and name*/
321 sourcePath.assign(sourcePrefix);
322 sourcePath += ('0' + index);
323 sourcePath += ls_script_source_suffix;
324 FILE* fIn = fopen(sourcePath.c_str(), "rb");
325 if (fIn == NULL) {
326 ALOGE("%s Cannot open LS script file %s, Error: %s\n", __func__,
327 sourcePath.c_str(), strerror(errno));
328 break;
329 }
330 ALOGD_IF(ese_debug_enabled, "%s File opened %s\n", __func__,
331 sourcePath.c_str());
332
333 /*Read the script content to a local buffer*/
334 fseek(fIn, 0, SEEK_END);
335 long lsBufSize = ftell(fIn);
336 if (lsBufSize < 0) {
337 ALOGE("%s Failed to get current value of position indicator\n", __func__);
338 fclose(fIn);
339 status = LSCSTATUS_FAILED;
340 break;
341 }
342 rewind(fIn);
343 if (lsHashInfo.lsRawScriptBuf == nullptr) {
344 lsHashInfo.lsRawScriptBuf = (uint8_t*)phNxpEse_memalloc(lsBufSize + 1);
345 }
346 memset(lsHashInfo.lsRawScriptBuf, 0x00, (lsBufSize + 1));
347 if (fread(lsHashInfo.lsRawScriptBuf, (size_t)lsBufSize, 1, fIn) != 1)
348 ALOGD_IF(ese_debug_enabled, "%s Failed to read file", __func__);
349 fclose(fIn);
350 LSCSTATUS lsHashStatus = LSCSTATUS_FAILED;
351
352 /*Get 20bye SHA1 of the script*/
353 lsHashInfo.lsScriptHash =
354 getHASH(lsHashInfo.lsRawScriptBuf, (size_t)lsBufSize);
355 phNxpEse_free(lsHashInfo.lsRawScriptBuf);
356 lsHashInfo.lsRawScriptBuf = nullptr;
357 if (lsHashInfo.lsScriptHash == nullptr) break;
358
359 if (lsHashInfo.readBuffHash == nullptr) {
360 lsHashInfo.readBuffHash = (uint8_t*)phNxpEse_memalloc(HASH_DATA_LENGTH);
361 }
362 memset(lsHashInfo.readBuffHash, 0x00, HASH_DATA_LENGTH);
363
364 /*Read the hash from applet for specified slot*/
365 lsHashStatus =
366 LSC_ReadLsHash(lsHashInfo.readBuffHash, &lsHashInfo.readHashLen, index);
367
368 /*Check if previously script is successfully installed.
369 if yes, continue reading next script else try update wit current script*/
370 if ((lsHashStatus == LSCSTATUS_SUCCESS) &&
371 (lsHashInfo.readHashLen == HASH_DATA_LENGTH) &&
372 (0 == memcmp(lsHashInfo.lsScriptHash, lsHashInfo.readBuffHash,
373 HASH_DATA_LENGTH - 1)) &&
374 (lsHashInfo.readBuffHash[HASH_STATUS_INDEX] == LS_DOWNLOAD_SUCCESS)) {
375 ALOGD_IF(ese_debug_enabled, "%s LS Loader sript is already installed \n",
376 __func__);
377 continue;
378 }
379
380 /*Create output file to write response data*/
381 outPath.assign(ls_script_output_prefix);
382 outPath += ('0' + index);
383 outPath += ls_script_output_suffix;
384
385 FILE* fOut = fopen(outPath.c_str(), "wb+");
386 if (fOut == NULL) {
387 ALOGE("%s Failed to open file %s\n", __func__, outPath.c_str());
388 break;
389 }
390 fclose(fOut);
391
392 /*Uptdates current script*/
393 status = LSC_Start(sourcePath.c_str(), outPath.c_str(), (uint8_t*)hash,
394 (uint16_t)sizeof(hash), resSW);
395 ALOGD_IF(ese_debug_enabled, "%s script %s perform done, result = %d\n",
396 __func__, sourcePath.c_str(), status);
397 if (status != LSCSTATUS_SUCCESS) {
398 lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_FAILED;
399 /*If current script updation fails, update the status with hash to the
400 * applet then clean and exit*/
401 lsHashStatus =
402 LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
403 if (lsHashStatus != LSCSTATUS_SUCCESS) {
404 ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
405 }
406 ESESTATUS estatus = phNxpEse_deInit();
407 if (estatus == ESESTATUS_SUCCESS) {
408 estatus = phNxpEse_close();
409 if (estatus == ESESTATUS_SUCCESS) {
410 ALOGD_IF(ese_debug_enabled, "%s: Ese_close success\n", __func__);
411 }
412 } else {
413 ALOGE("%s: Ese_deInit failed", __func__);
414 }
415
416 if (mCallback != nullptr) {
417 (mCallback)(false, printLSStatus(LS_DOWNLOAD_FAILED), mCallbackParams);
418 break;
419 }
420 } else {
421 /*If current script execution is succes, update the status along with the
422 * hash to the applet*/
423 lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_SUCCESS;
424 lsHashStatus =
425 LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
426 if (lsHashStatus != LSCSTATUS_SUCCESS) {
427 ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
428 }
429 }
430 } while (++index <= LS_MAX_COUNT);
431
432 phNxpEse_free(lsHashInfo.readBuffHash);
433
434 if (status == LSCSTATUS_SUCCESS) {
435 if (mCallback != nullptr) {
436 (mCallback)(true, printLSStatus(LS_DOWNLOAD_SUCCESS), mCallbackParams);
437 }
438 }
439 pthread_exit(NULL);
440 ALOGD_IF(ese_debug_enabled, "%s pthread_exit\n", __func__);
441 return NULL;
442 }
443
444 /*******************************************************************************
445 **
446 ** Function: getHASH
447 **
448 ** Description: generates SHA1 of given buffer
449 **
450 ** Returns: 20 bytes of SHA1
451 **
452 *******************************************************************************/
getHASH(uint8_t * buffer,size_t buffSize)453 unsigned char* getHASH(uint8_t* buffer, size_t buffSize) {
454 static uint8_t outHash[HASH_DATA_LENGTH] = {0};
455 unsigned int md_len = -1;
456 const EVP_MD* md = EVP_get_digestbyname("SHA1");
457 if (NULL != md) {
458 EVP_MD_CTX mdctx;
459 EVP_MD_CTX_init(&mdctx);
460 EVP_DigestInit_ex(&mdctx, md, NULL);
461 EVP_DigestUpdate(&mdctx, buffer, buffSize);
462 EVP_DigestFinal_ex(&mdctx, outHash, &md_len);
463 EVP_MD_CTX_cleanup(&mdctx);
464 }
465 return outHash;
466 }
467
468 /*******************************************************************************
469 **
470 ** Function: datahex
471 **
472 ** Description: Converts char to uint8_t
473 **
474 ** Returns: uint8_t variable
475 **
476 *******************************************************************************/
datahex(char c)477 uint8_t datahex(char c) {
478 uint8_t value = 0;
479 if (c >= '0' && c <= '9')
480 value = (c - '0');
481 else if (c >= 'A' && c <= 'F')
482 value = (10 + (c - 'A'));
483 else if (c >= 'a' && c <= 'f')
484 value = (10 + (c - 'a'));
485 return value;
486 }
487