xref: /freebsd/contrib/libfido2/src/random.c (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
1 /*
2  * Copyright (c) 2018-2024 Yubico AB. All rights reserved.
3  * Use of this source code is governed by a BSD-style
4  * license that can be found in the LICENSE file.
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #ifdef HAVE_SYS_RANDOM_H
11 #include <sys/random.h>
12 #endif
13 
14 #include <fcntl.h>
15 #ifdef HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 
19 #if defined(__has_feature)
20 # if  __has_feature(memory_sanitizer)
21 #  include <sanitizer/msan_interface.h>
22 #  define WITH_MSAN	1
23 # endif
24 #endif
25 
26 #include "fido.h"
27 
28 #if defined(_WIN32)
29 #include <windows.h>
30 
31 #include <winternl.h>
32 #include <winerror.h>
33 #include <stdio.h>
34 #include <bcrypt.h>
35 #include <sal.h>
36 
37 int
38 fido_get_random(void *buf, size_t len)
39 {
40 	NTSTATUS status;
41 
42 	status = BCryptGenRandom(NULL, buf, (ULONG)len,
43 	    BCRYPT_USE_SYSTEM_PREFERRED_RNG);
44 
45 	if (!NT_SUCCESS(status))
46 		return (-1);
47 
48 	return (0);
49 }
50 #elif defined(HAVE_ARC4RANDOM_BUF)
51 int
52 fido_get_random(void *buf, size_t len)
53 {
54 	arc4random_buf(buf, len);
55 #ifdef WITH_MSAN
56 	__msan_unpoison(buf, len); /* XXX */
57 #endif
58 	return (0);
59 }
60 #elif defined(HAVE_GETRANDOM)
61 int
62 fido_get_random(void *buf, size_t len)
63 {
64 	ssize_t	r;
65 
66 	if ((r = getrandom(buf, len, 0)) < 0 || (size_t)r != len)
67 		return (-1);
68 
69 	return (0);
70 }
71 #elif defined(HAVE_DEV_URANDOM)
72 int
73 fido_get_random(void *buf, size_t len)
74 {
75 	int	fd = -1;
76 	int	ok = -1;
77 	ssize_t	r;
78 
79 	if ((fd = open(FIDO_RANDOM_DEV, O_RDONLY)) < 0)
80 		goto fail;
81 	if ((r = read(fd, buf, len)) < 0 || (size_t)r != len)
82 		goto fail;
83 
84 	ok = 0;
85 fail:
86 	if (fd != -1)
87 		close(fd);
88 
89 	return (ok);
90 }
91 #else
92 #error "please provide an implementation of fido_get_random() for your platform"
93 #endif /* _WIN32 */
94