1 /*
2 * MD5 functions
3 *
4 * Copyright (C) 2011-2020, 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 <memory.h>
25 #include <types.h>
26
27 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H )
28 #include <openssl/md5.h>
29
30 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H )
31 #include <openssl/err.h>
32 #include <openssl/evp.h>
33
34 #endif
35
36 #include "libhmac_byte_stream.h"
37 #include "libhmac_definitions.h"
38 #include "libhmac_libcerror.h"
39 #include "libhmac_md5.h"
40
41 #if !defined( LIBHMAC_HAVE_MD5_SUPPORT )
42
43 /* RFC 1321 based MD5 functions
44 */
45
46 /* TODO decription what these values are based on
47 */
48 uint32_t libhmac_md5_fixed_constants[ 4 ] = {
49 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
50 };
51
52 /* The first 32-bits of the sines (in radians) of the first 64 integers [ 0, 63 ]
53 */
54 uint32_t libhmac_md5_sines[ 64 ] = {
55 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL,
56 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
57 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL,
58 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
59 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL,
60 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
61 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL,
62 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
63 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL,
64 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
65 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL,
66 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
67 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL,
68 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
69 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL,
70 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL
71 };
72
73 /* The bit shifts
74 */
75 uint8_t libhmac_md5_bit_shifts[ 64 ] = {
76 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
77 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
78 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
79 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
80 };
81
82 /* The 32-bit values indexes
83 * [ 0, 15 ] => index
84 * [ 16, 31 ] => ( ( 5 x index ) + 1 ) mod 16
85 * [ 32, 47 ] => ( ( 3 x index ) + 5 ) mod 16
86 * [ 48, 63 ] => ( 7 x index ) mod 16
87 */
88 uint8_t libhmac_md5_values_32bit_index[ 64 ] = {
89 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
90 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
91 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
92 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
93 };
94
95 #define libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, value_32bit_index, hash_values, hash_value_index0, hash_value_index1, hash_value_index2, hash_value_index3, block_index ) \
96 hash_values[ hash_value_index0 ] += ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index2 ] ) \
97 | ( ~( hash_values[ hash_value_index1 ] ) & hash_values[ hash_value_index3 ] ); \
98 hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
99 hash_values[ hash_value_index0 ] += libhmac_md5_sines[ block_index ]; \
100 \
101 hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
102 hash_values[ hash_value_index0 ], \
103 libhmac_md5_bit_shifts[ block_index ] ); \
104 \
105 hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
106
107 #define libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, value_32bit_index, hash_values, hash_value_index0, hash_value_index1, hash_value_index2, hash_value_index3, block_index ) \
108 hash_values[ hash_value_index0 ] += ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index3 ] ) \
109 | ( hash_values[ hash_value_index2 ] & ~( hash_values[ hash_value_index3 ] ) ); \
110 hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
111 hash_values[ hash_value_index0 ] += libhmac_md5_sines[ block_index ]; \
112 \
113 hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
114 hash_values[ hash_value_index0 ], \
115 libhmac_md5_bit_shifts[ block_index ] ); \
116 \
117 hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
118
119 #define libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, value_32bit_index, hash_values, hash_value_index0, hash_value_index1, hash_value_index2, hash_value_index3, block_index ) \
120 hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ] \
121 ^ hash_values[ hash_value_index2 ] \
122 ^ hash_values[ hash_value_index3 ]; \
123 hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
124 hash_values[ hash_value_index0 ] += libhmac_md5_sines[ block_index ]; \
125 \
126 hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
127 hash_values[ hash_value_index0 ], \
128 libhmac_md5_bit_shifts[ block_index ] ); \
129 \
130 hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
131
132 #define libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, value_32bit_index, hash_values, hash_value_index0, hash_value_index1, hash_value_index2, hash_value_index3, block_index ) \
133 hash_values[ hash_value_index0 ] += hash_values[ hash_value_index2 ] \
134 ^ ( hash_values[ hash_value_index1 ] | ~( hash_values[ hash_value_index3 ] ) ); \
135 hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
136 hash_values[ hash_value_index0 ] += libhmac_md5_sines[ block_index ]; \
137 \
138 hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
139 hash_values[ hash_value_index0 ], \
140 libhmac_md5_bit_shifts[ block_index ] ); \
141 \
142 hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
143
144 #define libhmac_md5_transform_unfolded_calculate_hash_values( values_32bit, hash_values ) \
145 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 0, hash_values, 0, 1, 2, 3, 0 ); \
146 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 1, hash_values, 3, 0, 1, 2, 1 ); \
147 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 2, hash_values, 2, 3, 0, 1, 2 ); \
148 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 3, hash_values, 1, 2, 3, 0, 3 ); \
149 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 4, hash_values, 0, 1, 2, 3, 4 ); \
150 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 5, hash_values, 3, 0, 1, 2, 5 ); \
151 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 6, hash_values, 2, 3, 0, 1, 6 ); \
152 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 7, hash_values, 1, 2, 3, 0, 7 ); \
153 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 8, hash_values, 0, 1, 2, 3, 8 ); \
154 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 9, hash_values, 3, 0, 1, 2, 9 ); \
155 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 10, hash_values, 2, 3, 0, 1, 10 ); \
156 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 11, hash_values, 1, 2, 3, 0, 11 ); \
157 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 12, hash_values, 0, 1, 2, 3, 12 ); \
158 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 13, hash_values, 3, 0, 1, 2, 13 ); \
159 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 14, hash_values, 2, 3, 0, 1, 14 ); \
160 libhmac_md5_transform_unfolded_calculate_hash_value_round1( values_32bit, 15, hash_values, 1, 2, 3, 0, 15 ); \
161 \
162 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 1, hash_values, 0, 1, 2, 3, 16 ); \
163 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 6, hash_values, 3, 0, 1, 2, 17 ); \
164 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 11, hash_values, 2, 3, 0, 1, 18 ); \
165 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 0, hash_values, 1, 2, 3, 0, 19 ); \
166 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 5, hash_values, 0, 1, 2, 3, 20 ); \
167 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 10, hash_values, 3, 0, 1, 2, 21 ); \
168 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 15, hash_values, 2, 3, 0, 1, 22 ); \
169 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 4, hash_values, 1, 2, 3, 0, 23 ); \
170 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 9, hash_values, 0, 1, 2, 3, 24 ); \
171 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 14, hash_values, 3, 0, 1, 2, 25 ); \
172 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 3, hash_values, 2, 3, 0, 1, 26 ); \
173 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 8, hash_values, 1, 2, 3, 0, 27 ); \
174 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 13, hash_values, 0, 1, 2, 3, 28 ); \
175 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 2, hash_values, 3, 0, 1, 2, 29 ); \
176 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 7, hash_values, 2, 3, 0, 1, 30 ); \
177 libhmac_md5_transform_unfolded_calculate_hash_value_round2( values_32bit, 12, hash_values, 1, 2, 3, 0, 31 ); \
178 \
179 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 5, hash_values, 0, 1, 2, 3, 32 ); \
180 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 8, hash_values, 3, 0, 1, 2, 33 ); \
181 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 11, hash_values, 2, 3, 0, 1, 34 ); \
182 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 14, hash_values, 1, 2, 3, 0, 35 ); \
183 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 1, hash_values, 0, 1, 2, 3, 36 ); \
184 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 4, hash_values, 3, 0, 1, 2, 37 ); \
185 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 7, hash_values, 2, 3, 0, 1, 38 ); \
186 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 10, hash_values, 1, 2, 3, 0, 39 ); \
187 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 13, hash_values, 0, 1, 2, 3, 40 ); \
188 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 0, hash_values, 3, 0, 1, 2, 41 ); \
189 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 3, hash_values, 2, 3, 0, 1, 42 ); \
190 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 6, hash_values, 1, 2, 3, 0, 43 ); \
191 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 9, hash_values, 0, 1, 2, 3, 44 ); \
192 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 12, hash_values, 3, 0, 1, 2, 45 ); \
193 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 15, hash_values, 2, 3, 0, 1, 46 ); \
194 libhmac_md5_transform_unfolded_calculate_hash_value_round3( values_32bit, 2, hash_values, 1, 2, 3, 0, 47 ); \
195 \
196 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 0, hash_values, 0, 1, 2, 3, 48 ); \
197 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 7, hash_values, 3, 0, 1, 2, 49 ); \
198 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 14, hash_values, 2, 3, 0, 1, 50 ); \
199 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 5, hash_values, 1, 2, 3, 0, 51 ); \
200 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 12, hash_values, 0, 1, 2, 3, 52 ); \
201 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 3, hash_values, 3, 0, 1, 2, 53 ); \
202 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 10, hash_values, 2, 3, 0, 1, 54 ); \
203 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 1, hash_values, 1, 2, 3, 0, 55 ); \
204 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 8, hash_values, 0, 1, 2, 3, 56 ); \
205 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 15, hash_values, 3, 0, 1, 2, 57 ); \
206 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 6, hash_values, 2, 3, 0, 1, 58 ); \
207 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 13, hash_values, 1, 2, 3, 0, 59 ); \
208 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 4, hash_values, 0, 1, 2, 3, 60 ); \
209 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 11, hash_values, 3, 0, 1, 2, 61 ); \
210 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 2, hash_values, 2, 3, 0, 1, 62 ); \
211 libhmac_md5_transform_unfolded_calculate_hash_value_round4( values_32bit, 9, hash_values, 1, 2, 3, 0, 63 );
212
213 /* Calculates the MD5 of 64 byte sized blocks of data in a buffer
214 * Returns the number of bytes used if successful or -1 on error
215 */
libhmac_md5_transform(libhmac_internal_md5_context_t * internal_context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)216 ssize_t libhmac_md5_transform(
217 libhmac_internal_md5_context_t *internal_context,
218 const uint8_t *buffer,
219 size_t size,
220 libcerror_error_t **error )
221 {
222 uint32_t hash_values[ 4 ];
223 uint32_t values_32bit[ 16 ];
224
225 static char *function = "libhmac_md5_transform";
226 size_t buffer_offset = 0;
227
228 #if !defined( LIBHMAC_UNFOLLED_LOOPS )
229 uint32_t hash_value = 0;
230 uint8_t block_index = 0;
231 uint8_t hash_values_index = 0;
232 uint8_t value_32bit_index = 0;
233 #endif
234
235 if( internal_context == NULL )
236 {
237 libcerror_error_set(
238 error,
239 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241 "%s: invalid internal context.",
242 function );
243
244 return( -1 );
245 }
246 if( buffer == NULL )
247 {
248 libcerror_error_set(
249 error,
250 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252 "%s: invalid buffer.",
253 function );
254
255 return( -1 );
256 }
257 if( size > (size_t) SSIZE_MAX )
258 {
259 libcerror_error_set(
260 error,
261 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
263 "%s: invalid size value exceeds maximum.",
264 function );
265
266 return( -1 );
267 }
268 while( size >= LIBHMAC_MD5_BLOCK_SIZE )
269 {
270 if( memory_copy(
271 hash_values,
272 internal_context->hash_values,
273 sizeof( uint32_t ) * 4 ) == NULL )
274 {
275 libcerror_error_set(
276 error,
277 LIBCERROR_ERROR_DOMAIN_MEMORY,
278 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
279 "%s: unable to copy hash values.",
280 function );
281
282 goto on_error;
283 }
284 #if defined( LIBHMAC_UNFOLLED_LOOPS )
285 /* Break the block into 16 x 32-bit values
286 */
287 libhmac_byte_stream_copy_to_16x_uint32_little_endian(
288 &( buffer[ buffer_offset ] ),
289 values_32bit );
290
291 buffer_offset += LIBHMAC_MD5_BLOCK_SIZE;
292
293 /* Calculate the hash values for the 32-bit values
294 */
295 libhmac_md5_transform_unfolded_calculate_hash_values(
296 values_32bit,
297 hash_values );
298
299 /* Update the hash values in the context
300 */
301 internal_context->hash_values[ 0 ] += hash_values[ 0 ];
302 internal_context->hash_values[ 1 ] += hash_values[ 1 ];
303 internal_context->hash_values[ 2 ] += hash_values[ 2 ];
304 internal_context->hash_values[ 3 ] += hash_values[ 3 ];
305
306 #else
307 /* Break the block into 16 x 32-bit values
308 */
309 for( value_32bit_index = 0;
310 value_32bit_index < 16;
311 value_32bit_index++ )
312 {
313 byte_stream_copy_to_uint32_little_endian(
314 &( buffer[ buffer_offset ] ),
315 values_32bit[ value_32bit_index ] );
316
317 buffer_offset += sizeof( uint32_t );
318 }
319 /* Calculate the hash values for the 32-bit values
320 */
321 for( block_index = 0;
322 block_index < 64;
323 block_index++ )
324 {
325 if( block_index < 16 )
326 {
327 hash_values[ 0 ] += ( hash_values[ 1 ] & hash_values[ 2 ] )
328 | ( ~( hash_values[ 1 ] ) & hash_values[ 3 ] );
329 }
330 else if( block_index < 32 )
331 {
332 hash_values[ 0 ] += ( hash_values[ 1 ] & hash_values[ 3 ] )
333 | ( hash_values[ 2 ] & ~( hash_values[ 3 ] ) );
334 }
335 else if( block_index < 48 )
336 {
337 hash_values[ 0 ] += hash_values[ 1 ]
338 ^ hash_values[ 2 ]
339 ^ hash_values[ 3 ];
340 }
341 else
342 {
343 hash_values[ 0 ] += hash_values[ 2 ]
344 ^ ( hash_values[ 1 ] | ~( hash_values[ 3 ] ) );
345 }
346 value_32bit_index = libhmac_md5_values_32bit_index[ block_index ];
347
348 hash_values[ 0 ] += values_32bit[ value_32bit_index ];
349 hash_values[ 0 ] += libhmac_md5_sines[ block_index ];
350 hash_values[ 0 ] = byte_stream_bit_rotate_left_32bit(
351 hash_values[ 0 ],
352 libhmac_md5_bit_shifts[ block_index ] );
353
354 hash_value = hash_values[ 3 ];
355 hash_values[ 3 ] = hash_values[ 2 ];
356 hash_values[ 2 ] = hash_values[ 1 ];
357 hash_values[ 1 ] += hash_values[ 0 ];
358 hash_values[ 0 ] = hash_value;
359 }
360 /* Update the hash values in the context
361 */
362 for( hash_values_index = 0;
363 hash_values_index < 4;
364 hash_values_index++ )
365 {
366 internal_context->hash_values[ hash_values_index ] += hash_values[ hash_values_index ];
367 }
368 #endif /* defined( LIBHMAC_UNFOLLED_LOOPS ) */
369
370 size -= LIBHMAC_MD5_BLOCK_SIZE;
371 }
372 /* Prevent sensitive data from leaking
373 */
374 if( memory_set(
375 hash_values,
376 0,
377 sizeof( uint32_t ) * 4 ) == NULL )
378 {
379 libcerror_error_set(
380 error,
381 LIBCERROR_ERROR_DOMAIN_MEMORY,
382 LIBCERROR_MEMORY_ERROR_SET_FAILED,
383 "%s: unable to clear hash values.",
384 function );
385
386 goto on_error;
387 }
388 if( memory_set(
389 values_32bit,
390 0,
391 sizeof( uint32_t ) * 16 ) == NULL )
392 {
393 libcerror_error_set(
394 error,
395 LIBCERROR_ERROR_DOMAIN_MEMORY,
396 LIBCERROR_MEMORY_ERROR_SET_FAILED,
397 "%s: unable to clear 32-bit values.",
398 function );
399
400 goto on_error;
401 }
402 return( (ssize_t) buffer_offset );
403
404 on_error:
405 memory_set(
406 values_32bit,
407 0,
408 sizeof( uint32_t ) * 16 );
409
410 memory_set(
411 hash_values,
412 0,
413 sizeof( uint32_t ) * 4 );
414
415 return( -1 );
416 }
417
418 #endif /* !defined( LIBHMAC_HAVE_MD5_SUPPORT ) */
419
420 /* Creates a MD5 context
421 * Make sure the value context is referencing, is set to NULL
422 * Returns 1 if successful or -1 on error
423 */
libhmac_md5_initialize(libhmac_md5_context_t ** context,libcerror_error_t ** error)424 int libhmac_md5_initialize(
425 libhmac_md5_context_t **context,
426 libcerror_error_t **error )
427 {
428 libhmac_internal_md5_context_t *internal_context = NULL;
429 static char *function = "libhmac_md5_initialize";
430
431 if( context == NULL )
432 {
433 libcerror_error_set(
434 error,
435 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
436 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
437 "%s: invalid context.",
438 function );
439
440 return( -1 );
441 }
442 if( *context != NULL )
443 {
444 libcerror_error_set(
445 error,
446 LIBCERROR_ERROR_DOMAIN_RUNTIME,
447 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
448 "%s: invalid context value already set.",
449 function );
450
451 return( -1 );
452 }
453 internal_context = memory_allocate_structure(
454 libhmac_internal_md5_context_t );
455
456 if( internal_context == NULL )
457 {
458 libcerror_error_set(
459 error,
460 LIBCERROR_ERROR_DOMAIN_MEMORY,
461 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
462 "%s: unable to create context.",
463 function );
464
465 goto on_error;
466 }
467 if( memory_set(
468 internal_context,
469 0,
470 sizeof( libhmac_internal_md5_context_t ) ) == NULL )
471 {
472 libcerror_error_set(
473 error,
474 LIBCERROR_ERROR_DOMAIN_MEMORY,
475 LIBCERROR_MEMORY_ERROR_SET_FAILED,
476 "%s: unable to clear context.",
477 function );
478
479 memory_free(
480 internal_context );
481
482 return( -1 );
483 }
484 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
485 if( MD5_Init(
486 &( internal_context->md5_context ) ) != 1 )
487 {
488 libcerror_error_set(
489 error,
490 LIBCERROR_ERROR_DOMAIN_RUNTIME,
491 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
492 "%s: unable to initialize context.",
493 function );
494
495 goto on_error;
496 }
497
498 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
499 #if defined( HAVE_EVP_MD_CTX_INIT )
500 EVP_MD_CTX_init(
501 &( internal_context->internal_evp_md_context ) );
502
503 internal_context->evp_md_context = &( internal_context->internal_evp_md_context );
504 #else
505 internal_context->evp_md_context = EVP_MD_CTX_new();
506
507 if( internal_context->evp_md_context == NULL )
508 {
509 libcerror_error_set(
510 error,
511 LIBCERROR_ERROR_DOMAIN_RUNTIME,
512 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
513 "%s: unable to create EVP message digest context.",
514 function );
515
516 goto on_error;
517 }
518 #endif /* defined( HAVE_EVP_MD_CTX_INIT ) */
519
520 if( EVP_DigestInit_ex(
521 internal_context->evp_md_context,
522 EVP_md5(),
523 NULL ) != 1 )
524 {
525 libcerror_error_set(
526 error,
527 LIBCERROR_ERROR_DOMAIN_RUNTIME,
528 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
529 "%s: unable to initialize EVP message digest context.",
530 function );
531
532 #if defined( HAVE_EVP_MD_CTX_CLEANUP )
533 EVP_MD_CTX_cleanup(
534 &( internal_context->internal_evp_md_context ) );
535 ERR_remove_thread_state(
536 NULL );
537 #else
538 EVP_MD_CTX_free(
539 internal_context->evp_md_context );
540 #endif
541 internal_context->evp_md_context = NULL;
542
543 goto on_error;
544 }
545 #else
546 if( memory_copy(
547 internal_context->hash_values,
548 libhmac_md5_fixed_constants,
549 sizeof( uint32_t ) * 4 ) == NULL )
550 {
551 libcerror_error_set(
552 error,
553 LIBCERROR_ERROR_DOMAIN_MEMORY,
554 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
555 "%s: unable to copy fixed constants to hash values.",
556 function );
557
558 goto on_error;
559 }
560 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
561
562 *context = (libhmac_md5_context_t *) internal_context;
563
564 return( 1 );
565
566 on_error:
567 if( internal_context != NULL )
568 {
569 memory_free(
570 internal_context );
571 }
572 return( -1 );
573 }
574
575 /* Frees a MD5 context
576 * Returns 1 if successful or -1 on error
577 */
libhmac_md5_free(libhmac_md5_context_t ** context,libcerror_error_t ** error)578 int libhmac_md5_free(
579 libhmac_md5_context_t **context,
580 libcerror_error_t **error )
581 {
582 libhmac_internal_md5_context_t *internal_context = NULL;
583 static char *function = "libhmac_md5_free";
584
585 if( context == NULL )
586 {
587 libcerror_error_set(
588 error,
589 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
590 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
591 "%s: invalid context.",
592 function );
593
594 return( -1 );
595 }
596 if( *context != NULL )
597 {
598 internal_context = (libhmac_internal_md5_context_t *) *context;
599 *context = NULL;
600
601 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
602 /* No additional clean up necessary
603 */
604
605 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
606 #if defined( HAVE_EVP_MD_CTX_CLEANUP )
607 if( EVP_MD_CTX_cleanup(
608 &( internal_context->internal_evp_md_context ) ) != 1 )
609 {
610 libcerror_error_set(
611 error,
612 LIBCERROR_ERROR_DOMAIN_RUNTIME,
613 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
614 "%s: unable to clean up EVP message digest context.",
615 function );
616 }
617 /* Make sure the error state is removed otherwise OpenSSL will leak memory
618 */
619 ERR_remove_thread_state(
620 NULL );
621 #else
622 EVP_MD_CTX_free(
623 internal_context->evp_md_context );
624
625 #endif /* defined( HAVE_EVP_MD_CTX_CLEANUP ) */
626
627 internal_context->evp_md_context = NULL;
628 #else
629 /* No additional clean up necessary
630 */
631 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
632
633 memory_free(
634 internal_context );
635 }
636 return( 1 );
637 }
638
639 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
640
641 /* Updates the MD5 context using OpenSSL
642 * Returns 1 if successful or -1 on error
643 */
libhmac_md5_update(libhmac_md5_context_t * context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)644 int libhmac_md5_update(
645 libhmac_md5_context_t *context,
646 const uint8_t *buffer,
647 size_t size,
648 libcerror_error_t **error )
649 {
650 libhmac_internal_md5_context_t *internal_context = NULL;
651 static char *function = "libhmac_md5_update";
652 unsigned long safe_hash_size = 0;
653
654 if( context == NULL )
655 {
656 libcerror_error_set(
657 error,
658 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
659 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
660 "%s: invalid context.",
661 function );
662
663 return( -1 );
664 }
665 internal_context = (libhmac_internal_md5_context_t *) context;
666
667 if( buffer == NULL )
668 {
669 libcerror_error_set(
670 error,
671 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
672 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
673 "%s: invalid buffer.",
674 function );
675
676 return( -1 );
677 }
678 #if ( SIZEOF_LONG < SIZEOF_SIZE_T )
679 if( size > (size_t) ULONG_MAX )
680 #else
681 if( size > (size_t) SSIZE_MAX )
682 #endif
683 {
684 libcerror_error_set(
685 error,
686 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
687 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
688 "%s: invalid size value exceeds maximum.",
689 function );
690
691 return( -1 );
692 }
693 if( size == 0 )
694 {
695 return( 1 );
696 }
697 safe_hash_size = (unsigned long) size;
698
699 if( MD5_Update(
700 &( internal_context->md5_context ),
701 (const void *) buffer,
702 size ) != 1 )
703 {
704 libcerror_error_set(
705 error,
706 LIBCERROR_ERROR_DOMAIN_RUNTIME,
707 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
708 "%s: unable to update context.",
709 function );
710
711 return( -1 );
712 }
713 return( 1 );
714 }
715
716 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
717
718 /* Updates the MD5 context using OpenSSL EVP
719 * Returns 1 if successful or -1 on error
720 */
libhmac_md5_update(libhmac_md5_context_t * context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)721 int libhmac_md5_update(
722 libhmac_md5_context_t *context,
723 const uint8_t *buffer,
724 size_t size,
725 libcerror_error_t **error )
726 {
727 libhmac_internal_md5_context_t *internal_context = NULL;
728 static char *function = "libhmac_md5_update";
729
730 if( context == NULL )
731 {
732 libcerror_error_set(
733 error,
734 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
735 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
736 "%s: invalid context.",
737 function );
738
739 return( -1 );
740 }
741 internal_context = (libhmac_internal_md5_context_t *) context;
742
743 if( buffer == NULL )
744 {
745 libcerror_error_set(
746 error,
747 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
748 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
749 "%s: invalid buffer.",
750 function );
751
752 return( -1 );
753 }
754 if( size > (size_t) SSIZE_MAX )
755 {
756 libcerror_error_set(
757 error,
758 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
759 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
760 "%s: invalid size value exceeds maximum.",
761 function );
762
763 return( -1 );
764 }
765 if( size == 0 )
766 {
767 return( 1 );
768 }
769 if( EVP_DigestUpdate(
770 internal_context->evp_md_context,
771 (const void *) buffer,
772 size ) != 1 )
773 {
774 libcerror_error_set(
775 error,
776 LIBCERROR_ERROR_DOMAIN_RUNTIME,
777 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
778 "%s: unable to update context.",
779 function );
780
781 return( -1 );
782 }
783 return( 1 );
784 }
785
786 #else
787
788 /* Updates the MD5 context using fallback implementation
789 * Returns 1 if successful or -1 on error
790 */
libhmac_md5_update(libhmac_md5_context_t * context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)791 int libhmac_md5_update(
792 libhmac_md5_context_t *context,
793 const uint8_t *buffer,
794 size_t size,
795 libcerror_error_t **error )
796 {
797 libhmac_internal_md5_context_t *internal_context = NULL;
798 static char *function = "libhmac_md5_update";
799 size_t buffer_offset = 0;
800 size_t remaining_block_size = 0;
801 ssize_t process_count = 0;
802
803 if( context == NULL )
804 {
805 libcerror_error_set(
806 error,
807 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
808 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
809 "%s: invalid context.",
810 function );
811
812 return( -1 );
813 }
814 internal_context = (libhmac_internal_md5_context_t *) context;
815
816 if( buffer == NULL )
817 {
818 libcerror_error_set(
819 error,
820 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
821 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
822 "%s: invalid buffer.",
823 function );
824
825 return( -1 );
826 }
827 if( size > (size_t) SSIZE_MAX )
828 {
829 libcerror_error_set(
830 error,
831 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
832 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
833 "%s: invalid size value exceeds maximum.",
834 function );
835
836 return( -1 );
837 }
838 if( size == 0 )
839 {
840 return( 1 );
841 }
842 if( internal_context->block_offset > 0 )
843 {
844 remaining_block_size = LIBHMAC_MD5_BLOCK_SIZE - internal_context->block_offset;
845
846 if( remaining_block_size > size )
847 {
848 remaining_block_size = size;
849 }
850 if( memory_copy(
851 &( internal_context->block[ internal_context->block_offset ] ),
852 buffer,
853 remaining_block_size ) == NULL )
854 {
855 libcerror_error_set(
856 error,
857 LIBCERROR_ERROR_DOMAIN_MEMORY,
858 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
859 "%s: unable to copy data to context block.",
860 function );
861
862 return( -1 );
863 }
864 internal_context->block_offset += remaining_block_size;
865
866 if( internal_context->block_offset < LIBHMAC_MD5_BLOCK_SIZE )
867 {
868 return( 1 );
869 }
870 buffer_offset += remaining_block_size;
871 size -= remaining_block_size;
872
873 process_count = libhmac_md5_transform(
874 internal_context,
875 internal_context->block,
876 LIBHMAC_MD5_BLOCK_SIZE,
877 error );
878
879 if( process_count == -1 )
880 {
881 libcerror_error_set(
882 error,
883 LIBCERROR_ERROR_DOMAIN_RUNTIME,
884 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
885 "%s: unable to transform context block.",
886 function );
887
888 return( -1 );
889 }
890 internal_context->hash_count += process_count;
891 internal_context->block_offset = 0;
892 }
893 if( size > 0 )
894 {
895 process_count = libhmac_md5_transform(
896 internal_context,
897 &( buffer[ buffer_offset ] ),
898 size,
899 error );
900
901 if( process_count == -1 )
902 {
903 libcerror_error_set(
904 error,
905 LIBCERROR_ERROR_DOMAIN_RUNTIME,
906 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
907 "%s: unable to transform buffer.",
908 function );
909
910 return( -1 );
911 }
912 internal_context->hash_count += process_count;
913
914 buffer_offset += process_count;
915 size -= process_count;
916 }
917 if( size > 0 )
918 {
919 if( size >= LIBHMAC_MD5_BLOCK_SIZE )
920 {
921 libcerror_error_set(
922 error,
923 LIBCERROR_ERROR_DOMAIN_RUNTIME,
924 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
925 "%s: invalid size value out of bounds.",
926 function );
927
928 return( -1 );
929 }
930 if( memory_copy(
931 internal_context->block,
932 &( buffer[ buffer_offset ] ),
933 size ) == NULL )
934 {
935 libcerror_error_set(
936 error,
937 LIBCERROR_ERROR_DOMAIN_MEMORY,
938 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
939 "%s: unable to copy remaining data to context block.",
940 function );
941
942 return( -1 );
943 }
944 internal_context->block_offset = size;
945 }
946 return( 1 );
947 }
948
949 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
950
951 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
952
953 /* Finalizes the MD5 context using OpenSSL
954 * Returns 1 if successful or -1 on error
955 */
libhmac_md5_finalize(libhmac_md5_context_t * context,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)956 int libhmac_md5_finalize(
957 libhmac_md5_context_t *context,
958 uint8_t *hash,
959 size_t hash_size,
960 libcerror_error_t **error )
961 {
962 libhmac_internal_md5_context_t *internal_context = NULL;
963 static char *function = "libhmac_md5_finalize";
964
965 if( context == NULL )
966 {
967 libcerror_error_set(
968 error,
969 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
970 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
971 "%s: invalid context.",
972 function );
973
974 return( -1 );
975 }
976 internal_context = (libhmac_internal_md5_context_t *) context;
977
978 if( hash == NULL )
979 {
980 libcerror_error_set(
981 error,
982 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
983 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
984 "%s: invalid hash.",
985 function );
986
987 return( -1 );
988 }
989 if( hash_size > (size_t) SSIZE_MAX )
990 {
991 libcerror_error_set(
992 error,
993 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
994 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
995 "%s: invalid hash size value exceeds maximum.",
996 function );
997
998 return( -1 );
999 }
1000 if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1001 {
1002 libcerror_error_set(
1003 error,
1004 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1005 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1006 "%s: invalid hash size value too small.",
1007 function );
1008
1009 return( -1 );
1010 }
1011 if( MD5_Final(
1012 hash,
1013 &( internal_context->md5_context ) ) != 1 )
1014 {
1015 libcerror_error_set(
1016 error,
1017 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1018 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1019 "%s: unable to finalize context.",
1020 function );
1021
1022 return( -1 );
1023 }
1024 return( 1 );
1025 }
1026
1027 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
1028
1029 /* Finalizes the MD5 context using OpenSSL EVP
1030 * Returns 1 if successful or -1 on error
1031 */
libhmac_md5_finalize(libhmac_md5_context_t * context,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1032 int libhmac_md5_finalize(
1033 libhmac_md5_context_t *context,
1034 uint8_t *hash,
1035 size_t hash_size,
1036 libcerror_error_t **error )
1037 {
1038 libhmac_internal_md5_context_t *internal_context = NULL;
1039 static char *function = "libhmac_md5_finalize";
1040 unsigned int safe_hash_size = 0;
1041
1042 if( context == NULL )
1043 {
1044 libcerror_error_set(
1045 error,
1046 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1047 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1048 "%s: invalid context.",
1049 function );
1050
1051 return( -1 );
1052 }
1053 internal_context = (libhmac_internal_md5_context_t *) context;
1054
1055 if( hash == NULL )
1056 {
1057 libcerror_error_set(
1058 error,
1059 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1060 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1061 "%s: invalid hash.",
1062 function );
1063
1064 return( -1 );
1065 }
1066 if( hash_size > (size_t) UINT_MAX )
1067 {
1068 libcerror_error_set(
1069 error,
1070 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1071 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1072 "%s: invalid hash size value exceeds maximum.",
1073 function );
1074
1075 return( -1 );
1076 }
1077 if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1078 {
1079 libcerror_error_set(
1080 error,
1081 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1082 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1083 "%s: invalid hash size value too small.",
1084 function );
1085
1086 return( -1 );
1087 }
1088 safe_hash_size = (unsigned int) hash_size;
1089
1090 if( EVP_DigestFinal_ex(
1091 internal_context->evp_md_context,
1092 (unsigned char *) hash,
1093 &safe_hash_size ) != 1 )
1094 {
1095 libcerror_error_set(
1096 error,
1097 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1098 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1099 "%s: unable to finalize context.",
1100 function );
1101
1102 return( -1 );
1103 }
1104 return( 1 );
1105 }
1106
1107 #else
1108
1109 /* Finalizes the MD5 context using fallback implementation
1110 * Returns 1 if successful or -1 on error
1111 */
libhmac_md5_finalize(libhmac_md5_context_t * context,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1112 int libhmac_md5_finalize(
1113 libhmac_md5_context_t *context,
1114 uint8_t *hash,
1115 size_t hash_size,
1116 libcerror_error_t **error )
1117 {
1118 libhmac_internal_md5_context_t *internal_context = NULL;
1119 static char *function = "libhmac_md5_finalize";
1120 size_t block_size = 0;
1121 size_t number_of_blocks = 0;
1122 ssize_t process_count = 0;
1123 uint64_t bit_size = 0;
1124
1125 #if !defined( LIBHMAC_UNFOLLED_LOOPS )
1126 size_t hash_index = 0;
1127 int hash_values_index = 0;
1128 #endif
1129
1130 if( context == NULL )
1131 {
1132 libcerror_error_set(
1133 error,
1134 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1135 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1136 "%s: invalid context.",
1137 function );
1138
1139 return( -1 );
1140 }
1141 internal_context = (libhmac_internal_md5_context_t *) context;
1142
1143 if( hash == NULL )
1144 {
1145 libcerror_error_set(
1146 error,
1147 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1148 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1149 "%s: invalid hash.",
1150 function );
1151
1152 return( -1 );
1153 }
1154 if( hash_size > (size_t) SSIZE_MAX )
1155 {
1156 libcerror_error_set(
1157 error,
1158 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1159 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1160 "%s: invalid hash size value exceeds maximum.",
1161 function );
1162
1163 return( -1 );
1164 }
1165 if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1166 {
1167 libcerror_error_set(
1168 error,
1169 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1170 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1171 "%s: invalid hash size value too small.",
1172 function );
1173
1174 return( -1 );
1175 }
1176 /* Add padding with a size of 56 mod 64
1177 */
1178 number_of_blocks = 1;
1179
1180 if( internal_context->block_offset > 55 )
1181 {
1182 number_of_blocks += 1;
1183 }
1184 block_size = number_of_blocks * LIBHMAC_MD5_BLOCK_SIZE;
1185
1186 if( memory_set(
1187 &( internal_context->block[ internal_context->block_offset ] ),
1188 0,
1189 block_size - internal_context->block_offset ) == NULL )
1190 {
1191 libcerror_error_set(
1192 error,
1193 LIBCERROR_ERROR_DOMAIN_MEMORY,
1194 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1195 "%s: unable to clear context block.",
1196 function );
1197
1198 return( -1 );
1199 }
1200 /* The first byte of the padding contains 0x80
1201 */
1202 internal_context->block[ internal_context->block_offset ] = 0x80;
1203
1204 bit_size = ( internal_context->hash_count + internal_context->block_offset ) * 8;
1205
1206 byte_stream_copy_from_uint64_little_endian(
1207 &( internal_context->block[ block_size - 8 ] ),
1208 bit_size );
1209
1210 process_count = libhmac_md5_transform(
1211 internal_context,
1212 internal_context->block,
1213 block_size,
1214 error );
1215
1216 if( process_count == -1 )
1217 {
1218 libcerror_error_set(
1219 error,
1220 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1221 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1222 "%s: unable to transform context block.",
1223 function );
1224
1225 return( -1 );
1226 }
1227 #if !defined( LIBHMAC_UNFOLLED_LOOPS )
1228 for( hash_values_index = 0;
1229 hash_values_index < 4;
1230 hash_values_index++ )
1231 {
1232 byte_stream_copy_from_uint32_little_endian(
1233 &( hash[ hash_index ] ),
1234 internal_context->hash_values[ hash_values_index ] );
1235
1236 hash_index += sizeof( uint32_t );
1237 }
1238 #else
1239 byte_stream_copy_from_uint32_little_endian(
1240 &( hash[ 0 ] ),
1241 internal_context->hash_values[ 0 ] );
1242
1243 byte_stream_copy_from_uint32_little_endian(
1244 &( hash[ 4 ] ),
1245 internal_context->hash_values[ 1 ] );
1246
1247 byte_stream_copy_from_uint32_little_endian(
1248 &( hash[ 8 ] ),
1249 internal_context->hash_values[ 2 ] );
1250
1251 byte_stream_copy_from_uint32_little_endian(
1252 &( hash[ 12 ] ),
1253 internal_context->hash_values[ 3 ] );
1254
1255 #endif /* !defined( LIBHMAC_UNFOLLED_LOOPS ) */
1256
1257 /* Prevent sensitive data from leaking
1258 */
1259 if( memory_set(
1260 internal_context,
1261 0,
1262 sizeof( libhmac_internal_md5_context_t ) ) == NULL )
1263 {
1264 libcerror_error_set(
1265 error,
1266 LIBCERROR_ERROR_DOMAIN_MEMORY,
1267 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1268 "%s: unable to clear context.",
1269 function );
1270
1271 return( -1 );
1272 }
1273 return( 1 );
1274 }
1275
1276 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
1277
1278 /* Calculates the MD5 of the buffer
1279 * Returns 1 if successful or -1 on error
1280 */
libhmac_md5_calculate(const uint8_t * buffer,size_t size,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1281 int libhmac_md5_calculate(
1282 const uint8_t *buffer,
1283 size_t size,
1284 uint8_t *hash,
1285 size_t hash_size,
1286 libcerror_error_t **error )
1287 {
1288 libhmac_md5_context_t *context = NULL;
1289 static char *function = "libhmac_md5_calculate";
1290
1291 if( libhmac_md5_initialize(
1292 &context,
1293 error ) != 1 )
1294 {
1295 libcerror_error_set(
1296 error,
1297 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1298 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1299 "%s: unable to initialize context.",
1300 function );
1301
1302 goto on_error;
1303 }
1304 if( libhmac_md5_update(
1305 context,
1306 buffer,
1307 size,
1308 error ) != 1 )
1309 {
1310 libcerror_error_set(
1311 error,
1312 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1313 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1314 "%s: unable to update context.",
1315 function );
1316
1317 goto on_error;
1318 }
1319 if( libhmac_md5_finalize(
1320 context,
1321 hash,
1322 hash_size,
1323 error ) != 1 )
1324 {
1325 libcerror_error_set(
1326 error,
1327 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1328 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1329 "%s: unable to finalize context.",
1330 function );
1331
1332 goto on_error;
1333 }
1334 if( libhmac_md5_free(
1335 &context,
1336 error ) != 1 )
1337 {
1338 libcerror_error_set(
1339 error,
1340 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1341 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1342 "%s: unable to free context.",
1343 function );
1344
1345 goto on_error;
1346 }
1347 return( 1 );
1348
1349 on_error:
1350 if( context != NULL )
1351 {
1352 libhmac_md5_free(
1353 &context,
1354 NULL );
1355 }
1356 return( -1 );
1357 }
1358
1359 /* Calculates the MD5 HMAC of the buffer
1360 * HMAC is defined in RFC 2104
1361 * Returns 1 if successful or -1 on error
1362 */
libhmac_md5_calculate_hmac(const uint8_t * key,size_t key_size,const uint8_t * buffer,size_t size,uint8_t * hmac,size_t hmac_size,libcerror_error_t ** error)1363 int libhmac_md5_calculate_hmac(
1364 const uint8_t *key,
1365 size_t key_size,
1366 const uint8_t *buffer,
1367 size_t size,
1368 uint8_t *hmac,
1369 size_t hmac_size,
1370 libcerror_error_t **error )
1371 {
1372 uint8_t key_hash[ LIBHMAC_MD5_HASH_SIZE ];
1373
1374 libhmac_md5_context_t *context = NULL;
1375 uint8_t *key_data = NULL;
1376 uint8_t *inner_padding = NULL;
1377 uint8_t *outer_padding = NULL;
1378 static char *function = "libhmac_md5_calculate_hmac";
1379 size_t block_index = 0;
1380 size_t block_size = 64;
1381
1382 if( key == NULL )
1383 {
1384 libcerror_error_set(
1385 error,
1386 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1387 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1388 "%s: invalid key.",
1389 function );
1390
1391 return( -1 );
1392 }
1393 if( key_size > (size_t) SSIZE_MAX )
1394 {
1395 libcerror_error_set(
1396 error,
1397 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1398 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1399 "%s: invalid key size value exceeds maximum.",
1400 function );
1401
1402 return( -1 );
1403 }
1404 if( hmac_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1405 {
1406 libcerror_error_set(
1407 error,
1408 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1409 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1410 "%s: invalid HMAC size value too small.",
1411 function );
1412
1413 return( -1 );
1414 }
1415 key_data = (uint8_t *) memory_allocate(
1416 sizeof( uint8_t ) * block_size );
1417
1418 if( key_data == NULL )
1419 {
1420 libcerror_error_set(
1421 error,
1422 LIBCERROR_ERROR_DOMAIN_MEMORY,
1423 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1424 "%s: unable to create key data.",
1425 function );
1426
1427 goto on_error;
1428 }
1429 if( key_size <= block_size )
1430 {
1431 if( memory_copy(
1432 key_data,
1433 key,
1434 key_size ) == NULL )
1435 {
1436 libcerror_error_set(
1437 error,
1438 LIBCERROR_ERROR_DOMAIN_MEMORY,
1439 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1440 "%s: unable to copy key data.",
1441 function );
1442
1443 goto on_error;
1444 }
1445 if( memory_set(
1446 &( key_data[ key_size ] ),
1447 0,
1448 block_size - key_size ) == NULL )
1449 {
1450 libcerror_error_set(
1451 error,
1452 LIBCERROR_ERROR_DOMAIN_MEMORY,
1453 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1454 "%s: unable to clear key remaining data.",
1455 function );
1456
1457 goto on_error;
1458 }
1459 }
1460 else
1461 {
1462 if( libhmac_md5_initialize(
1463 &context,
1464 error ) != 1 )
1465 {
1466 libcerror_error_set(
1467 error,
1468 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1469 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1470 "%s: unable to initialize context.",
1471 function );
1472
1473 goto on_error;
1474 }
1475 if( libhmac_md5_update(
1476 context,
1477 key,
1478 key_size,
1479 error ) != 1 )
1480 {
1481 libcerror_error_set(
1482 error,
1483 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1484 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1485 "%s: unable to update context.",
1486 function );
1487
1488 goto on_error;
1489 }
1490 if( libhmac_md5_finalize(
1491 context,
1492 key_hash,
1493 LIBHMAC_MD5_HASH_SIZE,
1494 error ) != 1 )
1495 {
1496 libcerror_error_set(
1497 error,
1498 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1499 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1500 "%s: unable to finalize context.",
1501 function );
1502
1503 goto on_error;
1504 }
1505 if( libhmac_md5_free(
1506 &context,
1507 error ) != 1 )
1508 {
1509 libcerror_error_set(
1510 error,
1511 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1512 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1513 "%s: unable to free context.",
1514 function );
1515
1516 goto on_error;
1517 }
1518 if( block_size > LIBHMAC_MD5_HASH_SIZE )
1519 {
1520 if( memory_set(
1521 &( key_data[ LIBHMAC_MD5_HASH_SIZE ] ),
1522 0,
1523 block_size - LIBHMAC_MD5_HASH_SIZE ) == NULL )
1524 {
1525 libcerror_error_set(
1526 error,
1527 LIBCERROR_ERROR_DOMAIN_MEMORY,
1528 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1529 "%s: unable to clear remaining key data.",
1530 function );
1531
1532 goto on_error;
1533 }
1534 }
1535 if( memory_copy(
1536 key_data,
1537 key_hash,
1538 LIBHMAC_MD5_HASH_SIZE ) == NULL )
1539 {
1540 libcerror_error_set(
1541 error,
1542 LIBCERROR_ERROR_DOMAIN_MEMORY,
1543 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1544 "%s: unable to copy key hash data.",
1545 function );
1546
1547 goto on_error;
1548 }
1549 }
1550 inner_padding = (uint8_t *) memory_allocate(
1551 sizeof( uint8_t ) * block_size );
1552
1553 if( inner_padding == NULL )
1554 {
1555 libcerror_error_set(
1556 error,
1557 LIBCERROR_ERROR_DOMAIN_MEMORY,
1558 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1559 "%s: unable to create inner padding.",
1560 function );
1561
1562 goto on_error;
1563 }
1564 if( memory_set(
1565 inner_padding,
1566 0x36,
1567 block_size ) == NULL )
1568 {
1569 libcerror_error_set(
1570 error,
1571 LIBCERROR_ERROR_DOMAIN_MEMORY,
1572 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1573 "%s: unable to set inner padding.",
1574 function );
1575
1576 goto on_error;
1577 }
1578 outer_padding = (uint8_t *) memory_allocate(
1579 sizeof( uint8_t ) * block_size );
1580
1581 if( outer_padding == NULL )
1582 {
1583 libcerror_error_set(
1584 error,
1585 LIBCERROR_ERROR_DOMAIN_MEMORY,
1586 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1587 "%s: unable to create outer padding.",
1588 function );
1589
1590 goto on_error;
1591 }
1592 if( memory_set(
1593 outer_padding,
1594 0x5c,
1595 block_size ) == NULL )
1596 {
1597 libcerror_error_set(
1598 error,
1599 LIBCERROR_ERROR_DOMAIN_MEMORY,
1600 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1601 "%s: unable to set outer padding.",
1602 function );
1603
1604 goto on_error;
1605 }
1606 for( block_index = 0;
1607 block_index < block_size;
1608 block_index++ )
1609 {
1610 inner_padding[ block_index ] ^= key_data[ block_index ];
1611 outer_padding[ block_index ] ^= key_data[ block_index ];
1612 }
1613 if( libhmac_md5_initialize(
1614 &context,
1615 error ) != 1 )
1616 {
1617 libcerror_error_set(
1618 error,
1619 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1620 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1621 "%s: unable to initialize context.",
1622 function );
1623
1624 goto on_error;
1625 }
1626 if( libhmac_md5_update(
1627 context,
1628 inner_padding,
1629 block_size,
1630 error ) != 1 )
1631 {
1632 libcerror_error_set(
1633 error,
1634 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1635 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1636 "%s: unable to update context.",
1637 function );
1638
1639 goto on_error;
1640 }
1641 if( libhmac_md5_update(
1642 context,
1643 buffer,
1644 size,
1645 error ) != 1 )
1646 {
1647 libcerror_error_set(
1648 error,
1649 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1650 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1651 "%s: unable to update context.",
1652 function );
1653
1654 goto on_error;
1655 }
1656 if( libhmac_md5_finalize(
1657 context,
1658 hmac,
1659 hmac_size,
1660 error ) != 1 )
1661 {
1662 libcerror_error_set(
1663 error,
1664 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1665 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1666 "%s: unable to finalize context.",
1667 function );
1668
1669 goto on_error;
1670 }
1671 if( libhmac_md5_free(
1672 &context,
1673 error ) != 1 )
1674 {
1675 libcerror_error_set(
1676 error,
1677 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1678 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1679 "%s: unable to free context.",
1680 function );
1681
1682 goto on_error;
1683 }
1684 if( libhmac_md5_initialize(
1685 &context,
1686 error ) != 1 )
1687 {
1688 libcerror_error_set(
1689 error,
1690 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1691 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1692 "%s: unable to initialize context.",
1693 function );
1694
1695 goto on_error;
1696 }
1697 if( libhmac_md5_update(
1698 context,
1699 outer_padding,
1700 block_size,
1701 error ) != 1 )
1702 {
1703 libcerror_error_set(
1704 error,
1705 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1706 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1707 "%s: unable to update context.",
1708 function );
1709
1710 goto on_error;
1711 }
1712 if( libhmac_md5_update(
1713 context,
1714 hmac,
1715 LIBHMAC_MD5_HASH_SIZE,
1716 error ) != 1 )
1717 {
1718 libcerror_error_set(
1719 error,
1720 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1721 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1722 "%s: unable to update context.",
1723 function );
1724
1725 goto on_error;
1726 }
1727 if( libhmac_md5_finalize(
1728 context,
1729 hmac,
1730 hmac_size,
1731 error ) != 1 )
1732 {
1733 libcerror_error_set(
1734 error,
1735 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1736 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1737 "%s: unable to finalize context.",
1738 function );
1739
1740 goto on_error;
1741 }
1742 if( libhmac_md5_free(
1743 &context,
1744 error ) != 1 )
1745 {
1746 libcerror_error_set(
1747 error,
1748 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1749 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1750 "%s: unable to free context.",
1751 function );
1752
1753 goto on_error;
1754 }
1755 if( memory_set(
1756 outer_padding,
1757 0,
1758 block_size ) == NULL )
1759 {
1760 libcerror_error_set(
1761 error,
1762 LIBCERROR_ERROR_DOMAIN_MEMORY,
1763 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1764 "%s: unable to clear outer padding.",
1765 function );
1766
1767 goto on_error;
1768 }
1769 memory_free(
1770 outer_padding );
1771
1772 outer_padding = NULL;
1773
1774 if( memory_set(
1775 inner_padding,
1776 0,
1777 block_size ) == NULL )
1778 {
1779 libcerror_error_set(
1780 error,
1781 LIBCERROR_ERROR_DOMAIN_MEMORY,
1782 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1783 "%s: unable to clear inner padding.",
1784 function );
1785
1786 goto on_error;
1787 }
1788 memory_free(
1789 inner_padding );
1790
1791 inner_padding = NULL;
1792
1793 if( memory_set(
1794 key_data,
1795 0,
1796 block_size ) == NULL )
1797 {
1798 libcerror_error_set(
1799 error,
1800 LIBCERROR_ERROR_DOMAIN_MEMORY,
1801 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1802 "%s: unable to clear key data.",
1803 function );
1804
1805 goto on_error;
1806 }
1807 memory_free(
1808 key_data );
1809
1810 key_data = NULL;
1811
1812 return( 1 );
1813
1814 on_error:
1815 if( context != NULL )
1816 {
1817 libhmac_md5_free(
1818 &context,
1819 NULL );
1820 }
1821 if( outer_padding != NULL )
1822 {
1823 memory_set(
1824 outer_padding,
1825 0,
1826 block_size );
1827
1828 memory_free(
1829 outer_padding );
1830 }
1831 if( inner_padding != NULL )
1832 {
1833 memory_set(
1834 inner_padding,
1835 0,
1836 block_size );
1837
1838 memory_free(
1839 inner_padding );
1840 }
1841 if( key_data != NULL )
1842 {
1843 memory_set(
1844 key_data,
1845 0,
1846 block_size );
1847
1848 memory_free(
1849 key_data );
1850 }
1851 return( -1 );
1852 }
1853
1854