Remove some dead code
[openssl.git] / crypto / siphash / siphash.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 /* Based on https://131002.net/siphash C reference implementation */
11 /*
12    SipHash reference C implementation
13
14    Copyright (c) 2012-2016 Jean-Philippe Aumasson
15    <jeanphilippe.aumasson@gmail.com>
16    Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
17
18    To the extent possible under law, the author(s) have dedicated all copyright
19    and related and neighboring rights to this software to the public domain
20    worldwide. This software is distributed without any warranty.
21
22    You should have received a copy of the CC0 Public Domain Dedication along
23    with
24    this software. If not, see
25    <http://creativecommons.org/publicdomain/zero/1.0/>.
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <openssl/crypto.h>
31
32 #include "internal/siphash.h"
33 #include "siphash_local.h"
34
35 /* default: SipHash-2-4 */
36 #define SIPHASH_C_ROUNDS 2
37 #define SIPHASH_D_ROUNDS 4
38
39 #define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
40
41 #define U32TO8_LE(p, v)                                                        \
42     (p)[0] = (uint8_t)((v));                                                   \
43     (p)[1] = (uint8_t)((v) >> 8);                                              \
44     (p)[2] = (uint8_t)((v) >> 16);                                             \
45     (p)[3] = (uint8_t)((v) >> 24);
46
47 #define U64TO8_LE(p, v)                                                        \
48     U32TO8_LE((p), (uint32_t)((v)));                                           \
49     U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
50
51 #define U8TO64_LE(p)                                                           \
52     (((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) |                        \
53      ((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) |                 \
54      ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) |                 \
55      ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
56
57 #define SIPROUND                                                               \
58     do {                                                                       \
59         v0 += v1;                                                              \
60         v1 = ROTL(v1, 13);                                                     \
61         v1 ^= v0;                                                              \
62         v0 = ROTL(v0, 32);                                                     \
63         v2 += v3;                                                              \
64         v3 = ROTL(v3, 16);                                                     \
65         v3 ^= v2;                                                              \
66         v0 += v3;                                                              \
67         v3 = ROTL(v3, 21);                                                     \
68         v3 ^= v0;                                                              \
69         v2 += v1;                                                              \
70         v1 = ROTL(v1, 17);                                                     \
71         v1 ^= v2;                                                              \
72         v2 = ROTL(v2, 32);                                                     \
73     } while (0)
74
75 size_t SipHash_ctx_size(void)
76 {
77     return sizeof(SIPHASH);
78 }
79
80 size_t SipHash_hash_size(SIPHASH *ctx)
81 {
82     return ctx->hash_size;
83 }
84
85 /* hash_size = crounds = drounds = 0 means SipHash24 with 16-byte output */
86 int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int hash_size, int crounds, int drounds)
87 {
88     uint64_t k0 = U8TO64_LE(k);
89     uint64_t k1 = U8TO64_LE(k + 8);
90
91     if (hash_size == 0)
92         hash_size = SIPHASH_MAX_DIGEST_SIZE;
93     else if (hash_size != SIPHASH_MIN_DIGEST_SIZE &&
94              hash_size != SIPHASH_MAX_DIGEST_SIZE)
95         return 0;
96
97     if (drounds == 0)
98         drounds = SIPHASH_D_ROUNDS;
99     if (crounds == 0)
100         crounds = SIPHASH_C_ROUNDS;
101
102     ctx->crounds = crounds;
103     ctx->drounds = drounds;
104     ctx->hash_size = hash_size;
105
106     ctx->len = 0;
107     ctx->total_inlen = 0;
108
109     ctx->v0 = 0x736f6d6570736575ULL ^ k0;
110     ctx->v1 = 0x646f72616e646f6dULL ^ k1;
111     ctx->v2 = 0x6c7967656e657261ULL ^ k0;
112     ctx->v3 = 0x7465646279746573ULL ^ k1;
113
114     if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
115         ctx->v1 ^= 0xee;
116
117     return 1;
118 }
119
120 void SipHash_Update(SIPHASH *ctx, const unsigned char *in, size_t inlen)
121 {
122     uint64_t m;
123     const uint8_t *end;
124     int left;
125     int i;
126     uint64_t v0 = ctx->v0;
127     uint64_t v1 = ctx->v1;
128     uint64_t v2 = ctx->v2;
129     uint64_t v3 = ctx->v3;
130
131     ctx->total_inlen += inlen;
132
133     if (ctx->len) {
134         /* deal with leavings */
135         size_t available = SIPHASH_BLOCK_SIZE - ctx->len;
136
137         /* not enough to fill leavings */
138         if (inlen < available) {
139             memcpy(&ctx->leavings[ctx->len], in, inlen);
140             ctx->len += inlen;
141             return;
142         }
143
144         /* copy data into leavings and reduce input */
145         memcpy(&ctx->leavings[ctx->len], in, available);
146         inlen -= available;
147         in += available;
148
149         /* process leavings */
150         m = U8TO64_LE(ctx->leavings);
151         v3 ^= m;
152         for (i = 0; i < ctx->crounds; ++i)
153             SIPROUND;
154         v0 ^= m;
155     }
156     left = inlen & (SIPHASH_BLOCK_SIZE-1); /* gets put into leavings */
157     end = in + inlen - left;
158
159     for (; in != end; in += 8) {
160         m = U8TO64_LE(in);
161         v3 ^= m;
162         for (i = 0; i < ctx->crounds; ++i)
163             SIPROUND;
164         v0 ^= m;
165     }
166
167     /* save leavings and other ctx */
168     if (left)
169         memcpy(ctx->leavings, end, left);
170     ctx->len = left;
171
172     ctx->v0 = v0;
173     ctx->v1 = v1;
174     ctx->v2 = v2;
175     ctx->v3 = v3;
176 }
177
178 int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen)
179 {
180     /* finalize hash */
181     int i;
182     uint64_t b = ctx->total_inlen << 56;
183     uint64_t v0 = ctx->v0;
184     uint64_t v1 = ctx->v1;
185     uint64_t v2 = ctx->v2;
186     uint64_t v3 = ctx->v3;
187
188     if (outlen != (size_t)ctx->hash_size)
189         return 0;
190
191     switch (ctx->len) {
192     case 7:
193         b |= ((uint64_t)ctx->leavings[6]) << 48;
194         /* fall thru */
195     case 6:
196         b |= ((uint64_t)ctx->leavings[5]) << 40;
197         /* fall thru */
198     case 5:
199         b |= ((uint64_t)ctx->leavings[4]) << 32;
200         /* fall thru */
201     case 4:
202         b |= ((uint64_t)ctx->leavings[3]) << 24;
203         /* fall thru */
204     case 3:
205         b |= ((uint64_t)ctx->leavings[2]) << 16;
206         /* fall thru */
207     case 2:
208         b |= ((uint64_t)ctx->leavings[1]) <<  8;
209         /* fall thru */
210     case 1:
211         b |= ((uint64_t)ctx->leavings[0]);
212     case 0:
213         break;
214     }
215
216     v3 ^= b;
217     for (i = 0; i < ctx->crounds; ++i)
218         SIPROUND;
219     v0 ^= b;
220     if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
221         v2 ^= 0xee;
222     else
223         v2 ^= 0xff;
224     for (i = 0; i < ctx->drounds; ++i)
225         SIPROUND;
226     b = v0 ^ v1 ^ v2  ^ v3;
227     U64TO8_LE(out, b);
228     if (ctx->hash_size == SIPHASH_MIN_DIGEST_SIZE)
229         return 1;
230     v1 ^= 0xdd;
231     for (i = 0; i < ctx->drounds; ++i)
232         SIPROUND;
233     b = v0 ^ v1 ^ v2  ^ v3;
234     U64TO8_LE(out + 8, b);
235     return 1;
236 }