libcoap 4.3.5-develop-19cef11
coap_prng.c
Go to the documentation of this file.
1/*
2 * coap_prng.c -- random number generation
3 *
4 * Copyright (C) 2020-2024 Olaf Bergmann <bergmann@tzi.org>
5 *
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * This file is part of the CoAP library libcoap. Please see README
9 * for terms of use.
10 */
11
18
19#ifdef HAVE_GETRANDOM
20#include <sys/random.h>
21#elif defined(WITH_CONTIKI)
22#include "lib/csprng.h"
23#else /* !WITH_CONTIKI */
24#include <stdlib.h>
25#endif /* !WITH_CONTIKI */
26
27#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
28#include <entropy_poll.h>
29#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
30
31#if defined(_WIN32)
32
33errno_t __cdecl rand_s(_Out_ unsigned int *_RandomValue);
40coap_prng_impl(unsigned char *buf, size_t len) {
41 while (len != 0) {
42 uint32_t r = 0;
43 size_t i;
44
45 if (rand_s(&r) != 0)
46 return 0;
47 for (i = 0; i < len && i < 4; i++) {
48 *buf++ = (uint8_t)r;
49 r >>= 8;
50 }
51 len -= i;
52 }
53 return 1;
54}
55
56#endif /* _WIN32 */
57
58COAP_API void
59coap_prng_init(unsigned int seed) {
60 coap_lock_lock(NULL, return);
62 coap_lock_unlock(NULL);
63}
64
65COAP_API int
66coap_prng(void *buf, size_t len) {
67 int ret;
68
69 coap_lock_lock(NULL, return 0);
70 ret = coap_prng_lkd(buf, len);
71 coap_lock_unlock(NULL);
72 return ret;
73}
74
75#if defined(WITH_LWIP) && defined(LWIP_RAND)
76
77void
78coap_prng_init_lkd(unsigned int seed) {
79 (void)seed;
80}
81
82int
83coap_prng_lkd(void *bufp, size_t len) {
84 unsigned char *buf = (unsigned char *)bufp;
85 u32_t v = LWIP_RAND();
86
87 while (len > sizeof(v)) {
88 memcpy(buf, &v, sizeof(v));
89 len -= sizeof(v);
90 buf += sizeof(v);
91 v = LWIP_RAND();
92 }
93
94 memcpy(buf, &v, len);
95 return 1;
96}
97
98#else
99
100/*
101 * This, or any user provided alternative, function is expected to
102 * return 0 on failure and 1 on success.
103 */
104static int
105coap_prng_default(void *buf, size_t len) {
106#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
107 /* mbedtls_hardware_poll() returns 0 on success */
108 return (mbedtls_hardware_poll(NULL, buf, len, NULL) ? 0 : 1);
109
110#elif defined(HAVE_GETRANDOM)
111 return (getrandom(buf, len, 0) > 0) ? 1 : 0;
112
113#elif defined(HAVE_RANDOM)
114#define RAND_BYTES (RAND_MAX >= 0xffffff ? 3 : (RAND_MAX >= 0xffff ? 2 : 1))
115 unsigned char *dst = (unsigned char *)buf;
116
117 if (len) {
118 uint8_t byte_counter = RAND_BYTES;
119 uint32_t r_v = random();
120
121 while (1) {
122 *dst++ = r_v & 0xFF;
123 if (!--len) {
124 break;
125 }
126 if (--byte_counter) {
127 r_v >>= 8;
128 } else {
129 r_v = random();
130 byte_counter = RAND_BYTES;
131 }
132 }
133 }
134 return 1;
135#elif defined(RIOT_VERSION)
136#include <random.h>
137 random_bytes(buf, len);
138 return 1;
139
140#elif defined(WITH_CONTIKI)
141 return csprng_rand(buf, len);
142
143#elif defined(_WIN32)
144 return coap_prng_impl(buf,len);
145
146#else /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !HAVE_GETRANDOM &&
147 !HAVE_RANDOM && !_WIN32 */
148#error "CVE-2021-34430: using rand() for crypto randoms is not secure!"
149#error "Please update you C-library and rerun the auto-configuration."
150 unsigned char *dst = (unsigned char *)buf;
151 while (len--)
152 *dst++ = rand() & 0xFF;
153 return 1;
154#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT && !HAVE_GETRANDOM &&
155 !HAVE_RANDOM && !_WIN32 */
156}
157
159
160void
162 rand_func = rng;
163}
164
165void
166coap_prng_init_lkd(unsigned int seed) {
167#ifdef HAVE_GETRANDOM
168 /* No seed to seed the random source if getrandom() is used */
169 (void)seed;
170#elif defined(HAVE_RANDOM)
171 srandom(seed);
172#else /* !HAVE_GETRANDOM && !HAVE_RANDOM */
173 srand(seed);
174#endif /* !HAVE_GETRANDOM */
175}
176
177int
178coap_prng_lkd(void *buf, size_t len) {
179 if (!rand_func) {
180 return 0;
181 }
182
183 return rand_func(buf, len);
184}
185
186#endif
Library specific build wrapper for coap_internal.h.
#define COAP_API
static int coap_prng_default(void *buf, size_t len)
Definition: coap_prng.c:105
static coap_rand_func_t rand_func
Definition: coap_prng.c:158
void coap_prng_init_lkd(unsigned int seed)
Seeds the default random number generation function with the given seed.
Definition: coap_prng.c:166
int coap_prng_lkd(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition: coap_prng.c:178
int(* coap_rand_func_t)(void *out, size_t len)
Data type for random number generator function.
Definition: coap_prng.h:32
void coap_set_prng(coap_rand_func_t rng)
Replaces the current random number generation function with the default function rng.
Definition: coap_prng.c:161
COAP_API int coap_prng(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition: coap_prng.c:66
COAP_API void coap_prng_init(unsigned int seed)
Seeds the default random number generation function with the given seed.
Definition: coap_prng.c:59
#define coap_lock_unlock(c)
Dummy for no thread-safe code.
#define coap_lock_lock(c, failed)
Dummy for no thread-safe code.
#define COAP_STATIC_INLINE
Definition: libcoap.h:53