10afa8e06SEd Maste /*
20afa8e06SEd Maste * Copyright (c) 2018 Yubico AB. All rights reserved.
30afa8e06SEd Maste * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste */
70afa8e06SEd Maste
80afa8e06SEd Maste #include <sys/types.h>
90afa8e06SEd Maste #include <sys/stat.h>
100afa8e06SEd Maste #ifdef HAVE_SYS_RANDOM_H
110afa8e06SEd Maste #include <sys/random.h>
120afa8e06SEd Maste #endif
130afa8e06SEd Maste
140afa8e06SEd Maste #include <fcntl.h>
150afa8e06SEd Maste #ifdef HAVE_UNISTD_H
160afa8e06SEd Maste #include <unistd.h>
170afa8e06SEd Maste #endif
180afa8e06SEd Maste
190afa8e06SEd Maste #include "fido.h"
200afa8e06SEd Maste
210afa8e06SEd Maste #if defined(_WIN32)
220afa8e06SEd Maste #include <windows.h>
230afa8e06SEd Maste
240afa8e06SEd Maste #include <winternl.h>
250afa8e06SEd Maste #include <winerror.h>
260afa8e06SEd Maste #include <stdio.h>
270afa8e06SEd Maste #include <bcrypt.h>
280afa8e06SEd Maste #include <sal.h>
290afa8e06SEd Maste
300afa8e06SEd Maste int
fido_get_random(void * buf,size_t len)310afa8e06SEd Maste fido_get_random(void *buf, size_t len)
320afa8e06SEd Maste {
330afa8e06SEd Maste NTSTATUS status;
340afa8e06SEd Maste
350afa8e06SEd Maste status = BCryptGenRandom(NULL, buf, (ULONG)len,
360afa8e06SEd Maste BCRYPT_USE_SYSTEM_PREFERRED_RNG);
370afa8e06SEd Maste
380afa8e06SEd Maste if (!NT_SUCCESS(status))
390afa8e06SEd Maste return (-1);
400afa8e06SEd Maste
410afa8e06SEd Maste return (0);
420afa8e06SEd Maste }
430afa8e06SEd Maste #elif defined(HAVE_ARC4RANDOM_BUF)
440afa8e06SEd Maste int
fido_get_random(void * buf,size_t len)450afa8e06SEd Maste fido_get_random(void *buf, size_t len)
460afa8e06SEd Maste {
470afa8e06SEd Maste arc4random_buf(buf, len);
480afa8e06SEd Maste return (0);
490afa8e06SEd Maste }
500afa8e06SEd Maste #elif defined(HAVE_GETRANDOM)
510afa8e06SEd Maste int
fido_get_random(void * buf,size_t len)520afa8e06SEd Maste fido_get_random(void *buf, size_t len)
530afa8e06SEd Maste {
540afa8e06SEd Maste ssize_t r;
550afa8e06SEd Maste
560afa8e06SEd Maste if ((r = getrandom(buf, len, 0)) < 0 || (size_t)r != len)
570afa8e06SEd Maste return (-1);
580afa8e06SEd Maste
590afa8e06SEd Maste return (0);
600afa8e06SEd Maste }
610afa8e06SEd Maste #elif defined(HAVE_DEV_URANDOM)
620afa8e06SEd Maste int
fido_get_random(void * buf,size_t len)630afa8e06SEd Maste fido_get_random(void *buf, size_t len)
640afa8e06SEd Maste {
650afa8e06SEd Maste int fd = -1;
660afa8e06SEd Maste int ok = -1;
670afa8e06SEd Maste ssize_t r;
680afa8e06SEd Maste
690afa8e06SEd Maste if ((fd = open(FIDO_RANDOM_DEV, O_RDONLY)) < 0)
700afa8e06SEd Maste goto fail;
710afa8e06SEd Maste if ((r = read(fd, buf, len)) < 0 || (size_t)r != len)
720afa8e06SEd Maste goto fail;
730afa8e06SEd Maste
740afa8e06SEd Maste ok = 0;
750afa8e06SEd Maste fail:
760afa8e06SEd Maste if (fd != -1)
770afa8e06SEd Maste close(fd);
780afa8e06SEd Maste
790afa8e06SEd Maste return (ok);
800afa8e06SEd Maste }
810afa8e06SEd Maste #else
820afa8e06SEd Maste #error "please provide an implementation of fido_get_random() for your platform"
830afa8e06SEd Maste #endif /* _WIN32 */
84