diff options
-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 | ||