Coverage Report

Created: 2026-01-20 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libbde/libbde/libbde_io_handle.c
Line
Count
Source
1
/*
2
 * Input/Output (IO) handle functions
3
 *
4
 * Copyright (C) 2011-2025, 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
#include "libbde_definitions.h"
28
#include "libbde_encryption_context.h"
29
#include "libbde_io_handle.h"
30
#include "libbde_libbfio.h"
31
#include "libbde_libcerror.h"
32
#include "libbde_libcnotify.h"
33
#include "libbde_ntfs_volume_header.h"
34
#include "libbde_sector_data.h"
35
#include "libbde_unused.h"
36
37
#include "bde_volume.h"
38
39
/* Creates an IO handle
40
 * Make sure the value io_handle is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libbde_io_handle_initialize(
44
     libbde_io_handle_t **io_handle,
45
     libcerror_error_t **error )
46
2.33k
{
47
2.33k
  static char *function = "libbde_io_handle_initialize";
48
49
2.33k
  if( io_handle == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid IO handle.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
2.33k
  if( *io_handle != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid IO handle value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
2.33k
  *io_handle = memory_allocate_structure(
72
2.33k
                libbde_io_handle_t );
73
74
2.33k
  if( *io_handle == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
79
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80
0
     "%s: unable to create IO handle.",
81
0
     function );
82
83
0
    goto on_error;
84
0
  }
85
2.33k
  if( memory_set(
86
2.33k
       *io_handle,
87
2.33k
       0,
88
2.33k
       sizeof( libbde_io_handle_t ) ) == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
94
0
     "%s: unable to clear IO handle.",
95
0
     function );
96
97
0
    goto on_error;
98
0
  }
99
2.33k
  ( *io_handle )->bytes_per_sector = 512;
100
101
2.33k
  return( 1 );
102
103
0
on_error:
104
0
  if( *io_handle != NULL )
105
0
  {
106
0
    memory_free(
107
0
     *io_handle );
108
109
0
    *io_handle = NULL;
110
0
  }
111
0
  return( -1 );
112
2.33k
}
113
114
/* Frees an IO handle
115
 * Returns 1 if successful or -1 on error
116
 */
117
int libbde_io_handle_free(
118
     libbde_io_handle_t **io_handle,
119
     libcerror_error_t **error )
120
2.33k
{
121
2.33k
  static char *function = "libbde_io_handle_free";
122
2.33k
  int result            = 1;
123
124
2.33k
  if( io_handle == NULL )
125
0
  {
126
0
    libcerror_error_set(
127
0
     error,
128
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
129
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
130
0
     "%s: invalid IO handle.",
131
0
     function );
132
133
0
    return( -1 );
134
0
  }
135
2.33k
  if( *io_handle != NULL )
136
2.33k
  {
137
2.33k
    if( libbde_io_handle_clear(
138
2.33k
         *io_handle,
139
2.33k
         error ) != 1 )
140
0
    {
141
0
      libcerror_error_set(
142
0
       error,
143
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
144
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
145
0
       "%s: unable to clear IO handle.",
146
0
       function );
147
148
0
      result = -1;
149
0
    }
150
2.33k
    memory_free(
151
2.33k
     *io_handle );
152
153
2.33k
    *io_handle = NULL;
154
2.33k
  }
155
2.33k
  return( result );
156
2.33k
}
157
158
/* Clears the IO handle
159
 * Returns 1 if successful or -1 on error
160
 */
161
int libbde_io_handle_clear(
162
     libbde_io_handle_t *io_handle,
163
     libcerror_error_t **error )
164
2.66k
{
165
2.66k
  static char *function = "libbde_io_handle_clear";
166
167
2.66k
  if( io_handle == NULL )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173
0
     "%s: invalid IO handle.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
2.66k
  io_handle->bytes_per_sector = 512;
179
180
2.66k
  return( 1 );
181
2.66k
}
182
183
/* Reads the unencrypted volume header
184
 * Returns 1 if successful or -1 on error
185
 */
186
int libbde_io_handle_read_unencrypted_volume_header(
187
     libbde_io_handle_t *io_handle,
188
     libbfio_handle_t *file_io_handle,
189
     off64_t volume_header_offset,
190
     libbde_encryption_context_t *encryption_context,
191
     libcerror_error_t **error )
192
763
{
193
763
  libbde_ntfs_volume_header_t *ntfs_volume_header = NULL;
194
763
  libbde_sector_data_t *sector_data               = NULL;
195
763
  static char *function                           = "libbde_io_handle_read_unencrypted_volume_header";
196
197
763
  if( io_handle == NULL )
198
0
  {
199
0
    libcerror_error_set(
200
0
     error,
201
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
202
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
203
0
     "%s: invalid IO handle.",
204
0
     function );
205
206
0
    goto on_error;
207
0
  }
208
#if defined( HAVE_DEBUG_OUTPUT )
209
  if( libcnotify_verbose != 0 )
210
  {
211
    libcnotify_printf(
212
     "%s: reading unencrypted volume header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
213
     function,
214
     volume_header_offset,
215
     volume_header_offset );
216
  }
217
#endif
218
763
  if( libbde_sector_data_initialize(
219
763
       &sector_data,
220
763
       io_handle->bytes_per_sector,
221
763
       error ) != 1 )
222
0
  {
223
0
    libcerror_error_set(
224
0
     error,
225
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
226
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
227
0
     "%s: unable to create sector data.",
228
0
     function );
229
230
0
    goto on_error;
231
0
  }
232
763
  if( libbde_sector_data_read_file_io_handle(
233
763
       sector_data,
234
763
       io_handle,
235
763
       file_io_handle,
236
763
       volume_header_offset,
237
763
       encryption_context,
238
763
       0,
239
763
       error ) != 1 )
240
284
  {
241
284
    libcerror_error_set(
242
284
     error,
243
284
     LIBCERROR_ERROR_DOMAIN_IO,
244
284
     LIBCERROR_IO_ERROR_READ_FAILED,
245
284
     "%s: unable to read volume header sector data.",
246
284
     function );
247
248
284
    goto on_error;
249
284
  }
250
479
  if( io_handle->volume_size == 0 )
251
297
  {
252
297
    if( libbde_ntfs_volume_header_initialize(
253
297
         &ntfs_volume_header,
254
297
         error ) != 1 )
255
0
    {
256
0
      libcerror_error_set(
257
0
       error,
258
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
259
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
260
0
       "%s: unable to create NTFS volume header.",
261
0
       function );
262
263
0
      goto on_error;
264
0
    }
265
297
    if( libbde_ntfs_volume_header_read_data(
266
297
         ntfs_volume_header,
267
297
         sector_data->data,
268
297
         sector_data->data_size,
269
297
         error ) != 1 )
270
239
    {
271
239
      libcerror_error_set(
272
239
       error,
273
239
       LIBCERROR_ERROR_DOMAIN_IO,
274
239
       LIBCERROR_IO_ERROR_READ_FAILED,
275
239
       "%s: unable to read NTFS volume header.",
276
239
       function );
277
278
239
      goto on_error;
279
239
    }
280
58
    io_handle->volume_size = ntfs_volume_header->volume_size;
281
282
58
    if( libbde_ntfs_volume_header_free(
283
58
         &ntfs_volume_header,
284
58
         error ) != 1 )
285
0
    {
286
0
      libcerror_error_set(
287
0
       error,
288
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
289
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
290
0
       "%s: unable to free NTFS volume header.",
291
0
       function );
292
293
0
      goto on_error;
294
0
    }
295
58
  }
296
240
  if( libbde_sector_data_free(
297
240
       &sector_data,
298
240
       error ) != 1 )
299
0
  {
300
0
    libcerror_error_set(
301
0
     error,
302
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
303
0
     LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
304
0
     "%s: unable to free sector data.",
305
0
     function );
306
307
0
    goto on_error;
308
0
  }
309
240
  return( 1 );
310
311
523
on_error:
312
523
  if( ntfs_volume_header != NULL )
313
239
  {
314
239
    libbde_ntfs_volume_header_free(
315
239
     &ntfs_volume_header,
316
239
     NULL );
317
239
  }
318
523
  if( sector_data != NULL )
319
523
  {
320
523
    libbde_sector_data_free(
321
523
     &sector_data,
322
     NULL );
323
523
  }
324
523
  return( -1 );
325
240
}
326