~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/siphash.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
  2 /* Copyright (C) 2016-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  3  *
  4  * SipHash: a fast short-input PRF
  5  * https://131002.net/siphash/
  6  *
  7  * This implementation is specifically for SipHash2-4 for a secure PRF
  8  * and HalfSipHash1-3/SipHash1-3 for an insecure PRF only suitable for
  9  * hashtables.
 10  */
 11 
 12 #include <linux/siphash.h>
 13 #include <asm/unaligned.h>
 14 
 15 #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
 16 #include <linux/dcache.h>
 17 #include <asm/word-at-a-time.h>
 18 #endif
 19 
 20 #define SIPROUND SIPHASH_PERMUTATION(v0, v1, v2, v3)
 21 
 22 #define PREAMBLE(len) \
 23         u64 v0 = SIPHASH_CONST_0; \
 24         u64 v1 = SIPHASH_CONST_1; \
 25         u64 v2 = SIPHASH_CONST_2; \
 26         u64 v3 = SIPHASH_CONST_3; \
 27         u64 b = ((u64)(len)) << 56; \
 28         v3 ^= key->key[1]; \
 29         v2 ^= key->key[0]; \
 30         v1 ^= key->key[1]; \
 31         v0 ^= key->key[0];
 32 
 33 #define POSTAMBLE \
 34         v3 ^= b; \
 35         SIPROUND; \
 36         SIPROUND; \
 37         v0 ^= b; \
 38         v2 ^= 0xff; \
 39         SIPROUND; \
 40         SIPROUND; \
 41         SIPROUND; \
 42         SIPROUND; \
 43         return (v0 ^ v1) ^ (v2 ^ v3);
 44 
 45 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 46 u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key)
 47 {
 48         const u8 *end = data + len - (len % sizeof(u64));
 49         const u8 left = len & (sizeof(u64) - 1);
 50         u64 m;
 51         PREAMBLE(len)
 52         for (; data != end; data += sizeof(u64)) {
 53                 m = le64_to_cpup(data);
 54                 v3 ^= m;
 55                 SIPROUND;
 56                 SIPROUND;
 57                 v0 ^= m;
 58         }
 59 #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
 60         if (left)
 61                 b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
 62                                                   bytemask_from_count(left)));
 63 #else
 64         switch (left) {
 65         case 7: b |= ((u64)end[6]) << 48; fallthrough;
 66         case 6: b |= ((u64)end[5]) << 40; fallthrough;
 67         case 5: b |= ((u64)end[4]) << 32; fallthrough;
 68         case 4: b |= le32_to_cpup(data); break;
 69         case 3: b |= ((u64)end[2]) << 16; fallthrough;
 70         case 2: b |= le16_to_cpup(data); break;
 71         case 1: b |= end[0];
 72         }
 73 #endif
 74         POSTAMBLE
 75 }
 76 EXPORT_SYMBOL(__siphash_aligned);
 77 #endif
 78 
 79 u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key)
 80 {
 81         const u8 *end = data + len - (len % sizeof(u64));
 82         const u8 left = len & (sizeof(u64) - 1);
 83         u64 m;
 84         PREAMBLE(len)
 85         for (; data != end; data += sizeof(u64)) {
 86                 m = get_unaligned_le64(data);
 87                 v3 ^= m;
 88                 SIPROUND;
 89                 SIPROUND;
 90                 v0 ^= m;
 91         }
 92 #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
 93         if (left)
 94                 b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
 95                                                   bytemask_from_count(left)));
 96 #else
 97         switch (left) {
 98         case 7: b |= ((u64)end[6]) << 48; fallthrough;
 99         case 6: b |= ((u64)end[5]) << 40; fallthrough;
100         case 5: b |= ((u64)end[4]) << 32; fallthrough;
101         case 4: b |= get_unaligned_le32(end); break;
102         case 3: b |= ((u64)end[2]) << 16; fallthrough;
103         case 2: b |= get_unaligned_le16(end); break;
104         case 1: b |= end[0];
105         }
106 #endif
107         POSTAMBLE
108 }
109 EXPORT_SYMBOL(__siphash_unaligned);
110 
111 /**
112  * siphash_1u64 - compute 64-bit siphash PRF value of a u64
113  * @first: first u64
114  * @key: the siphash key
115  */
116 u64 siphash_1u64(const u64 first, const siphash_key_t *key)
117 {
118         PREAMBLE(8)
119         v3 ^= first;
120         SIPROUND;
121         SIPROUND;
122         v0 ^= first;
123         POSTAMBLE
124 }
125 EXPORT_SYMBOL(siphash_1u64);
126 
127 /**
128  * siphash_2u64 - compute 64-bit siphash PRF value of 2 u64
129  * @first: first u64
130  * @second: second u64
131  * @key: the siphash key
132  */
133 u64 siphash_2u64(const u64 first, const u64 second, const siphash_key_t *key)
134 {
135         PREAMBLE(16)
136         v3 ^= first;
137         SIPROUND;
138         SIPROUND;
139         v0 ^= first;
140         v3 ^= second;
141         SIPROUND;
142         SIPROUND;
143         v0 ^= second;
144         POSTAMBLE
145 }
146 EXPORT_SYMBOL(siphash_2u64);
147 
148 /**
149  * siphash_3u64 - compute 64-bit siphash PRF value of 3 u64
150  * @first: first u64
151  * @second: second u64
152  * @third: third u64
153  * @key: the siphash key
154  */
155 u64 siphash_3u64(const u64 first, const u64 second, const u64 third,
156                  const siphash_key_t *key)
157 {
158         PREAMBLE(24)
159         v3 ^= first;
160         SIPROUND;
161         SIPROUND;
162         v0 ^= first;
163         v3 ^= second;
164         SIPROUND;
165         SIPROUND;
166         v0 ^= second;
167         v3 ^= third;
168         SIPROUND;
169         SIPROUND;
170         v0 ^= third;
171         POSTAMBLE
172 }
173 EXPORT_SYMBOL(siphash_3u64);
174 
175 /**
176  * siphash_4u64 - compute 64-bit siphash PRF value of 4 u64
177  * @first: first u64
178  * @second: second u64
179  * @third: third u64
180  * @forth: forth u64
181  * @key: the siphash key
182  */
183 u64 siphash_4u64(const u64 first, const u64 second, const u64 third,
184                  const u64 forth, const siphash_key_t *key)
185 {
186         PREAMBLE(32)
187         v3 ^= first;
188         SIPROUND;
189         SIPROUND;
190         v0 ^= first;
191         v3 ^= second;
192         SIPROUND;
193         SIPROUND;
194         v0 ^= second;
195         v3 ^= third;
196         SIPROUND;
197         SIPROUND;
198         v0 ^= third;
199         v3 ^= forth;
200         SIPROUND;
201         SIPROUND;
202         v0 ^= forth;
203         POSTAMBLE
204 }
205 EXPORT_SYMBOL(siphash_4u64);
206 
207 u64 siphash_1u32(const u32 first, const siphash_key_t *key)
208 {
209         PREAMBLE(4)
210         b |= first;
211         POSTAMBLE
212 }
213 EXPORT_SYMBOL(siphash_1u32);
214 
215 u64 siphash_3u32(const u32 first, const u32 second, const u32 third,
216                  const siphash_key_t *key)
217 {
218         u64 combined = (u64)second << 32 | first;
219         PREAMBLE(12)
220         v3 ^= combined;
221         SIPROUND;
222         SIPROUND;
223         v0 ^= combined;
224         b |= third;
225         POSTAMBLE
226 }
227 EXPORT_SYMBOL(siphash_3u32);
228 
229 #if BITS_PER_LONG == 64
230 /* Note that on 64-bit, we make HalfSipHash1-3 actually be SipHash1-3, for
231  * performance reasons. On 32-bit, below, we actually implement HalfSipHash1-3.
232  */
233 
234 #define HSIPROUND SIPROUND
235 #define HPREAMBLE(len) PREAMBLE(len)
236 #define HPOSTAMBLE \
237         v3 ^= b; \
238         HSIPROUND; \
239         v0 ^= b; \
240         v2 ^= 0xff; \
241         HSIPROUND; \
242         HSIPROUND; \
243         HSIPROUND; \
244         return (v0 ^ v1) ^ (v2 ^ v3);
245 
246 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
247 u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
248 {
249         const u8 *end = data + len - (len % sizeof(u64));
250         const u8 left = len & (sizeof(u64) - 1);
251         u64 m;
252         HPREAMBLE(len)
253         for (; data != end; data += sizeof(u64)) {
254                 m = le64_to_cpup(data);
255                 v3 ^= m;
256                 HSIPROUND;
257                 v0 ^= m;
258         }
259 #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
260         if (left)
261                 b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
262                                                   bytemask_from_count(left)));
263 #else
264         switch (left) {
265         case 7: b |= ((u64)end[6]) << 48; fallthrough;
266         case 6: b |= ((u64)end[5]) << 40; fallthrough;
267         case 5: b |= ((u64)end[4]) << 32; fallthrough;
268         case 4: b |= le32_to_cpup(data); break;
269         case 3: b |= ((u64)end[2]) << 16; fallthrough;
270         case 2: b |= le16_to_cpup(data); break;
271         case 1: b |= end[0];
272         }
273 #endif
274         HPOSTAMBLE
275 }
276 EXPORT_SYMBOL(__hsiphash_aligned);
277 #endif
278 
279 u32 __hsiphash_unaligned(const void *data, size_t len,
280                          const hsiphash_key_t *key)
281 {
282         const u8 *end = data + len - (len % sizeof(u64));
283         const u8 left = len & (sizeof(u64) - 1);
284         u64 m;
285         HPREAMBLE(len)
286         for (; data != end; data += sizeof(u64)) {
287                 m = get_unaligned_le64(data);
288                 v3 ^= m;
289                 HSIPROUND;
290                 v0 ^= m;
291         }
292 #if defined(CONFIG_DCACHE_WORD_ACCESS) && BITS_PER_LONG == 64
293         if (left)
294                 b |= le64_to_cpu((__force __le64)(load_unaligned_zeropad(data) &
295                                                   bytemask_from_count(left)));
296 #else
297         switch (left) {
298         case 7: b |= ((u64)end[6]) << 48; fallthrough;
299         case 6: b |= ((u64)end[5]) << 40; fallthrough;
300         case 5: b |= ((u64)end[4]) << 32; fallthrough;
301         case 4: b |= get_unaligned_le32(end); break;
302         case 3: b |= ((u64)end[2]) << 16; fallthrough;
303         case 2: b |= get_unaligned_le16(end); break;
304         case 1: b |= end[0];
305         }
306 #endif
307         HPOSTAMBLE
308 }
309 EXPORT_SYMBOL(__hsiphash_unaligned);
310 
311 /**
312  * hsiphash_1u32 - compute 64-bit hsiphash PRF value of a u32
313  * @first: first u32
314  * @key: the hsiphash key
315  */
316 u32 hsiphash_1u32(const u32 first, const hsiphash_key_t *key)
317 {
318         HPREAMBLE(4)
319         b |= first;
320         HPOSTAMBLE
321 }
322 EXPORT_SYMBOL(hsiphash_1u32);
323 
324 /**
325  * hsiphash_2u32 - compute 32-bit hsiphash PRF value of 2 u32
326  * @first: first u32
327  * @second: second u32
328  * @key: the hsiphash key
329  */
330 u32 hsiphash_2u32(const u32 first, const u32 second, const hsiphash_key_t *key)
331 {
332         u64 combined = (u64)second << 32 | first;
333         HPREAMBLE(8)
334         v3 ^= combined;
335         HSIPROUND;
336         v0 ^= combined;
337         HPOSTAMBLE
338 }
339 EXPORT_SYMBOL(hsiphash_2u32);
340 
341 /**
342  * hsiphash_3u32 - compute 32-bit hsiphash PRF value of 3 u32
343  * @first: first u32
344  * @second: second u32
345  * @third: third u32
346  * @key: the hsiphash key
347  */
348 u32 hsiphash_3u32(const u32 first, const u32 second, const u32 third,
349                   const hsiphash_key_t *key)
350 {
351         u64 combined = (u64)second << 32 | first;
352         HPREAMBLE(12)
353         v3 ^= combined;
354         HSIPROUND;
355         v0 ^= combined;
356         b |= third;
357         HPOSTAMBLE
358 }
359 EXPORT_SYMBOL(hsiphash_3u32);
360 
361 /**
362  * hsiphash_4u32 - compute 32-bit hsiphash PRF value of 4 u32
363  * @first: first u32
364  * @second: second u32
365  * @third: third u32
366  * @forth: forth u32
367  * @key: the hsiphash key
368  */
369 u32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
370                   const u32 forth, const hsiphash_key_t *key)
371 {
372         u64 combined = (u64)second << 32 | first;
373         HPREAMBLE(16)
374         v3 ^= combined;
375         HSIPROUND;
376         v0 ^= combined;
377         combined = (u64)forth << 32 | third;
378         v3 ^= combined;
379         HSIPROUND;
380         v0 ^= combined;
381         HPOSTAMBLE
382 }
383 EXPORT_SYMBOL(hsiphash_4u32);
384 #else
385 #define HSIPROUND HSIPHASH_PERMUTATION(v0, v1, v2, v3)
386 
387 #define HPREAMBLE(len) \
388         u32 v0 = HSIPHASH_CONST_0; \
389         u32 v1 = HSIPHASH_CONST_1; \
390         u32 v2 = HSIPHASH_CONST_2; \
391         u32 v3 = HSIPHASH_CONST_3; \
392         u32 b = ((u32)(len)) << 24; \
393         v3 ^= key->key[1]; \
394         v2 ^= key->key[0]; \
395         v1 ^= key->key[1]; \
396         v0 ^= key->key[0];
397 
398 #define HPOSTAMBLE \
399         v3 ^= b; \
400         HSIPROUND; \
401         v0 ^= b; \
402         v2 ^= 0xff; \
403         HSIPROUND; \
404         HSIPROUND; \
405         HSIPROUND; \
406         return v1 ^ v3;
407 
408 #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
409 u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key)
410 {
411         const u8 *end = data + len - (len % sizeof(u32));
412         const u8 left = len & (sizeof(u32) - 1);
413         u32 m;
414         HPREAMBLE(len)
415         for (; data != end; data += sizeof(u32)) {
416                 m = le32_to_cpup(data);
417                 v3 ^= m;
418                 HSIPROUND;
419                 v0 ^= m;
420         }
421         switch (left) {
422         case 3: b |= ((u32)end[2]) << 16; fallthrough;
423         case 2: b |= le16_to_cpup(data); break;
424         case 1: b |= end[0];
425         }
426         HPOSTAMBLE
427 }
428 EXPORT_SYMBOL(__hsiphash_aligned);
429 #endif
430 
431 u32 __hsiphash_unaligned(const void *data, size_t len,
432                          const hsiphash_key_t *key)
433 {
434         const u8 *end = data + len - (len % sizeof(u32));
435         const u8 left = len & (sizeof(u32) - 1);
436         u32 m;
437         HPREAMBLE(len)
438         for (; data != end; data += sizeof(u32)) {
439                 m = get_unaligned_le32(data);
440                 v3 ^= m;
441                 HSIPROUND;
442                 v0 ^= m;
443         }
444         switch (left) {
445         case 3: b |= ((u32)end[2]) << 16; fallthrough;
446         case 2: b |= get_unaligned_le16(end); break;
447         case 1: b |= end[0];
448         }
449         HPOSTAMBLE
450 }
451 EXPORT_SYMBOL(__hsiphash_unaligned);
452 
453 /**
454  * hsiphash_1u32 - compute 32-bit hsiphash PRF value of a u32
455  * @first: first u32
456  * @key: the hsiphash key
457  */
458 u32 hsiphash_1u32(const u32 first, const hsiphash_key_t *key)
459 {
460         HPREAMBLE(4)
461         v3 ^= first;
462         HSIPROUND;
463         v0 ^= first;
464         HPOSTAMBLE
465 }
466 EXPORT_SYMBOL(hsiphash_1u32);
467 
468 /**
469  * hsiphash_2u32 - compute 32-bit hsiphash PRF value of 2 u32
470  * @first: first u32
471  * @second: second u32
472  * @key: the hsiphash key
473  */
474 u32 hsiphash_2u32(const u32 first, const u32 second, const hsiphash_key_t *key)
475 {
476         HPREAMBLE(8)
477         v3 ^= first;
478         HSIPROUND;
479         v0 ^= first;
480         v3 ^= second;
481         HSIPROUND;
482         v0 ^= second;
483         HPOSTAMBLE
484 }
485 EXPORT_SYMBOL(hsiphash_2u32);
486 
487 /**
488  * hsiphash_3u32 - compute 32-bit hsiphash PRF value of 3 u32
489  * @first: first u32
490  * @second: second u32
491  * @third: third u32
492  * @key: the hsiphash key
493  */
494 u32 hsiphash_3u32(const u32 first, const u32 second, const u32 third,
495                   const hsiphash_key_t *key)
496 {
497         HPREAMBLE(12)
498         v3 ^= first;
499         HSIPROUND;
500         v0 ^= first;
501         v3 ^= second;
502         HSIPROUND;
503         v0 ^= second;
504         v3 ^= third;
505         HSIPROUND;
506         v0 ^= third;
507         HPOSTAMBLE
508 }
509 EXPORT_SYMBOL(hsiphash_3u32);
510 
511 /**
512  * hsiphash_4u32 - compute 32-bit hsiphash PRF value of 4 u32
513  * @first: first u32
514  * @second: second u32
515  * @third: third u32
516  * @forth: forth u32
517  * @key: the hsiphash key
518  */
519 u32 hsiphash_4u32(const u32 first, const u32 second, const u32 third,
520                   const u32 forth, const hsiphash_key_t *key)
521 {
522         HPREAMBLE(16)
523         v3 ^= first;
524         HSIPROUND;
525         v0 ^= first;
526         v3 ^= second;
527         HSIPROUND;
528         v0 ^= second;
529         v3 ^= third;
530         HSIPROUND;
531         v0 ^= third;
532         v3 ^= forth;
533         HSIPROUND;
534         v0 ^= forth;
535         HPOSTAMBLE
536 }
537 EXPORT_SYMBOL(hsiphash_4u32);
538 #endif
539 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php