summaryrefslogtreecommitdiff
path: root/tests/fuzz/proto_to_luks2_converter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fuzz/proto_to_luks2_converter.cc')
-rw-r--r--tests/fuzz/proto_to_luks2_converter.cc604
1 files changed, 604 insertions, 0 deletions
diff --git a/tests/fuzz/proto_to_luks2_converter.cc b/tests/fuzz/proto_to_luks2_converter.cc
new file mode 100644
index 0000000..96a70b7
--- /dev/null
+++ b/tests/fuzz/proto_to_luks2_converter.cc
@@ -0,0 +1,604 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "proto_to_luks2_converter.h"
+#include <iostream>
+
+extern "C" {
+#include "src/cryptsetup.h"
+#include "luks2/luks2.h"
+#include <err.h>
+}
+
+namespace LUKS2_proto {
+
+std::string LUKS2ProtoConverter::string_uint64_to_string(const string_uint64 &str_u64) {
+ std::ostringstream os;
+
+ if (str_u64.negative())
+ os << "-";
+
+ if (str_u64.has_uint_num())
+ os << str_u64.uint_num();
+ else if (str_u64.has_string_num())
+ os << str_u64.string_num();
+
+ return os.str();
+}
+
+std::string LUKS2ProtoConverter::object_id_to_string(const object_id &oid) {
+ std::ostringstream os;
+
+ if (oid.has_int_id()) {
+ os << (oid.int_id() % 33) - 16;
+ } else if (oid.has_string_id()) {
+ os << oid.string_id();
+ }
+
+ return os.str();
+}
+
+std::string LUKS2ProtoConverter::hash_algorithm_to_string(const hash_algorithm type) {
+ switch (type) {
+ case HASH_ALG_SHA1:
+ return "sha1";
+ case HASH_ALG_SHA256:
+ return "sha256";
+ }
+}
+
+std::string LUKS2ProtoConverter::keyslot_area_type_to_string(const keyslot_area_type type) {
+ switch (type) {
+ case KEYSLOT_AREA_TYPE_RAW:
+ return "raw";
+ case KEYSLOT_AREA_TYPE_NONE:
+ return "none";
+ case KEYSLOT_AREA_TYPE_JOURNAL:
+ return "journal";
+ case KEYSLOT_AREA_TYPE_CHECKSUM:
+ return "checksum";
+ case KEYSLOT_AREA_TYPE_DATASHIFT:
+ return "datashift";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot_area(struct json_object *jobj_area, const keyslot_area_description &keyslot_area_desc) {
+ // mandatory fields
+ if (keyslot_area_desc.has_type())
+ json_object_object_add(jobj_area, "type", json_object_new_string(keyslot_area_type_to_string(keyslot_area_desc.type()).c_str()));
+ if (keyslot_area_desc.has_offset())
+ json_object_object_add(jobj_area, "offset", json_object_new_string(string_uint64_to_string(keyslot_area_desc.offset()).c_str()));
+ if (keyslot_area_desc.has_size())
+ json_object_object_add(jobj_area, "size", json_object_new_string(string_uint64_to_string(keyslot_area_desc.size()).c_str()));
+
+ // raw type fields
+ if (keyslot_area_desc.has_encryption())
+ json_object_object_add(jobj_area, "encryption", json_object_new_string(keyslot_area_desc.encryption().c_str()));
+ if (keyslot_area_desc.has_key_size())
+ json_object_object_add(jobj_area, "key_size", json_object_new_int(keyslot_area_desc.key_size()));
+
+ // checksum type fields
+ if (keyslot_area_desc.has_hash())
+ json_object_object_add(jobj_area, "hash", json_object_new_string(hash_algorithm_to_string(keyslot_area_desc.hash()).c_str()));
+ if (keyslot_area_desc.has_sector_size())
+ json_object_object_add(jobj_area, "sector_size", json_object_new_int(keyslot_area_desc.sector_size()));
+
+ // datashift type fields
+ if (keyslot_area_desc.has_shift_size())
+ json_object_object_add(jobj_area, "shift_size", json_object_new_string(string_uint64_to_string(keyslot_area_desc.shift_size()).c_str()));
+}
+
+std::string LUKS2ProtoConverter::keyslot_kdf_type_to_string(const keyslot_kdf_type type) {
+ switch (type) {
+ case KEYSLOT_KDF_TYPE_PBKDF2:
+ return "pbkdf2";
+ case KEYSLOT_KDF_TYPE_ARGON2I:
+ return "argon2i";
+ case KEYSLOT_KDF_TYPE_ARGON2ID:
+ return "argon2id";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot_kdf(struct json_object *jobj_kdf, const keyslot_kdf_description &keyslot_kdf_desc) {
+ // mandatory fields
+ if (keyslot_kdf_desc.has_type())
+ json_object_object_add(jobj_kdf, "type", json_object_new_string(keyslot_kdf_type_to_string(keyslot_kdf_desc.type()).c_str()));
+
+ if (keyslot_kdf_desc.has_salt())
+ json_object_object_add(jobj_kdf, "salt", json_object_new_string(keyslot_kdf_desc.salt().c_str()));
+ else
+ json_object_object_add(jobj_kdf, "salt", json_object_new_string("6vz4xK7cjan92rDA5JF8O6Jk2HouV0O8DMB6GlztVk="));
+
+ // pbkdf2 type
+ if (keyslot_kdf_desc.has_hash())
+ json_object_object_add(jobj_kdf, "hash", json_object_new_string(hash_algorithm_to_string(keyslot_kdf_desc.hash()).c_str()));
+ if (keyslot_kdf_desc.has_iterations())
+ json_object_object_add(jobj_kdf, "iterations", json_object_new_int(keyslot_kdf_desc.iterations()));
+
+ // argon2i and argon2id types
+ if (keyslot_kdf_desc.has_time())
+ json_object_object_add(jobj_kdf, "time", json_object_new_int(keyslot_kdf_desc.time()));
+ if (keyslot_kdf_desc.has_memory())
+ json_object_object_add(jobj_kdf, "memory", json_object_new_int(keyslot_kdf_desc.memory()));
+ if (keyslot_kdf_desc.has_cpus())
+ json_object_object_add(jobj_kdf, "cpus", json_object_new_int(keyslot_kdf_desc.cpus()));
+}
+
+std::string LUKS2ProtoConverter::keyslot_af_type_to_string(const keyslot_af_type type) {
+ switch (type) {
+ case KEYSLOT_AF_TYPE_LUKS1:
+ return "luks1";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot_af(struct json_object *jobj_af, const keyslot_af_description &keyslot_af_desc) {
+ if (keyslot_af_desc.has_type())
+ json_object_object_add(jobj_af, "type", json_object_new_string(keyslot_af_type_to_string(keyslot_af_desc.type()).c_str()));
+ if (keyslot_af_desc.has_stripes())
+ json_object_object_add(jobj_af, "stripes", json_object_new_int(keyslot_af_desc.stripes()));
+ if (keyslot_af_desc.has_hash())
+ json_object_object_add(jobj_af, "hash", json_object_new_string(hash_algorithm_to_string(keyslot_af_desc.hash()).c_str()));
+}
+
+std::string LUKS2ProtoConverter::keyslot_type_to_string(const keyslot_type type) {
+ switch (type) {
+ case KEYSLOT_TYPE_LUKS2:
+ return "luks2";
+ case KEYSLOT_TYPE_REENCRYPT:
+ return "reencrypt";
+ case KEYSLOT_TYPE_PLACEHOLDER:
+ return "placeholder";
+ }
+}
+
+std::string LUKS2ProtoConverter::reencrypt_keyslot_mode_to_string(const reencrypt_keyslot_mode mode) {
+ switch (mode) {
+ case MODE_REENCRYPT:
+ return "reencrypt";
+ case MODE_ENCRYPT:
+ return "encrypt";
+ case MODE_DECRYPT:
+ return "decrypt";
+ }
+}
+
+std::string LUKS2ProtoConverter::reencrypt_keyslot_direction_to_string(const reencrypt_keyslot_direction direction) {
+ switch (direction) {
+ case DIRECTION_FORWARD:
+ return "forward";
+ case DIRECTION_BACKWARD:
+ return "backward";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot(struct json_object *jobj_keyslots, const keyslot_description &keyslot_desc) {
+ struct json_object *jobj_keyslot, *jobj_area, *jobj_kdf, *jobj_af;
+
+ jobj_keyslot = json_object_new_object();
+ if (keyslot_desc.has_type())
+ json_object_object_add(jobj_keyslot, "type", json_object_new_string(keyslot_type_to_string(keyslot_desc.type()).c_str()));
+ if (keyslot_desc.has_key_size())
+ json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(keyslot_desc.key_size()));
+ if (keyslot_desc.has_priority())
+ json_object_object_add(jobj_keyslot, "priority", json_object_new_int(keyslot_desc.priority()));
+ if (keyslot_desc.has_mode())
+ json_object_object_add(jobj_keyslot, "mode", json_object_new_int(keyslot_desc.mode()));
+ if (keyslot_desc.has_direction())
+ json_object_object_add(jobj_keyslot, "direction", json_object_new_int(keyslot_desc.direction()));
+
+ /* Area object */
+ if (keyslot_desc.has_area()) {
+ jobj_area = json_object_new_object();
+ generate_keyslot_area(jobj_area, keyslot_desc.area());
+ json_object_object_add(jobj_keyslot, "area", jobj_area);
+ }
+
+ /* KDF object */
+ if (keyslot_desc.has_kdf()) {
+ jobj_kdf = json_object_new_object();
+ generate_keyslot_kdf(jobj_kdf, keyslot_desc.kdf());
+ json_object_object_add(jobj_keyslot, "kdf", jobj_kdf);
+ }
+
+ /* AF object */
+ if (keyslot_desc.has_af()) {
+ jobj_af = json_object_new_object();
+ generate_keyslot_af(jobj_af, keyslot_desc.af());
+ json_object_object_add(jobj_keyslot, "af", jobj_af);
+ }
+
+ json_object_object_add(jobj_keyslots, object_id_to_string(keyslot_desc.oid()).c_str(), jobj_keyslot);
+}
+
+void LUKS2ProtoConverter::generate_token(struct json_object *jobj_tokens, const token_description &token_desc) {
+ struct json_object *jobj_token, *jobj_keyslots;
+ jobj_token = json_object_new_object();
+
+ if (token_desc.has_type())
+ json_object_object_add(jobj_token, "type", json_object_new_string(token_desc.type().c_str()));
+
+ if (token_desc.has_key_description())
+ json_object_object_add(jobj_token, "key_description", json_object_new_string(token_desc.key_description().c_str()));
+
+ if (!token_desc.keyslots().empty()) {
+ jobj_keyslots = json_object_new_array();
+
+ for (const object_id& oid : token_desc.keyslots()) {
+ json_object_array_add(jobj_keyslots,
+ json_object_new_string(object_id_to_string(oid).c_str()));
+ }
+
+ /* Replace or add new keyslots array */
+ json_object_object_add(jobj_token, "keyslots", jobj_keyslots);
+ }
+
+ json_object_object_add(jobj_tokens, object_id_to_string(token_desc.oid()).c_str(), jobj_token);
+}
+
+void LUKS2ProtoConverter::generate_digest(struct json_object *jobj_digests, const digest_description &digest_desc) {
+ struct json_object *jobj_digest, *jobj_keyslots, *jobj_segments;
+
+ jobj_digest = json_object_new_object();
+
+ if (digest_desc.has_type())
+ json_object_object_add(jobj_digest, "type", json_object_new_string(keyslot_kdf_type_to_string(digest_desc.type()).c_str()));
+
+ if (!digest_desc.keyslots().empty()) {
+ jobj_keyslots = json_object_new_array();
+
+ for (const object_id& oid : digest_desc.keyslots()) {
+ json_object_array_add(jobj_keyslots,
+ json_object_new_string(object_id_to_string(oid).c_str()));
+ }
+
+ /* Replace or add new keyslots array */
+ json_object_object_add(jobj_digest, "keyslots", jobj_keyslots);
+ }
+
+ if (!digest_desc.segments().empty()) {
+ jobj_segments = json_object_new_array();
+
+ for (const object_id& oid : digest_desc.segments()) {
+ json_object_array_add(jobj_segments,
+ json_object_new_string(object_id_to_string(oid).c_str()));
+ }
+
+ /* Replace or add new segments array */
+ json_object_object_add(jobj_digest, "segments", jobj_segments);
+ }
+
+ if (digest_desc.has_salt())
+ json_object_object_add(jobj_digest, "salt", json_object_new_string(digest_desc.salt().c_str()));
+ if (digest_desc.has_digest())
+ json_object_object_add(jobj_digest, "digest", json_object_new_string(digest_desc.digest().c_str()));
+ if (digest_desc.has_hash())
+ json_object_object_add(jobj_digest, "hash", json_object_new_string(hash_algorithm_to_string(digest_desc.hash()).c_str()));
+ if (digest_desc.has_iterations())
+ json_object_object_add(jobj_digest, "iterations", json_object_new_int(digest_desc.iterations()));
+
+ json_object_object_add(jobj_digests, object_id_to_string(digest_desc.oid()).c_str(), jobj_digest);
+}
+
+std::string LUKS2ProtoConverter::segment_type_to_string(segment_type type) {
+ switch (type) {
+ case SEGMENT_TYPE_LINEAR:
+ return "linear";
+ case SEGMENT_TYPE_CRYPT:
+ return "crypt";
+ }
+}
+
+std::string LUKS2ProtoConverter::segment_flag_to_string(segment_flag flag) {
+ switch (flag) {
+ case IN_REENCRYPTION:
+ return "in-reencryption";
+ case BACKUP_FINAL:
+ return "backup-final";
+ case BACKUP_PREVIOUS:
+ return "backup-previous";
+ case BACKUP_MOVED_SEGMENT:
+ return "backup-moved-segment";
+ }
+}
+
+void LUKS2ProtoConverter::generate_segment_integrity(struct json_object *jobj_integrity, const segment_integrity_description &segment_integrity_desc) {
+ if (segment_integrity_desc.has_type())
+ json_object_object_add(jobj_integrity, "type", json_object_new_string(segment_integrity_desc.type().c_str()));
+ if (segment_integrity_desc.has_journal_encryption())
+ json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string(segment_integrity_desc.journal_encryption().c_str()));
+ if (segment_integrity_desc.has_journal_integrity())
+ json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string(segment_integrity_desc.journal_integrity().c_str()));
+}
+
+void LUKS2ProtoConverter::generate_segment(struct json_object *jobj_segments, const segment_description &segment_desc) {
+ json_object *jobj_flags, *jobj_integrity;
+ json_object *jobj_segment = json_object_new_object();
+
+ if (segment_desc.has_type())
+ json_object_object_add(jobj_segment, "type", json_object_new_string(segment_type_to_string(segment_desc.type()).c_str()));
+
+ if (segment_desc.has_offset())
+ json_object_object_add(jobj_segment, "offset", json_object_new_string(string_uint64_to_string(segment_desc.offset()).c_str()));
+ if (segment_desc.has_size())
+ json_object_object_add(jobj_segment, "size", json_object_new_string(string_uint64_to_string(segment_desc.size()).c_str()));
+
+ if (!segment_desc.flags().empty()) {
+ jobj_flags = json_object_new_array();
+
+ for (const int flag : segment_desc.flags()) {
+ json_object_array_add(jobj_flags,
+ json_object_new_string(segment_flag_to_string(segment_flag(flag)).c_str()));
+ }
+
+ /* Replace or add new flags array */
+ json_object_object_add(jobj_segment, "flags", jobj_flags);
+ }
+
+ if (segment_desc.has_iv_tweak())
+ json_object_object_add(jobj_segment, "iv_tweak", json_object_new_string(string_uint64_to_string(segment_desc.iv_tweak()).c_str()));
+ if (segment_desc.has_encryption())
+ json_object_object_add(jobj_segment, "encryption", json_object_new_string(segment_desc.encryption().c_str()));
+ if (segment_desc.has_sector_size())
+ json_object_object_add(jobj_segment, "sector_size", json_object_new_int(segment_desc.sector_size()));
+
+ if (segment_desc.has_integrity()) {
+ jobj_integrity = json_object_new_object();
+ generate_segment_integrity(jobj_integrity, segment_desc.integrity());
+ json_object_object_add(jobj_segment, "integrity", jobj_integrity);
+ }
+
+ json_object_object_add(jobj_segments, object_id_to_string(segment_desc.oid()).c_str(), jobj_segment);
+}
+
+void LUKS2ProtoConverter::create_jobj(const LUKS2_both_headers &headers) {
+ json_object *jobj_keyslots = NULL;
+ json_object *jobj_digests = NULL;
+ json_object *jobj_segments = NULL;
+ json_object *jobj_tokens = NULL;
+
+ const json_area_description &json_desc = headers.json_area();
+
+ jobj = json_object_new_object();
+ if (!jobj)
+ return;
+
+ jobj_keyslots = json_object_new_object();
+ for (const keyslot_description &keyslot_desc : json_desc.keyslots()) {
+ generate_keyslot(jobj_keyslots, keyslot_desc);
+ }
+ json_object_object_add(jobj, "keyslots", jobj_keyslots);
+
+ jobj_digests = json_object_new_object();
+ for (const digest_description &digest_desc : json_desc.digests()) {
+ generate_digest(jobj_digests, digest_desc);
+ }
+ json_object_object_add(jobj, "digests", jobj_digests);
+
+ jobj_segments = json_object_new_object();
+ for (const segment_description &segment_desc : json_desc.segments()) {
+ generate_segment(jobj_segments, segment_desc);
+ }
+ json_object_object_add(jobj, "segments", jobj_segments);
+
+ jobj_tokens = json_object_new_object();
+ for (const token_description &token_desc : json_desc.tokens()) {
+ generate_token(jobj_tokens, token_desc);
+ }
+ json_object_object_add(jobj, "tokens", jobj_tokens);
+
+ if (json_desc.has_config()) {
+ uint64_t hdr_size = json_desc.config().use_primary_hdr_size() ? headers.primary_header().hdr_size() : headers.secondary_header().hdr_size();
+ generate_config(json_desc.config(), hdr_size - LUKS2_HDR_BIN_LEN, KEYSLOTS_SIZE);
+ }
+}
+
+void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid) {
+ struct luks2_hdr_disk hdr = {};
+ int r;
+
+ if (hd)
+ crypt_hash_destroy(hd);
+ if (crypt_hash_init(&hd, "sha256"))
+ err(EXIT_FAILURE, "crypt_hash_init failed");
+
+
+ r = lseek(fd, offset, SEEK_SET);
+ if (r == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ switch (header_proto.magic()) {
+ case INVALID:
+ memset(&hdr.magic, 0, LUKS2_MAGIC_L);
+ break;
+ case FIRST:
+ memcpy(&hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L);
+ break;
+ case SECOND:
+ memcpy(&hdr.magic, LUKS2_MAGIC_2ND, LUKS2_MAGIC_L);
+ break;
+ }
+ hdr.version = cpu_to_be16(header_proto.version());
+ hdr.hdr_size = cpu_to_be64(header_proto.hdr_size());
+ hdr.seqid = cpu_to_be64(seqid);
+ strncpy(hdr.checksum_alg, "sha256", LUKS2_CHECKSUM_ALG_L);
+ hdr.checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
+ strncpy(hdr.uuid, "af7f64ea-3233-4581-946b-6187d812841e", LUKS2_UUID_L);
+ memset(hdr.salt, 1, LUKS2_SALT_L);
+
+
+ if (header_proto.has_selected_offset())
+ hdr.hdr_offset = cpu_to_be64(header_proto.selected_offset());
+ else
+ hdr.hdr_offset = cpu_to_be64(offset);
+
+ if (write_buffer(fd, &hdr, LUKS2_HDR_BIN_LEN) != LUKS2_HDR_BIN_LEN)
+ err(EXIT_FAILURE, "write_buffer failed");
+ if (crypt_hash_write(hd, (char*)&hdr, LUKS2_HDR_BIN_LEN))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+
+ size_t hdr_json_area_len = header_proto.hdr_size() - LUKS2_HDR_BIN_LEN;
+ size_t json_text_len;
+ const char *json_text;
+ uint8_t csum[LUKS2_CHECKSUM_L];
+
+ if (jobj) {
+ json_text = json_object_to_json_string_ext((struct json_object *)jobj, JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
+ if (!json_text || !*json_text)
+ err(EXIT_FAILURE, "json_object_to_json_string_ext failed");
+
+ json_text_len = strlen(json_text);
+
+ size_t write_size = json_text_len > hdr_json_area_len - 1 ? hdr_json_area_len - 1 : json_text_len;
+ if (write_buffer(fd, json_text, write_size) != (ssize_t)write_size)
+ err(EXIT_FAILURE, "write_buffer failed");
+ if (crypt_hash_write(hd, json_text, write_size))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+
+ for (size_t i = 0; i < (hdr_json_area_len - write_size); i++) {
+ if (crypt_hash_write(hd, "\0", 1))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+ }
+ }
+
+ if (header_proto.use_correct_checksum()) {
+ if (lseek(fd, offset + offsetof(luks2_hdr_disk, csum), SEEK_SET) == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ int hash_size = crypt_hash_size("sha256");
+ if (hash_size <= 0)
+ err(EXIT_FAILURE, "crypt_hash_size failed");
+
+ if (crypt_hash_final(hd, (char*)csum, (size_t)hash_size))
+ err(EXIT_FAILURE, "crypt_hash_final failed");
+ if (write_buffer(fd, csum, hash_size) != hash_size)
+ err(EXIT_FAILURE, "write_buffer failed");
+ }
+}
+
+void LUKS2ProtoConverter::set_write_headers_only(bool headers_only) {
+ write_headers_only = headers_only;
+}
+
+void LUKS2ProtoConverter::convert(const LUKS2_both_headers &headers, int fd) {
+ uint64_t primary_seqid, secondary_seqid;
+ int result;
+
+ size_t out_size = headers.primary_header().hdr_size() + headers.secondary_header().hdr_size();
+
+ if (!write_headers_only)
+ out_size += KEYSLOTS_SIZE + DATA_SIZE;
+
+ result = ftruncate(fd, out_size);
+ if (result == -1)
+ err(EXIT_FAILURE, "truncate failed");
+
+ result = lseek(fd, 0, SEEK_SET);
+ if (result == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ switch (headers.seqid()) {
+ case EQUAL:
+ primary_seqid = 1;
+ secondary_seqid = 1;
+ break;
+ case PRIMARY_GREATER:
+ primary_seqid = 2;
+ secondary_seqid = 1;
+ break;
+ case SECONDARY_GREATER:
+ primary_seqid = 1;
+ secondary_seqid = 2;
+ break;
+ }
+
+ create_jobj(headers);
+ emit_luks2_binary_header(headers.primary_header(), fd, 0, primary_seqid);
+ emit_luks2_binary_header(headers.secondary_header(), fd, headers.primary_header().hdr_size(), secondary_seqid);
+}
+
+std::string LUKS2ProtoConverter::config_flag_to_string(config_flag flag) {
+ switch (flag) {
+ case CONFIG_FLAG_ALLOW_DISCARDS:
+ return "allow-discards";
+ case CONFIG_FLAG_SAME_CPU_CRYPT:
+ return "same-cpu-crypt";
+ case CONFIG_FLAG_SUBMIT_FROM_CRYPT_CPUS:
+ return "submit-from-crypt-cpus";
+ case CONFIG_FLAG_NO_JOURNAL:
+ return "no-journal";
+ case CONFIG_FLAG_NO_READ_WORKQUEUE:
+ return "no-read-workqueue";
+ case CONFIG_FLAG_NO_WRITE_WORKQUEUE:
+ return "no-write-workqueue";
+ }
+}
+
+std::string LUKS2ProtoConverter::config_requirement_to_string(config_requirement requirement) {
+ switch (requirement) {
+ case CONFIG_REQUIREMENT_OFFLINE_REENCRYPT:
+ return "offline-reencrypt";
+ case CONFIG_REQUIREMENT_ONLINE_REENCRYPT_V2:
+ return "online-reencrypt-v2";
+ }
+}
+
+void LUKS2ProtoConverter::generate_config(const config_description &config_desc, uint64_t json_size, uint64_t keyslots_size) {
+ json_object *jobj_config, *jobj_flags, *jobj_requirements, *jobj_mandatory;
+ jobj_config = json_object_new_object();
+
+ json_object_object_add(jobj_config, "json_size", json_object_new_string(std::to_string(json_size).c_str()));
+ json_object_object_add(jobj_config, "keyslots_size", json_object_new_string(std::to_string(keyslots_size).c_str()));
+
+ if (!config_desc.config_flags().empty()) {
+ jobj_flags = json_object_new_array();
+
+ for (const int flag : config_desc.config_flags()) {
+ json_object_array_add(jobj_flags,
+ json_object_new_string(config_flag_to_string(config_flag(flag)).c_str()));
+ }
+
+ /* Replace or add new flags array */
+ json_object_object_add(jobj_config, "flags", jobj_flags);
+ }
+
+ if (!config_desc.requirements().empty()) {
+ jobj_requirements = json_object_new_object();
+ jobj_mandatory = json_object_new_array();
+
+ for (const int requirement : config_desc.requirements()) {
+ json_object_array_add(jobj_mandatory,
+ json_object_new_string(config_requirement_to_string(config_requirement(requirement)).c_str()));
+ }
+
+ /* Replace or add new requirements array */
+ json_object_object_add(jobj_requirements, "mandatory", jobj_mandatory);
+ json_object_object_add(jobj_config, "requirements", jobj_requirements);
+ }
+
+ json_object_object_add(jobj, "config", jobj_config);
+}
+
+LUKS2ProtoConverter::~LUKS2ProtoConverter() {
+ json_object_put(jobj);
+ if (hd)
+ crypt_hash_destroy(hd);
+}
+} // namespace LUKS2_proto