diff options
author | matthew <> | 2014-06-19 00:13:22 +0000 |
---|---|---|
committer | matthew <> | 2014-06-19 00:13:22 +0000 |
commit | 621a34760179b1387de8337f525f1c9dedf54fad (patch) | |
tree | 8d5a4c9f2628f7ba9b7a476867a2fa97f9a4b63b /src | |
parent | ea52171d7ee0bb85a996dc2021440e122bf0357d (diff) | |
download | openbsd-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.c | 53 |
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. */ | ||
52 | static struct { | 53 | static 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; |
57 | static u_char *rs_buf; /* keystream blocks */ | 57 | |
58 | /* Preserved in fork children. */ | ||
59 | static struct { | ||
60 | chacha_ctx rs_chacha; /* chacha context for random keystream */ | ||
61 | u_char rs_buf[RSBUFSZ]; /* keystream blocks */ | ||
62 | } *rsx; | ||
58 | 63 | ||
59 | static inline void _rs_rekey(u_char *dat, size_t datlen); | 64 | static 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 | ||
86 | static void | 89 | static 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 | ||
140 | static inline void | 144 | static 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) | |||
161 | static inline void | 168 | static 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 | ||