support -X option in rpmmd2solv, make add_autopattern available in bindings
[platform/upstream/libsolv.git] / src / md5.c
1 /*
2  * This is an OpenSSL-compatible implementation of the RSA Data Security,
3  * Inc. MD5 Message-Digest Algorithm.
4  *
5  * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
6  * the public domain.
7  *
8  * This differs from Colin Plumb's older public domain implementation in
9  * that no 32-bit integer data type is required, there's no compile-time
10  * endianness configuration, and the function prototypes match OpenSSL's.
11  * The primary goals are portability and ease of use.
12  *
13  * This implementation is meant to be fast, but not as fast as possible.
14  * Some known optimizations are not included to reduce source code size
15  * and avoid compile-time configuration.
16  */
17
18 #include <string.h>
19 #include "md5.h"
20
21
22 /*
23  * The basic MD5 functions.
24  *
25  * F is optimized compared to its RFC 1321 definition just like in Colin
26  * Plumb's implementation.
27  */
28 #define F(x, y, z)                      ((z) ^ ((x) & ((y) ^ (z))))
29 #define G(x, y, z)                      ((y) ^ ((z) & ((x) ^ (y))))
30 #define H(x, y, z)                      ((x) ^ (y) ^ (z))
31 #define I(x, y, z)                      ((y) ^ ((x) | ~(z)))
32
33 /*
34  * The MD5 transformation for all four rounds.
35  */
36 #define STEP(f, a, b, c, d, x, t, s) \
37         (a) += f((b), (c), (d)) + (x) + (t); \
38         (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
39         (a) += (b);
40
41 /*
42  * SET reads 4 input bytes in little-endian byte order and stores them
43  * in a properly aligned word in host byte order.
44  *
45  * The check for little-endian architectures which tolerate unaligned
46  * memory accesses is just an optimization.  Nothing will break if it
47  * doesn't work.
48  */
49 #if defined(__i386__) || defined(__vax__)
50 #define SET(n) \
51         (*(MD5_u32plus *)&ptr[(n) * 4])
52 #define GET(n) \
53         SET(n)
54 #else
55 #define SET(n) \
56         (ctx->block[(n)] = \
57         (MD5_u32plus)ptr[(n) * 4] | \
58         ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
59         ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
60         ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
61 #define GET(n) \
62         (ctx->block[(n)])
63 #endif
64
65 /*
66  * This processes one or more 64-byte data blocks, but does NOT update
67  * the bit counters.  There're no alignment requirements.
68  */
69 static void *body(MD5_CTX *ctx, void *data, unsigned long size)
70 {
71         unsigned char *ptr;
72         MD5_u32plus a, b, c, d;
73         MD5_u32plus saved_a, saved_b, saved_c, saved_d;
74
75         ptr = data;
76
77         a = ctx->a;
78         b = ctx->b;
79         c = ctx->c;
80         d = ctx->d;
81
82         do {
83                 saved_a = a;
84                 saved_b = b;
85                 saved_c = c;
86                 saved_d = d;
87
88 /* Round 1 */
89                 STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
90                 STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
91                 STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
92                 STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
93                 STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
94                 STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
95                 STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
96                 STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
97                 STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
98                 STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
99                 STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
100                 STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
101                 STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
102                 STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
103                 STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
104                 STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
105
106 /* Round 2 */
107                 STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
108                 STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
109                 STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
110                 STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
111                 STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
112                 STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
113                 STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
114                 STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
115                 STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
116                 STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
117                 STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
118                 STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
119                 STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
120                 STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
121                 STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
122                 STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
123
124 /* Round 3 */
125                 STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
126                 STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
127                 STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
128                 STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
129                 STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
130                 STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
131                 STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
132                 STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
133                 STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
134                 STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
135                 STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
136                 STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
137                 STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
138                 STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
139                 STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
140                 STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
141
142 /* Round 4 */
143                 STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
144                 STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
145                 STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
146                 STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
147                 STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
148                 STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
149                 STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
150                 STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
151                 STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
152                 STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
153                 STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
154                 STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
155                 STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
156                 STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
157                 STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
158                 STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
159
160                 a += saved_a;
161                 b += saved_b;
162                 c += saved_c;
163                 d += saved_d;
164
165                 ptr += 64;
166         } while (size -= 64);
167
168         ctx->a = a;
169         ctx->b = b;
170         ctx->c = c;
171         ctx->d = d;
172
173         return ptr;
174 }
175
176 void solv_MD5_Init(MD5_CTX *ctx)
177 {
178         ctx->a = 0x67452301;
179         ctx->b = 0xefcdab89;
180         ctx->c = 0x98badcfe;
181         ctx->d = 0x10325476;
182
183         ctx->lo = 0;
184         ctx->hi = 0;
185 }
186
187 void solv_MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
188 {
189         MD5_u32plus saved_lo;
190         unsigned long used, free;
191
192         saved_lo = ctx->lo;
193         if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
194                 ctx->hi++;
195         ctx->hi += size >> 29;
196
197         used = saved_lo & 0x3f;
198
199         if (used) {
200                 free = 64 - used;
201
202                 if (size < free) {
203                         memcpy(&ctx->buffer[used], data, size);
204                         return;
205                 }
206
207                 memcpy(&ctx->buffer[used], data, free);
208                 data = (unsigned char *)data + free;
209                 size -= free;
210                 body(ctx, ctx->buffer, 64);
211         }
212
213         if (size >= 64) {
214                 data = body(ctx, data, size & ~(unsigned long)0x3f);
215                 size &= 0x3f;
216         }
217
218         memcpy(ctx->buffer, data, size);
219 }
220
221 void solv_MD5_Final(unsigned char *result, MD5_CTX *ctx)
222 {
223         unsigned long used, free;
224
225         used = ctx->lo & 0x3f;
226
227         ctx->buffer[used++] = 0x80;
228
229         free = 64 - used;
230
231         if (free < 8) {
232                 memset(&ctx->buffer[used], 0, free);
233                 body(ctx, ctx->buffer, 64);
234                 used = 0;
235                 free = 64;
236         }
237
238         memset(&ctx->buffer[used], 0, free - 8);
239
240         ctx->lo <<= 3;
241         ctx->buffer[56] = ctx->lo;
242         ctx->buffer[57] = ctx->lo >> 8;
243         ctx->buffer[58] = ctx->lo >> 16;
244         ctx->buffer[59] = ctx->lo >> 24;
245         ctx->buffer[60] = ctx->hi;
246         ctx->buffer[61] = ctx->hi >> 8;
247         ctx->buffer[62] = ctx->hi >> 16;
248         ctx->buffer[63] = ctx->hi >> 24;
249
250         body(ctx, ctx->buffer, 64);
251
252         result[0] = ctx->a;
253         result[1] = ctx->a >> 8;
254         result[2] = ctx->a >> 16;
255         result[3] = ctx->a >> 24;
256         result[4] = ctx->b;
257         result[5] = ctx->b >> 8;
258         result[6] = ctx->b >> 16;
259         result[7] = ctx->b >> 24;
260         result[8] = ctx->c;
261         result[9] = ctx->c >> 8;
262         result[10] = ctx->c >> 16;
263         result[11] = ctx->c >> 24;
264         result[12] = ctx->d;
265         result[13] = ctx->d >> 8;
266         result[14] = ctx->d >> 16;
267         result[15] = ctx->d >> 24;
268
269         memset(ctx, 0, sizeof(*ctx));
270 }