Coverage Report

Created: 2025-06-13 07:22

/src/libfsapfs/libfsapfs/libfsapfs_key_encrypted_key.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The key encrypted key (KEK) functions
3
 *
4
 * Copyright (C) 2018-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
#include "libfsapfs_debug.h"
28
#include "libfsapfs_encryption_context.h"
29
#include "libfsapfs_key_encrypted_key.h"
30
#include "libfsapfs_libcerror.h"
31
#include "libfsapfs_libcnotify.h"
32
#include "libfsapfs_libfguid.h"
33
#include "libfsapfs_libhmac.h"
34
#include "libfsapfs_password.h"
35
36
#include "fsapfs_key_bag.h"
37
38
const uint8_t libfsapfs_key_encrypted_key_wrapped_kek_initialization_vector[ 8 ] = {
39
       0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
40
41
/* Creates a key encrypted key
42
 * Make sure the value key_encrypted_key is referencing, is set to NULL
43
 * Returns 1 if successful or -1 on error
44
 */
45
int libfsapfs_key_encrypted_key_initialize(
46
     libfsapfs_key_encrypted_key_t **key_encrypted_key,
47
     libcerror_error_t **error )
48
0
{
49
0
  static char *function = "libfsapfs_key_encrypted_key_initialize";
50
51
0
  if( key_encrypted_key == NULL )
52
0
  {
53
0
    libcerror_error_set(
54
0
     error,
55
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
56
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
57
0
     "%s: invalid key encrypted key.",
58
0
     function );
59
60
0
    return( -1 );
61
0
  }
62
0
  if( *key_encrypted_key != NULL )
63
0
  {
64
0
    libcerror_error_set(
65
0
     error,
66
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
67
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
68
0
     "%s: invalid key encrypted key value already set.",
69
0
     function );
70
71
0
    return( -1 );
72
0
  }
73
0
  *key_encrypted_key = memory_allocate_structure(
74
0
                        libfsapfs_key_encrypted_key_t );
75
76
0
  if( *key_encrypted_key == NULL )
77
0
  {
78
0
    libcerror_error_set(
79
0
     error,
80
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
81
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
82
0
     "%s: unable to create key encrypted key.",
83
0
     function );
84
85
0
    goto on_error;
86
0
  }
87
0
  if( memory_set(
88
0
       *key_encrypted_key,
89
0
       0,
90
0
       sizeof( libfsapfs_key_encrypted_key_t ) ) == NULL )
91
0
  {
92
0
    libcerror_error_set(
93
0
     error,
94
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
95
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
96
0
     "%s: unable to clear key encrypted key.",
97
0
     function );
98
99
0
    goto on_error;
100
0
  }
101
0
  return( 1 );
102
103
0
on_error:
104
0
  if( *key_encrypted_key != NULL )
105
0
  {
106
0
    memory_free(
107
0
     *key_encrypted_key );
108
109
0
    *key_encrypted_key = NULL;
110
0
  }
111
0
  return( -1 );
112
0
}
113
114
/* Frees key encrypted key
115
 * Returns 1 if successful or -1 on error
116
 */
117
int libfsapfs_key_encrypted_key_free(
118
     libfsapfs_key_encrypted_key_t **key_encrypted_key,
119
     libcerror_error_t **error )
120
0
{
121
0
  static char *function = "libfsapfs_key_encrypted_key_free";
122
123
0
  if( key_encrypted_key == NULL )
124
0
  {
125
0
    libcerror_error_set(
126
0
     error,
127
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
128
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
129
0
     "%s: invalid key encrypted key.",
130
0
     function );
131
132
0
    return( -1 );
133
0
  }
134
0
  if( *key_encrypted_key != NULL )
135
0
  {
136
0
    memory_free(
137
0
     *key_encrypted_key );
138
139
0
    *key_encrypted_key = NULL;
140
0
  }
141
0
  return( 1 );
142
0
}
143
144
/* Reads the key encrypted key
145
 * Returns 1 if successful or -1 on error
146
 */
147
int libfsapfs_key_encrypted_key_read_data(
148
     libfsapfs_key_encrypted_key_t *key_encrypted_key,
149
     const uint8_t *data,
150
     size_t data_size,
151
     libcerror_error_t **error )
152
0
{
153
0
  fsapfs_key_bag_kek_metadata_t *kek_metadata = NULL;
154
0
  const uint8_t *wrapped_kek_object_data      = NULL;
155
0
  static char *function                       = "libfsapfs_key_encrypted_key_read_data";
156
0
  size_t data_offset                          = 0;
157
0
  uint16_t value_data_size                    = 0;
158
0
  uint16_t wrapped_kek_object_data_size       = 0;
159
0
  uint8_t byte_value                          = 0;
160
0
  uint8_t value_tag                           = 0;
161
162
#if defined( HAVE_DEBUG_OUTPUT )
163
  uint16_t value_16bit                        = 0;
164
#endif
165
166
0
  if( key_encrypted_key == NULL )
167
0
  {
168
0
    libcerror_error_set(
169
0
     error,
170
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
171
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
172
0
     "%s: invalid key encrypted key.",
173
0
     function );
174
175
0
    return( -1 );
176
0
  }
177
0
  if( data == NULL )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
182
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
183
0
     "%s: invalid data.",
184
0
     function );
185
186
0
    return( -1 );
187
0
  }
188
0
  if( ( data_size < 2 )
189
0
   || ( data_size > (size_t) SSIZE_MAX ) )
190
0
  {
191
0
    libcerror_error_set(
192
0
     error,
193
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
194
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
195
0
     "%s: invalid data size value out of bounds.",
196
0
     function );
197
198
0
    return( -1 );
199
0
  }
200
0
  value_tag  = data[ data_offset++ ];
201
0
  byte_value = data[ data_offset++ ];
202
203
0
  if( ( ( byte_value & 0x80 ) != 0 )
204
0
   && ( byte_value != 0x81 )
205
0
   && ( byte_value != 0x82 ) )
206
0
  {
207
0
    libcerror_error_set(
208
0
     error,
209
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
210
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
211
0
     "%s: unsupported object extended value data size: 0x02%" PRIx8 ".",
212
0
     function,
213
0
     byte_value );
214
215
0
    return( -1 );
216
0
  }
217
0
  if( ( byte_value & 0x80 ) == 0 )
218
0
  {
219
0
    value_data_size = (uint16_t) byte_value;
220
0
  }
221
0
  else if( byte_value == 0x81 )
222
0
  {
223
0
    value_data_size = (uint16_t) data[ data_offset++ ];
224
0
  }
225
0
  else if( byte_value == 0x82 )
226
0
  {
227
0
    byte_stream_copy_to_uint16_little_endian(
228
0
     &( data[ data_offset ] ),
229
0
     value_data_size );
230
231
0
    data_offset += 2;
232
0
  }
233
#if defined( HAVE_DEBUG_OUTPUT )
234
  if( libcnotify_verbose != 0 )
235
  {
236
    libcnotify_printf(
237
     "%s: KEK packed object data:\n",
238
     function );
239
    libcnotify_print_data(
240
     data,
241
     data_size,
242
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
243
  }
244
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
245
246
#if defined( HAVE_DEBUG_OUTPUT )
247
  if( libcnotify_verbose != 0 )
248
  {
249
    libcnotify_printf(
250
     "%s: object value tag\t\t\t: 0x%02" PRIx8 "\n",
251
     function,
252
     value_tag );
253
254
    libcnotify_printf(
255
     "%s: object value data size\t\t: %" PRIu16 "\n",
256
     function,
257
     value_data_size );
258
259
    libcnotify_printf(
260
     "%s: object value data:\n",
261
     function );
262
    libcnotify_print_data(
263
     &( data[ data_offset ] ),
264
     (size_t) value_data_size,
265
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
266
  }
267
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
268
269
0
  if( value_tag != 0x30 )
270
0
  {
271
0
    libcerror_error_set(
272
0
     error,
273
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
274
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
275
0
     "%s: unsupported object value tag: 0x02%" PRIx8 ".",
276
0
     function,
277
0
     value_tag );
278
279
0
    return( -1 );
280
0
  }
281
0
  if( value_data_size > ( data_size - 2 ) )
282
0
  {
283
0
    libcerror_error_set(
284
0
     error,
285
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
286
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
287
0
     "%s: invalid object value data size value out of bounds.",
288
0
     function );
289
290
0
    return( -1 );
291
0
  }
292
0
  while( data_offset < data_size )
293
0
  {
294
0
    value_tag  = data[ data_offset++ ];
295
0
    byte_value = data[ data_offset++ ];
296
297
0
    if( ( ( byte_value & 0x80 ) != 0 )
298
0
     && ( byte_value != 0x81 )
299
0
     && ( byte_value != 0x82 ) )
300
0
    {
301
0
      libcerror_error_set(
302
0
       error,
303
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
304
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
305
0
       "%s: unsupported attribute extended value data size: 0x02%" PRIx8 ".",
306
0
       function,
307
0
       byte_value );
308
309
0
      return( -1 );
310
0
    }
311
0
    if( ( byte_value & 0x80 ) == 0 )
312
0
    {
313
0
      value_data_size = (uint16_t) byte_value;
314
0
    }
315
0
    else if( byte_value == 0x81 )
316
0
    {
317
0
      value_data_size = (uint16_t) data[ data_offset++ ];
318
0
    }
319
0
    else if( byte_value == 0x82 )
320
0
    {
321
0
      byte_stream_copy_to_uint16_little_endian(
322
0
       &( data[ data_offset ] ),
323
0
       value_data_size );
324
325
0
      data_offset += 2;
326
0
    }
327
#if defined( HAVE_DEBUG_OUTPUT )
328
    if( libcnotify_verbose != 0 )
329
    {
330
      libcnotify_printf(
331
       "%s: attribute value tag\t\t: 0x%02" PRIx8 "\n",
332
       function,
333
       value_tag );
334
335
      libcnotify_printf(
336
       "%s: attribute value data size\t: %" PRIu16 "\n",
337
       function,
338
       value_data_size );
339
    }
340
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
341
342
0
    if( ( value_tag == 0 )
343
0
     && ( value_data_size == 0 ) )
344
0
    {
345
0
      break;
346
0
    }
347
0
    if( ( data_offset >= data_size )
348
0
     || ( value_data_size > ( data_size - data_offset ) ) )
349
0
    {
350
0
      libcerror_error_set(
351
0
       error,
352
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
353
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
354
0
       "%s: invalid value data size value out of bounds.",
355
0
       function );
356
357
0
      return( -1 );
358
0
    }
359
#if defined( HAVE_DEBUG_OUTPUT )
360
    if( libcnotify_verbose != 0 )
361
    {
362
      libcnotify_printf(
363
       "%s: attribute value data:\n",
364
       function );
365
      libcnotify_print_data(
366
       &( data[ data_offset ] ),
367
       (size_t) value_data_size,
368
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
369
    }
370
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
371
372
0
    switch( value_tag )
373
0
    {
374
0
      case 0x81:
375
0
        if( value_data_size != 32 )
376
0
        {
377
0
          libcerror_error_set(
378
0
           error,
379
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
380
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
381
0
           "%s: unsupported HMAC attribute value data size: %" PRIu16 ".",
382
0
           function,
383
0
           value_data_size );
384
385
0
          return( -1 );
386
0
        }
387
0
        if( memory_copy(
388
0
             key_encrypted_key->hmac,
389
0
             &( data[ data_offset ] ),
390
0
             32 ) == NULL )
391
0
        {
392
0
          libcerror_error_set(
393
0
           error,
394
0
           LIBCERROR_ERROR_DOMAIN_MEMORY,
395
0
           LIBCERROR_MEMORY_ERROR_COPY_FAILED,
396
0
           "%s: unable to copy HMAC.",
397
0
           function );
398
399
0
          return( -1 );
400
0
        }
401
0
        break;
402
403
0
      case 0x82:
404
0
        if( value_data_size != 8 )
405
0
        {
406
0
          libcerror_error_set(
407
0
           error,
408
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
409
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
410
0
           "%s: unsupported attribute value data size: %" PRIu16 ".",
411
0
           function,
412
0
           value_data_size );
413
414
0
          return( -1 );
415
0
        }
416
0
        break;
417
418
0
      case 0xa3:
419
0
        if( value_data_size == 0 )
420
0
        {
421
0
          libcerror_error_set(
422
0
           error,
423
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
424
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
425
0
           "%s: unsupported wrapped KEK packed object attribute value data size: %" PRIu16 ".",
426
0
           function,
427
0
           value_data_size );
428
429
0
          return( -1 );
430
0
        }
431
0
        wrapped_kek_object_data      = &( data[ data_offset - 2 ] );
432
0
        wrapped_kek_object_data_size = value_data_size + 2;
433
434
0
        break;
435
436
0
      default:
437
0
        break;
438
0
    }
439
0
    data_offset += value_data_size;
440
0
  }
441
0
  if( wrapped_kek_object_data == NULL )
442
0
  {
443
0
    libcerror_error_set(
444
0
     error,
445
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
446
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
447
0
     "%s: missing wrapped KEK packed object.",
448
0
     function );
449
450
0
    return( -1 );
451
0
  }
452
0
  data_offset = 0;
453
454
0
  value_tag  = wrapped_kek_object_data[ data_offset++ ];
455
0
  byte_value = wrapped_kek_object_data[ data_offset++ ];
456
457
0
  if( ( ( byte_value & 0x80 ) != 0 )
458
0
   && ( byte_value != 0x82 ) )
459
0
  {
460
0
    libcerror_error_set(
461
0
     error,
462
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
463
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
464
0
     "%s: unsupported object extended value data size: 0x02%" PRIx8 ".",
465
0
     function,
466
0
     byte_value );
467
468
0
    return( -1 );
469
0
  }
470
0
  if( ( byte_value & 0x80 ) == 0 )
471
0
  {
472
0
    value_data_size = (uint16_t) byte_value;
473
0
  }
474
0
  else if( byte_value == 0x82 )
475
0
  {
476
0
    byte_stream_copy_to_uint16_little_endian(
477
0
     &( wrapped_kek_object_data[ data_offset ] ),
478
0
     value_data_size );
479
480
0
    data_offset += 2;
481
0
  }
482
#if defined( HAVE_DEBUG_OUTPUT )
483
  if( libcnotify_verbose != 0 )
484
  {
485
    libcnotify_printf(
486
     "%s: wrapped KEK packed object data:\n",
487
     function );
488
    libcnotify_print_data(
489
     wrapped_kek_object_data,
490
     wrapped_kek_object_data_size,
491
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
492
  }
493
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
494
495
#if defined( HAVE_DEBUG_OUTPUT )
496
  if( libcnotify_verbose != 0 )
497
  {
498
    libcnotify_printf(
499
     "%s: object value tag\t\t\t: 0x%02" PRIx8 "\n",
500
     function,
501
     value_tag );
502
503
    libcnotify_printf(
504
     "%s: object value data size\t\t: %" PRIu16 "\n",
505
     function,
506
     value_data_size );
507
508
    libcnotify_printf(
509
     "%s: object value data:\n",
510
     function );
511
    libcnotify_print_data(
512
     &( wrapped_kek_object_data[ data_offset ] ),
513
     (size_t) value_data_size,
514
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
515
  }
516
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
517
518
0
  if( value_tag != 0xa3 )
519
0
  {
520
0
    libcerror_error_set(
521
0
     error,
522
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
523
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
524
0
     "%s: unsupported object value tag: 0x02%" PRIx8 ".",
525
0
     function,
526
0
     value_tag );
527
528
0
    return( -1 );
529
0
  }
530
0
  if( value_data_size > ( wrapped_kek_object_data_size - 2 ) )
531
0
  {
532
0
    libcerror_error_set(
533
0
     error,
534
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
535
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
536
0
     "%s: invalid object value data size value out of bounds.",
537
0
     function );
538
539
0
    return( -1 );
540
0
  }
541
0
  while( data_offset < wrapped_kek_object_data_size )
542
0
  {
543
0
    value_tag  = wrapped_kek_object_data[ data_offset++ ];
544
0
    byte_value = wrapped_kek_object_data[ data_offset++ ];
545
546
0
    if( ( ( byte_value & 0x80 ) != 0 )
547
0
     && ( byte_value != 0x82 ) )
548
0
    {
549
0
      libcerror_error_set(
550
0
       error,
551
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
552
0
       LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
553
0
       "%s: unsupported attribute extended value data size: 0x02%" PRIx8 ".",
554
0
       function,
555
0
       byte_value );
556
557
0
      return( -1 );
558
0
    }
559
0
    if( ( byte_value & 0x80 ) == 0 )
560
0
    {
561
0
      value_data_size = (uint16_t) byte_value;
562
0
    }
563
0
    else if( byte_value == 0x82 )
564
0
    {
565
0
      byte_stream_copy_to_uint16_little_endian(
566
0
       &( wrapped_kek_object_data[ data_offset ] ),
567
0
       value_data_size );
568
569
0
      data_offset += 2;
570
0
    }
571
#if defined( HAVE_DEBUG_OUTPUT )
572
    if( libcnotify_verbose != 0 )
573
    {
574
      libcnotify_printf(
575
       "%s: attribute value tag\t\t: 0x%02" PRIx8 "\n",
576
       function,
577
       value_tag );
578
579
      libcnotify_printf(
580
       "%s: attribute value data size\t: %" PRIu16 "\n",
581
       function,
582
       value_data_size );
583
    }
584
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
585
586
0
    if( ( value_tag == 0 )
587
0
     && ( value_data_size == 0 ) )
588
0
    {
589
0
      break;
590
0
    }
591
0
    if( ( data_offset >= wrapped_kek_object_data_size )
592
0
     || ( value_data_size > ( wrapped_kek_object_data_size - data_offset ) ) )
593
0
    {
594
0
      libcerror_error_set(
595
0
       error,
596
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
597
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
598
0
       "%s: invalid value data size value out of bounds.",
599
0
       function );
600
601
0
      return( -1 );
602
0
    }
603
#if defined( HAVE_DEBUG_OUTPUT )
604
    if( libcnotify_verbose != 0 )
605
    {
606
607
      libcnotify_printf(
608
       "%s: attribute value data:\n",
609
       function );
610
      libcnotify_print_data(
611
       &( wrapped_kek_object_data[ data_offset ] ),
612
       (size_t) value_data_size,
613
       LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
614
    }
615
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
616
617
0
    switch( value_tag )
618
0
    {
619
0
      case 0x81:
620
0
        if( value_data_size != 16 )
621
0
        {
622
0
          libcerror_error_set(
623
0
           error,
624
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
625
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
626
0
           "%s: unsupported identifier attribute value data size: %" PRIu16 ".",
627
0
           function,
628
0
           value_data_size );
629
630
0
          return( -1 );
631
0
        }
632
0
        if( memory_copy(
633
0
             key_encrypted_key->identifier,
634
0
             &( wrapped_kek_object_data[ data_offset ] ),
635
0
             16 ) == NULL )
636
0
        {
637
0
          libcerror_error_set(
638
0
           error,
639
0
           LIBCERROR_ERROR_DOMAIN_MEMORY,
640
0
           LIBCERROR_MEMORY_ERROR_COPY_FAILED,
641
0
           "%s: unable to copy identifier.",
642
0
           function );
643
644
0
          return( -1 );
645
0
        }
646
#if defined( HAVE_DEBUG_OUTPUT )
647
        if( libcnotify_verbose != 0 )
648
        {
649
          if( libfsapfs_debug_print_guid_value(
650
               function,
651
               "identifier\t\t\t",
652
               &( wrapped_kek_object_data[ data_offset ] ),
653
               16,
654
               LIBFGUID_ENDIAN_BIG,
655
               LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
656
               error ) != 1 )
657
          {
658
            libcerror_error_set(
659
             error,
660
             LIBCERROR_ERROR_DOMAIN_RUNTIME,
661
             LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
662
             "%s: unable to print UUID value.",
663
             function );
664
665
            return( -1 );
666
          }
667
          libcnotify_printf(
668
           "\n" );
669
        }
670
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
671
672
0
        break;
673
674
0
      case 0x82:
675
0
        if( value_data_size != 8 )
676
0
        {
677
0
          libcerror_error_set(
678
0
           error,
679
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
680
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
681
0
           "%s: unsupported KEK metadata attribute value data size: %" PRIu16 ".",
682
0
           function,
683
0
           value_data_size );
684
685
0
          return( -1 );
686
0
        }
687
0
        kek_metadata = (fsapfs_key_bag_kek_metadata_t *) &( wrapped_kek_object_data[ data_offset ] );
688
689
0
        byte_stream_copy_to_uint32_little_endian(
690
0
         kek_metadata->encryption_method,
691
0
         key_encrypted_key->encryption_method );
692
693
#if defined( HAVE_DEBUG_OUTPUT )
694
        if( libcnotify_verbose != 0 )
695
        {
696
          libcnotify_printf(
697
           "%s: encryption method\t\t: %" PRIu32 "\n",
698
           function,
699
           key_encrypted_key->encryption_method );
700
701
          byte_stream_copy_to_uint16_little_endian(
702
           kek_metadata->unknown1,
703
           value_16bit );
704
          libcnotify_printf(
705
           "%s: unknown1\t\t\t\t: 0x%04" PRIx16 "\n",
706
           function,
707
           value_16bit );
708
709
          libcnotify_printf(
710
           "%s: unknown2\t\t\t\t: 0x%02" PRIx8 "\n",
711
           function,
712
           kek_metadata->unknown2 );
713
714
          libcnotify_printf(
715
           "%s: unknown3\t\t\t\t: 0x%02" PRIx8 "\n",
716
           function,
717
           kek_metadata->unknown3 );
718
719
          libcnotify_printf(
720
           "\n" );
721
        }
722
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
723
724
0
        break;
725
726
0
      case 0x83:
727
0
        if( value_data_size != 40 )
728
0
        {
729
0
          libcerror_error_set(
730
0
           error,
731
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
732
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
733
0
           "%s: unsupported wrapped KEK attribute value data size: %" PRIu16 ".",
734
0
           function,
735
0
           value_data_size );
736
737
0
          return( -1 );
738
0
        }
739
0
        if( memory_copy(
740
0
             key_encrypted_key->wrapped_kek,
741
0
             &( wrapped_kek_object_data[ data_offset ] ),
742
0
             40 ) == NULL )
743
0
        {
744
0
          libcerror_error_set(
745
0
           error,
746
0
           LIBCERROR_ERROR_DOMAIN_MEMORY,
747
0
           LIBCERROR_MEMORY_ERROR_COPY_FAILED,
748
0
           "%s: unable to copy wrapped KEK.",
749
0
           function );
750
751
0
          return( -1 );
752
0
        }
753
0
        break;
754
755
0
      case 0x84:
756
0
        if( ( value_data_size == 0 )
757
0
         || ( value_data_size > 8 ) )
758
0
        {
759
0
          libcerror_error_set(
760
0
           error,
761
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
762
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
763
0
           "%s: unsupported number of iteration attribute value data size: %" PRIu16 ".",
764
0
           function,
765
0
           value_data_size );
766
767
0
          return( -1 );
768
0
        }
769
0
        key_encrypted_key->number_of_iterations = 0;
770
771
0
        while( value_data_size > 0 )
772
0
        {
773
0
          key_encrypted_key->number_of_iterations <<= 8;
774
0
          key_encrypted_key->number_of_iterations  |= wrapped_kek_object_data[ data_offset++ ];
775
776
0
          value_data_size--;
777
0
        }
778
779
#if defined( HAVE_DEBUG_OUTPUT )
780
        if( libcnotify_verbose != 0 )
781
        {
782
          libcnotify_printf(
783
           "%s: number of iterations\t\t: %" PRIu32 "\n",
784
           function,
785
           key_encrypted_key->number_of_iterations );
786
787
          libcnotify_printf(
788
           "\n" );
789
        }
790
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
791
792
0
        break;
793
794
0
      case 0x85:
795
0
        if( value_data_size != 16 )
796
0
        {
797
0
          libcerror_error_set(
798
0
           error,
799
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
800
0
           LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
801
0
           "%s: unsupported salt attribute value data size: %" PRIu16 ".",
802
0
           function,
803
0
           value_data_size );
804
805
0
          return( -1 );
806
0
        }
807
0
        if( memory_copy(
808
0
             key_encrypted_key->salt,
809
0
             &( wrapped_kek_object_data[ data_offset ] ),
810
0
             16 ) == NULL )
811
0
        {
812
0
          libcerror_error_set(
813
0
           error,
814
0
           LIBCERROR_ERROR_DOMAIN_MEMORY,
815
0
           LIBCERROR_MEMORY_ERROR_COPY_FAILED,
816
0
           "%s: unable to copy salt.",
817
0
           function );
818
819
0
          return( -1 );
820
0
        }
821
0
        break;
822
823
0
      default:
824
0
        break;
825
0
    }
826
0
    data_offset += value_data_size;
827
0
  }
828
0
  return( 1 );
829
0
}
830
831
/* Unlocks the key encrypted key with a key
832
 * Returns 1 if successful, 0 if not or -1 on error
833
 */
834
int libfsapfs_key_encrypted_key_unlock_with_key(
835
     libfsapfs_key_encrypted_key_t *key_encrypted_key,
836
     const uint8_t *key,
837
     size_t key_size,
838
     uint8_t *unlocked_key,
839
     size_t unlocked_key_size,
840
     libcerror_error_t **error )
841
0
{
842
0
  uint8_t hash_buffer[ LIBHMAC_SHA256_HASH_SIZE ];
843
0
  uint8_t wrapped_kek[ 40 ];
844
845
0
  static char *function     = "libfsapfs_key_encrypted_key_unlock_with_key";
846
0
  size_t used_kek_data_size = 0;
847
0
  size_t used_key_size      = 0;
848
0
  int result                = 0;
849
850
0
  if( key_encrypted_key == NULL )
851
0
  {
852
0
    libcerror_error_set(
853
0
     error,
854
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
855
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
856
0
     "%s: invalid key encrypted key.",
857
0
     function );
858
859
0
    return( -1 );
860
0
  }
861
0
  if( key_encrypted_key->encryption_method == 0 )
862
0
  {
863
0
    used_kek_data_size = 40;
864
0
    used_key_size      = 32;
865
0
  }
866
0
  else if( key_encrypted_key->encryption_method == 2 )
867
0
  {
868
0
    used_kek_data_size = 24;
869
0
    used_key_size      = 16;
870
0
  }
871
0
  else
872
0
  {
873
0
    libcerror_error_set(
874
0
     error,
875
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
876
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
877
0
     "%s: unsupported encryption method.",
878
0
     function );
879
880
0
    return( -1 );
881
0
  }
882
0
  if( key == NULL )
883
0
  {
884
0
    libcerror_error_set(
885
0
     error,
886
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
887
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
888
0
     "%s: invalid key.",
889
0
     function );
890
891
0
    return( -1 );
892
0
  }
893
0
  if( key_size != 256 )
894
0
  {
895
0
    libcerror_error_set(
896
0
     error,
897
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
898
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
899
0
     "%s: invalid key size value out of bounds.",
900
0
     function );
901
902
0
    return( -1 );
903
0
  }
904
0
  if( unlocked_key == NULL )
905
0
  {
906
0
    libcerror_error_set(
907
0
     error,
908
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
909
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
910
0
     "%s: invalid unlocked key.",
911
0
     function );
912
913
0
    return( -1 );
914
0
  }
915
0
  if( unlocked_key_size != 256 )
916
0
  {
917
0
    libcerror_error_set(
918
0
     error,
919
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
920
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
921
0
     "%s: invalid unlocked key size value out of bounds.",
922
0
     function );
923
924
0
    return( -1 );
925
0
  }
926
#if defined( HAVE_DEBUG_OUTPUT )
927
  if( libcnotify_verbose != 0 )
928
  {
929
    libcnotify_printf(
930
     "%s: key:\n",
931
     function );
932
    libcnotify_print_data(
933
     key,
934
     32,
935
     0 );
936
  }
937
#endif
938
0
  if( libfsapfs_encryption_aes_key_unwrap(
939
0
       key,
940
0
       used_key_size * 8,
941
0
       key_encrypted_key->wrapped_kek,
942
0
       used_kek_data_size,
943
0
       wrapped_kek,
944
0
       used_kek_data_size,
945
0
       error ) != 1 )
946
0
  {
947
0
    libcerror_error_set(
948
0
     error,
949
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
950
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
951
0
     "%s: unable to unwrap wrapped KEK with key.",
952
0
     function );
953
954
0
    goto on_error;
955
0
  }
956
0
  if( memory_compare(
957
0
       wrapped_kek,
958
0
       libfsapfs_key_encrypted_key_wrapped_kek_initialization_vector,
959
0
       8 ) == 0 )
960
0
  {
961
0
    if( memory_copy(
962
0
         unlocked_key,
963
0
         &( wrapped_kek[ 8 ] ),
964
0
         used_key_size ) == NULL )
965
0
    {
966
0
      libcerror_error_set(
967
0
       error,
968
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
969
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
970
0
       "%s: unable to copy unlocked key.",
971
0
       function );
972
973
0
      goto on_error;
974
0
    }
975
0
    if( key_encrypted_key->encryption_method == 2 )
976
0
    {
977
0
      if( memory_copy(
978
0
           &( unlocked_key[ 16 ] ),
979
0
           key_encrypted_key->identifier,
980
0
           16 ) == NULL )
981
0
      {
982
0
        libcerror_error_set(
983
0
         error,
984
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
985
0
         LIBCERROR_MEMORY_ERROR_COPY_FAILED,
986
0
         "%s: unable to copy identifier to unlocked key.",
987
0
         function );
988
989
0
        goto on_error;
990
0
      }
991
0
      if( libhmac_sha256_calculate(
992
0
           unlocked_key,
993
0
           32,
994
0
           hash_buffer,
995
0
           LIBHMAC_SHA256_HASH_SIZE,
996
0
           error ) != 1 )
997
0
      {
998
0
        libcerror_error_set(
999
0
         error,
1000
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1001
0
         LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1002
0
         "%s: unable to calculate SHA-256 of tweak key data.",
1003
0
         function );
1004
1005
0
        goto on_error;
1006
0
      }
1007
0
      if( memory_copy(
1008
0
           &( unlocked_key[ 16 ] ),
1009
0
           hash_buffer,
1010
0
           16 ) == NULL )
1011
0
      {
1012
0
        libcerror_error_set(
1013
0
         error,
1014
0
         LIBCERROR_ERROR_DOMAIN_MEMORY,
1015
0
         LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1016
0
         "%s: unable to copy SHA-256 hash to unlocked key.",
1017
0
         function );
1018
1019
0
        goto on_error;
1020
0
      }
1021
0
      memory_set(
1022
0
       hash_buffer,
1023
0
       0,
1024
0
       LIBHMAC_SHA256_HASH_SIZE );
1025
0
    }
1026
#if defined( HAVE_DEBUG_OUTPUT )
1027
    if( libcnotify_verbose != 0 )
1028
    {
1029
      libcnotify_printf(
1030
       "%s: unlocked key:\n",
1031
       function );
1032
      libcnotify_print_data(
1033
       unlocked_key,
1034
       unlocked_key_size / 8,
1035
       0 );
1036
    }
1037
#endif
1038
0
    result = 1;
1039
0
  }
1040
0
  memory_set(
1041
0
   wrapped_kek,
1042
0
   0,
1043
0
   40 );
1044
1045
0
  return( result );
1046
1047
0
on_error:
1048
0
  memory_set(
1049
0
   wrapped_kek,
1050
0
   0,
1051
0
   40 );
1052
1053
0
  memory_set(
1054
0
   hash_buffer,
1055
0
   0,
1056
0
   LIBHMAC_SHA256_HASH_SIZE );
1057
1058
0
  return( -1 );
1059
0
}
1060
1061
/* Unlocks the key encrypted key with a password
1062
 * Returns 1 if successful, 0 if not or -1 on error
1063
 */
1064
int libfsapfs_key_encrypted_key_unlock_with_password(
1065
     libfsapfs_key_encrypted_key_t *key_encrypted_key,
1066
     const uint8_t *password,
1067
     size_t password_length,
1068
     uint8_t *unlocked_key,
1069
     size_t unlocked_key_size,
1070
     libcerror_error_t **error )
1071
0
{
1072
0
  uint8_t password_key[ 32 ];
1073
0
  uint8_t wrapped_kek[ 40 ];
1074
1075
0
  static char *function     = "libfsapfs_key_encrypted_key_unlock_with_password";
1076
0
  size_t password_key_size  = 0;
1077
0
  size_t used_kek_data_size = 0;
1078
0
  int result                = 0;
1079
1080
0
  if( key_encrypted_key == NULL )
1081
0
  {
1082
0
    libcerror_error_set(
1083
0
     error,
1084
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1085
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1086
0
     "%s: invalid key encrypted key.",
1087
0
     function );
1088
1089
0
    return( -1 );
1090
0
  }
1091
0
  if( ( key_encrypted_key->encryption_method == 0 )
1092
0
   || ( key_encrypted_key->encryption_method == 16 ) )
1093
0
  {
1094
0
    password_key_size  = 32;
1095
0
    used_kek_data_size = 40;
1096
0
  }
1097
0
  else if( key_encrypted_key->encryption_method == 2 )
1098
0
  {
1099
0
    password_key_size  = 16;
1100
0
    used_kek_data_size = 24;
1101
0
  }
1102
0
  else
1103
0
  {
1104
0
    libcerror_error_set(
1105
0
     error,
1106
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1107
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
1108
0
     "%s: unsupported encryption method.",
1109
0
     function );
1110
1111
0
    return( -1 );
1112
0
  }
1113
0
  if( unlocked_key == NULL )
1114
0
  {
1115
0
    libcerror_error_set(
1116
0
     error,
1117
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1118
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1119
0
     "%s: invalid unlocked key.",
1120
0
     function );
1121
1122
0
    return( -1 );
1123
0
  }
1124
0
  if( unlocked_key_size != 256 )
1125
0
  {
1126
0
    libcerror_error_set(
1127
0
     error,
1128
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1129
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
1130
0
     "%s: invalid key size value out of bounds.",
1131
0
     function );
1132
1133
0
    return( -1 );
1134
0
  }
1135
0
  if( libfsapfs_password_pbkdf2(
1136
0
       password,
1137
0
       password_length,
1138
0
       key_encrypted_key->salt,
1139
0
       16,
1140
0
       (uint32_t) key_encrypted_key->number_of_iterations,
1141
0
       password_key,
1142
0
       password_key_size,
1143
0
       error ) != 1 )
1144
0
  {
1145
0
    libcerror_error_set(
1146
0
     error,
1147
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1148
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1149
0
     "%s: unable to determine password key.",
1150
0
     function );
1151
1152
0
    goto on_error;
1153
0
  }
1154
#if defined( HAVE_DEBUG_OUTPUT )
1155
  if( libcnotify_verbose != 0 )
1156
  {
1157
    libcnotify_printf(
1158
     "%s: password key:\n",
1159
     function );
1160
    libcnotify_print_data(
1161
     password_key,
1162
     password_key_size,
1163
     0 );
1164
  }
1165
#endif
1166
0
  if( libfsapfs_encryption_aes_key_unwrap(
1167
0
       password_key,
1168
0
       password_key_size * 8,
1169
0
       key_encrypted_key->wrapped_kek,
1170
0
       used_kek_data_size,
1171
0
       wrapped_kek,
1172
0
       used_kek_data_size,
1173
0
       error ) != 1 )
1174
0
  {
1175
0
    libcerror_error_set(
1176
0
     error,
1177
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1178
0
     LIBCERROR_RUNTIME_ERROR_GENERIC,
1179
0
     "%s: unable to unwrap wrapped KEK with password.",
1180
0
     function );
1181
1182
0
    goto on_error;
1183
0
  }
1184
0
  memory_set(
1185
0
   password_key,
1186
0
   0,
1187
0
   32 );
1188
1189
0
  if( memory_compare(
1190
0
       wrapped_kek,
1191
0
       libfsapfs_key_encrypted_key_wrapped_kek_initialization_vector,
1192
0
       8 ) == 0 )
1193
0
  {
1194
0
    if( memory_copy(
1195
0
         unlocked_key,
1196
0
         &( wrapped_kek[ 8 ] ),
1197
0
         password_key_size ) == NULL )
1198
0
    {
1199
0
      libcerror_error_set(
1200
0
       error,
1201
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
1202
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1203
0
       "%s: unable to copy unlocked key.",
1204
0
       function );
1205
1206
0
      goto on_error;
1207
0
    }
1208
#if defined( HAVE_DEBUG_OUTPUT )
1209
    if( libcnotify_verbose != 0 )
1210
    {
1211
      libcnotify_printf(
1212
       "%s: unlocked key:\n",
1213
       function );
1214
      libcnotify_print_data(
1215
       unlocked_key,
1216
       unlocked_key_size / 8,
1217
       0 );
1218
    }
1219
#endif
1220
0
    result = 1;
1221
0
  }
1222
0
  memory_set(
1223
0
   wrapped_kek,
1224
0
   0,
1225
0
   40 );
1226
1227
0
  return( result );
1228
1229
0
on_error:
1230
0
  memory_set(
1231
0
   wrapped_kek,
1232
0
   0,
1233
0
   40 );
1234
1235
0
  memory_set(
1236
0
   password_key,
1237
0
   0,
1238
0
   32 );
1239
1240
0
  return( -1 );
1241
0
}
1242