1 /*
2 * Copyright (c) 2023-2024, The TrustedFirmware-M Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 /** @file cc3xx_psa_random.c
9 *
10 * This file contains the implementations of the entry points associated to the
11 * random generation capability as described by the PSA Cryptoprocessor Driver
12 * interface specification.
13 */
14 #include "cc3xx_psa_api_config.h"
15
16 #include "cc3xx_psa_random.h"
17 #include "cc3xx_misc.h"
18 #include "cc3xx_error.h"
19 #include "cc3xx_drbg.h"
20 #include "cc3xx_rng.h"
21
22 /* Include the definition of the context types */
23 #include "cc3xx_crypto_primitives_private.h"
24
25 #if defined(CC3XX_CONFIG_ENABLE_RANDOM_HASH_DRBG) + \
26 defined(CC3XX_CONFIG_ENABLE_RANDOM_HMAC_DRBG) + \
27 defined(CC3XX_CONFIG_ENABLE_RANDOM_CTR_DRBG) != 1
28 #error "CC3XX configuration must have a single DRBG construction enabled"
29 #endif
30
31 struct random_context_params_t {
32 cc3xx_drbg_id_t type;
33 size_t initial_entropy_size;
34 size_t reseed_entropy_size;
35 };
36
37 /* Keep the context private to this module */
38 static struct {
39 cc3xx_random_context_t ctx;
40 bool isInitialized;
41 } cc3xx_psa_random_state;
42
43 /** @defgroup psa_random PSA driver entry points for collecting random
44 * numbers generated using an underlying DRBG
45 * mechanism
46 *
47 * Entry points random init, add_entropy and collection as described by
48 * the PSA Cryptoprocessor Driver interface specification.
49 *
50 * @{
51 */
cc3xx_init_random(cc3xx_random_context_t * context)52 psa_status_t cc3xx_init_random(cc3xx_random_context_t *context)
53 {
54 cc3xx_err_t err;
55 const struct random_context_params_t conf = {
56 #if defined(CC3XX_CONFIG_ENABLE_RANDOM_CTR_DRBG)
57 .type = CC3XX_DRBG_CTR, .initial_entropy_size = 32, .reseed_entropy_size = 32
58 #elif defined(CC3XX_CONFIG_ENABLE_RANDOM_HMAC_DRBG)
59 .type = CC3XX_DRBG_HMAC, .initial_entropy_size = 32, .reseed_entropy_size = 32
60 #elif defined(CC3XX_CONFIG_ENABLE_RANDOM_HASH_DRBG)
61 .type = CC3XX_DRBG_HASH, .initial_entropy_size = 32, .reseed_entropy_size = 32
62 #endif
63 };
64 uint8_t initial_entropy[conf.initial_entropy_size];
65
66 CC3XX_ASSERT(context != NULL);
67
68 err = cc3xx_lowlevel_rng_get_random(initial_entropy, sizeof(initial_entropy));
69 if (err != CC3XX_ERR_SUCCESS) {
70 return cc3xx_to_psa_err(err);
71 }
72
73 err = cc3xx_lowlevel_drbg_init(conf.type, &(context->state),
74 initial_entropy, sizeof(initial_entropy),
75 NULL, 0, NULL, 0);
76 if (err != CC3XX_ERR_SUCCESS) {
77 return cc3xx_to_psa_err(err);
78 }
79
80 return PSA_SUCCESS;
81 }
82
cc3xx_add_entropy(cc3xx_random_context_t * context,const uint8_t * entropy,size_t entropy_size)83 psa_status_t cc3xx_add_entropy(
84 cc3xx_random_context_t *context,
85 const uint8_t *entropy,
86 size_t entropy_size)
87 {
88 #ifdef CC3XX_CONFIG_ENABLE_RANDOM_CTR_DRBG
89 if (entropy_size != 32) {
90 return PSA_ERROR_INVALID_ARGUMENT;
91 }
92 #endif
93
94 /* Probably not needed to implement the logic of add_entropy as the expectation
95 * is that the driver will work as a FULL RNG driver, i.e. it takes care on its
96 * own of seeding and reseeding, which means its external initial_entropy_size
97 * and reseed_entropy_size properties will be set to 0, hence the core in that
98 * case would never call this entry point. In case the design changes, this
99 * entry point must just interface with cc3xx_drbg_reseed()
100 */
101 return PSA_ERROR_NOT_SUPPORTED;
102 }
103
cc3xx_get_random(cc3xx_random_context_t * context,uint8_t * output,size_t output_size,size_t * output_length)104 psa_status_t cc3xx_get_random(cc3xx_random_context_t *context,
105 uint8_t *output,
106 size_t output_size,
107 size_t *output_length)
108 {
109 cc3xx_err_t err;
110
111 CC3XX_ASSERT(context != NULL);
112 CC3XX_ASSERT(output != NULL);
113 CC3XX_ASSERT(output_length != NULL);
114
115 err = cc3xx_lowlevel_drbg_generate(&(context->state), output_size * 8, output, NULL, 0);
116 if (err != CC3XX_ERR_SUCCESS) {
117 *output_length = 0;
118 return cc3xx_to_psa_err(err);
119 }
120
121 *output_length = output_size;
122 return PSA_SUCCESS;
123 }
124
125 /* As of mbed TLS 3.5, there is no support in the Core for the random entry points,
126 * so the integration happens through the definition of MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
127 * as the function that mbed TLS uses to retrieve random numbers from an external
128 * generator. Note that we don't rely on redefining the type
129 * mbedtls_psa_external_random_context_t available to the PSA Crypto core to make
130 * keep integration simple, as there is no real gain in doing that.
131 */
mbedtls_psa_external_get_random(mbedtls_psa_external_random_context_t * context,uint8_t * output,size_t output_size,size_t * output_length)132 psa_status_t mbedtls_psa_external_get_random(
133 mbedtls_psa_external_random_context_t *context,
134 uint8_t *output, size_t output_size, size_t *output_length)
135 {
136 psa_status_t status;
137 (void)context; /* The driver keeps the state internal for simplicity */
138
139 CC3XX_ASSERT(output != NULL);
140 CC3XX_ASSERT(output_length != NULL);
141
142 if (!cc3xx_psa_random_state.isInitialized) {
143 status = cc3xx_init_random(&cc3xx_psa_random_state.ctx);
144 if (status == PSA_SUCCESS) {
145 cc3xx_psa_random_state.isInitialized = true;
146 } else {
147 return status;
148 }
149 }
150
151 status = cc3xx_get_random(&cc3xx_psa_random_state.ctx,
152 output, output_size, output_length);
153 return status;
154 }
155 /** @} */ // end of psa_random
156