ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
GHASH.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "GHASH.h"
24 #include "Crypto.h"
25 #include "utility/EndianUtil.h"
26 #include <string.h>
27 
48 {
49  state.posn = 0;
50 }
51 
56 {
57  clean(state);
58 }
59 
67 void GHASH::reset(const void *key)
68 {
69  // Copy the key into H and convert from big endian to host order.
70  memcpy(state.H, key, 16);
71 #if defined(CRYPTO_LITTLE_ENDIAN)
72  state.H[0] = be32toh(state.H[0]);
73  state.H[1] = be32toh(state.H[1]);
74  state.H[2] = be32toh(state.H[2]);
75  state.H[3] = be32toh(state.H[3]);
76 #endif
77 
78  // Reset the hash.
79  memset(state.Y, 0, sizeof(state.Y));
80  state.posn = 0;
81 }
82 
94 void GHASH::update(const void *data, size_t len)
95 {
96  // XOR the input with state.Y in 128-bit chunks and process them.
97  const uint8_t *d = (const uint8_t *)data;
98  while (len > 0) {
99  uint8_t size = 16 - state.posn;
100  if (size > len)
101  size = len;
102  uint8_t *y = ((uint8_t *)state.Y) + state.posn;
103  for (uint8_t i = 0; i < size; ++i)
104  y[i] ^= d[i];
105  state.posn += size;
106  len -= size;
107  d += size;
108  if (state.posn == 16) {
109  processChunk();
110  state.posn = 0;
111  }
112  }
113 }
114 
130 void GHASH::finalize(void *token, size_t len)
131 {
132  // Pad with zeroes to a multiple of 16 bytes.
133  pad();
134 
135  // The token is the current value of Y.
136  if (len > 16)
137  len = 16;
138  memcpy(token, state.Y, len);
139 }
140 
147 {
148  if (state.posn != 0) {
149  // Padding involves XOR'ing the rest of state.Y with zeroes,
150  // which does nothing. Immediately process the next chunk.
151  processChunk();
152  state.posn = 0;
153  }
154 }
155 
160 {
161  clean(state);
162 }
163 
164 void GHASH::processChunk()
165 {
166  uint32_t Z0 = 0; // Z = 0
167  uint32_t Z1 = 0;
168  uint32_t Z2 = 0;
169  uint32_t Z3 = 0;
170  uint32_t V0 = state.H[0]; // V = H
171  uint32_t V1 = state.H[1];
172  uint32_t V2 = state.H[2];
173  uint32_t V3 = state.H[3];
174 
175  // Multiply Z by V for the set bits in Y, starting at the top.
176  // This is a very simple bit by bit version that may not be very
177  // fast but it should be resistant to cache timing attacks.
178  for (uint8_t posn = 0; posn < 16; ++posn) {
179  uint8_t value = ((const uint8_t *)state.Y)[posn];
180  for (uint8_t bit = 0; bit < 8; ++bit, value <<= 1) {
181  // Extract the high bit of "value" and turn it into a mask.
182  uint32_t mask = (~((uint32_t)(value >> 7))) + 1;
183 
184  // XOR V with Z if the bit is 1.
185  Z0 ^= (V0 & mask);
186  Z1 ^= (V1 & mask);
187  Z2 ^= (V2 & mask);
188  Z3 ^= (V3 & mask);
189 
190  // Rotate V right by 1 bit.
191  mask = ((~(V3 & 0x01)) + 1) & 0xE1000000;
192  V3 = (V3 >> 1) | (V2 << 31);
193  V2 = (V2 >> 1) | (V1 << 31);
194  V1 = (V1 >> 1) | (V0 << 31);
195  V0 = (V0 >> 1) ^ mask;
196  }
197  }
198 
199  // We have finished the block so copy Z into Y and byte-swap.
200  state.Y[0] = htobe32(Z0);
201  state.Y[1] = htobe32(Z1);
202  state.Y[2] = htobe32(Z2);
203  state.Y[3] = htobe32(Z3);
204 }
void finalize(void *token, size_t len)
Finalizes the authentication process and returns the token.
Definition: GHASH.cpp:130
void update(const void *data, size_t len)
Updates the message authenticator with more data.
Definition: GHASH.cpp:94
~GHASH()
Destroys this GHASH message authenticator.
Definition: GHASH.cpp:55
void pad()
Pads the input stream with zero bytes to a multiple of 16.
Definition: GHASH.cpp:146
void clear()
Clears the authenticator's state, removing all sensitive data.
Definition: GHASH.cpp:159
GHASH()
Constructs a new GHASH message authenticator.
Definition: GHASH.cpp:47
void reset(const void *key)
Resets the GHASH message authenticator for a new session.
Definition: GHASH.cpp:67