ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
SHA512.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 "SHA512.h"
24 #include "Crypto.h"
25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
27 #include "utility/ProgMemUtil.h"
28 #include <string.h>
29 
43 {
44  reset();
45 }
46 
52 {
53  clean(state);
54 }
55 
56 size_t SHA512::hashSize() const
57 {
58  return 64;
59 }
60 
61 size_t SHA512::blockSize() const
62 {
63  return 128;
64 }
65 
67 {
68  static uint64_t const hashStart[8] PROGMEM = {
69  0x6A09E667F3BCC908ULL, 0xBB67AE8584CAA73BULL, 0x3C6EF372FE94F82BULL,
70  0xA54FF53A5F1D36F1ULL, 0x510E527FADE682D1ULL, 0x9B05688C2B3E6C1FULL,
71  0x1F83D9ABFB41BD6BULL, 0x5BE0CD19137E2179ULL
72  };
73  memcpy_P(state.h, hashStart, sizeof(hashStart));
74  state.chunkSize = 0;
75  state.lengthLow = 0;
76  state.lengthHigh = 0;
77 }
78 
79 void SHA512::update(const void *data, size_t len)
80 {
81  // Update the total length in bits, not bytes.
82  uint64_t temp = state.lengthLow;
83  state.lengthLow += (((uint64_t)len) << 3);
84  state.lengthHigh += (((uint64_t)len) >> 61);
85  if (state.lengthLow < temp)
86  ++state.lengthHigh;
87 
88  // Break the input up into 1024-bit chunks and process each in turn.
89  const uint8_t *d = (const uint8_t *)data;
90  while (len > 0) {
91  uint8_t size = 128 - state.chunkSize;
92  if (size > len)
93  size = len;
94  memcpy(((uint8_t *)state.w) + state.chunkSize, d, size);
95  state.chunkSize += size;
96  len -= size;
97  d += size;
98  if (state.chunkSize == 128) {
99  processChunk();
100  state.chunkSize = 0;
101  }
102  }
103 }
104 
105 void SHA512::finalize(void *hash, size_t len)
106 {
107  // Pad the last chunk. We may need two padding chunks if there
108  // isn't enough room in the first for the padding and length.
109  uint8_t *wbytes = (uint8_t *)state.w;
110  if (state.chunkSize <= (128 - 17)) {
111  wbytes[state.chunkSize] = 0x80;
112  memset(wbytes + state.chunkSize + 1, 0x00, 128 - 16 - (state.chunkSize + 1));
113  state.w[14] = htobe64(state.lengthHigh);
114  state.w[15] = htobe64(state.lengthLow);
115  processChunk();
116  } else {
117  wbytes[state.chunkSize] = 0x80;
118  memset(wbytes + state.chunkSize + 1, 0x00, 128 - (state.chunkSize + 1));
119  processChunk();
120  memset(wbytes, 0x00, 128 - 16);
121  state.w[14] = htobe64(state.lengthHigh);
122  state.w[15] = htobe64(state.lengthLow);
123  processChunk();
124  }
125 
126  // Convert the result into big endian and return it.
127  for (uint8_t posn = 0; posn < 8; ++posn)
128  state.w[posn] = htobe64(state.h[posn]);
129 
130  // Copy the hash to the caller's return buffer.
131  if (len > 64)
132  len = 64;
133  memcpy(hash, state.w, len);
134 }
135 
137 {
138  clean(state);
139  reset();
140 }
141 
147 void SHA512::processChunk()
148 {
149  // Round constants for SHA-512.
150  static uint64_t const k[80] PROGMEM = {
151  0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, 0xB5C0FBCFEC4D3B2FULL,
152  0xE9B5DBA58189DBBCULL, 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
153  0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL, 0xD807AA98A3030242ULL,
154  0x12835B0145706FBEULL, 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
155  0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, 0x9BDC06A725C71235ULL,
156  0xC19BF174CF692694ULL, 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
157  0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL, 0x2DE92C6F592B0275ULL,
158  0x4A7484AA6EA6E483ULL, 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
159  0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, 0xB00327C898FB213FULL,
160  0xBF597FC7BEEF0EE4ULL, 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
161  0x06CA6351E003826FULL, 0x142929670A0E6E70ULL, 0x27B70A8546D22FFCULL,
162  0x2E1B21385C26C926ULL, 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
163  0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, 0x81C2C92E47EDAEE6ULL,
164  0x92722C851482353BULL, 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
165  0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL, 0xD192E819D6EF5218ULL,
166  0xD69906245565A910ULL, 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
167  0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, 0x2748774CDF8EEB99ULL,
168  0x34B0BCB5E19B48A8ULL, 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
169  0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL, 0x748F82EE5DEFB2FCULL,
170  0x78A5636F43172F60ULL, 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
171  0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, 0xBEF9A3F7B2C67915ULL,
172  0xC67178F2E372532BULL, 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
173  0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL, 0x06F067AA72176FBAULL,
174  0x0A637DC5A2C898A6ULL, 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
175  0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, 0x3C9EBE0A15C9BEBCULL,
176  0x431D67C49C100D4CULL, 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
177  0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL
178  };
179 
180  // Convert the first 16 words from big endian to host byte order.
181  uint8_t index;
182  for (index = 0; index < 16; ++index)
183  state.w[index] = be64toh(state.w[index]);
184 
185  // Initialise working variables to the current hash value.
186  uint64_t a = state.h[0];
187  uint64_t b = state.h[1];
188  uint64_t c = state.h[2];
189  uint64_t d = state.h[3];
190  uint64_t e = state.h[4];
191  uint64_t f = state.h[5];
192  uint64_t g = state.h[6];
193  uint64_t h = state.h[7];
194 
195  // Perform the first 16 rounds of the compression function main loop.
196  uint64_t temp1, temp2;
197  for (index = 0; index < 16; ++index) {
198  temp1 = h + pgm_read_qword(k + index) + state.w[index] +
199  (rightRotate14_64(e) ^ rightRotate18_64(e) ^
200  rightRotate41_64(e)) + ((e & f) ^ ((~e) & g));
201  temp2 = (rightRotate28_64(a) ^ rightRotate34_64(a) ^
202  rightRotate39_64(a)) + ((a & b) ^ (a & c) ^ (b & c));
203  h = g;
204  g = f;
205  f = e;
206  e = d + temp1;
207  d = c;
208  c = b;
209  b = a;
210  a = temp1 + temp2;
211  }
212 
213  // Perform the 64 remaining rounds. We expand the first 16 words to
214  // 80 in-place in the "w" array. This saves 512 bytes of memory
215  // that would have otherwise need to be allocated to the "w" array.
216  for (; index < 80; ++index) {
217  // Expand the next word.
218  temp1 = state.w[(index - 15) & 0x0F];
219  temp2 = state.w[(index - 2) & 0x0F];
220  temp1 = state.w[index & 0x0F] =
221  state.w[(index - 16) & 0x0F] + state.w[(index - 7) & 0x0F] +
222  (rightRotate1_64(temp1) ^ rightRotate8_64(temp1) ^
223  (temp1 >> 7)) +
224  (rightRotate19_64(temp2) ^ rightRotate61_64(temp2) ^
225  (temp2 >> 6));
226 
227  // Perform the round.
228  temp1 = h + pgm_read_qword(k + index) + temp1 +
229  (rightRotate14_64(e) ^ rightRotate18_64(e) ^
230  rightRotate41_64(e)) + ((e & f) ^ ((~e) & g));
231  temp2 = (rightRotate28_64(a) ^ rightRotate34_64(a) ^
232  rightRotate39_64(a)) + ((a & b) ^ (a & c) ^ (b & c));
233  h = g;
234  g = f;
235  f = e;
236  e = d + temp1;
237  d = c;
238  c = b;
239  b = a;
240  a = temp1 + temp2;
241  }
242 
243  // Add the compressed chunk to the current hash value.
244  state.h[0] += a;
245  state.h[1] += b;
246  state.h[2] += c;
247  state.h[3] += d;
248  state.h[4] += e;
249  state.h[5] += f;
250  state.h[6] += g;
251  state.h[7] += h;
252 
253  // Attempt to clean up the stack.
254  a = b = c = d = e = f = g = h = temp1 = temp2 = 0;
255 }
size_t hashSize() const
Size of the hash result from finalize().
Definition: SHA512.cpp:56
size_t blockSize() const
Size of the internal block used by the hash algorithm.
Definition: SHA512.cpp:61
virtual ~SHA512()
Destroys this SHA-512 hash object after clearing sensitive information.
Definition: SHA512.cpp:51
void clear()
Clears the hash state, removing all sensitive data, and then resets the hash ready for a new hashing ...
Definition: SHA512.cpp:136
void reset()
Resets the hash ready for a new hashing process.
Definition: SHA512.cpp:66
void update(const void *data, size_t len)
Updates the hash with more data.
Definition: SHA512.cpp:79
void finalize(void *hash, size_t len)
Finalizes the hashing process and returns the hash.
Definition: SHA512.cpp:105
SHA512()
Constructs a SHA-512 hash object.
Definition: SHA512.cpp:42