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