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

	//printf("Entering test_read_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_RDONLY | O_DIRECT);
	if (fd < 0) {
		fprintf(stderr, "Failed to open %s.\n", test_file);
		goto out;
	}

	ret = read_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;
}
Exemple #2
0
int LUKS_read_phdr(struct luks_phdr *hdr,
		   int require_luks_device,
		   int repair,
		   struct crypt_device *ctx)
{
	int devfd, r = 0;
	struct device *device = crypt_metadata_device(ctx);
	ssize_t hdr_size = sizeof(struct luks_phdr);

	/* LUKS header starts at offset 0, first keyslot on LUKS_ALIGN_KEYSLOTS */
	assert(sizeof(struct luks_phdr) <= LUKS_ALIGN_KEYSLOTS);

	/* Stripes count cannot be changed without additional code fixes yet */
	assert(LUKS_STRIPES == 4000);

	if (repair && !require_luks_device)
		return -EINVAL;

	log_dbg(ctx, "Reading LUKS header of size %zu from device %s",
		hdr_size, device_path(device));

	devfd = device_open(ctx, device, O_RDONLY);
	if (devfd < 0) {
		log_err(ctx, _("Cannot open device %s."), device_path(device));
		return -EINVAL;
	}

	if (read_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
			   hdr, hdr_size, 0) < hdr_size)
		r = -EIO;
	else
		r = _check_and_convert_hdr(device_path(device), hdr, require_luks_device,
					   repair, ctx);

	if (!r)
		r = LUKS_check_device_size(ctx, hdr, 0);

	/*
	 * Cryptsetup 1.0.0 did not align keyslots to 4k (very rare version).
	 * Disable direct-io to avoid possible IO errors if underlying device
	 * has bigger sector size.
	 */
	if (!r && hdr->keyblock[0].keyMaterialOffset * SECTOR_SIZE < LUKS_ALIGN_KEYSLOTS) {
		log_dbg(ctx, "Old unaligned LUKS keyslot detected, disabling direct-io.");
		device_disable_direct_io(device);
	}

	return r;
}
int LUKS2_hdr_version_unlocked(struct crypt_device *cd, const char *backup_file)
{
	struct {
		char magic[LUKS2_MAGIC_L];
		uint16_t version;
	}  __attribute__ ((packed)) hdr;
	struct device *device = NULL;
	int r = 0, devfd = -1, flags;

	if (!backup_file)
		device = crypt_metadata_device(cd);
	else if (device_alloc(&device, backup_file) < 0)
		return 0;

	if (!device)
		return 0;

	flags = O_RDONLY;
	if (device_direct_io(device))
		flags |= O_DIRECT;

	devfd = open(device_path(device), flags);
	if (devfd < 0)
		goto err;

	if ((read_lseek_blockwise(devfd, device_block_size(device),
	     device_alignment(device), &hdr, sizeof(hdr), 0) == sizeof(hdr)) &&
	    !memcmp(hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
		r = (int)be16_to_cpu(hdr.version);
err:
	if (devfd != -1)
		close(devfd);

	if (backup_file)
		device_free(device);

	return r;
}
Exemple #4
0
int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
{
	struct device *device = crypt_metadata_device(ctx);
	struct luks_phdr hdr;
	int fd, devfd, r = 0;
	size_t hdr_size;
	size_t buffer_size;
	ssize_t ret;
	char *buffer = NULL;

	r = LUKS_read_phdr(&hdr, 1, 0, ctx);
	if (r)
		return r;

	hdr_size = LUKS_device_sectors(&hdr) << SECTOR_SHIFT;
	buffer_size = size_round_up(hdr_size, crypt_getpagesize());

	buffer = crypt_safe_alloc(buffer_size);
	if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) {
		r = -ENOMEM;
		goto out;
	}

	log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes).",
		sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS);

	log_dbg(ctx, "Output backup file size: %zu bytes.", buffer_size);

	devfd = device_open(ctx, device, O_RDONLY);
	if (devfd < 0) {
		log_err(ctx, _("Device %s is not a valid LUKS device."), device_path(device));
		r = -EINVAL;
		goto out;
	}

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

	/* Wipe unused area, so backup cannot contain old signatures */
	if (hdr.keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
		memset(buffer + sizeof(hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(hdr));

	fd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
	if (fd == -1) {
		if (errno == EEXIST)
			log_err(ctx, _("Requested header backup file %s already exists."), backup_file);
		else
			log_err(ctx, _("Cannot create header backup file %s."), backup_file);
		r = -EINVAL;
		goto out;
	}
	ret = write_buffer(fd, buffer, buffer_size);
	close(fd);
	if (ret < (ssize_t)buffer_size) {
		log_err(ctx, _("Cannot write header backup file %s."), backup_file);
		r = -EIO;
		goto out;
	}

	r = 0;
out:
	crypt_memzero(&hdr, sizeof(hdr));
	crypt_safe_free(buffer);
	return r;
}
/*
 * Read LUKS2 header from disk at specific offset.
 */
static int hdr_read_disk(struct device *device, struct luks2_hdr_disk *hdr_disk,
			 char **json_area, uint64_t offset, int secondary)
{
	size_t hdr_json_size = 0;
	int devfd = -1, r;

	log_dbg("Trying to read %s LUKS2 header at offset %" PRIu64 ".",
		secondary ? "secondary" : "primary", offset);

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

	/*
	 * Read binary header and run sanity check before reading
	 * JSON area and validating checksum.
	 */
	if (read_lseek_blockwise(devfd, device_block_size(device),
				 device_alignment(device), hdr_disk,
				 LUKS2_HDR_BIN_LEN, offset) != LUKS2_HDR_BIN_LEN) {
		close(devfd);
		return -EIO;
	}

	r = hdr_disk_sanity_check_pre(hdr_disk, &hdr_json_size, secondary, offset);
	if (r < 0) {
		close(devfd);
		return r;
	}

	/*
	 * Allocate and read JSON area. Always the whole area must be read.
	 */
	*json_area = malloc(hdr_json_size);
	if (!*json_area) {
		close(devfd);
		return -ENOMEM;
	}

	if (read_lseek_blockwise(devfd, device_block_size(device),
				 device_alignment(device), *json_area, hdr_json_size,
				 offset + LUKS2_HDR_BIN_LEN) != (ssize_t)hdr_json_size) {
		close(devfd);
		free(*json_area);
		*json_area = NULL;
		return -EIO;
	}

	close(devfd);

	/*
	 * Calculate and validate checksum and zero it afterwards.
	 */
	if (hdr_checksum_check(hdr_disk->checksum_alg, hdr_disk,
				*json_area, hdr_json_size)) {
		log_dbg("LUKS2 header checksum error (offset %" PRIu64 ").", offset);
		r = -EINVAL;
	}
	memset(hdr_disk->csum, 0, LUKS2_CHECKSUM_L);

	return r;
}