Ejemplo n.º 1
0
int LUKS_open_key_with_hdr(int keyIndex,
			   const char *password,
			   size_t passwordLen,
			   struct luks_phdr *hdr,
			   struct volume_key **vk,
			   struct crypt_device *ctx)
{
	unsigned int i;
	int r;

	*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);

	if (keyIndex >= 0) {
		r = LUKS_open_key(keyIndex, password, passwordLen, hdr, *vk, ctx);
		return (r < 0) ? r : keyIndex;
	}

	for(i = 0; i < LUKS_NUMKEYS; i++) {
		r = LUKS_open_key(i, password, passwordLen, hdr, *vk, ctx);
		if(r == 0)
			return i;

		/* Do not retry for errors that are no -EPERM or -ENOENT,
		   former meaning password wrong, latter key slot inactive */
		if ((r != -EPERM) && (r != -ENOENT))
			return r;
	}
	/* Warning, early returns above */
	log_err(ctx, _("No key available with this passphrase.\n"));
	return -EPERM;
}
Ejemplo 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;
}
Ejemplo n.º 3
0
/* Check that kernel supports requested cipher by decryption of one sector */
static int LUKS_check_cipher(struct luks_phdr *hdr, struct crypt_device *ctx)
{
	int r;
	struct volume_key *empty_key;
	char buf[SECTOR_SIZE];

	log_dbg("Checking if cipher %s-%s is usable.", hdr->cipherName, hdr->cipherMode);

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

	r = LUKS_decrypt_from_storage(buf, sizeof(buf),
				      hdr->cipherName, hdr->cipherMode,
				      empty_key, 0, ctx);

	crypt_free_volume_key(empty_key);
	crypt_memzero(buf, sizeof(buf));
	return r;
}
Ejemplo n.º 4
0
/* Check that kernel supports requested cipher by decryption of one sector */
int LUKS_check_cipher(struct crypt_device *ctx, size_t keylength, const char *cipher, const char *cipher_mode)
{
	int r;
	struct volume_key *empty_key;
	char buf[SECTOR_SIZE];

	log_dbg("Checking if cipher %s-%s is usable.", cipher, cipher_mode);

	empty_key = crypt_alloc_volume_key(keylength, NULL);
	if (!empty_key)
		return -ENOMEM;

	/* No need to get KEY quality random but it must avoid known weak keys. */
	r = crypt_random_get(ctx, empty_key->key, empty_key->keylength, CRYPT_RND_NORMAL);
	if (!r)
		r = LUKS_decrypt_from_storage(buf, sizeof(buf), cipher, cipher_mode, empty_key, 0, ctx);

	crypt_free_volume_key(empty_key);
	crypt_memzero(buf, sizeof(buf));
	return r;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/* This routine should do some just basic recovery for known problems. */
static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
{
	struct luks_phdr temp_phdr;
	const unsigned char *sector = (const unsigned char*)phdr;
	struct volume_key *vk;
	uint64_t PBKDF2_per_sec = 1;
	int i, bad, r, need_write = 0;

	if (phdr->keyBytes != 16 && phdr->keyBytes != 32 && phdr->keyBytes != 64) {
		log_err(ctx, _("Non standard key size, manual repair required.\n"));
		return -EINVAL;
	}
	/* cryptsetup 1.0 did not align to 4k, cannot repair this one */
	if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
		log_err(ctx, _("Non standard keyslots alignment, manual repair required.\n"));
		return -EINVAL;
	}

	vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);

	log_verbose(ctx, _("Repairing keyslots.\n"));

	log_dbg("Generating second header with the same parameters for check.");
	/* cipherName, cipherMode, hashSpec, uuid are already null terminated */
	/* payloadOffset - cannot check */
	r = LUKS_generate_phdr(&temp_phdr, vk, phdr->cipherName, phdr->cipherMode,
			       phdr->hashSpec,phdr->uuid, LUKS_STRIPES,
			       phdr->payloadOffset, 0,
			       1, &PBKDF2_per_sec,
			       1, ctx);
	if (r < 0) {
		log_err(ctx, _("Repair failed."));
		goto out;
	}

	for(i = 0; i < LUKS_NUMKEYS; ++i) {
		if (phdr->keyblock[i].active == LUKS_KEY_ENABLED)  {
			log_dbg("Skipping repair for active keyslot %i.", i);
			continue;
		}

		bad = 0;
		if (phdr->keyblock[i].keyMaterialOffset != temp_phdr.keyblock[i].keyMaterialOffset) {
			log_err(ctx, _("Keyslot %i: offset repaired (%u -> %u).\n"), i,
				(unsigned)phdr->keyblock[i].keyMaterialOffset,
				(unsigned)temp_phdr.keyblock[i].keyMaterialOffset);
			phdr->keyblock[i].keyMaterialOffset = temp_phdr.keyblock[i].keyMaterialOffset;
			bad = 1;
		}

		if (phdr->keyblock[i].stripes != temp_phdr.keyblock[i].stripes) {
			log_err(ctx, _("Keyslot %i: stripes repaired (%u -> %u).\n"), i,
				(unsigned)phdr->keyblock[i].stripes,
				(unsigned)temp_phdr.keyblock[i].stripes);
			phdr->keyblock[i].stripes = temp_phdr.keyblock[i].stripes;
			bad = 1;
		}

		/* Known case - MSDOS partition table signature */
		if (i == 6 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) {
			log_err(ctx, _("Keyslot %i: bogus partition signature.\n"), i);
			bad = 1;
		}

		if(bad) {
			log_err(ctx, _("Keyslot %i: salt wiped.\n"), i);
			phdr->keyblock[i].active = LUKS_KEY_DISABLED;
			memset(&phdr->keyblock[i].passwordSalt, 0x00, LUKS_SALTSIZE);
			phdr->keyblock[i].passwordIterations = 0;
		}

		if (bad)
			need_write = 1;
	}

	if (need_write) {
		log_verbose(ctx, _("Writing LUKS header to disk.\n"));
		r = LUKS_write_phdr(phdr, ctx);
	}
out:
	crypt_free_volume_key(vk);
	crypt_memzero(&temp_phdr, sizeof(temp_phdr));
	return r;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
	const char *hash_name;
	char tweak, *key_ptr;
	unsigned i, key_len_input;
	int r;

	hash_name = hash_override ?: get_hash(key_len_output);
	tweak = get_tweak(keys_count);
	key_len_input = strlen(input_keys[0]);

	if (!keys_count || !key_len_output || !hash_name || !key_len_input) {
		log_err(cd, _("Key processing error (using hash %s).\n"),
			hash_name ?: "[none]");
		return -EINVAL;
	}

	*vk = crypt_alloc_volume_key(key_len_output * keys_count, NULL);
	if (!*vk)
		return -ENOMEM;

	for (i = 0; i < keys_count; i++) {
		key_ptr = &(*vk)->key[i * key_len_output];
		r = hash_key(input_keys[i], key_len_input, key_ptr,
			     key_len_output, hash_name);
		if (r < 0)
			break;

		key_ptr[0] ^= tweak;
	}

	if (r < 0 && *vk) {
		crypt_free_volume_key(*vk);