xref: /freebsd/contrib/libfido2/src/random.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
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