1 /* $OpenBSD: siphash.c,v 1.8 2019/01/20 03:53:47 bcook Exp $ */
4 * Copyright (c) 2013 Andre Oppermann <andre@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote
16 * products derived from this software without specific prior written
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d
34 * are the number of compression rounds and the number of finalization rounds.
35 * A compression round is identical to a finalization round and this round
36 * function is called SipRound. Given a 128-bit key k and a (possibly empty)
37 * byte string m, SipHash-c-d returns a 64-bit value SipHash-c-d(k; m).
39 * Implemented from the paper "SipHash: a fast short-input PRF", 2012.09.18,
40 * by Jean-Philippe Aumasson and Daniel J. Bernstein,
41 * Permanent Document ID b9a943a805fbfc6fde808af9fc0ecdfa
42 * https://131002.net/siphash/siphash.pdf
43 * https://131002.net/siphash/
50 #include "got_compat.h"
52 static void SipHash_CRounds(SIPHASH_CTX
*, int);
53 static void SipHash_Rounds(SIPHASH_CTX
*, int);
56 SipHash_Init(SIPHASH_CTX
*ctx
, const SIPHASH_KEY
*key
)
60 k0
= le64toh(key
->k0
);
61 k1
= le64toh(key
->k1
);
63 ctx
->v
[0] = 0x736f6d6570736575ULL
^ k0
;
64 ctx
->v
[1] = 0x646f72616e646f6dULL
^ k1
;
65 ctx
->v
[2] = 0x6c7967656e657261ULL
^ k0
;
66 ctx
->v
[3] = 0x7465646279746573ULL
^ k1
;
68 memset(ctx
->buf
, 0, sizeof(ctx
->buf
));
73 SipHash_Update(SIPHASH_CTX
*ctx
, int rc
, int rf
, const void *src
, size_t len
)
75 const uint8_t *ptr
= src
;
81 used
= ctx
->bytes
% sizeof(ctx
->buf
);
85 left
= sizeof(ctx
->buf
) - used
;
88 memcpy(&ctx
->buf
[used
], ptr
, left
);
89 SipHash_CRounds(ctx
, rc
);
93 memcpy(&ctx
->buf
[used
], ptr
, len
);
98 while (len
>= sizeof(ctx
->buf
)) {
99 memcpy(ctx
->buf
, ptr
, sizeof(ctx
->buf
));
100 SipHash_CRounds(ctx
, rc
);
101 len
-= sizeof(ctx
->buf
);
102 ptr
+= sizeof(ctx
->buf
);
106 memcpy(ctx
->buf
, ptr
, len
);
110 SipHash_Final(void *dst
, SIPHASH_CTX
*ctx
, int rc
, int rf
)
114 r
= htole64(SipHash_End(ctx
, rc
, rf
));
115 memcpy(dst
, &r
, sizeof r
);
119 SipHash_End(SIPHASH_CTX
*ctx
, int rc
, int rf
)
124 used
= ctx
->bytes
% sizeof(ctx
->buf
);
125 left
= sizeof(ctx
->buf
) - used
;
126 memset(&ctx
->buf
[used
], 0, left
- 1);
127 ctx
->buf
[7] = ctx
->bytes
;
129 SipHash_CRounds(ctx
, rc
);
131 SipHash_Rounds(ctx
, rf
);
133 r
= (ctx
->v
[0] ^ ctx
->v
[1]) ^ (ctx
->v
[2] ^ ctx
->v
[3]);
136 memset_s(ctx
, sizeof(*ctx
), 0, sizeof(*ctx
));
137 #elif defined(__NetBSD__)
138 explicit_memset(ctx
, sizeof(*ctx
), 0);
140 explicit_bzero(ctx
, sizeof(*ctx
));
146 SipHash(const SIPHASH_KEY
*key
, int rc
, int rf
, const void *src
, size_t len
)
150 SipHash_Init(&ctx
, key
);
151 SipHash_Update(&ctx
, rc
, rf
, src
, len
);
152 return (SipHash_End(&ctx
, rc
, rf
));
155 #define SIP_ROTL(x, b) ((x) << (b)) | ( (x) >> (64 - (b)))
158 SipHash_Rounds(SIPHASH_CTX
*ctx
, int rounds
)
161 ctx
->v
[0] += ctx
->v
[1];
162 ctx
->v
[2] += ctx
->v
[3];
163 ctx
->v
[1] = SIP_ROTL(ctx
->v
[1], 13);
164 ctx
->v
[3] = SIP_ROTL(ctx
->v
[3], 16);
166 ctx
->v
[1] ^= ctx
->v
[0];
167 ctx
->v
[3] ^= ctx
->v
[2];
168 ctx
->v
[0] = SIP_ROTL(ctx
->v
[0], 32);
170 ctx
->v
[2] += ctx
->v
[1];
171 ctx
->v
[0] += ctx
->v
[3];
172 ctx
->v
[1] = SIP_ROTL(ctx
->v
[1], 17);
173 ctx
->v
[3] = SIP_ROTL(ctx
->v
[3], 21);
175 ctx
->v
[1] ^= ctx
->v
[2];
176 ctx
->v
[3] ^= ctx
->v
[0];
177 ctx
->v
[2] = SIP_ROTL(ctx
->v
[2], 32);
182 SipHash_CRounds(SIPHASH_CTX
*ctx
, int rounds
)
184 uint64_t m
= le64toh(*(uint64_t *)ctx
->buf
);
187 SipHash_Rounds(ctx
, rounds
);