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