Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_SOTP_test.c Source File

pal_SOTP_test.c

00001 /*******************************************************************************
00002  * Copyright 2016, 2017 ARM Ltd.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *******************************************************************************/
00016 
00017 #include "pal.h"
00018 #include "sotp.h"
00019 #include "unity.h"
00020 #include "unity_fixture.h"
00021 #include "test_runners.h"
00022 
00023 
00024 #define SOTP_DIR "/sotp"
00025 #define ROT_KEY_SIZE 16
00026 
00027 //add 5 years to minimum time
00028 #define PAL_TEST_START_TIME (PAL_MIN_SEC_FROM_EPOCH + ((PAL_SECONDS_PER_DAY * PAL_DAYS_IN_A_YEAR) * 5))
00029 #define ACCEPTABLE_DELAY_IN_SEC (5)
00030 #define PAL_SOTP_TEST_DELAY_IN_SEC (5 * 1000)
00031 
00032 
00033 extern palTestsStatusData_t palTestStatus;
00034 
00035 TEST_GROUP(pal_SOTP);
00036 
00037 #if (PAL_USE_HW_RTC)
00038     static uint64_t systemRealRTC = 0;
00039     static uint64_t systemStartTickCount = 0;
00040 #endif
00041 
00042 PAL_PRIVATE palCtrDrbgCtxHandle_t g_drbgCtx = NULLPTR;
00043 
00044 TEST_SETUP(pal_SOTP)
00045 {
00046     palStatus_t status = PAL_SUCCESS;
00047     status = pal_init();
00048     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00049 #if (PAL_USE_HW_RTC == 1)
00050     uint64_t sysTicks = 0;    
00051     status = pal_plat_osGetRtcTime(&systemRealRTC);
00052     if (systemRealRTC < (uint64_t)PAL_MIN_RTC_SET_TIME)
00053     {
00054         systemRealRTC = PAL_MIN_RTC_SET_TIME;
00055     }
00056     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00057     systemStartTickCount = pal_osKernelSysTick();
00058 #endif
00059 }
00060 
00061 TEST_TEAR_DOWN(pal_SOTP)
00062 {
00063     palStatus_t status = PAL_SUCCESS;
00064 #if (PAL_USE_HW_RTC == 1)
00065     uint64_t sysTicks = 0;
00066     uint64_t endTickCount = 0;
00067     uint64_t timeToAddInSec = 0;
00068     uint64_t timeToAddInMiliSec = 0;
00069     endTickCount = pal_osKernelSysTick();
00070     timeToAddInMiliSec = pal_osKernelSysMilliSecTick(endTickCount - systemStartTickCount); //switch from mili to seconds
00071     timeToAddInSec = PAL_MILISEC_TO_SEC(timeToAddInMiliSec);
00072     status = pal_plat_osSetRtcTime(systemRealRTC + timeToAddInSec);
00073     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00074 #endif
00075     if (g_drbgCtx)
00076     {
00077         pal_CtrDRBGFree(&g_drbgCtx);
00078     }
00079     status = pal_destroy();
00080     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00081 }
00082 
00083 static palStatus_t writeDataInFS(uint8_t* data, size_t dataSize, char* dataName)
00084 {
00085     palStatus_t status = PAL_SUCCESS, status2 = PAL_SUCCESS;
00086     char filePath[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
00087     palFileDescriptor_t fd = 0;
00088     size_t dataSizeWritten = 0;
00089 
00090     status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, filePath);
00091     strncat(filePath,SOTP_DIR,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
00092     if (PAL_SUCCESS == status) 
00093     {
00094          status = pal_fsMkDir(filePath);
00095          if ((PAL_SUCCESS == status) || (PAL_ERR_FS_NAME_ALREADY_EXIST == status)) 
00096          {
00097              strncat(filePath,"/",PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
00098              strncat(filePath,dataName,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
00099              status = pal_fsFopen(filePath,PAL_FS_FLAG_READWRITETRUNC,&fd);
00100              if (PAL_SUCCESS == status)
00101              {
00102                  status =  pal_fsFwrite(&fd, (void *)data, dataSize, &dataSizeWritten);
00103                  status2 = pal_fsFclose(&fd);
00104                  if (PAL_SUCCESS != status2) 
00105                  {
00106                      PAL_LOG(ERR,"Failed to close data file of sotp pal testing after write");
00107                  }
00108              }
00109          }
00110 
00111     }
00112     return status;
00113 }
00114 
00115 static palStatus_t readDataFromFS(uint8_t* data, size_t dataSize, char* dataName)
00116 {
00117     palStatus_t status= PAL_SUCCESS, status2 = PAL_SUCCESS;
00118     char filePath[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
00119     palFileDescriptor_t fd = 0;
00120     size_t dataSizeWritten = 0;
00121 
00122     status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, filePath);
00123     strncat(filePath,SOTP_DIR,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
00124     if (PAL_SUCCESS == status) 
00125     {
00126          strncat(filePath,"/",PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
00127          strncat(filePath,dataName,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
00128          status = pal_fsFopen(filePath, PAL_FS_FLAG_READONLY, &fd);
00129          if (PAL_SUCCESS == status)
00130          {
00131              status =  pal_fsFread(&fd, (void *)data, dataSize, &dataSizeWritten);
00132              status2 = pal_fsFclose(&fd);
00133              if (PAL_SUCCESS != status2) 
00134              {
00135                  PAL_LOG(ERR,"Failed to close data file of sotp pal testing after read");
00136              }
00137              status2 = pal_fsUnlink(filePath);
00138              if (PAL_SUCCESS != status2) 
00139              {
00140                  PAL_LOG(ERR,"Failed to delete data file of sotp pal testing after read");
00141              }
00142          }
00143 
00144     }
00145     return status;
00146 }
00147 
00148 TEST(pal_SOTP, SW_HW_RoT)
00149 {
00150         uint32_t rotLength = ROT_KEY_SIZE;
00151         palDevKeyType_t ketType = palOsStorageEncryptionKey128Bit;
00152         uint8_t rotA[ROT_KEY_SIZE] = {0};
00153         uint8_t rotB[ROT_KEY_SIZE] = {0};
00154         sotp_result_e sotpStatus = SOTP_SUCCESS;
00155         palStatus_t status = PAL_SUCCESS;
00156         (void)sotpStatus;
00157         if (palTestStatus.inner == -1) {
00158             status = pal_osGetDeviceKey(ketType, rotA, rotLength);
00159             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00160         #if(PAL_USE_HW_ROT == 0) // test SW RoT
00161             status = pal_osGetDeviceKey(ketType, rotB, rotLength);
00162             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00163 
00164             TEST_ASSERT_TRUE(0 == memcmp(rotA,rotB,rotLength))
00165 
00166             sotpStatus = sotp_delete(SOTP_TYPE_ROT);
00167             TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
00168 
00169             memset(rotA,0,sizeof(rotA));
00170 
00171             status = pal_osGetDeviceKey(ketType, rotA, rotLength);
00172             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00173 
00174             /** 
00175              * if there is no HW RoT, The Rot is generated from random. 
00176              * So, if deleted and re generated there is no chance that the 
00177              * ols RoT and the New will bw the same
00178              **/ 
00179             TEST_ASSERT_TRUE(0 != memcmp(rotA,rotB,rotLength))
00180          #endif
00181             status = writeDataInFS(rotA, rotLength,"RoT");
00182             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00183             status = palTestReboot(PAL_TEST_MODULE_SOTP, PAL_TEST_SOTP_TEST_SW_HW_ROT);
00184             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00185         }//start here after the reboot
00186         else 
00187         {
00188             memset(rotA,0,sizeof(rotA));
00189             memset(rotB,0,sizeof(rotB));
00190 
00191             if (palTestStatus.numberOfTests != 0)
00192             {
00193                 Unity.TestFailures = palTestStatus.numOfTestsFailures;
00194                 Unity.NumberOfTests = palTestStatus.numberOfTests;
00195                 Unity.CurrentTestIgnored =palTestStatus.numberOfIgnoredTests;
00196             }
00197 
00198             status = pal_osGetDeviceKey(ketType, rotA, rotLength);
00199             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00200 
00201             status = readDataFromFS(rotB, rotLength, "RoT");
00202             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00203 
00204             TEST_ASSERT_TRUE(0 == memcmp(rotA,rotB,rotLength))
00205         }
00206 }
00207 
00208 TEST(pal_SOTP, timeInit)
00209 {
00210     // call pal destroy as this test need to start before pal_init()
00211     
00212     
00213     palStatus_t status = PAL_SUCCESS;
00214 
00215     status = pal_destroy();
00216     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00217     /** 
00218      this is is splited to 2 different parts because of the ifdefs
00219      if the end of this if is inside the #if (PAL_USE_HW_RTC == 1) 
00220      in any other case, if this was a single if this had casue  
00221      compilation error 
00222      **/ 
00223 
00224     
00225     if (palTestStatus.inner == -1) 
00226     {
00227         #if ((PAL_USE_HW_RTC == 1) && (PAL_USE_INTERNAL_FLASH == 1) && (PAL_INT_FLASH_NUM_SECTION ==2))
00228          {
00229             uint64_t currentTime = 0;
00230             sotpStatus = sotp_delete(SOTP_TYPE_SAVED_TIME);
00231             TEST_ASSERT_TRUE((SOTP_SUCCESS == sotpStatus) || (SOTP_NOT_FOUND == sotpStatus))
00232             status = pal_plat_osSetRtcTime((uint64_t)PAL_TEST_START_TIME);
00233             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00234             status = pal_init();
00235             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00236             currentTime = pal_osGetTime();
00237             TEST_ASSERT_TRUE((currentTime - ACCEPTABLE_DELAY_IN_SEC) <= PAL_TEST_START_TIME);
00238             status = pal_destroy();
00239             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00240             status = pal_plat_osSetRtcTime((uint64_t)0);
00241             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00242             status = pal_init();
00243             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00244             status = pal_osDelay(PAL_SOTP_TEST_DELAY_IN_SEC);
00245             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00246             currentTime = pal_osGetTime();
00247             TEST_ASSERT_EQUAL_HEX(0, currentTime);
00248             status = pal_destroy();
00249             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00250             currentTime = PAL_TEST_START_TIME;
00251             sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&currentTime);
00252             TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, status);
00253             currentTime -= (PAL_SECONDS_PER_DAY * PAL_DAYS_IN_A_YEAR); // remove an year
00254             status = pal_plat_osSetRtcTime(currentTime);
00255             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00256             status = pal_init();
00257             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00258             currentTime = pal_osGetTime();
00259             TEST_ASSERT_TRUE((PAL_TEST_START_TIME - ACCEPTABLE_DELAY_IN_SEC) <= currentTime);
00260             status = pal_destroy();
00261             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00262             currentTime = PAL_TEST_START_TIME;
00263             status = pal_plat_osSetRtcTime(currentTime);
00264             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00265             currentTime -= (PAL_SECONDS_PER_DAY * PAL_DAYS_IN_A_YEAR); // remove an year
00266             sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&currentTime);
00267             TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, status);
00268             status = pal_init();
00269             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00270             currentTime = pal_osGetTime();
00271             TEST_ASSERT_TRUE((currentTime - ACCEPTABLE_DELAY_IN_SEC) <= PAL_TEST_START_TIME);
00272         #endif
00273 
00274 
00275         #if ((PAL_USE_HW_RTC == 0) && (PAL_USE_INTERNAL_FLASH == 1) && (PAL_INT_FLASH_NUM_SECTION ==2))
00276         {
00277             uint64_t currentTime = 0;
00278             currentTime = PAL_TEST_START_TIME; // remove an year
00279             sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&currentTime);
00280             TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, status);
00281             status = pal_init();
00282             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00283             currentTime = pal_osGetTime();
00284             TEST_ASSERT_TRUE((PAL_TEST_START_TIME - ACCEPTABLE_DELAY_IN_SEC) <= currentTime);
00285             status = pal_destroy();
00286             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 
00287         }
00288         #endif
00289     }
00290     #if (PAL_USE_HW_RTC == 1)
00291     {
00292         uint64_t currentTime = 0;
00293         if (palTestStatus.inner == -1) 
00294          {
00295             currentTime = PAL_TEST_START_TIME; // remove an year
00296             status = pal_plat_osSetRtcTime(currentTime);
00297             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00298 
00299             status = palTestReboot(PAL_TEST_MODULE_SOTP, PAL_TEST_SOTP_TEST_TIME_INIT);
00300             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00301          }//start here after reboot
00302          else
00303          {
00304             if (palTestStatus.numberOfTests != 0)
00305             {
00306                 Unity.TestFailures = palTestStatus.numOfTestsFailures;
00307                 Unity.NumberOfTests = palTestStatus.numberOfTests;
00308                 Unity.CurrentTestIgnored =palTestStatus.numberOfIgnoredTests;
00309             }
00310             status = pal_plat_osGetRtcTime(&currentTime);
00311             TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00312 
00313             TEST_ASSERT_TRUE((currentTime - ACCEPTABLE_DELAY_IN_SEC) <= PAL_TEST_START_TIME);
00314          }
00315     }
00316     #endif
00317 }
00318 
00319 // the following function is not part of PAL's external API hence extern
00320 extern palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead);
00321 
00322 /*! \brief Test random buffer generation with sotp
00323 *
00324 * | # |    Step                                                        |  Expected   |
00325 * |---|----------------------------------------------------------------|-------------|
00326 * | 1 | Save a fixed seed to sotp or read current value is exists.     | PAL_SUCCESS |
00327 * | 2 | Generate short & long term seed.                               | PAL_SUCCESS |
00328 * | 3 | Generate expected random.                                      | PAL_SUCCESS |
00329 * | 4 | Call pal_osRandomBuffer and compare expected to actual random. | PAL_SUCCESS |
00330 * | 5 | Validate counter and next (boot) long term seed.               | PAL_SUCCESS |
00331 */
00332 TEST(pal_SOTP, random)
00333 {
00334     palStatus_t status;
00335     sotp_result_e res;
00336     uint16_t bytesRead = 0;
00337     uint32_t counter = 0;
00338     uint32_t counterCopy = 0;
00339     uint8_t buf[(PAL_INITIAL_RANDOM_SIZE * 2 + sizeof(counter))] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 };
00340     bool sotpRandomExists = false;
00341 
00342 #if !PAL_USE_HW_TRNG
00343     uint16_t bitsRead = 0;
00344     int32_t noiseBuffer[PAL_NOISE_BUFFER_LEN] = { 0 };
00345     pal_noiseRead(noiseBuffer, true, &bitsRead);
00346 #endif // !PAL_USE_HW_TRNG
00347 
00348     /*#1*/
00349     res = sotp_get(SOTP_TYPE_RANDOM_SEED, (PAL_INITIAL_RANDOM_SIZE + sizeof(counter)), (uint32_t*)buf, &bytesRead); // read 48 drbg bytes + 4 counter bytes
00350     TEST_ASSERT_TRUE(SOTP_SUCCESS == res || SOTP_NOT_FOUND == res);
00351     if (SOTP_SUCCESS == res)
00352     {
00353         memcpy((void*)&counter, (void*)&buf[PAL_INITIAL_RANDOM_SIZE], sizeof(counter));
00354         sotpRandomExists = true;
00355     }
00356     else if (SOTP_NOT_FOUND == res)
00357     {
00358         memset((void*)buf, 7, PAL_INITIAL_RANDOM_SIZE); // fixed dummy seed
00359         res = sotp_set(SOTP_TYPE_RANDOM_SEED, PAL_INITIAL_RANDOM_SIZE, (uint32_t*)buf);
00360         TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, res);
00361     }
00362 
00363     /*#2*/
00364     status = pal_CtrDRBGInit(&g_drbgCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE);
00365     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00366     memset((void*)buf, 0, sizeof(buf));
00367     status = pal_CtrDRBGGenerate(g_drbgCtx, (unsigned char*)buf, PAL_INITIAL_RANDOM_SIZE * 2); // generate 48 bytes long term & 48 bytes short term seed
00368     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00369     status = pal_CtrDRBGFree(&g_drbgCtx);
00370     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00371     g_drbgCtx = NULLPTR;
00372 
00373     /*#3*/
00374     status = pal_CtrDRBGInit(&g_drbgCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE);
00375     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00376     memset((void*)buf, 0, PAL_INITIAL_RANDOM_SIZE);
00377     status = pal_CtrDRBGGenerate(g_drbgCtx, (unsigned char*)buf, PAL_INITIAL_RANDOM_SIZE); // generate expected random buffer
00378     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00379     status = pal_CtrDRBGFree(&g_drbgCtx);
00380     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00381     g_drbgCtx = NULLPTR;
00382 
00383     /*#4*/
00384     uint8_t random[PAL_INITIAL_RANDOM_SIZE] = { 0 };
00385     status = pal_osRandomBuffer(random, PAL_INITIAL_RANDOM_SIZE); // get the actual random buffer
00386     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
00387 #if !PAL_USE_HW_TRNG
00388     TEST_ASSERT_EQUAL_MEMORY(buf, random, PAL_INITIAL_RANDOM_SIZE);
00389 #endif // !PAL_USE_HW_TRNG
00390 
00391     /*#5*/
00392     memmove(&buf[(PAL_INITIAL_RANDOM_SIZE + sizeof(counter))], &buf[PAL_INITIAL_RANDOM_SIZE], PAL_INITIAL_RANDOM_SIZE); // make space for the counter while preserving next seed bytes
00393     memset((void*)buf, 0, (PAL_INITIAL_RANDOM_SIZE + sizeof(counter)));
00394     counterCopy = counter;
00395     res = sotp_get(SOTP_TYPE_RANDOM_SEED, (PAL_INITIAL_RANDOM_SIZE + sizeof(counter)), (uint32_t*)buf, &bytesRead);
00396     TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, res);
00397     TEST_ASSERT_EQUAL((PAL_INITIAL_RANDOM_SIZE + sizeof(counter)), bytesRead);
00398     memcpy((void*)&counter, (void*)&buf[PAL_INITIAL_RANDOM_SIZE], sizeof(counter)); // read the counter from sotp data
00399     TEST_ASSERT_EQUAL(counterCopy + 1, counter);
00400 #if !PAL_USE_HW_TRNG
00401     TEST_ASSERT_EQUAL_MEMORY(&buf[(PAL_INITIAL_RANDOM_SIZE + sizeof(counter))], buf, PAL_INITIAL_RANDOM_SIZE);
00402 #endif // !PAL_USE_HW_TRNG
00403 
00404     if (false == sotpRandomExists)
00405     {
00406         res = sotp_delete(SOTP_TYPE_RANDOM_SEED);
00407         TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, res);
00408     }
00409 }