Coverage Report

Created: 2026-08-12 06:14

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-2026 Red Hat, Inc. All rights reserved.
7
 */
8
9
extern "C" {
10
5.43k
#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
14
#define CHKSUM_ALG "sha256"
17
14
#define CHKSUM_SIZE 32
18
19
static bool fix_checksum_hdr(struct luks2_hdr_disk *hdr, const char *data, size_t len)
20
14
{
21
14
  char *csum = (char *)&hdr->csum;
22
14
  struct crypt_hash *hd = NULL;
23
14
  bool r = false;
24
25
14
  if (crypt_hash_init(&hd, CHKSUM_ALG))
26
0
    return false;
27
28
14
  memset(csum, 0, LUKS2_CHECKSUM_L);
29
30
14
  if (!crypt_hash_write(hd, data, len) &&
31
14
      !crypt_hash_final(hd, csum, CHKSUM_SIZE))
32
14
    r = true;
33
34
14
  crypt_hash_destroy(hd);
35
14
  return r;
36
14
}
37
38
static bool calculate_checksum(const char *data, size_t size, struct luks2_hdr_disk *hdr_rw)
39
4.34k
{
40
4.34k
  uint64_t hdr_size;
41
42
  /* Primary header cannot fit in data */
43
4.34k
  if (sizeof(*hdr_rw) > size)
44
0
    return false;
45
46
4.34k
  hdr_size = be64_to_cpu(((struct luks2_hdr_disk *)(uintptr_t)data)->hdr_size);
47
4.34k
  if (hdr_size > size || hdr_size <= sizeof(*hdr_rw))
48
4.33k
    return false;
49
50
  /* Calculate checksum for primary header */
51
14
  memcpy(hdr_rw, data, sizeof(*hdr_rw));
52
14
  return fix_checksum_hdr(hdr_rw, data, (size_t)hdr_size);
53
4.34k
}
54
55
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
56
5.43k
{
57
5.43k
  int fd, r = EXIT_FAILURE;
58
5.43k
  struct crypt_device *cd = NULL;
59
5.43k
  char name[] = "/tmp/test-script-fuzz.XXXXXX";
60
5.43k
  struct luks2_hdr_disk hdr_rw;
61
5.43k
  size_t modified_data_size;
62
63
  /* if csum calculation fails, keep fuzzer running on original input */
64
5.43k
  if (size >= sizeof(hdr_rw) && calculate_checksum((const char *)data, size, &hdr_rw))
65
14
    modified_data_size = sizeof(hdr_rw);
66
5.42k
  else
67
5.42k
    modified_data_size = 0;
68
69
  /* create file with LUKS header for libcryptsetup */
70
5.43k
  fd = mkostemp(name, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
71
5.43k
  if (fd == -1)
72
0
    return r;
73
74
  /* enlarge header */
75
5.43k
  if (ftruncate(fd, FILESIZE) == -1)
76
0
    goto out;
77
78
5.43k
  if (modified_data_size &&
79
14
      write_buffer(fd, &hdr_rw, modified_data_size) != (ssize_t)modified_data_size)
80
0
    goto out;
81
82
5.43k
  if (write_buffer(fd, data + modified_data_size, size - modified_data_size) != (ssize_t)size)
83
14
    goto out;
84
85
  /* Actual fuzzing */
86
5.42k
  if (crypt_init(&cd, name) == 0)
87
5.42k
    (void)crypt_load(cd, CRYPT_LUKS2, NULL);
88
5.42k
  crypt_free(cd);
89
5.42k
  r = 0;
90
5.43k
out:
91
5.43k
  close(fd);
92
5.43k
  unlink(name);
93
94
5.43k
  return r;
95
5.42k
}
96
}