Coverage Report

Created: 2025-06-13 07:21

/src/libluksde/libluksde/libluksde_diffuser.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * LUKS anti-forensic (AF) diffuser functions
3
 *
4
 * Copyright (C) 2013-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 "libluksde_definitions.h"
28
#include "libluksde_diffuser.h"
29
#include "libluksde_libcerror.h"
30
#include "libluksde_libcnotify.h"
31
#include "libluksde_libhmac.h"
32
33
/* Diffuses data
34
 * Returns 1 if successful or -1 on error
35
 */
36
int libluksde_diffuser_diffuse(
37
     uint8_t *data,
38
     size_t data_size,
39
     int hashing_method,
40
     libcerror_error_t **error )
41
0
{
42
0
  uint8_t block_index_buffer[ 4 ];
43
0
  uint8_t hash_buffer[ 64 ];
44
45
0
  libhmac_sha1_context_t *sha1_context     = NULL;
46
0
  libhmac_sha224_context_t *sha224_context = NULL;
47
0
  libhmac_sha256_context_t *sha256_context = NULL;
48
0
  libhmac_sha512_context_t *sha512_context = NULL;
49
0
  static char *function                    = "libluksde_diffuser_diffuse";
50
0
  size_t data_offset                       = 0;
51
0
  size_t hash_size                         = 0;
52
0
  size_t read_size                         = 0;
53
0
  uint32_t block_index                     = 0;
54
0
  int result                               = 0;
55
56
0
  if( data == NULL )
57
0
  {
58
0
    libcerror_error_set(
59
0
     error,
60
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
61
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
62
0
     "%s: invalid data.",
63
0
     function );
64
65
0
    return( -1 );
66
0
  }
67
#if SIZEOF_SIZE_T <= 4
68
  if( data_size > (size_t) SSIZE_MAX )
69
#else
70
0
  if( data_size > (size_t) UINT32_MAX )
71
0
#endif
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
76
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
77
0
     "%s: invalid data size value exceeds maximum.",
78
0
     function );
79
80
0
    return( -1 );
81
0
  }
82
0
  switch( hashing_method )
83
0
  {
84
0
    case LIBLUKSDE_HASHING_METHOD_SHA1:
85
0
      hash_size = LIBHMAC_SHA1_HASH_SIZE;
86
0
      break;
87
88
0
    case LIBLUKSDE_HASHING_METHOD_SHA224:
89
0
      hash_size = LIBHMAC_SHA224_HASH_SIZE;
90
0
      break;
91
92
0
    case LIBLUKSDE_HASHING_METHOD_SHA256:
93
0
      hash_size = LIBHMAC_SHA256_HASH_SIZE;
94
0
      break;
95
96
0
    case LIBLUKSDE_HASHING_METHOD_SHA512:
97
0
      hash_size = LIBHMAC_SHA512_HASH_SIZE;
98
0
      break;
99
100
0
    default:
101
0
      libcerror_error_set(
102
0
       error,
103
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
104
0
       LIBCERROR_ARGUMENT_ERROR_UNSUPPORTED_VALUE,
105
0
       "%s: unsupported hashing method.",
106
0
       function );
107
108
0
      return( -1 );
109
0
  }
110
0
  while( data_size > 0 )
111
0
  {
112
0
    switch( hashing_method )
113
0
    {
114
0
      case LIBLUKSDE_HASHING_METHOD_SHA1:
115
0
        result = libhmac_sha1_initialize(
116
0
            &sha1_context,
117
0
            error );
118
0
        break;
119
120
0
      case LIBLUKSDE_HASHING_METHOD_SHA224:
121
0
        result = libhmac_sha224_initialize(
122
0
            &sha224_context,
123
0
            error );
124
0
        break;
125
126
0
      case LIBLUKSDE_HASHING_METHOD_SHA256:
127
0
        result = libhmac_sha256_initialize(
128
0
            &sha256_context,
129
0
            error );
130
0
        break;
131
132
0
      case LIBLUKSDE_HASHING_METHOD_SHA512:
133
0
        result = libhmac_sha512_initialize(
134
0
            &sha512_context,
135
0
            error );
136
0
        break;
137
138
0
      default:
139
0
        result = 0;
140
0
        break;
141
0
    }
142
0
    if( result != 1 )
143
0
    {
144
0
      libcerror_error_set(
145
0
       error,
146
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
147
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
148
0
       "%s: unable to initialize context.",
149
0
       function );
150
151
0
      goto on_error;
152
0
    }
153
0
    byte_stream_copy_from_uint32_big_endian(
154
0
     block_index_buffer,
155
0
     block_index );
156
157
0
    switch( hashing_method )
158
0
    {
159
0
      case LIBLUKSDE_HASHING_METHOD_SHA1:
160
0
        result = libhmac_sha1_update(
161
0
                  sha1_context,
162
0
                  block_index_buffer,
163
0
                  4,
164
0
                  error );
165
0
        break;
166
167
0
      case LIBLUKSDE_HASHING_METHOD_SHA224:
168
0
        result = libhmac_sha224_update(
169
0
                  sha224_context,
170
0
                  block_index_buffer,
171
0
                  4,
172
0
                  error );
173
0
        break;
174
175
0
      case LIBLUKSDE_HASHING_METHOD_SHA256:
176
0
        result = libhmac_sha256_update(
177
0
                  sha256_context,
178
0
                  block_index_buffer,
179
0
                  4,
180
0
                  error );
181
0
        break;
182
183
0
      case LIBLUKSDE_HASHING_METHOD_SHA512:
184
0
        result = libhmac_sha512_update(
185
0
                  sha512_context,
186
0
                  block_index_buffer,
187
0
                  4,
188
0
                  error );
189
0
        break;
190
191
0
      default:
192
0
        result = 0;
193
0
        break;
194
0
    }
195
0
    if( result != 1 )
196
0
    {
197
0
      libcerror_error_set(
198
0
       error,
199
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
200
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
201
0
       "%s: unable to update context.",
202
0
       function );
203
204
0
      goto on_error;
205
0
    }
206
0
    if( data_size < hash_size )
207
0
    {
208
0
      read_size = data_size;
209
0
    }
210
0
    else
211
0
    {
212
0
      read_size = hash_size;
213
0
    }
214
0
    switch( hashing_method )
215
0
    {
216
0
      case LIBLUKSDE_HASHING_METHOD_SHA1:
217
0
        result = libhmac_sha1_update(
218
0
                  sha1_context,
219
0
                  &( data[ data_offset ] ),
220
0
                  read_size,
221
0
                  error );
222
0
        break;
223
224
0
      case LIBLUKSDE_HASHING_METHOD_SHA224:
225
0
        result = libhmac_sha224_update(
226
0
                  sha224_context,
227
0
                  &( data[ data_offset ] ),
228
0
                  read_size,
229
0
                  error );
230
0
        break;
231
232
0
      case LIBLUKSDE_HASHING_METHOD_SHA256:
233
0
        result = libhmac_sha256_update(
234
0
                  sha256_context,
235
0
                  &( data[ data_offset ] ),
236
0
                  read_size,
237
0
                  error );
238
0
        break;
239
240
0
      case LIBLUKSDE_HASHING_METHOD_SHA512:
241
0
        result = libhmac_sha512_update(
242
0
                  sha512_context,
243
0
                  &( data[ data_offset ] ),
244
0
                  read_size,
245
0
                  error );
246
0
        break;
247
248
0
      default:
249
0
        result = 0;
250
0
        break;
251
0
    }
252
0
    if( result != 1 )
253
0
    {
254
0
      libcerror_error_set(
255
0
       error,
256
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
257
0
       LIBCERROR_RUNTIME_ERROR_SET_FAILED,
258
0
       "%s: unable to update context.",
259
0
       function );
260
261
0
      goto on_error;
262
0
    }
263
0
    switch( hashing_method )
264
0
    {
265
0
      case LIBLUKSDE_HASHING_METHOD_SHA1:
266
0
        result = libhmac_sha1_finalize(
267
0
                  sha1_context,
268
0
                  hash_buffer,
269
0
                  hash_size,
270
0
                  error );
271
0
        break;
272
273
0
      case LIBLUKSDE_HASHING_METHOD_SHA224:
274
0
        result = libhmac_sha224_finalize(
275
0
                  sha224_context,
276
0
                  hash_buffer,
277
0
                  hash_size,
278
0
                  error );
279
0
        break;
280
281
0
      case LIBLUKSDE_HASHING_METHOD_SHA256:
282
0
        result = libhmac_sha256_finalize(
283
0
                  sha256_context,
284
0
                  hash_buffer,
285
0
                  hash_size,
286
0
                  error );
287
0
        break;
288
289
0
      case LIBLUKSDE_HASHING_METHOD_SHA512:
290
0
        result = libhmac_sha512_finalize(
291
0
                  sha512_context,
292
0
                  hash_buffer,
293
0
                  hash_size,
294
0
                  error );
295
0
        break;
296
297
0
      default:
298
0
        result = 0;
299
0
        break;
300
0
    }
301
0
    if( result != 1 )
302
0
    {
303
0
      libcerror_error_set(
304
0
       error,
305
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
306
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
307
0
       "%s: unable to finalize context.",
308
0
       function );
309
310
0
      goto on_error;
311
0
    }
312
0
    switch( hashing_method )
313
0
    {
314
0
      case LIBLUKSDE_HASHING_METHOD_SHA1:
315
0
        result = libhmac_sha1_free(
316
0
                  &sha1_context,
317
0
                  error );
318
0
        break;
319
320
0
      case LIBLUKSDE_HASHING_METHOD_SHA224:
321
0
        result = libhmac_sha224_free(
322
0
                  &sha224_context,
323
0
                  error );
324
0
        break;
325
326
0
      case LIBLUKSDE_HASHING_METHOD_SHA256:
327
0
        result = libhmac_sha256_free(
328
0
                  &sha256_context,
329
0
                  error );
330
0
        break;
331
332
0
      case LIBLUKSDE_HASHING_METHOD_SHA512:
333
0
        result = libhmac_sha512_free(
334
0
                  &sha512_context,
335
0
                  error );
336
0
        break;
337
338
0
      default:
339
0
        result = 0;
340
0
        break;
341
0
    }
342
0
    if( result != 1 )
343
0
    {
344
0
      libcerror_error_set(
345
0
       error,
346
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
347
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
348
0
       "%s: unable to free context.",
349
0
       function );
350
351
0
      goto on_error;
352
0
    }
353
0
    if( memory_copy(
354
0
         &( data[ data_offset ] ),
355
0
         hash_buffer,
356
0
         read_size ) == NULL)
357
0
    {
358
0
      libcerror_error_set(
359
0
       error,
360
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
361
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
362
0
       "%s: unable to copy hash to data.",
363
0
       function );
364
365
0
      goto on_error;
366
0
    }
367
0
    data_offset += read_size;
368
0
    data_size   -= read_size;
369
370
0
    block_index++;
371
0
  }
372
0
  return( 1 );
373
374
0
on_error:
375
0
  if( sha512_context != NULL )
376
0
  {
377
0
    libhmac_sha512_free(
378
0
     &sha512_context,
379
0
     NULL );
380
0
  }
381
0
  if( sha256_context != NULL )
382
0
  {
383
0
    libhmac_sha256_free(
384
0
     &sha256_context,
385
0
     NULL );
386
0
  }
387
0
  if( sha224_context != NULL )
388
0
  {
389
0
    libhmac_sha224_free(
390
0
     &sha224_context,
391
0
     NULL );
392
0
  }
393
0
  if( sha1_context != NULL )
394
0
  {
395
0
    libhmac_sha1_free(
396
0
     &sha1_context,
397
0
     NULL );
398
0
  }
399
0
  return( -1 );
400
0
}
401
402
/* Merges the split data using the diffuser
403
 * Returns 1 if successful or -1 on error
404
 */
405
int libluksde_diffuser_merge(
406
     const uint8_t *split_data,
407
     size_t split_data_size,
408
     uint8_t *data,
409
     size_t data_size,
410
     uint32_t number_of_stripes,
411
     int hashing_method,
412
     libcerror_error_t **error )
413
0
{
414
0
  static char *function    = "libluksde_diffuser_merge";
415
0
  size_t data_offset       = 0;
416
0
  size_t split_data_offset = 0;
417
0
  uint32_t stripe_iterator = 0;
418
419
0
  if( split_data == NULL )
420
0
  {
421
0
    libcerror_error_set(
422
0
     error,
423
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
424
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
425
0
     "%s: invalid split data.",
426
0
     function );
427
428
0
    return( -1 );
429
0
  }
430
0
  if( ( split_data_size == 0 )
431
0
   || ( split_data_size > (size_t) SSIZE_MAX ) )
432
0
  {
433
0
    libcerror_error_set(
434
0
     error,
435
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
436
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
437
0
     "%s: invalid split data size value out of bounds.",
438
0
     function );
439
440
0
    return( -1 );
441
0
  }
442
0
  if( data == NULL )
443
0
  {
444
0
    libcerror_error_set(
445
0
     error,
446
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
447
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
448
0
     "%s: invalid data.",
449
0
     function );
450
451
0
    return( -1 );
452
0
  }
453
0
  if( ( data_size == 0 )
454
0
   || ( data_size > split_data_size ) )
455
0
  {
456
0
    libcerror_error_set(
457
0
     error,
458
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
459
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
460
0
     "%s: invalid data size value out of bounds.",
461
0
     function );
462
463
0
    return( -1 );
464
0
  }
465
0
  if( ( number_of_stripes < 1 )
466
0
   || ( number_of_stripes > ( split_data_size / data_size ) ) )
467
0
  {
468
0
    libcerror_error_set(
469
0
     error,
470
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
471
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
472
0
     "%s: number of stripes value out of bounds.",
473
0
     function );
474
475
0
    return( -1 );
476
0
  }
477
0
  if( memory_set(
478
0
       data,
479
0
       0,
480
0
       data_size ) == NULL )
481
0
  {
482
0
    libcerror_error_set(
483
0
     error,
484
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
485
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
486
0
     "%s: unable to clear data.",
487
0
     function );
488
489
0
    return( -1 );
490
0
  }
491
0
  for( stripe_iterator = 0;
492
0
       stripe_iterator < ( number_of_stripes - 1 );
493
0
       stripe_iterator++ )
494
0
  {
495
0
    for( data_offset = 0;
496
0
         data_offset < data_size;
497
0
         data_offset++ )
498
0
    {
499
0
      data[ data_offset ] ^= split_data[ split_data_offset ];
500
501
0
      split_data_offset++;
502
0
    }
503
0
    if( libluksde_diffuser_diffuse(
504
0
         data,
505
0
         data_size,
506
0
         hashing_method,
507
0
         error ) != 1 )
508
0
    {
509
0
      libcerror_error_set(
510
0
       error,
511
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
512
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
513
0
       "%s: unable to diffuse stripe: %" PRIu32 ".",
514
0
       function,
515
0
       stripe_iterator );
516
517
0
      return( -1 );
518
0
    }
519
0
  }
520
0
  for( data_offset = 0;
521
0
       data_offset < data_size;
522
0
       data_offset++ )
523
0
  {
524
0
    data[ data_offset ] ^= split_data[ split_data_offset ];
525
526
0
    split_data_offset++;
527
0
  }
528
0
  return( 1 );
529
0
}
530