View | Details | Raw Unified | Return to bug 182610 | Differences between
and this patch

Collapse All | Expand All

(-)crypto/heimdal/lib/roken/rand.c (-1 lines)
Lines 37-43 void ROKEN_LIB_FUNCTION Link Here
37
rk_random_init(void)
37
rk_random_init(void)
38
{
38
{
39
#if defined(HAVE_ARC4RANDOM)
39
#if defined(HAVE_ARC4RANDOM)
40
    arc4random_stir();
41
#elif defined(HAVE_SRANDOMDEV)
40
#elif defined(HAVE_SRANDOMDEV)
42
    srandomdev();
41
    srandomdev();
43
#elif defined(HAVE_RANDOM)
42
#elif defined(HAVE_RANDOM)
(-)crypto/openssh/config.h (-1 / +1 lines)
Lines 191-197 Link Here
191
#define HAVE_ARC4RANDOM_BUF 1
191
#define HAVE_ARC4RANDOM_BUF 1
192
192
193
/* Define to 1 if you have the `arc4random_stir' function. */
193
/* Define to 1 if you have the `arc4random_stir' function. */
194
#define HAVE_ARC4RANDOM_STIR 1
194
/* #undef HAVE_ARC4RANDOM_STIR */
195
195
196
/* Define to 1 if you have the `arc4random_uniform' function. */
196
/* Define to 1 if you have the `arc4random_uniform' function. */
197
#define HAVE_ARC4RANDOM_UNIFORM 1
197
#define HAVE_ARC4RANDOM_UNIFORM 1
(-)include/stdlib.h (-2 / +7 lines)
Lines 250-260 extern void (*malloc_message)(void *, const char * Link Here
250
void	 abort2(const char *, int, void **) __dead2;
250
void	 abort2(const char *, int, void **) __dead2;
251
__uint32_t
251
__uint32_t
252
	 arc4random(void);
252
	 arc4random(void);
253
void	 arc4random_addrandom(unsigned char *, int);
254
void	 arc4random_buf(void *, size_t);
253
void	 arc4random_buf(void *, size_t);
255
void	 arc4random_stir(void);
256
__uint32_t 
254
__uint32_t 
257
	 arc4random_uniform(__uint32_t);
255
	 arc4random_uniform(__uint32_t);
256
257
#if !defined(BURN_BRIDGES)
258
/* Deprecated arc4random() functions */
259
#define arc4random_stir()
260
#define arc4random_addrandom(a,b)
261
#endif
262
258
#ifdef __BLOCKS__
263
#ifdef __BLOCKS__
259
int	 atexit_b(void (^ _Nonnull)(void));
264
int	 atexit_b(void (^ _Nonnull)(void));
260
void	*bsearch_b(const void *, const void *, size_t,
265
void	*bsearch_b(const void *, const void *, size_t,
(-)lib/libc/gen/Makefile.inc (+3 lines)
Lines 16-21 SRCS+= __getosreldate.c \ Link Here
16
	_thread_init.c \
16
	_thread_init.c \
17
	alarm.c \
17
	alarm.c \
18
	arc4random.c \
18
	arc4random.c \
19
	arc4random-compat.c \
19
	arc4random_uniform.c \
20
	arc4random_uniform.c \
20
	assert.c \
21
	assert.c \
21
	auxv.c \
22
	auxv.c \
Lines 166-171 SRCS+= devname-compat11.c \ Link Here
166
	unvis-compat.c
167
	unvis-compat.c
167
.endif
168
.endif
168
169
170
CFLAGS.arc4random.c= -I${SRCTOP}/sys -I${SRCTOP}/sys/crypto/chacha20
171
169
.PATH: ${SRCTOP}/contrib/libc-pwcache
172
.PATH: ${SRCTOP}/contrib/libc-pwcache
170
SRCS+=	pwcache.c pwcache.h
173
SRCS+=	pwcache.c pwcache.h
171
174
(-)lib/libc/gen/Symbol.map (-2 lines)
Lines 65-72 FBSD_1.0 { Link Here
65
	pthread_testcancel;
65
	pthread_testcancel;
66
	alarm;
66
	alarm;
67
	arc4random;
67
	arc4random;
68
	arc4random_addrandom;
69
	arc4random_stir;
70
	__assert;
68
	__assert;
71
	check_utility_compat;
69
	check_utility_compat;
72
	clock;
70
	clock;
(-)lib/libc/gen/arc4random-compat.c (+72 lines)
Line 0 Link Here
1
/*-
2
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3
 *
4
 * Copyright (c) 2018 Google LLC
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 *
28
 * $FreeBSD$
29
 */
30
31
#include <sys/cdefs.h>
32
__FBSDID("$FreeBSD$");
33
34
#include <sys/types.h>
35
#include <stdbool.h>
36
#include <syslog.h>
37
38
/*
39
 * The following functions were removed from OpenBSD for good reasons:
40
 *
41
 *  - arc4random_stir()
42
 *  - arc4random_addrandom()
43
 *
44
 * On FreeBSD, for backward ABI compatibility, we provide two wrapper which
45
 * logs this event and returns.
46
 */
47
48
void __arc4random_stir_fbsd11(void);
49
void __arc4random_addrandom_fbsd11(u_char *, int);
50
51
void
52
__arc4random_stir_fbsd11(void)
53
{
54
	static bool warned = false;
55
56
	if (!warned)
57
		syslog(LOG_DEBUG, "Deprecated function arc4random_stir() called");
58
	warned = true;
59
}
60
61
void
62
__arc4random_addrandom_fbsd11(u_char * dummy1 __unused, int dummy2 __unused)
63
{
64
	static bool warned = false;
65
66
	if (!warned)
67
		syslog(LOG_DEBUG, "Deprecated function arc4random_addrandom() called");
68
	warned = true;
69
}
70
71
__sym_compat(arc4random_stir, __arc4random_stir_fbsd11, FBSD_1.0);
72
__sym_compat(arc4random_addrandom, __arc4random_addrandom_fbsd11, FBSD_1.0);
(-)lib/libc/gen/arc4random.3 (-47 / +63 lines)
Lines 1-4 Link Here
1
.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $
1
.\" $OpenBSD: arc4random.3,v 1.35 2014/11/25 16:45:24 millert Exp $
2
.\"
2
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
3
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
3
.\" All rights reserved.
4
.\" All rights reserved.
4
.\"
5
.\"
Lines 30-45 Link Here
30
.\" Manual page, using -mandoc macros
31
.\" Manual page, using -mandoc macros
31
.\" $FreeBSD$
32
.\" $FreeBSD$
32
.\"
33
.\"
33
.Dd April 15, 1997
34
.Dd July 19, 2014
34
.Dt ARC4RANDOM 3
35
.Dt ARC4RANDOM 3
35
.Os
36
.Os
36
.Sh NAME
37
.Sh NAME
37
.Nm arc4random ,
38
.Nm arc4random ,
38
.Nm arc4random_buf ,
39
.Nm arc4random_buf ,
39
.Nm arc4random_uniform ,
40
.Nm arc4random_uniform
40
.Nm arc4random_stir ,
41
.Nd random number generator
41
.Nm arc4random_addrandom
42
.Nd arc4 random number generator
43
.Sh LIBRARY
42
.Sh LIBRARY
44
.Lb libc
43
.Lb libc
45
.Sh SYNOPSIS
44
.Sh SYNOPSIS
Lines 50-69 Link Here
50
.Fn arc4random_buf "void *buf" "size_t nbytes"
49
.Fn arc4random_buf "void *buf" "size_t nbytes"
51
.Ft uint32_t
50
.Ft uint32_t
52
.Fn arc4random_uniform "uint32_t upper_bound"
51
.Fn arc4random_uniform "uint32_t upper_bound"
53
.Ft void
54
.Fn arc4random_stir "void"
55
.Ft void
56
.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
57
.Sh DESCRIPTION
52
.Sh DESCRIPTION
53
This family of functions provides higher quality data than those
54
described in
55
.Xr rand 3 ,
56
.Xr random 3 ,
57
and
58
.Xr rand48 3 .
59
.Pp
60
Use of these functions is encouraged for almost all random number
61
consumption because the other interfaces are deficient in either
62
quality, portability, standardization, or availability.
63
These functions can be called in almost all coding environments,
64
including
65
.Xr pthreads 3
66
and
67
.Xr chroot 2 .
68
.Pp
69
High quality 32-bit pseudo-random numbers are generated very quickly.
70
On each call, a cryptographic pseudo-random number generator is used
71
to generate a new result.
72
One data pool is used for all consumers in a process, so that consumption
73
under program flow can act as additional stirring.
74
The subsystem is re-seeded from the kernel random number subsystem using
75
.Xr getentropy 2
76
on a regular basis, and also upon
77
.Xr fork 2 .
78
.Pp
58
The
79
The
59
.Fn arc4random
80
.Fn arc4random
60
function uses the key stream generator employed by the
81
function returns a single 32-bit value.
61
arc4 cipher, which uses 8*8 8 bit S-Boxes.
62
The S-Boxes
63
can be in about
64
.if t 2\u\s71700\s10\d
65
.if n (2**1700)
66
states.
67
The
82
The
68
.Fn arc4random
83
.Fn arc4random
69
function returns pseudo-random numbers in the range of 0 to
84
function returns pseudo-random numbers in the range of 0 to
Lines 75-107 and Link Here
75
.Xr random 3 .
90
.Xr random 3 .
76
.Pp
91
.Pp
77
.Fn arc4random_buf
92
.Fn arc4random_buf
78
function fills the region
93
fills the region
79
.Fa buf
94
.Fa buf
80
of length
95
of length
81
.Fa nbytes
96
.Fa nbytes
82
with ARC4-derived random data.
97
with random data.
83
.Pp
98
.Pp
84
.Fn arc4random_uniform
99
.Fn arc4random_uniform
85
will return a uniformly distributed random number less than
100
will return a single 32-bit value, uniformly distributed but less than
86
.Fa upper_bound .
101
.Fa upper_bound .
87
.Fn arc4random_uniform
102
This is recommended over constructions like
88
is recommended over constructions like
89
.Dq Li arc4random() % upper_bound
103
.Dq Li arc4random() % upper_bound
90
as it avoids "modulo bias" when the upper bound is not a power of two.
104
as it avoids "modulo bias" when the upper bound is not a power of two.
91
.Pp
105
In the worst case, this function may consume multiple iterations
92
The
106
to ensure uniformity; see the source code to understand the problem
93
.Fn arc4random_stir
107
and solution.
94
function reads data from
108
.Sh RETURN VALUES
95
.Pa /dev/urandom
109
These functions are always successful, and no return value is
96
and uses it to permute the S-Boxes via
110
reserved to indicate an error.
97
.Fn arc4random_addrandom .
98
.Pp
99
There is no need to call
100
.Fn arc4random_stir
101
before using
102
.Fn arc4random
103
functions family, since
104
they automatically initialize themselves.
105
.Sh EXAMPLES
111
.Sh EXAMPLES
106
The following produces a drop-in replacement for the traditional
112
The following produces a drop-in replacement for the traditional
107
.Fn rand
113
.Fn rand
Lines 113-127 functions using Link Here
113
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
119
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
114
.Sh SEE ALSO
120
.Sh SEE ALSO
115
.Xr rand 3 ,
121
.Xr rand 3 ,
116
.Xr random 3 ,
122
.Xr rand48 3 ,
117
.Xr srandomdev 3
123
.Xr random 3
118
.Sh HISTORY
124
.Sh HISTORY
119
.Pa RC4
125
These functions first appeared in
120
has been designed by RSA Data Security, Inc.
126
.Ox 2.1 .
121
It was posted anonymously
127
.Pp
122
to the USENET and was confirmed to be equivalent by several sources who
128
The original version of this random number generator used the
123
had access to the original cipher.
129
RC4 (also known as ARC4) algorithm.
124
Since
130
In
125
.Pa RC4
131
.Ox 5.5
126
used to be a trade secret, the cipher is now referred to as
132
it was replaced with the ChaCha20 cipher, and it may be replaced
127
.Pa ARC4 .
133
again in the future as cryptographic techniques advance.
134
A good mnemonic is
135
.Dq A Replacement Call for Random .
136
.Pp
137
The
138
.Fn arc4random
139
random number generator was first introduced in
140
.Fx 2.2.6 .
141
The ChaCha20 based implementation was introduced in
142
.Fx 12.0 ,
143
with obsolete stir and addrandom interfaces removed at the same time.
(-)lib/libc/gen/arc4random.c (-185 / +123 lines)
Lines 1-8 Link Here
1
/*	$OpenBSD: arc4random.c,v 1.24 2013/06/11 16:59:50 deraadt Exp $	*/
1
/*	$OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $	*/
2
2
3
/*
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
6
 *
8
 *
7
 * Permission to use, copy, modify, and distribute this software for any
9
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
10
 * purpose with or without fee is hereby granted, provided that the above
Lines 18-32 Link Here
18
 */
20
 */
19
21
20
/*
22
/*
21
 * Arc4 random number generator for OpenBSD.
23
 * ChaCha based random number generator for OpenBSD.
22
 *
23
 * This code is derived from section 17.1 of Applied Cryptography,
24
 * second edition, which describes a stream cipher allegedly
25
 * compatible with RSA Labs "RC4" cipher (the actual description of
26
 * which is a trade secret).  The same algorithm is used as a stream
27
 * cipher called "arcfour" in Tatu Ylonen's ssh package.
28
 *
29
 * RC4 is a registered trademark of RSA Laboratories.
30
 */
24
 */
31
25
32
#include <sys/cdefs.h>
26
#include <sys/cdefs.h>
Lines 35-266 __FBSDID("$FreeBSD$"); Link Here
35
#include "namespace.h"
29
#include "namespace.h"
36
#include <fcntl.h>
30
#include <fcntl.h>
37
#include <limits.h>
31
#include <limits.h>
32
#include <pthread.h>
33
#include <signal.h>
34
#include <stdint.h>
38
#include <stdlib.h>
35
#include <stdlib.h>
36
#include <string.h>
39
#include <unistd.h>
37
#include <unistd.h>
40
#include <sys/param.h>
38
#include <sys/types.h>
41
#include <sys/sysctl.h>
42
#include <sys/time.h>
39
#include <sys/time.h>
43
#include <pthread.h>
40
 
44
45
#include "libc_private.h"
41
#include "libc_private.h"
46
#include "un-namespace.h"
42
#include "un-namespace.h"
47
43
48
#ifdef __GNUC__
44
#define KEYSTREAM_ONLY
45
#include "chacha.c"
46
47
#define minimum(a, b) ((a) < (b) ? (a) : (b))
48
49
#if defined(__GNUC__) || defined(_MSC_VER)
49
#define inline __inline
50
#define inline __inline
50
#else				/* !__GNUC__ */
51
#else				/* __GNUC__ || _MSC_VER */
51
#define inline
52
#define inline
52
#endif				/* !__GNUC__ */
53
#endif				/* !__GNUC__ && !_MSC_VER */
53
54
54
struct arc4_stream {
55
#define KEYSZ	32
55
	u_int8_t i;
56
#define IVSZ	8
56
	u_int8_t j;
57
#define BLOCKSZ	64
57
	u_int8_t s[256];
58
#define RSBUFSZ	(16*BLOCKSZ)
58
};
59
59
60
static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
60
/* Marked INHERIT_ZERO, so zero'd out in fork children. */
61
static struct _rs {
62
	size_t		rs_have;	/* valid bytes at end of rs_buf */
63
	size_t		rs_count;	/* bytes till reseed */
64
} *rs;
61
65
62
#define	KEYSIZE		128
66
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
63
#define	_ARC4_LOCK()						\
67
static struct _rsx {
64
	do {							\
68
	chacha_ctx	rs_chacha;	/* chacha context for random keystream */
65
		if (__isthreaded)				\
69
	u_char		rs_buf[RSBUFSZ];	/* keystream blocks */
66
			_pthread_mutex_lock(&arc4random_mtx);	\
70
} *rsx;
67
	} while (0)
68
71
69
#define	_ARC4_UNLOCK()						\
72
static inline int _rs_allocate(struct _rs **, struct _rsx **);
70
	do {							\
73
static inline void _rs_forkdetect(void);
71
		if (__isthreaded)				\
74
#include "arc4random.h"
72
			_pthread_mutex_unlock(&arc4random_mtx);	\
73
	} while (0)
74
75
75
static int rs_initialized;
76
static inline void _rs_rekey(u_char *dat, size_t datlen);
76
static struct arc4_stream rs;
77
static pid_t arc4_stir_pid;
78
static int arc4_count;
79
77
80
extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
81
    void *newp, size_t newlen);
82
83
static inline u_int8_t arc4_getbyte(void);
84
static void arc4_stir(void);
85
86
static inline void
78
static inline void
87
arc4_init(void)
79
_rs_init(u_char *buf, size_t n)
88
{
80
{
89
	int     n;
81
	if (n < KEYSZ + IVSZ)
82
		return;
90
83
91
	for (n = 0; n < 256; n++)
84
	if (rs == NULL) {
92
		rs.s[n] = n;
85
		if (_rs_allocate(&rs, &rsx) == -1)
93
	rs.i = 0;
86
			abort();
94
	rs.j = 0;
87
	}
88
89
	chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
90
	chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ, NULL);
95
}
91
}
96
92
97
static inline void
93
static void
98
arc4_addrandom(u_char *dat, int datlen)
94
_rs_stir(void)
99
{
95
{
100
	int     n;
96
	u_char rnd[KEYSZ + IVSZ];
101
	u_int8_t si;
102
97
103
	rs.i--;
98
	if (getentropy(rnd, sizeof rnd) == -1)
104
	for (n = 0; n < 256; n++) {
99
		_getentropy_fail();
105
		rs.i = (rs.i + 1);
106
		si = rs.s[rs.i];
107
		rs.j = (rs.j + si + dat[n % datlen]);
108
		rs.s[rs.i] = rs.s[rs.j];
109
		rs.s[rs.j] = si;
110
	}
111
	rs.j = rs.i;
112
}
113
100
114
size_t
101
	if (!rs)
115
__arc4_sysctl(u_char *buf, size_t size)
102
		_rs_init(rnd, sizeof(rnd));
116
{
103
	else
117
	int mib[2];
104
		_rs_rekey(rnd, sizeof(rnd));
118
	size_t len, done;
105
	explicit_bzero(rnd, sizeof(rnd));	/* discard source seed */
119
106
120
	mib[0] = CTL_KERN;
107
	/* invalidate rs_buf */
121
	mib[1] = KERN_ARND;
108
	rs->rs_have = 0;
122
	done = 0;
109
	memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
123
110
124
	do {
111
	rs->rs_count = 1600000;
125
		len = size;
126
		if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
127
			return (done);
128
		done += len;
129
		buf += len;
130
		size -= len;
131
	} while (size > 0);
132
133
	return (done);
134
}
112
}
135
113
136
static void
114
static inline void
137
arc4_stir(void)
115
_rs_stir_if_needed(size_t len)
138
{
116
{
139
	u_char rdat[KEYSIZE];
117
	_rs_forkdetect();
140
	int i;
118
	if (!rs || rs->rs_count <= len)
141
119
		_rs_stir();
142
	if (!rs_initialized) {
120
	if (rs->rs_count <= len)
143
		arc4_init();
121
		rs->rs_count = 0;
144
		rs_initialized = 1;
122
	else
145
	}
123
		rs->rs_count -= len;
146
	if (__arc4_sysctl(rdat, KEYSIZE) != KEYSIZE) {
147
		/*
148
		 * The sysctl cannot fail. If it does fail on some FreeBSD
149
		 * derivative or after some future change, just abort so that
150
		 * the problem will be found and fixed. abort is not normally
151
		 * suitable for a library but makes sense here.
152
		 */
153
		abort();
154
	}
155
156
	arc4_addrandom(rdat, KEYSIZE);
157
158
	/*
159
	 * Discard early keystream, as per recommendations in:
160
	 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
161
	 */
162
	for (i = 0; i < 3072; i++)
163
		(void)arc4_getbyte();
164
	arc4_count = 1600000;
165
}
124
}
166
125
167
static void
126
static inline void
168
arc4_stir_if_needed(void)
127
_rs_rekey(u_char *dat, size_t datlen)
169
{
128
{
170
	pid_t pid = getpid();
129
#ifndef KEYSTREAM_ONLY
130
	memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
131
#endif
132
	/* fill rs_buf with the keystream */
133
	chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
134
	    rsx->rs_buf, sizeof(rsx->rs_buf));
135
	/* mix in optional user provided data */
136
	if (dat) {
137
		size_t i, m;
171
138
172
	if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid) {
139
		m = minimum(datlen, KEYSZ + IVSZ);
173
		arc4_stir_pid = pid;
140
		for (i = 0; i < m; i++)
174
		arc4_stir();
141
			rsx->rs_buf[i] ^= dat[i];
175
	}
142
	}
143
	/* immediately reinit for backtracking resistance */
144
	_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
145
	memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
146
	rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
176
}
147
}
177
148
178
static inline u_int8_t
149
static inline void
179
arc4_getbyte(void)
150
_rs_random_buf(void *_buf, size_t n)
180
{
151
{
181
	u_int8_t si, sj;
152
	u_char *buf = (u_char *)_buf;
153
	u_char *keystream;
154
	size_t m;
182
155
183
	rs.i = (rs.i + 1);
156
	_rs_stir_if_needed(n);
184
	si = rs.s[rs.i];
157
	while (n > 0) {
185
	rs.j = (rs.j + si);
158
		if (rs->rs_have > 0) {
186
	sj = rs.s[rs.j];
159
			m = minimum(n, rs->rs_have);
187
	rs.s[rs.i] = sj;
160
			keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
188
	rs.s[rs.j] = si;
161
			    - rs->rs_have;
189
	return (rs.s[(si + sj) & 0xff]);
162
			memcpy(buf, keystream, m);
163
			memset(keystream, 0, m);
164
			buf += m;
165
			n -= m;
166
			rs->rs_have -= m;
167
		}
168
		if (rs->rs_have == 0)
169
			_rs_rekey(NULL, 0);
170
	}
190
}
171
}
191
172
192
static inline u_int32_t
173
static inline void
193
arc4_getword(void)
174
_rs_random_u32(uint32_t *val)
194
{
175
{
195
	u_int32_t val;
176
	u_char *keystream;
196
	val = arc4_getbyte() << 24;
197
	val |= arc4_getbyte() << 16;
198
	val |= arc4_getbyte() << 8;
199
	val |= arc4_getbyte();
200
	return val;
201
}
202
177
203
void
178
	_rs_stir_if_needed(sizeof(*val));
204
arc4random_stir(void)
179
	if (rs->rs_have < sizeof(*val))
205
{
180
		_rs_rekey(NULL, 0);
206
	_ARC4_LOCK();
181
	keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
207
	arc4_stir();
182
	memcpy(val, keystream, sizeof(*val));
208
	_ARC4_UNLOCK();
183
	memset(keystream, 0, sizeof(*val));
184
	rs->rs_have -= sizeof(*val);
209
}
185
}
210
186
211
void
187
uint32_t
212
arc4random_addrandom(u_char *dat, int datlen)
188
arc4random(void)
213
{
189
{
214
	_ARC4_LOCK();
190
	uint32_t val;
215
	if (!rs_initialized)
216
		arc4_stir();
217
	arc4_addrandom(dat, datlen);
218
	_ARC4_UNLOCK();
219
}
220
191
221
u_int32_t
222
arc4random(void)
223
{
224
	u_int32_t val;
225
	_ARC4_LOCK();
192
	_ARC4_LOCK();
226
	arc4_count -= 4;
193
	_rs_random_u32(&val);
227
	arc4_stir_if_needed();
228
	val = arc4_getword();
229
	_ARC4_UNLOCK();
194
	_ARC4_UNLOCK();
230
	return val;
195
	return val;
231
}
196
}
232
197
233
void
198
void
234
arc4random_buf(void *_buf, size_t n)
199
arc4random_buf(void *buf, size_t n)
235
{
200
{
236
	u_char *buf = (u_char *)_buf;
237
	_ARC4_LOCK();
201
	_ARC4_LOCK();
238
	arc4_stir_if_needed();
202
	_rs_random_buf(buf, n);
239
	while (n--) {
240
		if (--arc4_count <= 0)
241
			arc4_stir();
242
		buf[n] = arc4_getbyte();
243
	}
244
	_ARC4_UNLOCK();
203
	_ARC4_UNLOCK();
245
}
204
}
246
247
#if 0
248
/*-------- Test code for i386 --------*/
249
#include <stdio.h>
250
#include <machine/pctr.h>
251
int
252
main(int argc, char **argv)
253
{
254
	const int iter = 1000000;
255
	int     i;
256
	pctrval v;
257
258
	v = rdtsc();
259
	for (i = 0; i < iter; i++)
260
		arc4random();
261
	v = rdtsc() - v;
262
	v /= iter;
263
264
	printf("%qd cycles\n", v);
265
}
266
#endif
(-)lib/libc/gen/arc4random.h (+74 lines)
Line 0 Link Here
1
/*	$OpenBSD: arc4random.h,v 1.4 2015/01/15 06:57:18 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 1996, David Mazieres <dm@uun.org>
5
 * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
6
 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
7
 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
8
 *
9
 * Permission to use, copy, modify, and distribute this software for any
10
 * purpose with or without fee is hereby granted, provided that the above
11
 * copyright notice and this permission notice appear in all copies.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
 *
21
 * $FreeBSD$
22
 */
23
24
/*
25
 * Stub functions for portability.
26
 */
27
#include <sys/mman.h>
28
29
#include <signal.h>
30
31
static pthread_mutex_t	arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
32
#define	_ARC4_LOCK()						\
33
	do {							\
34
		if (__isthreaded)				\
35
			_pthread_mutex_lock(&arc4random_mtx);	\
36
	} while (0)
37
38
#define	_ARC4_UNLOCK()						\
39
	do {							\
40
		if (__isthreaded)				\
41
			_pthread_mutex_unlock(&arc4random_mtx);	\
42
	} while (0)
43
44
static inline void
45
_getentropy_fail(void)
46
{
47
	raise(SIGKILL);
48
}
49
50
static inline int
51
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
52
{
53
	struct {
54
		struct _rs rs;
55
		struct _rsx rsx;
56
	} *p;
57
58
	if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
59
	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
60
		return (-1);
61
	if (minherit(p, sizeof(*p), INHERIT_ZERO) == -1) {
62
		munmap(p, sizeof(*p));
63
		return (-1);
64
	}
65
66
	*rsp = &p->rs;
67
	*rsxp = &p->rsx;
68
	return (0);
69
}
70
71
static inline void
72
_rs_forkdetect(void)
73
{
74
}
(-)lib/libc/gen/getentropy.c (-1 / +26 lines)
Lines 31-36 __FBSDID("$FreeBSD$"); Link Here
31
31
32
#include <sys/param.h>
32
#include <sys/param.h>
33
#include <sys/random.h>
33
#include <sys/random.h>
34
#include <sys/sysctl.h>
34
35
35
#include <errno.h>
36
#include <errno.h>
36
#include <stdlib.h>
37
#include <stdlib.h>
Lines 37-42 __FBSDID("$FreeBSD$"); Link Here
37
38
38
#include "libc_private.h"
39
#include "libc_private.h"
39
40
41
extern int __sysctl(int *, u_int, void *, size_t *, void *, size_t);
42
43
static size_t
44
arnd_sysctl(u_char *buf, size_t size)
45
{
46
	int mib[2];
47
	size_t len, done;
48
49
	mib[0] = CTL_KERN;
50
	mib[1] = KERN_ARND;
51
	done = 0;
52
53
	do {
54
		len = size;
55
		if (__sysctl(mib, 2, buf, &len, NULL, 0) == -1)
56
			return (done);
57
		done += len;
58
		buf += len;
59
		size -= len;
60
	} while (size > 0);
61
62
	return (done);
63
}
64
40
/*
65
/*
41
 * If a newer libc is accidentally installed on an older kernel, provide high
66
 * If a newer libc is accidentally installed on an older kernel, provide high
42
 * quality random data anyway.  The sysctl interface is not as fast and does
67
 * quality random data anyway.  The sysctl interface is not as fast and does
Lines 54-60 getentropy_fallback(void *buf, size_t buflen) Link Here
54
		errno = EFAULT;
79
		errno = EFAULT;
55
		return (-1);
80
		return (-1);
56
	}
81
	}
57
	if (__arc4_sysctl(buf, buflen) != buflen) {
82
	if (arnd_sysctl(buf, buflen) != buflen) {
58
		if (errno == EFAULT)
83
		if (errno == EFAULT)
59
			return (-1);
84
			return (-1);
60
		/*
85
		/*
(-)lib/libc/include/libc_private.h (-2 lines)
Lines 405-412 int __sys_futimens(int fd, const struct timespec Link Here
405
int		__sys_utimensat(int fd, const char *path,
405
int		__sys_utimensat(int fd, const char *path,
406
		    const struct timespec *times, int flag) __hidden;
406
		    const struct timespec *times, int flag) __hidden;
407
407
408
__size_t __arc4_sysctl(unsigned char *, __size_t);
409
410
/* execve() with PATH processing to implement posix_spawnp() */
408
/* execve() with PATH processing to implement posix_spawnp() */
411
int _execvpe(const char *, char * const *, char * const *);
409
int _execvpe(const char *, char * const *, char * const *);
412
410
(-)sys/crypto/chacha20/chacha.c (-4 / +7 lines)
Lines 14-20 __FBSDID("$FreeBSD$"); Link Here
14
14
15
#include <crypto/chacha20/chacha.h>
15
#include <crypto/chacha20/chacha.h>
16
16
17
18
typedef uint8_t u8;
17
typedef uint8_t u8;
19
typedef uint32_t u32;
18
typedef uint32_t u32;
20
19
Lines 57-63 typedef struct chacha_ctx chacha_ctx; Link Here
57
static const char sigma[16] = "expand 32-byte k";
56
static const char sigma[16] = "expand 32-byte k";
58
static const char tau[16] = "expand 16-byte k";
57
static const char tau[16] = "expand 16-byte k";
59
58
60
void
59
LOCAL void
61
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
60
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
62
{
61
{
63
  const char *constants;
62
  const char *constants;
Lines 82-88 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbit Link Here
82
  x->input[3] = U8TO32_LITTLE(constants + 12);
81
  x->input[3] = U8TO32_LITTLE(constants + 12);
83
}
82
}
84
83
85
void
84
LOCAL void
86
chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
85
chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
87
{
86
{
88
  x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
87
  x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
Lines 91-97 chacha_ivsetup(chacha_ctx *x, const u8 *iv, const Link Here
91
  x->input[15] = U8TO32_LITTLE(iv + 4);
90
  x->input[15] = U8TO32_LITTLE(iv + 4);
92
}
91
}
93
92
94
void
93
LOCAL void
95
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
94
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
96
{
95
{
97
  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
96
  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
Lines 169-174 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 Link Here
169
    x14 = PLUS(x14,j14);
168
    x14 = PLUS(x14,j14);
170
    x15 = PLUS(x15,j15);
169
    x15 = PLUS(x15,j15);
171
170
171
#ifndef KEYSTREAM_ONLY
172
    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
172
    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
173
    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
173
    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
174
    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
174
    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
Lines 185-190 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 Link Here
185
    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
185
    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
186
    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
186
    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
187
    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
187
    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
188
#endif
188
189
189
    j12 = PLUSONE(j12);
190
    j12 = PLUSONE(j12);
190
    if (!j12) {
191
    if (!j12) {
Lines 219-224 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 Link Here
219
    }
220
    }
220
    bytes -= 64;
221
    bytes -= 64;
221
    c += 64;
222
    c += 64;
223
#ifndef KEYSTREAM_ONLY
222
    m += 64;
224
    m += 64;
225
#endif
223
  }
226
  }
224
}
227
}
(-)sys/crypto/chacha20/chacha.h (-3 / +9 lines)
Lines 23-31 struct chacha_ctx { Link Here
23
#define CHACHA_STATELEN		(CHACHA_NONCELEN+CHACHA_CTRLEN)
23
#define CHACHA_STATELEN		(CHACHA_NONCELEN+CHACHA_CTRLEN)
24
#define CHACHA_BLOCKLEN		64
24
#define CHACHA_BLOCKLEN		64
25
25
26
void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);
26
#ifdef _KERNEL
27
void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);
27
#define LOCAL
28
void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
28
#else
29
#define LOCAL static
30
#endif
31
32
LOCAL void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits);
33
LOCAL void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr);
34
LOCAL void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m,
29
    u_char *c, u_int bytes);
35
    u_char *c, u_int bytes);
30
36
31
#endif	/* CHACHA_H */
37
#endif	/* CHACHA_H */

Return to bug 182610