11/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
22
3+ /*
4+ * Copyright (c) 2016, Chris Morrison
5+ * All rights reserved.
6+ *
7+ * Redistribution and use in source and binary forms, with or without
8+ * modification, are permitted provided that the following conditions are met:
9+ *
10+ * * Redistributions of source code must retain the above copyright notice, this
11+ * list of conditions and the following disclaimer.
12+ *
13+ * * Redistributions in binary form must reproduce the above copyright notice,
14+ * this list of conditions and the following disclaimer in the documentation
15+ * and/or other materials provided with the distribution.
16+ *
17+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+ * POSSIBILITY OF SUCH DAMAGE.
28+ */
29+
330#include <tinycrypt/ctr_prng.h>
431#include <tinycrypt/utils.h>
532#include <string.h>
633
7- //todo comment
34+ /*
35+ * This PRNG is based on the CTR_DRBG described in Recommendation for Random
36+ * Number Generation Using Deterministic Random Bit Generators,
37+ * NIST SP 800-90A Rev. 1.
38+ *
39+ * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
40+ * described in that document.
41+ *
42+ */
43+
44+ /**
45+ * @brief Array incrementer
46+ * Treats the supplied array as one contiguous number (MSB in arr[0]), and
47+ * increments it by one
48+ * @return none
49+ * @param arr IN/OUT -- array to be incremented
50+ * @param len IN -- size of arr in bytes
51+ */
852static void arrInc (uint8_t arr [], uint32_t len )
953{
1054 uint32_t i ;
@@ -20,8 +64,16 @@ static void arrInc(uint8_t arr[], uint32_t len)
2064 }
2165}
2266
23- //todo comment
24- static void tc_ctr_prng_update (TCCtrPrng_t * const ctx , uint8_t const providedData [])
67+ /**
68+ * @brief CTR PRNG update
69+ * Updates the internal state of supplied the CTR PRNG context
70+ * increments it by one
71+ * @return none
72+ * @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
73+ * @param ctx IN/OUT -- CTR PRNG state
74+ * @param providedData IN -- data used when updating the internal state
75+ */
76+ static void tc_ctr_prng_update (TCCtrPrng_t * const ctx , uint8_t const * const providedData )
2577{
2678 if (0 != ctx )
2779 {
@@ -70,37 +122,37 @@ static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const providedDa
70122}
71123
72124int32_t tc_ctr_prng_init (TCCtrPrng_t * const ctx ,
73- uint8_t const entropy [],
125+ uint8_t const * const entropy ,
74126 uint32_t entropyLen ,
75- uint8_t const personalization [],
127+ uint8_t const * const personalization ,
76128 uint32_t pLen )
77129{
78130 int32_t result = TC_FAIL ;
79131 uint32_t i ;
80- uint8_t persString [TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE ] = {0U };
132+ uint8_t personalization_buf [TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE ] = {0U };
81133 uint8_t seed_material [TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE ];
82134 uint8_t zeroArr [TC_AES_BLOCK_SIZE ] = {0U };
83135
84136 if (0 != personalization )
85137 {
86138 /* 10.2.1.3.1 step 1 */
87139 uint32_t len = pLen ;
88- if (len > sizeof persString )
140+ if (len > sizeof personalization_buf )
89141 {
90- len = sizeof persString ;
142+ len = sizeof personalization_buf ;
91143 }
92144
93145 /* 10.2.1.3.1 step 2 */
94- memcpy (persString , personalization , len );
146+ memcpy (personalization_buf , personalization , len );
95147 }
96148
97- if ((0 != ctx ) && (0 != entropy ) && (entropyLen = = sizeof seed_material ))
149+ if ((0 != ctx ) && (0 != entropy ) && (entropyLen > = sizeof seed_material ))
98150 {
99151 /* 10.2.1.3.1 step 3 */
100152 memcpy (seed_material , entropy , sizeof seed_material );
101153 for (i = 0U ; i < sizeof seed_material ; i ++ )
102154 {
103- seed_material [i ] ^= persString [i ];
155+ seed_material [i ] ^= personalization_buf [i ];
104156 }
105157
106158 /* 10.2.1.3.1 step 4 */
@@ -121,19 +173,39 @@ int32_t tc_ctr_prng_init(TCCtrPrng_t * const ctx,
121173}
122174
123175int32_t tc_ctr_prng_reseed (TCCtrPrng_t * const ctx ,
124- uint8_t const entropy [],
125- uint32_t entropyLen )
176+ uint8_t const * const entropy ,
177+ uint32_t entropyLen ,
178+ uint8_t const * const additional_input ,
179+ uint32_t additionallen )
126180{
181+ uint32_t i ;
127182 int32_t result = TC_FAIL ;
183+ uint8_t additional_input_buf [TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE ] = {0U };
184+ uint8_t seed_material [TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE ];
185+
186+ if (0 != additional_input )
187+ {
188+ /* 10.2.1.4.1 step 1 */
189+ uint32_t len = additionallen ;
190+ if (len > sizeof additional_input_buf )
191+ {
192+ len = sizeof additional_input_buf ;
193+ }
194+
195+ /* 10.2.1.4.1 step 2 */
196+ memcpy (additional_input_buf , additional_input , len );
197+ }
128198
129- //todo - add additional input support
130- /*
131- * 10.2.1.4.1 steps 1 - 3 not required - no additional input accepted by
132- * this reseed function
133- */
134199 uint32_t seedlen = (uint32_t )TC_AES_KEY_SIZE + (uint32_t )TC_AES_BLOCK_SIZE ;
135- if ((0 != ctx ) && (entropyLen = = seedlen ))
200+ if ((0 != ctx ) && (entropyLen > = seedlen ))
136201 {
202+ /* 10.2.1.4.1 step 3 */
203+ memcpy (seed_material , entropy , sizeof seed_material );
204+ for (i = 0U ; i < sizeof seed_material ; i ++ )
205+ {
206+ seed_material [i ] ^= additional_input_buf [i ];
207+ }
208+
137209 /* 10.2.1.4.1 step 4 */
138210 tc_ctr_prng_update (ctx , entropy );
139211
@@ -145,9 +217,10 @@ int32_t tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
145217 return result ;
146218}
147219
148- //todo comment
149- int32_t tc_ctr_prng_generate (TCCtrPrng_t * const ctx ,
150- uint8_t out [],
220+ int32_t tc_ctr_prng_generate (TCCtrPrng_t * const ctx ,
221+ uint8_t const * const additional_input ,
222+ uint32_t additionallen ,
223+ uint8_t * const out ,
151224 uint32_t outlen )
152225{
153226 /* 2^48 - see section 10.2.1 */
@@ -167,8 +240,18 @@ int32_t tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
167240 }
168241 else
169242 {
170- //todo - add additional input support
171- /* 10.2.1.5.1 step 2 - no additional input supported, so no action */
243+ uint8_t additional_input_buf [TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE ] = {0U };
244+ if (0 != additional_input )
245+ {
246+ /* 10.2.1.5.1 step 2 */
247+ uint32_t len = additionallen ;
248+ if (len > sizeof additional_input_buf )
249+ {
250+ len = sizeof additional_input_buf ;
251+ }
252+ memcpy (additional_input_buf , additional_input , len );
253+ tc_ctr_prng_update (ctx , additional_input_buf );
254+ }
172255
173256 /* 10.2.1.5.1 step 3 - implicit */
174257
@@ -209,6 +292,16 @@ int32_t tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
209292 return result ;
210293}
211294
295+ void tc_ctr_prng_uninstantiate (TCCtrPrng_t * const ctx )
296+ {
297+ if (0 != ctx )
298+ {
299+ memset (ctx -> key .words , 0x00 , sizeof ctx -> key .words );
300+ memset (ctx -> V , 0x00 , sizeof ctx -> V );
301+ ctx -> reseedCount = 0U ;
302+ }
303+ }
304+
212305
213306
214307
0 commit comments