1 /*
2 * Copyright (c) 2018-2019 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_CC13X2_CC26X2 || \
47 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0)
48
49 #include <ti/drivers/TRNG.h>
50 #include <ti/drivers/trng/TRNGCC26XX.h>
51 #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
52
53 #elif (DeviceFamily_ID == DeviceFamily_ID_MSP432E401Y || \
54 DeviceFamily_ID == DeviceFamily_ID_MSP432E411Y)
55
56 #include DeviceFamily_constructPath(driverlib/inc/hw_sysctl.h)
57 #include DeviceFamily_constructPath(driverlib/types.h)
58
59 #endif
60
61 #define STATE_SIZE_IN_WORDS 5
62
63 static uint32_t state[STATE_SIZE_IN_WORDS];
64
65 /*
66 * ======== Random_seedAutomatic ========
67 */
Random_seedAutomatic(void)68 int_fast16_t Random_seedAutomatic(void) {
69
70 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2 || \
71 DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0)
72
73 TRNGCC26XX_Object object = {0};
74 TRNG_Params params;
75 CryptoKey seedKey;
76 int_fast16_t status;
77
78 /* Use minimum TRNGCC26XX_SAMPLES_PER_CYCLE_MIN since
79 * we do not need the full amount of entropy and only need
80 * to kickstart the PRNG.
81 */
82 const TRNGCC26XX_HWAttrs hwAttrs = {
83 .samplesPerCycle = TRNGCC26XX_SAMPLES_PER_CYCLE_MIN
84 };
85
86 /* Allocate TRNG instance on the stack since we will not need it
87 * hereafter. This also helps avoid problems with hardcoded indexes.
88 */
89 TRNG_Config config = {
90 .object = &object,
91 .hwAttrs = &hwAttrs
92 };
93
94 params.returnBehavior = TRNG_RETURN_BEHAVIOR_POLLING;
95
96 TRNG_init();
97
98 TRNG_Handle handle = TRNG_construct(&config, ¶ms);
99
100 if (!handle) {
101 return Random_STATUS_ERROR;
102 }
103
104 CryptoKeyPlaintext_initBlankKey(&seedKey,
105 (uint8_t *)state,
106 sizeof(state));
107
108 status = TRNG_generateEntropy(handle, &seedKey);
109
110 TRNG_close(handle);
111
112 if (status != TRNG_STATUS_SUCCESS) {
113 return Random_STATUS_ERROR;
114 }
115
116 return Random_STATUS_SUCCESS;
117 #elif (DeviceFamily_ID == DeviceFamily_ID_MSP432E401Y || \
118 DeviceFamily_ID == DeviceFamily_ID_MSP432E411Y)
119
120 /* MSP432E4 has a 128-bit unique device ID that we can use */
121 state[0] = HWREG(SYSCTL_UNIQUEID0);
122 state[1] = HWREG(SYSCTL_UNIQUEID1);
123 state[2] = HWREG(SYSCTL_UNIQUEID2);
124 state[3] = HWREG(SYSCTL_UNIQUEID3);
125 state[4] = 0x00000001;
126
127 return Random_STATUS_SUCCESS;
128 #else
129
130 /* If neither a TRNG nor a unique ID are available, use a constant */
131 state[0] = 0x00000001;
132 state[1] = 0x00000002;
133 state[2] = 0x00000003;
134 state[3] = 0x00000004;
135 state[4] = 0x00000005;
136
137 return Random_STATUS_SUCCESS;
138 #endif
139 }
140
141 /*
142 * ======== Random_seedManual ========
143 */
Random_seedManual(uint8_t seed[Random_SEED_LENGTH])144 void Random_seedManual(uint8_t seed[Random_SEED_LENGTH]) {
145 uintptr_t key;
146
147 key = HwiP_disable();
148
149 memcpy(state, seed, sizeof(state));
150
151 HwiP_restore(key);
152 }
153
154 /*
155 * ======== Random_getNumber ========
156 */
Random_getNumber(void)157 uint32_t Random_getNumber(void) {
158 uintptr_t key;
159 uint32_t s;
160 uint32_t v;
161 uint32_t result;
162
163 key = HwiP_disable();
164
165 /* "xorwow" XOR shift PRNG from section 3.1 of Marsaglia's "Xorshift RNGs" paper */
166 v = state[3];
167
168 v ^= v >> 2;
169 v ^= v << 1;
170
171 state[3] = state[2];
172 state[2] = state[1];
173 state[1] = state[0];
174 s = state[0];
175
176 v ^= s;
177 v ^= s << 4;
178
179 state[0] = v;
180
181 state[4] += 362437;
182
183 result = v + state[4];
184
185 HwiP_restore(key);
186
187 return result;
188 }
189
190 /*
191 * ======== Random_getBytes ========
192 */
Random_getBytes(void * buffer,size_t bufferSize)193 void Random_getBytes(void *buffer, size_t bufferSize) {
194 uint32_t i;
195 uint32_t randomNumber;
196
197 for (i = 0; i < bufferSize / sizeof(uint32_t); i++){
198 ((uint32_t *)buffer)[i] = Random_getNumber();
199 }
200
201 randomNumber = Random_getNumber();
202
203 memcpy((uint32_t *)buffer + bufferSize / sizeof(uint32_t),
204 &randomNumber,
205 bufferSize % sizeof(uint32_t));
206 }
207