1 /*-
2  * Copyright (c) 2014 Michihiro NAKAJIMA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
28 
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 
33 #if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
34 
35 #ifdef HAVE_FCNTL
36 #include <fcntl.h>
37 #endif
38 #ifdef HAVE_LIMITS_H
39 #include <limits.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>
46 #endif
47 #ifdef HAVE_SYS_TIME_H
48 #include <sys/time.h>
49 #endif
50 #ifdef HAVE_PTHREAD_H
51 #include <pthread.h>
52 #endif
53 
54 static void la_arc4random_buf(void *, size_t);
55 
56 #endif /* HAVE_ARC4RANDOM_BUF */
57 
58 #include "archive.h"
59 #include "archive_random_private.h"
60 
61 #if defined(_WIN32) && !defined(__CYGWIN__)
62 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
63 /* don't use bcrypt when XP needs to be supported */
64 #include <bcrypt.h>
65 
66 /* Common in other bcrypt implementations, but missing from VS2008. */
67 #ifndef BCRYPT_SUCCESS
68 #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
69 #endif
70 
71 #elif defined(HAVE_WINCRYPT_H)
72 #include <wincrypt.h>
73 #endif
74 #endif
75 
76 #ifndef O_CLOEXEC
77 #define O_CLOEXEC	0
78 #endif
79 
80 /*
81  * Random number generator function.
82  * This simply calls arc4random_buf function if the platform provides it.
83  */
84 
85 int
86 archive_random(void *buf, size_t nbytes)
87 {
88 #if defined(_WIN32) && !defined(__CYGWIN__)
89 # if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
90 	NTSTATUS status;
91 	BCRYPT_ALG_HANDLE hAlg;
92 
93 	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0);
94 	if (!BCRYPT_SUCCESS(status))
95 		return ARCHIVE_FAILED;
96 	status = BCryptGenRandom(hAlg, buf, nbytes, 0);
97 	BCryptCloseAlgorithmProvider(hAlg, 0);
98 	if (!BCRYPT_SUCCESS(status))
99 		return ARCHIVE_FAILED;
100 
101 	return ARCHIVE_OK;
102 # else
103 	HCRYPTPROV hProv;
104 	BOOL success;
105 
106 	success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
107 	    CRYPT_VERIFYCONTEXT);
108 	if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
109 		success = CryptAcquireContext(&hProv, NULL, NULL,
110 		    PROV_RSA_FULL, CRYPT_NEWKEYSET);
111 	}
112 	if (success) {
113 		success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf);
114 		CryptReleaseContext(hProv, 0);
115 		if (success)
116 			return ARCHIVE_OK;
117 	}
118 	/* TODO: Does this case really happen? */
119 	return ARCHIVE_FAILED;
120 # endif
121 #elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
122 	la_arc4random_buf(buf, nbytes);
123 	return ARCHIVE_OK;
124 #else
125 	arc4random_buf(buf, nbytes);
126 	return ARCHIVE_OK;
127 #endif
128 }
129 
130 #if !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
131 
132 /*	$OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $	*/
133 /*
134  * Copyright (c) 1996, David Mazieres <dm@uun.org>
135  * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
136  *
137  * Permission to use, copy, modify, and distribute this software for any
138  * purpose with or without fee is hereby granted, provided that the above
139  * copyright notice and this permission notice appear in all copies.
140  *
141  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
142  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
143  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
144  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
145  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
146  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
147  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
148  */
149 
150 /*
151  * Arc4 random number generator for OpenBSD.
152  *
153  * This code is derived from section 17.1 of Applied Cryptography,
154  * second edition, which describes a stream cipher allegedly
155  * compatible with RSA Labs "RC4" cipher (the actual description of
156  * which is a trade secret).  The same algorithm is used as a stream
157  * cipher called "arcfour" in Tatu Ylonen's ssh package.
158  *
159  * RC4 is a registered trademark of RSA Laboratories.
160  */
161 
162 #ifdef __GNUC__
163 #define inline __inline
164 #else				/* !__GNUC__ */
165 #define inline
166 #endif				/* !__GNUC__ */
167 
168 struct arc4_stream {
169 	uint8_t i;
170 	uint8_t j;
171 	uint8_t s[256];
172 };
173 
174 #define	RANDOMDEV	"/dev/urandom"
175 #define	KEYSIZE		128
176 #ifdef HAVE_PTHREAD_H
177 static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
178 #define	_ARC4_LOCK()	pthread_mutex_lock(&arc4random_mtx);
179 #define	_ARC4_UNLOCK()  pthread_mutex_unlock(&arc4random_mtx);
180 #else
181 #define	_ARC4_LOCK()
182 #define	_ARC4_UNLOCK()
183 #endif
184 
185 static int rs_initialized;
186 static struct arc4_stream rs;
187 static pid_t arc4_stir_pid;
188 static int arc4_count;
189 
190 static inline uint8_t arc4_getbyte(void);
191 static void arc4_stir(void);
192 
193 static inline void
194 arc4_init(void)
195 {
196 	int     n;
197 
198 	for (n = 0; n < 256; n++)
199 		rs.s[n] = n;
200 	rs.i = 0;
201 	rs.j = 0;
202 }
203 
204 static inline void
205 arc4_addrandom(uint8_t *dat, int datlen)
206 {
207 	int     n;
208 	uint8_t si;
209 
210 	rs.i--;
211 	for (n = 0; n < 256; n++) {
212 		rs.i = (rs.i + 1);
213 		si = rs.s[rs.i];
214 		rs.j = (rs.j + si + dat[n % datlen]);
215 		rs.s[rs.i] = rs.s[rs.j];
216 		rs.s[rs.j] = si;
217 	}
218 	rs.j = rs.i;
219 }
220 
221 static void
222 arc4_stir(void)
223 {
224 	int done, fd, i;
225 	struct {
226 		struct timeval	tv;
227 		pid_t		pid;
228 		uint8_t		rnd[KEYSIZE];
229 	} rdat;
230 
231 	if (!rs_initialized) {
232 		arc4_init();
233 		rs_initialized = 1;
234 	}
235 	done = 0;
236 	fd = open(RANDOMDEV, O_RDONLY | O_CLOEXEC, 0);
237 	if (fd >= 0) {
238 		if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
239 			done = 1;
240 		(void)close(fd);
241 	}
242 	if (!done) {
243 		(void)gettimeofday(&rdat.tv, NULL);
244 		rdat.pid = getpid();
245 		/* We'll just take whatever was on the stack too... */
246 	}
247 
248 	arc4_addrandom((uint8_t *)&rdat, KEYSIZE);
249 
250 	/*
251 	 * Discard early keystream, as per recommendations in:
252 	 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
253 	 * As per the Network Operations Division, cryptographic requirements
254 	 * published on wikileaks on March 2017.
255 	 */
256 
257 	for (i = 0; i < 3072; i++)
258 		(void)arc4_getbyte();
259 	arc4_count = 1600000;
260 }
261 
262 static void
263 arc4_stir_if_needed(void)
264 {
265 	pid_t pid = getpid();
266 
267 	if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
268 		arc4_stir_pid = pid;
269 		arc4_stir();
270 	}
271 }
272 
273 static inline uint8_t
274 arc4_getbyte(void)
275 {
276 	uint8_t si, sj;
277 
278 	rs.i = (rs.i + 1);
279 	si = rs.s[rs.i];
280 	rs.j = (rs.j + si);
281 	sj = rs.s[rs.j];
282 	rs.s[rs.i] = sj;
283 	rs.s[rs.j] = si;
284 	return (rs.s[(si + sj) & 0xff]);
285 }
286 
287 static void
288 la_arc4random_buf(void *_buf, size_t n)
289 {
290 	uint8_t *buf = (uint8_t *)_buf;
291 	_ARC4_LOCK();
292 	arc4_stir_if_needed();
293 	while (n--) {
294 		if (--arc4_count <= 0)
295 			arc4_stir();
296 		buf[n] = arc4_getbyte();
297 	}
298 	_ARC4_UNLOCK();
299 }
300 
301 #endif /* !HAVE_ARC4RANDOM_BUF */
302