@@ -201,7 +201,8 @@ static time64_t get_time(void)
201201
202202#endif /* LINUX_KERNEL */
203203
204- static int lc_seed_seeded_rng (struct lc_seeded_rng_ctx * rng , int init ,
204+ static int lc_seed_seeded_rng (struct lc_seeded_rng_ctx * rng ,
205+ const uint8_t * pers , size_t pers_len , int init ,
205206 pid_t newpid )
206207{
207208 /* We provide twice the buffer size for the kernel seed sources */
@@ -229,8 +230,8 @@ static int lc_seed_seeded_rng(struct lc_seeded_rng_ctx *rng, int init,
229230 (size_t )datasize > sizeof (seed ))
230231 return - EFAULT ;
231232
232- CKINT (lc_rng_seed (rng -> rng_ctx , seed , (size_t )datasize , NULL ,
233- 0 ));
233+ CKINT (lc_rng_seed (rng -> rng_ctx , seed , (size_t )datasize , pers ,
234+ pers_len ));
234235 }
235236
236237 rng -> bytes = 0 ;
@@ -260,23 +261,41 @@ void lc_seeded_rng_zero_state(void)
260261 rng = seeded_rng .rng_ctx ;
261262 if (!rng )
262263 return ;
263- seeded_rng .rng_ctx = NULL ;
264+
265+ mutex_w_lock (& seeded_rng .lock );
264266
265267 if (seeded_rng .last_seeded )
266268 lc_rng_zero (rng );
267269
270+ /*
271+ * Set the state such that in case the seeded_rng is used after this
272+ * function, it is automatically newly instantiated. Surely any use
273+ * after this call of the seeded_rng is a programming bug, but
274+ * leancrypto tries to be as gracefully as possible especially in the
275+ * realm of random numbers - the pillar of all cryptography.
276+ *
277+ * seeded.rng does not need to be reinitialized as lc_rng_zero only
278+ * clears the state, but leaves the RNG handle fully in tact.
279+ */
280+ seeded_rng .pid = 0 ;
281+ seeded_rng .last_seeded = 0 ;
282+ seeded_rng .bytes = LC_SEEDED_RNG_MAX_BYTES + 1 ,
283+
284+ mutex_w_unlock (& seeded_rng .lock );
285+
268286 seeded_rng_noise_fini ();
269287}
270288
271- static time64_t time_after_now (time64_t base )
289+ static time64_t time_after_now (time64_t base , time64_t * curr_time )
272290{
273291 time64_t curr = get_time ();
274292
293+ * curr_time = curr ;
275294 return time64_after (curr , base ) ? (curr - base ) : 0 ;
276295}
277296
278297static int lc_seeded_rng_must_reseed (struct lc_seeded_rng_ctx * rng ,
279- pid_t * newpid )
298+ pid_t * newpid , time64_t * curr_time )
280299{
281300 pid_t pid ;
282301
@@ -287,7 +306,8 @@ static int lc_seeded_rng_must_reseed(struct lc_seeded_rng_ctx *rng,
287306 return 1 ;
288307
289308 /* ... or our seeding was too long ago ... */
290- if (time_after_now (rng -> last_seeded + LC_SEEDED_RNG_MAX_TIME ))
309+ if (time_after_now (rng -> last_seeded + LC_SEEDED_RNG_MAX_TIME ,
310+ curr_time ))
291311 return 1 ;
292312
293313 /*
@@ -303,7 +323,8 @@ static int lc_seeded_rng_must_reseed(struct lc_seeded_rng_ctx *rng,
303323 return 0 ;
304324}
305325
306- static int lc_get_seeded_rng (struct lc_seeded_rng_ctx * * rng_ret )
326+ static int lc_get_seeded_rng (struct lc_seeded_rng_ctx * * rng_ret ,
327+ time64_t * curr_time )
307328{
308329 pid_t newpid = 0 ;
309330 int ret = 0 , init = 0 ;
@@ -317,9 +338,11 @@ static int lc_get_seeded_rng(struct lc_seeded_rng_ctx **rng_ret)
317338 init = 1 ;
318339 }
319340
320- /* Force reseed if needed */
321- if (lc_seeded_rng_must_reseed (& seeded_rng , & newpid ))
322- CKINT (lc_seed_seeded_rng (& seeded_rng , init , newpid ));
341+ /* Force reseed if needed using the time stamp as additional data. */
342+ if (lc_seeded_rng_must_reseed (& seeded_rng , & newpid , curr_time )) {
343+ CKINT (lc_seed_seeded_rng (& seeded_rng , (uint8_t * )& curr_time ,
344+ sizeof (curr_time ), init , newpid ));
345+ }
323346
324347 * rng_ret = & seeded_rng ;
325348
@@ -335,19 +358,39 @@ static int lc_seeded_rng_generate(void *_state, const uint8_t *addtl_input,
335358{
336359 struct lc_seeded_rng_ctx * rng = NULL ;
337360 size_t updated_len ;
361+ time64_t curr_time ;
338362 int ret ;
339363
340364 if (_state )
341365 return - EINVAL ;
342366
343367 /* Get the DRNG state that is fully seeded */
344- CKINT (lc_get_seeded_rng (& rng ));
368+ CKINT (lc_get_seeded_rng (& rng , & curr_time ));
345369
346370 mutex_w_lock (& rng -> lock );
347371
348- /* Generate random numbers */
349- CKINT (lc_rng_generate (rng -> rng_ctx , addtl_input , addtl_input_len , out ,
350- outlen ));
372+ /*
373+ * Generate random numbers
374+ *
375+ * Always insert the gathered time as additional input into the DRBG.
376+ * This is intended to ensure different DRBG states in case there
377+ * was any address space duplication that the getpid() operation did
378+ * not detect (which we hope does not occur).
379+ */
380+ if (addtl_input ) {
381+ /*
382+ * Insert the current time as a reseed operation - this
383+ * operation is not considered to add entropy, but shall just
384+ * mix the state.
385+ */
386+ CKINT (lc_rng_seed (rng -> rng_ctx , (uint8_t * )& curr_time ,
387+ sizeof (curr_time ), NULL , 0 ));
388+ CKINT (lc_rng_generate (rng -> rng_ctx , addtl_input ,
389+ addtl_input_len , out , outlen ));
390+ } else {
391+ CKINT (lc_rng_generate (rng -> rng_ctx , (uint8_t * )& curr_time ,
392+ sizeof (curr_time ), out , outlen ));
393+ }
351394
352395 /* Check wrap around and avoid a wrap for the rng->bytes state */
353396 updated_len = rng -> bytes + outlen ;
@@ -366,15 +409,26 @@ static int lc_seeded_rng_seed(void *_state, const uint8_t *seed, size_t seedlen,
366409 const uint8_t * persbuf , size_t perslen )
367410{
368411 struct lc_seeded_rng_ctx * rng = NULL ;
412+ time64_t curr_time ;
369413 int ret ;
370414
371415 if (_state )
372416 return - EINVAL ;
373417
374- CKINT (lc_get_seeded_rng (& rng ));
418+ CKINT (lc_get_seeded_rng (& rng , & curr_time ));
375419
376420 mutex_w_lock (& rng -> lock );
377- CKINT (lc_seed_seeded_rng (rng , 0 , 0 ));
421+
422+ /*
423+ * Use the time stamp as additional data to seed the DRBG with the
424+ * internal entropy sources to ensure proper seeding with all required
425+ * entropy. The use of internal entropy sources is unconditional to
426+ * not rely on the caller-provided data.
427+ */
428+ CKINT (lc_seed_seeded_rng (rng , (uint8_t * )& curr_time , sizeof (curr_time ),
429+ 0 , 0 ));
430+
431+ /* Now insert the caller-provided data. */
378432 CKINT (lc_rng_seed (rng -> rng_ctx , seed , seedlen , persbuf , perslen ));
379433
380434out :
@@ -385,9 +439,25 @@ static int lc_seeded_rng_seed(void *_state, const uint8_t *seed, size_t seedlen,
385439
386440static void lc_seeded_rng_zero (void * _state )
387441{
442+ struct lc_seeded_rng_ctx * rng = NULL ;
443+ time64_t curr_time ;
444+
388445 (void )_state ;
389446
390- /* Do nothing */
447+ /*
448+ * Instead of zeroizing the state, we simply reseed the state to
449+ * obliterate any potential information an adversay may have about
450+ * the current state. This implies that the seeded_rng is always ready
451+ * for action in case there is a programming error in the caller and
452+ * he calls zeroize by immediately following a generate operation.
453+ */
454+
455+ if (lc_get_seeded_rng (& rng , & curr_time ))
456+ return ;
457+
458+ mutex_w_lock (& rng -> lock );
459+ lc_seed_seeded_rng (rng , (uint8_t * )& curr_time , sizeof (curr_time ), 0 , 0 );
460+ mutex_w_unlock (& rng -> lock );
391461}
392462
393463static const struct lc_rng _lc_seeded_rng = {
0 commit comments