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

Dependencies:   MQTT

Committer:
ccli8
Date:
Fri Mar 27 14:32:06 2020 +0800
Revision:
41:b878d7cd7035
Parent:
33:c3a985807206
Child:
42:fa6f7f79a112
Make code work across mbed-os 5.15/6.x

1. Replace deprecated API
2. Re-implement MyTLSSocket with Mbed OS internal TLSSocket
3. Fix PRNG driver calling code with M480 BSP update

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 41:b878d7cd7035 183 #if TARGET_NUC472 || (MBED_MAJOR_VERSION < 6)
ccli8 29:e890b0fdce53 184 PRNG_ENABLE_INT();
ccli8 41:b878d7cd7035 185 #else
ccli8 41:b878d7cd7035 186 PRNG_ENABLE_INT(CRPT);
ccli8 41:b878d7cd7035 187 #endif
ccli8 33:c3a985807206 188 #endif
ccli8 29:e890b0fdce53 189
ccli8 29:e890b0fdce53 190 uint32_t seed = 0;
ccli8 29:e890b0fdce53 191 unsigned i = 32;
ccli8 29:e890b0fdce53 192
ccli8 29:e890b0fdce53 193 /* Get seed from EADC band gap */
ccli8 29:e890b0fdce53 194 while (i --) {
ccli8 29:e890b0fdce53 195 seed <<= 1;
ccli8 29:e890b0fdce53 196 seed |= band_gap.read_bitstream();
ccli8 29:e890b0fdce53 197 }
ccli8 29:e890b0fdce53 198
ccli8 33:c3a985807206 199 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 200 /* PRNG reload seed */
ccli8 41:b878d7cd7035 201 #if TARGET_NUC472 || (MBED_MAJOR_VERSION < 6)
ccli8 29:e890b0fdce53 202 PRNG_Open(PRNG_KEYSIZE_ID, 1, seed);
ccli8 33:c3a985807206 203 #else
ccli8 41:b878d7cd7035 204 PRNG_Open(CRPT, PRNG_KEYSIZE_ID, 1, seed);
ccli8 41:b878d7cd7035 205 #endif
ccli8 41:b878d7cd7035 206 #else
ccli8 33:c3a985807206 207 srand(seed);
ccli8 33:c3a985807206 208 #endif /* #if NU_CRYPTO_PRNG_PRESENT */
ccli8 29:e890b0fdce53 209 }
ccli8 29:e890b0fdce53 210
ccli8 33:c3a985807206 211 NuEADCSeedRandom::~NuEADCSeedRandom()
ccli8 29:e890b0fdce53 212 {
ccli8 33:c3a985807206 213 #if NU_CRYPTO_PRNG_PRESENT
ccli8 41:b878d7cd7035 214 #if TARGET_NUC472 || (MBED_MAJOR_VERSION < 6)
ccli8 29:e890b0fdce53 215 PRNG_DISABLE_INT();
ccli8 41:b878d7cd7035 216 #else
ccli8 41:b878d7cd7035 217 PRNG_DISABLE_INT(CRPT);
ccli8 41:b878d7cd7035 218 #endif
ccli8 29:e890b0fdce53 219 crypto_uninit();
ccli8 33:c3a985807206 220 #endif /* #if NU_CRYPTO_PRNG_PRESENT */
ccli8 29:e890b0fdce53 221 }
ccli8 29:e890b0fdce53 222
ccli8 33:c3a985807206 223 int NuEADCSeedRandom::get_bytes(unsigned char *output, size_t len, size_t *olen)
ccli8 29:e890b0fdce53 224 {
ccli8 29:e890b0fdce53 225 /* Check argument validity */
ccli8 29:e890b0fdce53 226 if (!output && len) {
ccli8 29:e890b0fdce53 227 return -1;
ccli8 29:e890b0fdce53 228 }
ccli8 29:e890b0fdce53 229
ccli8 33:c3a985807206 230 #if NU_CRYPTO_PRNG_PRESENT
ccli8 29:e890b0fdce53 231 unsigned char *output_ind = output;
ccli8 29:e890b0fdce53 232 size_t rmn = len;
ccli8 29:e890b0fdce53 233 uint32_t rand_data[PRNG_KEYSIZE / sizeof(uint32_t)];
ccli8 29:e890b0fdce53 234 while (rmn) {
ccli8 29:e890b0fdce53 235 crypto_prng_prestart();
ccli8 41:b878d7cd7035 236 #if TARGET_NUC472 || (MBED_MAJOR_VERSION < 6)
ccli8 29:e890b0fdce53 237 PRNG_Start();
ccli8 41:b878d7cd7035 238 #else
ccli8 41:b878d7cd7035 239 PRNG_Start(CRPT);
ccli8 41:b878d7cd7035 240 #endif
ccli8 29:e890b0fdce53 241 crypto_prng_wait();
ccli8 29:e890b0fdce53 242
ccli8 41:b878d7cd7035 243 #if TARGET_NUC472 || (MBED_MAJOR_VERSION < 6)
ccli8 29:e890b0fdce53 244 PRNG_Read(rand_data);
ccli8 41:b878d7cd7035 245 #else
ccli8 41:b878d7cd7035 246 PRNG_Read(CRPT, rand_data);
ccli8 41:b878d7cd7035 247 #endif
ccli8 29:e890b0fdce53 248 size_t n = (rmn >= PRNG_KEYSIZE) ? PRNG_KEYSIZE : rmn;
ccli8 29:e890b0fdce53 249 memcpy(output_ind, rand_data, n);
ccli8 29:e890b0fdce53 250
ccli8 29:e890b0fdce53 251 output_ind += n;
ccli8 29:e890b0fdce53 252 rmn -= n;
ccli8 29:e890b0fdce53 253 }
ccli8 33:c3a985807206 254 #else
ccli8 33:c3a985807206 255 unsigned char *output_ind = output;
ccli8 33:c3a985807206 256 size_t rmn = len;
ccli8 33:c3a985807206 257 while (rmn) {
ccli8 33:c3a985807206 258 *output_ind ++ = rand() % 256;
ccli8 33:c3a985807206 259 rmn --;
ccli8 33:c3a985807206 260 }
ccli8 33:c3a985807206 261 #endif /* #if NU_CRYPTO_PRNG_PRESENT */
ccli8 29:e890b0fdce53 262
ccli8 29:e890b0fdce53 263 if (olen) {
ccli8 29:e890b0fdce53 264 *olen = len;
ccli8 29:e890b0fdce53 265 }
ccli8 29:e890b0fdce53 266
ccli8 29:e890b0fdce53 267 return 0;
ccli8 29:e890b0fdce53 268 }
ccli8 29:e890b0fdce53 269
ccli8 29:e890b0fdce53 270 #else
ccli8 29:e890b0fdce53 271
ccli8 29:e890b0fdce53 272 /* Support entropy source with mbedtls NV seed on non-PSA targets without TRNG
ccli8 29:e890b0fdce53 273 *
ccli8 29:e890b0fdce53 274 * Follow the steps below to replace TRNG with mbedtls NV seed:
ccli8 29:e890b0fdce53 275 *
ccli8 29:e890b0fdce53 276 * 1. Define MBEDTLS_ENTROPY_NV_SEED
ccli8 29:e890b0fdce53 277 * 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 278 * 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 279 * 4. For development, simulating partial provision process, inject entropy seed via mbedtls_psa_inject_entropy(...) pre-main.
ccli8 29:e890b0fdce53 280 *
ccli8 29:e890b0fdce53 281 * Reference configuration in mbed_app.json:
ccli8 29:e890b0fdce53 282 *
ccli8 29:e890b0fdce53 283 * For Pelion/mbedtls, don't define MBEDTLS_ENTROPY_NV_SEED because it has defined in:
ccli8 29:e890b0fdce53 284 * https://github.com/ARMmbed/mbed-cloud-client/blob/master/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS_SW_TRNG.h
ccli8 29:e890b0fdce53 285 *
ccli8 29:e890b0fdce53 286 * "target.macros_add": [
ccli8 29:e890b0fdce53 287 * "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS_SW_TRNG.h\"",
ccli8 29:e890b0fdce53 288 * "PAL_USE_HW_TRNG=0",
ccli8 29:e890b0fdce53 289 * "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO=mbedtls_platform_seed_read",
ccli8 29:e890b0fdce53 290 * "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO=mbedtls_platform_seed_write"
ccli8 29:e890b0fdce53 291 * ],
ccli8 29:e890b0fdce53 292 *
ccli8 29:e890b0fdce53 293 * For non-Pelion/mbedtls:
ccli8 29:e890b0fdce53 294 *
ccli8 29:e890b0fdce53 295 * "target.macros_add": [
ccli8 29:e890b0fdce53 296 * "MBEDTLS_ENTROPY_NV_SEED",
ccli8 29:e890b0fdce53 297 * "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO=mbedtls_platform_seed_read",
ccli8 29:e890b0fdce53 298 * "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO=mbedtls_platform_seed_write"
ccli8 29:e890b0fdce53 299 * ],
ccli8 29:e890b0fdce53 300 *
ccli8 29:e890b0fdce53 301 * For both Pelion/non-Pelion (skip when done in targets.json):
ccli8 29:e890b0fdce53 302 *
ccli8 29:e890b0fdce53 303 * "target.device_has_remove": ["TRNG"],
ccli8 29:e890b0fdce53 304 *
ccli8 29:e890b0fdce53 305 * WARNING: The injection of mbedtls NV seed pre-main is only for development. Run provision process for mass production.
ccli8 29:e890b0fdce53 306 */
ccli8 29:e890b0fdce53 307
ccli8 29:e890b0fdce53 308 #include "entropy_poll.h"
ccli8 29:e890b0fdce53 309 #include "psa/crypto.h"
ccli8 29:e890b0fdce53 310 #include "KVStore.h"
ccli8 29:e890b0fdce53 311 #include "TDBStore.h"
ccli8 29:e890b0fdce53 312 #include "KVMap.h"
ccli8 29:e890b0fdce53 313 #include "kv_config.h"
ccli8 29:e890b0fdce53 314
ccli8 29:e890b0fdce53 315 extern "C" {
ccli8 29:e890b0fdce53 316 psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size);
ccli8 29:e890b0fdce53 317 int mbedtls_platform_seed_read(unsigned char *buf, size_t buf_len);
ccli8 29:e890b0fdce53 318 int mbedtls_platform_seed_write(unsigned char *buf, size_t buf_len);
ccli8 29:e890b0fdce53 319 }
ccli8 29:e890b0fdce53 320
ccli8 29:e890b0fdce53 321 /* Requirement of seed size
ccli8 29:e890b0fdce53 322 *
ccli8 29:e890b0fdce53 323 * 1. >= MBEDTLS_ENTROPY_MIN_PLATFORM
ccli8 29:e890b0fdce53 324 * 2. >= MBEDTLS_ENTROPY_BLOCK_SIZE
ccli8 29:e890b0fdce53 325 * 3. <= MBEDTLS_ENTROPY_MAX_SEED_SIZE
ccli8 29:e890b0fdce53 326 */
ccli8 29:e890b0fdce53 327 #define SEED_SIZE 64
ccli8 29:e890b0fdce53 328 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 329 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 330 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 331
ccli8 29:e890b0fdce53 332 /* Seed key name in kvstore */
ccli8 29:e890b0fdce53 333 #define KV_KEY_SEED "seed"
ccli8 29:e890b0fdce53 334
ccli8 29:e890b0fdce53 335 /* Inject an initial entropy seed for the random generator into secure storage
ccli8 29:e890b0fdce53 336 *
ccli8 29:e890b0fdce53 337 * See reference below for its prototype:
ccli8 29:e890b0fdce53 338 * https://github.com/ARMmbed/mbed-os/blob/master/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h
ccli8 29:e890b0fdce53 339 */
ccli8 29:e890b0fdce53 340 psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size)
ccli8 29:e890b0fdce53 341 {
ccli8 29:e890b0fdce53 342 /* Check seed size requirement */
ccli8 29:e890b0fdce53 343 if ((( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) ||
ccli8 29:e890b0fdce53 344 (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) {
ccli8 29:e890b0fdce53 345 return PSA_ERROR_INVALID_ARGUMENT;
ccli8 29:e890b0fdce53 346 }
ccli8 29:e890b0fdce53 347
ccli8 29:e890b0fdce53 348 /* Get kvstore internal storage where seed is injected */
ccli8 29:e890b0fdce53 349 KVMap &kv_map = KVMap::get_instance();
ccli8 29:e890b0fdce53 350 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
ccli8 29:e890b0fdce53 351 if (inner_store == NULL) {
ccli8 29:e890b0fdce53 352 return PSA_ERROR_STORAGE_FAILURE;
ccli8 29:e890b0fdce53 353 }
ccli8 29:e890b0fdce53 354
ccli8 29:e890b0fdce53 355 /* Check if seed has injected */
ccli8 29:e890b0fdce53 356 KVStore::info_t kv_info;
ccli8 29:e890b0fdce53 357 int kv_status = inner_store->get_info(KV_KEY_SEED, &kv_info);
ccli8 29:e890b0fdce53 358 if (kv_status == MBED_SUCCESS) {
ccli8 29:e890b0fdce53 359 return PSA_ERROR_NOT_PERMITTED;
ccli8 29:e890b0fdce53 360 } else if (kv_status == MBED_ERROR_ITEM_NOT_FOUND) {
ccli8 29:e890b0fdce53 361 /* No seed injected, inject it below */
ccli8 29:e890b0fdce53 362 } else {
ccli8 29:e890b0fdce53 363 return PSA_ERROR_STORAGE_FAILURE;
ccli8 29:e890b0fdce53 364 }
ccli8 29:e890b0fdce53 365
ccli8 29:e890b0fdce53 366 /* Inject seed into kvstore internal storage */
ccli8 29:e890b0fdce53 367 kv_status = inner_store->set(KV_KEY_SEED, seed, seed_size, 0);
ccli8 29:e890b0fdce53 368 if (kv_status == MBED_SUCCESS) {
ccli8 29:e890b0fdce53 369 return PSA_SUCCESS;
ccli8 29:e890b0fdce53 370 } else {
ccli8 29:e890b0fdce53 371 return PSA_ERROR_STORAGE_FAILURE;
ccli8 29:e890b0fdce53 372 }
ccli8 29:e890b0fdce53 373 }
ccli8 29:e890b0fdce53 374
ccli8 29:e890b0fdce53 375 int mbedtls_platform_seed_read(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 /* Read seed from kvstore internal storage */
ccli8 29:e890b0fdce53 385 size_t actual_size = 0;
ccli8 29:e890b0fdce53 386 int kv_status = inner_store->get(KV_KEY_SEED, buf, buf_len, &actual_size, 0);
ccli8 29:e890b0fdce53 387 if (kv_status != MBED_SUCCESS || actual_size != buf_len) {
ccli8 29:e890b0fdce53 388 return -1;
ccli8 29:e890b0fdce53 389 } else {
ccli8 29:e890b0fdce53 390 return buf_len;
ccli8 29:e890b0fdce53 391 }
ccli8 29:e890b0fdce53 392 }
ccli8 29:e890b0fdce53 393
ccli8 29:e890b0fdce53 394 int mbedtls_platform_seed_write(unsigned char *buf, size_t buf_len)
ccli8 29:e890b0fdce53 395 {
ccli8 29:e890b0fdce53 396 /* Get kvstore internal storage where seed is injected */
ccli8 29:e890b0fdce53 397 KVMap &kv_map = KVMap::get_instance();
ccli8 29:e890b0fdce53 398 KVStore *inner_store = kv_map.get_internal_kv_instance(NULL);
ccli8 29:e890b0fdce53 399 if (inner_store == NULL) {
ccli8 29:e890b0fdce53 400 return -1;
ccli8 29:e890b0fdce53 401 }
ccli8 29:e890b0fdce53 402
ccli8 29:e890b0fdce53 403 /* Write seed into kvstore internal storage */
ccli8 29:e890b0fdce53 404 int kv_status = inner_store->set(KV_KEY_SEED, buf, buf_len, 0);
ccli8 29:e890b0fdce53 405 if (kv_status != MBED_SUCCESS) {
ccli8 29:e890b0fdce53 406 return -1;
ccli8 29:e890b0fdce53 407 } else {
ccli8 29:e890b0fdce53 408 return buf_len;
ccli8 29:e890b0fdce53 409 }
ccli8 29:e890b0fdce53 410 }
ccli8 29:e890b0fdce53 411
ccli8 29:e890b0fdce53 412 #endif /* #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) */
ccli8 29:e890b0fdce53 413
ccli8 29:e890b0fdce53 414 #endif /* !DEVICE_TRNG && !TARGET_PSA */