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