| 1 | /** \file psa_crypto_random_impl.h |
| 2 | * |
| 3 | * \brief PSA crypto random generator implementation abstraction. |
| 4 | */ |
| 5 | /* |
| 6 | * Copyright The Mbed TLS Contributors |
| 7 | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
| 8 | */ |
| 9 | |
| 10 | #ifndef PSA_CRYPTO_RANDOM_IMPL_H |
| 11 | #define PSA_CRYPTO_RANDOM_IMPL_H |
| 12 | |
| 13 | #include "psa_util_internal.h" |
| 14 | |
| 15 | #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) |
| 16 | |
| 17 | typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t; |
| 18 | |
| 19 | #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ |
| 20 | |
| 21 | #include "mbedtls/entropy.h" |
| 22 | |
| 23 | /* Choose a DRBG based on configuration and availability */ |
| 24 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 25 | |
| 26 | #include "mbedtls/ctr_drbg.h" |
| 27 | #undef MBEDTLS_PSA_HMAC_DRBG_MD_TYPE |
| 28 | |
| 29 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 30 | |
| 31 | #include "mbedtls/hmac_drbg.h" |
| 32 | #if defined(MBEDTLS_MD_CAN_SHA512) && defined(MBEDTLS_MD_CAN_SHA256) |
| 33 | #include <limits.h> |
| 34 | #if SIZE_MAX > 0xffffffff |
| 35 | /* Looks like a 64-bit system, so prefer SHA-512. */ |
| 36 | #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 |
| 37 | #else |
| 38 | /* Looks like a 32-bit system, so prefer SHA-256. */ |
| 39 | #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 |
| 40 | #endif |
| 41 | #elif defined(MBEDTLS_MD_CAN_SHA512) |
| 42 | #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 |
| 43 | #elif defined(MBEDTLS_MD_CAN_SHA256) |
| 44 | #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 |
| 45 | #else |
| 46 | #error "No hash algorithm available for HMAC_DBRG." |
| 47 | #endif |
| 48 | |
| 49 | #else /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ |
| 50 | |
| 51 | #error "No DRBG module available for the psa_crypto module." |
| 52 | |
| 53 | #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ |
| 54 | |
| 55 | /* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */ |
| 56 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 57 | #define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST |
| 58 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 59 | #define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST |
| 60 | #endif |
| 61 | |
| 62 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 63 | typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; |
| 64 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 65 | typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; |
| 66 | #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ |
| 67 | |
| 68 | typedef struct { |
| 69 | void (* entropy_init)(mbedtls_entropy_context *ctx); |
| 70 | void (* entropy_free)(mbedtls_entropy_context *ctx); |
| 71 | mbedtls_entropy_context entropy; |
| 72 | mbedtls_psa_drbg_context_t drbg; |
| 73 | #if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) |
| 74 | /* Fork protection: normally pid = getpid(). If the value changes, |
| 75 | * we are in a (grand)*child of the original process, so reseed |
| 76 | * the RNG to ensure that the child and the original process have |
| 77 | * distinct RNG states. See psa_random_internal_generate(). |
| 78 | * |
| 79 | * The type is intmax_t, not pid_t, for portability reasons: |
| 80 | * pid_t is defined in `unistd.h`, but on some platforms, it may |
| 81 | * only be defined if a certain compatibility level is requested |
| 82 | * by defining a macro such as _POSIX_C_SOURCE or _XOPEN_SOURCE. |
| 83 | * The macro needs to be defined before any system header, which |
| 84 | * may be hard to do in some C files that include this header |
| 85 | * (e.g. test suites). So we sidestep this complication, at the |
| 86 | * cost of possibly a few more instructions to compare pid values. |
| 87 | */ |
| 88 | intmax_t pid; |
| 89 | #endif |
| 90 | } mbedtls_psa_random_context_t; |
| 91 | |
| 92 | /** Initialize the PSA DRBG. |
| 93 | * |
| 94 | * \param p_rng Pointer to the Mbed TLS DRBG state. |
| 95 | */ |
| 96 | static inline void mbedtls_psa_drbg_init(mbedtls_psa_drbg_context_t *p_rng) |
| 97 | { |
| 98 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 99 | mbedtls_ctr_drbg_init(p_rng); |
| 100 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 101 | mbedtls_hmac_drbg_init(p_rng); |
| 102 | #endif |
| 103 | } |
| 104 | |
| 105 | /** Deinitialize the PSA DRBG. |
| 106 | * |
| 107 | * \param p_rng Pointer to the Mbed TLS DRBG state. |
| 108 | */ |
| 109 | static inline void mbedtls_psa_drbg_free(mbedtls_psa_drbg_context_t *p_rng) |
| 110 | { |
| 111 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 112 | mbedtls_ctr_drbg_free(p_rng); |
| 113 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 114 | mbedtls_hmac_drbg_free(p_rng); |
| 115 | #endif |
| 116 | } |
| 117 | |
| 118 | /** Seed the PSA DRBG. |
| 119 | * |
| 120 | * \param drbg_ctx The DRBG context to seed. |
| 121 | * It must be initialized but not active. |
| 122 | * \param entropy An entropy context to read the seed from. |
| 123 | * \param custom The personalization string. |
| 124 | * This can be \c NULL, in which case the personalization |
| 125 | * string is empty regardless of the value of \p len. |
| 126 | * \param len The length of the personalization string. |
| 127 | * |
| 128 | * \return \c 0 on success. |
| 129 | * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure. |
| 130 | */ |
| 131 | static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx, |
| 132 | mbedtls_entropy_context *entropy, |
| 133 | const unsigned char *custom, size_t len) |
| 134 | { |
| 135 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 136 | return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len); |
| 137 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 138 | const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE); |
| 139 | return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len); |
| 140 | #endif |
| 141 | } |
| 142 | |
| 143 | /** Reseed the PSA DRBG. |
| 144 | * |
| 145 | * \param drbg_ctx The DRBG context to reseed. |
| 146 | * It must be active. |
| 147 | * \param additional Additional data to inject. |
| 148 | * \param len The length of \p additional in bytes. |
| 149 | * This can be 0 to simply reseed from the entropy source. |
| 150 | * |
| 151 | * \return \c 0 on success. |
| 152 | * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure. |
| 153 | */ |
| 154 | static inline int mbedtls_psa_drbg_reseed(mbedtls_psa_drbg_context_t *drbg_ctx, |
| 155 | const unsigned char *additional, |
| 156 | size_t len) |
| 157 | { |
| 158 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 159 | return mbedtls_ctr_drbg_reseed(drbg_ctx, additional, len); |
| 160 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 161 | return mbedtls_hmac_drbg_reseed(drbg_ctx, additional, len); |
| 162 | #endif |
| 163 | } |
| 164 | |
| 165 | /** Deplete the PSA DRBG, i.e. cause it to reseed the next time it is used. |
| 166 | * |
| 167 | * \note This function is not thread-safe. |
| 168 | * |
| 169 | * \param drbg_ctx The DRBG context to deplete. |
| 170 | * It must be active. |
| 171 | */ |
| 172 | static inline void mbedtls_psa_drbg_deplete(mbedtls_psa_drbg_context_t *drbg_ctx) |
| 173 | { |
| 174 | drbg_ctx->reseed_counter = drbg_ctx->reseed_interval; |
| 175 | } |
| 176 | |
| 177 | #if MBEDTLS_ENTROPY_TRUE_SOURCES > 0 |
| 178 | /** Set prediction resistance in the PSA DRBG. |
| 179 | * |
| 180 | * \note This function is not thread-safe. |
| 181 | * |
| 182 | * \param drbg_ctx The DRBG context to reconfigure. |
| 183 | * It must be active. |
| 184 | * \param enabled \c 1 to enable, or \c 0 to disable. |
| 185 | */ |
| 186 | static inline void mbedtls_psa_drbg_set_prediction_resistance( |
| 187 | mbedtls_psa_drbg_context_t *drbg_ctx, |
| 188 | unsigned enabled) |
| 189 | { |
| 190 | #if defined(MBEDTLS_CTR_DRBG_C) |
| 191 | mbedtls_ctr_drbg_set_prediction_resistance(drbg_ctx, enabled); |
| 192 | #elif defined(MBEDTLS_HMAC_DRBG_C) |
| 193 | mbedtls_hmac_drbg_set_prediction_resistance(drbg_ctx, enabled); |
| 194 | #endif |
| 195 | } |
| 196 | #endif /* MBEDTLS_ENTROPY_TRUE_SOURCES > 0 */ |
| 197 | |
| 198 | #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ |
| 199 | |
| 200 | #endif /* PSA_CRYPTO_RANDOM_IMPL_H */ |
| 201 | |