Coverage Report

Created: 2026-02-11 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptsetup/tests/fuzz/crypt2_load_fuzz.cc
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * cryptsetup LUKS2 fuzz target
4
 *
5
 * Copyright (C) 2022-2025 Daniel Zatovic <daniel.zatovic@gmail.com>
6
 * Copyright (C) 2022-2025 Red Hat, Inc. All rights reserved.
7
 */
8
9
extern "C" {
10
5.46k
#define FILESIZE (16777216)
11
#include "src/cryptsetup.h"
12
#include "luks2/luks2.h"
13
#include "crypto_backend/crypto_backend.h"
14
#include "FuzzerInterface.h"
15
16
21
#define CHKSUM_ALG "sha256"
17
21
#define CHKSUM_SIZE 32
18
19
static bool fix_checksum_hdr(struct luks2_hdr_disk *hdr, const char *data, size_t len)
20
21
{
21
21
  char *csum = (char *)&hdr->csum;
22
21
  struct crypt_hash *hd = NULL;
23
21
  bool r = false;
24
25
21
  if (crypt_hash_init(&hd, CHKSUM_ALG))
26
0
    return false;
27
28
21
  memset(csum, 0, LUKS2_CHECKSUM_L);
29
30
21
  if (!crypt_hash_write(hd, data, len) &&
31
21
      !crypt_hash_final(hd, csum, CHKSUM_SIZE))
32
21
    r = true;
33
34
21
  crypt_hash_destroy(hd);
35
21
  return r;
36
21
}
37
38
static bool calculate_checksum(const char *data, size_t size, struct luks2_hdr_disk *hdr_rw)
39
4.50k
{
40
4.50k
  uint64_t hdr_size;
41
42
  /* Primary header cannot fit in data */
43
4.50k
  if (sizeof(*hdr_rw) > size)
44
0
    return false;
45
46
4.50k
  hdr_size = be64_to_cpu(((struct luks2_hdr_disk *)data)->hdr_size);
47
4.50k
  if (hdr_size > size || hdr_size <= sizeof(*hdr_rw))
48
4.47k
    return false;
49
50
  /* Calculate checksum for primary header */
51
21
  memcpy(hdr_rw, data, sizeof(*hdr_rw));
52
21
  return fix_checksum_hdr(hdr_rw, data, (size_t)hdr_size);
53
4.50k
}
54
55
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
56
5.46k
{
57
5.46k
  int fd, r = EXIT_FAILURE;
58
5.46k
  struct crypt_device *cd = NULL;
59
5.46k
  char name[] = "/tmp/test-script-fuzz.XXXXXX";
60
5.46k
  struct luks2_hdr_disk hdr_rw;
61
5.46k
  size_t modified_data_size;
62
63
  /* if csum calculation fails, keep fuzzer running on original input */
64
5.46k
  if (size >= sizeof(hdr_rw) && calculate_checksum((const char *)data, size, &hdr_rw))
65
21
    modified_data_size = sizeof(hdr_rw);
66
5.44k
  else
67
5.44k
    modified_data_size = 0;
68
69
  /* create file with LUKS header for libcryptsetup */
70
5.46k
  fd = mkostemp(name, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
71
5.46k
  if (fd == -1)
72
0
    return r;
73
74
  /* enlarge header */
75
5.46k
  if (ftruncate(fd, FILESIZE) == -1)
76
0
    goto out;
77
78
5.46k
  if (modified_data_size &&
79
21
      write_buffer(fd, &hdr_rw, modified_data_size) != (ssize_t)modified_data_size)
80
0
    goto out;
81
82
5.46k
  if (write_buffer(fd, data + modified_data_size, size - modified_data_size) != (ssize_t)size)
83
21
    goto out;
84
85
  /* Actual fuzzing */
86
5.44k
  if (crypt_init(&cd, name) == 0)
87
5.44k
    (void)crypt_load(cd, CRYPT_LUKS2, NULL);
88
5.44k
  crypt_free(cd);
89
5.44k
  r = 0;
90
5.46k
out:
91
5.46k
  close(fd);
92
5.46k
  unlink(name);
93
94
5.46k
  return r;
95
5.44k
}
96
}