Imported Upstream version 2.6.1
[platform/upstream/cryptsetup.git] / tests / fuzz / plain_json_proto_to_luks2_converter.cc
1 /*
2  * cryptsetup LUKS2 custom mutator fuzz target
3  *
4  * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
5  * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "plain_json_proto_to_luks2_converter.h"
23 #include "json_proto_converter.h"
24
25 extern "C" {
26 #include "src/cryptsetup.h"
27 #include "luks2/luks2.h"
28 #include <err.h>
29 }
30
31 namespace json_proto {
32
33 void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid, const std::string &json_text) {
34   struct luks2_hdr_disk hdr = {};
35   int r;
36
37   if (hd)
38     crypt_hash_destroy(hd);
39   if (crypt_hash_init(&hd, "sha256"))
40     err(EXIT_FAILURE, "crypt_hash_init failed");
41
42
43   r = lseek(fd, offset, SEEK_SET);
44   if (r == -1)
45     err(EXIT_FAILURE, "lseek failed");
46
47   switch (header_proto.magic()) {
48     case INVALID:
49       memset(&hdr.magic, 0, LUKS2_MAGIC_L);
50       break;
51     case FIRST:
52       memcpy(&hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L);
53       break;
54     case SECOND:
55       memcpy(&hdr.magic, LUKS2_MAGIC_2ND, LUKS2_MAGIC_L);
56       break;
57   }
58   hdr.version     = cpu_to_be16(header_proto.version());
59   hdr.hdr_size    = cpu_to_be64(header_proto.hdr_size());
60   hdr.seqid       = cpu_to_be64(seqid);
61   strncpy(hdr.checksum_alg, "sha256", LUKS2_CHECKSUM_ALG_L);
62   hdr.checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
63   strncpy(hdr.uuid, "af7f64ea-3233-4581-946b-6187d812841e", LUKS2_UUID_L);
64   memset(hdr.salt, 1, LUKS2_SALT_L);
65
66
67   if (header_proto.has_selected_offset())
68     hdr.hdr_offset  = cpu_to_be64(header_proto.selected_offset());
69   else
70     hdr.hdr_offset  = cpu_to_be64(offset);
71
72   if (write_buffer(fd, &hdr, LUKS2_HDR_BIN_LEN) != LUKS2_HDR_BIN_LEN)
73     err(EXIT_FAILURE, "write_buffer failed");
74   if (crypt_hash_write(hd, (char*)&hdr, LUKS2_HDR_BIN_LEN))
75     err(EXIT_FAILURE, "crypt_hash_write failed");
76
77   size_t hdr_json_area_len = header_proto.hdr_size() - LUKS2_HDR_BIN_LEN;
78   uint8_t csum[LUKS2_CHECKSUM_L];
79
80   size_t write_size = json_text.length() > hdr_json_area_len - 1 ? hdr_json_area_len - 1 : json_text.length();
81   if (write_buffer(fd, json_text.c_str(), write_size) != (ssize_t)write_size)
82     err(EXIT_FAILURE, "write_buffer failed");
83   if (crypt_hash_write(hd, json_text.c_str(), write_size))
84     err(EXIT_FAILURE, "crypt_hash_write failed");
85
86   for (size_t i = 0; i < (hdr_json_area_len - write_size); i++) {
87     if (crypt_hash_write(hd, "\0", 1))
88       err(EXIT_FAILURE, "crypt_hash_write failed");
89   }
90
91   if (header_proto.use_correct_checksum()) {
92     if (lseek(fd, offset + offsetof(luks2_hdr_disk, csum), SEEK_SET) == -1)
93       err(EXIT_FAILURE, "lseek failed");
94
95     int hash_size = crypt_hash_size("sha256");
96     if (hash_size <= 0)
97       err(EXIT_FAILURE, "crypt_hash_size failed");
98
99     if (crypt_hash_final(hd, (char*)csum, (size_t)hash_size))
100       err(EXIT_FAILURE, "crypt_hash_final failed");
101     if (write_buffer(fd, csum, hash_size) != hash_size)
102       err(EXIT_FAILURE, "write_buffer failed");
103   }
104 }
105
106 void LUKS2ProtoConverter::set_write_headers_only(bool headers_only) {
107   write_headers_only = headers_only;
108 }
109
110 void LUKS2ProtoConverter::convert(const LUKS2_both_headers &headers, int fd) {
111   uint64_t primary_seqid, secondary_seqid;
112   int result;
113
114   size_t out_size = headers.primary_header().hdr_size() + headers.secondary_header().hdr_size();
115
116   if (!write_headers_only)
117     out_size += KEYSLOTS_SIZE + DATA_SIZE;
118
119   result = ftruncate(fd, out_size);
120   if (result == -1)
121     err(EXIT_FAILURE, "truncate failed");
122
123   result = lseek(fd, 0, SEEK_SET);
124   if (result == -1)
125     err(EXIT_FAILURE, "lseek failed");
126
127   switch (headers.seqid()) {
128     case EQUAL:
129       primary_seqid = 1;
130       secondary_seqid = 1;
131       break;
132     case PRIMARY_GREATER:
133       primary_seqid = 2;
134       secondary_seqid = 1;
135       break;
136     case SECONDARY_GREATER:
137       primary_seqid = 1;
138       secondary_seqid = 2;
139       break;
140   }
141
142   JsonProtoConverter converter;
143   std::string json_text = converter.Convert(headers.json_area());
144
145   emit_luks2_binary_header(headers.primary_header(), fd, 0, primary_seqid, json_text);
146   emit_luks2_binary_header(headers.secondary_header(), fd, headers.primary_header().hdr_size(), secondary_seqid, json_text);
147 }
148
149 LUKS2ProtoConverter::~LUKS2ProtoConverter() {
150   if (hd)
151     crypt_hash_destroy(hd);
152 }
153 }  // namespace LUKS2_proto