1 /**
2 * MD2
3 * 
4 * Copyright:
5 * (C) 1999-2007 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.md2;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_MD2):
15 
16 import botan.hash.hash;
17 import botan.utils.xor_buf;
18 import botan.utils.types;
19 import botan.utils.mem_ops;
20 /**
21 * MD2
22 */
23 class MD2 : HashFunction
24 {
25 public:
26     override @property string name() const { return "MD2"; }
27     override @property size_t outputLength() const { return 16; }
28     override @property size_t hashBlockSize() const { return 16; }
29     override HashFunction clone() const { return new MD2; }
30 
31     /**
32     * Clear memory of sensitive data
33     */
34     override void clear()
35     {
36         zeroise(m_X);
37         zeroise(m_checksum);
38         zeroise(m_buffer);
39         m_position = 0;
40     }
41 
42     this() 
43     { 
44         m_X = SecureVector!ubyte(48);
45         m_checksum = SecureVector!ubyte(16);
46         m_buffer = SecureVector!ubyte(16);
47         clear(); 
48     }
49 protected:
50     /**
51     * Update the hash
52     */
53     override void addData(const(ubyte)* input, size_t length)
54     {
55         bufferInsert(m_buffer, m_position, input, length);
56         
57         if (m_position + length >= hashBlockSize)
58         {
59             hash(m_buffer.ptr);
60             input += (hashBlockSize - m_position);
61             length -= (hashBlockSize - m_position);
62             while (length >= hashBlockSize)
63             {
64                 hash(input);
65                 input += hashBlockSize;
66                 length -= hashBlockSize;
67             }
68             copyMem(m_buffer.ptr, input, length);
69             m_position = 0;
70         }
71         m_position += length;
72     }
73     /**
74     * MD2 Compression Function
75     */
76     void hash(const(ubyte)* input)
77     {
78         __gshared immutable ubyte[256] SBOX = [
79             0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1,
80             0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
81             0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C,
82             0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
83             0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
84             0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
85             0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, 0x80, 0x7F, 0x5D, 0x9A,
86             0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
87             0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A,
88             0xAC, 0x56, 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
89             0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, 0x70, 0x59,
90             0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
91             0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69,
92             0x34, 0x40, 0x7E, 0x0F, 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
93             0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
94             0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
95             0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08,
96             0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
97             0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E,
98             0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
99             0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33,
100             0x9F, 0x11, 0x83, 0x14 ];
101         
102         bufferInsert(m_X, 16, input, hashBlockSize);
103         xorBuf(&m_X[32], m_X.ptr, &m_X[16], hashBlockSize);
104         ubyte T = 0;
105         
106         foreach (size_t i; 0 .. 18)
107         {
108             for (size_t k = 0; k != 48; k += 8)
109             {
110                 T = m_X[k  ] ^= SBOX[T]; T = m_X[k+1] ^= SBOX[T];
111                 T = m_X[k+2] ^= SBOX[T]; T = m_X[k+3] ^= SBOX[T];
112                 T = m_X[k+4] ^= SBOX[T]; T = m_X[k+5] ^= SBOX[T];
113                 T = m_X[k+6] ^= SBOX[T]; T = m_X[k+7] ^= SBOX[T];
114             }
115             
116             T += cast(ubyte)(i);
117         }
118         
119         T = m_checksum[15];
120         foreach (size_t i; 0 .. hashBlockSize)
121             T = m_checksum[i] ^= SBOX[input[i] ^ T];
122     }
123 
124     /**
125     * Finalize a MD2 Hash
126     */
127     override void finalResult(ubyte* output)
128     {
129         foreach (size_t i; m_position .. hashBlockSize)
130             m_buffer[i] = cast(ubyte)(hashBlockSize - m_position);
131         
132         hash(m_buffer.ptr);
133         hash(m_checksum.ptr);
134         copyMem(output, m_X.ptr, outputLength);
135         clear();
136     }
137 
138     SecureVector!ubyte m_X, m_checksum, m_buffer;
139     size_t m_position;
140 }