// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package hwsec

import (
	"context"
	"reflect"
	"sort"
	"time"

	"chromiumos/tast/common/hwsec"
	"chromiumos/tast/errors"
	"chromiumos/tast/remote/bundles/cros/hwsec/util"
	hwsecremote "chromiumos/tast/remote/hwsec"
	"chromiumos/tast/testing"
	"chromiumos/tast/testing/hwdep"
)

func init() {
	testing.AddTest(&testing.Test{
		Func: CryptohomeKeysAndMountValidity,
		Desc: "Checks that the mount and keys related APIs works",
		Contacts: []string{
			"zuan@chromium.org", // Test author
			"cros-hwsec@google.com",
		},
		Attr:         []string{"group:hwsec_destructive_func"},
		SoftwareDeps: []string{"tpm", "reboot"},
		// Skip "enguarde" due to the reboot issue when removing the key. Please see b/151057300.
		HardwareDeps: hwdep.D(hwdep.SkipOnModel("enguarde")),
		Timeout:      15 * time.Minute,
	})
}

// unmountTestVault is a helper function that unmount the test vault. It expects
// the test vault to be mounted when it is called.
func unmountTestVault(ctx context.Context, utility *hwsec.CryptohomeClient) error {
	if _, err := utility.Unmount(ctx, util.FirstUsername); err != nil {
		return errors.Wrap(err, "failed to unmount vault")
	}
	if err := checkMountState(ctx, utility, false); err != nil {
		return errors.Wrap(err, "vault still mounted after unmount")
	}
	return nil
}

// checkMountState is a helper function that returns an error if the result
// from IsMounted() is not equal to expected, or if we've problem calling
// IsMounted().
func checkMountState(ctx context.Context, utility *hwsec.CryptohomeClient, expected bool) error {
	actuallyMounted, err := utility.IsMounted(ctx)
	if err != nil {
		return errors.Wrap(err, "failed to call IsMounted()")
	}
	if actuallyMounted != expected {
		return errors.Errorf("incorrect IsMounted() state %t, expected %t", actuallyMounted, expected)
	}
	return nil
}

// checkKeysLabels checks if the list of key labels matches target and returns
// an error if it doesn't.
func checkKeysLabels(ctx context.Context, utility *hwsec.CryptohomeClient, target []string) error {
	labels, err := utility.ListVaultKeys(ctx, util.FirstUsername)
	if err != nil {
		return errors.Wrap(err, "failed to list keys")
	}
	// Sort and compare the actual and expected keys.
	sort.Strings(labels)
	sortedTarget := make([]string, len(target))
	copy(sortedTarget, target)
	sort.Strings(sortedTarget)

	if !reflect.DeepEqual(labels, sortedTarget) {
		return errors.Errorf("mismatch result from list keys, got %q, expected %q", labels, sortedTarget)
	}

	return nil
}

// testCheckKeyEx tests that CheckKeyEx() works as expected.
func testCheckKeyEx(ctx context.Context, utility *hwsec.CryptohomeClient, username, label, correctPassword, incorrectPassword string) error {
	// CheckKeyEx should work with the correct password.
	result, err := utility.CheckVault(ctx, label, hwsec.NewPassAuthConfig(username, correctPassword))
	if err != nil {
		return errors.Wrap(err, "call to CheckKeyEx with the correct username and password resulted in an error")
	}
	if !result {
		return errors.New("failed to CheckKeyEx() with the correct username and password")
	}

	// CheckKeyEx should fail with the incorrect password.
	result, err = utility.CheckVault(ctx, label, hwsec.NewPassAuthConfig(username, incorrectPassword))
	if err == nil {
		return errors.New("call to CheckKeyEx() is successful with incorrect password ")
	}
	if result {
		return errors.New("incorrect password passed CheckKeyEx()")
	}

	return nil
}

// testListKeysEx tests that ListKeysEx() in cryptohome's API works as expected.
func testListKeysEx(ctx context.Context, utility *hwsec.CryptohomeClient) error {
	// ListKeysEx should show the keys that are in stock.
	if err := checkKeysLabels(ctx, utility, []string{util.Password1Label}); err != nil {
		return errors.Wrap(err, "list of keys is incorrect")
	}

	return nil
}

// testAddRemoveKeyEx tests that AddKeyEx() and RemoveKeyEx() work as expected.
func testAddRemoveKeyEx(ctx context.Context, utility *hwsec.CryptohomeClient) error {
	// AddKeyEx shouldn't work if password is incorrect.
	if err := utility.AddVaultKey(ctx, util.FirstUsername, util.IncorrectPassword, util.Password1Label, util.FirstPassword2, util.Password2Label, false); err == nil {
		return errors.New("add key succeeded when it shouldn't")
	}

	// AddKey should work if everything is correct.
	if err := utility.AddVaultKey(ctx, util.FirstUsername, util.FirstPassword1, util.Password1Label, util.FirstPassword2, util.Password2Label, false); err != nil {
		return errors.Wrap(err, "failed to add keys")
	}
	if err := checkKeysLabels(ctx, utility, []string{util.Password1Label, util.Password2Label}); err != nil {
		return errors.Wrap(err, "list of keys is incorrect after adding key")
	}

	// Mount and unmount with the new key.
	if err := checkMountState(ctx, utility, false); err != nil {
		return errors.Wrap(err, "vault mounted before testing AddKeyEx")
	}
	if err := utility.MountVault(ctx, util.Password2Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstPassword2), false, hwsec.NewVaultConfig()); err != nil {
		return errors.Wrap(err, "failed to mount vault with the added key")
	}
	if err := checkMountState(ctx, utility, true); err != nil {
		return errors.Wrap(err, "vault not mounted after mounting with added key")
	}

	// CheckKeyEx should work correctly with both the new and old key.
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password1Label, util.FirstPassword1, util.IncorrectPassword); err != nil {
		return errors.Wrap(err, "old key malfunctions while mounted with added key")
	}
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password2Label, util.FirstPassword2, util.IncorrectPassword); err != nil {
		return errors.Wrap(err, "new key malfunctions while mounted with added key")
	}
	// Now unmount it.
	if err := unmountTestVault(ctx, utility); err != nil {
		return errors.Wrap(err, "failed to unmount")
	}

	// The old key should still work as expected.
	if err := utility.MountVault(ctx, util.Password1Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstPassword1), false, hwsec.NewVaultConfig()); err != nil {
		return errors.Wrap(err, "failed to mount vault with the old key after adding pin")
	}
	if err := checkMountState(ctx, utility, true); err != nil {
		return errors.Wrap(err, "vault not mounted after mounting with old key after adding new key")
	}
	// CheckKeyEx should work correctly with both the new and old key.
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password1Label, util.FirstPassword1, util.IncorrectPassword); err != nil {
		return errors.Wrap(err, "old key malfunctions while mounted with old key")
	}
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password2Label, util.FirstPassword2, util.IncorrectPassword); err != nil {
		return errors.Wrap(err, "new key malfunctions while mounted with old key")
	}
	if err := unmountTestVault(ctx, utility); err != nil {
		return errors.Wrap(err, "failed to unmount")
	}

	// RemoveKeyEx should work, and test everything is alright after removing the key.
	if err := utility.RemoveVaultKey(ctx, util.FirstUsername, util.FirstPassword1, util.Password2Label); err != nil {
		return errors.Wrap(err, "failed to remove key")
	}
	if err := utility.MountVault(ctx, util.Password2Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstPassword2), false, hwsec.NewVaultConfig()); err == nil {
		return errors.New("still can mount vault with removed key")
	}
	if err := checkMountState(ctx, utility, false); err != nil {
		return errors.Wrap(err, "vault mounted after unmounting and failed mount")
	}

	return nil
}

// testMigrateKeyEx tests that MigrateKeyEx() works correctly.
// Note: MigrateKeyEx() changes the vault password.
func testMigrateKeyEx(ctx context.Context, utility *hwsec.CryptohomeClient) error {
	// MigrateKeyEx should work, and check if both new and old password behave as expected.
	if err := utility.ChangeVaultPassword(ctx, util.FirstUsername, util.FirstPassword1, util.Password1Label, util.FirstChangedPassword); err != nil {
		return errors.Wrap(err, "failed to change vault password")
	}
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password1Label, util.FirstChangedPassword, util.FirstPassword1); err != nil {
		return errors.Wrap(err, "incorrect CheckKeyEx behaviour right after MigrateKeyEx")
	}
	if err := utility.MountVault(ctx, util.Password1Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstPassword1), false, hwsec.NewVaultConfig()); err == nil {
		return errors.New("still can mount vault with old password")
	}

	// Mount with new password and try MigrateKeyEx() again.
	if err := utility.MountVault(ctx, util.Password1Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstChangedPassword), false, hwsec.NewVaultConfig()); err != nil {
		return errors.Wrap(err, "failed to mount with new password")
	}
	if err := checkMountState(ctx, utility, true); err != nil {
		return errors.Wrap(err, "vault not mounted after mounting with changed password")
	}
	if err := utility.ChangeVaultPassword(ctx, util.FirstUsername, util.FirstChangedPassword, util.Password1Label, util.FirstPassword1); err != nil {
		return errors.Wrap(err, "failed to change vault password back when mounted")
	}
	if err := checkMountState(ctx, utility, true); err != nil {
		return errors.Wrap(err, "vault not mounted after changing password while mounted")
	}

	// Calling CheckKeyEx(), which tries to authenticate with the new secret,
	// should be effective immediately without a remount.
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password1Label, util.FirstPassword1, util.FirstChangedPassword); err != nil {
		return errors.Wrap(err, "incorrect CheckKeyEx behaviour right after password is changed back")
	}

	// The new secret should continue to work when we try to authenticate
	// through CheckKeyEx() API, even after we unmount.
	if err := unmountTestVault(ctx, utility); err != nil {
		return errors.Wrap(err, "failed to unmount")
	}
	if err := checkMountState(ctx, utility, false); err != nil {
		return errors.Wrap(err, "vault mounted after unmounting while testing MigrateKeyEx")
	}
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password1Label, util.FirstPassword1, util.FirstChangedPassword); err != nil {
		return errors.Wrap(err, "incorrect CheckKeyEx behaviour after the password is changed back")
	}

	return nil
}

// checkUserVault checks that the vault/keys related API works correctly.
func checkUserVault(ctx context.Context, utility *hwsec.CryptohomeClient) error {
	if err := testCheckKeyEx(ctx, utility, util.FirstUsername, util.Password1Label, util.FirstPassword1, util.IncorrectPassword); err != nil {
		return errors.Wrap(err, "test on CheckKeyEx failed")
	}

	if err := testListKeysEx(ctx, utility); err != nil {
		return errors.Wrap(err, "test on ListKeysEx failed")
	}

	if err := testAddRemoveKeyEx(ctx, utility); err != nil {
		return errors.Wrap(err, "test on AddKeyEx/RemoveKeyEx failed")
	}

	if err := testMigrateKeyEx(ctx, utility); err != nil {
		return errors.Wrap(err, "test on MigrateKeyEx failed")
	}

	return nil
}

// CryptohomeKeysAndMountValidity exercizes and tests the correctness of
// cryptohome's key and vault related APIs when the DUT goes through
// various states (ownership not taken, ownership taken, after reboot).
func CryptohomeKeysAndMountValidity(ctx context.Context, s *testing.State) {
	r := hwsecremote.NewCmdRunner(s.DUT())
	helper, err := hwsecremote.NewHelper(r, s.DUT())
	if err != nil {
		s.Fatal("Helper creation error: ", err)
	}
	utility := helper.CryptohomeClient()

	s.Log("Start resetting TPM if needed")
	if err := helper.EnsureTPMAndSystemStateAreReset(ctx); err != nil {
		s.Fatal("Failed to ensure resetting TPM: ", err)
	}
	s.Log("TPM is confirmed to be reset")

	// Create the user and check it is correctly mounted and can be unmounted.
	func() {
		if err := utility.MountVault(ctx, util.Password1Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstPassword1), true, hwsec.NewVaultConfig()); err != nil {
			s.Fatal("Failed to create user: ", err)
		}
		// Unmount within this closure, because we want to have the thing
		// unmounted for checkUserVault() to work.
		defer func() {
			if err := unmountTestVault(ctx, utility); err != nil {
				s.Fatal("Failed to unmount: ", err)
			}
		}()

		if err := checkMountState(ctx, utility, true); err != nil {
			s.Fatal("Vault is not mounted: ", err)
		}
	}()

	// Cleanup the created vault.
	defer func() {
		// Remove the vault then verify that it's not mountable and that nothing is mounted.
		if _, err := utility.RemoveVault(ctx, util.FirstUsername); err != nil {
			s.Fatal("Failed to remove vault: ", err)
		}
		if err := utility.MountVault(ctx, util.Password1Label, hwsec.NewPassAuthConfig(util.FirstUsername, util.FirstPassword1), false, hwsec.NewVaultConfig()); err == nil {
			s.Fatal("Still can mount vault after removing vault: ")
		}
		if err := checkMountState(ctx, utility, false); err != nil {
			s.Fatal(err, "Vault mounted after removing vault: ")
		}
	}()

	// Take ownership, confirming the vault state before and afterwards.
	if err := checkUserVault(ctx, utility); err != nil {
		s.Fatal("Check user failed: ", err)
	}
	if err := helper.EnsureTPMIsReady(ctx, hwsec.DefaultTakingOwnershipTimeout); err != nil {
		s.Fatal("Time out waiting for TPM to be ready: ", err)
	}
	if err := checkUserVault(ctx, utility); err != nil {
		s.Fatal("Check user failed: ", err)
	}

	// Reboot then confirm vault status.
	if err := helper.Reboot(ctx); err != nil {
		s.Fatal("Failed to reboot: ", err)
	}
	if err := checkUserVault(ctx, utility); err != nil {
		s.Fatal("Check user failed: ", err)
	}
}
