Simulated product dispenser
Fork of mbed-cloud-workshop-connect-HTS221 by
pal_rtos.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 <stdio.h> 00018 #include "pal.h" 00019 #include "pal_plat_rtos.h" 00020 #include "sotp.h" 00021 00022 //! Store the last saved time in SOTP (ram) for quick access 00023 PAL_PRIVATE uint64_t g_lastSavedTimeInSec = 0; 00024 00025 //! static variables for Random functionality. 00026 //! CTR-DRBG context to be used for generating random numbers from given seed 00027 static palCtrDrbgCtxHandle_t s_ctrDRBGCtx = NULLPTR; 00028 00029 PAL_PRIVATE palStatus_t pal_setWeakTimeForward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime); 00030 PAL_PRIVATE palStatus_t pal_setWeakTimeBackward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime); 00031 00032 static uint64_t g_palDeviceBootTimeInSec = 0; 00033 00034 /* 00035 * Here we define const keys for RoT derivation algorithm. 00036 * Must be 16 characters or less 00037 */ 00038 #define PAL_STORAGE_SIGNATURE_128_BIT_KEY "RoTStorageSgn128" 00039 #define PAL_STORAGE_ENCRYPTION_128_BIT_KEY "RoTStorageEnc128" 00040 #define PAL_STORAGE_ENCRYPTION_256_BIT_KEY "StorageEnc256HMACSHA256SIGNATURE" 00041 00042 PAL_PRIVATE bool palRTOSInitialized = false; 00043 00044 #if (PAL_SIMULATE_RTOS_REBOOT == 1) 00045 #include <unistd.h> 00046 extern char *program_invocation_name; 00047 #endif 00048 00049 #define PAL_NOISE_WAIT_FOR_WRITERS_DELAY_MILLI_SEC 1 00050 #define PAL_NOISE_BITS_TO_BYTES(x) (x / CHAR_BIT) 00051 00052 typedef struct palNoise 00053 { 00054 int32_t buffer[PAL_NOISE_BUFFER_LEN]; 00055 volatile uint32_t bitCountAllocated; 00056 volatile uint32_t bitCountActual; 00057 volatile uint32_t numWriters; 00058 volatile bool isReading; 00059 } palNoise_t; 00060 00061 PAL_PRIVATE palNoise_t g_noise; 00062 00063 palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten); // forward declaration 00064 palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead); // forward declaration 00065 00066 #if PAL_USE_HW_TRNG 00067 PAL_PRIVATE palThreadID_t g_trngThreadID = NULLPTR; 00068 #endif 00069 00070 extern palStatus_t pal_plat_CtrDRBGGenerateWithAdditional(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len, unsigned char* additional, size_t additionalLen); 00071 00072 //Error Translation from SOTP module to PAL 00073 PAL_PRIVATE palStatus_t pal_osSotpErrorTranslation(sotp_result_e err) 00074 { 00075 palStatus_t ret; 00076 switch(err) 00077 { 00078 case SOTP_BAD_VALUE: 00079 ret = PAL_ERR_INVALID_ARGUMENT ; 00080 break; 00081 00082 case SOTP_BUFF_TOO_SMALL: 00083 ret = PAL_ERR_BUFFER_TOO_SMALL ; 00084 break; 00085 00086 case SOTP_BUFF_NOT_ALIGNED: 00087 ret = PAL_ERR_RTOS_BUFFER_NOT_ALIGNED ; 00088 break; 00089 00090 case SOTP_READ_ERROR: 00091 case SOTP_DATA_CORRUPT: 00092 case SOTP_OS_ERROR: 00093 default: 00094 ret = PAL_ERR_GENERIC_FAILURE; 00095 break; 00096 } 00097 return ret; 00098 } 00099 00100 palStatus_t pal_RTOSInitialize(void* opaqueContext) 00101 { 00102 palStatus_t status = PAL_SUCCESS; 00103 if (palRTOSInitialized) 00104 { 00105 return status; 00106 } 00107 00108 status = pal_plat_RTOSInitialize (opaqueContext); 00109 if (PAL_SUCCESS == status) 00110 { 00111 memset(g_noise.buffer, 0, PAL_NOISE_SIZE_BYTES); 00112 g_noise.bitCountActual = g_noise.bitCountAllocated = 0; 00113 g_noise.numWriters = 0; 00114 g_noise.isReading = false; 00115 #if PAL_USE_HW_TRNG 00116 g_trngThreadID = NULLPTR; 00117 #endif 00118 palRTOSInitialized = true; 00119 } 00120 else 00121 { 00122 PAL_LOG(ERR, "pal_RTOSInitialize: pal_plat_RTOSInitialize failed, status=%" PRIx32 "\n", status); 00123 } 00124 return status; 00125 } 00126 00127 palStatus_t pal_RTOSDestroy(void) 00128 { 00129 palStatus_t status = PAL_ERR_NOT_INITIALIZED ; 00130 if (!palRTOSInitialized) 00131 { 00132 return status; 00133 } 00134 00135 #if PAL_USE_HW_TRNG 00136 if (NULLPTR != g_trngThreadID) 00137 { 00138 if (PAL_SUCCESS != pal_osThreadTerminate(&g_trngThreadID)) 00139 { 00140 PAL_LOG(ERR, "pal_RTOSDestroy: failed to terminate trng noise thread\n"); 00141 } 00142 } 00143 #endif 00144 00145 if (NULLPTR != s_ctrDRBGCtx) 00146 { 00147 status = pal_CtrDRBGFree(&s_ctrDRBGCtx); 00148 if (PAL_SUCCESS != status) 00149 { 00150 PAL_LOG(ERR, "pal_RTOSDestroy: pal_CtrDRBGFree failed, status=%" PRIx32 "\n", status); 00151 } 00152 } 00153 00154 status = pal_plat_RTOSDestroy (); 00155 if (PAL_SUCCESS != status) 00156 { 00157 PAL_LOG(ERR, "pal_RTOSDestroy: pal_plat_RTOSDestroy failed, status=%" PRIx32 "\n", status); 00158 } 00159 palRTOSInitialized = false; 00160 return status; 00161 } 00162 00163 void pal_osReboot(void) 00164 { 00165 PAL_LOG(INFO, "pal_osReboot\r\n"); 00166 #if (PAL_USE_APPLICATION_REBOOT) 00167 pal_plat_osApplicationReboot (); 00168 #else 00169 //Simulator is currently for Linux only 00170 #if (PAL_SIMULATE_RTOS_REBOOT == 1) 00171 const char *argv[] = {"0" , 0}; 00172 char *const envp[] = { 0 }; 00173 argv[0] = program_invocation_name; 00174 00175 PAL_LOG(INFO, "pal_osReboot -> simulated reboot with execve(%s).\r\n", argv[0]); 00176 00177 if (-1 == execve(argv[0], (char **)argv , envp)) 00178 { 00179 PAL_LOG(ERR,"child process execve failed [%s]",argv[0]); 00180 } 00181 #else 00182 PAL_LOG(INFO, "Rebooting the system\r\n"); 00183 pal_plat_osReboot (); 00184 #endif 00185 #endif 00186 } 00187 00188 uint64_t pal_osKernelSysTick(void) 00189 { 00190 static uint64_t lastValue = 0; 00191 static uint64_t wraparoundsDetected = 0; 00192 const uint64_t one = 1; 00193 uint64_t tics = pal_plat_osKernelSysTick (); 00194 uint64_t tmp = tics + (wraparoundsDetected << 32); 00195 00196 if (tmp < lastValue) //erez's "wraparound algorithm" if we detect a wrap around add 1 to the higher 32 bits 00197 { 00198 tmp = tmp + (one << 32); 00199 wraparoundsDetected++; 00200 } 00201 lastValue = tmp; 00202 return (uint64_t)tmp; 00203 } 00204 00205 uint64_t pal_osKernelSysTickMicroSec(uint64_t microseconds) 00206 { 00207 uint64_t result; 00208 result = pal_plat_osKernelSysTickMicroSec (microseconds); 00209 return result; 00210 } 00211 00212 uint64_t pal_osKernelSysMilliSecTick(uint64_t sysTicks) 00213 { 00214 uint64_t result = 0; 00215 uint64_t osTickFreq = pal_plat_osKernelSysTickFrequency (); 00216 if ((sysTicks) && (osTickFreq)) // > 0 00217 { 00218 result = (uint64_t)((sysTicks) * PAL_TICK_TO_MILLI_FACTOR / osTickFreq); //convert ticks per second to milliseconds 00219 } 00220 00221 return result; 00222 } 00223 00224 uint64_t pal_osKernelSysTickFrequency(void) 00225 { 00226 uint64_t result; 00227 result = pal_plat_osKernelSysTickFrequency (); 00228 return result; 00229 } 00230 00231 palStatus_t pal_osThreadCreateWithAlloc(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadLocalStore_t* store, palThreadID_t* threadID) 00232 { 00233 PAL_VALIDATE_ARGUMENTS((NULL == function) || (PAL_osPrioritylast < priority) || (PAL_osPriorityError == priority) || (0 == stackSize) || (NULL == threadID)); 00234 if (store) 00235 { 00236 PAL_LOG(ERR, "thread storage in not supported\n"); 00237 return PAL_ERR_NOT_SUPPORTED ; 00238 } 00239 palStatus_t status = pal_plat_osThreadCreate (function, funcArgument, priority, stackSize, threadID); 00240 return status; 00241 } 00242 00243 palStatus_t pal_osThreadTerminate(palThreadID_t* threadID) 00244 { 00245 PAL_VALIDATE_ARGUMENTS ((NULL == threadID) || (PAL_INVALID_THREAD == *threadID)); 00246 palStatus_t status = pal_plat_osThreadTerminate (threadID); 00247 return status; 00248 } 00249 00250 palThreadID_t pal_osThreadGetId(void) 00251 { 00252 palThreadID_t threadID = pal_plat_osThreadGetId (); 00253 return threadID; 00254 } 00255 00256 palStatus_t pal_osDelay(uint32_t milliseconds) 00257 { 00258 palStatus_t status; 00259 status = pal_plat_osDelay (milliseconds); 00260 return status; 00261 } 00262 00263 palStatus_t pal_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID) 00264 { 00265 PAL_VALIDATE_ARGUMENTS(NULL == timerID || NULL == function); 00266 palStatus_t status; 00267 status = pal_plat_osTimerCreate (function, funcArgument, timerType, timerID); 00268 return status; 00269 } 00270 00271 palStatus_t pal_osTimerStart(palTimerID_t timerID, uint32_t millisec) 00272 { 00273 PAL_VALIDATE_ARGUMENTS (NULLPTR == timerID); 00274 palStatus_t status; 00275 if (0 == millisec) 00276 { 00277 return PAL_ERR_RTOS_VALUE ; 00278 } 00279 status = pal_plat_osTimerStart (timerID, millisec); 00280 return status; 00281 } 00282 00283 palStatus_t pal_osTimerStop(palTimerID_t timerID) 00284 { 00285 PAL_VALIDATE_ARGUMENTS(NULLPTR == timerID); 00286 palStatus_t status; 00287 status = pal_plat_osTimerStop (timerID); 00288 return status; 00289 } 00290 00291 palStatus_t pal_osTimerDelete(palTimerID_t* timerID) 00292 { 00293 PAL_VALIDATE_ARGUMENTS(NULL == timerID || NULLPTR == *timerID); 00294 palStatus_t status; 00295 status = pal_plat_osTimerDelete (timerID); 00296 return status; 00297 } 00298 00299 palStatus_t pal_osMutexCreate(palMutexID_t* mutexID) 00300 { 00301 PAL_VALIDATE_ARGUMENTS(NULL == mutexID); 00302 palStatus_t status; 00303 status = pal_plat_osMutexCreate (mutexID); 00304 return status; 00305 } 00306 00307 palStatus_t pal_osMutexWait(palMutexID_t mutexID, uint32_t millisec) 00308 { 00309 PAL_VALIDATE_ARGUMENTS((NULLPTR == mutexID)); 00310 palStatus_t status; 00311 status = pal_plat_osMutexWait (mutexID, millisec); 00312 return status; 00313 } 00314 00315 palStatus_t pal_osMutexRelease(palMutexID_t mutexID) 00316 { 00317 PAL_VALIDATE_ARGUMENTS(NULLPTR == mutexID); 00318 palStatus_t status; 00319 status = pal_plat_osMutexRelease (mutexID); 00320 return status; 00321 } 00322 00323 palStatus_t pal_osMutexDelete(palMutexID_t* mutexID) 00324 { 00325 PAL_VALIDATE_ARGUMENTS(NULL == mutexID || NULLPTR == *mutexID); 00326 palStatus_t status; 00327 status = pal_plat_osMutexDelete (mutexID); 00328 return status; 00329 } 00330 00331 palStatus_t pal_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID) 00332 { 00333 PAL_VALIDATE_ARGUMENTS(NULL == semaphoreID); 00334 palStatus_t status; 00335 status = pal_plat_osSemaphoreCreate (count, semaphoreID); 00336 return status; 00337 } 00338 00339 palStatus_t pal_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable) 00340 { 00341 PAL_VALIDATE_ARGUMENTS(NULLPTR == semaphoreID); 00342 palStatus_t status; 00343 status = pal_plat_osSemaphoreWait (semaphoreID, millisec, countersAvailable); 00344 return status; 00345 } 00346 00347 palStatus_t pal_osSemaphoreRelease(palSemaphoreID_t semaphoreID) 00348 { 00349 PAL_VALIDATE_ARGUMENTS(NULLPTR == semaphoreID); 00350 palStatus_t status; 00351 status = pal_plat_osSemaphoreRelease (semaphoreID); 00352 return status; 00353 } 00354 00355 palStatus_t pal_osSemaphoreDelete(palSemaphoreID_t* semaphoreID) 00356 { 00357 PAL_VALIDATE_ARGUMENTS(NULL == semaphoreID || NULLPTR == *semaphoreID); 00358 palStatus_t status; 00359 status = pal_plat_osSemaphoreDelete (semaphoreID); 00360 return status; 00361 } 00362 00363 00364 int32_t pal_osAtomicIncrement(int32_t* valuePtr, int32_t increment) 00365 { 00366 PAL_VALIDATE_ARGUMENTS(NULL == valuePtr); 00367 int32_t result; 00368 result = pal_plat_osAtomicIncrement (valuePtr, increment); 00369 return result; 00370 } 00371 00372 00373 PAL_PRIVATE uint64_t pal_sysTickTimeToSec() 00374 { 00375 uint64_t sysTicksFromBoot = pal_osKernelSysTick(); 00376 uint64_t secFromBoot = pal_osKernelSysMilliSecTick(sysTicksFromBoot) / PAL_MILLI_PER_SECOND; 00377 00378 return secFromBoot; 00379 } 00380 00381 uint64_t pal_osGetTime(void) 00382 { 00383 uint64_t curSysTimeInSec = 0; 00384 if (0 < g_palDeviceBootTimeInSec) //time was previously set 00385 { 00386 uint64_t secFromBoot = pal_sysTickTimeToSec(); 00387 curSysTimeInSec = g_palDeviceBootTimeInSec + secFromBoot; //boot time in sec + sec passed since boot 00388 00389 if((curSysTimeInSec > g_lastSavedTimeInSec) && (curSysTimeInSec - g_lastSavedTimeInSec > PAL_LAST_SAVED_TIME_LATENCY_SEC)) 00390 { 00391 sotp_result_e status = SOTP_SUCCESS; 00392 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&curSysTimeInSec); 00393 if (SOTP_SUCCESS != status) 00394 { 00395 PAL_LOG(ERR,"SOTP set time failed \n"); 00396 } 00397 else 00398 { 00399 g_lastSavedTimeInSec = curSysTimeInSec; 00400 } 00401 00402 } 00403 } 00404 00405 return curSysTimeInSec; 00406 } 00407 00408 palStatus_t pal_osSetTime(uint64_t seconds) 00409 { 00410 palStatus_t status = PAL_SUCCESS; 00411 if(0 == seconds) 00412 { 00413 g_palDeviceBootTimeInSec = 0; 00414 } 00415 else if (seconds < (uint64_t)PAL_MIN_SEC_FROM_EPOCH) 00416 { 00417 status = PAL_ERR_INVALID_TIME ; 00418 } 00419 else 00420 { 00421 uint64_t secFromBoot = pal_sysTickTimeToSec(); 00422 g_palDeviceBootTimeInSec = seconds - secFromBoot; //update device boot time 00423 } 00424 00425 return status; 00426 } 00427 00428 00429 00430 #if PAL_USE_HW_TRNG 00431 PAL_PRIVATE void pal_trngNoiseThreadFunc(void const* arg) 00432 { 00433 uint8_t buf[PAL_NOISE_SIZE_BYTES] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 }; 00434 size_t trngBytesRead = 0; 00435 uint16_t noiseBitsWritten = 0; 00436 palStatus_t status; 00437 while (true) 00438 { 00439 status = pal_plat_osRandomBuffer (buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead); 00440 if ((0 < trngBytesRead) && ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status))) 00441 { 00442 noiseBitsWritten = 0; 00443 status = pal_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWritten); 00444 } 00445 pal_osDelay(PAL_NOISE_TRNG_THREAD_DELAY_MILLI_SEC); 00446 } 00447 } 00448 #endif // PAL_USE_HW_TRNG 00449 00450 00451 // this function generates drbg with the possibility of adding noise as additional input to the drbg function. 00452 PAL_PRIVATE palStatus_t pal_generateDrbgWithNoiseAttempt(palCtrDrbgCtxHandle_t drbgContext, uint8_t* outBuffer, bool partial, size_t numBytesToGenerate) 00453 { 00454 uint16_t bitsRead = 0; 00455 int32_t buffer[PAL_NOISE_BUFFER_LEN] = { 0 }; 00456 palStatus_t status = pal_noiseRead(buffer, partial, &bitsRead); 00457 if (PAL_SUCCESS == status) 00458 { 00459 status = pal_plat_CtrDRBGGenerateWithAdditional(drbgContext, (unsigned char*)outBuffer, numBytesToGenerate, (unsigned char*)buffer, (size_t)PAL_NOISE_BITS_TO_BYTES(bitsRead)); 00460 } 00461 else 00462 { 00463 status = pal_CtrDRBGGenerate(drbgContext, (unsigned char*)outBuffer, numBytesToGenerate); 00464 } 00465 return status; 00466 } 00467 00468 palStatus_t pal_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes) 00469 { 00470 PAL_VALIDATE_ARGUMENTS (NULL == randomBuf); 00471 00472 palStatus_t status = PAL_ERR_GENERIC_FAILURE; 00473 if (palRTOSInitialized == true) 00474 { 00475 if (NULLPTR == s_ctrDRBGCtx) 00476 { 00477 uint32_t sotpCounter = 0; 00478 uint8_t buf[(PAL_INITIAL_RANDOM_SIZE * 2 + sizeof(sotpCounter))] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 }; // space for 48 bytes short term + 48 bytes long term + 4 counter bytes (note this buffer will also be used to collect TRNG noise) 00479 const uint16_t sotpLenBytes = PAL_INITIAL_RANDOM_SIZE + sizeof(sotpCounter); // the max number of bytes expected to be read/written form/to sotp, note that sotpCounter will probably be empty the 1st time data is read from sotp 00480 uint32_t* ptrSotpRead = (uint32_t*)&buf; // pointer to the memory address in buf which will point to the data that will be read from sotp 00481 uint32_t* ptrSotpWrite = (uint32_t*)&buf[PAL_INITIAL_RANDOM_SIZE]; // pointer to the memory address in buf which will point to the data which needs to be written back to sotp 00482 uint32_t* ptrSotpCounterRead = ptrSotpWrite; // pointer to the memory address in buf which will point to the counter read from sotp 00483 uint32_t* ptrSotpCounterWrite = (uint32_t*)&buf[PAL_INITIAL_RANDOM_SIZE * 2]; // pointer to the memory address in buf which will point to the incremented counter which will be written back to sotp 00484 uint16_t sotpBytesRead = 0, noiseBitsWrittern = 0; 00485 size_t trngBytesRead = 0; 00486 palCtrDrbgCtxHandle_t longCtrDRBGCtx = NULLPTR; // long term drbg context 00487 palStatus_t tmpStatus; 00488 sotp_result_e sotpResult = sotp_get(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpRead, &sotpBytesRead); // read 48 drbg bytes + 4 counter bytes 00489 if (SOTP_SUCCESS == sotpResult) 00490 { 00491 if ((PAL_INITIAL_RANDOM_SIZE != sotpBytesRead) && (sotpLenBytes != sotpBytesRead)) 00492 { 00493 status = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00494 PAL_LOG(ERR, "Invalid number of bytes read from sotp, bytes read=%" PRIu16, sotpBytesRead); 00495 goto finish; 00496 } 00497 status = pal_CtrDRBGInit(&longCtrDRBGCtx, ptrSotpRead, PAL_INITIAL_RANDOM_SIZE); // initialize long term drbg with the seed that was read from sotp 00498 if (PAL_SUCCESS != status) 00499 { 00500 PAL_LOG(ERR, "Failed to initialize long term drbg context, status=%" PRIx32 "\n", status); 00501 goto finish; 00502 } 00503 memcpy((void*)&sotpCounter, (void*)ptrSotpCounterRead, sizeof(sotpCounter)); // read the counter from the buffer (sotp data) to local var 00504 #if PAL_USE_HW_TRNG 00505 memset((void*)buf, 0, sizeof(buf)); 00506 status = pal_plat_osRandomBuffer (buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead); 00507 if ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status)) 00508 { 00509 if (0 < trngBytesRead) 00510 { 00511 tmpStatus = pal_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWrittern); // write whatever was collected from trng to the noise buffer 00512 PAL_LOG(DBG, "Write trng to noise buffer, status=%" PRIx32 ", bits writtern=%" PRIu16 "\n", tmpStatus, noiseBitsWrittern); 00513 } 00514 } 00515 else 00516 { 00517 PAL_LOG(ERR, "Read from TRNG failed, status=%" PRIx32 "\n", status); 00518 } 00519 #endif // PAL_USE_HW_TRNG 00520 memset((void*)buf, 0, sizeof(buf)); 00521 status = pal_generateDrbgWithNoiseAttempt(longCtrDRBGCtx, buf, true, (PAL_INITIAL_RANDOM_SIZE * 2)); // generate 96 bytes, the 1st 48 bytes will be used for short term drbg and the other 48 bytes will be used for long term drbg 00522 if (PAL_SUCCESS != status) 00523 { 00524 PAL_LOG(ERR, "Failed to gererate drbg long term and short term seeds, status=%" PRIx32 "\n", status); 00525 goto drbg_cleanup; 00526 } 00527 sotpCounter++; // increment counter before writting it back to sotp 00528 memcpy((void*)ptrSotpCounterWrite, (void*)&sotpCounter, sizeof(sotpCounter)); // copy the incremented counter to the last 4 bytes of the buffer 00529 sotpResult = sotp_set(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpWrite); // write 48 long term drbg bytes + 4 counter bytes 00530 if (SOTP_SUCCESS != sotpResult) 00531 { 00532 PAL_LOG(ERR, "Failed to write to sotp, sotp result=%d", sotpResult); 00533 status = PAL_ERR_GENERIC_FAILURE; 00534 } 00535 drbg_cleanup: 00536 { 00537 tmpStatus = pal_CtrDRBGFree(&longCtrDRBGCtx); 00538 if (PAL_SUCCESS != tmpStatus) 00539 { 00540 PAL_LOG(ERR, "Failed to free long term drbg context, status=%" PRIx32 "\n", tmpStatus); 00541 } 00542 longCtrDRBGCtx = NULLPTR; 00543 if (PAL_SUCCESS != status) 00544 { 00545 goto finish; 00546 } 00547 #if PAL_USE_HW_TRNG 00548 status = pal_osThreadCreateWithAlloc(pal_trngNoiseThreadFunc, NULL, PAL_osPriorityReservedTRNG, PAL_NOISE_TRNG_THREAD_STACK_SIZE, NULL, &g_trngThreadID); 00549 if (PAL_SUCCESS != status) 00550 { 00551 PAL_LOG(ERR, "Failed to create noise trng thread, status=%" PRIx32 "\n", tmpStatus); 00552 } 00553 #endif // PAL_USE_HW_TRNG 00554 } 00555 } 00556 else if (SOTP_NOT_FOUND == sotpResult) 00557 { 00558 #if PAL_USE_HW_TRNG 00559 memset((void*)buf, 0, sizeof(buf)); 00560 uint8_t* seedPtr = buf; 00561 size_t randomCounterBytes = 0; 00562 do 00563 { 00564 status = pal_plat_osRandomBuffer (seedPtr, PAL_INITIAL_RANDOM_SIZE - randomCounterBytes, &trngBytesRead); 00565 if (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status) 00566 { 00567 pal_osDelay(PAL_TRNG_COLLECT_DELAY_MILLI_SEC); // sleep to let the device to collect random data. 00568 randomCounterBytes += trngBytesRead; 00569 seedPtr += trngBytesRead; 00570 } 00571 } while (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status); 00572 #endif // PAL_USE_HW_TRNG 00573 } 00574 if (PAL_SUCCESS != status) 00575 { 00576 goto finish; 00577 } 00578 status = pal_CtrDRBGInit(&s_ctrDRBGCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE); 00579 if (PAL_SUCCESS != status) 00580 { 00581 PAL_LOG(ERR, "Failed to initialize short term drbg context, status=%" PRIx32 "\n", status); 00582 goto finish; 00583 } 00584 } 00585 status = pal_generateDrbgWithNoiseAttempt(s_ctrDRBGCtx, randomBuf, false, bufSizeBytes); 00586 if (PAL_SUCCESS != status) 00587 { 00588 PAL_LOG(ERR, "Failed to gererate random, status=%" PRIx32 "\n", status); 00589 } 00590 } 00591 else 00592 { 00593 return PAL_ERR_NOT_INITIALIZED ; 00594 } 00595 finish: 00596 return status; 00597 } 00598 00599 palStatus_t pal_osRandom32bit(uint32_t *random) 00600 { 00601 palStatus_t status = PAL_SUCCESS; 00602 00603 PAL_VALIDATE_ARGUMENTS(NULL == random); 00604 00605 status = pal_osRandomBuffer((uint8_t*)random, sizeof(uint32_t)); 00606 return status; 00607 } 00608 00609 00610 PAL_PRIVATE palStatus_t pal_osGetRoT(uint8_t * key,size_t keyLenBytes) 00611 { 00612 palStatus_t palStatus = PAL_SUCCESS; 00613 #if (PAL_USE_HW_ROT) 00614 palStatus = pal_plat_osGetRoTFromHW (key, keyLenBytes); 00615 #else 00616 sotp_result_e sotpStatus = SOTP_SUCCESS; 00617 uint16_t actual_size; 00618 sotpStatus = sotp_get(SOTP_TYPE_ROT, keyLenBytes, (uint32_t *)key, &actual_size); 00619 if (SOTP_NOT_FOUND == sotpStatus) 00620 { 00621 palStatus = pal_osRandomBuffer(key , keyLenBytes); 00622 if (PAL_SUCCESS == palStatus) 00623 { 00624 sotpStatus = sotp_set(SOTP_TYPE_ROT,keyLenBytes, (uint32_t *)key); 00625 } 00626 } 00627 if (SOTP_SUCCESS != sotpStatus) 00628 { 00629 palStatus = pal_osSotpErrorTranslation(sotpStatus); 00630 } 00631 #endif 00632 return palStatus; 00633 } 00634 00635 palStatus_t pal_osGetDeviceKey(palDevKeyType_t keyType, uint8_t *key, size_t keyLenBytes) 00636 { 00637 palStatus_t status = PAL_SUCCESS; 00638 uint8_t rotBuffer[PAL_DEVICE_KEY_SIZE_IN_BYTES] __attribute__ ((aligned(4))) = {0}; 00639 00640 00641 PAL_VALIDATE_CONDITION_WITH_ERROR(((keyLenBytes < PAL_DEVICE_KEY_SIZE_IN_BYTES) || ((palOsStorageHmacSha256 == keyType) && (keyLenBytes < PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES))),PAL_ERR_BUFFER_TOO_SMALL ) 00642 00643 PAL_VALIDATE_CONDITION_WITH_ERROR ((NULL == key),PAL_ERR_NULL_POINTER ) 00644 00645 status = pal_osGetRoT(rotBuffer, keyLenBytes); 00646 if (PAL_SUCCESS == status) 00647 { // Logic of RoT according to key type using 128 bit strong Key Derivation Algorithm 00648 00649 #if (PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC == 1) //calculate the key derivation in an old way 00650 switch(keyType) 00651 { 00652 case palOsStorageEncryptionKey128Bit: 00653 { 00654 //USE strong KDF here! 00655 status = pal_cipherCMAC((const unsigned char*)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 00656 break; 00657 } 00658 case palOsStorageSignatureKey128Bit : 00659 { 00660 //USE strong KDF here! 00661 status = pal_cipherCMAC((const unsigned char *)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 00662 break; 00663 } 00664 case palOsStorageHmacSha256 : 00665 { 00666 size_t outputLenInBytes = 0; 00667 status = pal_mdHmacSha256((const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes); 00668 break; 00669 } 00670 default: 00671 status = PAL_ERR_GET_DEV_KEY ; 00672 } //switch end 00673 #else //calculate the key derivation in a new way 00674 switch(keyType) 00675 { 00676 case palOsStorageEncryptionKey128Bit: 00677 { 00678 //USE strong KDF here! 00679 status = pal_cipherCMAC((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 00680 break; 00681 } 00682 case palOsStorageSignatureKey128Bit : 00683 { 00684 //USE strong KDF here! 00685 status = pal_cipherCMAC((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BYTES, key); 00686 break; 00687 } 00688 case palOsStorageHmacSha256 : 00689 { 00690 size_t outputLenInBytes = 0; 00691 status = pal_mdHmacSha256((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes); 00692 break; 00693 } 00694 default: 00695 status = PAL_ERR_GET_DEV_KEY ; 00696 } //switch end 00697 #endif 00698 00699 } // outer if 00700 else 00701 { 00702 status = PAL_ERR_GET_DEV_KEY ; 00703 } 00704 00705 return status; 00706 00707 } 00708 00709 palStatus_t pal_initTime(void) 00710 { 00711 uint64_t rtcTime = 0; 00712 uint64_t sotpGetTime = 0, sotpLastTimeBack = 0; 00713 palStatus_t ret = PAL_SUCCESS; 00714 sotp_result_e status = SOTP_SUCCESS; 00715 uint16_t actualLenBytes = 0; 00716 00717 status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes); 00718 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 00719 { 00720 ret = pal_osSotpErrorTranslation(status); 00721 } 00722 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 00723 { 00724 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00725 } 00726 00727 status = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpLastTimeBack, &actualLenBytes); 00728 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 00729 { 00730 ret = pal_osSotpErrorTranslation(status); 00731 } 00732 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 00733 { 00734 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00735 } 00736 00737 if (sotpLastTimeBack > sotpGetTime) 00738 {//Enter here only when reset occurs during set weak or strong time 00739 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&sotpLastTimeBack); 00740 if (SOTP_SUCCESS != status) 00741 { 00742 ret = pal_osSotpErrorTranslation(status); 00743 } 00744 sotpGetTime = sotpLastTimeBack; 00745 } 00746 g_lastSavedTimeInSec = sotpGetTime; 00747 00748 #if (PAL_USE_HW_RTC) 00749 if (PAL_SUCCESS == ret) 00750 { 00751 ret = pal_plat_osGetRtcTime(&rtcTime); 00752 } 00753 #endif 00754 00755 if (PAL_SUCCESS == ret) 00756 {//set the max time as boot time of the device 00757 pal_osSetTime(PAL_MAX(rtcTime, sotpGetTime)); 00758 } 00759 return ret; 00760 } 00761 00762 00763 palStatus_t pal_osSetStrongTime(uint64_t setNewTimeInSeconds) 00764 { 00765 palStatus_t ret = PAL_SUCCESS; 00766 00767 uint64_t getSotpTimeValue = 0; 00768 uint16_t actualLenBytes = 0; 00769 sotp_result_e status = SOTP_SUCCESS; 00770 00771 #if (PAL_USE_HW_RTC) 00772 //RTC Time Latency 00773 if (PAL_SUCCESS == ret) 00774 { 00775 uint64_t getRtcTimeValue = 0; 00776 ret = pal_plat_osGetRtcTime(&getRtcTimeValue); 00777 if (PAL_SUCCESS == ret) 00778 { 00779 if(llabs(setNewTimeInSeconds - getRtcTimeValue) > PAL_MINIMUM_RTC_LATENCY_SEC) 00780 { 00781 ret = pal_plat_osSetRtcTime(setNewTimeInSeconds); 00782 } 00783 } 00784 } 00785 #endif 00786 00787 status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes); 00788 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 00789 { 00790 ret = pal_osSotpErrorTranslation(status); 00791 } 00792 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 00793 { 00794 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00795 } 00796 else if (((setNewTimeInSeconds > getSotpTimeValue) && (setNewTimeInSeconds - getSotpTimeValue > PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC)) //Forward Time 00797 || ((setNewTimeInSeconds < getSotpTimeValue) && (getSotpTimeValue - setNewTimeInSeconds > PAL_MINIMUM_SOTP_BACKWARD_LATENCY_SEC))) //Backward Time 00798 { 00799 status = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 00800 if (SOTP_SUCCESS != status) 00801 { 00802 ret = pal_osSotpErrorTranslation(status); 00803 } 00804 else 00805 { 00806 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 00807 if (SOTP_SUCCESS != status) 00808 { 00809 ret = pal_osSotpErrorTranslation(status); 00810 } 00811 g_lastSavedTimeInSec = setNewTimeInSeconds; 00812 } 00813 } 00814 00815 if(PAL_SUCCESS == ret) 00816 { 00817 ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM 00818 } 00819 00820 return ret; 00821 } 00822 00823 PAL_PRIVATE palStatus_t pal_setWeakTimeForward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime) 00824 { 00825 sotp_result_e status = SOTP_SUCCESS; 00826 palStatus_t ret = PAL_SUCCESS; 00827 00828 ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM 00829 #if (PAL_USE_HW_RTC) 00830 //RTC Time Forward 00831 if (PAL_SUCCESS == ret) 00832 { 00833 uint64_t getRtcTimeValue = 0; 00834 ret = pal_plat_osGetRtcTime(&getRtcTimeValue); 00835 if (PAL_SUCCESS == ret) 00836 { 00837 if((setNewTimeInSeconds > getRtcTimeValue) && (setNewTimeInSeconds - getRtcTimeValue > PAL_MINIMUM_RTC_LATENCY_SEC)) 00838 { 00839 ret = pal_plat_osSetRtcTime(setNewTimeInSeconds); 00840 } 00841 } 00842 } 00843 #endif// (PAL_USE_HW_RTC) 00844 00845 if ((setNewTimeInSeconds - currentOsTime > PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC) && (PAL_SUCCESS == ret)) 00846 {//SOTP time forward 00847 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 00848 if (SOTP_SUCCESS != status) 00849 { 00850 ret = pal_osSotpErrorTranslation(status); 00851 } 00852 else 00853 { 00854 g_lastSavedTimeInSec = setNewTimeInSeconds; 00855 } 00856 } 00857 return ret; 00858 } 00859 00860 PAL_PRIVATE palStatus_t pal_setWeakTimeBackward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime) 00861 { 00862 uint64_t getSotpTimeValue = 0; 00863 uint16_t actualLenBytes = 0; 00864 sotp_result_e status = SOTP_SUCCESS; 00865 palStatus_t ret = PAL_SUCCESS; 00866 00867 status = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes); 00868 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 00869 { 00870 ret = pal_osSotpErrorTranslation(status); 00871 } 00872 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 00873 { 00874 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00875 } 00876 else if (setNewTimeInSeconds > getSotpTimeValue) 00877 { 00878 if ((setNewTimeInSeconds - getSotpTimeValue) / PAL_RATIO_SECONDS_PER_DAY > (currentOsTime - setNewTimeInSeconds)) 00879 { 00880 status = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 00881 if (SOTP_SUCCESS != status) 00882 { 00883 ret = pal_osSotpErrorTranslation(status); 00884 } 00885 else 00886 { 00887 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 00888 if (SOTP_SUCCESS != status) 00889 { 00890 ret = pal_osSotpErrorTranslation(status); 00891 } 00892 else 00893 { 00894 g_lastSavedTimeInSec = setNewTimeInSeconds; 00895 ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM 00896 } 00897 } 00898 } 00899 } 00900 00901 return ret; 00902 } 00903 00904 palStatus_t pal_osSetWeakTime(uint64_t setNewTimeInSeconds) 00905 { 00906 uint64_t getSotpTimeValue = 0; 00907 uint16_t actualLenBytes = 0; 00908 sotp_result_e status = SOTP_SUCCESS; 00909 palStatus_t ret = PAL_SUCCESS; 00910 uint64_t getOsTimeValue = 0; 00911 00912 getOsTimeValue = pal_osGetTime(); //get current system time 00913 00914 if (setNewTimeInSeconds > getOsTimeValue) 00915 {//Time Forward 00916 ret = pal_setWeakTimeForward(setNewTimeInSeconds, getOsTimeValue); 00917 } 00918 else if (getOsTimeValue > setNewTimeInSeconds) 00919 {//Time Backward 00920 ret = pal_setWeakTimeBackward(setNewTimeInSeconds, getOsTimeValue); 00921 } 00922 00923 if(PAL_SUCCESS == ret) 00924 { 00925 getSotpTimeValue = 0; 00926 status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes); 00927 if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status)) 00928 { 00929 ret = pal_osSotpErrorTranslation(status); 00930 } 00931 else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status)) 00932 { 00933 ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00934 } 00935 else if ((setNewTimeInSeconds > getSotpTimeValue) && (setNewTimeInSeconds - getSotpTimeValue > PAL_MINIMUM_STORAGE_LATENCY_SEC)) 00936 { 00937 status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds); 00938 if (SOTP_SUCCESS != status) 00939 { 00940 ret = pal_osSotpErrorTranslation(status); 00941 } 00942 else 00943 { 00944 g_lastSavedTimeInSec = setNewTimeInSeconds; 00945 } 00946 } 00947 } 00948 return ret; 00949 } 00950 00951 /*! Write a value (either all or specific bits) to the global noise buffer 00952 * 00953 * @param[in] data The value containing the bits to be written. 00954 * @param[in] startBit The index of the first bit to be written, valid values are 0-31. 00955 * @param[in] lenBits The number of bits that should be written (startBit+lenBits must be less than 32). 00956 * @param[out] bitsWritten The number of bits that were actually written. 00957 * 00958 * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. 00959 */ 00960 palStatus_t pal_noiseWriteValue(const int32_t* data, uint8_t startBit, uint8_t lenBits, uint8_t* bitsWritten) 00961 { 00962 PAL_VALIDATE_ARGUMENTS((NULL == data) || (PAL_INT32_BITS - 1 < startBit) || (PAL_INT32_BITS < lenBits + startBit) || (NULL == bitsWritten)); 00963 00964 palStatus_t status = PAL_SUCCESS; 00965 uint16_t incrementedBitCount; 00966 uint8_t currentIndex, occupiedBitsInCurrentIndex, availableBitsInCurrentIndex; 00967 uint32_t mask, value; 00968 00969 *bitsWritten = 0; 00970 if (PAL_NOISE_SIZE_BITS == g_noise.bitCountActual) 00971 { 00972 return PAL_ERR_RTOS_NOISE_BUFFER_FULL ; 00973 } 00974 00975 pal_osAtomicIncrement((int32_t*)(&g_noise.numWriters), 1); // increment number of writers 00976 if (g_noise.isReading) // if we're in read mode then discard & exit 00977 { 00978 status = PAL_ERR_RTOS_NOISE_BUFFER_IS_READING ; 00979 goto finish; 00980 } 00981 00982 incrementedBitCount = (uint16_t)pal_osAtomicIncrement((int32_t*)(&g_noise.bitCountAllocated), lenBits); // reserve space in the array 00983 if (PAL_NOISE_SIZE_BITS < incrementedBitCount) // we want to write more bits than are available in the (entire) buffer 00984 { 00985 lenBits -= incrementedBitCount - PAL_NOISE_SIZE_BITS; // max number of bits that are avialable for writing 00986 if ((int8_t)lenBits <= 0) // we don't have any available bits for writing 00987 { 00988 status = PAL_ERR_RTOS_NOISE_BUFFER_FULL ; 00989 goto finish; 00990 } 00991 incrementedBitCount = PAL_NOISE_SIZE_BITS; 00992 } 00993 00994 currentIndex = (incrementedBitCount - lenBits) / PAL_INT32_BITS; // the current index in the array 00995 occupiedBitsInCurrentIndex = (incrementedBitCount - lenBits) % PAL_INT32_BITS; // how many bits are already occupied (with either 0 or 1) in the current index 00996 availableBitsInCurrentIndex = PAL_INT32_BITS - occupiedBitsInCurrentIndex; // how many bits are available in the current index 00997 00998 if (lenBits > availableBitsInCurrentIndex) // we want to write more bits than are available in the current index so we need to split the bits 00999 { 01000 mask = ((((int32_t)1) << availableBitsInCurrentIndex) - 1) << startBit; // mask to isolate the wanted bits 01001 value = *data & mask; 01002 if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) > 0) 01003 { 01004 value = value >> (startBit - occupiedBitsInCurrentIndex); 01005 } 01006 else if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) < 0) 01007 { 01008 value = value << (occupiedBitsInCurrentIndex - startBit); 01009 } 01010 pal_osAtomicIncrement(&g_noise.buffer[currentIndex], value); // write the 1st part of the splitted bits to the current index of the noise buffer 01011 *bitsWritten = availableBitsInCurrentIndex; 01012 lenBits -= availableBitsInCurrentIndex; // how many bits remain to be written 01013 startBit += availableBitsInCurrentIndex; 01014 mask = ((((int32_t)1) << lenBits) - 1) << startBit; // mask for the remaining bits that have not been written yet 01015 value = *data & mask; 01016 value = value >> startBit; // since we're writting to the next index we start at bit 0 01017 pal_osAtomicIncrement(&g_noise.buffer[currentIndex + 1], value); // write the 2nd part of the splitted bits to the next index of the noise buffer 01018 *bitsWritten += lenBits; 01019 } 01020 else // we have enough available bits for the current index (no need to split the bits) 01021 { 01022 mask = ((((int64_t)1) << lenBits) - 1) << startBit; // int64_t in case we want all the 32 bits 01023 value = *data & mask; 01024 if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) > 0) 01025 { 01026 value = value >> (startBit - occupiedBitsInCurrentIndex); 01027 } 01028 else if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) < 0) 01029 { 01030 value = value << (occupiedBitsInCurrentIndex - startBit); 01031 } 01032 pal_osAtomicIncrement(&g_noise.buffer[currentIndex], value); // write the bits to the current index of the noise buffer 01033 *bitsWritten = lenBits; 01034 } 01035 pal_osAtomicIncrement((int32_t*)(&g_noise.bitCountActual) , *bitsWritten); // increment how many bits were actually written 01036 finish: 01037 pal_osAtomicIncrement((int32_t*)(&g_noise.numWriters), -1); // decrement number of writers 01038 return status; 01039 } 01040 01041 /*! Write values to the global noise buffer 01042 * 01043 * @param[in] buffer The buffer which contains the values to be written. 01044 * @param[in] lenBits The number of bits that should be written. 01045 * @param[out] bitsWritten The number of bits that were actually written. 01046 * 01047 * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. 01048 */ 01049 palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten) 01050 { 01051 PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (PAL_NOISE_SIZE_BITS < lenBits) || (NULL == bitsWritten)); 01052 01053 palStatus_t status; 01054 uint8_t idx, bitsToWrite; 01055 uint16_t totalBitsWritten; 01056 01057 idx = 0; 01058 totalBitsWritten = 0; 01059 do 01060 { 01061 bitsToWrite = (lenBits > PAL_INT32_BITS) ? PAL_INT32_BITS : lenBits; // we can write a max number of 32 bits at a time 01062 status = pal_noiseWriteValue(&buffer[idx], 0, bitsToWrite, (uint8_t*)bitsWritten); 01063 lenBits -= bitsToWrite; 01064 idx++; 01065 totalBitsWritten += *bitsWritten; 01066 } while ((PAL_SUCCESS == status) && (bitsToWrite == *bitsWritten) && lenBits); // exit if there was an error, or the noise buffer has no more space, or all bits were written 01067 01068 *bitsWritten = totalBitsWritten; 01069 if (0 < totalBitsWritten) 01070 { 01071 status = PAL_SUCCESS; 01072 } 01073 return status; 01074 } 01075 01076 /*! Read values from the global noise buffer 01077 * 01078 * @param[out] buffer The output buffer which will contain the noise data collected. 01079 * @param[in] partial When true read what was collected so far, otherwise read only if the noise buffer is full. 01080 * @param[out] bitsRead he number of bits that were actually read. 01081 * 01082 * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. 01083 */ 01084 palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead) 01085 { 01086 PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (NULL == bitsRead)); 01087 01088 static uint32_t numOfNoiseReaders = 0; // allow only one reader at a time (no concurrent reads) 01089 palStatus_t status = PAL_SUCCESS; 01090 uint8_t numBytesToRead, numReadersLocal; 01091 uint16_t bitCountActual = (uint16_t)g_noise.bitCountActual; 01092 numReadersLocal = (uint8_t)pal_osAtomicIncrement((int32_t*)(&numOfNoiseReaders), 1); // increment number of readers 01093 *bitsRead = 0; 01094 if (1 != numReadersLocal) // single reader 01095 { 01096 PAL_LOG(DBG, "noise cannot read by multiple readers\n"); 01097 status = PAL_ERR_RTOS_NOISE_BUFFER_EMPTY ; 01098 goto finish; 01099 } 01100 01101 if ((CHAR_BIT > bitCountActual) || (!partial && (PAL_NOISE_SIZE_BITS != bitCountActual))) // exit if less than 1 byte was written or if we want a full read and not all bits were written 01102 { 01103 status = (CHAR_BIT > bitCountActual) ? PAL_ERR_RTOS_NOISE_BUFFER_EMPTY : PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL ; 01104 goto finish; 01105 } 01106 01107 g_noise.isReading = true; // set mode to reading so that no more writes will be allowed 01108 while (g_noise.numWriters) // wait for currently executing writers to finish (relevant only for partial read) 01109 { 01110 pal_osDelay(PAL_NOISE_WAIT_FOR_WRITERS_DELAY_MILLI_SEC); 01111 } 01112 bitCountActual = (uint16_t)g_noise.bitCountActual; // this may occur if we waited for the writers to finish writing, meaning we might have a few more bits (relevant only for partial read) 01113 numBytesToRead = (uint8_t)PAL_NOISE_BITS_TO_BYTES(bitCountActual); 01114 memcpy((void*)buffer, (void*)g_noise.buffer, numBytesToRead); // copy noise buffer to output buffer 01115 *bitsRead = (numBytesToRead * CHAR_BIT); // set out param of how many bits were actually read 01116 memset((void*)g_noise.buffer, 0, PAL_NOISE_SIZE_BYTES); // reset the noise buffer 01117 g_noise.bitCountActual = g_noise.bitCountAllocated = 0; // reset counters 01118 g_noise.isReading = false; // exit read mode so that writters will be able to continue writting 01119 PAL_LOG(DBG, "noise read %" PRIu8 " bits\n", *bitsRead); 01120 finish: 01121 pal_osAtomicIncrement((int32_t*)(&numOfNoiseReaders), -1); // decrement number of readers 01122 return status; 01123 }
Generated on Tue Jul 12 2022 19:12:14 by 1.7.2