When autodetecting, don't segfault if no item was previously selected and a device...
[Rockbox.git] / rbutil / md5sum.cpp
blobe1c23c986792ff1bdb884bee16f32666b8cc986e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * Module: rbutil
9 * File: md5sum.cpp
11 * Copyright (C) 2007 Dominik Wenger
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
23 * RFC 1321 compliant MD5 implementation
25 * Copyright (C) 2001-2003 Christophe Devine
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License as published by
29 * the Free Software Foundation; either version 2 of the License, or
30 * (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43 #include "md5sum.h"
46 #define GET_UINT32(n,b,i) \
47 { \
48 (n) = ( (uint32) (b)[(i) ] ) \
49 | ( (uint32) (b)[(i) + 1] << 8 ) \
50 | ( (uint32) (b)[(i) + 2] << 16 ) \
51 | ( (uint32) (b)[(i) + 3] << 24 ); \
54 #define PUT_UINT32(n,b,i) \
55 { \
56 (b)[(i) ] = (uint8) ( (n) ); \
57 (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \
58 (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \
59 (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \
62 void md5_starts( md5_context *ctx )
64 ctx->total[0] = 0;
65 ctx->total[1] = 0;
67 ctx->state[0] = 0x67452301;
68 ctx->state[1] = 0xEFCDAB89;
69 ctx->state[2] = 0x98BADCFE;
70 ctx->state[3] = 0x10325476;
73 void md5_process( md5_context *ctx, uint8 data[64] )
75 uint32 X[16], A, B, C, D;
77 GET_UINT32( X[0], data, 0 );
78 GET_UINT32( X[1], data, 4 );
79 GET_UINT32( X[2], data, 8 );
80 GET_UINT32( X[3], data, 12 );
81 GET_UINT32( X[4], data, 16 );
82 GET_UINT32( X[5], data, 20 );
83 GET_UINT32( X[6], data, 24 );
84 GET_UINT32( X[7], data, 28 );
85 GET_UINT32( X[8], data, 32 );
86 GET_UINT32( X[9], data, 36 );
87 GET_UINT32( X[10], data, 40 );
88 GET_UINT32( X[11], data, 44 );
89 GET_UINT32( X[12], data, 48 );
90 GET_UINT32( X[13], data, 52 );
91 GET_UINT32( X[14], data, 56 );
92 GET_UINT32( X[15], data, 60 );
94 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
96 #define P(a,b,c,d,k,s,t) \
97 { \
98 a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
101 A = ctx->state[0];
102 B = ctx->state[1];
103 C = ctx->state[2];
104 D = ctx->state[3];
106 #define F(x,y,z) (z ^ (x & (y ^ z)))
108 P( A, B, C, D, 0, 7, 0xD76AA478 );
109 P( D, A, B, C, 1, 12, 0xE8C7B756 );
110 P( C, D, A, B, 2, 17, 0x242070DB );
111 P( B, C, D, A, 3, 22, 0xC1BDCEEE );
112 P( A, B, C, D, 4, 7, 0xF57C0FAF );
113 P( D, A, B, C, 5, 12, 0x4787C62A );
114 P( C, D, A, B, 6, 17, 0xA8304613 );
115 P( B, C, D, A, 7, 22, 0xFD469501 );
116 P( A, B, C, D, 8, 7, 0x698098D8 );
117 P( D, A, B, C, 9, 12, 0x8B44F7AF );
118 P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
119 P( B, C, D, A, 11, 22, 0x895CD7BE );
120 P( A, B, C, D, 12, 7, 0x6B901122 );
121 P( D, A, B, C, 13, 12, 0xFD987193 );
122 P( C, D, A, B, 14, 17, 0xA679438E );
123 P( B, C, D, A, 15, 22, 0x49B40821 );
125 #undef F
127 #define F(x,y,z) (y ^ (z & (x ^ y)))
129 P( A, B, C, D, 1, 5, 0xF61E2562 );
130 P( D, A, B, C, 6, 9, 0xC040B340 );
131 P( C, D, A, B, 11, 14, 0x265E5A51 );
132 P( B, C, D, A, 0, 20, 0xE9B6C7AA );
133 P( A, B, C, D, 5, 5, 0xD62F105D );
134 P( D, A, B, C, 10, 9, 0x02441453 );
135 P( C, D, A, B, 15, 14, 0xD8A1E681 );
136 P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
137 P( A, B, C, D, 9, 5, 0x21E1CDE6 );
138 P( D, A, B, C, 14, 9, 0xC33707D6 );
139 P( C, D, A, B, 3, 14, 0xF4D50D87 );
140 P( B, C, D, A, 8, 20, 0x455A14ED );
141 P( A, B, C, D, 13, 5, 0xA9E3E905 );
142 P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
143 P( C, D, A, B, 7, 14, 0x676F02D9 );
144 P( B, C, D, A, 12, 20, 0x8D2A4C8A );
146 #undef F
148 #define F(x,y,z) (x ^ y ^ z)
150 P( A, B, C, D, 5, 4, 0xFFFA3942 );
151 P( D, A, B, C, 8, 11, 0x8771F681 );
152 P( C, D, A, B, 11, 16, 0x6D9D6122 );
153 P( B, C, D, A, 14, 23, 0xFDE5380C );
154 P( A, B, C, D, 1, 4, 0xA4BEEA44 );
155 P( D, A, B, C, 4, 11, 0x4BDECFA9 );
156 P( C, D, A, B, 7, 16, 0xF6BB4B60 );
157 P( B, C, D, A, 10, 23, 0xBEBFBC70 );
158 P( A, B, C, D, 13, 4, 0x289B7EC6 );
159 P( D, A, B, C, 0, 11, 0xEAA127FA );
160 P( C, D, A, B, 3, 16, 0xD4EF3085 );
161 P( B, C, D, A, 6, 23, 0x04881D05 );
162 P( A, B, C, D, 9, 4, 0xD9D4D039 );
163 P( D, A, B, C, 12, 11, 0xE6DB99E5 );
164 P( C, D, A, B, 15, 16, 0x1FA27CF8 );
165 P( B, C, D, A, 2, 23, 0xC4AC5665 );
167 #undef F
169 #define F(x,y,z) (y ^ (x | ~z))
171 P( A, B, C, D, 0, 6, 0xF4292244 );
172 P( D, A, B, C, 7, 10, 0x432AFF97 );
173 P( C, D, A, B, 14, 15, 0xAB9423A7 );
174 P( B, C, D, A, 5, 21, 0xFC93A039 );
175 P( A, B, C, D, 12, 6, 0x655B59C3 );
176 P( D, A, B, C, 3, 10, 0x8F0CCC92 );
177 P( C, D, A, B, 10, 15, 0xFFEFF47D );
178 P( B, C, D, A, 1, 21, 0x85845DD1 );
179 P( A, B, C, D, 8, 6, 0x6FA87E4F );
180 P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
181 P( C, D, A, B, 6, 15, 0xA3014314 );
182 P( B, C, D, A, 13, 21, 0x4E0811A1 );
183 P( A, B, C, D, 4, 6, 0xF7537E82 );
184 P( D, A, B, C, 11, 10, 0xBD3AF235 );
185 P( C, D, A, B, 2, 15, 0x2AD7D2BB );
186 P( B, C, D, A, 9, 21, 0xEB86D391 );
188 #undef F
189 #undef S
190 #undef P
193 ctx->state[0] += A;
194 ctx->state[1] += B;
195 ctx->state[2] += C;
196 ctx->state[3] += D;
199 void md5_update( md5_context *ctx, uint8 *input, uint32 length )
201 uint32 left, fill;
203 if( ! length ) return;
205 left = ctx->total[0] & 0x3F;
206 fill = 64 - left;
208 ctx->total[0] += length;
209 ctx->total[0] &= 0xFFFFFFFF;
211 if( ctx->total[0] < length )
212 ctx->total[1]++;
214 if( left && length >= fill )
216 memcpy( (void *) (ctx->buffer + left),
217 (void *) input, fill );
218 md5_process( ctx, ctx->buffer );
219 length -= fill;
220 input += fill;
221 left = 0;
224 while( length >= 64 )
226 md5_process( ctx, input );
227 length -= 64;
228 input += 64;
231 if( length )
233 memcpy( (void *) (ctx->buffer + left),
234 (void *) input, length );
238 static uint8 md5_padding[64] =
240 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
242 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
243 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
246 void md5_finish( md5_context *ctx, uint8 digest[16] )
248 uint32 last, padn;
249 uint32 high, low;
250 uint8 msglen[8];
252 high = ( ctx->total[0] >> 29 )
253 | ( ctx->total[1] << 3 );
254 low = ( ctx->total[0] << 3 );
256 PUT_UINT32( low, msglen, 0 );
257 PUT_UINT32( high, msglen, 4 );
259 last = ctx->total[0] & 0x3F;
260 padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
262 md5_update( ctx, md5_padding, padn );
263 md5_update( ctx, msglen, 8 );
265 PUT_UINT32( ctx->state[0], digest, 0 );
266 PUT_UINT32( ctx->state[1], digest, 4 );
267 PUT_UINT32( ctx->state[2], digest, 8 );
268 PUT_UINT32( ctx->state[3], digest, 12 );
271 int FileMD5(wxString name, char *md5)
273 int i, read;
274 md5_context ctx;
275 unsigned char md5sum[16];
276 unsigned char block[32768];
278 wxFile file;
280 file.Open(name);
282 if (!file.IsOpened()) {
283 ERR_DIALOG(wxT("Could not open patched firmware for checksum check"), wxT("Open Firmware"));
284 return 0;
286 md5_starts(&ctx);
287 while ( !file.Eof() ) {
288 read = file.Read(block, sizeof(block));
289 md5_update(&ctx, block, read);
291 file.Close();
292 md5_finish(&ctx, md5sum);
293 for (i = 0; i < 16; ++i)
295 sprintf(md5 + 2*i, "%02x", md5sum[i]);
297 return 1;