int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
	int keyslot, // -1 any
	const char *passphrase,
	size_t passphrase_size,
	const char *new_passphrase,
	size_t new_passphrase_size)
{
	int digest, r, active_slots;
	struct luks2_keyslot_params params;
	struct volume_key *vk = NULL;

	log_dbg(cd, "Adding new keyslot, existing passphrase %sprovided,"
		"new passphrase %sprovided.",
		passphrase ? "" : "not ", new_passphrase  ? "" : "not ");

	if ((r = onlyLUKS(cd)))
		return r;

	if (!passphrase || !new_passphrase)
		return -EINVAL;

	r = keyslot_verify_or_find_empty(cd, &keyslot);
	if (r)
		return r;

	if (isLUKS1(cd->type))
		active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr);
	else
		active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
	if (active_slots == 0) {
		/* No slots used, try to use pre-generated key in header */
		if (cd->volume_key) {
			vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key);
			r = vk ? 0 : -ENOMEM;
		} else {
			log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided."));
			return -EINVAL;
		}
	} else if (active_slots < 0)
		return -EINVAL;
	else {
		/* Passphrase provided, use it to unlock existing keyslot */
		if (isLUKS1(cd->type))
			r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, passphrase,
						   passphrase_size, &cd->u.luks1.hdr, &vk, cd);
		else
			r = LUKS2_keyslot_open(cd, CRYPT_ANY_SLOT, CRYPT_DEFAULT_SEGMENT, passphrase,
						passphrase_size, &vk);
	}

	if (r < 0)
		goto out;

	if (isLUKS1(cd->type))
		r = LUKS_set_key(keyslot, CONST_CAST(char*)new_passphrase,
				 new_passphrase_size, &cd->u.luks1.hdr, vk, cd);
	else {
		r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
		digest = r;

		if (r >= 0)
			r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, &params);

		if (r >= 0)
			r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0);

		if (r >= 0)
			r = LUKS2_keyslot_store(cd,  &cd->u.luks2.hdr, keyslot,
						CONST_CAST(char*)new_passphrase,
						new_passphrase_size, vk, &params);
	}

	if (r < 0)
		goto out;

	r = 0;
out:
	crypt_free_volume_key(vk);
	if (r < 0) {
		_luks2_reload(cd);
		return r;
	}
	return keyslot;
}
int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
	int keyslot,  
	const char *passphrase,
	size_t passphrase_size,
	const char *new_passphrase,
	size_t new_passphrase_size)
{
	int digest, r, active_slots;
	struct luks2_keyslot_params params;
	struct volume_key *vk = NULL;

	log_dbg(cd, "Adding new keyslot, existing passphrase %sprovided,"
		"new passphrase %sprovided.",
		passphrase ? "" : "not ", new_passphrase  ? "" : "not ");

	if ((r = onlyLUKS(cd)))
		return r;

	if (!passphrase || !new_passphrase)
		return -EINVAL;

	r = keyslot_verify_or_find_empty(cd, &keyslot);
	if (r)
		return r;

	if (isLUKS1(cd->type))
		active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr);
	else
		active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
	if (active_slots == 0) {
		 
		if (cd->volume_key) {
			vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key);
			r = vk ? 0 : -ENOMEM;
		} else {
			log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided."));
			return -EINVAL;
		}
	} else if (active_slots < 0)
		return -EINVAL;
	else {
		 
		if (isLUKS1(cd->type))
			r = LUKS_open_key_with_hdr(CRYPT_ANY_SLOT, passphrase,
						   passphrase_size, &cd->u.luks1.hdr, &vk, cd);
		else
			r = LUKS2_keyslot_open(cd, CRYPT_ANY_SLOT, CRYPT_DEFAULT_SEGMENT, passphrase,
						passphrase_size, &vk);
	}

	if (r < 0)
		goto out;

	if (isLUKS1(cd->type))
		r = LUKS_set_key(keyslot, CONST_CAST(char*)new_passphrase,
				 new_passphrase_size, &cd->u.luks1.hdr, vk, cd);
	else {
		r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
		digest = r;

		if (r >= 0)
			r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, &params);

		if (r >= 0)
			r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot, digest, 1, 0);

		if (r >= 0)
			r = LUKS2_keyslot_store(cd,  &cd->u.luks2.hdr, keyslot,
						CONST_CAST(char*)new_passphrase,
						new_passphrase_size, vk, &params);
	}

	if (r < 0)
		goto out;

	r = 0;
out:
	crypt_free_volume_key(vk);
	if (r < 0) {
		_luks2_reload(cd);
		return r;
	}
	return keyslot;
}