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, &params);
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