Embedded systems coursework 2.

Fork of Crypto_light by Edward Stott

Revision:
0:7a1237bd2d13
Child:
1:14a7cea431aa
diff -r 000000000000 -r 7a1237bd2d13 MD5.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MD5.cpp	Sat Sep 07 23:47:28 2013 +0000
@@ -0,0 +1,231 @@
+#include "MD5.h"
+#include <string.h>
+
+static const uint32_t T[] =
+{
+    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+    0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+    0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+    0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+    0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+static const uint32_t A = 0x67452301;
+static const uint32_t B = 0xefcdab89;
+static const uint32_t C = 0x98badcfe;
+static const uint32_t D = 0x10325476;
+
+static uint32_t F(uint32_t x, uint32_t y, uint32_t z)
+{
+    return (x & y) | ((~x) & z);
+}
+
+static uint32_t G(uint32_t x, uint32_t y, uint32_t z)
+{
+    return (x & z) | (y & (~z));
+}
+
+static uint32_t H(uint32_t x, uint32_t y, uint32_t z)
+{
+    return x ^ y ^ z;
+}
+
+static uint32_t I(uint32_t x, uint32_t y, uint32_t z)
+{
+    return y ^ (x | (~z));
+}
+
+static uint32_t rotLeft(uint32_t w, uint8_t s)
+{
+    return (w << s) | (w >> (32-s));
+}
+
+#define ROUND1(a,b,c,d,k,s,i) \
+    a += F(b,c,d) + x[k] + T[i-1]; \
+    a = rotLeft(a,s);\
+    a += b;
+#define ROUND2(a,b,c,d,k,s,i) \
+    a += G(b,c,d) + x[k] + T[i-1]; \
+    a = rotLeft(a,s);\
+    a += b;
+#define ROUND3(a,b,c,d,k,s,i) \
+    a += H(b,c,d) + x[k] + T[i-1]; \
+    a = rotLeft(a,s);\
+    a += b;
+#define ROUND4(a,b,c,d,k,s,i) \
+    a += I(b,c,d) + x[k] + T[i-1]; \
+    a = rotLeft(a,s);\
+    a += b;
+
+    
+MD5::MD5():
+HashAlgorithm(),
+a(A),
+b(B),
+c(C),
+d(D),
+totalBufferLength(0),
+buffer(),
+bufferLength(0)
+{
+}
+
+uint8_t MD5::outputSize() const
+{
+    return 16;
+}
+
+void MD5::add(uint8_t *in, uint32_t length)
+{
+    if(length < 64-bufferLength)
+    {
+        memcpy(&buffer[bufferLength], in, length);
+        bufferLength += length;
+        totalBufferLength += length;
+        return;
+    }
+    int offset = 64-bufferLength;
+    memcpy(&buffer[bufferLength], in, offset);
+    uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
+    computeRounds(&a, &b, &c, &d, buffer);
+    a += tmpA;
+    b += tmpB;
+    c += tmpC;
+    d += tmpD;
+    while(length-offset > 64)
+    {
+        memcpy(buffer, &in[offset], 64);
+        tmpA = a;
+        tmpB = b;
+        tmpC = c;
+        tmpD = d;
+        computeRounds(&a, &b, &c, &d, buffer);
+        a += tmpA;
+        b += tmpB;
+        c += tmpC;
+        d += tmpD;      
+        offset += 64;
+    }
+    if(offset > length)
+        offset -= 64;
+    bufferLength = length - offset;
+    memcpy(buffer, &in[offset], bufferLength);
+    totalBufferLength += length;
+}
+
+void MD5::computeDigest(uint8_t *digest)
+{
+    uint16_t padding;
+    if(totalBufferLength % 64 < 56)
+        padding = 56 - (totalBufferLength % 64);
+    else
+        padding = 56 + (64 - (totalBufferLength % 64));
+    uint8_t val = 0x80;
+    add(&val, 1);
+    val = 0;
+    for(int i = 0; i < padding-1; ++i)
+        add(&val,1);
+    totalBufferLength -= padding;
+    uint64_t lengthBit = totalBufferLength * 8;
+    uint32_t lengthBitLow = lengthBit;
+    uint32_t lengthBitHigh = lengthBit >> 32;
+    add((uint8_t*)&lengthBitLow,4);
+    add((uint8_t*)&lengthBitHigh,4);
+
+    memcpy(digest, &a, 4);
+    memcpy(&digest[4], &b, 4);
+    memcpy(&digest[8], &c, 4);
+    memcpy(&digest[12], &d, 4);
+    // reset state
+    a = A;
+    b = B;
+    c = C;
+    d = D;
+    totalBufferLength = 0;
+    bufferLength = 0;
+}
+
+void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer)
+{
+    uint32_t a = *a2, b = *b2, c = *c2, d = *d2;
+    uint32_t x[16];
+    for(int j = 0; j < 16; ++j)
+        memcpy(&x[j], &buffer[j*4], 4); 
+        
+    // Round 1
+    ROUND1(a,b,c,d,0,7,1);      ROUND1(d,a,b,c,1,12,2);     ROUND1(c,d,a,b,2,17,3);     ROUND1(b,c,d,a,3,22,4);
+    ROUND1(a,b,c,d,4,7,5);      ROUND1(d,a,b,c,5,12,6);     ROUND1(c,d,a,b,6,17,7);     ROUND1(b,c,d,a,7,22,8);
+    ROUND1(a,b,c,d,8,7,9);      ROUND1(d,a,b,c,9,12,10);    ROUND1(c,d,a,b,10,17,11);   ROUND1(b,c,d,a,11,22,12);
+    ROUND1(a,b,c,d,12,7,13);    ROUND1(d,a,b,c,13,12,14);   ROUND1(c,d,a,b,14,17,15);   ROUND1(b,c,d,a,15,22,16);
+    
+    // Round 2      
+    ROUND2(a,b,c,d,1,5,17);     ROUND2(d,a,b,c,6,9,18);     ROUND2(c,d,a,b,11,14,19);   ROUND2(b,c,d,a,0,20,20);
+    ROUND2(a,b,c,d,5,5,21);     ROUND2(d,a,b,c,10,9,22);    ROUND2(c,d,a,b,15,14,23);   ROUND2(b,c,d,a,4,20,24);
+    ROUND2(a,b,c,d,9,5,25);     ROUND2(d,a,b,c,14,9,26);    ROUND2(c,d,a,b,3,14,27);    ROUND2(b,c,d,a,8,20,28);
+    ROUND2(a,b,c,d,13,5,29);    ROUND2(d,a,b,c,2,9,30);     ROUND2(c,d,a,b,7,14,31);    ROUND2(b,c,d,a,12,20,32);
+    
+    // Round 3      
+    ROUND3(a,b,c,d,5,4,33);     ROUND3(d,a,b,c,8,11,34);    ROUND3(c,d,a,b,11,16,35);   ROUND3(b,c,d,a,14,23,36);
+    ROUND3(a,b,c,d,1,4,37);     ROUND3(d,a,b,c,4,11,38);    ROUND3(c,d,a,b,7,16,39);    ROUND3(b,c,d,a,10,23,40);
+    ROUND3(a,b,c,d,13,4,41);    ROUND3(d,a,b,c,0,11,42);    ROUND3(c,d,a,b,3,16,43);    ROUND3(b,c,d,a,6,23,44);
+    ROUND3(a,b,c,d,9,4,45);     ROUND3(d,a,b,c,12,11,46);   ROUND3(c,d,a,b,15,16,47);   ROUND3(b,c,d,a,2,23,48);
+    
+    // Round 4
+    ROUND4(a,b,c,d,0,6,49);     ROUND4(d,a,b,c,7,10,50);    ROUND4(c,d,a,b,14,15,51);   ROUND4(b,c,d,a,5,21,52);
+    ROUND4(a,b,c,d,12,6,53);    ROUND4(d,a,b,c,3,10,54);    ROUND4(c,d,a,b,10,15,55);   ROUND4(b,c,d,a,1,21,56);
+    ROUND4(a,b,c,d,8,6,57);     ROUND4(d,a,b,c,15,10,58);   ROUND4(c,d,a,b,6,15,59);    ROUND4(b,c,d,a,13,21,60);
+    ROUND4(a,b,c,d,4,6,61);     ROUND4(d,a,b,c,11,10,62);   ROUND4(c,d,a,b,2,15,63);    ROUND4(b,c,d,a,9,21,64);
+
+    *a2 = a;
+    *b2 = b;
+    *c2 = c;
+    *d2 = d;
+}
+
+void MD5::computeDigest(uint8_t *digest, uint8_t *msg, uint32_t length)
+{
+    uint16_t padding;
+    if(length % 64 < 56)
+        padding = 56 - (length % 64);
+    else
+        padding = 56 + (64 - (length % 64));
+    uint32_t totalLength = length + padding + 8;
+    uint8_t *buffer = new uint8_t[totalLength];
+    memcpy(buffer, msg, length);
+    buffer[length] = 0x80;
+    memset(&buffer[length+1], 0, padding-1);
+    uint64_t lengthBit = length * 8;
+    uint32_t lengthBitLow = lengthBit;
+    uint32_t lengthBitHigh = lengthBit >> 32;
+    memcpy(&buffer[length+padding], &lengthBitLow, 4);
+    memcpy(&buffer[length+padding+4], &lengthBitHigh, 4);
+    
+    uint32_t a = A, b = B, c = C, d = D;
+    for(int i = 0; i < totalLength/64; ++i)
+    {   
+        uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
+        computeRounds(&a, &b, &c, &d, &buffer[64*i]);
+        
+        a += tmpA;
+        b += tmpB;
+        c += tmpC;
+        d += tmpD;
+    }
+    delete[] buffer;
+
+    memcpy(digest, &a, 4);
+    memcpy(&digest[4], &b, 4);
+    memcpy(&digest[8], &c, 4);
+    memcpy(&digest[12], &d, 4);
+}
\ No newline at end of file