|
| 1 | +using SharpHash.Base; |
| 2 | +using SharpHash.Interfaces; |
| 3 | +using SharpHash.Utils; |
| 4 | +using System; |
| 5 | + |
| 6 | +namespace SharpHash.Crypto |
| 7 | +{ |
| 8 | + internal sealed class Panama : BlockHash, ICryptoNotBuildIn, ITransformBlock |
| 9 | + { |
| 10 | + private UInt32[][] stages = null; |
| 11 | + private UInt32[] state, theta, gamma, pi, work_buffer; |
| 12 | + |
| 13 | + private Int32 tap; |
| 14 | + |
| 15 | + public Panama() |
| 16 | + : base(32, 32) |
| 17 | + { |
| 18 | + tap = 0; |
| 19 | + state = new UInt32[17]; |
| 20 | + theta = new UInt32[17]; |
| 21 | + gamma = new UInt32[17]; |
| 22 | + pi = new UInt32[17]; |
| 23 | + work_buffer = new UInt32[17]; |
| 24 | + |
| 25 | + Array.Resize(ref stages, 32); |
| 26 | + for (UInt32 i = 0; i < 32; i++) |
| 27 | + stages[i] = new UInt32[8]; |
| 28 | + |
| 29 | + } // end constructor |
| 30 | + |
| 31 | + override public IHash Clone() |
| 32 | + { |
| 33 | + Panama HashInstance = new Panama(); |
| 34 | + HashInstance.buffer = buffer.Clone(); |
| 35 | + HashInstance.processed_bytes = processed_bytes; |
| 36 | + |
| 37 | + HashInstance.tap = tap; |
| 38 | + |
| 39 | + HashInstance.state = new UInt32[state.Length]; |
| 40 | + Utils.Utils.memcopy(ref HashInstance.state, state, state.Length); |
| 41 | + |
| 42 | + HashInstance.theta = new UInt32[theta.Length]; |
| 43 | + Utils.Utils.memcopy(ref HashInstance.theta, theta, theta.Length); |
| 44 | + |
| 45 | + HashInstance.gamma = new UInt32[gamma.Length]; |
| 46 | + Utils.Utils.memcopy(ref HashInstance.gamma, gamma, gamma.Length); |
| 47 | + |
| 48 | + HashInstance.pi = new UInt32[pi.Length]; |
| 49 | + Utils.Utils.memcopy(ref HashInstance.pi, pi, pi.Length); |
| 50 | + |
| 51 | + Array.Resize(ref stages, 32); |
| 52 | + for (UInt32 i = 0; i < 32; i++) |
| 53 | + Utils.Utils.memcopy(ref HashInstance.stages[i], stages[i], stages[i].Length); |
| 54 | + |
| 55 | + HashInstance.BufferSize = BufferSize; |
| 56 | + |
| 57 | + return HashInstance; |
| 58 | + } // end function Clone |
| 59 | + |
| 60 | + override public unsafe void Initialize() |
| 61 | + { |
| 62 | + Utils.Utils.memset(ref state, 0); |
| 63 | + |
| 64 | + for (Int32 i = 0; i < 32; i++) |
| 65 | + Utils.Utils.memset(ref stages[i], 0); |
| 66 | + |
| 67 | + base.Initialize(); |
| 68 | + } // end function Initialize |
| 69 | + |
| 70 | + override protected unsafe byte[] GetResult() |
| 71 | + { |
| 72 | + byte[] result = new byte[8 * sizeof(UInt32)]; |
| 73 | + |
| 74 | + fixed (UInt32* statePtr = &state[9]) |
| 75 | + { |
| 76 | + fixed (byte* resultPtr = result) |
| 77 | + { |
| 78 | + Converters.le32_copy((IntPtr)statePtr, 0, (IntPtr)resultPtr, 0, |
| 79 | + result.Length); |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + return result; |
| 84 | + } // end function GetResult |
| 85 | + |
| 86 | + override protected unsafe void Finish() |
| 87 | + { |
| 88 | + Int32 tap4, tap16, tap25; |
| 89 | + |
| 90 | + Int32 padding_size = 32 - (Int32)(processed_bytes & 31); |
| 91 | + |
| 92 | + byte[] pad = new byte[padding_size]; |
| 93 | + |
| 94 | + pad[0] = 0x01; |
| 95 | + TransformBytes(pad, 0, padding_size); |
| 96 | + |
| 97 | + UInt32[] theta = new UInt32[17]; |
| 98 | + |
| 99 | + fixed (UInt32* ptr_theta = theta) |
| 100 | + { |
| 101 | + for (Int32 i = 0; i < 32; i++) |
| 102 | + { |
| 103 | + tap4 = (tap + 4) & 0x1F; |
| 104 | + tap16 = (tap + 16) & 0x1F; |
| 105 | + |
| 106 | + tap = (tap - 1) & 0x1F; |
| 107 | + tap25 = (tap + 25) & 0x1F; |
| 108 | + |
| 109 | + GPT(ptr_theta); |
| 110 | + |
| 111 | + stages[tap25][0] = stages[tap25][0] ^ stages[tap][2]; |
| 112 | + stages[tap25][1] = stages[tap25][1] ^ stages[tap][3]; |
| 113 | + stages[tap25][2] = stages[tap25][2] ^ stages[tap][4]; |
| 114 | + stages[tap25][3] = stages[tap25][3] ^ stages[tap][5]; |
| 115 | + stages[tap25][4] = stages[tap25][4] ^ stages[tap][6]; |
| 116 | + stages[tap25][5] = stages[tap25][5] ^ stages[tap][7]; |
| 117 | + stages[tap25][6] = stages[tap25][6] ^ stages[tap][0]; |
| 118 | + stages[tap25][7] = stages[tap25][7] ^ stages[tap][1]; |
| 119 | + stages[tap][0] = stages[tap][0] ^ state[1]; |
| 120 | + stages[tap][1] = stages[tap][1] ^ state[2]; |
| 121 | + stages[tap][2] = stages[tap][2] ^ state[3]; |
| 122 | + stages[tap][3] = stages[tap][3] ^ state[4]; |
| 123 | + stages[tap][4] = stages[tap][4] ^ state[5]; |
| 124 | + stages[tap][5] = stages[tap][5] ^ state[6]; |
| 125 | + stages[tap][6] = stages[tap][6] ^ state[7]; |
| 126 | + stages[tap][7] = stages[tap][7] ^ state[8]; |
| 127 | + |
| 128 | + state[0] = theta[0] ^ 0x01; |
| 129 | + state[1] = theta[1] ^ stages[tap4][0]; |
| 130 | + state[2] = theta[2] ^ stages[tap4][1]; |
| 131 | + state[3] = theta[3] ^ stages[tap4][2]; |
| 132 | + state[4] = theta[4] ^ stages[tap4][3]; |
| 133 | + state[5] = theta[5] ^ stages[tap4][4]; |
| 134 | + state[6] = theta[6] ^ stages[tap4][5]; |
| 135 | + state[7] = theta[7] ^ stages[tap4][6]; |
| 136 | + state[8] = theta[8] ^ stages[tap4][7]; |
| 137 | + state[9] = theta[9] ^ stages[tap16][0]; |
| 138 | + state[10] = theta[10] ^ stages[tap16][1]; |
| 139 | + state[11] = theta[11] ^ stages[tap16][2]; |
| 140 | + state[12] = theta[12] ^ stages[tap16][3]; |
| 141 | + state[13] = theta[13] ^ stages[tap16][4]; |
| 142 | + state[14] = theta[14] ^ stages[tap16][5]; |
| 143 | + state[15] = theta[15] ^ stages[tap16][6]; |
| 144 | + state[16] = theta[16] ^ stages[tap16][7]; |
| 145 | + |
| 146 | + } // end for |
| 147 | + } |
| 148 | + |
| 149 | + } // end function Finish |
| 150 | + |
| 151 | + override protected unsafe void TransformBlock(IntPtr a_data, |
| 152 | + Int32 a_data_length, Int32 a_index) |
| 153 | + { |
| 154 | + UInt32 tap16, tap25; |
| 155 | + |
| 156 | + fixed (UInt32* thetaPtr = theta, workPtr = work_buffer) |
| 157 | + { |
| 158 | + Converters.le32_copy(a_data, a_index, (IntPtr)workPtr, 0, 32); |
| 159 | + |
| 160 | + tap16 = (UInt32)((tap + 16) & 0x1F); |
| 161 | + |
| 162 | + tap = (tap - 1) & 0x1F; |
| 163 | + tap25 = (UInt32)((tap + 25) & 0x1F); |
| 164 | + |
| 165 | + GPT(thetaPtr); |
| 166 | + |
| 167 | + stages[tap25][0] = stages[tap25][0] ^ stages[tap][2]; |
| 168 | + stages[tap25][1] = stages[tap25][1] ^ stages[tap][3]; |
| 169 | + stages[tap25][2] = stages[tap25][2] ^ stages[tap][4]; |
| 170 | + stages[tap25][3] = stages[tap25][3] ^ stages[tap][5]; |
| 171 | + stages[tap25][4] = stages[tap25][4] ^ stages[tap][6]; |
| 172 | + stages[tap25][5] = stages[tap25][5] ^ stages[tap][7]; |
| 173 | + stages[tap25][6] = stages[tap25][6] ^ stages[tap][0]; |
| 174 | + stages[tap25][7] = stages[tap25][7] ^ stages[tap][1]; |
| 175 | + stages[tap][0] = stages[tap][0] ^ work_buffer[0]; |
| 176 | + stages[tap][1] = stages[tap][1] ^ work_buffer[1]; |
| 177 | + stages[tap][2] = stages[tap][2] ^ work_buffer[2]; |
| 178 | + stages[tap][3] = stages[tap][3] ^ work_buffer[3]; |
| 179 | + stages[tap][4] = stages[tap][4] ^ work_buffer[4]; |
| 180 | + stages[tap][5] = stages[tap][5] ^ work_buffer[5]; |
| 181 | + stages[tap][6] = stages[tap][6] ^ work_buffer[6]; |
| 182 | + stages[tap][7] = stages[tap][7] ^ work_buffer[7]; |
| 183 | + |
| 184 | + state[0] = theta[0] ^ 0x01; |
| 185 | + state[1] = theta[1] ^ work_buffer[0]; |
| 186 | + state[2] = theta[2] ^ work_buffer[1]; |
| 187 | + state[3] = theta[3] ^ work_buffer[2]; |
| 188 | + state[4] = theta[4] ^ work_buffer[3]; |
| 189 | + state[5] = theta[5] ^ work_buffer[4]; |
| 190 | + state[6] = theta[6] ^ work_buffer[5]; |
| 191 | + state[7] = theta[7] ^ work_buffer[6]; |
| 192 | + state[8] = theta[8] ^ work_buffer[7]; |
| 193 | + state[9] = theta[9] ^ stages[tap16][0]; |
| 194 | + state[10] = theta[10] ^ stages[tap16][1]; |
| 195 | + state[11] = theta[11] ^ stages[tap16][2]; |
| 196 | + state[12] = theta[12] ^ stages[tap16][3]; |
| 197 | + state[13] = theta[13] ^ stages[tap16][4]; |
| 198 | + state[14] = theta[14] ^ stages[tap16][5]; |
| 199 | + state[15] = theta[15] ^ stages[tap16][6]; |
| 200 | + state[16] = theta[16] ^ stages[tap16][7]; |
| 201 | + |
| 202 | + |
| 203 | + Utils.Utils.memset(ref work_buffer, 0); |
| 204 | + } |
| 205 | + |
| 206 | + } // end function TransformBlock |
| 207 | + |
| 208 | + private unsafe void GPT(UInt32* a_theta) |
| 209 | + { |
| 210 | + gamma[0] = state[0] ^ (state[1] | ~state[2]); |
| 211 | + gamma[1] = state[1] ^ (state[2] | ~state[3]); |
| 212 | + gamma[2] = state[2] ^ (state[3] | ~state[4]); |
| 213 | + gamma[3] = state[3] ^ (state[4] | ~state[5]); |
| 214 | + gamma[4] = state[4] ^ (state[5] | ~state[6]); |
| 215 | + gamma[5] = state[5] ^ (state[6] | ~state[7]); |
| 216 | + gamma[6] = state[6] ^ (state[7] | ~state[8]); |
| 217 | + gamma[7] = state[7] ^ (state[8] | ~state[9]); |
| 218 | + gamma[8] = state[8] ^ (state[9] | ~state[10]); |
| 219 | + gamma[9] = state[9] ^ (state[10] | ~state[11]); |
| 220 | + gamma[10] = state[10] ^ (state[11] | ~state[12]); |
| 221 | + gamma[11] = state[11] ^ (state[12] | ~state[13]); |
| 222 | + gamma[12] = state[12] ^ (state[13] | ~state[14]); |
| 223 | + gamma[13] = state[13] ^ (state[14] | ~state[15]); |
| 224 | + gamma[14] = state[14] ^ (state[15] | ~state[16]); |
| 225 | + gamma[15] = state[15] ^ (state[16] | ~state[0]); |
| 226 | + gamma[16] = state[16] ^ (state[0] | ~state[1]); |
| 227 | + |
| 228 | + pi[0] = gamma[0]; |
| 229 | + pi[1] = Bits.RotateLeft32(gamma[7], 1); |
| 230 | + pi[2] = Bits.RotateLeft32(gamma[14], 3); |
| 231 | + pi[3] = Bits.RotateLeft32(gamma[4], 6); |
| 232 | + pi[4] = Bits.RotateLeft32(gamma[11], 10); |
| 233 | + pi[5] = Bits.RotateLeft32(gamma[1], 15); |
| 234 | + pi[6] = Bits.RotateLeft32(gamma[8], 21); |
| 235 | + pi[7] = Bits.RotateLeft32(gamma[15], 28); |
| 236 | + pi[8] = Bits.RotateLeft32(gamma[5], 4); |
| 237 | + pi[9] = Bits.RotateLeft32(gamma[12], 13); |
| 238 | + pi[10] = Bits.RotateLeft32(gamma[2], 23); |
| 239 | + pi[11] = Bits.RotateLeft32(gamma[9], 2); |
| 240 | + pi[12] = Bits.RotateLeft32(gamma[16], 14); |
| 241 | + pi[13] = Bits.RotateLeft32(gamma[6], 27); |
| 242 | + pi[14] = Bits.RotateLeft32(gamma[13], 9); |
| 243 | + pi[15] = Bits.RotateLeft32(gamma[3], 24); |
| 244 | + pi[16] = Bits.RotateLeft32(gamma[10], 8); |
| 245 | + |
| 246 | + a_theta[0] = pi[0] ^ pi[1] ^ pi[4]; |
| 247 | + a_theta[1] = pi[1] ^ pi[2] ^ pi[5]; |
| 248 | + a_theta[2] = pi[2] ^ pi[3] ^ pi[6]; |
| 249 | + a_theta[3] = pi[3] ^ pi[4] ^ pi[7]; |
| 250 | + a_theta[4] = pi[4] ^ pi[5] ^ pi[8]; |
| 251 | + a_theta[5] = pi[5] ^ pi[6] ^ pi[9]; |
| 252 | + a_theta[6] = pi[6] ^ pi[7] ^ pi[10]; |
| 253 | + a_theta[7] = pi[7] ^ pi[8] ^ pi[11]; |
| 254 | + a_theta[8] = pi[8] ^ pi[9] ^ pi[12]; |
| 255 | + a_theta[9] = pi[9] ^ pi[10] ^ pi[13]; |
| 256 | + a_theta[10] = pi[10] ^ pi[11] ^ pi[14]; |
| 257 | + a_theta[11] = pi[11] ^ pi[12] ^ pi[15]; |
| 258 | + a_theta[12] = pi[12] ^ pi[13] ^ pi[16]; |
| 259 | + a_theta[13] = pi[13] ^ pi[14] ^ pi[0]; |
| 260 | + a_theta[14] = pi[14] ^ pi[15] ^ pi[1]; |
| 261 | + a_theta[15] = pi[15] ^ pi[16] ^ pi[2]; |
| 262 | + a_theta[16] = pi[16] ^ pi[0] ^ pi[3]; |
| 263 | + } // end function GPT |
| 264 | + |
| 265 | + } // end class Panama |
| 266 | + |
| 267 | +} |
0 commit comments