diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-11-29 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-11-30 15:27:15 +0500 |
commit | e5431fa6f5505e385c6f9367260717e9c47dc2ee (patch) | |
tree | 4cd2c2c3b225b48c8e7053432c41d7b6b6a3d5f8 /C/Md5.c | |
parent | e008ce3976c087bfd21344af8f00a23cf69d4174 (diff) | |
download | 7zip-main.tar.gz 7zip-main.tar.bz2 7zip-main.zip |
Diffstat (limited to 'C/Md5.c')
-rw-r--r-- | C/Md5.c | 206 |
1 files changed, 206 insertions, 0 deletions
@@ -0,0 +1,206 @@ | |||
1 | /* Md5.c -- MD5 Hash | ||
2 | : Igor Pavlov : Public domain | ||
3 | This code is based on Colin Plumb's public domain md5.c code */ | ||
4 | |||
5 | #include "Precomp.h" | ||
6 | |||
7 | #include <string.h> | ||
8 | |||
9 | #include "Md5.h" | ||
10 | #include "RotateDefs.h" | ||
11 | #include "CpuArch.h" | ||
12 | |||
13 | #define MD5_UPDATE_BLOCKS(p) Md5_UpdateBlocks | ||
14 | |||
15 | Z7_NO_INLINE | ||
16 | void Md5_Init(CMd5 *p) | ||
17 | { | ||
18 | p->count = 0; | ||
19 | p->state[0] = 0x67452301; | ||
20 | p->state[1] = 0xefcdab89; | ||
21 | p->state[2] = 0x98badcfe; | ||
22 | p->state[3] = 0x10325476; | ||
23 | } | ||
24 | |||
25 | #if 0 && !defined(MY_CPU_LE_UNALIGN) | ||
26 | // optional optimization for Big-endian processors or processors without unaligned access: | ||
27 | // it is intended to reduce the number of complex LE32 memory reading from 64 to 16. | ||
28 | // But some compilers (sparc, armt) are better without this optimization. | ||
29 | #define Z7_MD5_USE_DATA32_ARRAY | ||
30 | #endif | ||
31 | |||
32 | #define LOAD_DATA(i) GetUi32((const UInt32 *)(const void *)data + (i)) | ||
33 | |||
34 | #ifdef Z7_MD5_USE_DATA32_ARRAY | ||
35 | #define D(i) data32[i] | ||
36 | #else | ||
37 | #define D(i) LOAD_DATA(i) | ||
38 | #endif | ||
39 | |||
40 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | ||
41 | #define F2(x, y, z) F1(z, x, y) | ||
42 | #define F3(x, y, z) (x ^ y ^ z) | ||
43 | #define F4(x, y, z) (y ^ (x | ~z)) | ||
44 | |||
45 | #define R1(i, f, start, step, w, x, y, z, s, k) \ | ||
46 | w += D((start + step * (i)) % 16) + k; \ | ||
47 | w += f(x, y, z); \ | ||
48 | w = rotlFixed(w, s) + x; \ | ||
49 | |||
50 | #define R4(i4, f, start, step, s0,s1,s2,s3, k0,k1,k2,k3) \ | ||
51 | R1 (i4*4+0, f, start, step, a,b,c,d, s0, k0) \ | ||
52 | R1 (i4*4+1, f, start, step, d,a,b,c, s1, k1) \ | ||
53 | R1 (i4*4+2, f, start, step, c,d,a,b, s2, k2) \ | ||
54 | R1 (i4*4+3, f, start, step, b,c,d,a, s3, k3) \ | ||
55 | |||
56 | #define R16(f, start, step, s0,s1,s2,s3, k00,k01,k02,k03, k10,k11,k12,k13, k20,k21,k22,k23, k30,k31,k32,k33) \ | ||
57 | R4 (0, f, start, step, s0,s1,s2,s3, k00,k01,k02,k03) \ | ||
58 | R4 (1, f, start, step, s0,s1,s2,s3, k10,k11,k12,k13) \ | ||
59 | R4 (2, f, start, step, s0,s1,s2,s3, k20,k21,k22,k23) \ | ||
60 | R4 (3, f, start, step, s0,s1,s2,s3, k30,k31,k32,k33) \ | ||
61 | |||
62 | static | ||
63 | Z7_NO_INLINE | ||
64 | void Z7_FASTCALL Md5_UpdateBlocks(UInt32 state[4], const Byte *data, size_t numBlocks) | ||
65 | { | ||
66 | UInt32 a, b, c, d; | ||
67 | // if (numBlocks == 0) return; | ||
68 | a = state[0]; | ||
69 | b = state[1]; | ||
70 | c = state[2]; | ||
71 | d = state[3]; | ||
72 | do | ||
73 | { | ||
74 | #ifdef Z7_MD5_USE_DATA32_ARRAY | ||
75 | UInt32 data32[MD5_NUM_BLOCK_WORDS]; | ||
76 | { | ||
77 | #define LOAD_data32_x4(i) { \ | ||
78 | data32[i ] = LOAD_DATA(i ); \ | ||
79 | data32[i + 1] = LOAD_DATA(i + 1); \ | ||
80 | data32[i + 2] = LOAD_DATA(i + 2); \ | ||
81 | data32[i + 3] = LOAD_DATA(i + 3); } | ||
82 | #if 1 | ||
83 | LOAD_data32_x4 (0 * 4) | ||
84 | LOAD_data32_x4 (1 * 4) | ||
85 | LOAD_data32_x4 (2 * 4) | ||
86 | LOAD_data32_x4 (3 * 4) | ||
87 | #else | ||
88 | unsigned i; | ||
89 | for (i = 0; i < MD5_NUM_BLOCK_WORDS; i += 4) | ||
90 | { | ||
91 | LOAD_data32_x4(i) | ||
92 | } | ||
93 | #endif | ||
94 | } | ||
95 | #endif | ||
96 | |||
97 | R16 (F1, 0, 1, 7,12,17,22, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, | ||
98 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, | ||
99 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, | ||
100 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821) | ||
101 | R16 (F2, 1, 5, 5, 9,14,20, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, | ||
102 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, | ||
103 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, | ||
104 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a) | ||
105 | R16 (F3, 5, 3, 4,11,16,23, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, | ||
106 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, | ||
107 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, | ||
108 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665) | ||
109 | R16 (F4, 0, 7, 6,10,15,21, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, | ||
110 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, | ||
111 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, | ||
112 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391) | ||
113 | |||
114 | a += state[0]; | ||
115 | b += state[1]; | ||
116 | c += state[2]; | ||
117 | d += state[3]; | ||
118 | |||
119 | state[0] = a; | ||
120 | state[1] = b; | ||
121 | state[2] = c; | ||
122 | state[3] = d; | ||
123 | |||
124 | data += MD5_BLOCK_SIZE; | ||
125 | } | ||
126 | while (--numBlocks); | ||
127 | } | ||
128 | |||
129 | |||
130 | #define Md5_UpdateBlock(p) MD5_UPDATE_BLOCKS(p)(p->state, p->buffer, 1) | ||
131 | |||
132 | void Md5_Update(CMd5 *p, const Byte *data, size_t size) | ||
133 | { | ||
134 | if (size == 0) | ||
135 | return; | ||
136 | { | ||
137 | const unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1); | ||
138 | const unsigned num = MD5_BLOCK_SIZE - pos; | ||
139 | p->count += size; | ||
140 | if (num > size) | ||
141 | { | ||
142 | memcpy(p->buffer + pos, data, size); | ||
143 | return; | ||
144 | } | ||
145 | if (pos != 0) | ||
146 | { | ||
147 | size -= num; | ||
148 | memcpy(p->buffer + pos, data, num); | ||
149 | data += num; | ||
150 | Md5_UpdateBlock(p); | ||
151 | } | ||
152 | } | ||
153 | { | ||
154 | const size_t numBlocks = size >> 6; | ||
155 | if (numBlocks) | ||
156 | MD5_UPDATE_BLOCKS(p)(p->state, data, numBlocks); | ||
157 | size &= MD5_BLOCK_SIZE - 1; | ||
158 | if (size == 0) | ||
159 | return; | ||
160 | data += (numBlocks << 6); | ||
161 | memcpy(p->buffer, data, size); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | |||
166 | void Md5_Final(CMd5 *p, Byte *digest) | ||
167 | { | ||
168 | unsigned pos = (unsigned)p->count & (MD5_BLOCK_SIZE - 1); | ||
169 | p->buffer[pos++] = 0x80; | ||
170 | if (pos > (MD5_BLOCK_SIZE - 4 * 2)) | ||
171 | { | ||
172 | while (pos != MD5_BLOCK_SIZE) { p->buffer[pos++] = 0; } | ||
173 | // memset(&p->buf.buffer[pos], 0, MD5_BLOCK_SIZE - pos); | ||
174 | Md5_UpdateBlock(p); | ||
175 | pos = 0; | ||
176 | } | ||
177 | memset(&p->buffer[pos], 0, (MD5_BLOCK_SIZE - 4 * 2) - pos); | ||
178 | { | ||
179 | const UInt64 numBits = p->count << 3; | ||
180 | #if defined(MY_CPU_LE_UNALIGN) | ||
181 | SetUi64 (p->buffer + MD5_BLOCK_SIZE - 4 * 2, numBits) | ||
182 | #else | ||
183 | SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 2, (UInt32)(numBits)) | ||
184 | SetUi32a(p->buffer + MD5_BLOCK_SIZE - 4 * 1, (UInt32)(numBits >> 32)) | ||
185 | #endif | ||
186 | } | ||
187 | Md5_UpdateBlock(p); | ||
188 | |||
189 | SetUi32(digest, p->state[0]) | ||
190 | SetUi32(digest + 4, p->state[1]) | ||
191 | SetUi32(digest + 8, p->state[2]) | ||
192 | SetUi32(digest + 12, p->state[3]) | ||
193 | |||
194 | Md5_Init(p); | ||
195 | } | ||
196 | |||
197 | #undef R1 | ||
198 | #undef R4 | ||
199 | #undef R16 | ||
200 | #undef D | ||
201 | #undef LOAD_DATA | ||
202 | #undef LOAD_data32_x4 | ||
203 | #undef F1 | ||
204 | #undef F2 | ||
205 | #undef F3 | ||
206 | #undef F4 | ||