summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormatthew <>2014-06-17 00:37:07 +0000
committermatthew <>2014-06-17 00:37:07 +0000
commitacfb52126adbf0daf65110e13eae6fc2d27f7781 (patch)
tree7e8e3e42c22eb663855b2fb9e0fdfca34e79a0a8 /src
parente881246f1e12310587271f6c32e1e16438333b2c (diff)
downloadopenbsd-acfb52126adbf0daf65110e13eae6fc2d27f7781.tar.gz
openbsd-acfb52126adbf0daf65110e13eae6fc2d27f7781.tar.bz2
openbsd-acfb52126adbf0daf65110e13eae6fc2d27f7781.zip
Use MAP_INHERIT_ZERO in arc4random(3)
Now instead of calling getpid() each time a user invokes arc4random(), we're able to rely on the kernel zero'ing out the RNG state if the process forks. ok deraadt, djm
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/crypt/arc4random.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/src/lib/libc/crypt/arc4random.c b/src/lib/libc/crypt/arc4random.c
index 7a2d9e800a..03eb047f98 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.33 2014/06/13 18:58:58 deraadt Exp $ */ 1/* $OpenBSD: arc4random.c,v 1.34 2014/06/17 00:37:07 matthew Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1996, David Mazieres <dm@uun.org> 4 * Copyright (c) 1996, David Mazieres <dm@uun.org>
@@ -48,12 +48,13 @@
48#define IVSZ 8 48#define IVSZ 8
49#define BLOCKSZ 64 49#define BLOCKSZ 64
50#define RSBUFSZ (16*BLOCKSZ) 50#define RSBUFSZ (16*BLOCKSZ)
51static int rs_initialized; 51
52static pid_t rs_stir_pid; 52static struct {
53static chacha_ctx *rs; /* chacha context for random keystream */ 53 size_t rs_have; /* valid bytes at end of rs_buf */
54 size_t rs_count; /* bytes till reseed */
55 chacha_ctx rs_chacha; /* chacha context for random keystream */
56} *rs;
54static u_char *rs_buf; /* keystream blocks */ 57static u_char *rs_buf; /* keystream blocks */
55static size_t rs_have; /* valid bytes at end of rs_buf */
56static size_t rs_count; /* bytes till reseed */
57 58
58static inline void _rs_rekey(u_char *dat, size_t datlen); 59static inline void _rs_rekey(u_char *dat, size_t datlen);
59 60
@@ -63,15 +64,23 @@ _rs_init(u_char *buf, size_t n)
63 if (n < KEYSZ + IVSZ) 64 if (n < KEYSZ + IVSZ)
64 return; 65 return;
65 66
66 if (rs == NULL && (rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE, 67 if (rs == NULL) {
67 MAP_ANON, -1, 0)) == MAP_FAILED) 68 if ((rs = mmap(NULL, sizeof(*rs), PROT_READ|PROT_WRITE,
68 abort(); 69 MAP_ANON, -1, 0)) == MAP_FAILED)
69 if (rs_buf == NULL && (rs_buf = mmap(NULL, RSBUFSZ, PROT_READ|PROT_WRITE, 70 abort();
70 MAP_ANON, -1, 0)) == MAP_FAILED) 71 if (minherit(rs, sizeof(*rs), MAP_INHERIT_ZERO) == -1)
71 abort(); 72 abort();
73 }
74 if (rs_buf == NULL) {
75 if ((rs_buf = mmap(NULL, RSBUFSZ, PROT_READ|PROT_WRITE,
76 MAP_ANON, -1, 0)) == MAP_FAILED)
77 abort();
78 if (minherit(rs_buf, RSBUFSZ, MAP_INHERIT_ZERO) == -1)
79 abort();
80 }
72 81
73 chacha_keysetup(rs, buf, KEYSZ * 8, 0); 82 chacha_keysetup(&rs->rs_chacha, buf, KEYSZ * 8, 0);
74 chacha_ivsetup(rs, buf + KEYSZ); 83 chacha_ivsetup(&rs->rs_chacha, buf + KEYSZ);
75} 84}
76 85
77static void 86static void
@@ -82,30 +91,28 @@ _rs_stir(void)
82 /* XXX */ 91 /* XXX */
83 (void) getentropy(rnd, sizeof rnd); 92 (void) getentropy(rnd, sizeof rnd);
84 93
85 if (!rs_initialized) { 94 if (!rs)
86 rs_initialized = 1;
87 _rs_init(rnd, sizeof(rnd)); 95 _rs_init(rnd, sizeof(rnd));
88 } else 96 else
89 _rs_rekey(rnd, sizeof(rnd)); 97 _rs_rekey(rnd, sizeof(rnd));
90 explicit_bzero(rnd, sizeof(rnd)); 98 explicit_bzero(rnd, sizeof(rnd));
91 99
92 /* invalidate rs_buf */ 100 /* invalidate rs_buf */
93 rs_have = 0; 101 rs->rs_have = 0;
94 memset(rs_buf, 0, RSBUFSZ); 102 memset(rs_buf, 0, RSBUFSZ);
95 103
96 rs_count = 1600000; 104 rs->rs_count = 1600000;
97} 105}
98 106
99static inline void 107static inline void
100_rs_stir_if_needed(size_t len) 108_rs_stir_if_needed(size_t len)
101{ 109{
102 pid_t pid = getpid(); 110 if (!rs || rs->rs_count <= len)
103
104 if (rs_count <= len || !rs_initialized || rs_stir_pid != pid) {
105 rs_stir_pid = pid;
106 _rs_stir(); 111 _rs_stir();
107 } else 112 if (rs->rs_count <= len)
108 rs_count -= len; 113 rs->rs_count = 0;
114 else
115 rs->rs_count -= len;
109} 116}
110 117
111static inline void 118static inline void
@@ -115,7 +122,7 @@ _rs_rekey(u_char *dat, size_t datlen)
115 memset(rs_buf, 0,RSBUFSZ); 122 memset(rs_buf, 0,RSBUFSZ);
116#endif 123#endif
117 /* fill rs_buf with the keystream */ 124 /* fill rs_buf with the keystream */
118 chacha_encrypt_bytes(rs, rs_buf, rs_buf, RSBUFSZ); 125 chacha_encrypt_bytes(&rs->rs_chacha, rs_buf, rs_buf, RSBUFSZ);
119 /* mix in optional user provided data */ 126 /* mix in optional user provided data */
120 if (dat) { 127 if (dat) {
121 size_t i, m; 128 size_t i, m;
@@ -127,7 +134,7 @@ _rs_rekey(u_char *dat, size_t datlen)
127 /* immediately reinit for backtracking resistance */ 134 /* immediately reinit for backtracking resistance */
128 _rs_init(rs_buf, KEYSZ + IVSZ); 135 _rs_init(rs_buf, KEYSZ + IVSZ);
129 memset(rs_buf, 0, KEYSZ + IVSZ); 136 memset(rs_buf, 0, KEYSZ + IVSZ);
130 rs_have = RSBUFSZ - KEYSZ - IVSZ; 137 rs->rs_have = RSBUFSZ - KEYSZ - IVSZ;
131} 138}
132 139
133static inline void 140static inline void
@@ -138,15 +145,15 @@ _rs_random_buf(void *_buf, size_t n)
138 145
139 _rs_stir_if_needed(n); 146 _rs_stir_if_needed(n);
140 while (n > 0) { 147 while (n > 0) {
141 if (rs_have > 0) { 148 if (rs->rs_have > 0) {
142 m = MIN(n, rs_have); 149 m = MIN(n, rs->rs_have);
143 memcpy(buf, rs_buf + RSBUFSZ - rs_have, m); 150 memcpy(buf, rs_buf + RSBUFSZ - rs->rs_have, m);
144 memset(rs_buf + RSBUFSZ - rs_have, 0, m); 151 memset(rs_buf + RSBUFSZ - rs->rs_have, 0, m);
145 buf += m; 152 buf += m;
146 n -= m; 153 n -= m;
147 rs_have -= m; 154 rs->rs_have -= m;
148 } 155 }
149 if (rs_have == 0) 156 if (rs->rs_have == 0)
150 _rs_rekey(NULL, 0); 157 _rs_rekey(NULL, 0);
151 } 158 }
152} 159}
@@ -155,11 +162,11 @@ static inline void
155_rs_random_u32(u_int32_t *val) 162_rs_random_u32(u_int32_t *val)
156{ 163{
157 _rs_stir_if_needed(sizeof(*val)); 164 _rs_stir_if_needed(sizeof(*val));
158 if (rs_have < sizeof(*val)) 165 if (rs->rs_have < sizeof(*val))
159 _rs_rekey(NULL, 0); 166 _rs_rekey(NULL, 0);
160 memcpy(val, rs_buf + RSBUFSZ - rs_have, sizeof(*val)); 167 memcpy(val, rs_buf + RSBUFSZ - rs->rs_have, sizeof(*val));
161 memset(rs_buf + RSBUFSZ - rs_have, 0, sizeof(*val)); 168 memset(rs_buf + RSBUFSZ - rs->rs_have, 0, sizeof(*val));
162 rs_have -= sizeof(*val); 169 rs->rs_have -= sizeof(*val);
163} 170}
164 171
165u_int32_t 172u_int32_t