Rename pmdb_t to alpm_db_t
[pacman-ng.git] / lib / libalpm / md5.c
blob90635046c50d5cff0ad3f737da16f81fe2c5a818
1 /*
2 * RFC 1321 compliant MD5 implementation
4 * Copyright (C) 2006-2007 Christophe Devine
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * The MD5 algorithm was designed by Ron Rivest in 1991.
22 * http://www.ietf.org/rfc/rfc1321.txt
25 * Pacman Notes:
27 * Taken from the XySSL project at www.xyssl.org under terms of the
28 * GPL. This is from version 0.9 of the library, and has been modified
29 * as following, which may be helpful for future updates:
30 * * remove "xyssl/config.h" include
31 * * change include from "xyssl/md5.h" to "md5.h"
32 * * removal of HMAC code
33 * * removal of SELF_TEST code
34 * * removal of ipad and opad from the md5_context struct in md5.h
35 * * change of md5_file prototype from
36 * int md5_file( char *path, unsigned char *output )
37 * to
38 * int md5_file( const char *path, unsigned char *output )
39 * * use a dynamically-allocated buffer in md5_file, and increase the size
40 * for performance reasons
41 * * various static/inline changes
43 * NOTE: XySSL has been renamed to PolarSSL, which is available at
44 * www.polarssl.org. If we update, we should get it from there.
47 #include <string.h>
48 #include <stdio.h>
49 #include <stdlib.h>
51 #include "md5.h"
54 * 32-bit integer manipulation macros (little endian)
56 #ifndef GET_ULONG_LE
57 #define GET_ULONG_LE(n,b,i) \
58 { \
59 (n) = ( (unsigned long) (b)[(i) ] ) \
60 | ( (unsigned long) (b)[(i) + 1] << 8 ) \
61 | ( (unsigned long) (b)[(i) + 2] << 16 ) \
62 | ( (unsigned long) (b)[(i) + 3] << 24 ); \
64 #endif
66 #ifndef PUT_ULONG_LE
67 #define PUT_ULONG_LE(n,b,i) \
68 { \
69 (b)[(i) ] = (unsigned char) ( (n) ); \
70 (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
71 (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
72 (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
74 #endif
77 * MD5 context setup
79 static inline void md5_starts( md5_context *ctx )
81 ctx->total[0] = 0;
82 ctx->total[1] = 0;
84 ctx->state[0] = 0x67452301;
85 ctx->state[1] = 0xEFCDAB89;
86 ctx->state[2] = 0x98BADCFE;
87 ctx->state[3] = 0x10325476;
90 static inline void md5_process( md5_context *ctx, unsigned char data[64] )
92 unsigned long X[16], A, B, C, D;
94 GET_ULONG_LE( X[ 0], data, 0 );
95 GET_ULONG_LE( X[ 1], data, 4 );
96 GET_ULONG_LE( X[ 2], data, 8 );
97 GET_ULONG_LE( X[ 3], data, 12 );
98 GET_ULONG_LE( X[ 4], data, 16 );
99 GET_ULONG_LE( X[ 5], data, 20 );
100 GET_ULONG_LE( X[ 6], data, 24 );
101 GET_ULONG_LE( X[ 7], data, 28 );
102 GET_ULONG_LE( X[ 8], data, 32 );
103 GET_ULONG_LE( X[ 9], data, 36 );
104 GET_ULONG_LE( X[10], data, 40 );
105 GET_ULONG_LE( X[11], data, 44 );
106 GET_ULONG_LE( X[12], data, 48 );
107 GET_ULONG_LE( X[13], data, 52 );
108 GET_ULONG_LE( X[14], data, 56 );
109 GET_ULONG_LE( X[15], data, 60 );
111 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
113 #define P(a,b,c,d,k,s,t) \
115 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
118 A = ctx->state[0];
119 B = ctx->state[1];
120 C = ctx->state[2];
121 D = ctx->state[3];
123 #define F(x,y,z) (z ^ (x & (y ^ z)))
125 P( A, B, C, D, 0, 7, 0xD76AA478 );
126 P( D, A, B, C, 1, 12, 0xE8C7B756 );
127 P( C, D, A, B, 2, 17, 0x242070DB );
128 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
129 P( A, B, C, D, 4, 7, 0xF57C0FAF );
130 P( D, A, B, C, 5, 12, 0x4787C62A );
131 P( C, D, A, B, 6, 17, 0xA8304613 );
132 P( B, C, D, A, 7, 22, 0xFD469501 );
133 P( A, B, C, D, 8, 7, 0x698098D8 );
134 P( D, A, B, C, 9, 12, 0x8B44F7AF );
135 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
136 P( B, C, D, A, 11, 22, 0x895CD7BE );
137 P( A, B, C, D, 12, 7, 0x6B901122 );
138 P( D, A, B, C, 13, 12, 0xFD987193 );
139 P( C, D, A, B, 14, 17, 0xA679438E );
140 P( B, C, D, A, 15, 22, 0x49B40821 );
142 #undef F
144 #define F(x,y,z) (y ^ (z & (x ^ y)))
146 P( A, B, C, D, 1, 5, 0xF61E2562 );
147 P( D, A, B, C, 6, 9, 0xC040B340 );
148 P( C, D, A, B, 11, 14, 0x265E5A51 );
149 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
150 P( A, B, C, D, 5, 5, 0xD62F105D );
151 P( D, A, B, C, 10, 9, 0x02441453 );
152 P( C, D, A, B, 15, 14, 0xD8A1E681 );
153 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
154 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
155 P( D, A, B, C, 14, 9, 0xC33707D6 );
156 P( C, D, A, B, 3, 14, 0xF4D50D87 );
157 P( B, C, D, A, 8, 20, 0x455A14ED );
158 P( A, B, C, D, 13, 5, 0xA9E3E905 );
159 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
160 P( C, D, A, B, 7, 14, 0x676F02D9 );
161 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
163 #undef F
165 #define F(x,y,z) (x ^ y ^ z)
167 P( A, B, C, D, 5, 4, 0xFFFA3942 );
168 P( D, A, B, C, 8, 11, 0x8771F681 );
169 P( C, D, A, B, 11, 16, 0x6D9D6122 );
170 P( B, C, D, A, 14, 23, 0xFDE5380C );
171 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
172 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
173 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
174 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
175 P( A, B, C, D, 13, 4, 0x289B7EC6 );
176 P( D, A, B, C, 0, 11, 0xEAA127FA );
177 P( C, D, A, B, 3, 16, 0xD4EF3085 );
178 P( B, C, D, A, 6, 23, 0x04881D05 );
179 P( A, B, C, D, 9, 4, 0xD9D4D039 );
180 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
181 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
182 P( B, C, D, A, 2, 23, 0xC4AC5665 );
184 #undef F
186 #define F(x,y,z) (y ^ (x | ~z))
188 P( A, B, C, D, 0, 6, 0xF4292244 );
189 P( D, A, B, C, 7, 10, 0x432AFF97 );
190 P( C, D, A, B, 14, 15, 0xAB9423A7 );
191 P( B, C, D, A, 5, 21, 0xFC93A039 );
192 P( A, B, C, D, 12, 6, 0x655B59C3 );
193 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
194 P( C, D, A, B, 10, 15, 0xFFEFF47D );
195 P( B, C, D, A, 1, 21, 0x85845DD1 );
196 P( A, B, C, D, 8, 6, 0x6FA87E4F );
197 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
198 P( C, D, A, B, 6, 15, 0xA3014314 );
199 P( B, C, D, A, 13, 21, 0x4E0811A1 );
200 P( A, B, C, D, 4, 6, 0xF7537E82 );
201 P( D, A, B, C, 11, 10, 0xBD3AF235 );
202 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
203 P( B, C, D, A, 9, 21, 0xEB86D391 );
205 #undef F
207 ctx->state[0] += A;
208 ctx->state[1] += B;
209 ctx->state[2] += C;
210 ctx->state[3] += D;
214 * MD5 process buffer
216 static inline void md5_update( md5_context *ctx, unsigned char *input, int ilen )
218 int fill;
219 unsigned long left;
221 if( ilen <= 0 )
222 return;
224 left = ctx->total[0] & 0x3F;
225 fill = 64 - left;
227 ctx->total[0] += ilen;
228 ctx->total[0] &= 0xFFFFFFFF;
230 if( ctx->total[0] < (unsigned long) ilen )
231 ctx->total[1]++;
233 if( left && ilen >= fill )
235 memcpy( (void *) (ctx->buffer + left),
236 (void *) input, fill );
237 md5_process( ctx, ctx->buffer );
238 input += fill;
239 ilen -= fill;
240 left = 0;
243 while( ilen >= 64 )
245 md5_process( ctx, input );
246 input += 64;
247 ilen -= 64;
250 if( ilen > 0 )
252 memcpy( (void *) (ctx->buffer + left),
253 (void *) input, ilen );
257 static unsigned char md5_padding[64] =
259 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
262 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
266 * MD5 final digest
268 static inline void md5_finish( md5_context *ctx, unsigned char output[16] )
270 unsigned long last, padn;
271 unsigned long high, low;
272 unsigned char msglen[8];
274 high = ( ctx->total[0] >> 29 )
275 | ( ctx->total[1] << 3 );
276 low = ( ctx->total[0] << 3 );
278 PUT_ULONG_LE( low, msglen, 0 );
279 PUT_ULONG_LE( high, msglen, 4 );
281 last = ctx->total[0] & 0x3F;
282 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
284 md5_update( ctx, (unsigned char *) md5_padding, padn );
285 md5_update( ctx, msglen, 8 );
287 PUT_ULONG_LE( ctx->state[0], output, 0 );
288 PUT_ULONG_LE( ctx->state[1], output, 4 );
289 PUT_ULONG_LE( ctx->state[2], output, 8 );
290 PUT_ULONG_LE( ctx->state[3], output, 12 );
294 * output = MD5( input buffer )
296 void md5( unsigned char *input, int ilen, unsigned char output[16] )
298 md5_context ctx;
300 md5_starts( &ctx );
301 md5_update( &ctx, input, ilen );
302 md5_finish( &ctx, output );
304 memset( &ctx, 0, sizeof( md5_context ) );
308 * output = MD5( file contents )
310 int md5_file( const char *path, unsigned char output[16] )
312 FILE *f;
313 size_t n;
314 md5_context ctx;
315 unsigned char *buf;
317 if( ( buf = calloc(8192, sizeof(unsigned char)) ) == NULL )
318 return( 1 );
320 if( ( f = fopen( path, "rb" ) ) == NULL ) {
321 free( buf );
322 return( 1 );
325 md5_starts( &ctx );
327 while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
328 md5_update( &ctx, buf, (int) n );
330 md5_finish( &ctx, output );
332 memset( &ctx, 0, sizeof( md5_context ) );
333 free( buf );
335 if( ferror( f ) != 0 )
337 fclose( f );
338 return( 2 );
341 fclose( f );
342 return( 0 );