diff options
Diffstat (limited to 'tests/fuzz/proto_to_luks2_converter.cc')
-rw-r--r-- | tests/fuzz/proto_to_luks2_converter.cc | 604 |
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 |