Coverage Report

Created: 2026-07-10 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libregf/libregf/libregf_security_key.c
Line
Count
Source
1
/*
2
 * Security key functions
3
 *
4
 * Copyright (C) 2009-2026, 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 "libregf_debug.h"
28
#include "libregf_io_handle.h"
29
#include "libregf_libcerror.h"
30
#include "libregf_libcnotify.h"
31
#include "libregf_libfwnt.h"
32
#include "libregf_security_key.h"
33
34
#include "regf_cell_values.h"
35
36
/* Creates a security key
37
 * Make sure the value security_key is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libregf_security_key_initialize(
41
     libregf_security_key_t **security_key,
42
     libcerror_error_t **error )
43
597
{
44
597
  static char *function = "libregf_security_key_initialize";
45
46
597
  if( security_key == 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 security key.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
597
  if( *security_key != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid security key value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
597
  *security_key = memory_allocate_structure(
69
597
                   libregf_security_key_t );
70
71
597
  if( *security_key == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create security key.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
597
  if( memory_set(
83
597
       *security_key,
84
597
       0,
85
597
       sizeof( libregf_security_key_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear security key.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
597
  return( 1 );
97
98
0
on_error:
99
0
  if( *security_key != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *security_key );
103
104
0
    *security_key = NULL;
105
0
  }
106
0
  return( -1 );
107
597
}
108
109
/* Frees a security key
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libregf_security_key_free(
113
     libregf_security_key_t **security_key,
114
     libcerror_error_t **error )
115
597
{
116
597
  static char *function = "libregf_security_key_free";
117
118
597
  if( security_key == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid security key.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
597
  if( *security_key != NULL )
130
597
  {
131
597
    if( ( *security_key )->security_descriptor != NULL )
132
0
    {
133
0
      memory_free(
134
0
       ( *security_key )->security_descriptor );
135
0
    }
136
597
    memory_free(
137
597
     *security_key );
138
139
597
    *security_key = NULL;
140
597
  }
141
597
  return( 1 );
142
597
}
143
144
/* Reads a security key
145
 * Returns 1 if successful or -1 on error
146
 */
147
int libregf_security_key_read_data(
148
     libregf_security_key_t *security_key,
149
     libregf_io_handle_t *io_handle,
150
     const uint8_t *data,
151
     size_t data_size,
152
     libcerror_error_t **error )
153
597
{
154
597
  static char *function             = "libregf_security_key_read_data";
155
597
  size_t data_offset                = 0;
156
597
  size_t security_key_data_size     = 0;
157
597
  uint32_t security_descriptor_size = 0;
158
159
#if defined( HAVE_DEBUG_OUTPUT )
160
  uint32_t value_32bit              = 0;
161
  uint16_t value_16bit              = 0;
162
#endif
163
164
597
  if( security_key == NULL )
165
0
  {
166
0
    libcerror_error_set(
167
0
     error,
168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
169
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
170
0
     "%s: invalid security key.",
171
0
     function );
172
173
0
    return( -1 );
174
0
  }
175
597
  if( security_key->security_descriptor != NULL )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
180
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
181
0
     "%s: invalid security key - security descriptor value already set.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
597
  if( io_handle == NULL )
187
0
  {
188
0
    libcerror_error_set(
189
0
     error,
190
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
191
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
192
0
     "%s: invalid IO handle.",
193
0
     function );
194
195
0
    return( -1 );
196
0
  }
197
597
  security_key_data_size = sizeof( regf_security_key_t );
198
199
597
  if( ( io_handle->major_version == 1 )
200
395
   && ( io_handle->minor_version <= 1 ) )
201
0
  {
202
0
    security_key_data_size += 4;
203
0
  }
204
597
  if( data == NULL )
205
0
  {
206
0
    libcerror_error_set(
207
0
     error,
208
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
209
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
210
0
     "%s: invalid data.",
211
0
     function );
212
213
0
    return( -1 );
214
0
  }
215
597
  if( ( data_size < security_key_data_size )
216
594
   || ( data_size > (size_t) SSIZE_MAX ) )
217
3
  {
218
3
    libcerror_error_set(
219
3
     error,
220
3
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
221
3
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
222
3
     "%s: invalid data size value out of bounds.",
223
3
     function );
224
225
3
    return( -1 );
226
3
  }
227
#if defined( HAVE_DEBUG_OUTPUT )
228
  if( libcnotify_verbose != 0 )
229
  {
230
    libcnotify_printf(
231
     "%s: security key data:\n",
232
     function );
233
    libcnotify_print_data(
234
     data,
235
     data_size,
236
     0 );
237
  }
238
#endif
239
594
  if( ( io_handle->major_version == 1 )
240
394
   && ( io_handle->minor_version <= 1 ) )
241
0
  {
242
0
    data_offset += 4;
243
0
  }
244
  /* Check if the signature matches that of a security key: "sk"
245
   */
246
594
  if( ( data[ data_offset ] != (uint8_t) 's' )
247
504
   || ( data[ data_offset + 1 ] != (uint8_t) 'k' ) )
248
104
  {
249
104
    libcerror_error_set(
250
104
     error,
251
104
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
252
104
     LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
253
104
     "%s: unsupported security key signature.",
254
104
     function );
255
256
104
    goto on_error;
257
104
  }
258
490
  byte_stream_copy_to_uint32_little_endian(
259
490
   ( (regf_security_key_t *) &( data[ data_offset ] ) )->security_descriptor_size,
260
490
   security_descriptor_size );
261
262
#if defined( HAVE_DEBUG_OUTPUT )
263
  if( libcnotify_verbose != 0 )
264
  {
265
    if( ( io_handle->major_version == 1 )
266
     && ( io_handle->minor_version <= 1 ) )
267
    {
268
      byte_stream_copy_to_uint32_little_endian(
269
       data,
270
       value_32bit );
271
      libcnotify_printf(
272
       "%s: unknown0\t\t\t\t: 0x%08" PRIx32 " (%" PRIi32 ")\n",
273
       function,
274
       value_32bit,
275
       (int32_t) value_32bit );
276
    }
277
    libcnotify_printf(
278
     "%s: signature\t\t\t\t: %c%c\n",
279
     function,
280
     ( (regf_security_key_t *) &( data[ data_offset ] ) )->signature[ 0 ],
281
     ( (regf_security_key_t *) &( data[ data_offset ] ) )->signature[ 1 ] );
282
283
    byte_stream_copy_to_uint16_little_endian(
284
     ( (regf_security_key_t *) &( data[ data_offset ] ) )->unknown1,
285
     value_16bit );
286
    libcnotify_printf(
287
     "%s: unknown1\t\t\t\t: 0x%04" PRIx16 " (%" PRIu16 ")\n",
288
     function,
289
     value_16bit,
290
     value_16bit );
291
292
    byte_stream_copy_to_uint32_little_endian(
293
     ( (regf_security_key_t *) &( data[ data_offset ] ) )->previous_security_key_offset,
294
     value_32bit );
295
    libcnotify_printf(
296
     "%s: previous security key offset\t\t: 0x%08" PRIx32 "\n",
297
     function,
298
     value_32bit );
299
300
    byte_stream_copy_to_uint32_little_endian(
301
     ( (regf_security_key_t *) &( data[ data_offset ] ) )->next_security_key_offset,
302
     value_32bit );
303
    libcnotify_printf(
304
     "%s: next security key offset\t\t: 0x%08" PRIx32 "\n",
305
     function,
306
     value_32bit );
307
308
    byte_stream_copy_to_uint32_little_endian(
309
     ( (regf_security_key_t *) &( data[ data_offset ] ) )->reference_count,
310
     value_32bit );
311
    libcnotify_printf(
312
     "%s: reference count\t\t\t\t: %" PRIu32 "\n",
313
     function,
314
     value_32bit );
315
316
    libcnotify_printf(
317
     "%s: security descriptor size\t\t: %" PRIu32 "\n",
318
     function,
319
     security_descriptor_size );
320
321
    libcnotify_printf(
322
     "\n" );
323
  }
324
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
325
326
490
  data_offset += sizeof( regf_security_key_t );
327
328
490
  if( security_descriptor_size > ( data_size - data_offset ) )
329
53
  {
330
53
    libcerror_error_set(
331
53
     error,
332
53
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
333
53
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
334
53
     "%s: invalid security descriptor size value out of bounds.",
335
53
     function );
336
337
53
    goto on_error;
338
53
  }
339
#if defined( HAVE_DEBUG_OUTPUT )
340
  if( libcnotify_verbose != 0 )
341
  {
342
    libcnotify_printf(
343
     "%s: security descriptor data:\n",
344
     function );
345
    libcnotify_print_data(
346
     &( data[ data_offset ] ),
347
     security_descriptor_size,
348
     0 );
349
  }
350
#endif
351
437
  if( security_descriptor_size > 0 )
352
364
  {
353
364
    if( security_descriptor_size > (uint32_t) MEMORY_MAXIMUM_ALLOCATION_SIZE )
354
0
    {
355
0
      libcerror_error_set(
356
0
       error,
357
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
358
0
       LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
359
0
       "%s: invalid security descriptor size value exceeds maximum allocation size.",
360
0
       function );
361
362
0
      goto on_error;
363
0
    }
364
364
    security_key->security_descriptor = (uint8_t *) memory_allocate(
365
364
                                                     sizeof( uint8_t ) * security_descriptor_size );
366
367
364
    if( security_key->security_descriptor == NULL )
368
0
    {
369
0
      libcerror_error_set(
370
0
       error,
371
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
372
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
373
0
       "%s: unable to create security descriptor.",
374
0
       function );
375
376
0
      goto on_error;
377
0
    }
378
364
    if( memory_copy(
379
364
         security_key->security_descriptor,
380
364
         &( data[ data_offset ] ),
381
364
         security_descriptor_size ) == NULL )
382
0
    {
383
0
      libcerror_error_set(
384
0
       error,
385
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
386
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
387
0
       "%s: unable to copy security descriptor data.",
388
0
       function );
389
390
0
      goto on_error;
391
0
    }
392
364
    security_key->security_descriptor_size = security_descriptor_size;
393
394
#if defined( HAVE_DEBUG_OUTPUT )
395
    if( libcnotify_verbose != 0 )
396
    {
397
      if( libregf_debug_print_security_descriptor_value(
398
           security_key->security_descriptor,
399
           security_key->security_descriptor_size,
400
           LIBFWNT_ENDIAN_LITTLE,
401
           error ) != 1 )
402
      {
403
        libcerror_error_set(
404
         error,
405
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
406
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
407
         "%s: unable to print security descriptor value.",
408
         function );
409
410
        goto on_error;
411
      }
412
    }
413
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
414
364
  }
415
#if defined( HAVE_DEBUG_OUTPUT )
416
  data_offset += security_descriptor_size;
417
418
  if( libcnotify_verbose != 0 )
419
  {
420
    if( data_offset < data_size )
421
    {
422
      libcnotify_printf(
423
       "%s: padding:\n",
424
       function );
425
      libcnotify_print_data(
426
       &( data[ data_offset ] ),
427
       data_size - data_offset,
428
       0 );
429
    }
430
  }
431
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
432
433
437
  return( 1 );
434
435
157
on_error:
436
157
  if( security_key->security_descriptor != NULL )
437
0
  {
438
0
    memory_free(
439
0
     security_key->security_descriptor );
440
441
0
    security_key->security_descriptor = NULL;
442
0
  }
443
157
  security_key->security_descriptor_size = 0;
444
445
157
  return( -1 );
446
437
}
447