Ticket #13869: 0005-libs-bsd-add-arc4random-3.patch
File 0005-libs-bsd-add-arc4random-3.patch, 16.1 KB (added by , 7 years ago) |
---|
-
headers/compatibility/bsd/stdlib.h
From 477767615f768b41a7d4062d2841114fba73166d Mon Sep 17 00:00:00 2001 From: Leorize <alaviss@users.noreply.github.com> Date: Thu, 14 Dec 2017 08:15:01 +0700 Subject: [PATCH 5/5] libs/bsd: add arc4random(3) --- headers/compatibility/bsd/stdlib.h | 4 + headers/private/libbsd/chacha_private.h | 222 ++++++++++++++++++++++++++ src/libs/bsd/Jamfile | 3 + src/libs/bsd/arc4random.c | 265 ++++++++++++++++++++++++++++++++ src/libs/bsd/arc4random_uniform.c | 56 +++++++ 5 files changed, 550 insertions(+) create mode 100644 headers/private/libbsd/chacha_private.h create mode 100644 src/libs/bsd/arc4random.c create mode 100644 src/libs/bsd/arc4random_uniform.c diff --git a/headers/compatibility/bsd/stdlib.h b/headers/compatibility/bsd/stdlib.h index d65871f8..ae800480 100644
a b 11 11 12 12 #ifdef _BSD_SOURCE 13 13 14 #include <stdint.h> 14 15 15 16 #ifdef __cplusplus 16 17 extern "C" { … … extern "C" { 19 20 int daemon(int noChangeDir, int noClose); 20 21 const char *getprogname(void); 21 22 void setprogname(const char *programName); 23 uint32_t arc4random(void); 24 void arc4random_buf(void *buf, size_t nbytes); 25 uint32_t arc4random_uniform(uint32_t upper_bound); 22 26 23 27 #ifdef __cplusplus 24 28 } -
new file headers/private/libbsd/chacha_private.h
diff --git a/headers/private/libbsd/chacha_private.h b/headers/private/libbsd/chacha_private.h new file mode 100644 index 00000000..5aae8d86
- + 1 /* 2 chacha-merged.c version 20080118 3 D. J. Bernstein 4 Public domain. 5 */ 6 7 /* $OpenBSD$ */ 8 9 typedef unsigned char u8; 10 typedef unsigned int u32; 11 12 typedef struct 13 { 14 u32 input[16]; /* could be compressed */ 15 } chacha_ctx; 16 17 #define U8C(v) (v##U) 18 #define U32C(v) (v##U) 19 20 #define U8V(v) ((u8)(v) & U8C(0xFF)) 21 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) 22 23 #define ROTL32(v, n) \ 24 (U32V((v) << (n)) | ((v) >> (32 - (n)))) 25 26 #define U8TO32_LITTLE(p) \ 27 (((u32)((p)[0]) ) | \ 28 ((u32)((p)[1]) << 8) | \ 29 ((u32)((p)[2]) << 16) | \ 30 ((u32)((p)[3]) << 24)) 31 32 #define U32TO8_LITTLE(p, v) \ 33 do { \ 34 (p)[0] = U8V((v) ); \ 35 (p)[1] = U8V((v) >> 8); \ 36 (p)[2] = U8V((v) >> 16); \ 37 (p)[3] = U8V((v) >> 24); \ 38 } while (0) 39 40 #define ROTATE(v,c) (ROTL32(v,c)) 41 #define XOR(v,w) ((v) ^ (w)) 42 #define PLUS(v,w) (U32V((v) + (w))) 43 #define PLUSONE(v) (PLUS((v),1)) 44 45 #define QUARTERROUND(a,b,c,d) \ 46 a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ 47 c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ 48 a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ 49 c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); 50 51 static const char sigma[16] = "expand 32-byte k"; 52 static const char tau[16] = "expand 16-byte k"; 53 54 static void 55 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits) 56 { 57 const char *constants; 58 59 x->input[4] = U8TO32_LITTLE(k + 0); 60 x->input[5] = U8TO32_LITTLE(k + 4); 61 x->input[6] = U8TO32_LITTLE(k + 8); 62 x->input[7] = U8TO32_LITTLE(k + 12); 63 if (kbits == 256) { /* recommended */ 64 k += 16; 65 constants = sigma; 66 } else { /* kbits == 128 */ 67 constants = tau; 68 } 69 x->input[8] = U8TO32_LITTLE(k + 0); 70 x->input[9] = U8TO32_LITTLE(k + 4); 71 x->input[10] = U8TO32_LITTLE(k + 8); 72 x->input[11] = U8TO32_LITTLE(k + 12); 73 x->input[0] = U8TO32_LITTLE(constants + 0); 74 x->input[1] = U8TO32_LITTLE(constants + 4); 75 x->input[2] = U8TO32_LITTLE(constants + 8); 76 x->input[3] = U8TO32_LITTLE(constants + 12); 77 } 78 79 static void 80 chacha_ivsetup(chacha_ctx *x,const u8 *iv) 81 { 82 x->input[12] = 0; 83 x->input[13] = 0; 84 x->input[14] = U8TO32_LITTLE(iv + 0); 85 x->input[15] = U8TO32_LITTLE(iv + 4); 86 } 87 88 static void 89 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) 90 { 91 u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; 92 u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; 93 u8 *ctarget = NULL; 94 u8 tmp[64]; 95 unsigned int i; 96 97 if (!bytes) return; 98 99 j0 = x->input[0]; 100 j1 = x->input[1]; 101 j2 = x->input[2]; 102 j3 = x->input[3]; 103 j4 = x->input[4]; 104 j5 = x->input[5]; 105 j6 = x->input[6]; 106 j7 = x->input[7]; 107 j8 = x->input[8]; 108 j9 = x->input[9]; 109 j10 = x->input[10]; 110 j11 = x->input[11]; 111 j12 = x->input[12]; 112 j13 = x->input[13]; 113 j14 = x->input[14]; 114 j15 = x->input[15]; 115 116 for (;;) { 117 if (bytes < 64) { 118 for (i = 0;i < bytes;++i) tmp[i] = m[i]; 119 m = tmp; 120 ctarget = c; 121 c = tmp; 122 } 123 x0 = j0; 124 x1 = j1; 125 x2 = j2; 126 x3 = j3; 127 x4 = j4; 128 x5 = j5; 129 x6 = j6; 130 x7 = j7; 131 x8 = j8; 132 x9 = j9; 133 x10 = j10; 134 x11 = j11; 135 x12 = j12; 136 x13 = j13; 137 x14 = j14; 138 x15 = j15; 139 for (i = 20;i > 0;i -= 2) { 140 QUARTERROUND( x0, x4, x8,x12) 141 QUARTERROUND( x1, x5, x9,x13) 142 QUARTERROUND( x2, x6,x10,x14) 143 QUARTERROUND( x3, x7,x11,x15) 144 QUARTERROUND( x0, x5,x10,x15) 145 QUARTERROUND( x1, x6,x11,x12) 146 QUARTERROUND( x2, x7, x8,x13) 147 QUARTERROUND( x3, x4, x9,x14) 148 } 149 x0 = PLUS(x0,j0); 150 x1 = PLUS(x1,j1); 151 x2 = PLUS(x2,j2); 152 x3 = PLUS(x3,j3); 153 x4 = PLUS(x4,j4); 154 x5 = PLUS(x5,j5); 155 x6 = PLUS(x6,j6); 156 x7 = PLUS(x7,j7); 157 x8 = PLUS(x8,j8); 158 x9 = PLUS(x9,j9); 159 x10 = PLUS(x10,j10); 160 x11 = PLUS(x11,j11); 161 x12 = PLUS(x12,j12); 162 x13 = PLUS(x13,j13); 163 x14 = PLUS(x14,j14); 164 x15 = PLUS(x15,j15); 165 166 #ifndef KEYSTREAM_ONLY 167 x0 = XOR(x0,U8TO32_LITTLE(m + 0)); 168 x1 = XOR(x1,U8TO32_LITTLE(m + 4)); 169 x2 = XOR(x2,U8TO32_LITTLE(m + 8)); 170 x3 = XOR(x3,U8TO32_LITTLE(m + 12)); 171 x4 = XOR(x4,U8TO32_LITTLE(m + 16)); 172 x5 = XOR(x5,U8TO32_LITTLE(m + 20)); 173 x6 = XOR(x6,U8TO32_LITTLE(m + 24)); 174 x7 = XOR(x7,U8TO32_LITTLE(m + 28)); 175 x8 = XOR(x8,U8TO32_LITTLE(m + 32)); 176 x9 = XOR(x9,U8TO32_LITTLE(m + 36)); 177 x10 = XOR(x10,U8TO32_LITTLE(m + 40)); 178 x11 = XOR(x11,U8TO32_LITTLE(m + 44)); 179 x12 = XOR(x12,U8TO32_LITTLE(m + 48)); 180 x13 = XOR(x13,U8TO32_LITTLE(m + 52)); 181 x14 = XOR(x14,U8TO32_LITTLE(m + 56)); 182 x15 = XOR(x15,U8TO32_LITTLE(m + 60)); 183 #endif 184 185 j12 = PLUSONE(j12); 186 if (!j12) { 187 j13 = PLUSONE(j13); 188 /* stopping at 2^70 bytes per nonce is user's responsibility */ 189 } 190 191 U32TO8_LITTLE(c + 0,x0); 192 U32TO8_LITTLE(c + 4,x1); 193 U32TO8_LITTLE(c + 8,x2); 194 U32TO8_LITTLE(c + 12,x3); 195 U32TO8_LITTLE(c + 16,x4); 196 U32TO8_LITTLE(c + 20,x5); 197 U32TO8_LITTLE(c + 24,x6); 198 U32TO8_LITTLE(c + 28,x7); 199 U32TO8_LITTLE(c + 32,x8); 200 U32TO8_LITTLE(c + 36,x9); 201 U32TO8_LITTLE(c + 40,x10); 202 U32TO8_LITTLE(c + 44,x11); 203 U32TO8_LITTLE(c + 48,x12); 204 U32TO8_LITTLE(c + 52,x13); 205 U32TO8_LITTLE(c + 56,x14); 206 U32TO8_LITTLE(c + 60,x15); 207 208 if (bytes <= 64) { 209 if (bytes < 64) { 210 for (i = 0;i < bytes;++i) ctarget[i] = c[i]; 211 } 212 x->input[12] = j12; 213 x->input[13] = j13; 214 return; 215 } 216 bytes -= 64; 217 c += 64; 218 #ifndef KEYSTREAM_ONLY 219 m += 64; 220 #endif 221 } 222 } -
src/libs/bsd/Jamfile
diff --git a/src/libs/bsd/Jamfile b/src/libs/bsd/Jamfile index e14b3766..1606ebe6 100644
a b SubDir HAIKU_TOP src libs bsd ; 3 3 SetSubDirSupportedPlatforms $(HAIKU_BONE_COMPATIBLE_PLATFORMS) ; 4 4 5 5 UseHeaders [ FDirName $(HAIKU_TOP) headers compatibility bsd ] : true ; 6 UsePrivateHeaders libbsd ; 6 7 7 8 SubDirCcFlags [ FDefines _BSD_SOURCE=1 ] ; 8 9 SubDirC++Flags [ FDefines _BSD_SOURCE=1 ] ; … … local architectureObject ; 11 12 for architectureObject in [ MultiArchSubDirSetup ] { 12 13 on $(architectureObject) { 13 14 SharedLibrary [ MultiArchDefaultGristFiles libbsd.so ] : 15 arc4random.c 16 arc4random_uniform.c 14 17 daemon.c 15 18 err.c 16 19 explicit_bzero.c -
new file src/libs/bsd/arc4random.c
diff --git a/src/libs/bsd/arc4random.c b/src/libs/bsd/arc4random.c new file mode 100644 index 00000000..9a0ac4d4
- + 1 /* $OpenBSD: arc4random.c,v 1.54 2015/09/13 08:31:47 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 1996, David Mazieres <dm@uun.org> 5 * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 6 * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 7 * Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 /* 23 * ChaCha based random number generator for OpenBSD. 24 */ 25 26 #include <fcntl.h> 27 #include <limits.h> 28 #include <signal.h> 29 #include <stdint.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <sys/types.h> 34 #include <sys/time.h> 35 36 #define KEYSTREAM_ONLY 37 #include <chacha_private.h> 38 39 #define minimum(a, b) ((a) < (b) ? (a) : (b)) 40 41 #if defined(__GNUC__) || defined(_MSC_VER) 42 #define inline __inline 43 #else /* __GNUC__ || _MSC_VER */ 44 #define inline 45 #endif /* !__GNUC__ && !_MSC_VER */ 46 47 #define KEYSZ 32 48 #define IVSZ 8 49 #define BLOCKSZ 64 50 #define RSBUFSZ (16*BLOCKSZ) 51 52 /* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */ 53 static struct _rs { 54 size_t rs_have; /* valid bytes at end of rs_buf */ 55 size_t rs_count; /* bytes till reseed */ 56 } *rs; 57 58 /* Maybe be preserved in fork children, if _rs_allocate() decides. */ 59 static struct _rsx { 60 chacha_ctx rs_chacha; /* chacha context for random keystream */ 61 u_char rs_buf[RSBUFSZ]; /* keystream blocks */ 62 } *rsx; 63 64 65 /* 66 * Stub functions for portability. 67 */ 68 69 #include <sys/mman.h> 70 71 #include <pthread.h> 72 #include <signal.h> 73 74 static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; 75 #define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx) 76 #define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) 77 78 #ifdef __GLIBC__ 79 extern void *__dso_handle; 80 extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *); 81 #define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle) 82 #else 83 /* 84 * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if 85 * a program does not link to -lthr. Callbacks registered with pthread_atfork() 86 * appear to fail silently. So, it is not always possible to detect a PID 87 * wraparound. 88 */ 89 #define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) 90 #endif 91 92 static inline void 93 _getentropy_fail(void) 94 { 95 raise(SIGKILL); 96 } 97 98 static volatile sig_atomic_t _rs_forked; 99 100 static inline void 101 _rs_forkhandler(void) 102 { 103 _rs_forked = 1; 104 } 105 106 static inline void 107 _rs_forkdetect(void) 108 { 109 static pid_t _rs_pid = 0; 110 pid_t pid = getpid(); 111 112 if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) { 113 _rs_pid = pid; 114 _rs_forked = 0; 115 if (rs) 116 memset(rs, 0, sizeof(*rs)); 117 } 118 } 119 120 static inline int 121 _rs_allocate(struct _rs **rsp, struct _rsx **rsxp) 122 { 123 if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE, 124 MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) 125 return (-1); 126 127 if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE, 128 MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) { 129 munmap(*rsp, sizeof(**rsp)); 130 return (-1); 131 } 132 133 _ARC4_ATFORK(_rs_forkhandler); 134 return (0); 135 } 136 137 static inline void _rs_rekey(u_char *dat, size_t datlen); 138 139 static inline void 140 _rs_init(u_char *buf, size_t n) 141 { 142 if (n < KEYSZ + IVSZ) 143 return; 144 145 if (rs == NULL) { 146 if (_rs_allocate(&rs, &rsx) == -1) 147 abort(); 148 } 149 150 chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0); 151 chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ); 152 } 153 154 static void 155 _rs_stir(void) 156 { 157 u_char rnd[KEYSZ + IVSZ]; 158 159 if (getentropy(rnd, sizeof rnd) == -1) 160 _getentropy_fail(); 161 162 if (!rs) 163 _rs_init(rnd, sizeof(rnd)); 164 else 165 _rs_rekey(rnd, sizeof(rnd)); 166 explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */ 167 168 /* invalidate rs_buf */ 169 rs->rs_have = 0; 170 memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); 171 172 rs->rs_count = 1600000; 173 } 174 175 static inline void 176 _rs_stir_if_needed(size_t len) 177 { 178 _rs_forkdetect(); 179 if (!rs || rs->rs_count <= len) 180 _rs_stir(); 181 if (rs->rs_count <= len) 182 rs->rs_count = 0; 183 else 184 rs->rs_count -= len; 185 } 186 187 static inline void 188 _rs_rekey(u_char *dat, size_t datlen) 189 { 190 #ifndef KEYSTREAM_ONLY 191 memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf)); 192 #endif 193 /* fill rs_buf with the keystream */ 194 chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf, 195 rsx->rs_buf, sizeof(rsx->rs_buf)); 196 /* mix in optional user provided data */ 197 if (dat) { 198 size_t i, m; 199 200 m = minimum(datlen, KEYSZ + IVSZ); 201 for (i = 0; i < m; i++) 202 rsx->rs_buf[i] ^= dat[i]; 203 } 204 /* immediately reinit for backtracking resistance */ 205 _rs_init(rsx->rs_buf, KEYSZ + IVSZ); 206 memset(rsx->rs_buf, 0, KEYSZ + IVSZ); 207 rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ; 208 } 209 210 static inline void 211 _rs_random_buf(void *_buf, size_t n) 212 { 213 u_char *buf = (u_char *)_buf; 214 u_char *keystream; 215 size_t m; 216 217 _rs_stir_if_needed(n); 218 while (n > 0) { 219 if (rs->rs_have > 0) { 220 m = minimum(n, rs->rs_have); 221 keystream = rsx->rs_buf + sizeof(rsx->rs_buf) 222 - rs->rs_have; 223 memcpy(buf, keystream, m); 224 memset(keystream, 0, m); 225 buf += m; 226 n -= m; 227 rs->rs_have -= m; 228 } 229 if (rs->rs_have == 0) 230 _rs_rekey(NULL, 0); 231 } 232 } 233 234 static inline void 235 _rs_random_u32(uint32_t *val) 236 { 237 u_char *keystream; 238 239 _rs_stir_if_needed(sizeof(*val)); 240 if (rs->rs_have < sizeof(*val)) 241 _rs_rekey(NULL, 0); 242 keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have; 243 memcpy(val, keystream, sizeof(*val)); 244 memset(keystream, 0, sizeof(*val)); 245 rs->rs_have -= sizeof(*val); 246 } 247 248 uint32_t 249 arc4random(void) 250 { 251 uint32_t val; 252 253 _ARC4_LOCK(); 254 _rs_random_u32(&val); 255 _ARC4_UNLOCK(); 256 return val; 257 } 258 259 void 260 arc4random_buf(void *buf, size_t n) 261 { 262 _ARC4_LOCK(); 263 _rs_random_buf(buf, n); 264 _ARC4_UNLOCK(); 265 } -
new file src/libs/bsd/arc4random_uniform.c
diff --git a/src/libs/bsd/arc4random_uniform.c b/src/libs/bsd/arc4random_uniform.c new file mode 100644 index 00000000..2d224345
- + 1 /* $OpenBSD: arc4random_uniform.c,v 1.2 2015/09/13 08:31:47 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <stdlib.h> 21 22 /* 23 * Calculate a uniformly distributed random number less than upper_bound 24 * avoiding "modulo bias". 25 * 26 * Uniformity is achieved by generating new random numbers until the one 27 * returned is outside the range [0, 2**32 % upper_bound). This 28 * guarantees the selected random number will be inside 29 * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) 30 * after reduction modulo upper_bound. 31 */ 32 uint32_t 33 arc4random_uniform(uint32_t upper_bound) 34 { 35 uint32_t r, min; 36 37 if (upper_bound < 2) 38 return 0; 39 40 /* 2**32 % x == (2**32 - x) % x */ 41 min = -upper_bound % upper_bound; 42 43 /* 44 * This could theoretically loop forever but each retry has 45 * p > 0.5 (worst case, usually far better) of selecting a 46 * number inside the range we need, so it should rarely need 47 * to re-roll. 48 */ 49 for (;;) { 50 r = arc4random(); 51 if (r >= min) 52 break; 53 } 54 55 return r % upper_bound; 56 }