/src/libfvde/libfvde/libfvde_sector_data.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Sector data functions |
3 | | * |
4 | | * Copyright (C) 2011-2024, Omar Choudary <choudary.omar@gmail.com> |
5 | | * Joachim Metz <joachim.metz@gmail.com> |
6 | | * |
7 | | * Refer to AUTHORS for acknowledgements. |
8 | | * |
9 | | * This program is free software: you can redistribute it and/or modify |
10 | | * it under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation, either version 3 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
21 | | */ |
22 | | |
23 | | #include <common.h> |
24 | | #include <byte_stream.h> |
25 | | #include <memory.h> |
26 | | #include <types.h> |
27 | | |
28 | | #include "libfvde_definitions.h" |
29 | | #include "libfvde_encryption_context.h" |
30 | | #include "libfvde_libbfio.h" |
31 | | #include "libfvde_libcerror.h" |
32 | | #include "libfvde_libcnotify.h" |
33 | | #include "libfvde_sector_data.h" |
34 | | |
35 | | /* Creates sector data |
36 | | * Make sure the value sector_data is referencing, is set to NULL |
37 | | * Returns 1 if successful or -1 on error |
38 | | */ |
39 | | int libfvde_sector_data_initialize( |
40 | | libfvde_sector_data_t **sector_data, |
41 | | size_t data_size, |
42 | | libcerror_error_t **error ) |
43 | 0 | { |
44 | 0 | static char *function = "libfvde_sector_data_initialize"; |
45 | |
|
46 | 0 | if( sector_data == NULL ) |
47 | 0 | { |
48 | 0 | libcerror_error_set( |
49 | 0 | error, |
50 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
51 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
52 | 0 | "%s: invalid sector data.", |
53 | 0 | function ); |
54 | |
|
55 | 0 | return( -1 ); |
56 | 0 | } |
57 | 0 | if( ( data_size == 0 ) |
58 | 0 | || ( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) ) |
59 | 0 | { |
60 | 0 | libcerror_error_set( |
61 | 0 | error, |
62 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
63 | 0 | LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS, |
64 | 0 | "%s: invalid data size value out of bounds.", |
65 | 0 | function ); |
66 | |
|
67 | 0 | return( -1 ); |
68 | 0 | } |
69 | 0 | if( *sector_data != NULL ) |
70 | 0 | { |
71 | 0 | libcerror_error_set( |
72 | 0 | error, |
73 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
74 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET, |
75 | 0 | "%s: invalid sector data value already set.", |
76 | 0 | function ); |
77 | |
|
78 | 0 | return( -1 ); |
79 | 0 | } |
80 | 0 | *sector_data = memory_allocate_structure( |
81 | 0 | libfvde_sector_data_t ); |
82 | |
|
83 | 0 | if( *sector_data == NULL ) |
84 | 0 | { |
85 | 0 | libcerror_error_set( |
86 | 0 | error, |
87 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
88 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
89 | 0 | "%s: unable to sector data.", |
90 | 0 | function ); |
91 | |
|
92 | 0 | goto on_error; |
93 | 0 | } |
94 | 0 | if( memory_set( |
95 | 0 | *sector_data, |
96 | 0 | 0, |
97 | 0 | sizeof( libfvde_sector_data_t ) ) == NULL ) |
98 | 0 | { |
99 | 0 | libcerror_error_set( |
100 | 0 | error, |
101 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
102 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
103 | 0 | "%s: unable to clear sector data.", |
104 | 0 | function ); |
105 | |
|
106 | 0 | memory_free( |
107 | 0 | *sector_data ); |
108 | |
|
109 | 0 | *sector_data = NULL; |
110 | |
|
111 | 0 | return( -1 ); |
112 | 0 | } |
113 | 0 | ( *sector_data )->data = (uint8_t *) memory_allocate( |
114 | 0 | sizeof( uint8_t ) * data_size ); |
115 | |
|
116 | 0 | if( ( *sector_data )->data == NULL ) |
117 | 0 | { |
118 | 0 | libcerror_error_set( |
119 | 0 | error, |
120 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
121 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
122 | 0 | "%s: unable to create data.", |
123 | 0 | function ); |
124 | |
|
125 | 0 | goto on_error; |
126 | 0 | } |
127 | 0 | ( *sector_data )->data_size = data_size; |
128 | |
|
129 | 0 | return( 1 ); |
130 | | |
131 | 0 | on_error: |
132 | 0 | if( *sector_data != NULL ) |
133 | 0 | { |
134 | 0 | memory_free( |
135 | 0 | *sector_data ); |
136 | |
|
137 | 0 | *sector_data = NULL; |
138 | 0 | } |
139 | 0 | return( -1 ); |
140 | 0 | } |
141 | | |
142 | | /* Frees sector data |
143 | | * Returns 1 if successful or -1 on error |
144 | | */ |
145 | | int libfvde_sector_data_free( |
146 | | libfvde_sector_data_t **sector_data, |
147 | | libcerror_error_t **error ) |
148 | 0 | { |
149 | 0 | static char *function = "libfvde_sector_data_free"; |
150 | 0 | int result = 1; |
151 | |
|
152 | 0 | if( sector_data == NULL ) |
153 | 0 | { |
154 | 0 | libcerror_error_set( |
155 | 0 | error, |
156 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
157 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
158 | 0 | "%s: invalid sector data.", |
159 | 0 | function ); |
160 | |
|
161 | 0 | return( -1 ); |
162 | 0 | } |
163 | 0 | if( *sector_data != NULL ) |
164 | 0 | { |
165 | 0 | if( ( *sector_data )->data != NULL ) |
166 | 0 | { |
167 | 0 | if( memory_set( |
168 | 0 | ( *sector_data )->data, |
169 | 0 | 0, |
170 | 0 | ( *sector_data )->data_size ) == NULL ) |
171 | 0 | { |
172 | 0 | libcerror_error_set( |
173 | 0 | error, |
174 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
175 | 0 | LIBCERROR_MEMORY_ERROR_SET_FAILED, |
176 | 0 | "%s: unable to clear data.", |
177 | 0 | function ); |
178 | |
|
179 | 0 | result = -1; |
180 | 0 | } |
181 | 0 | memory_free( |
182 | 0 | ( *sector_data )->data ); |
183 | 0 | } |
184 | 0 | memory_free( |
185 | 0 | *sector_data ); |
186 | |
|
187 | 0 | *sector_data = NULL; |
188 | 0 | } |
189 | 0 | return( result ); |
190 | 0 | } |
191 | | |
192 | | /* Reads sector data |
193 | | * Returns 1 if successful or -1 on error |
194 | | */ |
195 | | int libfvde_sector_data_read( |
196 | | libfvde_sector_data_t *sector_data, |
197 | | libfvde_encryption_context_t *encryption_context, |
198 | | libbfio_pool_t *file_io_pool, |
199 | | int file_io_pool_entry, |
200 | | off64_t file_offset, |
201 | | uint64_t block_number, |
202 | | uint8_t is_encrypted, |
203 | | libcerror_error_t **error ) |
204 | 0 | { |
205 | 0 | uint8_t *encrypted_data = NULL; |
206 | 0 | static char *function = "libfvde_sector_data_read"; |
207 | 0 | ssize_t read_count = 0; |
208 | |
|
209 | 0 | if( sector_data == NULL ) |
210 | 0 | { |
211 | 0 | libcerror_error_set( |
212 | 0 | error, |
213 | 0 | LIBCERROR_ERROR_DOMAIN_ARGUMENTS, |
214 | 0 | LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, |
215 | 0 | "%s: invalid sector data.", |
216 | 0 | function ); |
217 | |
|
218 | 0 | return( -1 ); |
219 | 0 | } |
220 | 0 | if( sector_data->data == NULL ) |
221 | 0 | { |
222 | 0 | libcerror_error_set( |
223 | 0 | error, |
224 | 0 | LIBCERROR_ERROR_DOMAIN_RUNTIME, |
225 | 0 | LIBCERROR_RUNTIME_ERROR_VALUE_MISSING, |
226 | 0 | "%s: invalid sector data - missing data.", |
227 | 0 | function ); |
228 | |
|
229 | 0 | return( -1 ); |
230 | 0 | } |
231 | | #if defined( HAVE_DEBUG_OUTPUT ) |
232 | | if( libcnotify_verbose != 0 ) |
233 | | { |
234 | | libcnotify_printf( |
235 | | "%s: reading sector data at offset: %" PRIi64 " (0x%08" PRIx64 ")\n", |
236 | | function, |
237 | | file_offset, |
238 | | file_offset ); |
239 | | } |
240 | | #endif |
241 | 0 | if( is_encrypted != 0 ) |
242 | 0 | { |
243 | 0 | encrypted_data = (uint8_t *) memory_allocate( |
244 | 0 | sizeof( uint8_t ) * sector_data->data_size ); |
245 | |
|
246 | 0 | if( encrypted_data == NULL ) |
247 | 0 | { |
248 | 0 | libcerror_error_set( |
249 | 0 | error, |
250 | 0 | LIBCERROR_ERROR_DOMAIN_MEMORY, |
251 | 0 | LIBCERROR_MEMORY_ERROR_INSUFFICIENT, |
252 | 0 | "%s: unable to create encrypted data.", |
253 | 0 | function ); |
254 | |
|
255 | 0 | goto on_error; |
256 | 0 | } |
257 | 0 | read_count = libbfio_pool_read_buffer_at_offset( |
258 | 0 | file_io_pool, |
259 | 0 | file_io_pool_entry, |
260 | 0 | encrypted_data, |
261 | 0 | sector_data->data_size, |
262 | 0 | file_offset, |
263 | 0 | error ); |
264 | |
|
265 | 0 | if( read_count != (ssize_t) sector_data->data_size ) |
266 | 0 | { |
267 | 0 | libcerror_error_set( |
268 | 0 | error, |
269 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
270 | 0 | LIBCERROR_IO_ERROR_READ_FAILED, |
271 | 0 | "%s: unable to read encrypted data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
272 | 0 | function, |
273 | 0 | file_offset, |
274 | 0 | file_offset ); |
275 | |
|
276 | 0 | goto on_error; |
277 | 0 | } |
278 | | #if defined( HAVE_DEBUG_OUTPUT ) |
279 | | if( libcnotify_verbose != 0 ) |
280 | | { |
281 | | libcnotify_printf( |
282 | | "%s: encrypted data:\n", |
283 | | function ); |
284 | | libcnotify_print_data( |
285 | | encrypted_data, |
286 | | sector_data->data_size, |
287 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
288 | | |
289 | | libcnotify_printf( |
290 | | "%s: tweak value: %" PRIu64 ".\n", |
291 | | function, |
292 | | block_number ); |
293 | | |
294 | | libcnotify_printf( |
295 | | "\n" ); |
296 | | } |
297 | | #endif /* defined( HAVE_DEBUG_OUTPUT ) */ |
298 | | |
299 | 0 | if( libfvde_encryption_context_crypt( |
300 | 0 | encryption_context, |
301 | 0 | LIBFVDE_ENCRYPTION_CRYPT_MODE_DECRYPT, |
302 | 0 | encrypted_data, |
303 | 0 | sector_data->data_size, |
304 | 0 | sector_data->data, |
305 | 0 | sector_data->data_size, |
306 | 0 | block_number, |
307 | 0 | error ) != 1 ) |
308 | 0 | { |
309 | 0 | libcerror_error_set( |
310 | 0 | error, |
311 | 0 | LIBCERROR_ERROR_DOMAIN_ENCRYPTION, |
312 | 0 | LIBCERROR_ENCRYPTION_ERROR_GENERIC, |
313 | 0 | "%s: unable to decrypt data.", |
314 | 0 | function ); |
315 | |
|
316 | 0 | goto on_error; |
317 | 0 | } |
318 | 0 | memory_free( |
319 | 0 | encrypted_data ); |
320 | |
|
321 | 0 | encrypted_data = NULL; |
322 | 0 | } |
323 | 0 | else |
324 | 0 | { |
325 | 0 | read_count = libbfio_pool_read_buffer_at_offset( |
326 | 0 | file_io_pool, |
327 | 0 | file_io_pool_entry, |
328 | 0 | sector_data->data, |
329 | 0 | sector_data->data_size, |
330 | 0 | file_offset, |
331 | 0 | error ); |
332 | |
|
333 | 0 | if( read_count != (ssize_t) sector_data->data_size ) |
334 | 0 | { |
335 | 0 | libcerror_error_set( |
336 | 0 | error, |
337 | 0 | LIBCERROR_ERROR_DOMAIN_IO, |
338 | 0 | LIBCERROR_IO_ERROR_READ_FAILED, |
339 | 0 | "%s: unable to read sector data at offset: %" PRIi64 " (0x%08" PRIx64 ").", |
340 | 0 | function, |
341 | 0 | file_offset, |
342 | 0 | file_offset ); |
343 | |
|
344 | 0 | goto on_error; |
345 | 0 | } |
346 | 0 | } |
347 | | #if defined( HAVE_DEBUG_OUTPUT ) |
348 | | if( libcnotify_verbose != 0 ) |
349 | | { |
350 | | libcnotify_printf( |
351 | | "%s: sector data:\n", |
352 | | function ); |
353 | | libcnotify_print_data( |
354 | | sector_data->data, |
355 | | sector_data->data_size, |
356 | | LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA ); |
357 | | } |
358 | | #endif |
359 | 0 | return( 1 ); |
360 | | |
361 | 0 | on_error: |
362 | 0 | if( encrypted_data != NULL ) |
363 | 0 | { |
364 | 0 | memory_free( |
365 | 0 | encrypted_data ); |
366 | 0 | } |
367 | 0 | return( -1 ); |
368 | 0 | } |
369 | | |