1 /**
2  * \file random.c
3  *
4  * \brief   This file contains the helper functions to generate random numbers
5  *          for the purpose of testing.
6  */
7 
8 /*
9  *  Copyright The Mbed TLS Contributors
10  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
11  */
12 
13 /*
14  * for arc4random_buf() from <stdlib.h>
15  */
16 #if defined(__NetBSD__)
17 #define _NETBSD_SOURCE 1
18 #elif defined(__OpenBSD__)
19 #define _BSD_SOURCE 1
20 #endif
21 
22 #include <test/macros.h>
23 #include <test/random.h>
24 #include <string.h>
25 
26 #include <mbedtls/entropy.h>
27 #include <alignment.h>
28 
mbedtls_test_rnd_std_rand(void * rng_state,unsigned char * output,size_t len)29 int mbedtls_test_rnd_std_rand(void *rng_state,
30                               unsigned char *output,
31                               size_t len)
32 {
33 #if !defined(__OpenBSD__) && !defined(__NetBSD__)
34     size_t i;
35 
36     if (rng_state != NULL) {
37         rng_state  = NULL;
38     }
39 
40     for (i = 0; i < len; ++i) {
41         output[i] = rand();
42     }
43 #else
44     if (rng_state != NULL) {
45         rng_state = NULL;
46     }
47 
48     arc4random_buf(output, len);
49 #endif /* !OpenBSD && !NetBSD */
50 
51     return 0;
52 }
53 
mbedtls_test_rnd_zero_rand(void * rng_state,unsigned char * output,size_t len)54 int mbedtls_test_rnd_zero_rand(void *rng_state,
55                                unsigned char *output,
56                                size_t len)
57 {
58     if (rng_state != NULL) {
59         rng_state  = NULL;
60     }
61 
62     memset(output, 0, len);
63 
64     return 0;
65 }
66 
mbedtls_test_rnd_buffer_rand(void * rng_state,unsigned char * output,size_t len)67 int mbedtls_test_rnd_buffer_rand(void *rng_state,
68                                  unsigned char *output,
69                                  size_t len)
70 {
71     mbedtls_test_rnd_buf_info *info = (mbedtls_test_rnd_buf_info *) rng_state;
72     size_t use_len;
73 
74     if (rng_state == NULL) {
75         return mbedtls_test_rnd_std_rand(NULL, output, len);
76     }
77 
78     use_len = len;
79     if (len > info->length) {
80         use_len = info->length;
81     }
82 
83     if (use_len) {
84         memcpy(output, info->buf, use_len);
85         info->buf += use_len;
86         info->length -= use_len;
87     }
88 
89     if (len - use_len > 0) {
90         if (info->fallback_f_rng != NULL) {
91             return info->fallback_f_rng(info->fallback_p_rng,
92                                         output + use_len,
93                                         len - use_len);
94         } else {
95             return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
96         }
97     }
98 
99     return 0;
100 }
101 
mbedtls_test_rnd_pseudo_rand(void * rng_state,unsigned char * output,size_t len)102 int mbedtls_test_rnd_pseudo_rand(void *rng_state,
103                                  unsigned char *output,
104                                  size_t len)
105 {
106     mbedtls_test_rnd_pseudo_info *info =
107         (mbedtls_test_rnd_pseudo_info *) rng_state;
108     uint32_t i, *k, sum, delta = 0x9E3779B9;
109     unsigned char result[4], *out = output;
110 
111     if (rng_state == NULL) {
112         return mbedtls_test_rnd_std_rand(NULL, output, len);
113     }
114 
115     k = info->key;
116 
117     while (len > 0) {
118         size_t use_len = (len > 4) ? 4 : len;
119         sum = 0;
120 
121         for (i = 0; i < 32; i++) {
122             info->v0 += (((info->v1 << 4) ^ (info->v1 >> 5))
123                          + info->v1) ^ (sum + k[sum & 3]);
124             sum += delta;
125             info->v1 += (((info->v0 << 4) ^ (info->v0 >> 5))
126                          + info->v0) ^ (sum + k[(sum>>11) & 3]);
127         }
128 
129         MBEDTLS_PUT_UINT32_BE(info->v0, result, 0);
130         memcpy(out, result, use_len);
131         len -= use_len;
132         out += 4;
133     }
134 
135     return 0;
136 }
137