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 } else {
134 ALOGD("%s Cannot open file %s\n", __func__, source_path);
135 }
136 }
137 if (prefix.empty()) {
138 prefix.assign(ls_script_source_prefix);
139 }
140 }
141
142 /*******************************************************************************
143 **
144 ** Function: LSC_Start
145 **
146 ** Description: Starts the LSC update with encrypted data privided in the
147 updater file
148 **
149 ** Returns: SUCCESS if ok.
150 **
151 *******************************************************************************/
LSC_Start(const char * name,const char * dest,uint8_t * pdata,uint16_t len,uint8_t * respSW)152 LSCSTATUS LSC_Start(const char* name, const char* dest, uint8_t* pdata,
153 uint16_t len, uint8_t* respSW) {
154 static const char fn[] = "LSC_Start";
155 LSCSTATUS status = LSCSTATUS_FAILED;
156 if (name != NULL) {
157 status = Perform_LSC(name, dest, pdata, len, respSW);
158 } else {
159 ALOGE("%s: LS script file is missing", fn);
160 }
161 ALOGD_IF(ese_debug_enabled, "%s: Exit; status=0x0%X", fn, status);
162 return status;
163 }
164
165 /*******************************************************************************
166 **
167 ** Function: LSC_doDownload
168 **
169 ** Description: Start LS download process
170 **
171 ** Returns: SUCCESS if ok
172 **
173 *******************************************************************************/
LSC_doDownload(LSC_onCompletedCallback callback,void * args)174 LSCSTATUS LSC_doDownload(LSC_onCompletedCallback callback, void* args) {
175 static const char fn[] = "LSC_doDownload";
176
177 mCallback = callback;
178 mCallbackParams = args;
179
180 LSCSTATUS status;
181 pthread_t thread;
182 pthread_attr_t attr;
183 pthread_attr_init(&attr);
184 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
185 if (pthread_create(&thread, &attr, &performLSDownload_thread, NULL) < 0) {
186 ALOGE("%s: Thread creation failed", fn);
187 status = LSCSTATUS_FAILED;
188 } else {
189 status = LSCSTATUS_SUCCESS;
190 }
191 pthread_attr_destroy(&attr);
192 return status;
193 }
194
195 /*******************************************************************************
196 **
197 ** Function: printLSStatus
198 **
199 ** Description: print LS applet state and Slot 1 & 2 data
200 **
201 ** Returns: LS status log
202 **
203 *******************************************************************************/
printLSStatus(int lsStatus)204 std::string printLSStatus(int lsStatus) {
205 ALOGD_IF(ese_debug_enabled, "%s enter ", __func__);
206
207 uint8_t slotHashBuffer[HASH_DATA_LENGTH] = {0};
208 uint16_t length = 0;
209 uint16_t lsVersion = 0;
210 uint8_t lsMode = 0;
211 std::stringstream outStream;
212 std::stringstream outHash;
213
214 LSInfo lsInfo;
215 memset(&lsInfo, 0xFF, sizeof(LSInfo));
216 lsInfo.m_status = lsStatus;
217
218 outStream << "\nCurrent LS info:";
219 /*Read LS applet mode*/
220 LSCSTATUS status = LSC_ReadLscInfo(&lsMode, &lsVersion);
221 if (status != LSCSTATUS_SUCCESS) {
222 outStream << dumpLsInfo(&lsInfo);
223 outStream << "\nFailed to access LS applet!\n";
224 return outStream.str();
225 }
226
227 ALOGI_IF(ese_debug_enabled, "LS applet version is %d.%d", (lsVersion >> 8),
228 (lsVersion & 0xFF));
229 if (lsMode == 2) {
230 ALOGI_IF(ese_debug_enabled, "LS is in UPDATE mode!");
231 }
232 lsInfo.m_version = lsVersion & 0xFF;
233 lsInfo.m_mode = lsMode;
234
235 /*Read the hash from slot 1*/
236 status = LSC_ReadLsHash(slotHashBuffer, &length, 1);
237 if (status != LSCSTATUS_SUCCESS) {
238 ALOGI_IF(ese_debug_enabled, "Failed to read Hash value from slot 1.");
239 outStream << dumpLsInfo(&lsInfo);
240 return outStream.str();
241 }
242 if (slotHashBuffer[HASH_DATA_LENGTH - 1] == LS_DOWNLOAD_SUCCESS) {
243 ALOGI_IF(ese_debug_enabled, "LS Slot 1 passed.");
244 lsInfo.m_slot1_status = LS_DOWNLOAD_SUCCESS;
245 } else {
246 ALOGI_IF(ese_debug_enabled, "LS Slot 1 failed.");
247 lsInfo.m_slot1_status = LS_DOWNLOAD_FAILED;
248 }
249 lsInfo.m_slot1_hash = compareLSHash(slotHashBuffer, HASH_DATA_LENGTH - 1);
250 if (lsInfo.m_slot1_hash == 0xFF) {
251 outHash << "\n slot 1 hash:\n";
252 for (int i = 0; i < HASH_DATA_LENGTH - 1; i++) {
253 outHash << std::setw(2) << std::setfill('0') << std::hex
254 << (int)slotHashBuffer[i];
255 }
256 }
257
258 /*Read the hash from slot 2*/
259 status = LSC_ReadLsHash(slotHashBuffer, &length, 2);
260 if (status != LSCSTATUS_SUCCESS) {
261 ALOGI_IF(ese_debug_enabled, "Failed to read Hash value from slot 1.");
262 outStream << dumpLsInfo(&lsInfo);
263 return outStream.str();
264 }
265 if (slotHashBuffer[HASH_DATA_LENGTH - 1] == LS_DOWNLOAD_SUCCESS) {
266 ALOGI_IF(ese_debug_enabled, "LS Slot 2 passed.");
267 lsInfo.m_slot2_status = LS_DOWNLOAD_SUCCESS;
268 } else {
269 ALOGI_IF(ese_debug_enabled, "LS Slot 2 failed.");
270 lsInfo.m_slot2_status = LS_DOWNLOAD_FAILED;
271 }
272 lsInfo.m_slot2_hash = compareLSHash(slotHashBuffer, HASH_DATA_LENGTH - 1);
273 if (lsInfo.m_slot2_hash == 0xFF) {
274 outHash << "\n slot 2 hash:\n";
275 for (int i = 0; i < HASH_DATA_LENGTH - 1; i++) {
276 outHash << std::setw(2) << std::setfill('0') << std::hex
277 << (int)slotHashBuffer[i];
278 }
279 }
280
281 outStream << dumpLsInfo(&lsInfo) << outHash.str();
282
283 ALOGD_IF(ese_debug_enabled, "%s exit\n", __func__);
284 return outStream.str();
285 }
286
287 /*******************************************************************************
288 **
289 ** Function: performLSDownload_thread
290 **
291 ** Description: Perform LS during hal init
292 **
293 ** Returns: None
294 **
295 *******************************************************************************/
performLSDownload_thread(void * data)296 void* performLSDownload_thread(__attribute__((unused)) void* data) {
297 ALOGD_IF(ese_debug_enabled, "%s enter ", __func__);
298 /*generated SHA-1 string for secureElementLS
299 This will remain constant as handled in secureElement HAL*/
300 char sha1[] = "6d583e84f2710e6b0f06beebc1a12a1083591373";
301 uint8_t hash[20] = {0};
302
303 for (int i = 0; i < 40; i = i + 2) {
304 hash[i / 2] =
305 (((datahex(sha1[i]) & 0x0F) << 4) | (datahex(sha1[i + 1]) & 0x0F));
306 }
307
308 uint8_t resSW[4] = {0x4e, 0x02, 0x69, 0x87};
309
310 std::string sourcePath;
311 std::string sourcePrefix;
312 std::string outPath;
313 int index = 1;
314 LSCSTATUS status = LSCSTATUS_SUCCESS;
315 Lsc_HashInfo_t lsHashInfo;
316
317 getLSScriptSourcePrefix(sourcePrefix);
318 do {
319 /*Open the script file from specified location and name*/
320 sourcePath.assign(sourcePrefix);
321 sourcePath += ('0' + index);
322 sourcePath += ls_script_source_suffix;
323 FILE* fIn = fopen(sourcePath.c_str(), "rb");
324 if (fIn == NULL) {
325 ALOGE("%s Cannot open LS script file %s, Error: %s\n", __func__,
326 sourcePath.c_str(), strerror(errno));
327 break;
328 }
329 ALOGD_IF(ese_debug_enabled, "%s File opened %s\n", __func__,
330 sourcePath.c_str());
331
332 /*Read the script content to a local buffer*/
333 fseek(fIn, 0, SEEK_END);
334 long lsBufSize = ftell(fIn);
335 rewind(fIn);
336 if (lsHashInfo.lsRawScriptBuf == nullptr) {
337 lsHashInfo.lsRawScriptBuf = (uint8_t*)phNxpEse_memalloc(lsBufSize + 1);
338 }
339 memset(lsHashInfo.lsRawScriptBuf, 0x00, (lsBufSize + 1));
340 fread(lsHashInfo.lsRawScriptBuf, lsBufSize, 1, fIn);
341
342 LSCSTATUS lsHashStatus = LSCSTATUS_FAILED;
343
344 /*Get 20bye SHA1 of the script*/
345 lsHashInfo.lsScriptHash =
346 getHASH(lsHashInfo.lsRawScriptBuf, (size_t)lsBufSize);
347 phNxpEse_free(lsHashInfo.lsRawScriptBuf);
348 lsHashInfo.lsRawScriptBuf = nullptr;
349 if (lsHashInfo.lsScriptHash == nullptr) break;
350
351 if (lsHashInfo.readBuffHash == nullptr) {
352 lsHashInfo.readBuffHash = (uint8_t*)phNxpEse_memalloc(HASH_DATA_LENGTH);
353 }
354 memset(lsHashInfo.readBuffHash, 0x00, HASH_DATA_LENGTH);
355
356 /*Read the hash from applet for specified slot*/
357 lsHashStatus =
358 LSC_ReadLsHash(lsHashInfo.readBuffHash, &lsHashInfo.readHashLen, index);
359
360 /*Check if previously script is successfully installed.
361 if yes, continue reading next script else try update wit current script*/
362 if ((lsHashStatus == LSCSTATUS_SUCCESS) &&
363 (lsHashInfo.readHashLen == HASH_DATA_LENGTH) &&
364 (0 == memcmp(lsHashInfo.lsScriptHash, lsHashInfo.readBuffHash,
365 HASH_DATA_LENGTH - 1)) &&
366 (lsHashInfo.readBuffHash[HASH_STATUS_INDEX] == LS_DOWNLOAD_SUCCESS)) {
367 ALOGD_IF(ese_debug_enabled, "%s LS Loader sript is already installed \n",
368 __func__);
369 continue;
370 }
371
372 /*Create output file to write response data*/
373 outPath.assign(ls_script_output_prefix);
374 outPath += ('0' + index);
375 outPath += ls_script_output_suffix;
376
377 FILE* fOut = fopen(outPath.c_str(), "wb+");
378 if (fOut == NULL) {
379 ALOGE("%s Failed to open file %s\n", __func__, outPath.c_str());
380 break;
381 }
382 fclose(fOut);
383
384 /*Uptdates current script*/
385 status = LSC_Start(sourcePath.c_str(), outPath.c_str(), (uint8_t*)hash,
386 (uint16_t)sizeof(hash), resSW);
387 ALOGD_IF(ese_debug_enabled, "%s script %s perform done, result = %d\n",
388 __func__, sourcePath.c_str(), status);
389 if (status != LSCSTATUS_SUCCESS) {
390 lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_FAILED;
391 /*If current script updation fails, update the status with hash to the
392 * applet then clean and exit*/
393 lsHashStatus =
394 LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
395 if (lsHashStatus != LSCSTATUS_SUCCESS) {
396 ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
397 }
398 ESESTATUS estatus = phNxpEse_deInit();
399 if (estatus == ESESTATUS_SUCCESS) {
400 estatus = phNxpEse_close();
401 if (estatus == ESESTATUS_SUCCESS) {
402 ALOGD_IF(ese_debug_enabled, "%s: Ese_close success\n", __func__);
403 }
404 } else {
405 ALOGE("%s: Ese_deInit failed", __func__);
406 }
407
408 if (mCallback != nullptr) {
409 (mCallback)(false, printLSStatus(LS_DOWNLOAD_FAILED), mCallbackParams);
410 break;
411 }
412 } else {
413 /*If current script execution is succes, update the status along with the
414 * hash to the applet*/
415 lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_SUCCESS;
416 lsHashStatus =
417 LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
418 if (lsHashStatus != LSCSTATUS_SUCCESS) {
419 ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
420 }
421 }
422 } while (++index <= LS_MAX_COUNT);
423
424 phNxpEse_free(lsHashInfo.readBuffHash);
425
426 if (status == LSCSTATUS_SUCCESS) {
427 if (mCallback != nullptr) {
428 (mCallback)(true, printLSStatus(LS_DOWNLOAD_SUCCESS), mCallbackParams);
429 }
430 }
431 pthread_exit(NULL);
432 ALOGD_IF(ese_debug_enabled, "%s pthread_exit\n", __func__);
433 return NULL;
434 }
435
436 /*******************************************************************************
437 **
438 ** Function: getHASH
439 **
440 ** Description: generates SHA1 of given buffer
441 **
442 ** Returns: 20 bytes of SHA1
443 **
444 *******************************************************************************/
getHASH(uint8_t * buffer,size_t buffSize)445 unsigned char* getHASH(uint8_t* buffer, size_t buffSize) {
446 static uint8_t outHash[HASH_DATA_LENGTH] = {0};
447 unsigned int md_len = -1;
448 const EVP_MD* md = EVP_get_digestbyname("SHA1");
449 if (NULL != md) {
450 EVP_MD_CTX mdctx;
451 EVP_MD_CTX_init(&mdctx);
452 EVP_DigestInit_ex(&mdctx, md, NULL);
453 EVP_DigestUpdate(&mdctx, buffer, buffSize);
454 EVP_DigestFinal_ex(&mdctx, outHash, &md_len);
455 EVP_MD_CTX_cleanup(&mdctx);
456 }
457 return outHash;
458 }
459
460 /*******************************************************************************
461 **
462 ** Function: datahex
463 **
464 ** Description: Converts char to uint8_t
465 **
466 ** Returns: uint8_t variable
467 **
468 *******************************************************************************/
datahex(char c)469 uint8_t datahex(char c) {
470 uint8_t value = 0;
471 if (c >= '0' && c <= '9')
472 value = (c - '0');
473 else if (c >= 'A' && c <= 'F')
474 value = (10 + (c - 'A'));
475 else if (c >= 'a' && c <= 'f')
476 value = (10 + (c - 'a'));
477 return value;
478 }
479