Home | History | Annotate | Download | only in src
      1 /*-
      2  * Copyright  2011, 2014, 2015
      3  *	mirabilos <m (at) mirbsd.org>
      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 persons 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).
     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
     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 
     47 __RCSID("$MirOS: src/bin/mksh/mirhash.h,v 1.6 2015/11/29 17:05:02 tg Exp $");
     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,
     64  *   rotated right by cl  [0; 31] (no casting, be careful!) where
     65  *   eax must be uint32_t and cl an in-range integer.
     66  *
     67  *  BAFHFinish(ctx) avalanches the context around so every sub-byte
     68  *   depends on all input octets; afterwards, the context variables
     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 doesnt).
     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
     92  * other arguments are always evaluated at most once except BAFHror.
     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 thats 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);			\
    210 	BAFHHost_v.as_u32 = 0;					\
    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
    227