1 /*
2 * Copyright (c) 2013-2015 Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Non-random number generator based on system timer
10 *
11 * This module provides a non-random implementation of sys_rand32_get(), which
12 * is not meant to be used in a final product as a truly random number
13 * generator. It was provided to allow testing on a platform that does not (yet)
14 * provide a random number generator.
15 */
16
17 #include <zephyr/random/random.h>
18 #include <zephyr/drivers/timer/system_timer.h>
19 #include <zephyr/kernel.h>
20 #include <zephyr/spinlock.h>
21 #include <string.h>
22
23 static struct k_spinlock rand32_lock;
24
25 /**
26 * @brief Get a 32 bit random number
27 *
28 * This pseudo-random number generator returns values that are based off the
29 * target's clock counter, which means that successive calls will return
30 * different values.
31 *
32 * @return a 32-bit number
33 */
rand32_get(void)34 static inline uint32_t rand32_get(void)
35 {
36 /* initial seed value */
37 static uint64_t state = (uint64_t)CONFIG_TIMER_RANDOM_INITIAL_STATE;
38 k_spinlock_key_t key = k_spin_lock(&rand32_lock);
39
40 state = state + k_cycle_get_32();
41 state = state * 2862933555777941757ULL + 3037000493ULL;
42 uint32_t val = (uint32_t)(state >> 32);
43
44 k_spin_unlock(&rand32_lock, key);
45 return val;
46 }
47
48 /**
49 * @brief Fill destination buffer with random numbers
50 *
51 * The pseudo-random number generator returns values that are based off the
52 * target's clock counter, which means that successive calls will return
53 * different values.
54 *
55 * @param dst destination buffer to fill
56 * @param outlen size of destination buffer to fill
57 */
z_impl_sys_rand_get(void * dst,size_t outlen)58 void z_impl_sys_rand_get(void *dst, size_t outlen)
59 {
60 uint8_t *udst = dst;
61 uint32_t blocksize;
62 uint32_t ret;
63
64 while (outlen > 0) {
65 ret = rand32_get();
66 blocksize = MIN(outlen, sizeof(ret));
67 (void)memcpy((void *)udst, &ret, blocksize);
68 udst += blocksize;
69 outlen -= blocksize;
70 }
71 }
72