1 /** 2 * MD4 (x86-32) 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.md4_x86_32; 12 13 import botan.constants; 14 static if (BOTAN_HAS_MD4_X86_32): 15 16 import botan.utils.asm_x86_32.asm_x86_32; 17 import botan.hash.md4; 18 import botan.hash.hash; 19 20 /** 21 * MD4 using x86 assembly 22 */ 23 class MD4_X86_32 : MD4 24 { 25 public: 26 override HashFunction clone() const { return new MD4_X86_32; } 27 28 protected: 29 /* 30 * MD4 Compression Function 31 */ 32 override void compressN(const(ubyte)* input, size_t blocks) 33 { 34 foreach (size_t i; 0 .. blocks) 35 { 36 botan_md4_x86_32_compress(m_digest.ptr, input, m_M.ptr); 37 input += hashBlockSize; 38 } 39 } 40 } 41 42 private: 43 /** 44 * MD4 compression function in x86-32 asm 45 * Params: 46 * digest = the current digest 47 * input = the input block 48 * M = the message buffer 49 */ 50 extern(C) 51 void botan_md4_x86_32_compress(uint* digest, const(ubyte)* input, uint* M) 52 { 53 enum PUSHED = 4; 54 enum ASM = START_ASM ~ 55 "naked;" ~ 56 SPILL_REGS() ~ 57 ASSIGN(EBP, ARG(PUSHED, 2)) ~/* input block */ 58 ASSIGN(EDI, ARG(PUSHED, 3)) ~ /* expanded words */ 59 60 ZEROIZE(ESI) ~ 61 62 START_LOOP("LOAD_INPUT") ~ 63 ADD_IMM(ESI, 4) ~ 64 65 ASSIGN(EAX, ARRAY4(EBP, 0)) ~ 66 ASSIGN(EBX, ARRAY4(EBP, 1)) ~ 67 ASSIGN(ECX, ARRAY4(EBP, 2)) ~ 68 ASSIGN(EDX, ARRAY4(EBP, 3)) ~ 69 70 ADD_IMM(EBP, 16) ~ 71 72 ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-4), EAX) ~ 73 ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-3), EBX) ~ 74 ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-2), ECX) ~ 75 ASSIGN(ARRAY4_INDIRECT(EDI,ESI,-1), EDX) ~ 76 LOOP_UNTIL_EQ(ESI, 16, "LOAD_INPUT") ~ 77 78 ASSIGN(EBP, ARG(PUSHED, 1)) ~ 79 ASSIGN(EAX, ARRAY4(EBP, 0)) ~ 80 ASSIGN(EBX, ARRAY4(EBP, 1)) ~ 81 ASSIGN(ECX, ARRAY4(EBP, 2)) ~ 82 ASSIGN(EDX, ARRAY4(EBP, 3)) ~ 83 84 FF(EAX,EBX,ECX,EDX, 0, 3) ~ 85 FF(EDX,EAX,EBX,ECX, 1, 7) ~ 86 FF(ECX,EDX,EAX,EBX, 2,11) ~ 87 FF(EBX,ECX,EDX,EAX, 3,19) ~ 88 FF(EAX,EBX,ECX,EDX, 4, 3) ~ 89 FF(EDX,EAX,EBX,ECX, 5, 7) ~ 90 FF(ECX,EDX,EAX,EBX, 6,11) ~ 91 FF(EBX,ECX,EDX,EAX, 7,19) ~ 92 FF(EAX,EBX,ECX,EDX, 8, 3) ~ 93 FF(EDX,EAX,EBX,ECX, 9, 7) ~ 94 FF(ECX,EDX,EAX,EBX,10,11) ~ 95 FF(EBX,ECX,EDX,EAX,11,19) ~ 96 FF(EAX,EBX,ECX,EDX,12, 3) ~ 97 FF(EDX,EAX,EBX,ECX,13, 7) ~ 98 FF(ECX,EDX,EAX,EBX,14,11) ~ 99 FF(EBX,ECX,EDX,EAX,15,19) ~ 100 101 GG(EAX,EBX,ECX,EDX, 0, 3) ~ 102 GG(EDX,EAX,EBX,ECX, 4, 5) ~ 103 GG(ECX,EDX,EAX,EBX, 8, 9) ~ 104 GG(EBX,ECX,EDX,EAX,12,13) ~ 105 GG(EAX,EBX,ECX,EDX, 1, 3) ~ 106 GG(EDX,EAX,EBX,ECX, 5, 5) ~ 107 GG(ECX,EDX,EAX,EBX, 9, 9) ~ 108 GG(EBX,ECX,EDX,EAX,13,13) ~ 109 GG(EAX,EBX,ECX,EDX, 2, 3) ~ 110 GG(EDX,EAX,EBX,ECX, 6, 5) ~ 111 GG(ECX,EDX,EAX,EBX,10, 9) ~ 112 GG(EBX,ECX,EDX,EAX,14,13) ~ 113 GG(EAX,EBX,ECX,EDX, 3, 3) ~ 114 GG(EDX,EAX,EBX,ECX, 7, 5) ~ 115 GG(ECX,EDX,EAX,EBX,11, 9) ~ 116 GG(EBX,ECX,EDX,EAX,15,13) ~ 117 118 HH(EAX,EBX,ECX,EDX, 0, 3) ~ 119 HH(EDX,EAX,EBX,ECX, 8, 9) ~ 120 HH(ECX,EDX,EAX,EBX, 4,11) ~ 121 HH(EBX,ECX,EDX,EAX,12,15) ~ 122 HH(EAX,EBX,ECX,EDX, 2, 3) ~ 123 HH(EDX,EAX,EBX,ECX,10, 9) ~ 124 HH(ECX,EDX,EAX,EBX, 6,11) ~ 125 HH(EBX,ECX,EDX,EAX,14,15) ~ 126 HH(EAX,EBX,ECX,EDX, 1, 3) ~ 127 HH(EDX,EAX,EBX,ECX, 9, 9) ~ 128 HH(ECX,EDX,EAX,EBX, 5,11) ~ 129 HH(EBX,ECX,EDX,EAX,13,15) ~ 130 HH(EAX,EBX,ECX,EDX, 3, 3) ~ 131 HH(EDX,EAX,EBX,ECX,11, 9) ~ 132 HH(ECX,EDX,EAX,EBX, 7,11) ~ 133 HH(EBX,ECX,EDX,EAX,15,15) ~ 134 135 ASSIGN(EBP, ARG(PUSHED, 1)) ~ 136 ADD(ARRAY4(EBP, 0), EAX) ~ 137 ADD(ARRAY4(EBP, 1), EBX) ~ 138 ADD(ARRAY4(EBP, 2), ECX) ~ 139 ADD(ARRAY4(EBP, 3), EDX) ~ 140 RESTORE_REGS() ~ 141 "ret;" ~ 142 END_ASM; 143 mixin(ASM); 144 } 145 146 147 enum MSG = EDI; 148 enum T1 = ESI; 149 enum T2 = EBP; 150 151 string FF(string A, string B, string C, string D, ubyte N, ubyte S) { 152 return ASSIGN(T1, ARRAY4(MSG, N))~ 153 ASSIGN(T2, C)~ 154 XOR(T2, D) ~ 155 AND(T2, B) ~ 156 XOR(T2, D) ~ 157 ADD(A, T1) ~ 158 ADD(A, T2) ~ 159 ROTL_IMM(A, S); 160 } 161 162 string GG(string A, string B, string C, string D, ubyte N, ubyte S) { 163 return ASSIGN(T1, ARRAY4(MSG, N)) ~ 164 ASSIGN(T2, B) ~ 165 OR(T2, C) ~ 166 AND(T2, D) ~ 167 ADD3_IMM(A, T1, 0x5A827999) ~ 168 ASSIGN(T1, B) ~ 169 AND(T1, C) ~ 170 OR(T2, T1) ~ 171 ADD(A, T2) ~ 172 ROTL_IMM(A, S); 173 } 174 string HH(string A, string B, string C, string D, ubyte N, ubyte S) { 175 return ASSIGN(T1, ARRAY4(MSG, N)) ~ 176 ASSIGN(T2, B) ~ 177 XOR(T2, C) ~ 178 XOR(T2, D) ~ 179 ADD3_IMM(A, T1, 0x6ED9EBA1) ~ 180 ADD(A, T2) ~ 181 ROTL_IMM(A, S); 182 }