X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbasic%2Fsiphash24.c;h=4bb41786c8b2a27b224ca9b9a0a682bde50e6fb8;hb=f082899f180431f04553e4ee3b0968020ef59188;hp=1c827dff1ac942f099d82871129da5e423365d6b;hpb=15acb464c46e743bb035589a398cff75b3538303;p=elogind.git diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c index 1c827dff1..4bb41786c 100644 --- a/src/basic/siphash24.c +++ b/src/basic/siphash24.c @@ -13,184 +13,188 @@ this software. If not, see . (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd) + (Refactored by Tom Gundersen to split up in several functions and follow systemd + coding style) */ -#include + #include -#include +#include "macro.h" #include "siphash24.h" +#include "unaligned.h" + +static inline uint64_t rotate_left(uint64_t x, uint8_t b) { + assert(b < 64); -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint8_t u8; - -#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) ) - -#define U32TO8_LE(p, v) \ - (p)[0] = (u8)((v) ); (p)[1] = (u8)((v) >> 8); \ - (p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24); - -#define U64TO8_LE(p, v) \ - U32TO8_LE((p), (u32)((v) )); \ - U32TO8_LE((p) + 4, (u32)((v) >> 32)); - -#define U8TO64_LE(p) \ - (((u64)((p)[0]) ) | \ - ((u64)((p)[1]) << 8) | \ - ((u64)((p)[2]) << 16) | \ - ((u64)((p)[3]) << 24) | \ - ((u64)((p)[4]) << 32) | \ - ((u64)((p)[5]) << 40) | \ - ((u64)((p)[6]) << 48) | \ - ((u64)((p)[7]) << 56)) - -#define SIPROUND(state) \ - do { \ - (state)->v0 += (state)->v1; (state)->v1=ROTL((state)->v1,13); (state)->v1 ^= (state)->v0; (state)->v0=ROTL((state)->v0,32); \ - (state)->v2 += (state)->v3; (state)->v3=ROTL((state)->v3,16); (state)->v3 ^= (state)->v2; \ - (state)->v0 += (state)->v3; (state)->v3=ROTL((state)->v3,21); (state)->v3 ^= (state)->v0; \ - (state)->v2 += (state)->v1; (state)->v1=ROTL((state)->v1,17); (state)->v1 ^= (state)->v2; (state)->v2=ROTL((state)->v2,32); \ - } while(0) - -struct siphash { - u64 v0; - u64 v1; - u64 v2; - u64 v3; - u64 padding; - size_t inlen; -}; - -static void siphash_init(struct siphash *state, const uint8_t k[16]) { - u64 k0, k1; - - k0 = U8TO64_LE( k ); - k1 = U8TO64_LE( k + 8 ); - - /* "somepseudorandomlygeneratedbytes" */ - state->v0 = 0x736f6d6570736575ULL ^ k0; - state->v1 = 0x646f72616e646f6dULL ^ k1; - state->v2 = 0x6c7967656e657261ULL ^ k0; - state->v3 = 0x7465646279746573ULL ^ k1; - state->padding = 0; - state->inlen = 0; + return (x << b) | (x >> (64 - b)); } -static void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { - u64 m; - const u8 *in = _in; - const u8 *end = in + inlen; - int left = state->inlen & 7; +static inline void sipround(struct siphash *state) { + assert(state); + + state->v0 += state->v1; + state->v1 = rotate_left(state->v1, 13); + state->v1 ^= state->v0; + state->v0 = rotate_left(state->v0, 32); + state->v2 += state->v3; + state->v3 = rotate_left(state->v3, 16); + state->v3 ^= state->v2; + state->v0 += state->v3; + state->v3 = rotate_left(state->v3, 21); + state->v3 ^= state->v0; + state->v2 += state->v1; + state->v1 = rotate_left(state->v1, 17); + state->v1 ^= state->v2; + state->v2 = rotate_left(state->v2, 32); +} - /* update total length */ - state->inlen += inlen; +void siphash24_init(struct siphash *state, const uint8_t k[16]) { + uint64_t k0, k1; - /* if padding exists, fill it out */ - if (left > 0) { - for ( ; in < end && left < 8; in ++, left ++ ) - state->padding |= ( ( u64 )*in ) << (left * 8); + assert(state); + assert(k); - if (in == end && left < 8) - /* we did not have enough input to fill out the padding completely */ - return; + k0 = unaligned_read_le64(k); + k1 = unaligned_read_le64(k + 8); -#ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 ); - printf( "(%3d) compress padding %08x %08x\n", ( int )state->inlen, ( u32 )( state->padding >> 32 ), ( u32 )state->padding ); -#endif - state->v3 ^= state->padding; - SIPROUND(state); - SIPROUND(state); - state->v0 ^= state->padding; - - state->padding = 0; - } + *state = (struct siphash) { + /* "somepseudorandomlygeneratedbytes" */ + .v0 = 0x736f6d6570736575ULL ^ k0, + .v1 = 0x646f72616e646f6dULL ^ k1, + .v2 = 0x6c7967656e657261ULL ^ k0, + .v3 = 0x7465646279746573ULL ^ k1, + .padding = 0, + .inlen = 0, + }; +} - end -= ( state->inlen % sizeof (u64) ); +void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { - for ( ; in < end; in += 8 ) - { - m = U8TO64_LE( in ); -#ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 ); - printf( "(%3d) compress %08x %08x\n", ( int )state->inlen, ( u32 )( m >> 32 ), ( u32 )m ); -#endif - state->v3 ^= m; - SIPROUND(state); - SIPROUND(state); - state->v0 ^= m; - } + const uint8_t *in = _in; + const uint8_t *end = in + inlen; + size_t left = state->inlen & 7; + uint64_t m; - left = state->inlen & 7; + assert(in); + assert(state); - switch( left ) - { - case 7: state->padding |= ( ( u64 )in[ 6] ) << 48; + /* Update total length */ + state->inlen += inlen; - case 6: state->padding |= ( ( u64 )in[ 5] ) << 40; + /* If padding exists, fill it out */ + if (left > 0) { + for ( ; in < end && left < 8; in ++, left ++) + state->padding |= ((uint64_t) *in) << (left * 8); - case 5: state->padding |= ( ( u64 )in[ 4] ) << 32; + if (in == end && left < 8) + /* We did not have enough input to fill out the padding completely */ + return; - case 4: state->padding |= ( ( u64 )in[ 3] ) << 24; +#ifdef DEBUG + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding); +#endif - case 3: state->padding |= ( ( u64 )in[ 2] ) << 16; + state->v3 ^= state->padding; + sipround(state); + sipround(state); + state->v0 ^= state->padding; - case 2: state->padding |= ( ( u64 )in[ 1] ) << 8; + state->padding = 0; + } - case 1: state->padding |= ( ( u64 )in[ 0] ); break; + end -= (state->inlen % sizeof(uint64_t)); - case 0: break; - } + for ( ; in < end; in += 8) { + m = unaligned_read_le64(in); +#ifdef DEBUG + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m); +#endif + state->v3 ^= m; + sipround(state); + sipround(state); + state->v0 ^= m; + } + + left = state->inlen & 7; + switch (left) { + case 7: + state->padding |= ((uint64_t) in[6]) << 48; + /* fall through */ + case 6: + state->padding |= ((uint64_t) in[5]) << 40; + /* fall through */ + case 5: + state->padding |= ((uint64_t) in[4]) << 32; + /* fall through */ + case 4: + state->padding |= ((uint64_t) in[3]) << 24; + /* fall through */ + case 3: + state->padding |= ((uint64_t) in[2]) << 16; + /* fall through */ + case 2: + state->padding |= ((uint64_t) in[1]) << 8; + /* fall through */ + case 1: + state->padding |= ((uint64_t) in[0]); + /* fall through */ + case 0: + break; + } } -static u64 siphash24_finalize(struct siphash *state) { - u64 b; +uint64_t siphash24_finalize(struct siphash *state) { + uint64_t b; + + assert(state); + + b = state->padding | (((uint64_t) state->inlen) << 56); - b = state->padding | (( ( u64 )state->inlen ) << 56); #ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 ); - printf( "(%3d) padding %08x %08x\n", ( int )state->inlen, ( u32 )( state->padding >> 32 ), ( u32 )state->padding ); + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding); #endif - state->v3 ^= b; - SIPROUND(state); - SIPROUND(state); - state->v0 ^= b; + + state->v3 ^= b; + sipround(state); + sipround(state); + state->v0 ^= b; #ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v0 >> 32 ), ( u32 )state->v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v1 >> 32 ), ( u32 )state->v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v2 >> 32 ), ( u32 )state->v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )state->inlen, ( u32 )( state->v3 >> 32 ), ( u32 )state->v3 ); + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); #endif - state->v2 ^= 0xff; - SIPROUND(state); - SIPROUND(state); - SIPROUND(state); - SIPROUND(state); + state->v2 ^= 0xff; - return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; -} + sipround(state); + sipround(state); + sipround(state); + sipround(state); -/* SipHash-2-4 */ -void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) -{ - struct siphash state; - u64 b; + return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; +} - siphash_init(&state, k); +uint64_t siphash24(const void *in, size_t inlen, const uint8_t k[16]) { + struct siphash state; - siphash24_compress(_in, inlen, &state); + assert(in); + assert(k); - b = siphash24_finalize(&state); + siphash24_init(&state, k); + siphash24_compress(in, inlen, &state); - U64TO8_LE( out, b ); + return siphash24_finalize(&state); }