diff --git a/src/c-siphash/.github/workflows/ci.yml b/src/c-siphash/.github/workflows/ci.yml index d54b120011..00bca960db 100644 --- a/src/c-siphash/.github/workflows/ci.yml +++ b/src/c-siphash/.github/workflows/ci.yml @@ -7,11 +7,26 @@ on: - cron: '0 0 * * *' jobs: - ci: - name: CI with Default Configuration + ci-linux: + name: Linux CI uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1 with: cabuild_ref: "v1" + linux: true m32: true matrixmode: true valgrind: true + ci-macos: + name: MacOS CI + uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1 + with: + cabuild_ref: "v1" + linux: false + macos: true + ci-windows: + name: Windows CI + uses: bus1/cabuild/.github/workflows/ci-c-util.yml@v1 + with: + cabuild_ref: "v1" + linux: false + windows: true diff --git a/src/c-siphash/AUTHORS b/src/c-siphash/AUTHORS index 3c6436a932..ee6d914fdc 100644 --- a/src/c-siphash/AUTHORS +++ b/src/c-siphash/AUTHORS @@ -33,5 +33,6 @@ COPYRIGHT: (ordered alphabetically) Copyright (C) 2015-2022 Red Hat, Inc. AUTHORS: (ordered alphabetically) + Daniele Nicolodi David Rheinsberg Tom Gundersen diff --git a/src/c-siphash/src/c-siphash.c b/src/c-siphash/src/c-siphash.c index 720e403a43..b92af658dd 100644 --- a/src/c-siphash/src/c-siphash.c +++ b/src/c-siphash/src/c-siphash.c @@ -8,7 +8,7 @@ * * So far, only SipHash24 is implemented, since there was no need for other * parameters. However, adjusted c_siphash_append_X() and - * C_siphash_finalize_Y() can be easily provided, if required. + * c_siphash_finalize_Y() can be easily provided, if required. */ #include @@ -88,23 +88,8 @@ _c_public_ void c_siphash_init(CSipHash *state, const uint8_t seed[16]) { }; } -/** - * c_siphash_append() - hash stream of data - * @state: context object - * @bytes: array of input bytes - * @n_bytes: number of input bytes - * - * This feeds an array of bytes into the SipHash state machine. This is a - * streaming-capable API. That is, the resulting hash is the same, regardless - * of the way you chunk the input. - * This function simply feeds the given bytes into the SipHash state machine. - * It does not produce a final hash. You can call this function many times to - * append more data. To retrieve the final hash, call c_siphash_finalize(). - * - * Note that this implementation works best when used with chunk-sizes of - * multiples of 64bit (8-bytes). This is not a requirement, though. - */ -_c_public_ void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n_bytes) { + +static inline _c_always_inline_ void c_siphash_append_N(CSipHash *state, const uint8_t *bytes, size_t n_bytes, unsigned N) { const uint8_t *end = bytes + n_bytes; size_t left = state->n_bytes & 7; uint64_t m; @@ -123,8 +108,8 @@ _c_public_ void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n return; state->v3 ^= state->padding; - c_siphash_sipround(state); - c_siphash_sipround(state); + for (unsigned i = 0; i < N; i++) + c_siphash_sipround(state); state->v0 ^= state->padding; state->padding = 0; @@ -141,8 +126,8 @@ _c_public_ void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n m = c_siphash_read_le64(bytes); state->v3 ^= m; - c_siphash_sipround(state); - c_siphash_sipround(state); + for (unsigned i = 0; i < N; i++) + c_siphash_sipround(state); state->v0 ^= m; } @@ -179,6 +164,50 @@ _c_public_ void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n } } +static inline _c_always_inline_ uint64_t c_siphash_finalize_NM(CSipHash *state, unsigned N, unsigned M) { + uint64_t b; + + b = state->padding | (((uint64_t) state->n_bytes) << 56); + + state->v3 ^= b; + for (unsigned i = 0; i < N; i++) + c_siphash_sipround(state); + state->v0 ^= b; + + state->v2 ^= 0xff; + + for (unsigned i = 0; i < M; i++) + c_siphash_sipround(state); + + return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; +} + +/** + * c_siphash_append() - hash stream of data + * @state: context object + * @bytes: array of input bytes + * @n_bytes: number of input bytes + * + * This feeds an array of bytes into the SipHash state machine. This is a + * streaming-capable API. That is, the resulting hash is the same, regardless + * of the way you chunk the input. + * This function simply feeds the given bytes into the SipHash state machine. + * It does not produce a final hash. You can call this function many times to + * append more data. To retrieve the final hash, call c_siphash_finalize(). + * + * Note that this implementation works best when used with chunk-sizes of + * multiples of 64bit (8-bytes). This is not a requirement, though. + * + * This uses the SipHash-2-4 variant. + */ +_c_public_ void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n_bytes) { + c_siphash_append_N(state, bytes, n_bytes, 2); +} + +_c_public_ void c_siphash_append_13(CSipHash *state, const uint8_t *bytes, size_t n_bytes) { + c_siphash_append_N(state, bytes, n_bytes, 1); +} + /** * c_siphash_finalize() - finalize hash * @state: context object @@ -192,26 +221,16 @@ _c_public_ void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n * the object, anymore, you can release it any time. There is no need to * destroy the object explicitly. * + * This uses the SipHash-2-4 variant. + * * Return: 64bit hash value */ _c_public_ uint64_t c_siphash_finalize(CSipHash *state) { - uint64_t b; + return c_siphash_finalize_NM(state, 2, 4); +} - b = state->padding | (((uint64_t) state->n_bytes) << 56); - - state->v3 ^= b; - c_siphash_sipround(state); - c_siphash_sipround(state); - state->v0 ^= b; - - state->v2 ^= 0xff; - - c_siphash_sipround(state); - c_siphash_sipround(state); - c_siphash_sipround(state); - c_siphash_sipround(state); - - return state->v0 ^ state->v1 ^ state->v2 ^ state->v3; +_c_public_ uint64_t c_siphash_finalize_13(CSipHash *state) { + return c_siphash_finalize_NM(state, 1, 3); } /** @@ -233,13 +252,24 @@ _c_public_ uint64_t c_siphash_finalize(CSipHash *state) { * Unlike the streaming API, this is a one-shot call suitable for any data that * is available in-memory at the same time. * + * This uses the SipHash-2-4 variant. + * * Return: 64bit hash value */ _c_public_ uint64_t c_siphash_hash(const uint8_t seed[16], const uint8_t *bytes, size_t n_bytes) { CSipHash state; c_siphash_init(&state, seed); - c_siphash_append(&state, bytes, n_bytes); + c_siphash_append_24(&state, bytes, n_bytes); - return c_siphash_finalize(&state); + return c_siphash_finalize_24(&state); +} + +_c_public_ uint64_t c_siphash_hash_13(const uint8_t seed[16], const uint8_t *bytes, size_t n_bytes) { + CSipHash state; + + c_siphash_init(&state, seed); + c_siphash_append_13(&state, bytes, n_bytes); + + return c_siphash_finalize_13(&state); } diff --git a/src/c-siphash/src/c-siphash.h b/src/c-siphash/src/c-siphash.h index c0cfc1e084..24fc3f2714 100644 --- a/src/c-siphash/src/c-siphash.h +++ b/src/c-siphash/src/c-siphash.h @@ -47,14 +47,36 @@ struct CSipHash { size_t n_bytes; }; -#define C_SIPHASH_NULL {} +#define C_SIPHASH_NULL {0} void c_siphash_init(CSipHash *state, const uint8_t seed[16]); + +/* siphash-2-4 (default for historical reasons) */ + void c_siphash_append(CSipHash *state, const uint8_t *bytes, size_t n_bytes); uint64_t c_siphash_finalize(CSipHash *state); - uint64_t c_siphash_hash(const uint8_t seed[16], const uint8_t *bytes, size_t n_bytes); +/* siphash-1-3 */ + +void c_siphash_append_13(CSipHash *state, const uint8_t *bytes, size_t n_bytes); +uint64_t c_siphash_finalize_13(CSipHash *state); +uint64_t c_siphash_hash_13(const uint8_t seed[16], const uint8_t *bytes, size_t n_bytes); + +/* inline helpers */ + +static inline void c_siphash_append_24(CSipHash *state, const uint8_t *bytes, size_t n_bytes) { + c_siphash_append(state, bytes, n_bytes); +} + +static inline uint64_t c_siphash_finalize_24(CSipHash *state) { + return c_siphash_finalize(state); +} + +static inline uint64_t c_siphash_hash_24(const uint8_t seed[16], const uint8_t *bytes, size_t n_bytes) { + return c_siphash_hash(seed, bytes, n_bytes); +} + #ifdef __cplusplus } #endif diff --git a/src/c-siphash/src/libcsiphash.def b/src/c-siphash/src/libcsiphash.def new file mode 100644 index 0000000000..445cb0c42b --- /dev/null +++ b/src/c-siphash/src/libcsiphash.def @@ -0,0 +1,9 @@ +LIBRARY csiphash-1-0 +EXPORTS + c_siphash_init + c_siphash_append + c_siphash_finalize + c_siphash_hash + c_siphash_append_13 + c_siphash_finalize_13 + c_siphash_hash_13 diff --git a/src/c-siphash/src/libcsiphash.sym b/src/c-siphash/src/libcsiphash.sym index 5ab16d6115..aad193d011 100644 --- a/src/c-siphash/src/libcsiphash.sym +++ b/src/c-siphash/src/libcsiphash.sym @@ -7,3 +7,10 @@ global: local: *; }; + +LIBCSIPHASH_2 { +global: + c_siphash_append_13; + c_siphash_finalize_13; + c_siphash_hash_13; +} LIBCSIPHASH_1; diff --git a/src/c-siphash/src/meson.build b/src/c-siphash/src/meson.build index 7300f355a9..f2cc186428 100644 --- a/src/c-siphash/src/meson.build +++ b/src/c-siphash/src/meson.build @@ -2,6 +2,7 @@ # target: libcsiphash.so # +libcsiphash_deffile = join_paths(meson.current_source_dir(), 'libcsiphash.def') libcsiphash_symfile = join_paths(meson.current_source_dir(), 'libcsiphash.sym') libcsiphash_deps = [ @@ -23,6 +24,7 @@ libcsiphash_both = both_libraries( '-Wl,--version-script=@0@'.format(libcsiphash_symfile), ] : [], link_depends: libcsiphash_symfile, + vs_module_defs: libcsiphash_deffile, soversion: 0, ) diff --git a/src/c-siphash/src/test-basic.c b/src/c-siphash/src/test-basic.c index 6b80d0cdfa..58442dac26 100644 --- a/src/c-siphash/src/test-basic.c +++ b/src/c-siphash/src/test-basic.c @@ -14,7 +14,7 @@ /* See https://131002.net/siphash/siphash.pdf, Appendix A. */ static void do_reference_test(const uint8_t *in, size_t len, const uint8_t *key) { - CSipHash state = {}; + CSipHash state = C_SIPHASH_NULL; uint64_t out; unsigned i, j; @@ -77,9 +77,9 @@ static void test_short_hashes(void) { 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; const uint8_t key[16] = { 0x22, 0x24, 0x41, 0x22, 0x55, 0x77, 0x88, 0x07, 0x23, 0x09, 0x23, 0x14, 0x0c, 0x33, 0x0e, 0x0f}; - uint8_t two[sizeof one] = {}; + uint8_t two[sizeof one] = {0}; - CSipHash state1 = {}, state2 = {}; + CSipHash state1 = C_SIPHASH_NULL, state2 = C_SIPHASH_NULL; unsigned i, j; c_siphash_init(&state1, key);