NuMaker connection with AWS IoT thru MQTT/HTTPS
Dependencies: MQTT
targets/TARGET_NUVOTON/platform_entropy.cpp@41:b878d7cd7035, 2020-03-27 (annotated)
- 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?
User | Revision | Line number | New 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 */ |