v / thirdparty / mbedtls / library / psa_crypto_random_impl.h
200 lines · 176 sloc · 6.89 KB · 3d9911f887ecec942f9ae2a5be02d064f233b729
Raw
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
17typedef 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)
63typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
64#elif defined(MBEDTLS_HMAC_DRBG_C)
65typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
66#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
67
68typedef 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 */
96static 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 */
109static 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 */
131static 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 */
154static 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 */
172static 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 */
186static 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