Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_drbg_w_entropy_sources.c Source File

pal_plat_drbg_w_entropy_sources.c

00001 
00002 // ----------------------------------------------------------------------------
00003 // Copyright 2019 ARM Ltd.
00004 //
00005 // SPDX-License-Identifier: Apache-2.0
00006 //
00007 // Licensed under the Apache License, Version 2.0 (the "License");
00008 // you may not use this file except in compliance with the License.
00009 // You may obtain a copy of the License at
00010 //
00011 //     http://www.apache.org/licenses/LICENSE-2.0
00012 //
00013 // Unless required by applicable law or agreed to in writing, software
00014 // distributed under the License is distributed on an "AS IS" BASIS,
00015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016 // See the License for the specific language governing permissions and
00017 // limitations under the License.
00018 // ----------------------------------------------------------------------------
00019 
00020 // This file is compiled if we wish to use mbedtls entropy sources for collecting entropy and updating the non-volatile entropy
00021 // There is currently an open issue https://jira.arm.com/browse/IOTCRYPT-180 (ability to accumulate sufficiently large entropy)
00022 // So, meanwhile use this module only with PSA build since we must use the mbedtls entropy sourcing method. 
00023 // When this issue is resolved - SOTP builds may also use this module, which will deprecate pal_plat_drbg_sotp.c
00024 
00025 // This file implements pal_plat_drbg.h for mbedtls properly
00026 
00027 #if defined(MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT)
00028 #include "pal.h"
00029 #include "pal_plat_drbg.h"
00030 #include "sotp.h"
00031 #include "mbedtls/x509_crt.h"
00032 #include "mbedtls/ctr_drbg.h"
00033 #include "mbedtls/entropy.h"
00034 #include "config.h"
00035 #include "pal_plat_Crypto.h"
00036 #if PAL_USE_HW_TRNG
00037 #include "pal_plat_drbg_noise.h"
00038 #endif
00039 #include "mbed_trace.h"
00040 #include <stdlib.h>
00041 
00042 #define TRACE_GROUP "PAL"
00043 
00044 // Forward declaration to use non-public function from pal_plat_Crypto.c
00045 palStatus_t pal_plat_CtrDRBGSeedFromEntropySources(palCtrDrbgCtxHandle_t ctx, int (*f_entropy)(void *, unsigned char *, size_t), const void* additionalData, size_t additionalDataLen);
00046 
00047 PAL_PRIVATE palCtrDrbgCtxHandle_t g_palCtrDrbgCtx = NULLPTR;
00048 
00049 // Forward declaration
00050 palStatus_t pal_plat_DRBGSeed(void);
00051 
00052 
00053 /**
00054  * 1. init CTR DRBG context (entropy and DRBG mbedtls contexts) and noise
00055  * 2. If not expecting entropy (MBEDTLS_ENTROPY_NV_SEED not defined):
00056  *   2.a Seed the DRBG
00057  * 3. If expecting entropy (MBEDTLS_ENTROPY_NV_SEED defined):
00058  *    Do nothing (DRBG will be initialized by pal_plat_osEntropyInject()
00059  */
00060 palStatus_t pal_plat_DRBGInit(void)
00061 {
00062     palStatus_t status = PAL_SUCCESS;
00063     if (g_palCtrDrbgCtx) {
00064         return status;
00065     }
00066 
00067 #if PAL_USE_HW_TRNG
00068     status = pal_plat_noiseInit();
00069     if (status != PAL_SUCCESS)
00070     {
00071         goto Exit;
00072     }
00073 #endif 
00074 
00075     // Notice that pal_plat_CtrDRBGInit is used and NOT pal_CtrDRBGInit, because the latter also tries to seed the DRBG
00076     status = pal_plat_CtrDRBGInit(&g_palCtrDrbgCtx);
00077     if (status != PAL_SUCCESS)
00078     {
00079         goto Exit;
00080     }
00081 
00082     /*
00083      * Seed the DRBG only if we do not expect a non-volatile entropy to be injected.
00084      * If we expect an NV seed, mbedtls_ctr_drbg_seed will fail trying to read the seed 
00085      * since the entropy was not injected yet.
00086      */
00087 
00088 #ifndef MBEDTLS_ENTROPY_NV_SEED
00089     status = pal_plat_DRBGSeed();
00090     if (status != PAL_SUCCESS) {
00091         goto Exit;
00092     }    
00093 #else
00094 
00095 #if PAL_USE_HW_TRNG
00096     status = pal_plat_noiseCreateThread();
00097     if (status != PAL_SUCCESS)
00098     {
00099         PAL_LOG_ERR("Error creating noise thread\n");
00100         goto Exit;
00101     }
00102 #endif // PAL_USE_HW_TRNG
00103 #endif // MBEDTLS_ENTROPY_NV_SEED
00104 
00105     /*
00106      * At this point the DRBG has the following state:
00107      * * If defined(MBEDTLS_ENTROPY_NV_SEED): initialized but not seeded - will be seeded when pal_plat_osEntropyInject() is called. pal_plat_osRandomBuffer_blocking() 
00108      *   will fail until entropy is injected.
00109      * * If not defined(MBEDTLS_ENTROPY_NV_SEED): initialized and seeded. pal_plat_osRandomBuffer_blocking() call should succeed.
00110      */
00111     
00112 Exit:
00113     if (status != PAL_SUCCESS && g_palCtrDrbgCtx != NULLPTR) {
00114         (void)pal_CtrDRBGFree(&g_palCtrDrbgCtx);
00115         // No need to set g_palCtrDrbgCtx = NULLPTR, the pal_plat_CtrDRBGFree function already does so
00116     }
00117     return status;
00118 }
00119 
00120 palStatus_t pal_plat_DRBGDestroy(void)
00121 {
00122     palStatus_t status = PAL_SUCCESS;
00123     if (!g_palCtrDrbgCtx) {
00124         return PAL_ERR_NOT_INITIALIZED ;
00125     } else {
00126         (void)pal_CtrDRBGFree(&g_palCtrDrbgCtx);
00127         status = pal_plat_noiseDestroy();
00128         //g_palDRBGIsSeeded = false;
00129     }
00130     return status;
00131 }
00132 
00133 //! This function must not be static as it is also called from pal_plat_osEntropyInject() which declares it explicitly
00134 // FIXME: move to pal_plat_Crypto (mbedtls) ? then pal_plat_CtrDRBGSeedFromEntropySources is a static function within
00135 // This function seeds the DRBG based on internal sources (i.e entropy that is already injected, trng, etc.)
00136 // Should be pal_plat_DRBGSeed(palCtrDrbgCtxHandle_t handle) and we can move
00137 palStatus_t pal_plat_DRBGSeed()
00138 {
00139     palStatus_t status = PAL_SUCCESS;
00140 
00141     if (!g_palCtrDrbgCtx) 
00142     {
00143         return PAL_ERR_NOT_INITIALIZED ;
00144     }
00145 
00146     // Seed the DRBG if not seeded. If it is - reseed it.
00147     status = pal_plat_CtrDRBGSeedFromEntropySources(g_palCtrDrbgCtx, mbedtls_entropy_func, NULL, 0);
00148 
00149     return status;
00150 }
00151 
00152 palStatus_t pal_plat_osRandomBuffer_blocking(uint8_t *randomBuf, size_t bufSizeBytes)
00153 {
00154     palStatus_t status = PAL_SUCCESS;
00155 
00156     if (!g_palCtrDrbgCtx) 
00157     {
00158         return PAL_ERR_NOT_INITIALIZED ;
00159     }
00160     /*
00161      * If the DRBG is not yet seeded, try to seed it.
00162      * This check is important for the production flow where NV entropy is expected (MBEDTLS_ENTROPY_NV_SEED defined):
00163      * First run factory app:
00164      *  - Entropy is injected and DRBG is seeded
00165      * Then run Pelion client app (entropy exists in storage):
00166      *  - call pal_plat_osRandomBuffer_blocking(). DRBG is not seeded during pal_plat_DRBGInit() and pal_plat_osEntropyInject() 
00167      *    will not be called so we should seed the DRBG with the entropy already in storage.
00168      */
00169     if (pal_CtrDRBGIsSeeded(g_palCtrDrbgCtx) == PAL_ERR_CTR_DRBG_NOT_SEEDED)
00170     {
00171         status = pal_plat_DRBGSeed();
00172         // If seeding failed with source error, we assume that the NV source did not exist, and return a PAL_ERR_CTR_DRBG_NOT_SEEDED error
00173         if (status == PAL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED)
00174         {
00175             return PAL_ERR_CTR_DRBG_NOT_SEEDED;
00176         } else if (status != PAL_SUCCESS) {
00177             return status;
00178         }
00179     }
00180 
00181 #if PAL_USE_HW_TRNG
00182     return pal_plat_generateDrbgWithNoiseAttempt(g_palCtrDrbgCtx, randomBuf, false, bufSizeBytes);
00183 #else 
00184     // Note that calling pal_plat_generateDrbgWithNoiseAttempt here will also work
00185     // but that will add some unnecessary code to the image. Besides, it is more clear
00186     // this way.
00187     return pal_CtrDRBGGenerate(g_palCtrDrbgCtx, randomBuf, bufSizeBytes);
00188 #endif
00189 }
00190 
00191 #endif // MBED_CONF_MBED_CLOUD_CLIENT_EXTERNAL_SST_SUPPORT