int crypt_activate_by_signed_key(struct crypt_device *cd,
	const char *name,
	const char *volume_key,
	size_t volume_key_size,
	const char *signature,
	size_t signature_size,
	uint32_t flags)
{
	char description[512];
	int r;

	if (!cd || !isVERITY(cd->type))
		return -EINVAL;

	if (!volume_key || !volume_key_size || (!name && signature)) {
		log_err(cd, _("Incorrect root hash specified for verity device."));
		return -EINVAL;
	}

	log_dbg(cd, "%s volume %s by %skey.", name ? "Activating" : "Checking", name ?: "", signature ? "signed " : "");

	if (cd->u.verity.hdr.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE && !signature) {
		log_err(cd, _("Root hash signature required."));
		return -EINVAL;
	}

	r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
	if (r < 0)
		return r;

	if (signature && !kernel_keyring_support()) {
		log_err(cd, _("Kernel keyring missing: required for passing signature to kernel."));
		return -EINVAL;
	}

	/* volume_key == root hash */
	free(CONST_CAST(void*)cd->u.verity.root_hash);
	cd->u.verity.root_hash = NULL;

	if (signature) {
		r = snprintf(description, sizeof(description)-1, "cryptsetup:%s%s%s",
			     crypt_get_uuid(cd) ?: "", crypt_get_uuid(cd) ? "-" : "", name);
		if (r < 0)
			return -EINVAL;

		log_dbg(cd, "Adding signature into keyring %s", description);
		r = keyring_add_key_in_thread_keyring(USER_KEY, description, signature, signature_size);
		if (r) {
			log_err(cd, _("Failed to load key in kernel keyring."));
			return r;
		}
	}

	r = VERITY_activate(cd, name, volume_key, volume_key_size,
			    signature ? description : NULL,
			    cd->u.verity.fec_device,
			    &cd->u.verity.hdr, flags | CRYPT_ACTIVATE_READONLY);

	if (!r) {
		cd->u.verity.root_hash_size = volume_key_size;
		cd->u.verity.root_hash = malloc(volume_key_size);
		if (cd->u.verity.root_hash)
			memcpy(CONST_CAST(void*)cd->u.verity.root_hash, volume_key, volume_key_size);
	}

	if (signature)
		crypt_drop_keyring_key_by_description(cd, description, USER_KEY);

	return r;
}
int crypt_activate_by_signed_key(struct crypt_device *cd,
	const char *name,
	const char *volume_key,
	size_t volume_key_size,
	const char *signature,
	size_t signature_size,
	uint32_t flags)
{
	char description[512];
	int r;

	if (!cd || !isVERITY(cd->type))
		return -EINVAL;

	if (!volume_key || !volume_key_size || (!name && signature)) {
		log_err(cd, _("Incorrect root hash specified for verity device."));
		return -EINVAL;
	}

	log_dbg(cd, "%s volume %s by %skey.", name ? "Activating" : "Checking", name ?: "", signature ? "signed " : "");

	if (cd->u.verity.hdr.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE && !signature) {
		log_err(cd, _("Root hash signature required."));
		return -EINVAL;
	}

	r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
	if (r < 0)
		return r;

	if (signature && !kernel_keyring_support()) {
		log_err(cd, _("Kernel keyring missing: required for passing signature to kernel."));
		return -EINVAL;
	}

	 
	free(CONST_CAST(void*)cd->u.verity.root_hash);
	cd->u.verity.root_hash = NULL;

	if (signature) {
		r = snprintf(description, sizeof(description)-1, "cryptsetup:%s%s%s",
			     crypt_get_uuid(cd) ?: "", crypt_get_uuid(cd) ? "-" : "", name);
		if (r < 0)
			return -EINVAL;

		log_dbg(cd, "Adding signature into keyring %s", description);
		r = keyring_add_key_in_thread_keyring(USER_KEY, description, signature, signature_size);
		if (r) {
			log_err(cd, _("Failed to load key in kernel keyring."));
			return r;
		}
	}

	r = VERITY_activate(cd, name, volume_key, volume_key_size,
			    signature ? description : NULL,
			    cd->u.verity.fec_device,
			    &cd->u.verity.hdr, flags | CRYPT_ACTIVATE_READONLY);

	if (!r) {
		cd->u.verity.root_hash_size = volume_key_size;
		cd->u.verity.root_hash = malloc(volume_key_size);
		if (cd->u.verity.root_hash)
			memcpy(CONST_CAST(void*)cd->u.verity.root_hash, volume_key, volume_key_size);
	}

	if (signature)
		crypt_drop_keyring_key_by_description(cd, description, USER_KEY);

	return r;
}