r = crypt_cipher_init(&cipher, "blowfish", "ecb",
&key[alg->key_offset], alg->key_size);
if (r < 0)
- goto out;
+ return r;
memcpy(iv, &key[alg->iv_offset], alg->iv_size);
for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
bs, NULL, 0);
blowfish_le(&buf[i]);
if (r < 0)
- goto out;
+ break;
for (j = 0; j < bs; j++)
buf[i + j] ^= iv[j];
memcpy(iv, iv_old, bs);
}
-out:
+
crypt_cipher_destroy(cipher);
return r;
}
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],
const char *key, int legacy_modes)
{
struct tcrypt_phdr hdr2;
- int i, j, r;
+ int i, j, r = -EINVAL;
for (i = 0; tcrypt_cipher[i].chain_count; i++) {
if (!legacy_modes && tcrypt_cipher[i].legacy)
continue;
r = decrypt_hdr_one(&tcrypt_cipher[i].cipher[j],
tcrypt_cipher[i].mode, key, &hdr2);
- if (r < 0) {
- log_dbg("Error %s.", tcrypt_cipher[i].cipher[j].name);
+ 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)) {
unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {};
size_t passphrase_size;
char *key;
- int r = -EINVAL, i, legacy_modes;
+ int r = -EINVAL, i, legacy_modes, skipped = 0;
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
return -ENOMEM;
/* Decrypt header */
r = decrypt_hdr(cd, hdr, key, legacy_modes);
+ if (r == -ENOENT) {
+ skipped++;
+ continue;
+ }
if (r != -EPERM)
break;
}
+ if ((skipped && skipped == i) || r == -ENOTSUP)
+ log_err(cd, _("Required kernel crypto interface not available.\n"
+ "Ensure you have algif_skcipher kernel module loaded.\n"));
if (r < 0)
goto out;
r = hdr_from_disk(hdr, params, i, r);
if (!r) {
log_dbg("TCRYPT: Header version: %d, req. %d, sector %d"
- ", PBKDF2 hash %s", (int)hdr->d.version,
+ ", mk_offset %" PRIu64 ", hidden_size %" PRIu64
+ ", volume size %" PRIu64, (int)hdr->d.version,
(int)hdr->d.version_tc, (int)hdr->d.sector_size,
- params->hash_name);
+ hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size);
log_dbg("TCRYPT: Header cipher %s-%s, key size %d",
params->cipher, params->mode, params->key_size);
}
if (!algs)
return -EINVAL;
+ if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
+ dmd.size = hdr->d.hidden_volume_size / hdr->d.sector_size;
+ else
+ dmd.size = hdr->d.volume_size / hdr->d.sector_size;
+
r = device_block_adjust(cd, dmd.data_device, DEV_EXCL,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (r)
return 0;
}
-uint64_t TCRYPT_get_data_offset(struct tcrypt_phdr *hdr)
+uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params)
{
+ uint64_t size;
+
+ if (params->mode && !strncmp(params->mode, "xts", 3)) {
+ if (hdr->d.version < 3)
+ return 1;
+
+ if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
+ if (hdr->d.version > 3)
+ return (hdr->d.mk_offset / hdr->d.sector_size);
+ if (device_size(crypt_metadata_device(cd), &size) < 0)
+ return 0;
+ return (size - hdr->d.hidden_volume_size +
+ (TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size;
+ }
+ return (hdr->d.mk_offset / hdr->d.sector_size);
+ }
+
+ if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
+ if (device_size(crypt_metadata_device(cd), &size) < 0)
+ return 0;
+ return (size - hdr->d.hidden_volume_size +
+ (TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / hdr->d.sector_size;
+ }
+
// FIXME: system vol.
- if (!hdr->d.mk_offset)
- return 1;
- return (hdr->d.mk_offset / hdr->d.sector_size);
+ return hdr->d.mk_offset / hdr->d.sector_size;
}
-uint64_t TCRYPT_get_iv_offset(struct tcrypt_phdr *hdr)
+uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params
+)
{
- if (!hdr->d.mk_offset)
+ if (params->mode && !strncmp(params->mode, "xts", 3))
+ return TCRYPT_get_data_offset(cd, hdr, params);
+ else if (params->mode && !strncmp(params->mode, "lrw", 3))
return 0;
- return (hdr->d.mk_offset / hdr->d.sector_size);
+
+ return hdr->d.mk_offset / hdr->d.sector_size;
}
int TCRYPT_get_volume_key(struct crypt_device *cd,