/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 | | |