Exemplo n.º 1
0
// FIXME: move this to tools and handle EINTR
static int _read_mk(const char *file, char **key, int keysize)
{
	int fd;

	if (keysize <= 0 || keysize > MAX_KEY_SIZE) {
		log_err(_("Invalid key size."));
		return -EINVAL;
	}

	*key = crypt_safe_alloc(keysize);
	if (!*key)
		return -ENOMEM;

	fd = open(file, O_RDONLY);
	if (fd == -1) {
		log_err(_("Cannot read keyfile %s."), file);
		goto fail;
	}
	if ((read(fd, *key, keysize) != keysize)) {
		log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file);
		close(fd);
		goto fail;
	}
	close(fd);
	return 0;
fail:
	crypt_safe_free(*key);
	*key = NULL;
	return -EINVAL;
}
Exemplo n.º 2
0
/* Try to open a particular key slot */
static int LUKS_open_key(unsigned int keyIndex,
		  const char *password,
		  size_t passwordLen,
		  struct luks_phdr *hdr,
		  struct volume_key *vk,
		  struct crypt_device *ctx)
{
	crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
	struct volume_key *derived_key;
	char *AfKey;
	size_t AFEKSize;
	int r;

	log_dbg("Trying to open key slot %d [%s].", keyIndex,
		dbg_slot_state(ki));

	if (ki < CRYPT_SLOT_ACTIVE)
		return -ENOENT;

	derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
	if (!derived_key)
		return -ENOMEM;

	assert(vk->keylength == hdr->keyBytes);
	AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
	AfKey = crypt_safe_alloc(AFEKSize);
	if (!AfKey) {
		r = -ENOMEM;
		goto out;
	}

	r = crypt_pbkdf("pbkdf2", hdr->hashSpec, password, passwordLen,
			hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
			derived_key->key, hdr->keyBytes,
			hdr->keyblock[keyIndex].passwordIterations);
	if (r < 0)
		goto out;

	log_dbg("Reading key slot %d area.", keyIndex);
	r = LUKS_decrypt_from_storage(AfKey,
				      AFEKSize,
				      hdr->cipherName, hdr->cipherMode,
				      derived_key,
				      hdr->keyblock[keyIndex].keyMaterialOffset,
				      ctx);
	if (r < 0)
		goto out;

	r = AF_merge(AfKey,vk->key,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
	if (r < 0)
		goto out;

	r = LUKS_verify_volume_key(hdr, vk);
	if (!r)
		log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex);
out:
	crypt_safe_free(AfKey);
	crypt_free_volume_key(derived_key);
	return r;
}
Exemplo n.º 3
0
int LUKS_set_key(unsigned int keyIndex,
		 const char *password, size_t passwordLen,
		 struct luks_phdr *hdr, struct volume_key *vk,
		 uint32_t iteration_time_ms,
		 uint64_t *PBKDF2_per_sec,
		 struct crypt_device *ctx)
{
	struct volume_key *derived_key;
	char *AfKey = NULL;
	size_t AFEKSize;
	uint64_t PBKDF2_temp;
	int r;

	if(hdr->keyblock[keyIndex].active != LUKS_KEY_DISABLED) {
		log_err(ctx, _("Key slot %d active, purge first.\n"), keyIndex);
		return -EINVAL;
	}

	/* LUKS keyslot has always at least 4000 stripes accoding to specification */
	if(hdr->keyblock[keyIndex].stripes < 4000) {
	        log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?\n"),
			keyIndex);
	         return -EINVAL;
	}

	log_dbg("Calculating data for key slot %d", keyIndex);

	r = crypt_benchmark_kdf(ctx, "pbkdf2", hdr->hashSpec,
				"foo", 3, "bar", 3, PBKDF2_per_sec);
	if (r < 0) {
		log_err(ctx, _("Not compatible PBKDF2 options (using hash algorithm %s).\n"),
			hdr->hashSpec);
		return r;
	}

	/*
	 * Avoid floating point operation
	 * Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
	 */
	PBKDF2_temp = (*PBKDF2_per_sec / 2) * (uint64_t)iteration_time_ms;
	PBKDF2_temp /= 1024;
	if (PBKDF2_temp > UINT32_MAX)
		PBKDF2_temp = UINT32_MAX;
	hdr->keyblock[keyIndex].passwordIterations = at_least((uint32_t)PBKDF2_temp,
							      LUKS_SLOT_ITERATIONS_MIN);

	log_dbg("Key slot %d use %" PRIu32 " password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);

	derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
	if (!derived_key)
		return -ENOMEM;

	r = crypt_random_get(ctx, hdr->keyblock[keyIndex].passwordSalt,
		       LUKS_SALTSIZE, CRYPT_RND_SALT);
	if (r < 0)
		goto out;

	r = crypt_pbkdf("pbkdf2", hdr->hashSpec, password, passwordLen,
			hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
			derived_key->key, hdr->keyBytes,
			hdr->keyblock[keyIndex].passwordIterations);
	if (r < 0)
		goto out;

	/*
	 * AF splitting, the masterkey stored in vk->key is split to AfKey
	 */
	assert(vk->keylength == hdr->keyBytes);
	AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
	AfKey = crypt_safe_alloc(AFEKSize);
	if (!AfKey) {
		r = -ENOMEM;
		goto out;
	}

	log_dbg("Using hash %s for AF in key slot %d, %d stripes",
		hdr->hashSpec, keyIndex, hdr->keyblock[keyIndex].stripes);
	r = AF_split(vk->key,AfKey,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
	if (r < 0)
		goto out;

	log_dbg("Updating key slot %d [0x%04x] area.", keyIndex,
		hdr->keyblock[keyIndex].keyMaterialOffset << 9);
	/* Encryption via dm */
	r = LUKS_encrypt_to_storage(AfKey,
				    AFEKSize,
				    hdr->cipherName, hdr->cipherMode,
				    derived_key,
				    hdr->keyblock[keyIndex].keyMaterialOffset,
				    ctx);
	if (r < 0)
		goto out;

	/* Mark the key as active in phdr */
	r = LUKS_keyslot_set(hdr, (int)keyIndex, 1);
	if (r < 0)
		goto out;

	r = LUKS_write_phdr(hdr, ctx);
	if (r < 0)
		goto out;

	r = 0;
out:
	crypt_safe_free(AfKey);
	crypt_free_volume_key(derived_key);
	return r;
}
Exemplo n.º 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;
}
Exemplo n.º 5
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 r = 0, devfd = -1;
	ssize_t hdr_size;
	ssize_t buffer_size;
	char *buffer = NULL;

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

	hdr_size = LUKS_device_sectors(hdr.keyBytes) << 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("Storing backup of header (%zu bytes) and keyslot area (%zu bytes).",
		sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS);

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

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

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

	/* 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));

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

	r = 0;
out:
	if (devfd != -1)
		close(devfd);
	crypt_memzero(&hdr, sizeof(hdr));
	crypt_safe_free(buffer);
	return r;
}
Exemplo n.º 6
0
int LUKS_set_key(unsigned int keyIndex,
		 const char *password, size_t passwordLen,
		 struct luks_phdr *hdr, struct volume_key *vk,
		 struct crypt_device *ctx)
{
	struct volume_key *derived_key;
	char *AfKey = NULL;
	size_t AFEKSize;
	struct crypt_pbkdf_type *pbkdf;
	int r;

	if(hdr->keyblock[keyIndex].active != LUKS_KEY_DISABLED) {
		log_err(ctx, _("Key slot %d active, purge first."), keyIndex);
		return -EINVAL;
	}

	/* LUKS keyslot has always at least 4000 stripes according to specification */
	if(hdr->keyblock[keyIndex].stripes < 4000) {
	        log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?"),
			keyIndex);
	         return -EINVAL;
	}

	log_dbg("Calculating data for key slot %d", keyIndex);
	pbkdf = crypt_get_pbkdf(ctx);
	r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength);
	if (r < 0)
		return r;
	assert(pbkdf->iterations);

	/*
	 * Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
	 */
	hdr->keyblock[keyIndex].passwordIterations =
		at_least(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN);
	log_dbg("Key slot %d use %" PRIu32 " password iterations.", keyIndex,
		hdr->keyblock[keyIndex].passwordIterations);

	derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
	if (!derived_key)
		return -ENOMEM;

	r = crypt_random_get(ctx, hdr->keyblock[keyIndex].passwordSalt,
		       LUKS_SALTSIZE, CRYPT_RND_SALT);
	if (r < 0)
		goto out;

	r = crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, password, passwordLen,
			hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
			derived_key->key, hdr->keyBytes,
			hdr->keyblock[keyIndex].passwordIterations, 0, 0);
	if (r < 0)
		goto out;

	/*
	 * AF splitting, the masterkey stored in vk->key is split to AfKey
	 */
	assert(vk->keylength == hdr->keyBytes);
	AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
	AfKey = crypt_safe_alloc(AFEKSize);
	if (!AfKey) {
		r = -ENOMEM;
		goto out;
	}

	log_dbg("Using hash %s for AF in key slot %d, %d stripes",
		hdr->hashSpec, keyIndex, hdr->keyblock[keyIndex].stripes);
	r = AF_split(vk->key,AfKey,vk->keylength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
	if (r < 0)
		goto out;

	log_dbg("Updating key slot %d [0x%04x] area.", keyIndex,
		hdr->keyblock[keyIndex].keyMaterialOffset << 9);
	/* Encryption via dm */
	r = LUKS_encrypt_to_storage(AfKey,
				    AFEKSize,
				    hdr->cipherName, hdr->cipherMode,
				    derived_key,
				    hdr->keyblock[keyIndex].keyMaterialOffset,
				    ctx);
	if (r < 0)
		goto out;

	/* Mark the key as active in phdr */
	r = LUKS_keyslot_set(hdr, (int)keyIndex, 1);
	if (r < 0)
		goto out;

	r = LUKS_write_phdr(hdr, ctx);
	if (r < 0)
		goto out;

	r = 0;
out:
	crypt_safe_free(AfKey);
	crypt_free_volume_key(derived_key);
	return r;
}
Exemplo n.º 7
0
static int backup_luks_headers(struct reenc_ctx *rc)
{
	struct crypt_device *cd = NULL;
	struct crypt_params_luks1 params = {0};
	char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
	char *old_key = NULL;
	size_t old_key_size;
	int r;

	log_dbg("Creating LUKS header backup for device %s.", rc->device);

	if ((r = crypt_init(&cd, rc->device)) ||
	    (r = crypt_load(cd, CRYPT_LUKS1, NULL)))
		goto out;

	crypt_set_confirm_callback(cd, NULL, NULL);
	if ((r = crypt_header_backup(cd, CRYPT_LUKS1, rc->header_file_org)))
		goto out;
	log_verbose(_("LUKS header backup of device %s created.\n"), rc->device);

	/* For decrypt, new header will be fake one, so we are done here. */
	if (rc->reencrypt_mode == DECRYPT)
		goto out;

	if ((r = create_empty_header(rc->header_file_new, rc->header_file_org,
		crypt_get_data_offset(cd))))
		goto out;

	params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
	params.data_alignment = crypt_get_data_offset(cd);
	params.data_alignment += ROUND_SECTOR(opt_reduce_size);
	params.data_device = rc->device;

	if (opt_cipher) {
		r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
		if (r < 0) {
			log_err(_("No known cipher specification pattern detected.\n"));
			goto out;
		}
	}

	if (opt_keep_key) {
		log_dbg("Keeping key from old header.");
		old_key_size  = crypt_get_volume_key_size(cd);
		old_key = crypt_safe_alloc(old_key_size);
		if (!old_key) {
			r = -ENOMEM;
			goto out;
		}
		r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, old_key, &old_key_size,
			rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
		if (r < 0)
			goto out;
	}

	r = create_new_header(rc,
		opt_cipher ? cipher : crypt_get_cipher(cd),
		opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd),
		crypt_get_uuid(cd),
		old_key,
		opt_key_size ? opt_key_size / 8 : crypt_get_volume_key_size(cd),
		&params);
out:
	crypt_free(cd);
	crypt_safe_free(old_key);
	if (r)
		log_err(_("Creation of LUKS backup headers failed.\n"));
	return r;
}
Exemplo n.º 8
0
int crypt_keyfile_device_read(struct crypt_device *cd,  const char *keyfile,
			      char **key, size_t *key_size_read,
			      uint64_t keyfile_offset, size_t keyfile_size_max,
			      uint32_t flags)
{
	int fd, regular_file, char_to_read = 0, char_read = 0, unlimited_read = 0;
	int r = -EINVAL, newline;
	char *pass = NULL;
	size_t buflen, i;
	uint64_t file_read_size;
	struct stat st;

	if (!key || !key_size_read)
		return -EINVAL;

	*key = NULL;
	*key_size_read = 0;

	fd = keyfile ? open(keyfile, O_RDONLY) : STDIN_FILENO;
	if (fd < 0) {
		log_err(cd, _("Failed to open key file."));
		return -EINVAL;
	}

	if (isatty(fd)) {
		log_err(cd, _("Cannot read keyfile from a terminal."));
		r = -EINVAL;
		goto out_err;
	}

	/* If not requested otherwise, we limit input to prevent memory exhaustion */
	if (keyfile_size_max == 0) {
		keyfile_size_max = DEFAULT_KEYFILE_SIZE_MAXKB * 1024 + 1;
		unlimited_read = 1;
		/* use 4k for buffer (page divisor but avoid huge pages) */
		buflen = 4096 - sizeof(struct safe_allocation);
	} else
		buflen = keyfile_size_max;

	regular_file = 0;
	if (keyfile) {
		if (stat(keyfile, &st) < 0) {
			log_err(cd, _("Failed to stat key file."));
			goto out_err;
		}
		if (S_ISREG(st.st_mode)) {
			regular_file = 1;
			file_read_size = (uint64_t)st.st_size;

			if (keyfile_offset > file_read_size) {
				log_err(cd, _("Cannot seek to requested keyfile offset."));
				goto out_err;
			}
			file_read_size -= keyfile_offset;

			/* known keyfile size, alloc it in one step */
			if (file_read_size >= (uint64_t)keyfile_size_max)
				buflen = keyfile_size_max;
			else if (file_read_size)
				buflen = file_read_size;
		}
	}

	pass = crypt_safe_alloc(buflen);
	if (!pass) {
		log_err(cd, _("Out of memory while reading passphrase."));
		goto out_err;
	}

	/* Discard keyfile_offset bytes on input */
	if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
		log_err(cd, _("Cannot seek to requested keyfile offset."));
		goto out_err;
	}

	for (i = 0, newline = 0; i < keyfile_size_max; i += char_read) {
		if (i == buflen) {
			buflen += 4096;
			pass = crypt_safe_realloc(pass, buflen);
			if (!pass) {
				log_err(cd, _("Out of memory while reading passphrase."));
				r = -ENOMEM;
				goto out_err;
			}
		}

		if (flags & CRYPT_KEYFILE_STOP_EOL) {
			/* If we should stop on newline, we must read the input
			 * one character at the time. Otherwise we might end up
			 * having read some bytes after the newline, which we
			 * promised not to do.
			 */
			char_to_read = 1;
		} else {
			/* char_to_read = min(keyfile_size_max - i, buflen - i) */
			char_to_read = keyfile_size_max < buflen ?
				keyfile_size_max - i : buflen - i;
		}
		char_read = read_buffer(fd, &pass[i], char_to_read);
		if (char_read < 0) {
			log_err(cd, _("Error reading passphrase."));
			r = -EPIPE;
			goto out_err;
		}

		if (char_read == 0)
			break;
		/* Stop on newline only if not requested read from keyfile */
		if ((flags & CRYPT_KEYFILE_STOP_EOL) && pass[i] == '\n') {
			newline = 1;
			pass[i] = '\0';
			break;
		}
	}

	/* Fail if piped input dies reading nothing */
	if (!i && !regular_file && !newline) {
		log_dbg("Nothing read on input.");
		r = -EPIPE;
		goto out_err;
	}

	/* Fail if we exceeded internal default (no specified size) */
	if (unlimited_read && i == keyfile_size_max) {
		log_err(cd, _("Maximum keyfile size exceeded."));
		goto out_err;
	}

	if (!unlimited_read && i != keyfile_size_max) {
		log_err(cd, _("Cannot read requested amount of data."));
		goto out_err;
	}

	*key = pass;
	*key_size_read = i;
	r = 0;
out_err:
	if (fd != STDIN_FILENO)
		close(fd);

	if (r)
		crypt_safe_free(pass);
	return r;
}