1 // SPDX-License-Identifier: BSD-3-Clause
2 /* $OpenBSD: siphash.c,v 1.3 2015/02/20 11:51:03 tedu Exp $ */
5 * Copyright (c) 2013 Andre Oppermann <andre@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior written
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d
35 * are the number of compression rounds and the number of finalization rounds.
36 * A compression round is identical to a finalization round and this round
37 * function is called SipRound. Given a 128-bit key k and a (possibly empty)
38 * byte string m, SipHash-c-d returns a 64-bit value SipHash-c-d(k; m).
40 * Implemented from the paper "SipHash: a fast short-input PRF", 2012.09.18,
41 * by Jean-Philippe Aumasson and Daniel J. Bernstein,
42 * Permanent Document ID b9a943a805fbfc6fde808af9fc0ecdfa
43 * https://131002.net/siphash/siphash.pdf
44 * https://131002.net/siphash/
47 #include <asm/byteorder.h>
48 #include <linux/unaligned.h>
49 #include <linux/bitops.h>
50 #include <linux/string.h>
54 static void SipHash_Rounds(SIPHASH_CTX
*ctx
, int rounds
)
57 ctx
->v
[0] += ctx
->v
[1];
58 ctx
->v
[2] += ctx
->v
[3];
59 ctx
->v
[1] = rol64(ctx
->v
[1], 13);
60 ctx
->v
[3] = rol64(ctx
->v
[3], 16);
62 ctx
->v
[1] ^= ctx
->v
[0];
63 ctx
->v
[3] ^= ctx
->v
[2];
64 ctx
->v
[0] = rol64(ctx
->v
[0], 32);
66 ctx
->v
[2] += ctx
->v
[1];
67 ctx
->v
[0] += ctx
->v
[3];
68 ctx
->v
[1] = rol64(ctx
->v
[1], 17);
69 ctx
->v
[3] = rol64(ctx
->v
[3], 21);
71 ctx
->v
[1] ^= ctx
->v
[2];
72 ctx
->v
[3] ^= ctx
->v
[0];
73 ctx
->v
[2] = rol64(ctx
->v
[2], 32);
77 static void SipHash_CRounds(SIPHASH_CTX
*ctx
, const void *ptr
, int rounds
)
79 u64 m
= get_unaligned_le64(ptr
);
82 SipHash_Rounds(ctx
, rounds
);
86 void SipHash_Init(SIPHASH_CTX
*ctx
, const SIPHASH_KEY
*key
)
90 k0
= le64_to_cpu(key
->k0
);
91 k1
= le64_to_cpu(key
->k1
);
93 ctx
->v
[0] = 0x736f6d6570736575ULL
^ k0
;
94 ctx
->v
[1] = 0x646f72616e646f6dULL
^ k1
;
95 ctx
->v
[2] = 0x6c7967656e657261ULL
^ k0
;
96 ctx
->v
[3] = 0x7465646279746573ULL
^ k1
;
98 memset(ctx
->buf
, 0, sizeof(ctx
->buf
));
102 void SipHash_Update(SIPHASH_CTX
*ctx
, int rc
, int rf
,
103 const void *src
, size_t len
)
111 used
= ctx
->bytes
% sizeof(ctx
->buf
);
115 left
= sizeof(ctx
->buf
) - used
;
118 memcpy(&ctx
->buf
[used
], ptr
, left
);
119 SipHash_CRounds(ctx
, ctx
->buf
, rc
);
123 memcpy(&ctx
->buf
[used
], ptr
, len
);
128 while (len
>= sizeof(ctx
->buf
)) {
129 SipHash_CRounds(ctx
, ptr
, rc
);
130 len
-= sizeof(ctx
->buf
);
131 ptr
+= sizeof(ctx
->buf
);
135 memcpy(&ctx
->buf
[used
], ptr
, len
);
138 void SipHash_Final(void *dst
, SIPHASH_CTX
*ctx
, int rc
, int rf
)
142 r
= SipHash_End(ctx
, rc
, rf
);
144 *((__le64
*) dst
) = cpu_to_le64(r
);
147 u64
SipHash_End(SIPHASH_CTX
*ctx
, int rc
, int rf
)
152 used
= ctx
->bytes
% sizeof(ctx
->buf
);
153 left
= sizeof(ctx
->buf
) - used
;
154 memset(&ctx
->buf
[used
], 0, left
- 1);
155 ctx
->buf
[7] = ctx
->bytes
;
157 SipHash_CRounds(ctx
, ctx
->buf
, rc
);
159 SipHash_Rounds(ctx
, rf
);
161 r
= (ctx
->v
[0] ^ ctx
->v
[1]) ^ (ctx
->v
[2] ^ ctx
->v
[3]);
162 memset(ctx
, 0, sizeof(*ctx
));
166 u64
SipHash(const SIPHASH_KEY
*key
, int rc
, int rf
, const void *src
, size_t len
)
170 SipHash_Init(&ctx
, key
);
171 SipHash_Update(&ctx
, rc
, rf
, src
, len
);
172 return SipHash_End(&ctx
, rc
, rf
);