Coverage Report

Created: 2023-06-07 06:53

/src/libewf/libhmac/libhmac_md5_context.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * MD5 functions
3
 *
4
 * Copyright (C) 2011-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <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_context.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_context_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_context_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_context_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_context_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_context_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
1.83M
  hash_values[ hash_value_index0 ] += ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index2 ] ) \
97
1.83M
                                    | ( ~( hash_values[ hash_value_index1 ] ) & hash_values[ hash_value_index3 ] ); \
98
1.83M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
99
1.83M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
100
1.83M
\
101
1.83M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
102
1.83M
                                      hash_values[ hash_value_index0 ],  \
103
1.83M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
104
1.83M
\
105
1.83M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
106
107
#define libhmac_md5_context_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
1.83M
  hash_values[ hash_value_index0 ] += ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index3 ] ) \
109
1.83M
                                    | ( hash_values[ hash_value_index2 ] & ~( hash_values[ hash_value_index3 ] ) ); \
110
1.83M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
111
1.83M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
112
1.83M
\
113
1.83M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
114
1.83M
                                      hash_values[ hash_value_index0 ],  \
115
1.83M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
116
1.83M
\
117
1.83M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
118
119
#define libhmac_md5_context_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
1.83M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ] \
121
1.83M
                                    ^ hash_values[ hash_value_index2 ] \
122
1.83M
                                    ^ hash_values[ hash_value_index3 ]; \
123
1.83M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
124
1.83M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
125
1.83M
\
126
1.83M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
127
1.83M
                                      hash_values[ hash_value_index0 ],  \
128
1.83M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
129
1.83M
\
130
1.83M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
131
132
#define libhmac_md5_context_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
1.83M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index2 ] \
134
1.83M
                                    ^ ( hash_values[ hash_value_index1 ] | ~( hash_values[ hash_value_index3 ] ) ); \
135
1.83M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
136
1.83M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
137
1.83M
\
138
1.83M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
139
1.83M
                                      hash_values[ hash_value_index0 ],  \
140
1.83M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
141
1.83M
\
142
1.83M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ];
143
144
#define libhmac_md5_context_transform_unfolded_calculate_hash_values( values_32bit, hash_values ) \
145
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 0, hash_values, 0, 1, 2, 3, 0 ); \
146
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 1, hash_values, 3, 0, 1, 2, 1 ); \
147
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 2, hash_values, 2, 3, 0, 1, 2 ); \
148
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 3, hash_values, 1, 2, 3, 0, 3 ); \
149
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 4, hash_values, 0, 1, 2, 3, 4 ); \
150
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 5, hash_values, 3, 0, 1, 2, 5 ); \
151
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 6, hash_values, 2, 3, 0, 1, 6 ); \
152
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 7, hash_values, 1, 2, 3, 0, 7 ); \
153
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 8, hash_values, 0, 1, 2, 3, 8 ); \
154
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 9, hash_values, 3, 0, 1, 2, 9 ); \
155
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 10, hash_values, 2, 3, 0, 1, 10 ); \
156
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 11, hash_values, 1, 2, 3, 0, 11 ); \
157
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 12, hash_values, 0, 1, 2, 3, 12 ); \
158
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 13, hash_values, 3, 0, 1, 2, 13 ); \
159
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 14, hash_values, 2, 3, 0, 1, 14 ); \
160
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 15, hash_values, 1, 2, 3, 0, 15 ); \
161
114k
\
162
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 1, hash_values, 0, 1, 2, 3, 16 ); \
163
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 6, hash_values, 3, 0, 1, 2, 17 ); \
164
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 11, hash_values, 2, 3, 0, 1, 18 ); \
165
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 0, hash_values, 1, 2, 3, 0, 19 ); \
166
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 5, hash_values, 0, 1, 2, 3, 20 ); \
167
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 10, hash_values, 3, 0, 1, 2, 21 ); \
168
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 15, hash_values, 2, 3, 0, 1, 22 ); \
169
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 4, hash_values, 1, 2, 3, 0, 23 ); \
170
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 9, hash_values, 0, 1, 2, 3, 24 ); \
171
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 14, hash_values, 3, 0, 1, 2, 25 ); \
172
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 3, hash_values, 2, 3, 0, 1, 26 ); \
173
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 8, hash_values, 1, 2, 3, 0, 27 ); \
174
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 13, hash_values, 0, 1, 2, 3, 28 ); \
175
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 2, hash_values, 3, 0, 1, 2, 29 ); \
176
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 7, hash_values, 2, 3, 0, 1, 30 ); \
177
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 12, hash_values, 1, 2, 3, 0, 31 ); \
178
114k
\
179
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 5, hash_values, 0, 1, 2, 3, 32 ); \
180
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 8, hash_values, 3, 0, 1, 2, 33 ); \
181
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 11, hash_values, 2, 3, 0, 1, 34 ); \
182
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 14, hash_values, 1, 2, 3, 0, 35 ); \
183
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 1, hash_values, 0, 1, 2, 3, 36 ); \
184
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 4, hash_values, 3, 0, 1, 2, 37 ); \
185
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 7, hash_values, 2, 3, 0, 1, 38 ); \
186
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 10, hash_values, 1, 2, 3, 0, 39 ); \
187
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 13, hash_values, 0, 1, 2, 3, 40 ); \
188
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 0, hash_values, 3, 0, 1, 2, 41 ); \
189
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 3, hash_values, 2, 3, 0, 1, 42 ); \
190
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 6, hash_values, 1, 2, 3, 0, 43 ); \
191
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 9, hash_values, 0, 1, 2, 3, 44 ); \
192
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 12, hash_values, 3, 0, 1, 2, 45 ); \
193
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 15, hash_values, 2, 3, 0, 1, 46 ); \
194
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 2, hash_values, 1, 2, 3, 0, 47 ); \
195
114k
\
196
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 0, hash_values, 0, 1, 2, 3, 48 ); \
197
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 7, hash_values, 3, 0, 1, 2, 49 ); \
198
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 14, hash_values, 2, 3, 0, 1, 50 ); \
199
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 5, hash_values, 1, 2, 3, 0, 51 ); \
200
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 12, hash_values, 0, 1, 2, 3, 52 ); \
201
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 3, hash_values, 3, 0, 1, 2, 53 ); \
202
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 10, hash_values, 2, 3, 0, 1, 54 ); \
203
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 1, hash_values, 1, 2, 3, 0, 55 ); \
204
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 8, hash_values, 0, 1, 2, 3, 56 ); \
205
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 15, hash_values, 3, 0, 1, 2, 57 ); \
206
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 6, hash_values, 2, 3, 0, 1, 58 ); \
207
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 13, hash_values, 1, 2, 3, 0, 59 ); \
208
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 4, hash_values, 0, 1, 2, 3, 60 ); \
209
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 11, hash_values, 3, 0, 1, 2, 61 ); \
210
114k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 2, hash_values, 2, 3, 0, 1, 62 ); \
211
114k
  libhmac_md5_context_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
 */
216
ssize_t libhmac_md5_context_transform(
217
         libhmac_internal_md5_context_t *internal_context,
218
         const uint8_t *buffer,
219
         size_t size,
220
         libcerror_error_t **error )
221
116
{
222
116
  uint32_t hash_values[ 4 ];
223
116
  uint32_t values_32bit[ 16 ];
224
225
116
  static char *function     = "libhmac_md5_context_transform";
226
116
  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
116
  if( internal_context == NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
240
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
241
0
     "%s: invalid internal context.",
242
0
     function );
243
244
0
    return( -1 );
245
0
  }
246
116
  if( buffer == NULL )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252
0
     "%s: invalid buffer.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
116
  if( size > (size_t) SSIZE_MAX )
258
0
  {
259
0
    libcerror_error_set(
260
0
     error,
261
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
262
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
263
0
     "%s: invalid size value exceeds maximum.",
264
0
     function );
265
266
0
    return( -1 );
267
0
  }
268
115k
  while( size >= LIBHMAC_MD5_BLOCK_SIZE )
269
114k
  {
270
114k
    if( memory_copy(
271
114k
         hash_values,
272
114k
         internal_context->hash_values,
273
114k
         sizeof( uint32_t ) * 4 ) == NULL )
274
0
    {
275
0
      libcerror_error_set(
276
0
       error,
277
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
278
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
279
0
       "%s: unable to copy hash values.",
280
0
       function );
281
282
0
      goto on_error;
283
0
    }
284
114k
#if defined( LIBHMAC_UNFOLLED_LOOPS )
285
    /* Break the block into 16 x 32-bit values
286
     */
287
114k
    libhmac_byte_stream_copy_to_16x_uint32_little_endian(
288
114k
     &( buffer[ buffer_offset ] ),
289
114k
     values_32bit );
290
291
114k
    buffer_offset += LIBHMAC_MD5_BLOCK_SIZE;
292
293
    /* Calculate the hash values for the 32-bit values
294
     */
295
114k
    libhmac_md5_context_transform_unfolded_calculate_hash_values(
296
114k
     values_32bit,
297
114k
     hash_values );
298
299
    /* Update the hash values in the context
300
     */
301
114k
    internal_context->hash_values[ 0 ] += hash_values[ 0 ];
302
114k
    internal_context->hash_values[ 1 ] += hash_values[ 1 ];
303
114k
    internal_context->hash_values[ 2 ] += hash_values[ 2 ];
304
114k
    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_context_values_32bit_index[ block_index ];
347
348
      hash_values[ 0 ] += values_32bit[ value_32bit_index ];
349
      hash_values[ 0 ] += libhmac_md5_context_sines[ block_index ];
350
      hash_values[ 0 ]  = byte_stream_bit_rotate_left_32bit(
351
                           hash_values[ 0 ],
352
                           libhmac_md5_context_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
114k
    size -= LIBHMAC_MD5_BLOCK_SIZE;
371
114k
  }
372
  /* Prevent sensitive data from leaking
373
   */
374
116
  if( memory_set(
375
116
       hash_values,
376
116
       0,
377
116
       sizeof( uint32_t ) * 4 ) == NULL )
378
0
  {
379
0
    libcerror_error_set(
380
0
     error,
381
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
382
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
383
0
     "%s: unable to clear hash values.",
384
0
     function );
385
386
0
    goto on_error;
387
0
  }
388
116
  if( memory_set(
389
116
       values_32bit,
390
116
       0,
391
116
       sizeof( uint32_t ) * 16 ) == NULL )
392
0
  {
393
0
    libcerror_error_set(
394
0
     error,
395
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
396
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
397
0
     "%s: unable to clear 32-bit values.",
398
0
     function );
399
400
0
    goto on_error;
401
0
  }
402
116
  return( (ssize_t) buffer_offset );
403
404
0
on_error:
405
0
  memory_set(
406
0
   values_32bit,
407
0
   0,
408
0
   sizeof( uint32_t ) * 16 );
409
410
0
  memory_set(
411
0
   hash_values,
412
0
   0,
413
0
   sizeof( uint32_t ) * 4 );
414
415
0
  return( -1 );
416
116
}
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
 */
424
int libhmac_md5_context_initialize(
425
     libhmac_md5_context_t **context,
426
     libcerror_error_t **error )
427
58
{
428
58
  libhmac_internal_md5_context_t *internal_context = NULL;
429
58
  static char *function                            = "libhmac_md5_context_initialize";
430
431
#if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
432
  const EVP_MD *evp_md_type                        = NULL;
433
#endif
434
435
58
  if( context == NULL )
436
0
  {
437
0
    libcerror_error_set(
438
0
     error,
439
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
440
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
441
0
     "%s: invalid context.",
442
0
     function );
443
444
0
    return( -1 );
445
0
  }
446
58
  if( *context != NULL )
447
0
  {
448
0
    libcerror_error_set(
449
0
     error,
450
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
451
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
452
0
     "%s: invalid context value already set.",
453
0
     function );
454
455
0
    return( -1 );
456
0
  }
457
58
  internal_context = memory_allocate_structure(
458
58
                      libhmac_internal_md5_context_t );
459
460
58
  if( internal_context == NULL )
461
0
  {
462
0
    libcerror_error_set(
463
0
     error,
464
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
465
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
466
0
     "%s: unable to create context.",
467
0
     function );
468
469
0
    goto on_error;
470
0
  }
471
58
  if( memory_set(
472
58
       internal_context,
473
58
       0,
474
58
       sizeof( libhmac_internal_md5_context_t ) ) == NULL )
475
0
  {
476
0
    libcerror_error_set(
477
0
     error,
478
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
479
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
480
0
     "%s: unable to clear context.",
481
0
     function );
482
483
0
    memory_free(
484
0
     internal_context );
485
486
0
    return( -1 );
487
0
  }
488
#if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
489
  if( MD5_Init(
490
       &( internal_context->md5_context ) ) != 1 )
491
  {
492
    libcerror_error_set(
493
     error,
494
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
495
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
496
     "%s: unable to initialize context.",
497
     function );
498
499
    goto on_error;
500
  }
501
502
#elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
503
#if defined( HAVE_EVP_MD_CTX_INIT )
504
  EVP_MD_CTX_init(
505
   &( internal_context->internal_evp_md_context ) );
506
507
  internal_context->evp_md_context = &( internal_context->internal_evp_md_context );
508
#else
509
  internal_context->evp_md_context = EVP_MD_CTX_new();
510
511
  if( internal_context->evp_md_context == NULL )
512
  {
513
    libcerror_error_set(
514
     error,
515
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
516
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
517
     "%s: unable to create EVP message digest context.",
518
     function );
519
520
    goto on_error;
521
  }
522
#endif /* defined( HAVE_EVP_MD_CTX_INIT ) */
523
524
/* TODO use EVP_MD_fetch for EVP_DigestInit_ex2 */
525
  evp_md_type = EVP_md5();
526
527
#if defined( HAVE_EVP_DIGESTINIT_EX2 )
528
  if( EVP_DigestInit_ex2(
529
       internal_context->evp_md_context,
530
       evp_md_type,
531
       NULL ) != 1 )
532
#else
533
  if( EVP_DigestInit_ex(
534
       internal_context->evp_md_context,
535
       evp_md_type,
536
       NULL ) != 1 )
537
#endif
538
  {
539
    libcerror_error_set(
540
     error,
541
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
542
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
543
     "%s: unable to initialize EVP message digest context.",
544
     function );
545
546
#if defined( HAVE_EVP_MD_CTX_CLEANUP )
547
    EVP_MD_CTX_cleanup(
548
     &( internal_context->internal_evp_md_context ) );
549
    ERR_remove_thread_state(
550
     NULL );
551
#else
552
    EVP_MD_CTX_free(
553
     internal_context->evp_md_context );
554
#endif
555
    internal_context->evp_md_context = NULL;
556
557
    goto on_error;
558
  }
559
#else
560
58
  if( memory_copy(
561
58
       internal_context->hash_values,
562
58
       libhmac_md5_context_fixed_constants,
563
58
       sizeof( uint32_t ) * 4 ) == NULL )
564
0
  {
565
0
    libcerror_error_set(
566
0
     error,
567
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
568
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
569
0
     "%s: unable to copy fixed constants to hash values.",
570
0
     function );
571
572
0
    goto on_error;
573
0
  }
574
58
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
575
576
58
  *context = (libhmac_md5_context_t *) internal_context;
577
578
58
  return( 1 );
579
580
0
on_error:
581
0
  if( internal_context != NULL )
582
0
  {
583
0
    memory_free(
584
0
     internal_context );
585
0
  }
586
0
  return( -1 );
587
58
}
588
589
/* Frees a MD5 context
590
 * Returns 1 if successful or -1 on error
591
 */
592
int libhmac_md5_context_free(
593
     libhmac_md5_context_t **context,
594
     libcerror_error_t **error )
595
58
{
596
58
  libhmac_internal_md5_context_t *internal_context = NULL;
597
58
  static char *function                            = "libhmac_md5_context_free";
598
599
58
  if( context == NULL )
600
0
  {
601
0
    libcerror_error_set(
602
0
     error,
603
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
604
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
605
0
     "%s: invalid context.",
606
0
     function );
607
608
0
    return( -1 );
609
0
  }
610
58
  if( *context != NULL )
611
58
  {
612
58
    internal_context = (libhmac_internal_md5_context_t *) *context;
613
58
    *context         = NULL;
614
615
#if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
616
    /* No additional clean up necessary
617
     */
618
619
#elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
620
#if defined( HAVE_EVP_MD_CTX_CLEANUP )
621
    if( EVP_MD_CTX_cleanup(
622
         &( internal_context->internal_evp_md_context ) ) != 1 )
623
    {
624
      libcerror_error_set(
625
       error,
626
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
627
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
628
       "%s: unable to clean up EVP message digest context.",
629
       function );
630
    }
631
    /* Make sure the error state is removed otherwise OpenSSL will leak memory
632
     */
633
    ERR_remove_thread_state(
634
     NULL );
635
#else
636
    EVP_MD_CTX_free(
637
     internal_context->evp_md_context );
638
639
#endif /* defined( HAVE_EVP_MD_CTX_CLEANUP ) */
640
641
    internal_context->evp_md_context = NULL;
642
#else
643
    /* No additional clean up necessary
644
     */
645
58
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
646
647
58
    memory_free(
648
58
     internal_context );
649
58
  }
650
58
  return( 1 );
651
58
}
652
653
#if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
654
655
/* Updates the MD5 context using OpenSSL
656
 * Returns 1 if successful or -1 on error
657
 */
658
int libhmac_md5_context_update(
659
     libhmac_md5_context_t *context,
660
     const uint8_t *buffer,
661
     size_t size,
662
     libcerror_error_t **error )
663
{
664
  libhmac_internal_md5_context_t *internal_context = NULL;
665
  static char *function                            = "libhmac_md5_context_update";
666
  unsigned long safe_hash_size                     = 0;
667
668
  if( context == NULL )
669
  {
670
    libcerror_error_set(
671
     error,
672
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
673
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
674
     "%s: invalid context.",
675
     function );
676
677
    return( -1 );
678
  }
679
  internal_context = (libhmac_internal_md5_context_t *) context;
680
681
  if( buffer == NULL )
682
  {
683
    libcerror_error_set(
684
     error,
685
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
686
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
687
     "%s: invalid buffer.",
688
     function );
689
690
    return( -1 );
691
  }
692
#if ( SIZEOF_LONG < SIZEOF_SIZE_T )
693
  if( size > (size_t) ULONG_MAX )
694
#else
695
  if( size > (size_t) SSIZE_MAX )
696
#endif
697
  {
698
    libcerror_error_set(
699
     error,
700
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
701
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
702
     "%s: invalid size value exceeds maximum.",
703
     function );
704
705
    return( -1 );
706
  }
707
  if( size == 0 )
708
  {
709
    return( 1 );
710
  }
711
  safe_hash_size = (unsigned long) size;
712
713
  if( MD5_Update(
714
       &( internal_context->md5_context ),
715
       (const void *) buffer,
716
       size ) != 1 )
717
  {
718
    libcerror_error_set(
719
     error,
720
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
721
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
722
     "%s: unable to update context.",
723
     function );
724
725
    return( -1 );
726
  }
727
  return( 1 );
728
}
729
730
#elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
731
732
/* Updates the MD5 context using OpenSSL EVP
733
 * Returns 1 if successful or -1 on error
734
 */
735
int libhmac_md5_context_update(
736
     libhmac_md5_context_t *context,
737
     const uint8_t *buffer,
738
     size_t size,
739
     libcerror_error_t **error )
740
{
741
  libhmac_internal_md5_context_t *internal_context = NULL;
742
  static char *function                            = "libhmac_md5_context_update";
743
744
  if( context == NULL )
745
  {
746
    libcerror_error_set(
747
     error,
748
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
749
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
750
     "%s: invalid context.",
751
     function );
752
753
    return( -1 );
754
  }
755
  internal_context = (libhmac_internal_md5_context_t *) context;
756
757
  if( buffer == NULL )
758
  {
759
    libcerror_error_set(
760
     error,
761
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
762
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
763
     "%s: invalid buffer.",
764
     function );
765
766
    return( -1 );
767
  }
768
  if( size > (size_t) SSIZE_MAX )
769
  {
770
    libcerror_error_set(
771
     error,
772
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
773
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
774
     "%s: invalid size value exceeds maximum.",
775
     function );
776
777
    return( -1 );
778
  }
779
  if( size == 0 )
780
  {
781
    return( 1 );
782
  }
783
  if( EVP_DigestUpdate(
784
       internal_context->evp_md_context,
785
       (const void *) buffer,
786
       size ) != 1 )
787
  {
788
    libcerror_error_set(
789
     error,
790
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
791
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
792
     "%s: unable to update context.",
793
     function );
794
795
    return( -1 );
796
  }
797
  return( 1 );
798
}
799
800
#else
801
802
/* Updates the MD5 context using fallback implementation
803
 * Returns 1 if successful or -1 on error
804
 */
805
int libhmac_md5_context_update(
806
     libhmac_md5_context_t *context,
807
     const uint8_t *buffer,
808
     size_t size,
809
     libcerror_error_t **error )
810
58
{
811
58
  libhmac_internal_md5_context_t *internal_context = NULL;
812
58
  static char *function                            = "libhmac_md5_context_update";
813
58
  size_t buffer_offset                             = 0;
814
58
  size_t remaining_block_size                      = 0;
815
58
  ssize_t process_count                            = 0;
816
817
58
  if( context == NULL )
818
0
  {
819
0
    libcerror_error_set(
820
0
     error,
821
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
822
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
823
0
     "%s: invalid context.",
824
0
     function );
825
826
0
    return( -1 );
827
0
  }
828
58
  internal_context = (libhmac_internal_md5_context_t *) context;
829
830
58
  if( buffer == NULL )
831
0
  {
832
0
    libcerror_error_set(
833
0
     error,
834
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
835
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
836
0
     "%s: invalid buffer.",
837
0
     function );
838
839
0
    return( -1 );
840
0
  }
841
58
  if( size > (size_t) SSIZE_MAX )
842
0
  {
843
0
    libcerror_error_set(
844
0
     error,
845
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
846
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
847
0
     "%s: invalid size value exceeds maximum.",
848
0
     function );
849
850
0
    return( -1 );
851
0
  }
852
58
  if( size == 0 )
853
0
  {
854
0
    return( 1 );
855
0
  }
856
58
  if( internal_context->block_offset > 0 )
857
0
  {
858
0
    if( internal_context->block_offset >= LIBHMAC_MD5_BLOCK_SIZE )
859
0
    {
860
0
      libcerror_error_set(
861
0
       error,
862
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
863
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
864
0
       "%s: invalid context - block offset value out of bounds.",
865
0
       function );
866
867
0
      return( -1 );
868
0
    }
869
0
    remaining_block_size = LIBHMAC_MD5_BLOCK_SIZE - internal_context->block_offset;
870
871
0
    if( remaining_block_size > size )
872
0
    {
873
0
      remaining_block_size = size;
874
0
    }
875
0
    if( memory_copy(
876
0
         &( internal_context->block[ internal_context->block_offset ] ),
877
0
         buffer,
878
0
         remaining_block_size ) == NULL )
879
0
    {
880
0
      libcerror_error_set(
881
0
       error,
882
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
883
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
884
0
       "%s: unable to copy data to context block.",
885
0
       function );
886
887
0
      return( -1 );
888
0
    }
889
0
    internal_context->block_offset += remaining_block_size;
890
891
0
    if( internal_context->block_offset < LIBHMAC_MD5_BLOCK_SIZE )
892
0
    {
893
0
      return( 1 );
894
0
    }
895
0
    buffer_offset += remaining_block_size;
896
0
    size          -= remaining_block_size;
897
898
0
    process_count = libhmac_md5_context_transform(
899
0
                     internal_context,
900
0
                     internal_context->block,
901
0
                     LIBHMAC_MD5_BLOCK_SIZE,
902
0
                     error );
903
904
0
    if( process_count == -1 )
905
0
    {
906
0
      libcerror_error_set(
907
0
       error,
908
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
909
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
910
0
       "%s: unable to transform context block.",
911
0
       function );
912
913
0
      return( -1 );
914
0
    }
915
0
    internal_context->hash_count  += process_count;
916
0
    internal_context->block_offset = 0;
917
0
  }
918
58
  if( size > 0 )
919
58
  {
920
58
    process_count = libhmac_md5_context_transform(
921
58
                     internal_context,
922
58
                     &( buffer[ buffer_offset ] ),
923
58
                     size,
924
58
                     error );
925
926
58
    if( process_count == -1 )
927
0
    {
928
0
      libcerror_error_set(
929
0
       error,
930
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
931
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
932
0
       "%s: unable to transform buffer.",
933
0
       function );
934
935
0
      return( -1 );
936
0
    }
937
58
    internal_context->hash_count += process_count;
938
939
58
    buffer_offset += process_count;
940
58
    size          -= process_count;
941
58
  }
942
58
  if( size > 0 )
943
41
  {
944
41
    if( size >= LIBHMAC_MD5_BLOCK_SIZE )
945
0
    {
946
0
      libcerror_error_set(
947
0
       error,
948
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
949
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
950
0
       "%s: invalid size value out of bounds.",
951
0
       function );
952
953
0
      return( -1 );
954
0
    }
955
41
    if( memory_copy(
956
41
         internal_context->block,
957
41
         &( buffer[ buffer_offset ] ),
958
41
         size ) == NULL )
959
0
    {
960
0
      libcerror_error_set(
961
0
       error,
962
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
963
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
964
0
       "%s: unable to copy remaining data to context block.",
965
0
       function );
966
967
0
      return( -1 );
968
0
    }
969
41
    internal_context->block_offset = size;
970
41
  }
971
58
  return( 1 );
972
58
}
973
974
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
975
976
#if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH )
977
978
/* Finalizes the MD5 context using OpenSSL
979
 * Returns 1 if successful or -1 on error
980
 */
981
int libhmac_md5_context_finalize(
982
     libhmac_md5_context_t *context,
983
     uint8_t *hash,
984
     size_t hash_size,
985
     libcerror_error_t **error )
986
{
987
  libhmac_internal_md5_context_t *internal_context = NULL;
988
  static char *function                            = "libhmac_md5_context_finalize";
989
990
  if( context == NULL )
991
  {
992
    libcerror_error_set(
993
     error,
994
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
995
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
996
     "%s: invalid context.",
997
     function );
998
999
    return( -1 );
1000
  }
1001
  internal_context = (libhmac_internal_md5_context_t *) context;
1002
1003
  if( hash == NULL )
1004
  {
1005
    libcerror_error_set(
1006
     error,
1007
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1008
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1009
     "%s: invalid hash.",
1010
     function );
1011
1012
    return( -1 );
1013
  }
1014
  if( hash_size > (size_t) SSIZE_MAX )
1015
  {
1016
    libcerror_error_set(
1017
     error,
1018
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1019
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1020
     "%s: invalid hash size value exceeds maximum.",
1021
     function );
1022
1023
    return( -1 );
1024
  }
1025
  if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1026
  {
1027
    libcerror_error_set(
1028
     error,
1029
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1030
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1031
     "%s: invalid hash size value too small.",
1032
     function );
1033
1034
    return( -1 );
1035
  }
1036
  if( MD5_Final(
1037
       hash,
1038
       &( internal_context->md5_context ) ) != 1 )
1039
  {
1040
    libcerror_error_set(
1041
     error,
1042
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1043
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1044
     "%s: unable to finalize context.",
1045
     function );
1046
1047
    return( -1 );
1048
  }
1049
  return( 1 );
1050
}
1051
1052
#elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_MD5 )
1053
1054
/* Finalizes the MD5 context using OpenSSL EVP
1055
 * Returns 1 if successful or -1 on error
1056
 */
1057
int libhmac_md5_context_finalize(
1058
     libhmac_md5_context_t *context,
1059
     uint8_t *hash,
1060
     size_t hash_size,
1061
     libcerror_error_t **error )
1062
{
1063
  libhmac_internal_md5_context_t *internal_context = NULL;
1064
  static char *function                            = "libhmac_md5_context_finalize";
1065
  unsigned int safe_hash_size                      = 0;
1066
1067
  if( context == NULL )
1068
  {
1069
    libcerror_error_set(
1070
     error,
1071
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1072
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1073
     "%s: invalid context.",
1074
     function );
1075
1076
    return( -1 );
1077
  }
1078
  internal_context = (libhmac_internal_md5_context_t *) context;
1079
1080
  if( hash == NULL )
1081
  {
1082
    libcerror_error_set(
1083
     error,
1084
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1085
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1086
     "%s: invalid hash.",
1087
     function );
1088
1089
    return( -1 );
1090
  }
1091
  if( hash_size > (size_t) UINT_MAX )
1092
  {
1093
    libcerror_error_set(
1094
     error,
1095
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1096
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1097
     "%s: invalid hash size value exceeds maximum.",
1098
     function );
1099
1100
    return( -1 );
1101
  }
1102
  if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1103
  {
1104
    libcerror_error_set(
1105
     error,
1106
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1107
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1108
     "%s: invalid hash size value too small.",
1109
     function );
1110
1111
    return( -1 );
1112
  }
1113
  safe_hash_size = (unsigned int) hash_size;
1114
1115
  if( EVP_DigestFinal_ex(
1116
       internal_context->evp_md_context,
1117
       (unsigned char *) hash,
1118
       &safe_hash_size ) != 1 )
1119
  {
1120
    libcerror_error_set(
1121
     error,
1122
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1123
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1124
     "%s: unable to finalize context.",
1125
     function );
1126
1127
    return( -1 );
1128
  }
1129
  return( 1 );
1130
}
1131
1132
#else
1133
1134
/* Finalizes the MD5 context using fallback implementation
1135
 * Returns 1 if successful or -1 on error
1136
 */
1137
int libhmac_md5_context_finalize(
1138
     libhmac_md5_context_t *context,
1139
     uint8_t *hash,
1140
     size_t hash_size,
1141
     libcerror_error_t **error )
1142
58
{
1143
58
  libhmac_internal_md5_context_t *internal_context = NULL;
1144
58
  static char *function                            = "libhmac_md5_context_finalize";
1145
58
  size_t block_size                                = 0;
1146
58
  size_t number_of_blocks                          = 0;
1147
58
  ssize_t process_count                            = 0;
1148
58
  uint64_t bit_size                                = 0;
1149
1150
#if !defined( LIBHMAC_UNFOLLED_LOOPS )
1151
  size_t hash_index                                = 0;
1152
  int hash_values_index                            = 0;
1153
#endif
1154
1155
58
  if( context == NULL )
1156
0
  {
1157
0
    libcerror_error_set(
1158
0
     error,
1159
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1160
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1161
0
     "%s: invalid context.",
1162
0
     function );
1163
1164
0
    return( -1 );
1165
0
  }
1166
58
  internal_context = (libhmac_internal_md5_context_t *) context;
1167
1168
58
  if( hash == NULL )
1169
0
  {
1170
0
    libcerror_error_set(
1171
0
     error,
1172
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1173
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1174
0
     "%s: invalid hash.",
1175
0
     function );
1176
1177
0
    return( -1 );
1178
0
  }
1179
58
  if( hash_size > (size_t) SSIZE_MAX )
1180
0
  {
1181
0
    libcerror_error_set(
1182
0
     error,
1183
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1184
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1185
0
     "%s: invalid hash size value exceeds maximum.",
1186
0
     function );
1187
1188
0
    return( -1 );
1189
0
  }
1190
58
  if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1191
0
  {
1192
0
    libcerror_error_set(
1193
0
     error,
1194
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1195
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1196
0
     "%s: invalid hash size value too small.",
1197
0
     function );
1198
1199
0
    return( -1 );
1200
0
  }
1201
  /* Add padding with a size of 56 mod 64
1202
   */
1203
58
  number_of_blocks = 1;
1204
1205
58
  if( internal_context->block_offset > 55 )
1206
25
  {
1207
25
    number_of_blocks += 1;
1208
25
  }
1209
58
  block_size = number_of_blocks * LIBHMAC_MD5_BLOCK_SIZE;
1210
1211
58
  if( memory_set(
1212
58
       &( internal_context->block[ internal_context->block_offset ] ),
1213
58
       0,
1214
58
       block_size - internal_context->block_offset ) == NULL )
1215
0
  {
1216
0
    libcerror_error_set(
1217
0
     error,
1218
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1219
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
1220
0
     "%s: unable to clear context block.",
1221
0
     function );
1222
1223
0
    return( -1 );
1224
0
  }
1225
  /* The first byte of the padding contains 0x80
1226
   */
1227
58
  internal_context->block[ internal_context->block_offset ] = 0x80;
1228
1229
58
  bit_size = ( internal_context->hash_count + internal_context->block_offset ) * 8;
1230
1231
58
  byte_stream_copy_from_uint64_little_endian(
1232
58
   &( internal_context->block[ block_size - 8 ] ),
1233
58
   bit_size );
1234
1235
58
  process_count = libhmac_md5_context_transform(
1236
58
                   internal_context,
1237
58
                   internal_context->block,
1238
58
                   block_size,
1239
58
                   error );
1240
1241
58
  if( process_count == -1 )
1242
0
  {
1243
0
    libcerror_error_set(
1244
0
     error,
1245
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1246
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1247
0
     "%s: unable to transform context block.",
1248
0
     function );
1249
1250
0
    return( -1 );
1251
0
  }
1252
#if !defined( LIBHMAC_UNFOLLED_LOOPS )
1253
  for( hash_values_index = 0;
1254
       hash_values_index < 4;
1255
       hash_values_index++ )
1256
  {
1257
    byte_stream_copy_from_uint32_little_endian(
1258
     &( hash[ hash_index ] ),
1259
     internal_context->hash_values[ hash_values_index ] );
1260
1261
    hash_index += sizeof( uint32_t );
1262
  }
1263
#else
1264
58
  byte_stream_copy_from_uint32_little_endian(
1265
58
   &( hash[ 0 ] ),
1266
58
   internal_context->hash_values[ 0 ] );
1267
1268
58
  byte_stream_copy_from_uint32_little_endian(
1269
58
   &( hash[ 4 ] ),
1270
58
   internal_context->hash_values[ 1 ] );
1271
1272
58
  byte_stream_copy_from_uint32_little_endian(
1273
58
   &( hash[ 8 ] ),
1274
58
   internal_context->hash_values[ 2 ] );
1275
1276
58
  byte_stream_copy_from_uint32_little_endian(
1277
58
   &( hash[ 12 ] ),
1278
58
   internal_context->hash_values[ 3 ] );
1279
1280
58
#endif /* !defined( LIBHMAC_UNFOLLED_LOOPS ) */
1281
1282
  /* Prevent sensitive data from leaking
1283
   */
1284
58
  if( memory_set(
1285
58
       internal_context,
1286
58
       0,
1287
58
       sizeof( libhmac_internal_md5_context_t ) ) == NULL )
1288
0
  {
1289
0
    libcerror_error_set(
1290
0
     error,
1291
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1292
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
1293
0
     "%s: unable to clear context.",
1294
0
     function );
1295
1296
0
    return( -1 );
1297
0
  }
1298
58
  return( 1 );
1299
58
}
1300
1301
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
1302