42#ifdef PV_USE_PCLMUL_DETECT
59static inline u128 u128_from_bytes(
const uint8_t *bytes);
64static inline void u128_to_bytes(u128, uint8_t *bytes_out);
70static inline void pv_xor_y(
polyval_t *, u128 v);
86#ifdef WORDS_BIG_ENDIAN
88#define bswap64(x) __builtin_bswap64(x)
89#define bswap32(x) __builtin_bswap32(x)
96 ((value & 0xFF00000000000000) >> 56) |
97 ((value & 0x00FF000000000000) >> 48) |
98 ((value & 0x0000FF0000000000) >> 40) |
99 ((value & 0x000000FF00000000) >> 32) |
100 ((value & 0x00000000FF000000) >> 24) |
101 ((value & 0x0000000000FF0000) >> 16) |
102 ((value & 0x000000000000FF00) >> 8) |
103 ((value & 0x00000000000000FF));
105static inline uint64_t
109 ((value & 0xFF000000) >> 24) |
110 ((value & 0x00FF0000) >> 16) |
111 ((value & 0x0000FF00) >> 8) |
112 ((value & 0x000000FF));
117#ifdef WORDS_BIG_ENDIAN
118#define convert_byte_order64(x) bswap64(x)
119#define convert_byte_order32(x) bswap32(x)
121#define convert_byte_order64(x) (x)
122#define convert_byte_order32(x) (x)
125#if defined PV_USE_PCLMUL_UNCONDITIONAL
126#define PCLMUL_MEMBER(v) (v)
129#elif defined PV_USE_PCLMUL_DETECT
130#define PCLMUL_MEMBER(v) (v).u128x1
131#define CTMUL64_MEMBER(v) (v).u64x2
133#define PV_USE_CTMUL64
135#elif defined PV_USE_CTMUL64
136#define CTMUL64_MEMBER(v) (v)
140#include "ext/polyval/pclmul.c"
143u128_from_bytes_pclmul(
const uint8_t *bytes)
146 PCLMUL_MEMBER(r) = _mm_loadu_si128((
const __m128i*)bytes);
150u128_to_bytes_pclmul(u128 val, uint8_t *bytes_out)
152 _mm_storeu_si128((__m128i*)bytes_out, PCLMUL_MEMBER(val));
157 PCLMUL_MEMBER(pv->
y) = _mm_xor_si128(PCLMUL_MEMBER(pv->
y),
162#if defined(PV_USE_CTMUL64)
163#include "ext/polyval/ctmul64.c"
166u128_from_bytes_ctmul64(
const uint8_t *bytes)
169 memcpy(&CTMUL64_MEMBER(r).lo, bytes, 8);
170 memcpy(&CTMUL64_MEMBER(r).hi, bytes + 8, 8);
171 CTMUL64_MEMBER(r).lo = convert_byte_order64(CTMUL64_MEMBER(r).lo);
172 CTMUL64_MEMBER(r).hi = convert_byte_order64(CTMUL64_MEMBER(r).hi);
176u128_to_bytes_ctmul64(u128 val, uint8_t *bytes_out)
178 uint64_t lo = convert_byte_order64(CTMUL64_MEMBER(val).lo);
179 uint64_t hi = convert_byte_order64(CTMUL64_MEMBER(val).hi);
180 memcpy(bytes_out, &lo, 8);
181 memcpy(bytes_out + 8, &hi, 8);
186 CTMUL64_MEMBER(pv->
y).lo ^= CTMUL64_MEMBER(val).lo;
187 CTMUL64_MEMBER(pv->
y).hi ^= CTMUL64_MEMBER(val).hi;
191#if defined(PV_USE_CTMUL)
192#include "ext/polyval/ctmul.c"
195u128_from_bytes_ctmul(
const uint8_t *bytes)
198 memcpy(&r.v, bytes, 16);
199 for (
int i = 0; i < 4; ++i) {
200 r.v[i] = convert_byte_order32(r.v[i]);
205u128_to_bytes_ctmul(u128 val, uint8_t *bytes_out)
208 for (
int i = 0; i < 4; ++i) {
209 v[i] = convert_byte_order32(val.v[i]);
211 memcpy(bytes_out, v, 16);
216 for (
int i = 0; i < 4; ++i) {
217 pv->
y.v[i] ^= val.v[i];
223static inline void add_multiple_none(
polyval_t *pv,
224 const uint8_t *input,
231static inline void expand_key_none(
const polyval_t *inp,
241#define BLOCK_STRIDE_NONE 0xffff
243#define PV_DECLARE(prefix, \
250 expanded_key_tp, expand_fn, add_multiple_fn) \
252 prefix ## polyval_key_init(polyval_key_t *pvk, const uint8_t *key) \
254 pvk->h = u128_from_bytes(key); \
257 prefix ## polyval_init(polyval_t *pv, const uint8_t *key) \
259 polyval_key_init(&pv->key, key); \
260 memset(&pv->y, 0, sizeof(u128)); \
263 prefix ## polyval_init_from_key(polyval_t *pv, const polyval_key_t *key) \
265 memcpy(&pv->key, key, sizeof(polyval_key_t)); \
266 memset(&pv->y, 0, sizeof(u128)); \
269 prefix ## polyval_add_block(polyval_t *pv, const uint8_t *block) \
271 u128 b = u128_from_bytes(block); \
276 prefix ## polyval_add_zpad(polyval_t *pv, const uint8_t *data, size_t n) \
279 if ((block_stride != BLOCK_STRIDE_NONE) \
280 && n >= (block_stride) * 16) { \
281 expanded_key_tp expanded_key; \
282 expand_fn(pv, &expanded_key); \
283 while (n >= (block_stride) * 16) { \
284 add_multiple_fn(pv, data, &expanded_key); \
285 n -= block_stride*16; \
286 data += block_stride * 16; \
290 polyval_add_block(pv, data); \
296 memset(&block, 0, sizeof(block)); \
297 memcpy(block, data, n); \
298 polyval_add_block(pv, block); \
302 prefix ## polyval_get_tag(const polyval_t *pv, uint8_t *tag_out) \
304 u128_to_bytes(pv->y, tag_out); \
307 prefix ## polyval_reset(polyval_t *pv) \
309 memset(&pv->y, 0, sizeof(u128)); \
312#ifdef PV_USE_PCLMUL_DETECT
317static bool use_pclmul =
false;
321PV_DECLARE(pclmul_,
static,
322 u128_from_bytes_pclmul,
323 u128_to_bytes_pclmul,
329 pv_add_multiple_pclmul)
331PV_DECLARE(ctmul64_,
static,
332 u128_from_bytes_ctmul64,
333 u128_to_bytes_ctmul64,
345 pclmul_polyval_key_init(pv, key);
347 ctmul64_polyval_key_init(pv, key);
353 pclmul_polyval_init(pv, key);
355 ctmul64_polyval_init(pv, key);
361 pclmul_polyval_init_from_key(pv, key);
363 ctmul64_polyval_init_from_key(pv, key);
369 pclmul_polyval_add_block(pv, block);
371 ctmul64_polyval_add_block(pv, block);
377 pclmul_polyval_add_zpad(pv, data, n);
379 ctmul64_polyval_add_zpad(pv, data, n);
385 pclmul_polyval_get_tag(pv, tag_out);
387 ctmul64_polyval_get_tag(pv, tag_out);
393 pclmul_polyval_reset(pv);
395 ctmul64_polyval_reset(pv);
398#elif defined(PV_USE_PCLMUL)
400 u128_from_bytes_pclmul,
401 u128_to_bytes_pclmul,
407 pv_add_multiple_pclmul)
408#elif defined(PV_USE_CTMUL64)
410 u128_from_bytes_ctmul64,
411 u128_to_bytes_ctmul64,
419#elif defined(PV_USE_CTMUL)
420PV_DECLARE(, , u128_from_bytes_ctmul,
430#ifdef PV_USE_PCLMUL_DETECT
434 unsigned int eax, ebx, ecx, edx;
436 if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
437 if (0 != (ecx & bit_PCLMUL)) {
449#ifdef POLYVAL_USE_EXPANDED_KEYS
451#ifdef PV_USE_PCLMUL_DETECT
452#define SHOULD_EXPAND() (use_pclmul)
454#define SHOULD_EXPAND() (1)
458polyvalx_init(polyvalx_t *pvx,
const uint8_t *key)
461 if (SHOULD_EXPAND()) {
462 expand_key_pclmul(&pvx->pv, &pvx->expanded);
466polyvalx_init_from_key(polyvalx_t *pvx,
const polyval_key_t *key)
469 if (SHOULD_EXPAND()) {
470 expand_key_pclmul(&pvx->pv, &pvx->expanded);
474polyvalx_add_block(polyvalx_t *pvx,
const uint8_t *block)
479polyvalx_add_zpad(polyvalx_t *pvx,
const uint8_t *data,
size_t n)
481 if (SHOULD_EXPAND() && n >= PV_BLOCK_STRIDE * 16) {
482 while (n > PV_BLOCK_STRIDE * 16) {
483 pv_add_multiple_pclmul(&pvx->pv, data, &pvx->expanded);
484 data += PV_BLOCK_STRIDE * 16;
485 n -= PV_BLOCK_STRIDE * 16;
495 memset(&block, 0,
sizeof(block));
496 memcpy(block, data, n);
501polyvalx_get_tag(
const polyvalx_t *pvx, uint8_t *tag_out)
505void polyvalx_reset(polyvalx_t *pvx)
518 { 0x25, 0x62, 0x93, 0x47, 0x58, 0x92, 0x42, 0x76,
519 0x1d, 0x31, 0xf8, 0x26, 0xba, 0x4b, 0x75, 0x7b };
521 { 0x4f, 0x4f, 0x95, 0x66, 0x8c, 0x83, 0xdf, 0xb6,
522 0x40, 0x17, 0x62, 0xbb, 0x2d, 0x01, 0xa2, 0x62 };
523 uint8_t block2[16] = {
524 0xd1, 0xa2, 0x4d, 0xdd, 0x27, 0x21, 0xd0, 0x06,
525 0xbb, 0xe4, 0x5f, 0x20, 0xd3, 0xc9, 0xf3, 0x62 };
526 uint8_t expect_result[16] = {
527 0xf7, 0xa3, 0xb4, 0x7b, 0x84, 0x61, 0x19, 0xfa,
528 0xe5, 0xb7, 0x86, 0x6c, 0xf5, 0xe5, 0xb7, 0x7e };
536 if (!memcmp(expect_result, tag, 16)) {
Implementation for polyval universal hash function.
void polyval_reset(polyval_t *)
void polyval_init(polyval_t *, const uint8_t *key)
void polyval_add_zpad(polyval_t *, const uint8_t *data, size_t n)
void polyval_add_block(polyval_t *, const uint8_t *block)
void polyval_get_tag(const polyval_t *, uint8_t *tag_out)
void polyval_init_from_key(polyval_t *, const polyval_key_t *key)
void polyval_detect_implementation(void)
void polyval_key_init(polyval_key_t *, const uint8_t *key)
int main(int argc, char *argv[])