#include "luks.h"
#include "loopaes.h"
#include "verity.h"
+#include "tcrypt.h"
#include "internal.h"
struct crypt_device {
int password_verify;
int rng_type;
+ // FIXME: switch to union
+ // FIXME: privatre binary headers and access it properly
+ // through sub-library (LUKS1, TCRYPT)
+
/* used in CRYPT_LUKS1 */
struct luks_phdr hdr;
uint64_t PBKDF2_per_sec;
unsigned int verity_root_hash_size;
char *verity_uuid;
+ /* used in CRYPT_TCRYPT */
+ struct crypt_params_tcrypt tcrypt_params;
+ struct tcrypt_phdr tcrypt_hdr;
+
/* callbacks definitions */
void (*log)(int level, const char *msg, void *usrptr);
void *log_usrptr;
return cd->device;
}
-static int init_crypto(struct crypt_device *ctx)
+int init_crypto(struct crypt_device *ctx)
{
int r;
return (type && !strcmp(CRYPT_VERITY, type));
}
+static int isTCRYPT(const char *type)
+{
+ return (type && !strcmp(CRYPT_TCRYPT, type));
+}
+
/* keyslot helpers */
static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
{
if (r < 0)
goto bad;
- if (dm_init(h, 1) < 0) {
- r = -ENOSYS;
- goto bad;
- }
+ dm_backend_init();
h->iteration_time = 1000;
h->password_verify = 0;
return r;
}
+static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcrypt *params)
+{
+ int r;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ memcpy(&cd->tcrypt_params, params, sizeof(*params));
+
+ r = TCRYPT_read_phdr(cd, &cd->tcrypt_hdr, &cd->tcrypt_params);
+
+ cd->tcrypt_params.passphrase = NULL;
+ cd->tcrypt_params.passphrase_size = 0;
+ cd->tcrypt_params.keyfiles = NULL;
+ cd->tcrypt_params.keyfiles_count = 0;
+
+ if (r < 0)
+ return r;
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_TCRYPT)))
+ return -ENOMEM;
+
+ return r;
+}
+
static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verity *params)
{
int r;
if (r < 0)
return r;
- if (params->flags & CRYPT_VERITY_NO_HEADER)
+ if (params && params->flags & CRYPT_VERITY_NO_HEADER)
return -EINVAL;
if (params)
goto out;
}
}
+ } else if (isTCRYPT(cd->type)) {
+ r = TCRYPT_init_by_name(cd, name, &dmd, &cd->device,
+ &cd->tcrypt_params, &cd->tcrypt_hdr);
}
out:
crypt_free_volume_key(dmd.u.crypt.vk);
(*cd)->type = strdup(CRYPT_LUKS1);
else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1))
(*cd)->type = strdup(CRYPT_VERITY);
+ else if (!strncmp(CRYPT_TCRYPT, dmd.uuid, sizeof(CRYPT_TCRYPT)-1))
+ (*cd)->type = strdup(CRYPT_TCRYPT);
else
log_dbg("Unknown UUID set, some parameters are not set.");
} else
&required_alignment,
&alignment_offset, DEFAULT_DISK_ALIGNMENT);
+ /* Check early if we cannot allocate block device for key slot access */
+ r = device_block_adjust(cd, cd->device, DEV_OK, 0, NULL, NULL);
+ if(r < 0)
+ return r;
+
r = LUKS_generate_phdr(&cd->hdr, cd->volume_key, cipher, cipher_mode,
(params && params->hash) ? params->hash : "sha1",
uuid, LUKS_STRIPES,
return -ENOMEM;
cd->verity_hdr.flags = params->flags;
- cd->verity_hdr.hash_name = strdup(params->hash_name);
+ if (!(cd->verity_hdr.hash_name = strdup(params->hash_name)))
+ return -ENOMEM;
cd->verity_hdr.data_device = NULL;
cd->verity_hdr.data_block_size = params->data_block_size;
cd->verity_hdr.hash_block_size = params->hash_block_size;
cd->verity_hdr.hash_type = params->hash_type;
cd->verity_hdr.flags = params->flags;
cd->verity_hdr.salt_size = params->salt_size;
- cd->verity_hdr.salt = malloc(params->salt_size);
+ if (!(cd->verity_hdr.salt = malloc(params->salt_size)))
+ return -ENOMEM;
+
if (params->salt)
memcpy(CONST_CAST(char*)cd->verity_hdr.salt, params->salt,
params->salt_size);
return -EINVAL;
}
r = _crypt_load_verity(cd, params);
+ } else if (isTCRYPT(requested_type)) {
+ if (cd->type && !isTCRYPT(cd->type)) {
+ log_dbg("Context is already initialised to type %s", cd->type);
+ return -EINVAL;
+ }
+ r = _crypt_load_tcrypt(cd, params);
} else
return -EINVAL;
r = 0;
} else {
dmd.size = new_size;
- r = dm_create_device(cd, name, cd->type, &dmd, 1);
+ if (isTCRYPT(cd->type))
+ r = -ENOTSUP;
+ else
+ r = dm_create_device(cd, name, cd->type, &dmd, 1);
}
out:
if (dmd.target == DM_CRYPT) {
if (cd) {
log_dbg("Releasing crypt device %s context.", mdata_device_path(cd));
- dm_exit();
+ dm_backend_exit();
crypt_free_volume_key(cd->volume_key);
device_free(cd->device);
log_dbg("Suspending volume %s.", name);
- if (!isLUKS(cd->type)) {
+ if (!cd || !isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
r = -EINVAL;
goto out;
return -EINVAL;
}
- if (!cd && dm_init(NULL, 1) < 0)
- return -ENOSYS;
+ dm_backend_init();
r = dm_status_suspended(cd, name);
if (r < 0)
else if (r)
log_err(cd, "Error during suspending device %s.\n", name);
out:
- if (!cd)
- dm_exit();
+ dm_backend_exit();
return r;
}
if (cd->verity_root_hash)
memcpy(cd->verity_root_hash, volume_key, volume_key_size);
}
+ } else if (isTCRYPT(cd->type)) {
+ if (!name)
+ return 0;
+ r = TCRYPT_activate(cd, name, &cd->tcrypt_hdr,
+ &cd->tcrypt_params, flags);
} else
log_err(cd, _("Device type is not properly initialised.\n"));
log_dbg("Deactivating volume %s.", name);
- if (!cd && dm_init(NULL, 1) < 0)
- return -ENOSYS;
+ if (!cd)
+ dm_backend_init();
switch (crypt_status(cd, name)) {
case CRYPT_ACTIVE:
case CRYPT_BUSY:
- r = dm_remove_device(cd, name, 0, 0);
+ if (isTCRYPT(cd->type))
+ r = TCRYPT_deactivate(cd, name);
+ else
+ r = dm_remove_device(cd, name, 0, 0);
break;
case CRYPT_INACTIVE:
log_err(cd, _("Device %s is not active.\n"), name);
}
if (!cd)
- dm_exit();
+ dm_backend_exit();
return r;
}
} else if (isLUKS(cd->type)) {
r = LUKS_open_key_with_hdr(keyslot, passphrase,
passphrase_size, &cd->hdr, &vk, cd);
-
+ } else if (isTCRYPT(cd->type)) {
+ r = TCRYPT_get_volume_key(cd, &cd->tcrypt_hdr, &cd->tcrypt_params, &vk);
} else
log_err(cd, _("This operation is not supported for %s crypt device.\n"), cd->type ?: "(none)");
{
int r;
- if (!cd && dm_init(NULL, 1) < 0)
- return CRYPT_INVALID;
+ if (!cd)
+ dm_backend_init();
r = dm_status_device(cd, name);
if (!cd)
- dm_exit();
+ dm_backend_exit();
if (r < 0 && r != -ENODEV)
return CRYPT_INVALID;
return _luks_dump(cd);
else if (isVERITY(cd->type))
return _verity_dump(cd);
+ else if (isTCRYPT(cd->type))
+ return TCRYPT_dump(cd, &cd->tcrypt_hdr, &cd->tcrypt_params);
log_err(cd, _("Dump operation is not supported for this device type.\n"));
return -EINVAL;
if (isLOOPAES(cd->type))
return cd->loopaes_cipher;
+ if (isTCRYPT(cd->type))
+ return cd->tcrypt_params.cipher;
+
return NULL;
}
if (isLOOPAES(cd->type))
return cd->loopaes_cipher_mode;
+ if (isTCRYPT(cd->type))
+ return cd->tcrypt_params.mode;
+
return NULL;
}
if (isVERITY(cd->type))
return cd->verity_root_hash_size;
+ if (isTCRYPT(cd->type))
+ return cd->tcrypt_params.key_size;
+
return 0;
}
if (isLOOPAES(cd->type))
return cd->loopaes_hdr.offset;
+ if (isTCRYPT(cd->type))
+ return TCRYPT_get_data_offset(&cd->tcrypt_hdr);
+
return 0;
}
if (isLOOPAES(cd->type))
return cd->loopaes_hdr.skip;
+ if (isTCRYPT(cd->type))
+ return TCRYPT_get_iv_offset(&cd->tcrypt_hdr);
+
return 0;
}
return -EINVAL;
}
+int crypt_keyslot_area(struct crypt_device *cd,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length)
+{
+ if (!isLUKS(cd->type))
+ return -EINVAL;
+
+ return LUKS_keyslot_area(&cd->hdr, keyslot, offset, length);
+}
+
const char *crypt_get_type(struct crypt_device *cd)
{
return cd->type;
return 0;
}
-int crypt_get_active_device(struct crypt_device *cd __attribute__((unused)),
- const char *name,
+int crypt_get_active_device(struct crypt_device *cd, const char *name,
struct crypt_active_device *cad)
{
struct crypt_dm_active_device dmd;
if (dmd.target != DM_CRYPT && dmd.target != DM_VERITY)
return -ENOTSUP;
- cad->offset = dmd.u.crypt.offset;
- cad->iv_offset = dmd.u.crypt.iv_offset;
+ if (cd && isTCRYPT(cd->type)) {
+ cad->offset = TCRYPT_get_data_offset(&cd->tcrypt_hdr);
+ cad->iv_offset = TCRYPT_get_iv_offset(&cd->tcrypt_hdr);
+ } else {
+ cad->offset = dmd.u.crypt.offset;
+ cad->iv_offset = dmd.u.crypt.iv_offset;
+ }
cad->size = dmd.size;
cad->flags = dmd.flags;