Ejemplo n.º 1
0
static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
				   const char *key, char *buf)
{
	int bs = alg->iv_size;
	char iv[bs], iv_old[bs];
	struct crypt_cipher *cipher = NULL;
	int i, j, r;

	assert(bs == 2*sizeof(uint32_t));

	r = crypt_cipher_init(&cipher, "blowfish", "ecb",
			      &key[alg->key_offset], alg->key_size);
	if (r < 0)
		return r;

	memcpy(iv, &key[alg->iv_offset], alg->iv_size);
	for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
		memcpy(iv_old, &buf[i], bs);
		TCRYPT_swab_le(&buf[i]);
		r = crypt_cipher_decrypt(cipher, &buf[i], &buf[i],
					  bs, NULL, 0);
		TCRYPT_swab_le(&buf[i]);
		if (r < 0)
			break;
		for (j = 0; j < bs; j++)
			buf[i + j] ^= iv[j];
		memcpy(iv, iv_old, bs);
	}

	crypt_cipher_destroy(cipher);
	crypt_memzero(iv, bs);
	crypt_memzero(iv_old, bs);
	return r;
}
Ejemplo n.º 2
0
/*
 * For chanined ciphers and CBC mode we need "outer" decryption.
 * Backend doesn't provide this, so implement it here directly using ECB.
 */
static int TCRYPT_decrypt_cbci(struct tcrypt_algs *ciphers,
				const char *key, struct tcrypt_phdr *hdr)
{
	struct crypt_cipher *cipher[ciphers->chain_count];
	unsigned int bs = ciphers->cipher[0].iv_size;
	char *buf = (char*)&hdr->e, iv[bs], iv_old[bs];
	unsigned int i, j;
	int r = -EINVAL;

	TCRYPT_remove_whitening(buf, &key[8]);

	memcpy(iv, &key[ciphers->cipher[0].iv_offset], bs);

	/* Initialize all ciphers in chain in ECB mode */
	for (j = 0; j < ciphers->chain_count; j++)
		cipher[j] = NULL;
	for (j = 0; j < ciphers->chain_count; j++) {
		r = crypt_cipher_init(&cipher[j], ciphers->cipher[j].name, "ecb",
				      &key[ciphers->cipher[j].key_offset],
				      ciphers->cipher[j].key_size);
		if (r < 0)
			goto out;
	}

	/* Implements CBC with chained ciphers in loop inside */
	for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
		memcpy(iv_old, &buf[i], bs);
		for (j = ciphers->chain_count; j > 0; j--) {
			r = crypt_cipher_decrypt(cipher[j - 1], &buf[i], &buf[i],
						  bs, NULL, 0);
			if (r < 0)
				goto out;
		}
		for (j = 0; j < bs; j++)
			buf[i + j] ^= iv[j];
		memcpy(iv, iv_old, bs);
	}
out:
	for (j = 0; j < ciphers->chain_count; j++)
		if (cipher[j])
			crypt_cipher_destroy(cipher[j]);

	crypt_memzero(iv, bs);
	crypt_memzero(iv_old, bs);
	return r;
}
Ejemplo n.º 3
0
static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
			       const char *key, uint32_t flags)
{
	struct tcrypt_phdr hdr2;
	int i, j, r = -EINVAL;

	for (i = 0; tcrypt_cipher[i].chain_count; i++) {
		if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
			continue;
		log_dbg("TCRYPT:  trying cipher %s-%s",
			tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode);

		memcpy(&hdr2.e, &hdr->e, TCRYPT_HDR_LEN);

		if (!strncmp(tcrypt_cipher[i].mode, "cbci", 4))
			r = TCRYPT_decrypt_cbci(&tcrypt_cipher[i], key, &hdr2);
		else for (j = tcrypt_cipher[i].chain_count - 1; j >= 0 ; j--) {
			if (!tcrypt_cipher[i].cipher[j].name)
				continue;
			r = TCRYPT_decrypt_hdr_one(&tcrypt_cipher[i].cipher[j],
					    tcrypt_cipher[i].mode, key, &hdr2);
			if (r < 0)
				break;
		}

		if (r < 0) {
			log_dbg("TCRYPT:   returned error %d, skipped.", r);
			if (r == -ENOTSUP)
				break;
			r = -ENOENT;
			continue;
		}

		if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
			log_dbg("TCRYPT: Signature magic detected.");
			memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
			r = i;
			break;
		}
		if ((flags & CRYPT_TCRYPT_VERA_MODES) &&
		     !strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
			log_dbg("TCRYPT: Signature magic detected (Veracrypt).");
			memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
			r = i;
			break;
		}
		r = -EPERM;
	}

	crypt_memzero(&hdr2, sizeof(hdr2));
	return r;
}
Ejemplo n.º 4
0
static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
				   const char *key,struct tcrypt_phdr *hdr)
{
	char backend_key[TCRYPT_HDR_KEY_LEN];
	char iv[TCRYPT_HDR_IV_LEN] = {};
	char mode_name[MAX_CIPHER_LEN];
	struct crypt_cipher *cipher;
	char *c, *buf = (char*)&hdr->e;
	int r;

	/* Remove IV if present */
	strncpy(mode_name, mode, MAX_CIPHER_LEN);
	c = strchr(mode_name, '-');
	if (c)
		*c = '\0';

	if (!strncmp(mode, "lrw", 3))
		iv[alg->iv_size - 1] = 1;
	else if (!strncmp(mode, "cbc", 3)) {
		TCRYPT_remove_whitening(buf, &key[8]);
		if (!strcmp(alg->name, "blowfish_le"))
			return decrypt_blowfish_le_cbc(alg, key, buf);
		memcpy(iv, &key[alg->iv_offset], alg->iv_size);
	}

	TCRYPT_copy_key(alg, mode, backend_key, key);
	r = crypt_cipher_init(&cipher, alg->name, mode_name,
			      backend_key, alg->key_size);
	if (!r) {
		r = crypt_cipher_decrypt(cipher, buf, buf, TCRYPT_HDR_LEN,
					 iv, alg->iv_size);
		crypt_cipher_destroy(cipher);
	}

	crypt_memzero(backend_key, sizeof(backend_key));
	crypt_memzero(iv, TCRYPT_HDR_IV_LEN);
	return r;
}
Ejemplo n.º 5
0
static int TCRYPT_pool_keyfile(struct crypt_device *cd,
                               unsigned char pool[TCRYPT_KEY_POOL_LEN],
                               const char *keyfile)
{
    unsigned char data[TCRYPT_KEYFILE_LEN];
    int i, j, fd, data_size;
    uint32_t crc;

    log_dbg("TCRYPT: using keyfile %s.", keyfile);

    fd = open(keyfile, O_RDONLY);
    if (fd < 0) {
        log_err(cd, _("Failed to open key file.\n"));
        return -EIO;
    }

    /* FIXME: add while */
    data_size = read(fd, data, TCRYPT_KEYFILE_LEN);
    close(fd);
    if (data_size < 0) {
        log_err(cd, _("Error reading keyfile %s.\n"), keyfile);
        return -EIO;
    }

    for (i = 0, j = 0, crc = ~0U; i < data_size; i++) {
        crc = crypt_crc32(crc, &data[i], 1);
        pool[j++] += (unsigned char)(crc >> 24);
        pool[j++] += (unsigned char)(crc >> 16);
        pool[j++] += (unsigned char)(crc >>  8);
        pool[j++] += (unsigned char)(crc);
        j %= TCRYPT_KEY_POOL_LEN;
    }

    crypt_memzero(&crc, sizeof(crc));
    crypt_memzero(data, TCRYPT_KEYFILE_LEN);

    return 0;
}
Ejemplo n.º 6
0
/*
 * A simple call to lseek(3) might not be possible for some inputs (e.g.
 * reading from a pipe), so this function instead reads of up to BUFSIZ bytes
 * at a time until the specified number of bytes. It returns -1 on read error
 * or when it reaches EOF before the requested number of bytes have been
 * discarded.
 */
static int keyfile_seek(int fd, uint64_t bytes)
{
	char tmp[BUFSIZ];
	size_t next_read;
	ssize_t bytes_r;
	off64_t r;

	r = lseek64(fd, bytes, SEEK_CUR);
	if (r > 0)
		return 0;
	if (r < 0 && errno != ESPIPE)
		return -1;

	while (bytes > 0) {
		/* figure out how much to read */
		next_read = bytes > sizeof(tmp) ? sizeof(tmp) : (size_t)bytes;

		bytes_r = read(fd, tmp, next_read);
		if (bytes_r < 0) {
			if (errno == EINTR)
				continue;

			crypt_memzero(tmp, sizeof(tmp));
			/* read error */
			return -1;
		}

		if (bytes_r == 0)
			/* EOF */
			break;

		bytes -= bytes_r;
	}

	crypt_memzero(tmp, sizeof(tmp));
	return bytes == 0 ? 0 : -1;
}
Ejemplo n.º 7
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.º 8
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.º 9
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.º 10
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;
}
Ejemplo n.º 11
0
static int TCRYPT_init_hdr(struct crypt_device *cd,
			   struct tcrypt_phdr *hdr,
			   struct crypt_params_tcrypt *params)
{
	unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {};
	size_t passphrase_size;
	char *key;
	unsigned int i, skipped = 0;
	int r = -EPERM;

	if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
		return -ENOMEM;

	if (params->keyfiles_count)
		passphrase_size = TCRYPT_KEY_POOL_LEN;
	else
		passphrase_size = params->passphrase_size;

	if (params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
		log_err(cd, _("Maximum TCRYPT passphrase length (%d) exceeded.\n"),
			      TCRYPT_KEY_POOL_LEN);
		goto out;
	}

	/* Calculate pool content from keyfiles */
	for (i = 0; i < params->keyfiles_count; i++) {
		r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i]);
		if (r < 0)
			goto out;
	}

	/* If provided password, combine it with pool */
	for (i = 0; i < params->passphrase_size; i++)
		pwd[i] += params->passphrase[i];

	for (i = 0; tcrypt_kdf[i].name; i++) {
		if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
			continue;
		if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt)
			continue;
		/* Derive header key */
		log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
			tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations);
		r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash,
				(char*)pwd, passphrase_size,
				hdr->salt, TCRYPT_HDR_SALT_LEN,
				key, TCRYPT_HDR_KEY_LEN,
				tcrypt_kdf[i].iterations);
		if (r < 0 && crypt_hash_size(tcrypt_kdf[i].hash) < 0) {
			log_verbose(cd, _("PBKDF2 hash algorithm %s not available, skipping.\n"),
				      tcrypt_kdf[i].hash);
			continue;
		}
		if (r < 0)
			break;

		/* Decrypt header */
		r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags);
		if (r == -ENOENT) {
			skipped++;
			r = -EPERM;
		}
		if (r != -EPERM)
			break;
	}

	if ((r < 0 && r != -EPERM && skipped && skipped == i) || r == -ENOTSUP) {
		log_err(cd, _("Required kernel crypto interface not available.\n"));
#ifdef ENABLE_AF_ALG
		log_err(cd, _("Ensure you have algif_skcipher kernel module loaded.\n"));
#endif
	}
	if (r < 0)
		goto out;

	r = TCRYPT_hdr_from_disk(hdr, params, i, r);
	if (!r) {
		log_dbg("TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d"
			", mk_offset %" PRIu64 ", hidden_size %" PRIu64
			", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ?
			VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC,
			(int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size,
			hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size);
		log_dbg("TCRYPT: Header cipher %s-%s, key size %zu",
			params->cipher, params->mode, params->key_size);
	}
out:
	crypt_memzero(pwd, TCRYPT_KEY_POOL_LEN);
	if (key)
		crypt_memzero(key, TCRYPT_HDR_KEY_LEN);
	free(key);
	return r;
}