/src/libesedb/libesedb/libesedb_checksum.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Checksum functions |
3 | | * |
4 | | * Copyright (C) 2009-2023, Joachim Metz <joachim.metz@gmail.com> |
5 | | * |
6 | | * Refer to AUTHORS for acknowledgements. |
7 | | * |
8 | | * This program is free software: you can redistribute it and/or modify |
9 | | * it under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation, either version 3 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include <common.h> |
23 | | #include <byte_stream.h> |
24 | | #include <types.h> |
25 | | |
26 | | #include "libesedb_checksum.h" |
27 | | #include "libesedb_libcerror.h" |
28 | | |
29 | | /* The largest primary (or scalar) available |
30 | | * supported by a single load and store instruction |
31 | | */ |
32 | | typedef unsigned long int libesedb_aligned_t; |
33 | | |
34 | | /* The ECC-32 mask lookup table |
35 | | */ |
36 | | const uint8_t libesedb_checksum_ecc32_include_lookup_table[ 256 ] = { |
37 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
38 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
39 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
40 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
41 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
42 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
43 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
44 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
45 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
46 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
47 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
48 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
49 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, |
50 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
51 | | 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, |
52 | | 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 |
53 | | }; |
54 | | |
55 | | /* Calculates the little-endian ECC-32 and XOR-32 of a buffer |
56 | | * It uses the initial value to calculate a new XOR-32 |
57 | | * Returns 1 if successful or -1 on error |
58 | | */ |
59 | | int libesedb_checksum_calculate_little_endian_ecc32( |
60 | | uint32_t *ecc_checksum_value, |
61 | | uint32_t *xor_checksum_value, |
62 | | const uint8_t *buffer, |
63 | | size_t size, |
64 | | size_t offset, |
65 | | uint32_t initial_value, |
66 | | libcerror_error_t **error ) |
67 | 2.27k | { |
68 | 2.27k | static char *function = "libesedb_checksum_calculate_little_endian_ecc32"; |
69 | 2.27k | size_t buffer_iterator = 0; |
70 | 2.27k | size_t buffer_alignment = 0; |
71 | 2.27k | uint32_t bitmask = 0; |
72 | 2.27k | uint32_t bit_iterator = 0; |
73 | 2.27k | uint32_t final_bitmask = 0; |
74 | 2.27k | uint32_t value_32bit = 0; |
75 | 2.27k | uint32_t xor32_value = 0; |
76 | 2.27k | uint32_t xor32_vertical_first = 0; |
77 | 2.27k | uint32_t xor32_vertical_second = 0; |
78 | 2.27k | uint32_t xor32_vertical_third = 0; |
79 | 2.27k | uint32_t xor32_vertical_fourth = 0; |
80 | 2.27k | uint8_t mask_table_index = 0; |
81 | | |
82 | 2.27k | if( ecc_checksum_value == NULL ) |
83 | 0 | { |
84 | 0 | libcerror_error_set( |
85 | 0 | error, |
86 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
87 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
88 | 0 | "%s: invalid ECC checksum value.", |
89 | 0 | function ); |
90 | |
|
91 | 0 | return( -1 ); |
92 | 0 | } |
93 | 2.27k | if( xor_checksum_value == NULL ) |
94 | 0 | { |
95 | 0 | libcerror_error_set( |
96 | 0 | error, |
97 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
98 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
99 | 0 | "%s: invalid XOR checksum value.", |
100 | 0 | function ); |
101 | |
|
102 | 0 | return( -1 ); |
103 | 0 | } |
104 | 2.27k | if( buffer == NULL ) |
105 | 0 | { |
106 | 0 | libcerror_error_set( |
107 | 0 | error, |
108 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
109 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
110 | 0 | "%s: invalid buffer.", |
111 | 0 | function ); |
112 | |
|
113 | 0 | return( -1 ); |
114 | 0 | } |
115 | 2.27k | if( size > (size_t) SSIZE_MAX ) |
116 | 0 | { |
117 | 0 | libcerror_error_set( |
118 | 0 | error, |
119 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
120 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
121 | 0 | "%s: invalid size value exceeds maximum.", |
122 | 0 | function ); |
123 | |
|
124 | 0 | return( -1 ); |
125 | 0 | } |
126 | 2.27k | if( offset > size ) |
127 | 0 | { |
128 | 0 | libcerror_error_set( |
129 | 0 | error, |
130 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
131 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS, |
132 | 0 | "%s: invalid offset value out of bounds.", |
133 | 0 | function ); |
134 | |
|
135 | 0 | return( -1 ); |
136 | 0 | } |
137 | 2.27k | buffer_alignment = offset % 16; |
138 | | |
139 | 2.27k | if( ( buffer_alignment % sizeof( uint32_t ) ) != 0 ) |
140 | 0 | { |
141 | 0 | libcerror_error_set( |
142 | 0 | error, |
143 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
144 | 0 | LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE, |
145 | 0 | "%s: offset is not 32-bit aligned.", |
146 | 0 | function ); |
147 | |
|
148 | 0 | return( -1 ); |
149 | 0 | } |
150 | 2.27k | *ecc_checksum_value = 0; |
151 | 2.27k | *xor_checksum_value = initial_value; |
152 | 2.27k | bitmask = 0xff800000UL; |
153 | 2.27k | buffer += offset; |
154 | | |
155 | 2.27k | for( buffer_iterator = offset; |
156 | 1.16M | buffer_iterator < size; |
157 | 1.16M | buffer_iterator += 4 ) |
158 | 1.16M | { |
159 | 1.16M | byte_stream_copy_to_uint32_little_endian( |
160 | 1.16M | buffer, |
161 | 1.16M | value_32bit ); |
162 | | |
163 | 1.16M | if( buffer_alignment == 0 ) |
164 | 289k | { |
165 | 289k | xor32_vertical_first ^= value_32bit; |
166 | 289k | } |
167 | 873k | else if( buffer_alignment == 4 ) |
168 | 289k | { |
169 | 289k | xor32_vertical_second ^= value_32bit; |
170 | 289k | } |
171 | 583k | else if( buffer_alignment == 8 ) |
172 | 291k | { |
173 | 291k | xor32_vertical_third ^= value_32bit; |
174 | 291k | } |
175 | 291k | else |
176 | 291k | { |
177 | 291k | xor32_vertical_fourth ^= value_32bit; |
178 | 291k | } |
179 | 1.16M | xor32_value ^= value_32bit; |
180 | 1.16M | buffer += 4; |
181 | 1.16M | buffer_alignment += 4; |
182 | | |
183 | 1.16M | if( buffer_alignment >= 16 ) |
184 | 291k | { |
185 | 291k | mask_table_index = ( xor32_value & 0xff ); |
186 | 291k | xor32_value >>= 8; |
187 | 291k | mask_table_index ^= ( xor32_value & 0xff ); |
188 | 291k | xor32_value >>= 8; |
189 | 291k | mask_table_index ^= ( xor32_value & 0xff ); |
190 | 291k | xor32_value >>= 8; |
191 | 291k | mask_table_index ^= ( xor32_value & 0xff ); |
192 | | |
193 | 291k | if( libesedb_checksum_ecc32_include_lookup_table[ mask_table_index ] != 0 ) |
194 | 100k | { |
195 | 100k | *ecc_checksum_value ^= bitmask; |
196 | 100k | } |
197 | 291k | bitmask -= 0x007fff80UL; |
198 | 291k | buffer_alignment = 0; |
199 | 291k | xor32_value = 0; |
200 | 291k | } |
201 | 1.16M | } |
202 | 2.27k | if( xor32_value != 0 ) |
203 | 0 | { |
204 | 0 | mask_table_index = ( xor32_value & 0xff ); |
205 | 0 | xor32_value >>= 8; |
206 | 0 | mask_table_index ^= ( xor32_value & 0xff ); |
207 | 0 | xor32_value >>= 8; |
208 | 0 | mask_table_index ^= ( xor32_value & 0xff ); |
209 | 0 | xor32_value >>= 8; |
210 | 0 | mask_table_index ^= ( xor32_value & 0xff ); |
211 | |
|
212 | 0 | if( libesedb_checksum_ecc32_include_lookup_table[ mask_table_index ] != 0 ) |
213 | 0 | { |
214 | 0 | *ecc_checksum_value ^= bitmask; |
215 | 0 | } |
216 | 0 | } |
217 | | /* Determine the checksum part of the combination of |
218 | | * the first and second vertical XOR |
219 | | */ |
220 | 2.27k | xor32_value = xor32_vertical_first; |
221 | 2.27k | xor32_value ^= xor32_vertical_second; |
222 | | |
223 | 2.27k | mask_table_index = ( xor32_value & 0xff ); |
224 | 2.27k | xor32_value >>= 8; |
225 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
226 | 2.27k | xor32_value >>= 8; |
227 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
228 | 2.27k | xor32_value >>= 8; |
229 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
230 | | |
231 | 2.27k | if( libesedb_checksum_ecc32_include_lookup_table[ mask_table_index ] != 0 ) |
232 | 1.05k | { |
233 | 1.05k | *ecc_checksum_value ^= 0x00400000UL; |
234 | 1.05k | } |
235 | | /* Determine the checksum part of the combination of |
236 | | * the first and third vertical XOR |
237 | | */ |
238 | 2.27k | xor32_value = xor32_vertical_first; |
239 | 2.27k | xor32_value ^= xor32_vertical_third; |
240 | | |
241 | 2.27k | mask_table_index = ( xor32_value & 0xff ); |
242 | 2.27k | xor32_value >>= 8; |
243 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
244 | 2.27k | xor32_value >>= 8; |
245 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
246 | 2.27k | xor32_value >>= 8; |
247 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
248 | | |
249 | 2.27k | if( libesedb_checksum_ecc32_include_lookup_table[ mask_table_index ] != 0 ) |
250 | 981 | { |
251 | 981 | *ecc_checksum_value ^= 0x00200000UL; |
252 | 981 | } |
253 | | /* Determine the checksum part of the combination of |
254 | | * the second and fourth vertical XOR |
255 | | */ |
256 | 2.27k | xor32_value = xor32_vertical_second; |
257 | 2.27k | xor32_value ^= xor32_vertical_fourth; |
258 | | |
259 | 2.27k | mask_table_index = ( xor32_value & 0xff ); |
260 | 2.27k | xor32_value >>= 8; |
261 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
262 | 2.27k | xor32_value >>= 8; |
263 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
264 | 2.27k | xor32_value >>= 8; |
265 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
266 | | |
267 | 2.27k | if( libesedb_checksum_ecc32_include_lookup_table[ mask_table_index ] != 0 ) |
268 | 1.10k | { |
269 | 1.10k | *ecc_checksum_value ^= 0x00000020UL; |
270 | 1.10k | } |
271 | | /* Determine the checksum part of the combination of |
272 | | * the third and fourth vertical XOR |
273 | | */ |
274 | 2.27k | xor32_value = xor32_vertical_third; |
275 | 2.27k | xor32_value ^= xor32_vertical_fourth; |
276 | | |
277 | 2.27k | mask_table_index = ( xor32_value & 0xff ); |
278 | 2.27k | xor32_value >>= 8; |
279 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
280 | 2.27k | xor32_value >>= 8; |
281 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
282 | 2.27k | xor32_value >>= 8; |
283 | 2.27k | mask_table_index ^= ( xor32_value & 0xff ); |
284 | | |
285 | 2.27k | if( libesedb_checksum_ecc32_include_lookup_table[ mask_table_index ] != 0 ) |
286 | 1.10k | { |
287 | 1.10k | *ecc_checksum_value ^= 0x00000040UL; |
288 | 1.10k | } |
289 | | /* Determine the XOR-32 |
290 | | */ |
291 | 2.27k | xor32_value = xor32_vertical_first; |
292 | 2.27k | xor32_value ^= xor32_vertical_second; |
293 | 2.27k | xor32_value ^= xor32_vertical_third; |
294 | 2.27k | xor32_value ^= xor32_vertical_fourth; |
295 | | |
296 | | /* Determine the final bitmask |
297 | | */ |
298 | 2.27k | bitmask = 0xffff0000UL; |
299 | 2.27k | final_bitmask = 0; |
300 | | |
301 | 2.27k | for( bit_iterator = 1; |
302 | 75.0k | bit_iterator != 0; |
303 | 72.8k | bit_iterator <<= 1 ) |
304 | 72.8k | { |
305 | 72.8k | if( ( xor32_value & bit_iterator ) != 0 ) |
306 | 36.2k | { |
307 | 36.2k | final_bitmask ^= bitmask; |
308 | 36.2k | } |
309 | 72.8k | bitmask -= 0x0000ffffUL; |
310 | 72.8k | } |
311 | | /* Determine the buffer size bitmask |
312 | | */ |
313 | 2.27k | if( size < 8192 ) |
314 | 2.27k | { |
315 | 2.27k | *ecc_checksum_value &= 0xffffffffUL ^ (uint32_t) ( size << 19 ); |
316 | 2.27k | } |
317 | 2.27k | *ecc_checksum_value ^= ( *ecc_checksum_value ^ final_bitmask ) & 0x001f001fUL; |
318 | 2.27k | *xor_checksum_value ^= xor32_value; |
319 | | |
320 | 2.27k | return( 1 ); |
321 | 2.27k | } |
322 | | |
323 | | /* Calculates the little-endian XOR-32 of a buffer |
324 | | * It uses the initial value to calculate a new XOR-32 |
325 | | * Returns 1 if successful or -1 on error |
326 | | */ |
327 | | int libesedb_checksum_calculate_little_endian_xor32( |
328 | | uint32_t *checksum_value, |
329 | | const uint8_t *buffer, |
330 | | size_t size, |
331 | | uint32_t initial_value, |
332 | | libcerror_error_t **error ) |
333 | 16.7k | { |
334 | 16.7k | libesedb_aligned_t *aligned_buffer_iterator = NULL; |
335 | 16.7k | uint8_t *buffer_iterator = NULL; |
336 | 16.7k | static char *function = "libesedb_checksum_calculate_little_endian_xor32"; |
337 | 16.7k | libesedb_aligned_t value_aligned = 0; |
338 | 16.7k | uint32_t big_endian_value_32bit = 0; |
339 | 16.7k | uint32_t safe_checksum_value = 0; |
340 | 16.7k | uint32_t value_32bit = 0; |
341 | 16.7k | uint8_t alignment_count = 0; |
342 | 16.7k | uint8_t alignment_size = 0; |
343 | 16.7k | uint8_t byte_count = 0; |
344 | 16.7k | uint8_t byte_order = 0; |
345 | 16.7k | uint8_t byte_size = 0; |
346 | | |
347 | 16.7k | if( checksum_value == NULL ) |
348 | 0 | { |
349 | 0 | libcerror_error_set( |
350 | 0 | error, |
351 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
352 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
353 | 0 | "%s: invalid checksum value.", |
354 | 0 | function ); |
355 | |
|
356 | 0 | return( -1 ); |
357 | 0 | } |
358 | 16.7k | if( buffer == NULL ) |
359 | 0 | { |
360 | 0 | libcerror_error_set( |
361 | 0 | error, |
362 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
363 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
364 | 0 | "%s: invalid buffer.", |
365 | 0 | function ); |
366 | |
|
367 | 0 | return( -1 ); |
368 | 0 | } |
369 | 16.7k | if( size > (size_t) SSIZE_MAX ) |
370 | 0 | { |
371 | 0 | libcerror_error_set( |
372 | 0 | error, |
373 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
374 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM, |
375 | 0 | "%s: invalid size value exceeds maximum.", |
376 | 0 | function ); |
377 | |
|
378 | 0 | return( -1 ); |
379 | 0 | } |
380 | 16.7k | safe_checksum_value = initial_value; |
381 | | |
382 | 16.7k | buffer_iterator = (uint8_t *) buffer; |
383 | | |
384 | | /* Only optimize when there is the alignment is a multitude of 32-bit |
385 | | * and for buffers larger than the alignment |
386 | | */ |
387 | 16.7k | if( ( ( sizeof( libesedb_aligned_t ) % 4 ) == 0 ) |
388 | 16.7k | && ( size > ( 2 * sizeof( libesedb_aligned_t ) ) ) ) |
389 | 16.7k | { |
390 | | /* Align the buffer iterator |
391 | | */ |
392 | 16.7k | alignment_size = (uint8_t) ( (intptr_t) buffer_iterator % sizeof( libesedb_aligned_t ) ); |
393 | | |
394 | 16.7k | if( alignment_size > 0 ) |
395 | 16.7k | { |
396 | 16.7k | byte_size = sizeof( libesedb_aligned_t ) - alignment_size; |
397 | | |
398 | | /* Align the buffer iterator in 4-byte steps |
399 | | */ |
400 | 33.5k | while( byte_size != 0 ) |
401 | 16.7k | { |
402 | 16.7k | value_32bit = 0; |
403 | 16.7k | byte_count = 1; |
404 | | |
405 | 16.7k | if( byte_size >= 4 ) |
406 | 16.7k | { |
407 | 16.7k | value_32bit |= buffer_iterator[ 3 ]; |
408 | 16.7k | value_32bit <<= 8; |
409 | | |
410 | 16.7k | byte_count++; |
411 | 16.7k | } |
412 | 16.7k | if( byte_size >= 3 ) |
413 | 16.7k | { |
414 | 16.7k | value_32bit |= buffer_iterator[ 2 ]; |
415 | 16.7k | value_32bit <<= 8; |
416 | | |
417 | 16.7k | byte_count++; |
418 | 16.7k | } |
419 | 16.7k | if( byte_size >= 2 ) |
420 | 16.7k | { |
421 | 16.7k | value_32bit |= buffer_iterator[ 1 ]; |
422 | 16.7k | value_32bit <<= 8; |
423 | | |
424 | 16.7k | byte_count++; |
425 | 16.7k | } |
426 | 16.7k | value_32bit |= buffer_iterator[ 0 ]; |
427 | | |
428 | 16.7k | buffer_iterator += byte_count; |
429 | 16.7k | byte_size -= byte_count; |
430 | | |
431 | 16.7k | safe_checksum_value ^= value_32bit; |
432 | 16.7k | } |
433 | 16.7k | size -= byte_count; |
434 | 16.7k | } |
435 | 16.7k | aligned_buffer_iterator = (libesedb_aligned_t *) buffer_iterator; |
436 | | |
437 | 16.7k | if( *buffer_iterator != (uint8_t) ( *aligned_buffer_iterator & 0xff ) ) |
438 | 0 | { |
439 | 0 | byte_order = _BYTE_STREAM_ENDIAN_BIG; |
440 | 0 | } |
441 | 16.7k | else |
442 | 16.7k | { |
443 | 16.7k | byte_order = _BYTE_STREAM_ENDIAN_LITTLE; |
444 | 16.7k | } |
445 | | /* Calculate the XOR value using the aligned buffer iterator |
446 | | */ |
447 | 2.12M | while( size > sizeof( libesedb_aligned_t ) ) |
448 | 2.11M | { |
449 | 2.11M | value_aligned ^= *aligned_buffer_iterator; |
450 | | |
451 | 2.11M | aligned_buffer_iterator++; |
452 | | |
453 | 2.11M | size -= sizeof( libesedb_aligned_t ); |
454 | 2.11M | } |
455 | | /* Align the aligned XOR value with the 32-bit XOR value |
456 | | */ |
457 | 16.7k | if( alignment_size > 0 ) |
458 | 16.7k | { |
459 | 16.7k | byte_count = ( alignment_size % 4 ) * 8; |
460 | 16.7k | alignment_count = ( sizeof( libesedb_aligned_t ) - alignment_size ) * 8; |
461 | | |
462 | 16.7k | if( byte_order == _BYTE_STREAM_ENDIAN_BIG ) |
463 | 0 | { |
464 | | /* Shift twice to set unused bytes to 0 |
465 | | */ |
466 | 0 | big_endian_value_32bit = (uint32_t) ( ( value_aligned >> alignment_count ) << byte_count ); |
467 | | |
468 | | /* Change big-endian into little-endian |
469 | | */ |
470 | 0 | value_32bit = ( ( big_endian_value_32bit & 0x000000ffUL ) << 24 ) |
471 | 0 | | ( ( big_endian_value_32bit & 0x0000ff00UL ) << 8 ) |
472 | 0 | | ( ( big_endian_value_32bit >> 8 ) & 0x0000ff00UL ) |
473 | 0 | | ( ( big_endian_value_32bit >> 24 ) & 0x000000ffUL ); |
474 | | |
475 | | /* Strip-off the used part of the aligned value |
476 | | */ |
477 | 0 | value_aligned <<= alignment_count; |
478 | 0 | } |
479 | 16.7k | else if( byte_order == _BYTE_STREAM_ENDIAN_LITTLE ) |
480 | 16.7k | { |
481 | 16.7k | value_32bit = (uint32_t) ( value_aligned << byte_count ); |
482 | | |
483 | | /* Strip-off the used part of the aligned value |
484 | | */ |
485 | 16.7k | value_aligned >>= alignment_count; |
486 | 16.7k | } |
487 | 16.7k | safe_checksum_value ^= value_32bit; |
488 | 16.7k | } |
489 | | /* Update the 32-bit XOR value with the aligned XOR value |
490 | | */ |
491 | 16.7k | byte_size = (uint8_t) sizeof( libesedb_aligned_t ); |
492 | | |
493 | 50.2k | while( byte_size != 0 ) |
494 | 33.5k | { |
495 | 33.5k | byte_count = ( ( byte_size / 4 ) - 1 ) * 32; |
496 | | |
497 | 33.5k | if( byte_order == _BYTE_STREAM_ENDIAN_BIG ) |
498 | 0 | { |
499 | 0 | big_endian_value_32bit = (uint32_t) ( ( value_aligned >> byte_count ) & 0xffffffffUL ); |
500 | | |
501 | | /* Change big-endian into little-endian |
502 | | */ |
503 | 0 | value_32bit = ( ( big_endian_value_32bit & 0x000000ffUL ) << 24 ) |
504 | 0 | | ( ( big_endian_value_32bit & 0x0000ff00UL ) << 8 ) |
505 | 0 | | ( ( big_endian_value_32bit >> 8 ) & 0x0000ff00UL ) |
506 | 0 | | ( ( big_endian_value_32bit >> 24 ) & 0x000000ffUL ); |
507 | 0 | } |
508 | 33.5k | else if( byte_order == _BYTE_STREAM_ENDIAN_LITTLE ) |
509 | 33.5k | { |
510 | 33.5k | value_32bit = (uint32_t) value_aligned; |
511 | | |
512 | 33.5k | value_aligned >>= byte_count; |
513 | 33.5k | } |
514 | 33.5k | byte_size -= 4; |
515 | | |
516 | 33.5k | safe_checksum_value ^= value_32bit; |
517 | 33.5k | } |
518 | | /* Re-align the buffer iterator |
519 | | */ |
520 | 16.7k | buffer_iterator = (uint8_t *) aligned_buffer_iterator; |
521 | | |
522 | 16.7k | byte_size = 4 - ( alignment_size % 4 ); |
523 | | |
524 | 16.7k | if( byte_size != 4 ) |
525 | 0 | { |
526 | 0 | value_32bit = buffer_iterator[ 0 ]; |
527 | 0 | value_32bit <<= 8; |
528 | |
|
529 | 0 | if( byte_size >= 2 ) |
530 | 0 | { |
531 | 0 | value_32bit |= buffer_iterator[ 1 ]; |
532 | 0 | } |
533 | 0 | value_32bit <<= 8; |
534 | |
|
535 | 0 | if( byte_size >= 3 ) |
536 | 0 | { |
537 | 0 | value_32bit |= buffer_iterator[ 2 ]; |
538 | 0 | } |
539 | 0 | value_32bit <<= 8; |
540 | |
|
541 | 0 | buffer_iterator += byte_size; |
542 | 0 | size -= byte_size; |
543 | |
|
544 | 0 | safe_checksum_value ^= value_32bit; |
545 | 0 | } |
546 | 16.7k | } |
547 | 37.6k | while( size > 0 ) |
548 | 20.8k | { |
549 | 20.8k | value_32bit = 0; |
550 | 20.8k | byte_count = 1; |
551 | | |
552 | 20.8k | if( size >= 4 ) |
553 | 20.8k | { |
554 | 20.8k | value_32bit |= buffer_iterator[ 3 ]; |
555 | 20.8k | value_32bit <<= 8; |
556 | | |
557 | 20.8k | byte_count++; |
558 | 20.8k | } |
559 | 20.8k | if( size >= 3 ) |
560 | 20.8k | { |
561 | 20.8k | value_32bit |= buffer_iterator[ 2 ]; |
562 | 20.8k | value_32bit <<= 8; |
563 | | |
564 | 20.8k | byte_count++; |
565 | 20.8k | } |
566 | 20.8k | if( size >= 2 ) |
567 | 20.8k | { |
568 | 20.8k | value_32bit |= buffer_iterator[ 1 ]; |
569 | 20.8k | value_32bit <<= 8; |
570 | | |
571 | 20.8k | byte_count++; |
572 | 20.8k | } |
573 | 20.8k | value_32bit |= buffer_iterator[ 0 ]; |
574 | | |
575 | 20.8k | buffer_iterator += byte_count; |
576 | 20.8k | size -= byte_count; |
577 | | |
578 | 20.8k | safe_checksum_value ^= value_32bit; |
579 | 20.8k | } |
580 | 16.7k | *checksum_value = safe_checksum_value; |
581 | | |
582 | 16.7k | return( 1 ); |
583 | 16.7k | } |
584 | | |