1 /*
2 * Shows information obtained from a BitLocker Drive Encrypted (BDE) volume
3 *
4 * Copyright (C) 2011-2021, 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 <memory.h>
24 #include <system_string.h>
25 #include <types.h>
26
27 #include <stdio.h>
28
29 #if defined( HAVE_UNISTD_H )
30 #include <unistd.h>
31 #endif
32
33 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
34 #include <stdlib.h>
35 #endif
36
37 #include "bdetools_getopt.h"
38 #include "bdetools_libbde.h"
39 #include "bdetools_libcerror.h"
40 #include "bdetools_libclocale.h"
41 #include "bdetools_libcnotify.h"
42 #include "bdetools_output.h"
43 #include "bdetools_signal.h"
44 #include "bdetools_unused.h"
45 #include "info_handle.h"
46
47 info_handle_t *bdeinfo_info_handle = NULL;
48 int bdeinfo_abort = 0;
49
50 /* Prints the executable usage information
51 */
usage_fprint(FILE * stream)52 void usage_fprint(
53 FILE *stream )
54 {
55 if( stream == NULL )
56 {
57 return;
58 }
59 fprintf( stream, "Use bdeinfo to determine information about a BitLocker Drive\n"
60 " Encrypted (BDE) volume\n\n" );
61
62 fprintf( stream, "Usage: bdeinfo [ -k keys ] [ -o offset ] [ -p password ]\n"
63 " [ -r password ] [ -s filename ] [ -hvV ] source\n\n" );
64
65 fprintf( stream, "\tsource: the source file or device\n\n" );
66
67 fprintf( stream, "\t-h: shows this help\n" );
68 fprintf( stream, "\t-k: the full volume encryption key and tweak key\n"
69 "\t formatted in base16 and separated by a : character\n"
70 "\t e.g. FVEK:TWEAK\n" );
71 fprintf( stream, "\t-o: specify the volume offset in bytes\n" );
72 fprintf( stream, "\t-p: specify the password/passphrase\n" );
73 fprintf( stream, "\t-r: specify the recovery password\n" );
74 fprintf( stream, "\t-s: specify the file containing the startup key.\n"
75 "\t typically this file has the extension .BEK\n" );
76 fprintf( stream, "\t-v: verbose output to stderr\n" );
77 fprintf( stream, "\t-V: print version\n" );
78 }
79
80 /* Signal handler for bdeinfo
81 */
bdeinfo_signal_handler(bdetools_signal_t signal BDETOOLS_ATTRIBUTE_UNUSED)82 void bdeinfo_signal_handler(
83 bdetools_signal_t signal BDETOOLS_ATTRIBUTE_UNUSED )
84 {
85 libcerror_error_t *error = NULL;
86 static char *function = "bdeinfo_signal_handler";
87
88 BDETOOLS_UNREFERENCED_PARAMETER( signal )
89
90 bdeinfo_abort = 1;
91
92 if( bdeinfo_info_handle != NULL )
93 {
94 if( info_handle_signal_abort(
95 bdeinfo_info_handle,
96 &error ) != 1 )
97 {
98 libcnotify_printf(
99 "%s: unable to signal info handle to abort.\n",
100 function );
101
102 libcnotify_print_error_backtrace(
103 error );
104 libcerror_error_free(
105 &error );
106 }
107 }
108 /* Force stdin to close otherwise any function reading it will remain blocked
109 */
110 #if defined( WINAPI ) && !defined( __CYGWIN__ )
111 if( _close(
112 0 ) != 0 )
113 #else
114 if( close(
115 0 ) != 0 )
116 #endif
117 {
118 libcnotify_printf(
119 "%s: unable to close stdin.\n",
120 function );
121 }
122 }
123
124 /* The main program
125 */
126 #if defined( HAVE_WIDE_SYSTEM_CHARACTER )
wmain(int argc,wchar_t * const argv[])127 int wmain( int argc, wchar_t * const argv[] )
128 #else
129 int main( int argc, char * const argv[] )
130 #endif
131 {
132 libbde_error_t *error = NULL;
133 system_character_t *option_keys = NULL;
134 system_character_t *option_password = NULL;
135 system_character_t *option_recovery_password = NULL;
136 system_character_t *option_startup_key_filename = NULL;
137 system_character_t *option_volume_offset = NULL;
138 system_character_t *source = NULL;
139 char *program = "bdeinfo";
140 system_integer_t option = 0;
141 int result = 0;
142 int verbose = 0;
143
144 libcnotify_stream_set(
145 stderr,
146 NULL );
147 libcnotify_verbose_set(
148 1 );
149
150 if( libclocale_initialize(
151 "bdetools",
152 &error ) != 1 )
153 {
154 fprintf(
155 stderr,
156 "Unable to initialize locale values.\n" );
157
158 goto on_error;
159 }
160 if( bdetools_output_initialize(
161 _IONBF,
162 &error ) != 1 )
163 {
164 fprintf(
165 stderr,
166 "Unable to initialize output settings.\n" );
167
168 goto on_error;
169 }
170 bdetools_output_version_fprint(
171 stdout,
172 program );
173
174 while( ( option = bdetools_getopt(
175 argc,
176 argv,
177 _SYSTEM_STRING( "hk:o:p:r:s:vV" ) ) ) != (system_integer_t) -1 )
178 {
179 switch( option )
180 {
181 case (system_integer_t) '?':
182 default:
183 fprintf(
184 stderr,
185 "Invalid argument: %" PRIs_SYSTEM "\n",
186 argv[ optind - 1 ] );
187
188 usage_fprint(
189 stdout );
190
191 return( EXIT_FAILURE );
192
193 case (system_integer_t) 'h':
194 usage_fprint(
195 stdout );
196
197 return( EXIT_SUCCESS );
198
199 case (system_integer_t) 'k':
200 option_keys = optarg;
201
202 break;
203
204 case (system_integer_t) 'o':
205 option_volume_offset = optarg;
206
207 break;
208
209 case (system_integer_t) 'p':
210 option_password = optarg;
211
212 break;
213
214 case (system_integer_t) 'r':
215 option_recovery_password = optarg;
216
217 break;
218
219 case (system_integer_t) 's':
220 option_startup_key_filename = optarg;
221
222 break;
223
224 case (system_integer_t) 'v':
225 verbose = 1;
226
227 break;
228
229 case (system_integer_t) 'V':
230 bdetools_output_copyright_fprint(
231 stdout );
232
233 return( EXIT_SUCCESS );
234 }
235 }
236 if( optind == argc )
237 {
238 fprintf(
239 stderr,
240 "Missing source file or device.\n" );
241
242 usage_fprint(
243 stdout );
244
245 return( EXIT_FAILURE );
246 }
247 source = argv[ optind ];
248
249 libcnotify_verbose_set(
250 verbose );
251 libbde_notify_set_stream(
252 stderr,
253 NULL );
254 libbde_notify_set_verbose(
255 verbose );
256
257 if( info_handle_initialize(
258 &bdeinfo_info_handle,
259 &error ) != 1 )
260 {
261 fprintf(
262 stderr,
263 "Unable to initialize info handle.\n" );
264
265 goto on_error;
266 }
267 if( option_keys != NULL )
268 {
269 if( info_handle_set_keys(
270 bdeinfo_info_handle,
271 option_keys,
272 &error ) != 1 )
273 {
274 fprintf(
275 stderr,
276 "Unable to set keys.\n" );
277
278 goto on_error;
279 }
280 }
281 if( option_password != NULL )
282 {
283 if( info_handle_set_password(
284 bdeinfo_info_handle,
285 option_password,
286 &error ) != 1 )
287 {
288 fprintf(
289 stderr,
290 "Unable to set password.\n" );
291
292 goto on_error;
293 }
294 }
295 if( option_recovery_password != NULL )
296 {
297 if( info_handle_set_recovery_password(
298 bdeinfo_info_handle,
299 option_recovery_password,
300 &error ) != 1 )
301 {
302 fprintf(
303 stderr,
304 "Unable to set recovery password.\n" );
305
306 goto on_error;
307 }
308 }
309 if( option_startup_key_filename != NULL )
310 {
311 if( info_handle_read_startup_key(
312 bdeinfo_info_handle,
313 option_startup_key_filename,
314 &error ) != 1 )
315 {
316 fprintf(
317 stderr,
318 "Unable to read startup key.\n" );
319
320 goto on_error;
321 }
322 }
323 if( option_volume_offset != NULL )
324 {
325 if( info_handle_set_volume_offset(
326 bdeinfo_info_handle,
327 option_volume_offset,
328 &error ) != 1 )
329 {
330 fprintf(
331 stderr,
332 "Unable to set volume offset.\n" );
333
334 goto on_error;
335 }
336 }
337 result = info_handle_open_input(
338 bdeinfo_info_handle,
339 source,
340 &error );
341
342 if( result != 1 )
343 {
344 fprintf(
345 stderr,
346 "Unable to open: %" PRIs_SYSTEM ".\n",
347 source );
348
349 goto on_error;
350 }
351 if( info_handle_volume_fprint(
352 bdeinfo_info_handle,
353 &error ) != 1 )
354 {
355 fprintf(
356 stderr,
357 "Unable to print volume information.\n" );
358
359 goto on_error;
360 }
361 result = info_handle_input_is_locked(
362 bdeinfo_info_handle,
363 &error );
364
365 if( result != 0 )
366 {
367 fprintf(
368 stderr,
369 "Unable to unlock volume.\n" );
370
371 goto on_error;
372 }
373 if( info_handle_close_input(
374 bdeinfo_info_handle,
375 &error ) != 0 )
376 {
377 fprintf(
378 stderr,
379 "Unable to close info handle.\n" );
380
381 goto on_error;
382 }
383 if( info_handle_free(
384 &bdeinfo_info_handle,
385 &error ) != 1 )
386 {
387 fprintf(
388 stderr,
389 "Unable to free info handle.\n" );
390
391 goto on_error;
392 }
393 return( EXIT_SUCCESS );
394
395 on_error:
396 if( error != NULL )
397 {
398 libcnotify_print_error_backtrace(
399 error );
400 libcerror_error_free(
401 &error );
402 }
403 if( bdeinfo_info_handle != NULL )
404 {
405 info_handle_free(
406 &bdeinfo_info_handle,
407 NULL );
408 }
409 return( EXIT_FAILURE );
410 }
411
412