xref: /freebsd-src/crypto/libecc/src/external_deps/rand.c (revision f0865ec9906d5a18fa2a3b61381f22ce16e606ad)
1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans  *  Copyright (C) 2017 - This file is part of libecc project
3*f0865ec9SKyle Evans  *
4*f0865ec9SKyle Evans  *  Authors:
5*f0865ec9SKyle Evans  *      Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans  *      Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans  *      Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans  *
9*f0865ec9SKyle Evans  *  Contributors:
10*f0865ec9SKyle Evans  *      Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans  *      Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans  *
13*f0865ec9SKyle Evans  *  This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans  *  See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans  */
16*f0865ec9SKyle Evans #include <libecc/external_deps/rand.h>
17*f0865ec9SKyle Evans 
18*f0865ec9SKyle Evans /* Unix and compatible case (including macOS) */
19*f0865ec9SKyle Evans #if defined(WITH_STDLIB) && (defined(__unix__) || defined(__APPLE__))
20*f0865ec9SKyle Evans #include <stdio.h>
21*f0865ec9SKyle Evans #include <stdlib.h>
22*f0865ec9SKyle Evans #include <string.h>
23*f0865ec9SKyle Evans #include <limits.h>
24*f0865ec9SKyle Evans 
25*f0865ec9SKyle Evans #include <sys/types.h>
26*f0865ec9SKyle Evans #include <sys/stat.h>
27*f0865ec9SKyle Evans #include <fcntl.h>
28*f0865ec9SKyle Evans #include <unistd.h>
29*f0865ec9SKyle Evans #include <libecc/words/words.h>
30*f0865ec9SKyle Evans 
31*f0865ec9SKyle Evans /*
32*f0865ec9SKyle Evans  * Copy file content to buffer. Return 0 on success, i.e. if the request
33*f0865ec9SKyle Evans  * size has been read and copied to buffer and -1 otherwise.
34*f0865ec9SKyle Evans  */
35*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET static int fimport(unsigned char *buf, u16 buflen,
36*f0865ec9SKyle Evans 					     const char *path)
37*f0865ec9SKyle Evans {
38*f0865ec9SKyle Evans 	u16 rem = buflen, copied = 0;
39*f0865ec9SKyle Evans 	ssize_t ret;
40*f0865ec9SKyle Evans 	int fd;
41*f0865ec9SKyle Evans 
42*f0865ec9SKyle Evans 	if ((buf == NULL) || (path == NULL)) {
43*f0865ec9SKyle Evans 		ret = -1;
44*f0865ec9SKyle Evans 		goto err;
45*f0865ec9SKyle Evans 	}
46*f0865ec9SKyle Evans 
47*f0865ec9SKyle Evans 	fd = open(path, O_RDONLY);
48*f0865ec9SKyle Evans 	if (fd == -1) {
49*f0865ec9SKyle Evans 		printf("Unable to open input file %s\n", path);
50*f0865ec9SKyle Evans 		ret = -1;
51*f0865ec9SKyle Evans 		goto err;
52*f0865ec9SKyle Evans 	}
53*f0865ec9SKyle Evans 
54*f0865ec9SKyle Evans 	while (rem) {
55*f0865ec9SKyle Evans 		ret = (int)read(fd, buf + copied, rem);
56*f0865ec9SKyle Evans 		if (ret <= 0) {
57*f0865ec9SKyle Evans 			break;
58*f0865ec9SKyle Evans 		} else {
59*f0865ec9SKyle Evans 			rem = (u16)(rem - ret);
60*f0865ec9SKyle Evans 			copied = (u16)(copied + ret);
61*f0865ec9SKyle Evans 		}
62*f0865ec9SKyle Evans 	}
63*f0865ec9SKyle Evans 
64*f0865ec9SKyle Evans 	if (close(fd)) {
65*f0865ec9SKyle Evans 		printf("Unable to close input file %s\n", path);
66*f0865ec9SKyle Evans 		ret = -1;
67*f0865ec9SKyle Evans 		goto err;
68*f0865ec9SKyle Evans 	}
69*f0865ec9SKyle Evans 
70*f0865ec9SKyle Evans 	ret = (copied == buflen) ? 0 : -1;
71*f0865ec9SKyle Evans 
72*f0865ec9SKyle Evans err:
73*f0865ec9SKyle Evans 	return (int)ret;
74*f0865ec9SKyle Evans }
75*f0865ec9SKyle Evans 
76*f0865ec9SKyle Evans int get_random(unsigned char *buf, u16 len)
77*f0865ec9SKyle Evans {
78*f0865ec9SKyle Evans 	return fimport(buf, len, "/dev/urandom");
79*f0865ec9SKyle Evans }
80*f0865ec9SKyle Evans 
81*f0865ec9SKyle Evans /* Windows case */
82*f0865ec9SKyle Evans #elif defined(WITH_STDLIB) && defined(__WIN32__)
83*f0865ec9SKyle Evans #include <windows.h>
84*f0865ec9SKyle Evans #include <wincrypt.h>
85*f0865ec9SKyle Evans 
86*f0865ec9SKyle Evans int get_random(unsigned char *buf, u16 len)
87*f0865ec9SKyle Evans {
88*f0865ec9SKyle Evans 	int ret;
89*f0865ec9SKyle Evans 	HCRYPTPROV hCryptProv = 0;
90*f0865ec9SKyle Evans 
91*f0865ec9SKyle Evans 	if (CryptAcquireContext(&hCryptProv, NULL, NULL,
92*f0865ec9SKyle Evans 				PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
93*f0865ec9SKyle Evans 		ret = -1;
94*f0865ec9SKyle Evans 		goto err;
95*f0865ec9SKyle Evans 	}
96*f0865ec9SKyle Evans 
97*f0865ec9SKyle Evans 	if (CryptGenRandom(hCryptProv, len, buf) == FALSE) {
98*f0865ec9SKyle Evans 		CryptReleaseContext(hCryptProv, 0);
99*f0865ec9SKyle Evans 		ret = -1;
100*f0865ec9SKyle Evans 		goto err;
101*f0865ec9SKyle Evans 	}
102*f0865ec9SKyle Evans 	CryptReleaseContext(hCryptProv, 0);
103*f0865ec9SKyle Evans 	ret = 0;
104*f0865ec9SKyle Evans 
105*f0865ec9SKyle Evans err:
106*f0865ec9SKyle Evans 	return ret;
107*f0865ec9SKyle Evans }
108*f0865ec9SKyle Evans 
109*f0865ec9SKyle Evans /* No platform detected, the user must provide an implementation! */
110*f0865ec9SKyle Evans #else
111*f0865ec9SKyle Evans /* WARNING: when providing/implementing the get_random function, one must:
112*f0865ec9SKyle Evans  * 	- Use a proper entropy source with a TRNG (True Random Number Generator)
113*f0865ec9SKyle Evans  *	basis and clean PRNG (Pseudo-Random Number Generator) post-processing
114*f0865ec9SKyle Evans  *	when needed.
115*f0865ec9SKyle Evans  *	- Use a non-leaking generator in contexts where attackers that have access
116*f0865ec9SKyle Evans  *	to side channels are a plausible threat (a process in an OS sharing memory
117*f0865ec9SKyle Evans  *	and caches with other possibly malicious processes, a microcontroller
118*f0865ec9SKyle Evans  *	that can be observed using EM probes or power consumtion, ...).
119*f0865ec9SKyle Evans  */
120*f0865ec9SKyle Evans #error "rand.c: you have to implement get_random with a proper entropy source!"
121*f0865ec9SKyle Evans #endif
122