Пример #1
0
static int test_write_lseek_blockwise(void)
{
	void *buffer = NULL;
	int fd = -1;
	ssize_t ret = -EINVAL;

	//printf("Entering test_write_lseek_blockwise\n");

	if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
		fprintf(stderr, "Failed to allocate aligned buffer.\n");
		goto out;
	}

	fd = open(test_file, O_RDWR | O_DIRECT);
	if (fd < 0) {
		fprintf(stderr, "Failed to open %s.\n", test_file);
		goto out;
	}

	ret = write_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset);
	if (ret < 0)
		goto out;

	ret = (size_t) ret == test_length ? 0 : -EIO;
out:
	if (fd >= 0)
		close(fd);
	free(buffer);
	return ret;
}
Пример #2
0
int LUKS_write_phdr(struct luks_phdr *hdr,
		    struct crypt_device *ctx)
{
	struct device *device = crypt_metadata_device(ctx);
	ssize_t hdr_size = sizeof(struct luks_phdr);
	int devfd = 0;
	unsigned int i;
	struct luks_phdr convHdr;
	int r;

	log_dbg(ctx, "Updating LUKS header of size %zu on device %s",
		sizeof(struct luks_phdr), device_path(device));

	r = LUKS_check_device_size(ctx, hdr, 1);
	if (r)
		return r;

	devfd = device_open(ctx, device, O_RDWR);
	if (devfd < 0) {
		if (errno == EACCES)
			log_err(ctx, _("Cannot write to device %s, permission denied."),
				device_path(device));
		else
			log_err(ctx, _("Cannot open device %s."), device_path(device));
		return -EINVAL;
	}

	memcpy(&convHdr, hdr, hdr_size);
	memset(&convHdr._padding, 0, sizeof(convHdr._padding));

	/* Convert every uint16/32_t item to network byte order */
	convHdr.version            = htons(hdr->version);
	convHdr.payloadOffset      = htonl(hdr->payloadOffset);
	convHdr.keyBytes           = htonl(hdr->keyBytes);
	convHdr.mkDigestIterations = htonl(hdr->mkDigestIterations);
	for(i = 0; i < LUKS_NUMKEYS; ++i) {
		convHdr.keyblock[i].active             = htonl(hdr->keyblock[i].active);
		convHdr.keyblock[i].passwordIterations = htonl(hdr->keyblock[i].passwordIterations);
		convHdr.keyblock[i].keyMaterialOffset  = htonl(hdr->keyblock[i].keyMaterialOffset);
		convHdr.keyblock[i].stripes            = htonl(hdr->keyblock[i].stripes);
	}

	r = write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
			    &convHdr, hdr_size, 0) < hdr_size ? -EIO : 0;
	if (r)
		log_err(ctx, _("Error during update of LUKS header on device %s."), device_path(device));

	device_sync(ctx, device);

	/* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
	if (!r) {
		r = LUKS_read_phdr(hdr, 1, 0, ctx);
		if (r)
			log_err(ctx, _("Error re-reading LUKS header after update on device %s."),
				device_path(device));
	}

	return r;
}
Пример #3
0
/* Write verity superblock to disk */
int VERITY_write_sb(struct crypt_device *cd,
		   uint64_t sb_offset,
		   const char *uuid_string,
		   struct crypt_params_verity *params)
{
	struct device *device = crypt_metadata_device(cd);
	int bsize = device_block_size(device);
	struct verity_sb sb = {};
	ssize_t hdr_size = sizeof(struct verity_sb);
	uuid_t uuid;
	int r, devfd = 0;

	log_dbg("Updating VERITY header of size %zu on device %s, offset %" PRIu64 ".",
		sizeof(struct verity_sb), device_path(device), sb_offset);

	if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) {
		log_err(cd, _("Wrong VERITY UUID format provided on device %s. \n"),
			device_path(device));
		return -EINVAL;
	}

	if (params->flags & CRYPT_VERITY_NO_HEADER) {
		log_err(cd, _("Verity device %s doesn't use on-disk header.\n"),
			device_path(device));
		return -EINVAL;
	}

	devfd = device_open(device, O_RDWR);
	if(devfd == -1) {
		log_err(cd, _("Cannot open device %s.\n"), device_path(device));
		return -EINVAL;
	}

	memcpy(&sb.signature, VERITY_SIGNATURE, sizeof(sb.signature));
	sb.version         = cpu_to_le32(1);
	sb.hash_type       = cpu_to_le32(params->hash_type);
	sb.data_block_size = cpu_to_le32(params->data_block_size);
	sb.hash_block_size = cpu_to_le32(params->hash_block_size);
	sb.salt_size       = cpu_to_le16(params->salt_size);
	sb.data_blocks     = cpu_to_le64(params->data_size);
	strncpy((char *)sb.algorithm, params->hash_name, sizeof(sb.algorithm));
	memcpy(sb.salt, params->salt, params->salt_size);
	memcpy(sb.uuid, uuid, sizeof(sb.uuid));

	r = write_lseek_blockwise(devfd, bsize, (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0;
	if (r)
		log_err(cd, _("Error during update of verity header on device %s.\n"),
			device_path(device));
	close(devfd);

	return r;
}
Пример #4
0
int LUKS_hdr_restore(
	const char *backup_file,
	struct luks_phdr *hdr,
	struct crypt_device *ctx)
{
	struct device *device = crypt_metadata_device(ctx);
	int fd, r = 0, devfd = -1, diff_uuid = 0;
	ssize_t ret, buffer_size = 0;
	char *buffer = NULL, msg[200];
	struct luks_phdr hdr_file;

	r = LUKS_read_phdr_backup(backup_file, &hdr_file, 0, ctx);
	if (r == -ENOENT)
		return r;

	if (!r)
		buffer_size = LUKS_device_sectors(&hdr_file) << SECTOR_SHIFT;

	if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
		log_err(ctx, _("Backup file doesn't contain valid LUKS header."));
		r = -EINVAL;
		goto out;
	}

	buffer = crypt_safe_alloc(buffer_size);
	if (!buffer) {
		r = -ENOMEM;
		goto out;
	}

	fd = open(backup_file, O_RDONLY);
	if (fd == -1) {
		log_err(ctx, _("Cannot open header backup file %s."), backup_file);
		r = -EINVAL;
		goto out;
	}

	ret = read_buffer(fd, buffer, buffer_size);
	close(fd);
	if (ret < buffer_size) {
		log_err(ctx, _("Cannot read header backup file %s."), backup_file);
		r = -EIO;
		goto out;
	}

	r = LUKS_read_phdr(hdr, 0, 0, ctx);
	if (r == 0) {
		log_dbg(ctx, "Device %s already contains LUKS header, checking UUID and offset.", device_path(device));
		if(hdr->payloadOffset != hdr_file.payloadOffset ||
		   hdr->keyBytes != hdr_file.keyBytes) {
			log_err(ctx, _("Data offset or key size differs on device and backup, restore failed."));
			r = -EINVAL;
			goto out;
		}
		if (memcmp(hdr->uuid, hdr_file.uuid, UUID_STRING_L))
			diff_uuid = 1;
	}

	if (snprintf(msg, sizeof(msg), _("Device %s %s%s"), device_path(device),
		 r ? _("does not contain LUKS header. Replacing header can destroy data on that device.") :
		     _("already contains LUKS header. Replacing header will destroy existing keyslots."),
		     diff_uuid ? _("\nWARNING: real device header has different UUID than backup!") : "") < 0) {
		r = -ENOMEM;
		goto out;
	}

	if (!crypt_confirm(ctx, msg)) {
		r = -EINVAL;
		goto out;
	}

	log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.",
		sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device));

	devfd = device_open(ctx, device, O_RDWR);
	if (devfd < 0) {
		if (errno == EACCES)
			log_err(ctx, _("Cannot write to device %s, permission denied."),
				device_path(device));
		else
			log_err(ctx, _("Cannot open device %s."), device_path(device));
		r = -EINVAL;
		goto out;
	}

	if (write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
			    buffer, buffer_size, 0) < buffer_size) {
		r = -EIO;
		goto out;
	}

	/* Be sure to reload new data */
	r = LUKS_read_phdr(hdr, 1, 0, ctx);
out:
	device_sync(ctx, device);
	crypt_safe_free(buffer);
	return r;
}
/*
 * Write LUKS2 header to disk at specific offset.
 */
static int hdr_write_disk(struct device *device, struct luks2_hdr *hdr,
		   const char *json_area, int secondary)
{
	struct luks2_hdr_disk hdr_disk;
	uint64_t offset = secondary ? hdr->hdr_size : 0;
	size_t hdr_json_len;
	int devfd = -1, r;

	log_dbg("Trying to write LUKS2 header (%zu bytes) at offset %" PRIu64 ".",
		hdr->hdr_size, offset);

	/* FIXME: read-only device silent fail? */

	devfd = device_open_locked(device, O_RDWR);
	if (devfd < 0)
		return devfd == -1 ? -EINVAL : devfd;

	hdr_json_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN;

	hdr_to_disk(hdr, &hdr_disk, secondary, offset);

	/*
	 * Write header without checksum but with proper seqid.
	 */
	if (write_lseek_blockwise(devfd, device_block_size(device),
				  device_alignment(device), (char *)&hdr_disk,
				  LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN) {
		close(devfd);
		return -EIO;
	}

	/*
	 * Write json area.
	 */
	if (write_lseek_blockwise(devfd, device_block_size(device),
				  device_alignment(device),
				  CONST_CAST(char*)json_area, hdr_json_len,
				  LUKS2_HDR_BIN_LEN + offset) < (ssize_t)hdr_json_len) {
		close(devfd);
		return -EIO;
	}

	/*
	 * Calculate checksum and write header with checksum.
	 */
	r = hdr_checksum_calculate(hdr_disk.checksum_alg, &hdr_disk,
				   json_area, hdr_json_len);
	if (r < 0) {
		close(devfd);
		return r;
	}
	log_dbg_checksum(hdr_disk.csum, hdr_disk.checksum_alg, "in-memory");

	if (write_lseek_blockwise(devfd, device_block_size(device),
				  device_alignment(device), (char *)&hdr_disk,
				  LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN)
		r = -EIO;

	close(devfd);
	return r;
}