Coverage Report

Created: 2025-10-14 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libbde/libbde/libbde_aes_ccm_encrypted_key.c
Line
Count
Source
1
/*
2
 * AES-CCM encrypted key metadata entry 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 <system_string.h>
26
#include <types.h>
27
28
#include "libbde_aes_ccm_encrypted_key.h"
29
#include "libbde_debug.h"
30
#include "libbde_definitions.h"
31
#include "libbde_libcerror.h"
32
#include "libbde_libcnotify.h"
33
#include "libbde_libfdatetime.h"
34
#include "libbde_metadata_entry.h"
35
36
#include "bde_metadata.h"
37
38
/* Creates an AES-CCM encrypted key
39
 * Make sure the value AES-CCM encrypted key is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libbde_aes_ccm_encrypted_key_initialize(
43
     libbde_aes_ccm_encrypted_key_t **aes_ccm_encrypted_key,
44
     libcerror_error_t **error )
45
8.21k
{
46
8.21k
  static char *function = "libbde_aes_ccm_encrypted_key_initialize";
47
48
8.21k
  if( aes_ccm_encrypted_key == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid AES-CCM encrypted key.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
8.21k
  if( *aes_ccm_encrypted_key != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid AES-CCM encrypted key value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
8.21k
  *aes_ccm_encrypted_key = memory_allocate_structure(
71
8.21k
                            libbde_aes_ccm_encrypted_key_t );
72
73
8.21k
  if( *aes_ccm_encrypted_key == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
78
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79
0
     "%s: unable to create AES-CCM encrypted key.",
80
0
     function );
81
82
0
    goto on_error;
83
0
  }
84
8.21k
  if( memory_set(
85
8.21k
       *aes_ccm_encrypted_key,
86
8.21k
       0,
87
8.21k
       sizeof( libbde_aes_ccm_encrypted_key_t ) ) == NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
92
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
93
0
     "%s: unable to clear AES-CCM encrypted key.",
94
0
     function );
95
96
0
    goto on_error;
97
0
  }
98
8.21k
  return( 1 );
99
100
0
on_error:
101
0
  if( *aes_ccm_encrypted_key != NULL )
102
0
  {
103
0
    memory_free(
104
0
     *aes_ccm_encrypted_key );
105
106
0
    *aes_ccm_encrypted_key = NULL;
107
0
  }
108
0
  return( -1 );
109
8.21k
}
110
111
/* Frees an AES-CCM encrypted key
112
 * Returns 1 if successful or -1 on error
113
 */
114
int libbde_aes_ccm_encrypted_key_free(
115
     libbde_aes_ccm_encrypted_key_t **aes_ccm_encrypted_key,
116
     libcerror_error_t **error )
117
8.21k
{
118
8.21k
  static char *function = "libbde_aes_ccm_encrypted_key_free";
119
120
8.21k
  if( aes_ccm_encrypted_key == NULL )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
125
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
126
0
     "%s: invalid AES-CCM encrypted key.",
127
0
     function );
128
129
0
    return( -1 );
130
0
  }
131
8.21k
  if( *aes_ccm_encrypted_key != NULL )
132
8.21k
  {
133
8.21k
    if( ( *aes_ccm_encrypted_key )->data != NULL )
134
8.19k
    {
135
8.19k
      memory_free(
136
8.19k
       ( *aes_ccm_encrypted_key )->data );
137
8.19k
    }
138
8.21k
    memory_free(
139
8.21k
     *aes_ccm_encrypted_key );
140
141
8.21k
    *aes_ccm_encrypted_key = NULL;
142
8.21k
  }
143
8.21k
  return( 1 );
144
8.21k
}
145
146
/* Reads a AES-CCM encrypted key from the metadata entry
147
 * Returns 1 if successful or -1 on error
148
 */
149
int libbde_aes_ccm_encrypted_key_read(
150
     libbde_aes_ccm_encrypted_key_t *aes_ccm_encrypted_key,
151
     libbde_metadata_entry_t *metadata_entry,
152
     libcerror_error_t **error )
153
8.21k
{
154
8.21k
  uint8_t *value_data    = NULL;
155
8.21k
  static char *function  = "libbde_aes_ccm_encrypted_key_read";
156
8.21k
  size_t value_data_size = 0;
157
158
#if defined( HAVE_DEBUG_OUTPUT )
159
  uint32_t value_32bit   = 0;
160
#endif
161
162
8.21k
  if( aes_ccm_encrypted_key == NULL )
163
0
  {
164
0
    libcerror_error_set(
165
0
     error,
166
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
167
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
168
0
     "%s: invalid AES-CCM encrypted key.",
169
0
     function );
170
171
0
    return( -1 );
172
0
  }
173
8.21k
  if( metadata_entry == NULL )
174
0
  {
175
0
    libcerror_error_set(
176
0
     error,
177
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
178
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
179
0
     "%s: invalid metadata entry.",
180
0
     function );
181
182
0
    return( -1 );
183
0
  }
184
8.21k
  if( metadata_entry->value_data == NULL )
185
0
  {
186
0
    libcerror_error_set(
187
0
     error,
188
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
189
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
190
0
     "%s: invalid metadata entry - missing value data.",
191
0
     function );
192
193
0
    return( -1 );
194
0
  }
195
8.21k
  if( metadata_entry->value_type != LIBBDE_VALUE_TYPE_AES_CCM_ENCRYPTED_KEY )
196
17
  {
197
17
    libcerror_error_set(
198
17
     error,
199
17
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
200
17
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
201
17
     "%s: invalid metadata entry - unsupported value type: 0x%04" PRIx16 ".",
202
17
     function,
203
17
     metadata_entry->value_type );
204
205
17
    return( -1 );
206
17
  }
207
8.19k
  value_data      = metadata_entry->value_data;
208
8.19k
  value_data_size = metadata_entry->value_data_size;
209
210
8.19k
  if( ( value_data_size < sizeof( bde_metadata_entry_aes_ccm_encrypted_key_header_t ) )
211
8.19k
   || ( value_data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
212
4
  {
213
4
    libcerror_error_set(
214
4
     error,
215
4
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
216
4
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
217
4
     "%s: invalid metadata entry - value data size value out of bounds.",
218
4
     function );
219
220
4
    return( -1 );
221
4
  }
222
#if defined( HAVE_DEBUG_OUTPUT )
223
  if( libcnotify_verbose != 0 )
224
  {
225
    if( libbde_debug_print_filetime_value(
226
         function,
227
         "nonce time\t\t\t\t",
228
         ( (bde_metadata_entry_aes_ccm_encrypted_key_header_t *) value_data )->nonce_time,
229
         8,
230
         LIBFDATETIME_ENDIAN_LITTLE,
231
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME_NANO_SECONDS,
232
         error ) != 1 )
233
    {
234
      libcerror_error_set(
235
       error,
236
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
237
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
238
       "%s: unable to print FILETIME value.",
239
       function );
240
241
      goto on_error;
242
    }
243
    byte_stream_copy_to_uint32_little_endian(
244
     ( (bde_metadata_entry_aes_ccm_encrypted_key_header_t *) value_data )->nonce_counter,
245
     value_32bit );
246
    libcnotify_printf(
247
     "%s: nonce counter\t\t\t: %" PRIu32 "\n",
248
     function,
249
     value_32bit );
250
  }
251
#endif
252
8.19k
  if( memory_copy(
253
8.19k
       aes_ccm_encrypted_key->nonce,
254
8.19k
       value_data,
255
8.19k
       12 ) == NULL )
256
0
  {
257
0
    libcerror_error_set(
258
0
     error,
259
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
260
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
261
0
     "%s: unable to copy nonce to AES-CCM encrypted key.",
262
0
     function );
263
264
0
    return( -1 );
265
0
  }
266
8.19k
  value_data      += sizeof( bde_metadata_entry_aes_ccm_encrypted_key_header_t );
267
8.19k
  value_data_size -= sizeof( bde_metadata_entry_aes_ccm_encrypted_key_header_t );
268
269
#if defined( HAVE_DEBUG_OUTPUT )
270
  if( libcnotify_verbose != 0 )
271
  {
272
    libcnotify_printf(
273
     "%s: encrypted data:\n",
274
     function );
275
    libcnotify_print_data(
276
     value_data,
277
     value_data_size,
278
     0 );
279
  }
280
#endif
281
8.19k
  aes_ccm_encrypted_key->data = (uint8_t *) memory_allocate(
282
8.19k
                                             sizeof( uint8_t ) * value_data_size );
283
284
8.19k
  if( aes_ccm_encrypted_key->data == NULL )
285
0
  {
286
0
    libcerror_error_set(
287
0
     error,
288
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
289
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
290
0
     "%s: unable to create data.",
291
0
     function );
292
293
0
    goto on_error;
294
0
  }
295
8.19k
  if( memory_copy(
296
8.19k
       aes_ccm_encrypted_key->data,
297
8.19k
       value_data,
298
8.19k
       value_data_size ) == NULL )
299
0
  {
300
0
    libcerror_error_set(
301
0
     error,
302
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
303
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
304
0
     "%s: unable to copy data to AES-CCM encrypted key.",
305
0
     function );
306
307
0
    goto on_error;
308
0
  }
309
8.19k
  aes_ccm_encrypted_key->data_size = value_data_size;
310
  
311
8.19k
  return( 1 );
312
313
0
on_error:
314
0
  if( aes_ccm_encrypted_key->data != NULL )
315
0
  {
316
0
    memory_free(
317
0
     aes_ccm_encrypted_key->data );
318
319
    aes_ccm_encrypted_key->data = NULL;
320
0
  }
321
0
  return( -1 );
322
8.19k
}
323