summaryrefslogtreecommitdiffstats
path: root/utils/sbinfo/sha1.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sbinfo/sha1.c')
-rw-r--r--utils/sbinfo/sha1.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/utils/sbinfo/sha1.c b/utils/sbinfo/sha1.c
new file mode 100644
index 0000000000..99657fb14a
--- /dev/null
+++ b/utils/sbinfo/sha1.c
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+/* Based on http://en.wikipedia.org/wiki/SHA-1 */
+#include "crypto.h"
+
+static uint32_t rot_left(uint32_t val, int rot)
+{
+ return (val << rot) | (val >> (32 - rot));
+}
+
+static inline void byte_swapxx(byte *ptr, int size)
+{
+ for(int i = 0; i < size / 2; i++)
+ {
+ byte c = ptr[i];
+ ptr[i] = ptr[size - i - 1];
+ ptr[size - i - 1] = c;
+ }
+}
+
+static void byte_swap32(uint32_t *v)
+{
+ byte_swapxx((byte *)v, 4);
+}
+
+void sha_1_init(struct sha_1_params_t *params)
+{
+ params->hash[0] = 0x67452301;
+ params->hash[1] = 0xEFCDAB89;
+ params->hash[2] = 0x98BADCFE;
+ params->hash[3] = 0x10325476;
+ params->hash[4] = 0xC3D2E1F0;
+ params->buffer_nr_bits = 0;
+}
+
+void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size)
+{
+ int buffer_nr_bytes = (params->buffer_nr_bits / 8) % 64;
+ params->buffer_nr_bits += 8 * size;
+ int pos = 0;
+ if(buffer_nr_bytes + size >= 64)
+ {
+ pos = 64 - buffer_nr_bytes;
+ memcpy((byte *)(params->w) + buffer_nr_bytes, buffer, 64 - buffer_nr_bytes);
+ sha_1_block(params, params->hash, (byte *)params->w);
+ for(; pos + 64 <= size; pos += 64)
+ sha_1_block(params, params->hash, buffer + pos);
+ buffer_nr_bytes = 0;
+ }
+ memcpy((byte *)(params->w) + buffer_nr_bytes, buffer + pos, size - pos);
+}
+
+void sha_1_finish(struct sha_1_params_t *params)
+{
+ /* length (in bits) in big endian BEFORE preprocessing */
+ byte length_big_endian[8];
+ memcpy(length_big_endian, &params->buffer_nr_bits, 8);
+ byte_swapxx(length_big_endian, 8);
+ /* append '1' and then '0's to the message to get 448 bit length for the last block */
+ byte b = 0x80;
+ sha_1_update(params, &b, 1);
+ b = 0;
+ while((params->buffer_nr_bits % 512) != 448)
+ sha_1_update(params, &b, 1);
+ /* append length */
+ sha_1_update(params, length_big_endian, 8);
+ /* go back to big endian */
+ for(int i = 0; i < 5; i++)
+ byte_swap32(&params->hash[i]);
+}
+
+void sha_1_output(struct sha_1_params_t *params, byte *out)
+{
+ memcpy(out, params->hash, 20);
+}
+
+void sha_1_block(struct sha_1_params_t *params, uint32_t cur_hash[5], byte *data)
+{
+ uint32_t a, b, c, d, e;
+ a = cur_hash[0];
+ b = cur_hash[1];
+ c = cur_hash[2];
+ d = cur_hash[3];
+ e = cur_hash[4];
+
+ #define w params->w
+
+ memcpy(w, data, 64);
+ for(int i = 0; i < 16; i++)
+ byte_swap32(&w[i]);
+
+ for(int i = 16; i <= 79; i++)
+ w[i] = rot_left(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
+
+ for(int i = 0; i<= 79; i++)
+ {
+ uint32_t f, k;
+ if(i <= 19)
+ {
+ f = (b & c) | ((~b) & d);
+ k = 0x5A827999;
+ }
+ else if(i <= 39)
+ {
+ f = b ^ c ^ d;
+ k = 0x6ED9EBA1;
+ }
+ else if(i <= 59)
+ {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8F1BBCDC;
+ }
+ else
+ {
+ f = b ^ c ^ d;
+ k = 0xCA62C1D6;
+ }
+ uint32_t temp = rot_left(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = rot_left(b, 30);
+ b = a;
+ a = temp;
+ }
+ #undef w
+
+ cur_hash[0] += a;
+ cur_hash[1] += b;
+ cur_hash[2] += c;
+ cur_hash[3] += d;
+ cur_hash[4] += e;
+}