Coverage Report

Created: 2024-02-25 07:20

/src/libewf/libhmac/libhmac_md5_context.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * MD5 functions
3
 *
4
 * Copyright (C) 2011-2024, 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
2.10M
  hash_values[ hash_value_index0 ] += ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index2 ] ) \
97
2.10M
                                    | ( ~( hash_values[ hash_value_index1 ] ) & hash_values[ hash_value_index3 ] ); \
98
2.10M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
99
2.10M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
100
2.10M
\
101
2.10M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
102
2.10M
                                      hash_values[ hash_value_index0 ],  \
103
2.10M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
104
2.10M
\
105
2.10M
  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
2.10M
  hash_values[ hash_value_index0 ] += ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index3 ] ) \
109
2.10M
                                    | ( hash_values[ hash_value_index2 ] & ~( hash_values[ hash_value_index3 ] ) ); \
110
2.10M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
111
2.10M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
112
2.10M
\
113
2.10M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
114
2.10M
                                      hash_values[ hash_value_index0 ],  \
115
2.10M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
116
2.10M
\
117
2.10M
  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
2.10M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index1 ] \
121
2.10M
                                    ^ hash_values[ hash_value_index2 ] \
122
2.10M
                                    ^ hash_values[ hash_value_index3 ]; \
123
2.10M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
124
2.10M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
125
2.10M
\
126
2.10M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
127
2.10M
                                      hash_values[ hash_value_index0 ],  \
128
2.10M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
129
2.10M
\
130
2.10M
  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
2.10M
  hash_values[ hash_value_index0 ] += hash_values[ hash_value_index2 ] \
134
2.10M
                                    ^ ( hash_values[ hash_value_index1 ] | ~( hash_values[ hash_value_index3 ] ) ); \
135
2.10M
  hash_values[ hash_value_index0 ] += values_32bit[ value_32bit_index ]; \
136
2.10M
  hash_values[ hash_value_index0 ] += libhmac_md5_context_sines[ block_index ]; \
137
2.10M
\
138
2.10M
  hash_values[ hash_value_index0 ] = byte_stream_bit_rotate_left_32bit( \
139
2.10M
                                      hash_values[ hash_value_index0 ],  \
140
2.10M
                                      libhmac_md5_context_bit_shifts[ block_index ] ); \
141
2.10M
\
142
2.10M
  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
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 0, hash_values, 0, 1, 2, 3, 0 ); \
146
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 1, hash_values, 3, 0, 1, 2, 1 ); \
147
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 2, hash_values, 2, 3, 0, 1, 2 ); \
148
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 3, hash_values, 1, 2, 3, 0, 3 ); \
149
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 4, hash_values, 0, 1, 2, 3, 4 ); \
150
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 5, hash_values, 3, 0, 1, 2, 5 ); \
151
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 6, hash_values, 2, 3, 0, 1, 6 ); \
152
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 7, hash_values, 1, 2, 3, 0, 7 ); \
153
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 8, hash_values, 0, 1, 2, 3, 8 ); \
154
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 9, hash_values, 3, 0, 1, 2, 9 ); \
155
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 10, hash_values, 2, 3, 0, 1, 10 ); \
156
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 11, hash_values, 1, 2, 3, 0, 11 ); \
157
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 12, hash_values, 0, 1, 2, 3, 12 ); \
158
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 13, hash_values, 3, 0, 1, 2, 13 ); \
159
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 14, hash_values, 2, 3, 0, 1, 14 ); \
160
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round1( values_32bit, 15, hash_values, 1, 2, 3, 0, 15 ); \
161
131k
\
162
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 1, hash_values, 0, 1, 2, 3, 16 ); \
163
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 6, hash_values, 3, 0, 1, 2, 17 ); \
164
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 11, hash_values, 2, 3, 0, 1, 18 ); \
165
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 0, hash_values, 1, 2, 3, 0, 19 ); \
166
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 5, hash_values, 0, 1, 2, 3, 20 ); \
167
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 10, hash_values, 3, 0, 1, 2, 21 ); \
168
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 15, hash_values, 2, 3, 0, 1, 22 ); \
169
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 4, hash_values, 1, 2, 3, 0, 23 ); \
170
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 9, hash_values, 0, 1, 2, 3, 24 ); \
171
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 14, hash_values, 3, 0, 1, 2, 25 ); \
172
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 3, hash_values, 2, 3, 0, 1, 26 ); \
173
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 8, hash_values, 1, 2, 3, 0, 27 ); \
174
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 13, hash_values, 0, 1, 2, 3, 28 ); \
175
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 2, hash_values, 3, 0, 1, 2, 29 ); \
176
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 7, hash_values, 2, 3, 0, 1, 30 ); \
177
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round2( values_32bit, 12, hash_values, 1, 2, 3, 0, 31 ); \
178
131k
\
179
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 5, hash_values, 0, 1, 2, 3, 32 ); \
180
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 8, hash_values, 3, 0, 1, 2, 33 ); \
181
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 11, hash_values, 2, 3, 0, 1, 34 ); \
182
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 14, hash_values, 1, 2, 3, 0, 35 ); \
183
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 1, hash_values, 0, 1, 2, 3, 36 ); \
184
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 4, hash_values, 3, 0, 1, 2, 37 ); \
185
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 7, hash_values, 2, 3, 0, 1, 38 ); \
186
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 10, hash_values, 1, 2, 3, 0, 39 ); \
187
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 13, hash_values, 0, 1, 2, 3, 40 ); \
188
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 0, hash_values, 3, 0, 1, 2, 41 ); \
189
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 3, hash_values, 2, 3, 0, 1, 42 ); \
190
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 6, hash_values, 1, 2, 3, 0, 43 ); \
191
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 9, hash_values, 0, 1, 2, 3, 44 ); \
192
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 12, hash_values, 3, 0, 1, 2, 45 ); \
193
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 15, hash_values, 2, 3, 0, 1, 46 ); \
194
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round3( values_32bit, 2, hash_values, 1, 2, 3, 0, 47 ); \
195
131k
\
196
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 0, hash_values, 0, 1, 2, 3, 48 ); \
197
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 7, hash_values, 3, 0, 1, 2, 49 ); \
198
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 14, hash_values, 2, 3, 0, 1, 50 ); \
199
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 5, hash_values, 1, 2, 3, 0, 51 ); \
200
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 12, hash_values, 0, 1, 2, 3, 52 ); \
201
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 3, hash_values, 3, 0, 1, 2, 53 ); \
202
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 10, hash_values, 2, 3, 0, 1, 54 ); \
203
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 1, hash_values, 1, 2, 3, 0, 55 ); \
204
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 8, hash_values, 0, 1, 2, 3, 56 ); \
205
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 15, hash_values, 3, 0, 1, 2, 57 ); \
206
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 6, hash_values, 2, 3, 0, 1, 58 ); \
207
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 13, hash_values, 1, 2, 3, 0, 59 ); \
208
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 4, hash_values, 0, 1, 2, 3, 60 ); \
209
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 11, hash_values, 3, 0, 1, 2, 61 ); \
210
131k
  libhmac_md5_context_transform_unfolded_calculate_hash_value_round4( values_32bit, 2, hash_values, 2, 3, 0, 1, 62 ); \
211
131k
  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
118
{
222
118
  uint32_t hash_values[ 4 ];
223
118
  uint32_t values_32bit[ 16 ];
224
225
118
  static char *function     = "libhmac_md5_context_transform";
226
118
  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
118
  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
118
  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
118
  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
131k
  while( size >= LIBHMAC_MD5_BLOCK_SIZE )
269
131k
  {
270
131k
    if( memory_copy(
271
131k
         hash_values,
272
131k
         internal_context->hash_values,
273
131k
         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
131k
#if defined( LIBHMAC_UNFOLLED_LOOPS )
285
    /* Break the block into 16 x 32-bit values
286
     */
287
131k
    libhmac_byte_stream_copy_to_16x_uint32_little_endian(
288
131k
     &( buffer[ buffer_offset ] ),
289
131k
     values_32bit );
290
291
131k
    buffer_offset += LIBHMAC_MD5_BLOCK_SIZE;
292
293
    /* Calculate the hash values for the 32-bit values
294
     */
295
131k
    libhmac_md5_context_transform_unfolded_calculate_hash_values(
296
131k
     values_32bit,
297
131k
     hash_values );
298
299
    /* Update the hash values in the context
300
     */
301
131k
    internal_context->hash_values[ 0 ] += hash_values[ 0 ];
302
131k
    internal_context->hash_values[ 1 ] += hash_values[ 1 ];
303
131k
    internal_context->hash_values[ 2 ] += hash_values[ 2 ];
304
131k
    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
131k
    size -= LIBHMAC_MD5_BLOCK_SIZE;
371
131k
  }
372
  /* Prevent sensitive data from leaking
373
   */
374
118
  if( memory_set(
375
118
       hash_values,
376
118
       0,
377
118
       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
118
  if( memory_set(
389
118
       values_32bit,
390
118
       0,
391
118
       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
118
  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
118
}
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
59
{
428
59
  libhmac_internal_md5_context_t *internal_context = NULL;
429
59
  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
59
  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
59
  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
59
  internal_context = memory_allocate_structure(
458
59
                      libhmac_internal_md5_context_t );
459
460
59
  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
59
  if( memory_set(
472
59
       internal_context,
473
59
       0,
474
59
       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
59
  if( memory_copy(
561
59
       internal_context->hash_values,
562
59
       libhmac_md5_context_fixed_constants,
563
59
       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
59
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
575
576
59
  *context = (libhmac_md5_context_t *) internal_context;
577
578
59
  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
59
}
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
59
{
596
59
  libhmac_internal_md5_context_t *internal_context = NULL;
597
59
  static char *function                            = "libhmac_md5_context_free";
598
599
59
  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
59
  if( *context != NULL )
611
59
  {
612
59
    internal_context = (libhmac_internal_md5_context_t *) *context;
613
59
    *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
59
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
646
647
59
    memory_free(
648
59
     internal_context );
649
59
  }
650
59
  return( 1 );
651
59
}
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
59
{
811
59
  libhmac_internal_md5_context_t *internal_context = NULL;
812
59
  static char *function                            = "libhmac_md5_context_update";
813
59
  size_t buffer_offset                             = 0;
814
59
  size_t remaining_block_size                      = 0;
815
59
  ssize_t process_count                            = 0;
816
817
59
  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
59
  internal_context = (libhmac_internal_md5_context_t *) context;
829
830
59
  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
59
  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
59
  if( size == 0 )
853
0
  {
854
0
    return( 1 );
855
0
  }
856
59
  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
59
  if( size > 0 )
919
59
  {
920
59
    process_count = libhmac_md5_context_transform(
921
59
                     internal_context,
922
59
                     &( buffer[ buffer_offset ] ),
923
59
                     size,
924
59
                     error );
925
926
59
    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
59
    internal_context->hash_count += process_count;
938
939
59
    buffer_offset += process_count;
940
59
    size          -= process_count;
941
59
  }
942
59
  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
59
  return( 1 );
972
59
}
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) LIBHMAC_MD5_HASH_SIZE )
1092
   || ( hash_size > (size_t) UINT_MAX ) )
1093
  {
1094
    libcerror_error_set(
1095
     error,
1096
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1097
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
1098
     "%s: invalid hash size value out of bounds.",
1099
     function );
1100
1101
    return( -1 );
1102
  }
1103
  safe_hash_size = (unsigned int) hash_size;
1104
1105
  if( EVP_DigestFinal_ex(
1106
       internal_context->evp_md_context,
1107
       (unsigned char *) hash,
1108
       &safe_hash_size ) != 1 )
1109
  {
1110
    libcerror_error_set(
1111
     error,
1112
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1113
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1114
     "%s: unable to finalize context.",
1115
     function );
1116
1117
    return( -1 );
1118
  }
1119
  return( 1 );
1120
}
1121
1122
#else
1123
1124
/* Finalizes the MD5 context using fallback implementation
1125
 * Returns 1 if successful or -1 on error
1126
 */
1127
int libhmac_md5_context_finalize(
1128
     libhmac_md5_context_t *context,
1129
     uint8_t *hash,
1130
     size_t hash_size,
1131
     libcerror_error_t **error )
1132
59
{
1133
59
  libhmac_internal_md5_context_t *internal_context = NULL;
1134
59
  static char *function                            = "libhmac_md5_context_finalize";
1135
59
  size_t block_size                                = 0;
1136
59
  size_t number_of_blocks                          = 0;
1137
59
  ssize_t process_count                            = 0;
1138
59
  uint64_t bit_size                                = 0;
1139
1140
#if !defined( LIBHMAC_UNFOLLED_LOOPS )
1141
  size_t hash_index                                = 0;
1142
  int hash_values_index                            = 0;
1143
#endif
1144
1145
59
  if( context == NULL )
1146
0
  {
1147
0
    libcerror_error_set(
1148
0
     error,
1149
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1150
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1151
0
     "%s: invalid context.",
1152
0
     function );
1153
1154
0
    return( -1 );
1155
0
  }
1156
59
  internal_context = (libhmac_internal_md5_context_t *) context;
1157
1158
59
  if( hash == NULL )
1159
0
  {
1160
0
    libcerror_error_set(
1161
0
     error,
1162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1164
0
     "%s: invalid hash.",
1165
0
     function );
1166
1167
0
    return( -1 );
1168
0
  }
1169
59
  if( hash_size > (size_t) SSIZE_MAX )
1170
0
  {
1171
0
    libcerror_error_set(
1172
0
     error,
1173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1174
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1175
0
     "%s: invalid hash size value exceeds maximum.",
1176
0
     function );
1177
1178
0
    return( -1 );
1179
0
  }
1180
59
  if( hash_size < (size_t) LIBHMAC_MD5_HASH_SIZE )
1181
0
  {
1182
0
    libcerror_error_set(
1183
0
     error,
1184
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1185
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1186
0
     "%s: invalid hash size value too small.",
1187
0
     function );
1188
1189
0
    return( -1 );
1190
0
  }
1191
  /* Add padding with a size of 56 mod 64
1192
   */
1193
59
  number_of_blocks = 1;
1194
1195
59
  if( internal_context->block_offset > 55 )
1196
25
  {
1197
25
    number_of_blocks += 1;
1198
25
  }
1199
59
  block_size = number_of_blocks * LIBHMAC_MD5_BLOCK_SIZE;
1200
1201
59
  if( memory_set(
1202
59
       &( internal_context->block[ internal_context->block_offset ] ),
1203
59
       0,
1204
59
       block_size - internal_context->block_offset ) == NULL )
1205
0
  {
1206
0
    libcerror_error_set(
1207
0
     error,
1208
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1209
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
1210
0
     "%s: unable to clear context block.",
1211
0
     function );
1212
1213
0
    return( -1 );
1214
0
  }
1215
  /* The first byte of the padding contains 0x80
1216
   */
1217
59
  internal_context->block[ internal_context->block_offset ] = 0x80;
1218
1219
59
  bit_size = ( internal_context->hash_count + internal_context->block_offset ) * 8;
1220
1221
59
  byte_stream_copy_from_uint64_little_endian(
1222
59
   &( internal_context->block[ block_size - 8 ] ),
1223
59
   bit_size );
1224
1225
59
  process_count = libhmac_md5_context_transform(
1226
59
                   internal_context,
1227
59
                   internal_context->block,
1228
59
                   block_size,
1229
59
                   error );
1230
1231
59
  if( process_count == -1 )
1232
0
  {
1233
0
    libcerror_error_set(
1234
0
     error,
1235
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1236
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1237
0
     "%s: unable to transform context block.",
1238
0
     function );
1239
1240
0
    return( -1 );
1241
0
  }
1242
#if !defined( LIBHMAC_UNFOLLED_LOOPS )
1243
  for( hash_values_index = 0;
1244
       hash_values_index < 4;
1245
       hash_values_index++ )
1246
  {
1247
    byte_stream_copy_from_uint32_little_endian(
1248
     &( hash[ hash_index ] ),
1249
     internal_context->hash_values[ hash_values_index ] );
1250
1251
    hash_index += sizeof( uint32_t );
1252
  }
1253
#else
1254
59
  byte_stream_copy_from_uint32_little_endian(
1255
59
   &( hash[ 0 ] ),
1256
59
   internal_context->hash_values[ 0 ] );
1257
1258
59
  byte_stream_copy_from_uint32_little_endian(
1259
59
   &( hash[ 4 ] ),
1260
59
   internal_context->hash_values[ 1 ] );
1261
1262
59
  byte_stream_copy_from_uint32_little_endian(
1263
59
   &( hash[ 8 ] ),
1264
59
   internal_context->hash_values[ 2 ] );
1265
1266
59
  byte_stream_copy_from_uint32_little_endian(
1267
59
   &( hash[ 12 ] ),
1268
59
   internal_context->hash_values[ 3 ] );
1269
1270
59
#endif /* !defined( LIBHMAC_UNFOLLED_LOOPS ) */
1271
1272
  /* Prevent sensitive data from leaking
1273
   */
1274
59
  if( memory_set(
1275
59
       internal_context,
1276
59
       0,
1277
59
       sizeof( libhmac_internal_md5_context_t ) ) == NULL )
1278
0
  {
1279
0
    libcerror_error_set(
1280
0
     error,
1281
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
1282
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
1283
0
     "%s: unable to clear context.",
1284
0
     function );
1285
1286
0
    return( -1 );
1287
0
  }
1288
59
  return( 1 );
1289
59
}
1290
1291
#endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_MD5_H ) && defined( MD5_DIGEST_LENGTH ) */
1292