XRootD
XrdOucSHA3.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O u c S H A 3 . c c */
4 /* */
5 /* The MIT License (MIT) */
6 /* */
7 /* Copyright (c) 2015 Markku-Juhani O. Saarinen */
8 /* Contact: 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi> */
9 /* Reprository: https://github.com/mjosaarinen/tiny_sha3.git */
10 /* Original: tiny_sha3/sha3.c */
11 /* */
12 /* Revised 07-Aug-15 to match with official release of FIPS PUB 202 "SHA3" */
13 /* Revised 03-Sep-15 for portability + OpenSSL - style API */
14 /* */
15 /* Permission is hereby granted, free of charge, to any person obtaining a */
16 /* copy of this software and associated documentation files (the "Software"), */
17 /* to deal in the Software without restriction, including without limitation */
18 /* the rights to use, copy, modify, merge, publish, distribute, sublicense, */
19 /* and/or sell copies of the Software, and to permit persons to whom the */
20 /* Software is furnished to do so, subject to the following conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be included */
23 /* in all copies or substantial portions of the Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */
26 /* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */
27 /* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL */
28 /* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */
29 /* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
30 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER */
31 /* DEALINGS IN THE SOFTWARE. */
32 /******************************************************************************/
33 
34 #include "XrdOuc/XrdOucSHA3.hh"
35 
36 /******************************************************************************/
37 /* S H A 3 D e f i n e s */
38 /******************************************************************************/
39 
40 #ifndef KECCAKF_ROUNDS
41 #define KECCAKF_ROUNDS 24
42 #endif
43 
44 #ifndef ROTL64
45 #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
46 #endif
47 
48 /******************************************************************************/
49 /* Private: s h a 3 _ k e c c a k f */
50 /******************************************************************************/
51 
52 // update the state with given number of rounds
53 
54 void XrdOucSHA3::sha3_keccakf(uint64_t st[25])
55 {
56  // constants
57  const uint64_t keccakf_rndc[24] = {
58  0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
59  0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
60  0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
61  0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
62  0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
63  0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
64  0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
65  0x8000000000008080, 0x0000000080000001, 0x8000000080008008
66  };
67  const int keccakf_rotc[24] = {
68  1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
69  27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
70  };
71  const int keccakf_piln[24] = {
72  10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
73  15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
74  };
75 
76  // variables
77  int i, j, r;
78  uint64_t t, bc[5];
79 
80 #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
81  uint8_t *v;
82 
83  // endianess conversion. this is redundant on little-endian targets
84  for (i = 0; i < 25; i++) {
85  v = (uint8_t *) &st[i];
86  st[i] = ((uint64_t) v[0]) | (((uint64_t) v[1]) << 8) |
87  (((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) |
88  (((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) |
89  (((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56);
90  }
91 #endif
92 
93  // actual iteration
94  for (r = 0; r < KECCAKF_ROUNDS; r++) {
95 
96  // Theta
97  for (i = 0; i < 5; i++)
98  bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
99 
100  for (i = 0; i < 5; i++) {
101  t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
102  for (j = 0; j < 25; j += 5)
103  st[j + i] ^= t;
104  }
105 
106  // Rho Pi
107  t = st[1];
108  for (i = 0; i < 24; i++) {
109  j = keccakf_piln[i];
110  bc[0] = st[j];
111  st[j] = ROTL64(t, keccakf_rotc[i]);
112  t = bc[0];
113  }
114 
115  // Chi
116  for (j = 0; j < 25; j += 5) {
117  for (i = 0; i < 5; i++)
118  bc[i] = st[j + i];
119  for (i = 0; i < 5; i++)
120  st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
121  }
122 
123  // Iota
124  st[0] ^= keccakf_rndc[r];
125  }
126 
127 #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
128  // endianess conversion. this is redundant on little-endian targets
129  for (i = 0; i < 25; i++) {
130  v = (uint8_t *) &st[i];
131  t = st[i];
132  v[0] = t & 0xFF;
133  v[1] = (t >> 8) & 0xFF;
134  v[2] = (t >> 16) & 0xFF;
135  v[3] = (t >> 24) & 0xFF;
136  v[4] = (t >> 32) & 0xFF;
137  v[5] = (t >> 40) & 0xFF;
138  v[6] = (t >> 48) & 0xFF;
139  v[7] = (t >> 56) & 0xFF;
140  }
141 #endif
142 }
143 
144 /******************************************************************************/
145 /* C a l c */
146 /******************************************************************************/
147 
148 // compute a SHA-3 hash (md) of given byte length from "in"
149 
150 void *XrdOucSHA3::Calc(const void *in, size_t inlen, void *md,
151  XrdOucSHA3::MDLen mdlen)
152 {
153  sha3_ctx_t sha3;
154 
155  Init(&sha3, mdlen);
156  Update(&sha3, in, inlen);
157  Final(&sha3, md);
158 
159  return md;
160 }
161 
162 /******************************************************************************/
163 /* I n i t */
164 /******************************************************************************/
165 
166 // Initialize the context for SHA3
167 
169 {
170  int i;
171 
172  for (i = 0; i < 25; i++)
173  c->st.q[i] = 0;
174  c->mdlen = (int)mdlen;
175  c->rsiz = 200 - 2 * (int)mdlen;
176  c->pt = 0;
177  c->xof= 1;
178 }
179 
180 /******************************************************************************/
181 /* U p d a t e */
182 /******************************************************************************/
183 
184 // update state with more data
185 
186 void XrdOucSHA3::Update(XrdOucSHA3::sha3_ctx_t *c, const void *data, size_t len)
187 {
188  size_t i;
189  int j;
190 
191  j = c->pt;
192  for (i = 0; i < len; i++) {
193  c->st.b[j++] ^= ((const uint8_t *) data)[i];
194  if (j >= c->rsiz) {
195  sha3_keccakf(c->st.q);
196  j = 0;
197  }
198  }
199  c->pt = j;
200 }
201 
202 /******************************************************************************/
203 /* F i n a l */
204 /******************************************************************************/
205 
206 // finalize and output a hash
207 
209 {
210  int i;
211 
212  c->st.b[c->pt] ^= 0x06;
213  c->st.b[c->rsiz - 1] ^= 0x80;
214  sha3_keccakf(c->st.q);
215 
216  for (i = 0; i < c->mdlen; i++) {
217  ((uint8_t *) md)[i] = c->st.b[i];
218  }
219 }
220 
221 /******************************************************************************/
222 /* Private: s h a k e _ x o f */
223 /******************************************************************************/
224 
225 // SHAKE128 and SHAKE256 extensible-output functionality
226 
227 void XrdOucSHA3::shake_xof(XrdOucSHA3::sha3_ctx_t *c)
228 {
229  c->st.b[c->pt] ^= 0x1F;
230  c->st.b[c->rsiz - 1] ^= 0x80;
231  sha3_keccakf(c->st.q);
232  c->pt = 0;
233 }
234 
235 /******************************************************************************/
236 /* S H A K E _ O u t */
237 /******************************************************************************/
238 
239 void XrdOucSHA3::SHAKE_Out(XrdOucSHA3::sha3_ctx_t *c, void *out, size_t len)
240 {
241  size_t i;
242  int j;
243 
244  if (c->xof)
245  {shake_xof(c);
246  c->xof = 0;
247  }
248 
249  j = c->pt;
250  for (i = 0; i < len; i++) {
251  if (j >= c->rsiz) {
252  sha3_keccakf(c->st.q);
253  j = 0;
254  }
255  ((uint8_t *) out)[i] = c->st.b[j++];
256  }
257  c->pt = j;
258 }
#define KECCAKF_ROUNDS
Definition: XrdOucSHA3.cc:41
#define ROTL64(x, y)
Definition: XrdOucSHA3.cc:45
union XrdOucSHA3::sha3_ctx_t::@120 st
static void Update(sha3_ctx_t *c, const void *data, size_t len)
Definition: XrdOucSHA3.cc:186
int xof
these don't overflow
Definition: XrdOucSHA3.hh:49
MDLen
SHA3 digest lengths (bits to bytes).
Definition: XrdOucSHA3.hh:56
static void * Calc(const void *in, size_t inlen, void *md, MDLen mdlen)
Definition: XrdOucSHA3.cc:150
static void SHAKE_Out(sha3_ctx_t *c, void *out, size_t len)
Definition: XrdOucSHA3.cc:239
static void Init(sha3_ctx_t *c, MDLen mdlen)
Definition: XrdOucSHA3.cc:168
static void Final(sha3_ctx_t *c, void *md)
Definition: XrdOucSHA3.cc:208
SHA3 state context used by all methods (OpenSSL - like interface)
Definition: XrdOucSHA3.hh:44