+static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
+{
+ struct crypt_dm_active_device dmd = {};
+ char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ int key_nums, r;
+
+ r = dm_query_device(cd, name,
+ DM_ACTIVE_DEVICE |
+ DM_ACTIVE_UUID |
+ DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
+ if (r < 0)
+ goto out;
+
+ if (isPLAIN(cd->type)) {
+ cd->u.plain.uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
+ cd->u.plain.hdr.hash = NULL; /* no way to get this */
+ cd->u.plain.hdr.offset = dmd.u.crypt.offset;
+ cd->u.plain.hdr.skip = dmd.u.crypt.iv_offset;
+ cd->u.plain.key_size = dmd.u.crypt.vk->keylength;
+
+ r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher, NULL, cipher_mode);
+ if (!r) {
+ cd->u.plain.cipher = strdup(cipher);
+ cd->u.plain.cipher_mode = strdup(cipher_mode);
+ }
+ } else if (isLOOPAES(cd->type)) {
+ cd->u.loopaes.uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
+ cd->u.loopaes.hdr.offset = dmd.u.crypt.offset;
+
+ r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher,
+ &key_nums, cipher_mode);
+ if (!r) {
+ cd->u.loopaes.cipher = strdup(cipher);
+ cd->u.loopaes.cipher_mode = strdup(cipher_mode);
+ /* version 3 uses last key for IV */
+ if (dmd.u.crypt.vk->keylength % key_nums)
+ key_nums++;
+ cd->u.loopaes.key_size = dmd.u.crypt.vk->keylength / key_nums;
+ }
+ } else if (isLUKS(cd->type)) {
+ if (crypt_metadata_device(cd)) {
+ r = _crypt_load_luks1(cd, 0, 0);
+ if (r < 0) {
+ log_dbg("LUKS device header does not match active device.");
+ free(cd->type);
+ cd->type = NULL;
+ r = 0;
+ goto out;
+ }
+ /* check whether UUIDs match each other */
+ r = crypt_uuid_cmp(dmd.uuid, cd->u.luks1.hdr.uuid);
+ if (r < 0) {
+ log_dbg("LUKS device header uuid: %s mismatches DM returned uuid %s",
+ cd->u.luks1.hdr.uuid, dmd.uuid);
+ free(cd->type);
+ cd->type = NULL;
+ r = 0;
+ goto out;
+ }
+ }
+ } else if (isTCRYPT(cd->type)) {
+ r = TCRYPT_init_by_name(cd, name, &dmd, &cd->device,
+ &cd->u.tcrypt.params, &cd->u.tcrypt.hdr);
+ }
+out:
+ crypt_free_volume_key(dmd.u.crypt.vk);
+ device_free(dmd.data_device);
+ free(CONST_CAST(void*)dmd.u.crypt.cipher);
+ free(CONST_CAST(void*)dmd.uuid);
+ return r;
+}