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