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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.