1 /*
2 * Copyright (c) 2018-2023, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== Random.c ========
34 */
35
36 #include <ti/drivers/dpl/HwiP.h>
37 #include <ti/drivers/utils/Random.h>
38
39 #include <stdint.h>
40 #include <stdbool.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include <ti/devices/DeviceFamily.h>
45
46 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0 || \
47 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X1_CC26X1 || \
48 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2 || \
49 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X4_CC26X3_CC26X4)
50
51 #include <ti/drivers/TRNG.h>
52 #include <ti/drivers/trng/TRNGCC26XX.h>
53 #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
54 #elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0)
55 #include <ti/drivers/RNG.h>
56 #include <ti/drivers/rng/RNGLPF3RF.h>
57 #endif
58
59 #define STATE_SIZE_IN_WORDS 5
60
61 static uint32_t state[STATE_SIZE_IN_WORDS];
62
63 /*
64 * ======== Random_seedAutomatic ========
65 */
Random_seedAutomatic(void)66 int_fast16_t Random_seedAutomatic(void)
67 {
68
69 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0 || \
70 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X1_CC26X1 || \
71 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2 || \
72 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X4_CC26X3_CC26X4)
73
74 TRNGCC26XX_Object object = {0};
75 TRNG_Params params;
76 CryptoKey seedKey;
77 int_fast16_t status;
78
79 /* Use minimum TRNGCC26XX_SAMPLES_PER_CYCLE_MIN since
80 * we do not need the full amount of entropy and only need
81 * to kickstart the PRNG.
82 */
83 const TRNGCC26XX_HWAttrs hwAttrs = {
84 .samplesPerCycle = TRNGCC26XX_SAMPLES_PER_CYCLE_MIN,
85 .intPriority = ~0,
86 };
87
88 /* Allocate TRNG instance on the stack since we will not need it
89 * hereafter. This also helps avoid problems with hardcoded indexes.
90 */
91 TRNG_Config config = {.object = &object, .hwAttrs = &hwAttrs};
92
93 params.returnBehavior = TRNG_RETURN_BEHAVIOR_POLLING;
94
95 TRNG_init();
96
97 TRNG_Handle handle = TRNG_construct(&config, ¶ms);
98
99 if (!handle)
100 {
101 return Random_STATUS_ERROR;
102 }
103
104 CryptoKeyPlaintext_initBlankKey(&seedKey, (uint8_t *)state, sizeof(state));
105
106 status = TRNG_generateEntropy(handle, &seedKey);
107
108 TRNG_close(handle);
109
110 if (status != TRNG_STATUS_SUCCESS)
111 {
112 return Random_STATUS_ERROR;
113 }
114
115 return Random_STATUS_SUCCESS;
116
117 #elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0)
118 RNG_Config rngConfig;
119 RNG_Handle rngHandle;
120 RNG_Params rngParams;
121 RNGLPF3RF_Object rngObject = {0};
122
123 int_fast16_t status;
124
125 /*
126 * Note: For CC23X0, RNG must be initialized by application in a task context with interrupts enabled
127 * using the following steps, before using Random_seedAutomatic() and prior to the use of the Radio.
128 * 1. Read radio noise using RCL_AdcNoise_get_samples_blocking(). This RCL function must
129 * be called from a task context with interrupts enabled and therefore cannot be called
130 * by startup code. This must be executed prior to the use of the radio.
131 * 2. Condition the noise to seed the RNG using RNGLPF3RF_conditionNoiseToGenerateSeed().
132 * 3. Initialize the RNG from the application with RNG_init()
133 * RNG_init() need not be called again here or by any other code.
134 */
135 rngConfig.object = &rngObject;
136 rngConfig.hwAttrs = NULL;
137
138 RNG_Params_init(&rngParams);
139
140 rngHandle = RNG_construct(&rngConfig, &rngParams);
141
142 if (!rngHandle)
143 {
144 return Random_STATUS_ERROR;
145 }
146
147 status = RNG_getRandomBits(rngHandle, &state, sizeof(state) * 8);
148
149 RNG_close(rngHandle);
150
151 if (status != RNG_STATUS_SUCCESS)
152 {
153 return Random_STATUS_ERROR;
154 }
155
156 return Random_STATUS_SUCCESS;
157 #else
158
159 /* If neither a TRNG nor a unique ID are available, use a constant */
160 state[0] = 0x00000001;
161 state[1] = 0x00000002;
162 state[2] = 0x00000003;
163 state[3] = 0x00000004;
164 state[4] = 0x00000005;
165
166 return Random_STATUS_SUCCESS;
167 #endif
168 }
169
170 /*
171 * ======== Random_seedManual ========
172 */
Random_seedManual(uint8_t seed[Random_SEED_LENGTH])173 void Random_seedManual(uint8_t seed[Random_SEED_LENGTH])
174 {
175 uintptr_t key;
176
177 key = HwiP_disable();
178
179 memcpy(state, seed, sizeof(state));
180
181 HwiP_restore(key);
182 }
183
184 /*
185 * ======== Random_getNumber ========
186 */
Random_getNumber(void)187 uint32_t Random_getNumber(void)
188 {
189 uintptr_t key;
190 uint32_t s;
191 uint32_t v;
192 uint32_t result;
193
194 key = HwiP_disable();
195
196 /* "xorwow" XOR shift PRNG from section 3.1 of Marsaglia's "Xorshift RNGs" paper */
197 v = state[3];
198
199 v ^= v >> 2;
200 v ^= v << 1;
201
202 state[3] = state[2];
203 state[2] = state[1];
204 state[1] = state[0];
205 s = state[0];
206
207 v ^= s;
208 v ^= s << 4;
209
210 state[0] = v;
211
212 state[4] += 362437;
213
214 result = v + state[4];
215
216 HwiP_restore(key);
217
218 return result;
219 }
220
221 /*
222 * ======== Random_getBytes ========
223 */
Random_getBytes(void * buffer,size_t bufferSize)224 void Random_getBytes(void *buffer, size_t bufferSize)
225 {
226 uint32_t i;
227 uint32_t randomNumber;
228
229 for (i = 0; i < bufferSize / sizeof(uint32_t); i++)
230 {
231 ((uint32_t *)buffer)[i] = Random_getNumber();
232 }
233
234 randomNumber = Random_getNumber();
235
236 memcpy((uint32_t *)buffer + bufferSize / sizeof(uint32_t), &randomNumber, bufferSize % sizeof(uint32_t));
237 }
238