summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormatthew <>2014-06-19 00:13:22 +0000
committermatthew <>2014-06-19 00:13:22 +0000
commit621a34760179b1387de8337f525f1c9dedf54fad (patch)
tree8d5a4c9f2628f7ba9b7a476867a2fa97f9a4b63b /src
parentea52171d7ee0bb85a996dc2021440e122bf0357d (diff)
downloadopenbsd-621a34760179b1387de8337f525f1c9dedf54fad.tar.gz
openbsd-621a34760179b1387de8337f525f1c9dedf54fad.tar.bz2
openbsd-621a34760179b1387de8337f525f1c9dedf54fad.zip
Move rs_chacha and rs_buf into the same memory page and don't mark it
MAP_INHERIT_ZERO anymore. This restores arc4random's previous behavior where fork children would mix in some randomness from the parent process. New behavior noticed by deraadt ok deraadt, tedu
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/crypt/arc4random.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
index 03eb047f98..985fa8a0e5 100644
--- a/src/lib/libc/crypt/arc4random.c
+++ b/src/lib/libc/crypt/arc4random.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: arc4random.c,v 1.34 2014/06/17 00:37:07 matthew Exp $ */ 1/* $OpenBSD: arc4random.c,v 1.35 2014/06/19 00:13:22 matthew Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996, David Mazieres <dm@uun.org> 4 * Copyright (c) 1996, David Mazieres <dm@uun.org>
@@ -49,12 +49,17 @@
49#define BLOCKSZ 64 49#define BLOCKSZ 64
50#define RSBUFSZ (16*BLOCKSZ) 50#define RSBUFSZ (16*BLOCKSZ)
51 51
52/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
52static struct { 53static struct {
53 size_t rs_have; /* valid bytes at end of rs_buf */ 54 size_t rs_have; /* valid bytes at end of rs_buf */
54 size_t rs_count; /* bytes till reseed */ 55 size_t rs_count; /* bytes till reseed */
55 chacha_ctx rs_chacha; /* chacha context for random keystream */
56} *rs; 56} *rs;
57static u_char *rs_buf; /* keystream blocks */ 57
58/* Preserved in fork children. */
59static struct {
60 chacha_ctx rs_chacha; /* chacha context for random keystream */
61 u_char rs_buf[RSBUFSZ]; /* keystream blocks */
62} *rsx;
58 63
59static inline void _rs_rekey(u_char *dat, size_t datlen); 64static inline void _rs_rekey(u_char *dat, size_t datlen);
60 65
@@ -66,21 +71,19 @@ _rs_init(u_char *buf, size_t n)
66 71
67 if (rs == NULL) { 72 if (rs == NULL) {
68 if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE, 73 if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
69 MAP_ANON, -1, 0)) == MAP_FAILED) 74 MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
70 abort(); 75 abort();
71 if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1) 76 if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1)
72 abort(); 77 abort();
73 } 78 }
74 if (rs_buf == NULL) { 79 if (rsx == NULL) {
75 if ((rs_buf = mmap(NULL, RSBUFSZ, PROT_READ|PROT_WRITE, 80 if ((rsx = mmap(NULL, sizeof(*rsx), PROT_READ|PROT_WRITE,
76 MAP_ANON, -1, 0)) == MAP_FAILED) 81 MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
77 abort();
78 if (minherit(rs_buf, RSBUFSZ, MAP_INHERIT_ZERO) == -1)
79 abort(); 82 abort();
80 } 83 }
81 84
82 chacha_keysetup(&rs->rs_chacha, buf, KEYSZ * 8, 0); 85 chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
83 chacha_ivsetup(&rs->rs_chacha, buf + KEYSZ); 86 chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
84} 87}
85 88
86static void 89static void
@@ -99,7 +102,7 @@ _rs_stir(void)
99 102
100 /* invalidate rs_buf */ 103 /* invalidate rs_buf */
101 rs->rs_have = 0; 104 rs->rs_have = 0;
102 memset(rs_buf, 0, RSBUFSZ); 105 memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
103 106
104 rs->rs_count = 1600000; 107 rs->rs_count = 1600000;
105} 108}
@@ -119,36 +122,40 @@ static inline void
119_rs_rekey(u_char *dat, size_t datlen) 122_rs_rekey(u_char *dat, size_t datlen)
120{ 123{
121#ifndef KEYSTREAM_ONLY 124#ifndef KEYSTREAM_ONLY
122 memset(rs_buf, 0,RSBUFSZ); 125 memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
123#endif 126#endif
124 /* fill rs_buf with the keystream */ 127 /* fill rs_buf with the keystream */
125 chacha_encrypt_bytes(&rs->rs_chacha, rs_buf, rs_buf, RSBUFSZ); 128 chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
129 rsx->rs_buf, sizeof(rsx->rs_buf));
126 /* mix in optional user provided data */ 130 /* mix in optional user provided data */
127 if (dat) { 131 if (dat) {
128 size_t i, m; 132 size_t i, m;
129 133
130 m = MIN(datlen, KEYSZ + IVSZ); 134 m = MIN(datlen, KEYSZ + IVSZ);
131 for (i = 0; i < m; i++) 135 for (i = 0; i < m; i++)
132 rs_buf[i] ^= dat[i]; 136 rsx->rs_buf[i] ^= dat[i];
133 } 137 }
134 /* immediately reinit for backtracking resistance */ 138 /* immediately reinit for backtracking resistance */
135 _rs_init(rs_buf, KEYSZ + IVSZ); 139 _rs_init(rsx->rs_buf, KEYSZ + IVSZ);
136 memset(rs_buf, 0, KEYSZ + IVSZ); 140 memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
137 rs->rs_have = RSBUFSZ - KEYSZ - IVSZ; 141 rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
138} 142}
139 143
140static inline void 144static inline void
141_rs_random_buf(void *_buf, size_t n) 145_rs_random_buf(void *_buf, size_t n)
142{ 146{
143 u_char *buf = (u_char *)_buf; 147 u_char *buf = (u_char *)_buf;
148 u_char *keystream;
144 size_t m; 149 size_t m;
145 150
146 _rs_stir_if_needed(n); 151 _rs_stir_if_needed(n);
147 while (n > 0) { 152 while (n > 0) {
148 if (rs->rs_have > 0) { 153 if (rs->rs_have > 0) {
149 m = MIN(n, rs->rs_have); 154 m = MIN(n, rs->rs_have);
150 memcpy(buf, rs_buf + RSBUFSZ - rs->rs_have, m); 155 keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
151 memset(rs_buf + RSBUFSZ - rs->rs_have, 0, m); 156 - rs->rs_have;
157 memcpy(buf, keystream, m);
158 memset(keystream, 0, m);
152 buf += m; 159 buf += m;
153 n -= m; 160 n -= m;
154 rs->rs_have -= m; 161 rs->rs_have -= m;
@@ -161,11 +168,13 @@ _rs_random_buf(void *_buf, size_t n)
161static inline void 168static inline void
162_rs_random_u32(u_int32_t *val) 169_rs_random_u32(u_int32_t *val)
163{ 170{
171 u_char *keystream;
164 _rs_stir_if_needed(sizeof(*val)); 172 _rs_stir_if_needed(sizeof(*val));
165 if (rs->rs_have < sizeof(*val)) 173 if (rs->rs_have < sizeof(*val))
166 _rs_rekey(NULL, 0); 174 _rs_rekey(NULL, 0);
167 memcpy(val, rs_buf + RSBUFSZ - rs->rs_have, sizeof(*val)); 175 keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
168 memset(rs_buf + RSBUFSZ - rs->rs_have, 0, sizeof(*val)); 176 memcpy(val, keystream, sizeof(*val));
177 memset(keystream, 0, sizeof(*val));
169 rs->rs_have -= sizeof(*val); 178 rs->rs_have -= sizeof(*val);
170} 179}
171 180