Example #1
0
static int test_write_blockwise(void)
{
	void *buffer = NULL;
	int fd = -1;
	ssize_t ret = -EINVAL;

	//printf("Entering test_write_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_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length);
	if (ret < 0)
		goto out;

	ret = (size_t) ret == test_length ? 0 : -EIO;
out:
	if (fd >= 0)
		close(fd);
	free(buffer);
	return ret;
}
Example #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("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(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_blockwise(devfd, device_block_size(device), device_alignment(device),
			    &convHdr, hdr_size) < hdr_size ? -EIO : 0;
	if (r)
		log_err(ctx, _("Error during update of LUKS header on device %s."), device_path(device));
	close(devfd);

	/* 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;
}
Example #3
0
/*
 * Combines llseek with blockwise write. write_blockwise can already deal with short writes
 * but we also need a function to deal with short writes at the start. But this information
 * is implicitly included in the read/write offset, which can not be set to non-aligned
 * boundaries. Hence, we combine llseek with write.
 */
ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset) {
	char *frontPadBuf;
	void *frontPadBuf_base = NULL;
	int r, bsize, frontHang;
	size_t innerCount = 0;
	ssize_t ret = -1;

	if ((bsize = sector_size(fd)) < 0)
		return bsize;

	frontHang = offset % bsize;

	if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
		goto out;

	if (frontHang) {
		frontPadBuf = aligned_malloc(&frontPadBuf_base,
					     bsize, get_alignment(fd));
		if (!frontPadBuf)
			goto out;

		r = read(fd, frontPadBuf, bsize);
		if (r < 0 || r != bsize)
			goto out;

		innerCount = bsize - frontHang;
		if (innerCount > count)
			innerCount = count;

		memcpy(frontPadBuf + frontHang, buf, innerCount);

		if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
			goto out;

		r = write(fd, frontPadBuf, bsize);
		if (r < 0 || r != bsize)
			goto out;

		buf += innerCount;
		count -= innerCount;
	}

	ret = count ? write_blockwise(fd, buf, count) : 0;
	if (ret >= 0)
		ret += innerCount;
out:
	free(frontPadBuf_base);

	return ret;
}
Example #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 r = 0, devfd = -1, diff_uuid = 0;
	ssize_t 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.keyBytes) << SECTOR_SHIFT;

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

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

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

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

	r = LUKS_read_phdr(hdr, 0, 0, ctx);
	if (r == 0) {
		log_dbg("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.\n"));
			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("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(device, O_RDWR);
	if (devfd == -1) {
		if (errno == EACCES)
			log_err(ctx, _("Cannot write to device %s, permission denied.\n"),
				device_path(device));
		else
			log_err(ctx, _("Cannot open device %s.\n"), device_path(device));
		r = -EINVAL;
		goto out;
	}

	if (write_blockwise(devfd, device_block_size(device), buffer, buffer_size) < buffer_size) {
		r = -EIO;
		goto out;
	}
	close(devfd);

	/* Be sure to reload new data */
	r = LUKS_read_phdr(hdr, 1, 0, ctx);
out:
	if (devfd != -1)
		close(devfd);
	crypt_safe_free(buffer);
	return r;
}