[PATCH] ARM optimized SHA1 implementation
[git.git] / arm / sha1.c
diff --git a/arm/sha1.c b/arm/sha1.c
new file mode 100644 (file)
index 0000000..11b1a04
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SHA-1 implementation optimized for ARM
+ *
+ * Copyright:   (C) 2005 by Nicolas Pitre <nico@cam.org>
+ * Created:     September 17, 2005
+ */
+
+#include <string.h>
+#include "sha1.h"
+
+extern void sha_transform(uint32_t *hash, const unsigned char *data, uint32_t *W);
+
+void SHA1_Init(SHA_CTX *c)
+{
+       c->len = 0;
+       c->hash[0] = 0x67452301;
+       c->hash[1] = 0xefcdab89;
+       c->hash[2] = 0x98badcfe;
+       c->hash[3] = 0x10325476;
+       c->hash[4] = 0xc3d2e1f0;
+}
+
+void SHA1_Update(SHA_CTX *c, const void *p, unsigned long n)
+{
+       uint32_t workspace[80];
+       unsigned int partial;
+       unsigned long done;
+
+       partial = c->len & 0x3f;
+       c->len += n;
+       if ((partial + n) >= 64) {
+               if (partial) {
+                       done = 64 - partial;
+                       memcpy(c->buffer + partial, p, done);
+                       sha_transform(c->hash, c->buffer, workspace);
+                       partial = 0;
+               } else
+                       done = 0;
+               while (n >= done + 64) {
+                       sha_transform(c->hash, p + done, workspace);
+                       done += 64;
+               }
+       } else
+               done = 0;
+       if (n - done)
+               memcpy(c->buffer + partial, p + done, n - done);
+}
+
+void SHA1_Final(unsigned char *hash, SHA_CTX *c)
+{
+       uint64_t bitlen;
+       uint32_t bitlen_hi, bitlen_lo; 
+       unsigned int i, offset, padlen;
+       unsigned char bits[8];
+       static const unsigned char padding[64] = { 0x80, };
+
+       bitlen = c->len << 3;
+       offset = c->len & 0x3f;
+       padlen = ((offset < 56) ? 56 : (64 + 56)) - offset;
+       SHA1_Update(c, padding, padlen);
+
+       bitlen_hi = bitlen >> 32;
+       bitlen_lo = bitlen & 0xffffffff;
+       bits[0] = bitlen_hi >> 24;
+       bits[1] = bitlen_hi >> 16;
+       bits[2] = bitlen_hi >> 8;
+       bits[3] = bitlen_hi;
+       bits[4] = bitlen_lo >> 24;
+       bits[5] = bitlen_lo >> 16;
+       bits[6] = bitlen_lo >> 8;
+       bits[7] = bitlen_lo;
+       SHA1_Update(c, bits, 8); 
+
+       for (i = 0; i < 5; i++) {
+               uint32_t v = c->hash[i];
+               hash[0] = v >> 24;
+               hash[1] = v >> 16;
+               hash[2] = v >> 8;
+               hash[3] = v;
+               hash += 4;
+       }
+}