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