1 /**
2 * MD5
3 * 
4 * Copyright:
5 * (C) 1999-2008 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.hash.md5;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_MD5):
15 
16 
17 import botan.hash.mdx_hash;
18 import botan.utils.loadstor;
19 import botan.utils.rotate;
20 import botan.utils.types;
21 import botan.utils.mem_ops;
22 
23 /**
24 * MD5
25 */
26 class MD5 : MDxHashFunction, HashFunction
27 {
28 public:
29     
30     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
31     final override @property string name() const { return "MD5"; }
32     override final @property size_t outputLength() const { return 16; }
33     override HashFunction clone() const { return new MD5; }
34 
35     /*
36     * Clear memory of sensitive data
37     */
38     override final void clear()
39     {
40         super.clear();
41         zeroise(m_M);
42         m_digest[0] = 0x67452301;
43         m_digest[1] = 0xEFCDAB89;
44         m_digest[2] = 0x98BADCFE;
45         m_digest[3] = 0x10325476;
46     }
47 
48 
49     this()
50     { 
51         super(64, false, true); 
52         m_M = 16;
53         m_digest.length = 4;
54         clear();
55     }
56 protected:
57     /*
58     * MD5 Compression Function
59     */
60     override void compressN(const(ubyte)* input, size_t blocks)
61     {
62         uint A = m_digest[0], B = m_digest[1], C = m_digest[2], D = m_digest[3];
63         
64         foreach (size_t i; 0 .. blocks)
65         {
66             loadLittleEndian(m_M.ptr, input, m_M.length);
67             
68             FF(A,B,C,D,m_M[ 0], 7,0xD76AA478);    FF(D,A,B,C,m_M[ 1],12,0xE8C7B756);
69             FF(C,D,A,B,m_M[ 2],17,0x242070DB);    FF(B,C,D,A,m_M[ 3],22,0xC1BDCEEE);
70             FF(A,B,C,D,m_M[ 4], 7,0xF57C0FAF);    FF(D,A,B,C,m_M[ 5],12,0x4787C62A);
71             FF(C,D,A,B,m_M[ 6],17,0xA8304613);    FF(B,C,D,A,m_M[ 7],22,0xFD469501);
72             FF(A,B,C,D,m_M[ 8], 7,0x698098D8);    FF(D,A,B,C,m_M[ 9],12,0x8B44F7AF);
73             FF(C,D,A,B,m_M[10],17,0xFFFF5BB1);    FF(B,C,D,A,m_M[11],22,0x895CD7BE);
74             FF(A,B,C,D,m_M[12], 7,0x6B901122);    FF(D,A,B,C,m_M[13],12,0xFD987193);
75             FF(C,D,A,B,m_M[14],17,0xA679438E);    FF(B,C,D,A,m_M[15],22,0x49B40821);
76             
77             GG(A,B,C,D,m_M[ 1], 5,0xF61E2562);    GG(D,A,B,C,m_M[ 6], 9,0xC040B340);
78             GG(C,D,A,B,m_M[11],14,0x265E5A51);    GG(B,C,D,A,m_M[ 0],20,0xE9B6C7AA);
79             GG(A,B,C,D,m_M[ 5], 5,0xD62F105D);    GG(D,A,B,C,m_M[10], 9,0x02441453);
80             GG(C,D,A,B,m_M[15],14,0xD8A1E681);    GG(B,C,D,A,m_M[ 4],20,0xE7D3FBC8);
81             GG(A,B,C,D,m_M[ 9], 5,0x21E1CDE6);    GG(D,A,B,C,m_M[14], 9,0xC33707D6);
82             GG(C,D,A,B,m_M[ 3],14,0xF4D50D87);    GG(B,C,D,A,m_M[ 8],20,0x455A14ED);
83             GG(A,B,C,D,m_M[13], 5,0xA9E3E905);    GG(D,A,B,C,m_M[ 2], 9,0xFCEFA3F8);
84             GG(C,D,A,B,m_M[ 7],14,0x676F02D9);    GG(B,C,D,A,m_M[12],20,0x8D2A4C8A);
85             
86             HH(A,B,C,D,m_M[ 5], 4,0xFFFA3942);    HH(D,A,B,C,m_M[ 8],11,0x8771F681);
87             HH(C,D,A,B,m_M[11],16,0x6D9D6122);    HH(B,C,D,A,m_M[14],23,0xFDE5380C);
88             HH(A,B,C,D,m_M[ 1], 4,0xA4BEEA44);    HH(D,A,B,C,m_M[ 4],11,0x4BDECFA9);
89             HH(C,D,A,B,m_M[ 7],16,0xF6BB4B60);    HH(B,C,D,A,m_M[10],23,0xBEBFBC70);
90             HH(A,B,C,D,m_M[13], 4,0x289B7EC6);    HH(D,A,B,C,m_M[ 0],11,0xEAA127FA);
91             HH(C,D,A,B,m_M[ 3],16,0xD4EF3085);    HH(B,C,D,A,m_M[ 6],23,0x04881D05);
92             HH(A,B,C,D,m_M[ 9], 4,0xD9D4D039);    HH(D,A,B,C,m_M[12],11,0xE6DB99E5);
93             HH(C,D,A,B,m_M[15],16,0x1FA27CF8);    HH(B,C,D,A,m_M[ 2],23,0xC4AC5665);
94             
95             II(A,B,C,D,m_M[ 0], 6,0xF4292244);    II(D,A,B,C,m_M[ 7],10,0x432AFF97);
96             II(C,D,A,B,m_M[14],15,0xAB9423A7);    II(B,C,D,A,m_M[ 5],21,0xFC93A039);
97             II(A,B,C,D,m_M[12], 6,0x655B59C3);    II(D,A,B,C,m_M[ 3],10,0x8F0CCC92);
98             II(C,D,A,B,m_M[10],15,0xFFEFF47D);    II(B,C,D,A,m_M[ 1],21,0x85845DD1);
99             II(A,B,C,D,m_M[ 8], 6,0x6FA87E4F);    II(D,A,B,C,m_M[15],10,0xFE2CE6E0);
100             II(C,D,A,B,m_M[ 6],15,0xA3014314);    II(B,C,D,A,m_M[13],21,0x4E0811A1);
101             II(A,B,C,D,m_M[ 4], 6,0xF7537E82);    II(D,A,B,C,m_M[11],10,0xBD3AF235);
102             II(C,D,A,B,m_M[ 2],15,0x2AD7D2BB);    II(B,C,D,A,m_M[ 9],21,0xEB86D391);
103             
104             A = (m_digest[0] += A);
105             B = (m_digest[1] += B);
106             C = (m_digest[2] += C);
107             D = (m_digest[3] += D);
108             
109             input += hashBlockSize;
110         }
111     }
112 
113     /*
114     * Copy out the digest
115     */
116     override final void copyOut(ubyte* output)
117     {
118         for (size_t i = 0; i != outputLength; i += 4)
119             storeLittleEndian(m_digest[i/4], output + i);
120     }
121 
122     /**
123     * The message buffer, exposed for use by subclasses (x86 asm)
124     */
125     SecureVector!uint m_M;
126 
127     /**
128     * The digest value, exposed for use by subclasses (x86 asm)
129     */
130     SecureVector!uint m_digest;
131 }
132 
133 private:
134 
135 /*
136 * MD5 FF Function
137 */
138 void FF(ref uint A, uint B, uint C, uint D, uint msg,
139         ubyte S, uint magic) pure
140 {
141     A += (D ^ (B & (C ^ D))) + msg + magic;
142     A  = rotateLeft(A, S) + B;
143 }
144 
145 /*
146 * MD5 GG Function
147 */
148 void GG(ref uint A, uint B, uint C, uint D, uint msg,
149         ubyte S, uint magic) pure
150 {
151     A += (C ^ (D & (B ^ C))) + msg + magic;
152     A  = rotateLeft(A, S) + B;
153 }
154 
155 /*
156 * MD5 HH Function
157 */
158 void HH(ref uint A, uint B, uint C, uint D, uint msg,
159         ubyte S, uint magic) pure
160 {
161     A += (B ^ C ^ D) + msg + magic;
162     A  = rotateLeft(A, S) + B;
163 }
164 
165 /*
166 * MD5 II Function
167 */
168 void II(ref uint A, uint B, uint C, uint D, uint msg,
169         ubyte S, uint magic) pure
170 {
171     A += (C ^ (B | ~D)) + msg + magic;
172     A  = rotateLeft(A, S) + B;
173 }