/* Create verity hash */ int VERITY_create(struct crypt_device *cd, struct crypt_params_verity *verity_hdr, char *root_hash, size_t root_hash_size) { unsigned pgsize = crypt_getpagesize(); if (verity_hdr->salt_size > 256) return -EINVAL; if (verity_hdr->data_block_size > pgsize) log_err(cd, "WARNING: Kernel cannot activate device if data " "block size exceeds page size (%u).\n", pgsize); off_t sz = verity_hdr->data_size; return VERITY_create_or_verify_hash(cd, 0, verity_hdr->hash_type, verity_hdr->hash_name, crypt_metadata_device(cd), crypt_data_device(cd), verity_hdr->hash_block_size, verity_hdr->data_block_size, verity_hdr->data_size, VERITY_hash_offset_block(verity_hdr), root_hash, root_hash_size, verity_hdr->salt, verity_hdr->salt_size); }
int LUKS1_activate(struct crypt_device *cd, const char *name, struct volume_key *vk, uint32_t flags) { int r; char *dm_cipher = NULL; enum devcheck device_check; struct crypt_dm_active_device dmd = { .target = DM_CRYPT, .uuid = crypt_get_uuid(cd), .flags = flags, .size = 0, .data_device = crypt_data_device(cd), .u.crypt = { .cipher = NULL, .vk = vk, .offset = crypt_get_data_offset(cd), .iv_offset = 0, .sector_size = crypt_get_sector_size(cd), } }; if (dmd.flags & CRYPT_ACTIVATE_SHARED) device_check = DEV_SHARED; else device_check = DEV_EXCL; r = device_block_adjust(cd, dmd.data_device, device_check, dmd.u.crypt.offset, &dmd.size, &dmd.flags); if (r) return r; r = asprintf(&dm_cipher, "%s-%s", crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); if (r < 0) return -ENOMEM; dmd.u.crypt.cipher = dm_cipher; r = dm_create_device(cd, name, CRYPT_LUKS1, &dmd, 0); free(dm_cipher); return r; }
/* Verify verity device using userspace crypto backend */ int VERITY_verify(struct crypt_device *cd, struct crypt_params_verity *verity_hdr, const char *root_hash, size_t root_hash_size) { return VERITY_create_or_verify_hash(cd, 1, verity_hdr->hash_type, verity_hdr->hash_name, crypt_metadata_device(cd), crypt_data_device(cd), verity_hdr->hash_block_size, verity_hdr->data_block_size, verity_hdr->data_size, VERITY_hash_offset_block(verity_hdr), CONST_CAST(char*)root_hash, root_hash_size, verity_hdr->salt, verity_hdr->salt_size); }
int LUKS1_activate(struct crypt_device *cd, const char *name, struct volume_key *vk, uint32_t flags) { int r; struct crypt_dm_active_device dmd = { .flags = flags, .uuid = crypt_get_uuid(cd), }; r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd), crypt_get_data_offset(cd), crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); if (!r) r = create_or_reload_device(cd, name, CRYPT_LUKS1, &dmd); dm_targets_free(cd, &dmd); return r; }
/* Activate verity device in kernel device-mapper */ int VERITY_activate(struct crypt_device *cd, const char *name, const char *root_hash, size_t root_hash_size, struct crypt_params_verity *verity_hdr, uint32_t activation_flags) { struct crypt_dm_active_device dmd; int r; log_dbg("Trying to activate VERITY device %s using hash %s.", name ?: "[none]", verity_hdr->hash_name); if (verity_hdr->flags & CRYPT_VERITY_CHECK_HASH) { log_dbg("Verification of data in userspace required."); r = VERITY_verify(cd, verity_hdr, root_hash, root_hash_size); if (r < 0) return r; } if (!name) return 0; dmd.target = DM_VERITY; dmd.data_device = crypt_data_device(cd); dmd.u.verity.hash_device = crypt_metadata_device(cd); dmd.u.verity.root_hash = root_hash; dmd.u.verity.root_hash_size = root_hash_size; dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr), dmd.flags = activation_flags; dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512; dmd.uuid = crypt_get_uuid(cd); dmd.u.verity.vp = verity_hdr; r = device_block_adjust(cd, dmd.u.verity.hash_device, DEV_OK, 0, NULL, NULL); if (r) return r; r = device_block_adjust(cd, dmd.data_device, DEV_EXCL, 0, &dmd.size, &dmd.flags); if (r) return r; r = dm_create_device(cd, name, CRYPT_VERITY, &dmd, 0); if (r < 0 && !(dm_flags() & DM_VERITY_SUPPORTED)) { log_err(cd, _("Kernel doesn't support dm-verity mapping.\n")); return -ENOTSUP; } if (r < 0) return r; r = dm_status_verity_ok(cd, name); if (r < 0) return r; if (!r) log_err(cd, _("Verity device detected corruption after activation.\n")); return 0; }