+ if (r == -EBUSY)
+ log_err(cd, _("Cannot format device %s which is still in use.\n"),
+ mdata_device_path(cd));
+ else if (r == -EACCES) {
+ log_err(cd, _("Cannot format device %s, permission denied.\n"),
+ mdata_device_path(cd));
+ r = -EINVAL;
+ } else
+ log_err(cd, _("Cannot wipe header on device %s.\n"),
+ mdata_device_path(cd));
+
+ return r;
+ }
+
+ r = LUKS_write_phdr(&cd->hdr, cd);
+
+ return r;
+}
+
+static int _crypt_format_loopaes(struct crypt_device *cd,
+ const char *cipher,
+ const char *uuid,
+ size_t volume_key_size,
+ struct crypt_params_loopaes *params)
+{
+ if (!crypt_metadata_device(cd)) {
+ log_err(cd, _("Can't format LOOPAES without device.\n"));
+ return -EINVAL;
+ }
+
+ if (volume_key_size > 1024) {
+ log_err(cd, _("Invalid key size.\n"));
+ return -EINVAL;
+ }
+
+ if (!(cd->type = strdup(CRYPT_LOOPAES)))
+ return -ENOMEM;
+
+ cd->loopaes_key_size = volume_key_size;
+
+ cd->loopaes_cipher = strdup(cipher ?: DEFAULT_LOOPAES_CIPHER);
+
+ if (uuid)
+ cd->loopaes_uuid = strdup(uuid);
+
+ if (params && params->hash)
+ cd->loopaes_hdr.hash = strdup(params->hash);
+
+ cd->loopaes_hdr.offset = params ? params->offset : 0;
+ cd->loopaes_hdr.skip = params ? params->skip : 0;
+
+ return 0;
+}
+
+static int _crypt_format_verity(struct crypt_device *cd,
+ const char *uuid,
+ struct crypt_params_verity *params)
+{
+ int r = 0, hash_size;
+ uint64_t data_device_size;
+
+ if (!crypt_metadata_device(cd)) {
+ log_err(cd, _("Can't format VERITY without device.\n"));
+ return -EINVAL;
+ }
+
+ if (!params || !params->data_device)
+ return -EINVAL;
+
+ if (params->hash_type > VERITY_MAX_HASH_TYPE) {
+ log_err(cd, _("Unsupported VERITY hash type %d.\n"), params->hash_type);
+ return -EINVAL;
+ }
+
+ if (VERITY_BLOCK_SIZE_OK(params->data_block_size) ||
+ VERITY_BLOCK_SIZE_OK(params->hash_block_size)) {
+ log_err(cd, _("Unsupported VERITY block size.\n"));
+ return -EINVAL;
+ }
+
+ if (params->hash_area_offset % 512) {
+ log_err(cd, _("Unsupported VERITY hash offset.\n"));
+ return -EINVAL;
+ }
+
+ if (!(cd->type = strdup(CRYPT_VERITY)))
+ return -ENOMEM;
+
+ r = crypt_set_data_device(cd, params->data_device);
+ if (r)
+ return r;
+ if (!params->data_size) {
+ r = device_size(cd->device, &data_device_size);
+ if (r < 0)
+ return r;
+
+ cd->verity_hdr.data_size = data_device_size / params->data_block_size;
+ } else
+ cd->verity_hdr.data_size = params->data_size;
+
+ hash_size = crypt_hash_size(params->hash_name);
+ if (hash_size <= 0) {
+ log_err(cd, _("Hash algorithm %s not supported.\n"),
+ params->hash_name);
+ return -EINVAL;
+ }
+ cd->verity_root_hash_size = hash_size;
+
+ cd->verity_root_hash = malloc(cd->verity_root_hash_size);
+ if (!cd->verity_root_hash)
+ return -ENOMEM;
+
+ cd->verity_hdr.flags = params->flags;
+ if (!(cd->verity_hdr.hash_name = strdup(params->hash_name)))
+ return -ENOMEM;
+ cd->verity_hdr.data_device = NULL;
+ cd->verity_hdr.data_block_size = params->data_block_size;
+ cd->verity_hdr.hash_block_size = params->hash_block_size;
+ cd->verity_hdr.hash_area_offset = params->hash_area_offset;
+ cd->verity_hdr.hash_type = params->hash_type;
+ cd->verity_hdr.flags = params->flags;
+ cd->verity_hdr.salt_size = params->salt_size;
+ if (!(cd->verity_hdr.salt = malloc(params->salt_size)))
+ return -ENOMEM;
+
+ if (params->salt)
+ memcpy(CONST_CAST(char*)cd->verity_hdr.salt, params->salt,
+ params->salt_size);
+ else
+ r = crypt_random_get(cd, CONST_CAST(char*)cd->verity_hdr.salt,
+ params->salt_size, CRYPT_RND_SALT);
+ if (r)