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