• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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