NuMaker connection with AWS IoT thru MQTT/HTTPS (Mbed OS 6)

Dependencies:   MQTT

Committer:
ccli8
Date:
Mon Mar 16 13:29:32 2020 +0800
Revision:
33:c3a985807206
Parent:
29:e890b0fdce53
Child:
41:b878d7cd7035
Support MBEDTLS_ENTROPY_HARDWARE_ALT with EADC+S/W random

Some targets e.g. M482 have neither TRNG nor PRNG. Add EADC+S/W random to implement MBEDTLS_ENTROPY_HARDWARE_ALT.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ccli8 29:e890b0fdce53 1 /*
ccli8 29:e890b0fdce53 2 * Copyright (c) 2019 Nuvoton Technology Corporation
ccli8 29:e890b0fdce53 3 *
ccli8 29:e890b0fdce53 4 * SPDX-License-Identifier: Apache-2.0
ccli8 29:e890b0fdce53 5 *
ccli8 29:e890b0fdce53 6 * Licensed under the Apache License, Version 2.0 (the "License");
ccli8 29:e890b0fdce53 7 * you may not use this file except in compliance with the License.
ccli8 29:e890b0fdce53 8 * You may obtain a copy of the License at
ccli8 29:e890b0fdce53 9 *
ccli8 29:e890b0fdce53 10 * http://www.apache.org/licenses/LICENSE-2.0
ccli8 29:e890b0fdce53 11 *
ccli8 29:e890b0fdce53 12 * Unless required by applicable law or agreed to in writing, software
ccli8 29:e890b0fdce53 13 * distributed under the License is distributed on an "AS IS" BASIS,
ccli8 29:e890b0fdce53 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ccli8 29:e890b0fdce53 15 * See the License for the specific language governing permissions and
ccli8 29:e890b0fdce53 16 * limitations under the License.
ccli8 29:e890b0fdce53 17 */
ccli8 29:e890b0fdce53 18
ccli8 29:e890b0fdce53 19 #if !DEVICE_TRNG && !TARGET_PSA
ccli8 29:e890b0fdce53 20
ccli8 29:e890b0fdce53 21 #include "mbed.h"
ccli8 29:e890b0fdce53 22 #include "mbedtls/config.h"
ccli8 29:e890b0fdce53 23
ccli8 29:e890b0fdce53 24 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
ccli8 29:e890b0fdce53 25
ccli8 33:c3a985807206 26 /* Support entropy source with EADC seeded random on non-PSA targets without TRNG
ccli8 29:e890b0fdce53 27 *
ccli8 33:c3a985807206 28 * Follow the steps below to replace TRNG with EADC seeded random:
ccli8 29:e890b0fdce53 29 *
ccli8 33:c3a985807206 30 * 1. Seed random generator with EADC band gap
ccli8 29:e890b0fdce53 31 * 2. Define MBEDTLS_ENTROPY_HARDWARE_ALT and provide custom mbedtls_hardware_poll(...)
ccli8 29:e890b0fdce53 32 *
ccli8 29:e890b0fdce53 33 * Reference configuration in mbed_app.json:
ccli8 29:e890b0fdce53 34 *
ccli8 29:e890b0fdce53 35 * For Pelion/mbedtls:
ccli8 29:e890b0fdce53 36 *
ccli8 29:e890b0fdce53 37 * "target.macros_add": [
ccli8 29:e890b0fdce53 38 * "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"",
ccli8 29:e890b0fdce53 39 * "MBEDTLS_ENTROPY_HARDWARE_ALT"
ccli8 29:e890b0fdce53 40 * ],
ccli8 29:e890b0fdce53 41 *
ccli8 29:e890b0fdce53 42 * For non-Pelion/mbedtls:
ccli8 29:e890b0fdce53 43 *
ccli8 29:e890b0fdce53 44 * "target.macros_add": [
ccli8 29:e890b0fdce53 45 * "MBEDTLS_ENTROPY_HARDWARE_ALT"
ccli8 29:e890b0fdce53 46 * ],
ccli8 29:e890b0fdce53 47 *
ccli8 29:e890b0fdce53 48 * For both Pelion/non-Pelion (skip when done in targets.json):
ccli8 29:e890b0fdce53 49 *
ccli8 29:e890b0fdce53 50 * "target.device_has_remove": ["TRNG"],
ccli8 29:e890b0fdce53 51 *
ccli8 33:c3a985807206 52 * WARNING: If the security level of EADC seeded random generator cannot meet requirements, replace it with another entropy source.
ccli8 33:c3a985807206 53 *
ccli8 33:c3a985807206 54 * Select random generator between PRNG and S/W random:
ccli8 33:c3a985807206 55 *
ccli8 33:c3a985807206 56 * For targets with PRNG:
ccli8 33:c3a985807206 57 * "crypto-prng-present": true,
ccli8 33:c3a985807206 58 * For targets without PRNG (e.g. M482):
ccli8 33:c3a985807206 59 * "crypto-prng-present": false,
ccli8 29:e890b0fdce53 60 */
ccli8 29:e890b0fdce53 61
ccli8 33:c3a985807206 62 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 63 #include "crypto-misc.h"
ccli8 33:c3a985807206 64 #else
ccli8 33:c3a985807206 65 #include <stdlib.h>
ccli8 33:c3a985807206 66 #endif
ccli8 29:e890b0fdce53 67
ccli8 29:e890b0fdce53 68 extern "C" {
ccli8 29:e890b0fdce53 69 int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen);
ccli8 29:e890b0fdce53 70 }
ccli8 29:e890b0fdce53 71
ccli8 29:e890b0fdce53 72 /* Support EADC band gap
ccli8 29:e890b0fdce53 73 *
ccli8 29:e890b0fdce53 74 * Mbed OS defines analog-in HAL for normal purposes, but EADC band gap is not defined.
ccli8 29:e890b0fdce53 75 * To avoid EADC code conflict and fit into existent analog-in HAL, we:
ccli8 29:e890b0fdce53 76 *
ccli8 29:e890b0fdce53 77 * 1. Hijack AnalogIn driver to involve analog-in HAL protection and EADC initialization.
ccli8 29:e890b0fdce53 78 * This needs one dedicated EADC pin EADC_AUX_PINNAME.
ccli8 29:e890b0fdce53 79 * 2. Run EADC band gap conversion, with EADC module already initialized via above. This needs
ccli8 29:e890b0fdce53 80 * one dedicated sample module and one dedicated channel.
ccli8 29:e890b0fdce53 81 */
ccli8 29:e890b0fdce53 82
ccli8 29:e890b0fdce53 83 #if TARGET_NUC472
ccli8 29:e890b0fdce53 84 #define EADC_AUX_PINNAME A0
ccli8 29:e890b0fdce53 85 #define EADC_BANDGAP_SMPLMOD 7
ccli8 29:e890b0fdce53 86 #define EADC_BANDGAP_CHN 8
ccli8 33:c3a985807206 87 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 88 #define PRNG_KEYSIZE_ID PRNG_KEY_SIZE_128
ccli8 29:e890b0fdce53 89 #define PRNG_KEYSIZE 16
ccli8 33:c3a985807206 90 #endif
ccli8 29:e890b0fdce53 91 #elif TARGET_M480
ccli8 29:e890b0fdce53 92 #define EADC_AUX_PINNAME A0
ccli8 29:e890b0fdce53 93 #define EADC_BANDGAP_SMPLMOD 16
ccli8 29:e890b0fdce53 94 #define EADC_BANDGAP_CHN 16
ccli8 33:c3a985807206 95 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 96 #define PRNG_KEYSIZE_ID PRNG_KEY_SIZE_128
ccli8 29:e890b0fdce53 97 #define PRNG_KEYSIZE 16
ccli8 33:c3a985807206 98 #endif
ccli8 29:e890b0fdce53 99 #else
ccli8 29:e890b0fdce53 100 #error("Target not support")
ccli8 29:e890b0fdce53 101 #endif
ccli8 29:e890b0fdce53 102
ccli8 29:e890b0fdce53 103 class NuBandGap : public mbed::AnalogIn {
ccli8 29:e890b0fdce53 104 public:
ccli8 29:e890b0fdce53 105 NuBandGap();
ccli8 29:e890b0fdce53 106 ~NuBandGap();
ccli8 29:e890b0fdce53 107
ccli8 29:e890b0fdce53 108 /* Generate bitstream based on EADC band gap
ccli8 29:e890b0fdce53 109 *
ccli8 29:e890b0fdce53 110 * @returns 1/0 bitstream
ccli8 29:e890b0fdce53 111 */
ccli8 29:e890b0fdce53 112 uint16_t read_bitstream();
ccli8 29:e890b0fdce53 113 };
ccli8 29:e890b0fdce53 114
ccli8 33:c3a985807206 115 class NuEADCSeedRandom : private mbed::NonCopyable<NuEADCSeedRandom>
ccli8 29:e890b0fdce53 116 {
ccli8 29:e890b0fdce53 117 public:
ccli8 33:c3a985807206 118 NuEADCSeedRandom();
ccli8 33:c3a985807206 119 ~NuEADCSeedRandom();
ccli8 29:e890b0fdce53 120
ccli8 29:e890b0fdce53 121 /* Get random data
ccli8 29:e890b0fdce53 122 *
ccli8 29:e890b0fdce53 123 * @param output The pointer to an output array
ccli8 29:e890b0fdce53 124 * @param len The size of output data, to avoid buffer overwrite
ccli8 29:e890b0fdce53 125 * @param olen The length of generated data
ccli8 29:e890b0fdce53 126 */
ccli8 29:e890b0fdce53 127 int get_bytes(unsigned char *output, size_t len, size_t *olen);
ccli8 29:e890b0fdce53 128
ccli8 29:e890b0fdce53 129 private:
ccli8 29:e890b0fdce53 130 NuBandGap band_gap;
ccli8 29:e890b0fdce53 131 };
ccli8 29:e890b0fdce53 132
ccli8 29:e890b0fdce53 133 int mbedtls_hardware_poll(MBED_UNUSED void *data, unsigned char *output, size_t len, size_t *olen)
ccli8 29:e890b0fdce53 134 {
ccli8 33:c3a985807206 135 static NuEADCSeedRandom eadc_seed_random;
ccli8 29:e890b0fdce53 136
ccli8 33:c3a985807206 137 return eadc_seed_random.get_bytes(output, len, olen);
ccli8 29:e890b0fdce53 138 }
ccli8 29:e890b0fdce53 139
ccli8 29:e890b0fdce53 140 NuBandGap::NuBandGap() : mbed::AnalogIn(EADC_AUX_PINNAME)
ccli8 29:e890b0fdce53 141 {
ccli8 29:e890b0fdce53 142 EADC_T *eadc_base = (EADC_T *) EADC_BASE;
ccli8 29:e890b0fdce53 143
ccli8 29:e890b0fdce53 144 EADC_ConfigSampleModule(eadc_base, EADC_BANDGAP_SMPLMOD, EADC_SOFTWARE_TRIGGER, EADC_BANDGAP_CHN);
ccli8 29:e890b0fdce53 145 }
ccli8 29:e890b0fdce53 146
ccli8 29:e890b0fdce53 147 NuBandGap::~NuBandGap()
ccli8 29:e890b0fdce53 148 {
ccli8 29:e890b0fdce53 149 }
ccli8 29:e890b0fdce53 150
ccli8 29:e890b0fdce53 151 uint16_t NuBandGap::read_bitstream()
ccli8 29:e890b0fdce53 152 {
ccli8 29:e890b0fdce53 153 uint16_t one_or_zero;
ccli8 29:e890b0fdce53 154
ccli8 29:e890b0fdce53 155 lock();
ccli8 29:e890b0fdce53 156
ccli8 29:e890b0fdce53 157 EADC_T *eadc_base = (EADC_T *) EADC_BASE;
ccli8 29:e890b0fdce53 158
ccli8 29:e890b0fdce53 159 EADC_START_CONV(eadc_base, 1 << EADC_BANDGAP_SMPLMOD);
ccli8 29:e890b0fdce53 160 while (EADC_GET_DATA_VALID_FLAG(eadc_base, 1 << EADC_BANDGAP_SMPLMOD) != (1 << EADC_BANDGAP_SMPLMOD));
ccli8 29:e890b0fdce53 161 uint16_t conv_res_12 = EADC_GET_CONV_DATA(eadc_base, EADC_BANDGAP_SMPLMOD);
ccli8 29:e890b0fdce53 162
ccli8 29:e890b0fdce53 163 /* 1 as number of 'one' is odd; 0 otherwise */
ccli8 29:e890b0fdce53 164 unsigned i;
ccli8 29:e890b0fdce53 165 uint16_t count_one = 0;
ccli8 29:e890b0fdce53 166 for (i = 0; i < 12; i ++) {
ccli8 29:e890b0fdce53 167 if (conv_res_12 & 1) {
ccli8 29:e890b0fdce53 168 count_one ++;
ccli8 29:e890b0fdce53 169 }
ccli8 29:e890b0fdce53 170 conv_res_12 >>= 1;
ccli8 29:e890b0fdce53 171 }
ccli8 29:e890b0fdce53 172 one_or_zero = count_one & 1;
ccli8 29:e890b0fdce53 173
ccli8 29:e890b0fdce53 174 unlock();
ccli8 29:e890b0fdce53 175
ccli8 29:e890b0fdce53 176 return one_or_zero;
ccli8 29:e890b0fdce53 177 }
ccli8 29:e890b0fdce53 178
ccli8 33:c3a985807206 179 NuEADCSeedRandom::NuEADCSeedRandom()
ccli8 29:e890b0fdce53 180 {
ccli8 33:c3a985807206 181 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 182 crypto_init();
ccli8 29:e890b0fdce53 183 PRNG_ENABLE_INT();
ccli8 33:c3a985807206 184 #endif
ccli8 29:e890b0fdce53 185
ccli8 29:e890b0fdce53 186 uint32_t seed = 0;
ccli8 29:e890b0fdce53 187 unsigned i = 32;
ccli8 29:e890b0fdce53 188
ccli8 29:e890b0fdce53 189 /* Get seed from EADC band gap */
ccli8 29:e890b0fdce53 190 while (i --) {
ccli8 29:e890b0fdce53 191 seed <<= 1;
ccli8 29:e890b0fdce53 192 seed |= band_gap.read_bitstream();
ccli8 29:e890b0fdce53 193 }
ccli8 29:e890b0fdce53 194
ccli8 33:c3a985807206 195 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 196 /* PRNG reload seed */
ccli8 29:e890b0fdce53 197 PRNG_Open(PRNG_KEYSIZE_ID, 1, seed);
ccli8 33:c3a985807206 198 #else
ccli8 33:c3a985807206 199 srand(seed);
ccli8 33:c3a985807206 200 #endif /* #if NU_CRYPTO_PRNG_PRESENT */
ccli8 29:e890b0fdce53 201 }
ccli8 29:e890b0fdce53 202
ccli8 33:c3a985807206 203 NuEADCSeedRandom::~NuEADCSeedRandom()
ccli8 29:e890b0fdce53 204 {
ccli8 33:c3a985807206 205 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 206 PRNG_DISABLE_INT();
ccli8 29:e890b0fdce53 207 crypto_uninit();
ccli8 33:c3a985807206 208 #endif /* #if NU_CRYPTO_PRNG_PRESENT */
ccli8 29:e890b0fdce53 209 }
ccli8 29:e890b0fdce53 210
ccli8 33:c3a985807206 211 int NuEADCSeedRandom::get_bytes(unsigned char *output, size_t len, size_t *olen)
ccli8 29:e890b0fdce53 212 {
ccli8 29:e890b0fdce53 213 /* Check argument validity */
ccli8 29:e890b0fdce53 214 if (!output && len) {
ccli8 29:e890b0fdce53 215 return -1;
ccli8 29:e890b0fdce53 216 }
ccli8 29:e890b0fdce53 217
ccli8 33:c3a985807206 218 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 219 unsigned char *output_ind = output;
ccli8 29:e890b0fdce53 220 size_t rmn = len;
ccli8 29:e890b0fdce53 221 uint32_t rand_data[PRNG_KEYSIZE / sizeof(uint32_t)];
ccli8 29:e890b0fdce53 222 while (rmn) {
ccli8 29:e890b0fdce53 223 crypto_prng_prestart();
ccli8 29:e890b0fdce53 224 PRNG_Start();
ccli8 29:e890b0fdce53 225 crypto_prng_wait();
ccli8 29:e890b0fdce53 226
ccli8 29:e890b0fdce53 227 PRNG_Read(rand_data);
ccli8 29:e890b0fdce53 228
ccli8 29:e890b0fdce53 229 size_t n = (rmn >= PRNG_KEYSIZE) ? PRNG_KEYSIZE : rmn;
ccli8 29:e890b0fdce53 230 memcpy(output_ind, rand_data, n);
ccli8 29:e890b0fdce53 231
ccli8 29:e890b0fdce53 232 output_ind += n;
ccli8 29:e890b0fdce53 233 rmn -= n;
ccli8 29:e890b0fdce53 234 }
ccli8 33:c3a985807206 235 #else
ccli8 33:c3a985807206 236 unsigned char *output_ind = output;
ccli8 33:c3a985807206 237 size_t rmn = len;
ccli8 33:c3a985807206 238 while (rmn) {
ccli8 33:c3a985807206 239 *output_ind ++ = rand() % 256;
ccli8 33:c3a985807206 240 rmn --;
ccli8 33:c3a985807206 241 }
ccli8 33:c3a985807206 242 #endif /* #if NU_CRYPTO_PRNG_PRESENT */
ccli8 29:e890b0fdce53 243
ccli8 29:e890b0fdce53 244 if (olen) {
ccli8 29:e890b0fdce53 245 *olen = len;
ccli8 29:e890b0fdce53 246 }
ccli8 29:e890b0fdce53 247
ccli8 29:e890b0fdce53 248 return 0;
ccli8 29:e890b0fdce53 249 }
ccli8 29:e890b0fdce53 250
ccli8 29:e890b0fdce53 251 #else
ccli8 29:e890b0fdce53 252
ccli8 29:e890b0fdce53 253 /* Support entropy source with mbedtls NV seed on non-PSA targets without TRNG
ccli8 29:e890b0fdce53 254 *
ccli8 29:e890b0fdce53 255 * Follow the steps below to replace TRNG with mbedtls NV seed:
ccli8 29:e890b0fdce53 256 *
ccli8 29:e890b0fdce53 257 * 1. Define MBEDTLS_ENTROPY_NV_SEED
ccli8 29:e890b0fdce53 258 * 2. Define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO/MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and provide custom mbedtls_nv_seed_read(...)/mbedtls_nv_seed_write(...).
ccli8 29:e890b0fdce53 259 * 3. Don't define MBEDTLS_PSA_INJECT_ENTROPY. Meet mbedtls_psa_inject_entropy(...) undefined and then provide custom one, which must be compatible with mbedtls_nv_seed_read(...)/mbedtls_nv_seed_write(...) above.
ccli8 29:e890b0fdce53 260 * 4. For development, simulating partial provision process, inject entropy seed via mbedtls_psa_inject_entropy(...) pre-main.
ccli8 29:e890b0fdce53 261 *
ccli8 29:e890b0fdce53 262 * Reference configuration in mbed_app.json:
ccli8 29:e890b0fdce53 263 *
ccli8 29:e890b0fdce53 264 * For Pelion/mbedtls, don't define MBEDTLS_ENTROPY_NV_SEED because it has defined in:
ccli8 29:e890b0fdce53 265 * https://github.com/ARMmbed/mbed-cloud-client/blob/master/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS_SW_TRNG.h
ccli8 29:e890b0fdce53 266 *
ccli8 29:e890b0fdce53 267 * "target.macros_add": [
ccli8 29:e890b0fdce53 268 * "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS_SW_TRNG.h\"",
ccli8 29:e890b0fdce53 269 * "PAL_USE_HW_TRNG=0",
ccli8 29:e890b0fdce53 270 * "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO=mbedtls_platform_seed_read",
ccli8 29:e890b0fdce53 271 * "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO=mbedtls_platform_seed_write"
ccli8 29:e890b0fdce53 272 * ],
ccli8 29:e890b0fdce53 273 *
ccli8 29:e890b0fdce53 274 * For non-Pelion/mbedtls:
ccli8 29:e890b0fdce53 275 *
ccli8 29:e890b0fdce53 276 * "target.macros_add": [
ccli8 29:e890b0fdce53 277 * "MBEDTLS_ENTROPY_NV_SEED",
ccli8 29:e890b0fdce53 278 * "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO=mbedtls_platform_seed_read",
ccli8 29:e890b0fdce53 279 * "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO=mbedtls_platform_seed_write"
ccli8 29:e890b0fdce53 280 * ],
ccli8 29:e890b0fdce53 281 *
ccli8 29:e890b0fdce53 282 * For both Pelion/non-Pelion (skip when done in targets.json):
ccli8 29:e890b0fdce53 283 *
ccli8 29:e890b0fdce53 284 * "target.device_has_remove": ["TRNG"],
ccli8 29:e890b0fdce53 285 *
ccli8 29:e890b0fdce53 286 * WARNING: The injection of mbedtls NV seed pre-main is only for development. Run provision process for mass production.
ccli8 29:e890b0fdce53 287 */
ccli8 29:e890b0fdce53 288
ccli8 29:e890b0fdce53 289 #include "entropy_poll.h"
ccli8 29:e890b0fdce53 290 #include "psa/crypto.h"
ccli8 29:e890b0fdce53 291 #include "KVStore.h"
ccli8 29:e890b0fdce53 292 #include "TDBStore.h"
ccli8 29:e890b0fdce53 293 #include "KVMap.h"
ccli8 29:e890b0fdce53 294 #include "kv_config.h"
ccli8 29:e890b0fdce53 295
ccli8 29:e890b0fdce53 296 extern "C" {
ccli8 29:e890b0fdce53 297 psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size);
ccli8 29:e890b0fdce53 298 int mbedtls_platform_seed_read(unsigned char *buf, size_t buf_len);
ccli8 29:e890b0fdce53 299 int mbedtls_platform_seed_write(unsigned char *buf, size_t buf_len);
ccli8 29:e890b0fdce53 300 }
ccli8 29:e890b0fdce53 301
ccli8 29:e890b0fdce53 302 /* Requirement of seed size
ccli8 29:e890b0fdce53 303 *
ccli8 29:e890b0fdce53 304 * 1. >= MBEDTLS_ENTROPY_MIN_PLATFORM
ccli8 29:e890b0fdce53 305 * 2. >= MBEDTLS_ENTROPY_BLOCK_SIZE
ccli8 29:e890b0fdce53 306 * 3. <= MBEDTLS_ENTROPY_MAX_SEED_SIZE
ccli8 29:e890b0fdce53 307 */
ccli8 29:e890b0fdce53 308 #define SEED_SIZE 64
ccli8 29:e890b0fdce53 309 MBED_STATIC_ASSERT(SEED_SIZE >= MBEDTLS_ENTROPY_MIN_PLATFORM, "Seed size must be larger than or equal to MBEDTLS_ENTROPY_MIN_PLATFORM");
ccli8 29:e890b0fdce53 310 MBED_STATIC_ASSERT(SEED_SIZE >= MBEDTLS_ENTROPY_BLOCK_SIZE, "Seed size must be larger than or equal to MBEDTLS_ENTROPY_BLOCK_SIZE");
ccli8 29:e890b0fdce53 311 MBED_STATIC_ASSERT(SEED_SIZE <= MBEDTLS_ENTROPY_MAX_SEED_SIZE, "Seed size must be smaller than or equal to MBEDTLS_ENTROPY_MAX_SEED_SIZE");
ccli8 29:e890b0fdce53 312
ccli8 29:e890b0fdce53 313 /* Seed key name in kvstore */
ccli8 29:e890b0fdce53 314 #define KV_KEY_SEED "seed"
ccli8 29:e890b0fdce53 315
ccli8 29:e890b0fdce53 316 /* Inject an initial entropy seed for the random generator into secure storage
ccli8 29:e890b0fdce53 317 *
ccli8 29:e890b0fdce53 318 * See reference below for its prototype:
ccli8 29:e890b0fdce53 319 * https://github.com/ARMmbed/mbed-os/blob/master/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h
ccli8 29:e890b0fdce53 320 */
ccli8 29:e890b0fdce53 321 psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size)
ccli8 29:e890b0fdce53 322 {
ccli8 29:e890b0fdce53 323 /* Check seed size requirement */
ccli8 29:e890b0fdce53 324 if ((( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) ||
ccli8 29:e890b0fdce53 325 (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) {
ccli8 29:e890b0fdce53 326 return PSA_ERROR_INVALID_ARGUMENT;
ccli8 29:e890b0fdce53 327 }
ccli8 29:e890b0fdce53 328
ccli8 29:e890b0fdce53 329 /* Get kvstore internal storage where seed is injected */
ccli8 29:e890b0fdce53 330 KVMap &kv_map = KVMap::get_instance();
ccli8 29:e890b0fdce53 331 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
ccli8 29:e890b0fdce53 332 if (inner_store == NULL) {
ccli8 29:e890b0fdce53 333 return PSA_ERROR_STORAGE_FAILURE;
ccli8 29:e890b0fdce53 334 }
ccli8 29:e890b0fdce53 335
ccli8 29:e890b0fdce53 336 /* Check if seed has injected */
ccli8 29:e890b0fdce53 337 KVStore::info_t kv_info;
ccli8 29:e890b0fdce53 338 int kv_status = inner_store->get_info(KV_KEY_SEED, &kv_info);
ccli8 29:e890b0fdce53 339 if (kv_status == MBED_SUCCESS) {
ccli8 29:e890b0fdce53 340 return PSA_ERROR_NOT_PERMITTED;
ccli8 29:e890b0fdce53 341 } else if (kv_status == MBED_ERROR_ITEM_NOT_FOUND) {
ccli8 29:e890b0fdce53 342 /* No seed injected, inject it below */
ccli8 29:e890b0fdce53 343 } else {
ccli8 29:e890b0fdce53 344 return PSA_ERROR_STORAGE_FAILURE;
ccli8 29:e890b0fdce53 345 }
ccli8 29:e890b0fdce53 346
ccli8 29:e890b0fdce53 347 /* Inject seed into kvstore internal storage */
ccli8 29:e890b0fdce53 348 kv_status = inner_store->set(KV_KEY_SEED, seed, seed_size, 0);
ccli8 29:e890b0fdce53 349 if (kv_status == MBED_SUCCESS) {
ccli8 29:e890b0fdce53 350 return PSA_SUCCESS;
ccli8 29:e890b0fdce53 351 } else {
ccli8 29:e890b0fdce53 352 return PSA_ERROR_STORAGE_FAILURE;
ccli8 29:e890b0fdce53 353 }
ccli8 29:e890b0fdce53 354 }
ccli8 29:e890b0fdce53 355
ccli8 29:e890b0fdce53 356 int mbedtls_platform_seed_read(unsigned char *buf, size_t buf_len)
ccli8 29:e890b0fdce53 357 {
ccli8 29:e890b0fdce53 358 /* Get kvstore internal storage where seed is injected */
ccli8 29:e890b0fdce53 359 KVMap &kv_map = KVMap::get_instance();
ccli8 29:e890b0fdce53 360 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
ccli8 29:e890b0fdce53 361 if (inner_store == NULL) {
ccli8 29:e890b0fdce53 362 return -1;
ccli8 29:e890b0fdce53 363 }
ccli8 29:e890b0fdce53 364
ccli8 29:e890b0fdce53 365 /* Read seed from kvstore internal storage */
ccli8 29:e890b0fdce53 366 size_t actual_size = 0;
ccli8 29:e890b0fdce53 367 int kv_status = inner_store->get(KV_KEY_SEED, buf, buf_len, &actual_size, 0);
ccli8 29:e890b0fdce53 368 if (kv_status != MBED_SUCCESS || actual_size != buf_len) {
ccli8 29:e890b0fdce53 369 return -1;
ccli8 29:e890b0fdce53 370 } else {
ccli8 29:e890b0fdce53 371 return buf_len;
ccli8 29:e890b0fdce53 372 }
ccli8 29:e890b0fdce53 373 }
ccli8 29:e890b0fdce53 374
ccli8 29:e890b0fdce53 375 int mbedtls_platform_seed_write(unsigned char *buf, size_t buf_len)
ccli8 29:e890b0fdce53 376 {
ccli8 29:e890b0fdce53 377 /* Get kvstore internal storage where seed is injected */
ccli8 29:e890b0fdce53 378 KVMap &kv_map = KVMap::get_instance();
ccli8 29:e890b0fdce53 379 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
ccli8 29:e890b0fdce53 380 if (inner_store == NULL) {
ccli8 29:e890b0fdce53 381 return -1;
ccli8 29:e890b0fdce53 382 }
ccli8 29:e890b0fdce53 383
ccli8 29:e890b0fdce53 384 /* Write seed into kvstore internal storage */
ccli8 29:e890b0fdce53 385 int kv_status = inner_store->set(KV_KEY_SEED, buf, buf_len, 0);
ccli8 29:e890b0fdce53 386 if (kv_status != MBED_SUCCESS) {
ccli8 29:e890b0fdce53 387 return -1;
ccli8 29:e890b0fdce53 388 } else {
ccli8 29:e890b0fdce53 389 return buf_len;
ccli8 29:e890b0fdce53 390 }
ccli8 29:e890b0fdce53 391 }
ccli8 29:e890b0fdce53 392
ccli8 29:e890b0fdce53 393 #endif /* #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) */
ccli8 29:e890b0fdce53 394
ccli8 29:e890b0fdce53 395 #endif /* !DEVICE_TRNG && !TARGET_PSA */