43#ifdef PV_USE_PCLMUL_DETECT
60static inline u128 u128_from_bytes(
const uint8_t *bytes);
65static inline void u128_to_bytes(u128, uint8_t *bytes_out);
71static inline void pv_xor_y(
polyval_t *, u128 v);
89#define bswap64(x) __builtin_bswap64(x)
90#define bswap32(x) __builtin_bswap32(x)
94bswap64(uint64_t value)
97 ((value & 0xFF00000000000000) >> 56) |
98 ((value & 0x00FF000000000000) >> 40) |
99 ((value & 0x0000FF0000000000) >> 24) |
100 ((value & 0x000000FF00000000) >> 8) |
101 ((value & 0x00000000FF000000) << 8) |
102 ((value & 0x0000000000FF0000) << 24) |
103 ((value & 0x000000000000FF00) << 40) |
104 ((value & 0x00000000000000FF) << 56);
107static inline uint32_t
108bswap32(uint32_t value)
111 ((value & 0xFF000000) >> 24) |
112 ((value & 0x00FF0000) >> 8) |
113 ((value & 0x0000FF00) << 8) |
114 ((value & 0x000000FF) << 24);
119#ifdef WORDS_BIGENDIAN
120#define convert_byte_order64(x) bswap64(x)
121#define convert_byte_order32(x) bswap32(x)
123#define convert_byte_order64(x) (x)
124#define convert_byte_order32(x) (x)
127#if defined PV_USE_PCLMUL_UNCONDITIONAL
128#define PCLMUL_MEMBER(v) (v)
131#elif defined PV_USE_PCLMUL_DETECT
132#define PCLMUL_MEMBER(v) (v).u128x1
133#define CTMUL64_MEMBER(v) (v).u64x2
135#define PV_USE_CTMUL64
137#elif defined PV_USE_CTMUL64
138#define CTMUL64_MEMBER(v) (v)
142#include "ext/polyval/pclmul.c"
144DISABLE_GCC_WARNING(
"-Waggregate-return")
146u128_from_bytes_pclmul(const uint8_t *bytes)
149 PCLMUL_MEMBER(r) = _mm_loadu_si128((
const __m128i*)bytes);
152ENABLE_GCC_WARNING(
"-Waggregate-return")
155u128_to_bytes_pclmul(u128 val, uint8_t *bytes_out)
157 _mm_storeu_si128((__m128i*)bytes_out, PCLMUL_MEMBER(val));
162 PCLMUL_MEMBER(pv->
y) = _mm_xor_si128(PCLMUL_MEMBER(pv->
y),
167#if defined(PV_USE_CTMUL64)
168#include "ext/polyval/ctmul64.c"
170DISABLE_GCC_WARNING(
"-Waggregate-return")
172u128_from_bytes_ctmul64(const uint8_t *bytes)
175 memcpy(&CTMUL64_MEMBER(r).lo, bytes, 8);
176 memcpy(&CTMUL64_MEMBER(r).hi, bytes + 8, 8);
177 CTMUL64_MEMBER(r).lo = convert_byte_order64(CTMUL64_MEMBER(r).lo);
178 CTMUL64_MEMBER(r).hi = convert_byte_order64(CTMUL64_MEMBER(r).hi);
181ENABLE_GCC_WARNING(
"-Waggregate-return")
184u128_to_bytes_ctmul64(u128 val, uint8_t *bytes_out)
186 uint64_t lo = convert_byte_order64(CTMUL64_MEMBER(val).lo);
187 uint64_t hi = convert_byte_order64(CTMUL64_MEMBER(val).hi);
188 memcpy(bytes_out, &lo, 8);
189 memcpy(bytes_out + 8, &hi, 8);
194 CTMUL64_MEMBER(pv->
y).lo ^= CTMUL64_MEMBER(val).lo;
195 CTMUL64_MEMBER(pv->
y).hi ^= CTMUL64_MEMBER(val).hi;
199#if defined(PV_USE_CTMUL)
200#include "ext/polyval/ctmul.c"
202DISABLE_GCC_WARNING(
"-Waggregate-return")
204u128_from_bytes_ctmul(const uint8_t *bytes)
207 memcpy(&r.v, bytes, 16);
208 for (
int i = 0; i < 4; ++i) {
209 r.v[i] = convert_byte_order32(r.v[i]);
213ENABLE_GCC_WARNING(
"-Waggregate-return")
216u128_to_bytes_ctmul(u128 val, uint8_t *bytes_out)
219 for (
int i = 0; i < 4; ++i) {
220 v[i] = convert_byte_order32(val.v[i]);
222 memcpy(bytes_out, v, 16);
227 for (
int i = 0; i < 4; ++i) {
228 pv->
y.v[i] ^= val.v[i];
234static inline void add_multiple_none(
polyval_t *pv,
235 const uint8_t *input,
242static inline void expand_key_none(
const polyval_t *inp,
252#define BLOCK_STRIDE_NONE 0xffff
254DISABLE_GCC_WARNING(
"-Waggregate-return")
255#define PV_DECLARE(prefix, \
262 expanded_key_tp, expand_fn, add_multiple_fn) \
264 prefix ## polyval_key_init(polyval_key_t *pvk, const uint8_t *key) \
266 pvk->h = u128_from_bytes(key); \
269 prefix ## polyval_init(polyval_t *pv, const uint8_t *key) \
271 polyval_key_init(&pv->key, key); \
272 memset(&pv->y, 0, sizeof(u128)); \
275 prefix ## polyval_init_from_key(polyval_t *pv, const polyval_key_t *key) \
277 memcpy(&pv->key, key, sizeof(polyval_key_t)); \
278 memset(&pv->y, 0, sizeof(u128)); \
281 prefix ## polyval_add_block(polyval_t *pv, const uint8_t *block) \
283 u128 b = u128_from_bytes(block); \
288 prefix ## polyval_add_zpad(polyval_t *pv, const uint8_t *data, size_t n) \
291 if ((block_stride != BLOCK_STRIDE_NONE) \
292 && n >= (block_stride) * 16) { \
293 expanded_key_tp expanded_key; \
294 expand_fn(pv, &expanded_key); \
295 while (n >= (block_stride) * 16) { \
296 add_multiple_fn(pv, data, &expanded_key); \
297 n -= block_stride*16; \
298 data += block_stride * 16; \
302 polyval_add_block(pv, data); \
308 memset(&block, 0, sizeof(block)); \
309 memcpy(block, data, n); \
310 polyval_add_block(pv, block); \
314 prefix ## polyval_get_tag(const polyval_t *pv, uint8_t *tag_out) \
316 u128_to_bytes(pv->y, tag_out); \
319 prefix ## polyval_reset(polyval_t *pv) \
321 memset(&pv->y, 0, sizeof(u128)); \
323ENABLE_GCC_WARNING(
"-Waggregate-return")
325#ifdef PV_USE_PCLMUL_DETECT
330static bool use_pclmul =
false;
334DISABLE_GCC_WARNING(
"-Waggregate-return")
335PV_DECLARE(pclmul_, static,
336 u128_from_bytes_pclmul,
337 u128_to_bytes_pclmul,
343 pv_add_multiple_pclmul)
345PV_DECLARE(ctmul64_, static,
346 u128_from_bytes_ctmul64,
347 u128_to_bytes_ctmul64,
354ENABLE_GCC_WARNING("-Waggregate-return")
360 pclmul_polyval_key_init(pv, key);
362 ctmul64_polyval_key_init(pv, key);
368 pclmul_polyval_init(pv, key);
370 ctmul64_polyval_init(pv, key);
376 pclmul_polyval_init_from_key(pv, key);
378 ctmul64_polyval_init_from_key(pv, key);
384 pclmul_polyval_add_block(pv, block);
386 ctmul64_polyval_add_block(pv, block);
392 pclmul_polyval_add_zpad(pv, data, n);
394 ctmul64_polyval_add_zpad(pv, data, n);
400 pclmul_polyval_get_tag(pv, tag_out);
402 ctmul64_polyval_get_tag(pv, tag_out);
408 pclmul_polyval_reset(pv);
410 ctmul64_polyval_reset(pv);
413#elif defined(PV_USE_PCLMUL)
415 u128_from_bytes_pclmul,
416 u128_to_bytes_pclmul,
422 pv_add_multiple_pclmul)
423#elif defined(PV_USE_CTMUL64)
425 u128_from_bytes_ctmul64,
426 u128_to_bytes_ctmul64,
434#elif defined(PV_USE_CTMUL)
435DISABLE_GCC_WARNING(
"-Waggregate-return")
436PV_DECLARE(, , u128_from_bytes_ctmul,
444ENABLE_GCC_WARNING("-Waggregate-return")
447#ifdef PV_USE_PCLMUL_DETECT
449polyval_detect_implementation(
void)
451 unsigned int eax, ebx, ecx, edx;
453 if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
454 if (0 != (ecx & bit_PCLMUL)) {
461polyval_detect_implementation(
void)
466#ifdef POLYVAL_USE_EXPANDED_KEYS
468#ifdef PV_USE_PCLMUL_DETECT
469#define SHOULD_EXPAND() (use_pclmul)
471#define SHOULD_EXPAND() (1)
475polyvalx_init(polyvalx_t *pvx,
const uint8_t *key)
478 if (SHOULD_EXPAND()) {
479 expand_key_pclmul(&pvx->pv, &pvx->expanded);
483polyvalx_init_from_key(polyvalx_t *pvx,
const polyval_key_t *key)
486 if (SHOULD_EXPAND()) {
487 expand_key_pclmul(&pvx->pv, &pvx->expanded);
491polyvalx_add_block(polyvalx_t *pvx,
const uint8_t *block)
496polyvalx_add_zpad(polyvalx_t *pvx,
const uint8_t *data,
size_t n)
498 if (SHOULD_EXPAND() && n >= PV_BLOCK_STRIDE * 16) {
499 while (n > PV_BLOCK_STRIDE * 16) {
500 pv_add_multiple_pclmul(&pvx->pv, data, &pvx->expanded);
501 data += PV_BLOCK_STRIDE * 16;
502 n -= PV_BLOCK_STRIDE * 16;
512 memset(&block, 0,
sizeof(block));
513 memcpy(block, data, n);
518polyvalx_get_tag(
const polyvalx_t *pvx, uint8_t *tag_out)
522void polyvalx_reset(polyvalx_t *pvx)
535 { 0x25, 0x62, 0x93, 0x47, 0x58, 0x92, 0x42, 0x76,
536 0x1d, 0x31, 0xf8, 0x26, 0xba, 0x4b, 0x75, 0x7b };
538 { 0x4f, 0x4f, 0x95, 0x66, 0x8c, 0x83, 0xdf, 0xb6,
539 0x40, 0x17, 0x62, 0xbb, 0x2d, 0x01, 0xa2, 0x62 };
540 uint8_t block2[16] = {
541 0xd1, 0xa2, 0x4d, 0xdd, 0x27, 0x21, 0xd0, 0x06,
542 0xbb, 0xe4, 0x5f, 0x20, 0xd3, 0xc9, 0xf3, 0x62 };
543 uint8_t expect_result[16] = {
544 0xf7, 0xa3, 0xb4, 0x7b, 0x84, 0x61, 0x19, 0xfa,
545 0xe5, 0xb7, 0x86, 0x6c, 0xf5, 0xe5, 0xb7, 0x7e };
553 if (!memcmp(expect_result, tag, 16)) {
Utility macros to handle different features and behavior in different compilers.
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_key_init(polyval_key_t *, const uint8_t *key)
int main(int argc, char *argv[])