Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
pal_plat_drbg_sotp.c
00001 /******************************************************************************* 00002 * Copyright 2016-2018 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 // This file is compiled when using ESFS and SOTP 00018 #if !defined(MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT) 00019 00020 00021 #include "pal.h" 00022 #include "pal_plat_drbg.h" 00023 #include "pal_plat_drbg_noise.h" 00024 #include "sotp.h" 00025 00026 #include <stdlib.h> 00027 00028 #define TRACE_GROUP "PAL" 00029 00030 00031 //! static variables for Random functionality. 00032 //! CTR-DRBG context to be used for generating random numbers from given seed 00033 static palCtrDrbgCtxHandle_t s_ctrDRBGCtx = NULLPTR; 00034 00035 PAL_PRIVATE bool g_palDRBGInitialized = false; 00036 00037 palStatus_t pal_plat_DRBGInit(void) 00038 { 00039 palStatus_t status = PAL_SUCCESS; 00040 if (g_palDRBGInitialized) 00041 { 00042 return status; 00043 } 00044 status = pal_plat_noiseInit(); 00045 if (PAL_SUCCESS != status) 00046 { 00047 PAL_LOG_ERR("pal_plat_DRBGInit: pal_plat_NoiseInit failed, status=%" PRIx32 "\n", status); 00048 } 00049 00050 g_palDRBGInitialized = true; 00051 00052 return status; 00053 } 00054 00055 palStatus_t pal_plat_DRBGDestroy(void) 00056 { 00057 palStatus_t status = PAL_ERR_NOT_INITIALIZED ; 00058 if (!g_palDRBGInitialized) 00059 { 00060 return status; 00061 } 00062 00063 #if PAL_USE_HW_TRNG 00064 if (PAL_SUCCESS != pal_plat_noiseDestroy()) 00065 { 00066 PAL_LOG_ERR("pal_DRBGDestroy: failed to terminate trng noise thread\n"); 00067 // FIXME: return error status? 00068 } 00069 #endif 00070 if (NULLPTR != s_ctrDRBGCtx) 00071 { 00072 status = pal_CtrDRBGFree(&s_ctrDRBGCtx); 00073 if (PAL_SUCCESS != status) 00074 { 00075 PAL_LOG_ERR("pal_DRBGDestroy: pal_CtrDRBGFree failed, status=%" PRIx32 "\n", status); 00076 } 00077 } 00078 00079 g_palDRBGInitialized = false; 00080 return status; 00081 } 00082 00083 00084 palStatus_t pal_plat_osRandomBuffer_blocking(uint8_t *randomBuf, size_t bufSizeBytes) 00085 { 00086 PAL_VALIDATE_ARGUMENTS (NULL == randomBuf); 00087 00088 palStatus_t status = PAL_ERR_GENERIC_FAILURE ; 00089 if (g_palDRBGInitialized == true) 00090 { 00091 if (NULLPTR == s_ctrDRBGCtx) 00092 { 00093 // XXX: move this to pal_plat_DRBGInit(), no point to do lazy initializations as it is 00094 // better to fail early on init phase than unexpectedly on a call to pal_osRandomBuffer(). 00095 uint32_t sotpCounter = 0; 00096 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) 00097 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 00098 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 00099 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 00100 uint32_t* ptrSotpCounterRead = ptrSotpWrite; // pointer to the memory address in buf which will point to the counter read from sotp 00101 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 00102 uint16_t sotpBytesRead = 0, noiseBitsWrittern = 0; 00103 size_t trngBytesRead = 0; 00104 palCtrDrbgCtxHandle_t longCtrDRBGCtx = NULLPTR; // long term drbg context 00105 palStatus_t tmpStatus; 00106 sotp_result_e sotpResult = sotp_get(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpRead, &sotpBytesRead); // read 48 drbg bytes + 4 counter bytes 00107 if (SOTP_SUCCESS == sotpResult) 00108 { 00109 if ((PAL_INITIAL_RANDOM_SIZE != sotpBytesRead) && (sotpLenBytes != sotpBytesRead)) 00110 { 00111 status = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT ; 00112 PAL_LOG_ERR("Invalid number of bytes read from SOTP, bytes read=%" PRIu16, sotpBytesRead); 00113 goto finish; 00114 } 00115 status = pal_CtrDRBGInit(&longCtrDRBGCtx, ptrSotpRead, PAL_INITIAL_RANDOM_SIZE); // initialize long term drbg with the seed that was read from sotp 00116 if (PAL_SUCCESS != status) 00117 { 00118 PAL_LOG_ERR("Failed to initialize long term DRBG context, status=%" PRIx32 "\n", status); 00119 goto finish; 00120 } 00121 memcpy((void*)&sotpCounter, (void*)ptrSotpCounterRead, sizeof(sotpCounter)); // read the counter from the buffer (sotp data) to local var 00122 #if PAL_USE_HW_TRNG 00123 memset((void*)buf, 0, sizeof(buf)); 00124 status = pal_plat_osRandomBuffer(buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead); 00125 if ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status)) 00126 { 00127 if (0 < trngBytesRead) 00128 { 00129 tmpStatus = pal_plat_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWrittern); // write whatever was collected from trng to the noise buffer 00130 PAL_LOG_DBG( "Write TRNG to noise buffer, status=%" PRIx32 ", bits writtern=%" PRIu16 "\n", tmpStatus, noiseBitsWrittern); 00131 } 00132 } 00133 else 00134 { 00135 PAL_LOG_ERR("Read from TRNG failed, status=%" PRIx32 "\n", status); 00136 } 00137 #endif // PAL_USE_HW_TRNG 00138 memset((void*)buf, 0, sizeof(buf)); 00139 status = pal_plat_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 00140 if (PAL_SUCCESS != status) 00141 { 00142 PAL_LOG_ERR("Failed to gererate DRBG long term and short term seeds, status=%" PRIx32 "\n", status); 00143 goto drbg_cleanup; 00144 } 00145 sotpCounter++; // increment counter before writting it back to sotp 00146 memcpy((void*)ptrSotpCounterWrite, (void*)&sotpCounter, sizeof(sotpCounter)); // copy the incremented counter to the last 4 bytes of the buffer 00147 sotpResult = sotp_set(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpWrite); // write 48 long term drbg bytes + 4 counter bytes 00148 if (SOTP_SUCCESS != sotpResult) 00149 { 00150 PAL_LOG_ERR("Failed to write to SOTP, sotp result=%d", sotpResult); 00151 status = PAL_ERR_GENERIC_FAILURE ; 00152 } 00153 drbg_cleanup: 00154 { 00155 tmpStatus = pal_CtrDRBGFree(&longCtrDRBGCtx); 00156 if (PAL_SUCCESS != tmpStatus) 00157 { 00158 PAL_LOG_ERR("Failed to free long term DRBG context, status=%" PRIx32 "\n", tmpStatus); 00159 } 00160 longCtrDRBGCtx = NULLPTR; 00161 if (PAL_SUCCESS != status) 00162 { 00163 goto finish; 00164 } 00165 #if PAL_USE_HW_TRNG 00166 status = pal_plat_noiseCreateThread(); 00167 if (PAL_SUCCESS != status) 00168 { 00169 PAL_LOG_ERR("Failed to create noise TRNG thread, status=%" PRIx32 "\n", tmpStatus); 00170 } 00171 #endif // PAL_USE_HW_TRNG 00172 } 00173 } 00174 else if (SOTP_NOT_FOUND == sotpResult) 00175 { 00176 #if PAL_USE_HW_TRNG 00177 memset((void*)buf, 0, sizeof(buf)); 00178 uint8_t* seedPtr = buf; 00179 size_t randomCounterBytes = 0; 00180 do 00181 { 00182 status = pal_plat_osRandomBuffer(seedPtr, PAL_INITIAL_RANDOM_SIZE - randomCounterBytes, &trngBytesRead); 00183 if (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status) 00184 { 00185 pal_osDelay(PAL_TRNG_COLLECT_DELAY_MILLI_SEC); // sleep to let the device to collect random data. 00186 randomCounterBytes += trngBytesRead; 00187 seedPtr += trngBytesRead; 00188 } 00189 } while (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status); 00190 #else 00191 status = PAL_ERR_CTR_DRBG_NOT_SEEDED; // No entropy in SOTP and no TRNG = DRBG not seeded 00192 #endif // PAL_USE_HW_TRNG 00193 } 00194 if (PAL_SUCCESS != status) 00195 { 00196 goto finish; 00197 } 00198 status = pal_CtrDRBGInit(&s_ctrDRBGCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE); 00199 if (PAL_SUCCESS != status) 00200 { 00201 PAL_LOG_ERR("Failed to initialize short term DRBG context, status=%" PRIx32 "\n", status); 00202 goto finish; 00203 } 00204 } 00205 status = pal_plat_generateDrbgWithNoiseAttempt(s_ctrDRBGCtx, randomBuf, false, bufSizeBytes); 00206 if (PAL_SUCCESS != status) 00207 { 00208 PAL_LOG_ERR("Failed to generate random, status=%" PRIx32 "\n", status); 00209 } 00210 } 00211 else 00212 { 00213 return PAL_ERR_NOT_INITIALIZED ; 00214 } 00215 finish: 00216 return status; 00217 } 00218 00219 00220 00221 #endif // !MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT
Generated on Tue Jul 12 2022 20:21:01 by
