Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 1 | /*- |
Elliott Hughes | 96b4363 | 2015-07-17 11:39:41 -0700 | [diff] [blame] | 2 | * Copyright © 2011, 2014, 2015 |
Elliott Hughes | fc0307d | 2016-02-02 15:26:47 -0800 | [diff] [blame] | 3 | * mirabilos <m@mirbsd.org> |
Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 4 | * |
| 5 | * Provided that these terms and disclaimer and all copyright notices |
| 6 | * are retained or reproduced in an accompanying document, permission |
| 7 | * is granted to deal in this work without restriction, including un‐ |
| 8 | * limited rights to use, publicly perform, distribute, sell, modify, |
| 9 | * merge, give away, or sublicence. |
| 10 | * |
| 11 | * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to |
| 12 | * the utmost extent permitted by applicable law, neither express nor |
| 13 | * implied; without malicious intent or gross negligence. In no event |
| 14 | * may a licensor, author or contributor be held liable for indirect, |
| 15 | * direct, other damage, loss, or other issues arising in any way out |
| 16 | * of dealing in the work, even if advised of the possibility of such |
| 17 | * damage or existence of a defect, except proven that it results out |
| 18 | * of said person’s immediate fault when using the work as intended. |
| 19 | *- |
| 20 | * This file provides BAFH (Better Avalanche for the Jenkins Hash) as |
| 21 | * inline macro bodies that operate on “register uint32_t” variables, |
| 22 | * with variants that use their local intermediate registers. |
| 23 | * |
| 24 | * Usage note for BAFH with entropy distribution: input up to 4 bytes |
| 25 | * is best combined into a 32-bit unsigned integer, which is then run |
| 26 | * through BAFHFinish_reg for mixing and then used as context instead |
| 27 | * of 0. Longer input should be handled the same: take the first four |
| 28 | * bytes as IV after mixing then add subsequent bytes the same way. |
| 29 | * This needs counting input bytes and is endian-dependent, thus not, |
| 30 | * for speed reasons, specified for the regular stable hash, but very |
| 31 | * much recommended if the actual output value may differ across runs |
| 32 | * (so is using a random value instead of 0 for the IV). |
Elliott Hughes | 56b517d | 2014-10-06 11:30:44 -0700 | [diff] [blame] | 33 | *- |
| 34 | * Little quote gem: |
| 35 | * We are looking into it. Changing the core |
| 36 | * hash function in PHP isn't a trivial change |
| 37 | * and will take us some time. |
| 38 | * -- Rasmus Lerdorf |
Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 39 | */ |
| 40 | |
| 41 | #ifndef SYSKERN_MIRHASH_H |
| 42 | #define SYSKERN_MIRHASH_H 1 |
| 43 | #define SYSKERN_MIRHASH_BAFH |
| 44 | |
| 45 | #include <sys/types.h> |
| 46 | |
Elliott Hughes | fc0307d | 2016-02-02 15:26:47 -0800 | [diff] [blame] | 47 | __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.6 2015/11/29 17:05:02 tg Exp $"); |
Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 48 | |
| 49 | /*- |
| 50 | * BAFH itself is defined by the following primitives: |
| 51 | * |
| 52 | * • BAFHInit(ctx) initialises the hash context, which consists of a |
| 53 | * sole 32-bit unsigned integer (ideally in a register), to 0. |
| 54 | * It is possible to use any initial value out of [0; 2³²[ – which |
| 55 | * is, in fact, recommended if using BAFH for entropy distribution |
| 56 | * – but for a regular stable hash, the IV 0 is needed. |
| 57 | * |
| 58 | * • BAFHUpdateOctet(ctx,val) compresses the unsigned 8-bit quantity |
| 59 | * into the hash context. The algorithm used is Jenkins’ one-at-a- |
| 60 | * time, except that an additional constant 1 is added so that, if |
| 61 | * the context is (still) zero, adding a NUL byte is not ignored. |
| 62 | * |
| 63 | * • BAFHror(eax,cl) evaluates to the unsigned 32-bit integer “eax”, |
Elliott Hughes | 96b4363 | 2015-07-17 11:39:41 -0700 | [diff] [blame] | 64 | * rotated right by “cl” ∈ [0; 31] (no casting, be careful!) where |
| 65 | * “eax” must be uint32_t and “cl” an in-range integer. |
Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 66 | * |
| 67 | * • BAFHFinish(ctx) avalanches the context around so every sub-byte |
| 68 | * depends on all input octets; afterwards, the context variable’s |
| 69 | * value is the hash output. BAFH does not use any padding, nor is |
| 70 | * the input length added; this is due to the common use case (for |
| 71 | * quick entropy distribution and use with a hashtable). |
| 72 | * Warning: BAFHFinish uses the MixColumn algorithm of AES – which |
| 73 | * is reversible (to avoid introducing funnels and reducing entro‐ |
| 74 | * py), so blinding may need to be employed for some uses, e.g. in |
| 75 | * mksh, after a fork. |
| 76 | * |
| 77 | * The BAFHUpdateOctet and BAFHFinish are available in two flavours: |
| 78 | * suffixed with _reg (assumes the context is in a register) or _mem |
| 79 | * (which doesn’t). |
| 80 | * |
| 81 | * The following high-level macros (with _reg and _mem variants) are |
| 82 | * available: |
| 83 | * |
| 84 | * • BAFHUpdateMem(ctx,buf,len) adds a memory block to a context. |
| 85 | * • BAFHUpdateStr(ctx,buf) is equivalent to using len=strlen(buf). |
| 86 | * • BAFHHostMem(ctx,buf,len) calculates the hash of the memory buf‐ |
| 87 | * fer using the first 4 octets (mixed) for IV, as outlined above; |
| 88 | * the result is endian-dependent; “ctx” assumed to be a register. |
| 89 | * • BAFHHostStr(ctx,buf) does the same for C strings. |
| 90 | * |
| 91 | * All macros may use ctx multiple times in their expansion, but all |
Elliott Hughes | 96b4363 | 2015-07-17 11:39:41 -0700 | [diff] [blame] | 92 | * other arguments are always evaluated at most once except BAFHror. |
Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 93 | * |
| 94 | * To stay portable, never use the BAFHHost*() macros (these are for |
| 95 | * host-local entropy shuffling), and encode numbers using ULEB128. |
| 96 | */ |
| 97 | |
| 98 | #define BAFHInit(h) do { \ |
| 99 | (h) = 0; \ |
| 100 | } while (/* CONSTCOND */ 0) |
| 101 | |
| 102 | #define BAFHUpdateOctet_reg(h,b) do { \ |
| 103 | (h) += (uint8_t)(b); \ |
| 104 | ++(h); \ |
| 105 | (h) += (h) << 10; \ |
| 106 | (h) ^= (h) >> 6; \ |
| 107 | } while (/* CONSTCOND */ 0) |
| 108 | |
| 109 | #define BAFHUpdateOctet_mem(m,b) do { \ |
| 110 | register uint32_t BAFH_h = (m); \ |
| 111 | \ |
| 112 | BAFHUpdateOctet_reg(BAFH_h, (b)); \ |
| 113 | (m) = BAFH_h; \ |
| 114 | } while (/* CONSTCOND */ 0) |
| 115 | |
| 116 | #define BAFHror(eax,cl) (((eax) >> (cl)) | ((eax) << (32 - (cl)))) |
| 117 | |
| 118 | #define BAFHFinish_reg(h) do { \ |
| 119 | register uint32_t BAFHFinish_v; \ |
| 120 | \ |
| 121 | BAFHFinish_v = ((h) >> 7) & 0x01010101U; \ |
| 122 | BAFHFinish_v += BAFHFinish_v << 1; \ |
| 123 | BAFHFinish_v += BAFHFinish_v << 3; \ |
| 124 | BAFHFinish_v ^= ((h) << 1) & 0xFEFEFEFEU; \ |
| 125 | \ |
| 126 | BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \ |
| 127 | BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \ |
| 128 | BAFHFinish_v ^= ((h) = BAFHror((h), 8)); \ |
| 129 | (h) = BAFHror((h), 8) ^ BAFHFinish_v; \ |
| 130 | } while (/* CONSTCOND */ 0) |
| 131 | |
| 132 | #define BAFHFinish_mem(m) do { \ |
| 133 | register uint32_t BAFHFinish_v, BAFH_h = (m); \ |
| 134 | \ |
| 135 | BAFHFinish_v = (BAFH_h >> 7) & 0x01010101U; \ |
| 136 | BAFHFinish_v += BAFHFinish_v << 1; \ |
| 137 | BAFHFinish_v += BAFHFinish_v << 3; \ |
| 138 | BAFHFinish_v ^= (BAFH_h << 1) & 0xFEFEFEFEU; \ |
| 139 | \ |
| 140 | BAFHFinish_v ^= BAFHror(BAFHFinish_v, 8); \ |
| 141 | BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \ |
| 142 | BAFHFinish_v ^= (BAFH_h = BAFHror(BAFH_h, 8)); \ |
| 143 | (m) = BAFHror(BAFH_h, 8) ^ BAFHFinish_v; \ |
| 144 | } while (/* CONSTCOND */ 0) |
| 145 | |
| 146 | #define BAFHUpdateMem_reg(h,p,z) do { \ |
| 147 | register const uint8_t *BAFHUpdate_p; \ |
| 148 | register size_t BAFHUpdate_z = (z); \ |
| 149 | \ |
| 150 | BAFHUpdate_p = (const void *)(p); \ |
| 151 | while (BAFHUpdate_z--) \ |
| 152 | BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \ |
| 153 | } while (/* CONSTCOND */ 0) |
| 154 | |
| 155 | /* meh should have named them _r/m but that’s not valid C */ |
| 156 | #define BAFHUpdateMem_mem(m,p,z) do { \ |
| 157 | register uint32_t BAFH_h = (m); \ |
| 158 | \ |
| 159 | BAFHUpdateMem_reg(BAFH_h, (p), (z)); \ |
| 160 | (m) = BAFH_h; \ |
| 161 | } while (/* CONSTCOND */ 0) |
| 162 | |
| 163 | #define BAFHUpdateStr_reg(h,s) do { \ |
| 164 | register const uint8_t *BAFHUpdate_s; \ |
| 165 | register uint8_t BAFHUpdate_c; \ |
| 166 | \ |
| 167 | BAFHUpdate_s = (const void *)(s); \ |
| 168 | while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \ |
| 169 | BAFHUpdateOctet_reg((h), BAFHUpdate_c); \ |
| 170 | } while (/* CONSTCOND */ 0) |
| 171 | |
| 172 | #define BAFHUpdateStr_mem(m,s) do { \ |
| 173 | register uint32_t BAFH_h = (m); \ |
| 174 | \ |
| 175 | BAFHUpdateStr_reg(BAFH_h, (s)); \ |
| 176 | (m) = BAFH_h; \ |
| 177 | } while (/* CONSTCOND */ 0) |
| 178 | |
| 179 | #define BAFHHostMem(h,p,z) do { \ |
| 180 | register const uint8_t *BAFHUpdate_p; \ |
| 181 | register size_t BAFHUpdate_z = (z); \ |
| 182 | size_t BAFHHost_z; \ |
| 183 | union { \ |
| 184 | uint8_t as_u8[4]; \ |
| 185 | uint32_t as_u32; \ |
| 186 | } BAFHHost_v; \ |
| 187 | \ |
| 188 | BAFHUpdate_p = (const void *)(p); \ |
| 189 | BAFHHost_v.as_u32 = 0; \ |
| 190 | BAFHHost_z = BAFHUpdate_z < 4 ? BAFHUpdate_z : 4; \ |
| 191 | memcpy(BAFHHost_v.as_u8, BAFHUpdate_p, BAFHHost_z); \ |
| 192 | BAFHUpdate_p += BAFHHost_z; \ |
| 193 | BAFHUpdate_z -= BAFHHost_z; \ |
| 194 | (h) = BAFHHost_v.as_u32; \ |
| 195 | BAFHFinish_reg(h); \ |
| 196 | while (BAFHUpdate_z--) \ |
| 197 | BAFHUpdateOctet_reg((h), *BAFHUpdate_p++); \ |
| 198 | BAFHFinish_reg(h); \ |
| 199 | } while (/* CONSTCOND */ 0) |
| 200 | |
| 201 | #define BAFHHostStr(h,s) do { \ |
| 202 | register const uint8_t *BAFHUpdate_s; \ |
| 203 | register uint8_t BAFHUpdate_c; \ |
| 204 | union { \ |
| 205 | uint8_t as_u8[4]; \ |
| 206 | uint32_t as_u32; \ |
| 207 | } BAFHHost_v; \ |
| 208 | \ |
| 209 | BAFHUpdate_s = (const void *)(s); \ |
Elliott Hughes | 96b4363 | 2015-07-17 11:39:41 -0700 | [diff] [blame] | 210 | BAFHHost_v.as_u32 = 0; \ |
Elliott Hughes | 737fdce | 2014-08-07 12:59:26 -0700 | [diff] [blame] | 211 | if ((BAFHHost_v.as_u8[0] = *BAFHUpdate_s) != 0) \ |
| 212 | ++BAFHUpdate_s; \ |
| 213 | if ((BAFHHost_v.as_u8[1] = *BAFHUpdate_s) != 0) \ |
| 214 | ++BAFHUpdate_s; \ |
| 215 | if ((BAFHHost_v.as_u8[2] = *BAFHUpdate_s) != 0) \ |
| 216 | ++BAFHUpdate_s; \ |
| 217 | if ((BAFHHost_v.as_u8[3] = *BAFHUpdate_s) != 0) \ |
| 218 | ++BAFHUpdate_s; \ |
| 219 | (h) = BAFHHost_v.as_u32; \ |
| 220 | BAFHFinish_reg(h); \ |
| 221 | while ((BAFHUpdate_c = *BAFHUpdate_s++) != 0) \ |
| 222 | BAFHUpdateOctet_reg((h), BAFHUpdate_c); \ |
| 223 | BAFHFinish_reg(h); \ |
| 224 | } while (/* CONSTCOND */ 0) |
| 225 | |
| 226 | #endif |