text: // Copyright (c) 2012 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.
  
  #ifndef CRYPTOHOME_VAULT_KEYSET_H_
  #define CRYPTOHOME_VAULT_KEYSET_H_
  
  #include <memory>
  #include <optional>
  #include <string>
  
  #include <base/compiler_specific.h>
  #include <base/files/file_path.h>
  #include <base/gtest_prod_util.h>
  #include <brillo/secure_blob.h>
  
  #include "cryptohome/auth_blocks/auth_block_state.h"
  #include "cryptohome/crypto.h"
  #include "cryptohome/crypto_error.h"
  #include "cryptohome/cryptohome_common.h"
  #include "cryptohome/key_objects.h"
  #include "cryptohome/storage/file_system_keyset.h"
  #include "cryptohome/vault_keyset.pb.h"
  
  namespace cryptohome {
  
  class Crypto;
  class FileSystemKeyset;
  class Platform;
  
  // VaultKeyset holds the File Encryption Key (FEK) and File Name Encryption Key
  // (FNEK) and their corresponding signatures.
  class VaultKeyset {
   public:
    // Constructors and destructors.
    VaultKeyset();
    VaultKeyset(VaultKeyset&&) = default;
    VaultKeyset(const VaultKeyset&) = default;
    VaultKeyset& operator=(const VaultKeyset&) = default;
    virtual ~VaultKeyset();
  
    // Does not take ownership of platform and crypto. The objects pointed to by
    // them must outlive this object.
    virtual void Initialize(Platform* platform, Crypto* crypto);
  
    // Populates the fields from a SerializedVaultKeyset.
    void InitializeFromSerialized(const SerializedVaultKeyset& serialized);
  
    // Populates the fields from a Vaultkeyset to add a new key for the user.
    virtual void InitializeToAdd(const VaultKeyset& vault_keyset);
  
    //  The following methods deal with importing another object type into this
    //  VaultKeyset container.
    virtual void FromKeys(const VaultKeysetKeys& keys);
    virtual bool FromKeysBlob(const brillo::SecureBlob& keys_blob);
  
    // The following two methods export this VaultKeyset container to other
    // objects.
    virtual bool ToKeys(VaultKeysetKeys* keys) const;
    virtual bool ToKeysBlob(brillo::SecureBlob* keys_blob) const;
  
    // Do not call Load directly, use KeysetManagement::LoadVaultKeysetForUser.
    virtual bool Load(const base::FilePath& filename);
  
    // Encrypt must be called first.
    virtual bool Save(const base::FilePath& filename);
  
    // Load must be called first. |crypto_error| may be null.
    // Decrypts the encrypted fields of the VaultKeyset from serialized with the
    // KeyBlobs derived from the provided |key|.
    virtual bool Decrypt(const brillo::SecureBlob& key,
                         bool is_pcr_extended,
                         CryptoError* crypto_error);
  
    // Load must be called first. |crypto_error| may be null.
    // Decrypts the encrypted fields of the VaultKeyset from serialized with the
    // provided |key_blobs|.
    virtual bool DecryptEx(const KeyBlobs& key_blobs, CryptoError* crypto_error);
  
    // Encrypts the VaultKeyset fields with the KeyBlobs derived from the provided
    // |key| for the |obfuscated_username|.
    virtual bool Encrypt(const brillo::SecureBlob& key,
                         const std::string& obfuscated_username);
  
    // Encrypts the VaultKeyset fields with the provided |key_blobs| based on the
    // encryption mechanisms provided by the |auth_state|.
    virtual bool EncryptEx(const KeyBlobs& key_blobs,
                           const AuthBlockState& auth_state);
  
    // Convenience methods to initialize a new VaultKeyset with random values.
    virtual void CreateRandomChapsKey();
    virtual void CreateRandomResetSeed();
    virtual void CreateFromFileSystemKeyset(
        const FileSystemKeyset& file_system_keyset);
  
    // Methods to access runtime class state.
    virtual const base::FilePath& GetSourceFile() const;
  
    virtual void SetAuthLocked(bool locked);
    virtual bool GetAuthLocked() const;
  
    // Group 1. Methods to access plaintext metadata as stored in AuthBlockState.
    // Returns the SerializedVaultKeyset flags.
    virtual int32_t GetFlags() const;
    virtual void SetFlags(int32_t flags);
  
    // Getters and setters for the index. See the |legacy_index_| member for a
    // comment explaining the legacy name.
    virtual void SetLegacyIndex(int index);
    virtual const int GetLegacyIndex() const;
  
    virtual bool HasTpmPublicKeyHash() const;
    virtual const brillo::SecureBlob& GetTpmPublicKeyHash() const;
    virtual void SetTpmPublicKeyHash(const brillo::SecureBlob& hash);
  
    virtual bool HasPasswordRounds() const;
    virtual int32_t GetPasswordRounds() const;
  
    // TODO(b/205759690, dlunev): can be removed after a stepping stone release.
    virtual bool HasLastActivityTimestamp() const;
    virtual int64_t GetLastActivityTimestamp() const;
  
    virtual bool HasKeyData() const;
    virtual void SetKeyData(const KeyData& key_data);
    virtual void ClearKeyData();
    virtual const KeyData& GetKeyData() const;
  
    // Gets the label from the KeyData.
    virtual std::string GetLabel() const;
  
    // Checks the key data policy for low entropy credential (not the flags).
    virtual bool IsLECredential() const;
  
    // Populates the le cred policy field in |key_data_|. |key_data_| is created
    // if empty. An LE credential is a PinWeaver credential.
    virtual void SetLowEntropyCredential(bool is_le_cred);
  
    // Checks the flags field if this is a signature challenge credential.
    virtual bool IsSignatureChallengeProtected() const;
  
    // Sets the label on |key_data_|. |key_data_| is created if empty.
    virtual void SetKeyDataLabel(const std::string& key_label);
  
    virtual void SetResetIV(const brillo::SecureBlob& iv);
    virtual bool HasResetIV() const;
    virtual const brillo::SecureBlob& GetResetIV() const;
  
    virtual void SetLELabel(uint64_t label);
    virtual bool HasLELabel() const;
    virtual uint64_t GetLELabel() const;
  
    virtual void SetLEFekIV(const brillo::SecureBlob& iv);
    virtual bool HasLEFekIV() const;
    virtual const brillo::SecureBlob& GetLEFekIV() const;
  
    virtual void SetLEChapsIV(const brillo::SecureBlob& iv);
    virtual bool HasLEChapsIV() const;
    virtual const brillo::SecureBlob& GetLEChapsIV() const;
  
    virtual void SetResetSalt(const brillo::SecureBlob& reset_salt);
    virtual bool HasResetSalt() const;
    virtual const brillo::SecureBlob& GetResetSalt() const;
  
    virtual void SetFSCryptPolicyVersion(int32_t policy_version);
    virtual bool HasFSCryptPolicyVersion() const;
    virtual int32_t GetFSCryptPolicyVersion() const;
  
    // Group 2. Fields containing wrapped data.
  
    virtual void SetWrappedKeyset(const brillo::SecureBlob& wrapped_keyset);
    virtual const brillo::SecureBlob& GetWrappedKeyset() const;
  
    virtual bool HasWrappedChapsKey() const;
    virtual void SetWrappedChapsKey(const brillo::SecureBlob& wrapped_chaps_key);
    virtual const brillo::SecureBlob& GetWrappedChapsKey() const;
    virtual void ClearWrappedChapsKey();
  
    virtual bool HasTPMKey() const;
    virtual void SetTPMKey(const brillo::SecureBlob& tpm_key);
    virtual const brillo::SecureBlob& GetTPMKey() const;
  
    virtual bool HasExtendedTPMKey() const;
    virtual void SetExtendedTPMKey(const brillo::SecureBlob& tpm_key);
    virtual const brillo::SecureBlob& GetExtendedTPMKey() const;
  
    virtual bool HasWrappedResetSeed() const;
    virtual void SetWrappedResetSeed(const brillo::SecureBlob& reset_seed);
    virtual const brillo::SecureBlob& GetWrappedResetSeed() const;
  
    virtual bool HasSignatureChallengeInfo() const;
    virtual const SerializedVaultKeyset::SignatureChallengeInfo&
    GetSignatureChallengeInfo() const;
    virtual void SetSignatureChallengeInfo(
        const SerializedVaultKeyset::SignatureChallengeInfo& info);
  
    // Group 3. Unwrapped data.
  
    virtual const brillo::SecureBlob& GetFek() const;
    virtual const brillo::SecureBlob& GetFekSig() const;
    virtual const brillo::SecureBlob& GetFekSalt() const;
    virtual const brillo::SecureBlob& GetFnek() const;
    virtual const brillo::SecureBlob& GetFnekSig() const;
    virtual const brillo::SecureBlob& GetFnekSalt() const;
  
    virtual void SetChapsKey(const brillo::SecureBlob& chaps_key);
    virtual const brillo::SecureBlob& GetChapsKey() const;
    virtual void ClearChapsKey();
  
    virtual void SetResetSeed(const brillo::SecureBlob& reset_seed);
    virtual const brillo::SecureBlob& GetResetSeed() const;
  
    virtual void SetResetSecret(const brillo::SecureBlob& reset_secret);
    virtual const brillo::SecureBlob& GetResetSecret() const;
  
    // This populates each sub type of AuthBlockState into the caller allocated
    // object.
    bool GetTpmBoundToPcrState(AuthBlockState* auth_state) const;
    bool GetTpmNotBoundToPcrState(AuthBlockState* auth_state) const;
    bool GetPinWeaverState(AuthBlockState* auth_state) const;
    bool GetSignatureChallengeState(AuthBlockState* auth_state) const;
    bool GetLibScryptCompatState(AuthBlockState* auth_state) const;
    bool GetDoubleWrappedCompatState(AuthBlockState* auth_state) const;
    bool GetTpmEccState(AuthBlockState* auth_state) const;
  
    // Reads an auth block state and update the VaultKeyset with what it
    // returns.
    void SetAuthBlockState(const AuthBlockState& auth_state);
  
    // Set each type of AuthBlockState's sub messages.
    void SetTpmNotBoundToPcrState(
        const TpmNotBoundToPcrAuthBlockState& auth_state);
    void SetTpmBoundToPcrState(const TpmBoundToPcrAuthBlockState& auth_state);
    void SetPinWeaverState(const PinWeaverAuthBlockState& auth_state);
    void SetLibScryptCompatState(const LibScryptCompatAuthBlockState& auth_state);
    void SetChallengeCredentialState(
        const ChallengeCredentialAuthBlockState& auth_state);
    void SetTpmEccState(const TpmEccAuthBlockState& auth_state);
  
    // Generates a random blob to be used as reset secret for LE Credentials.
    std::optional<brillo::SecureBlob> GetOrGenerateResetSecret();
  
   private:
    // Converts the class to a protobuf for serialization to disk.
    SerializedVaultKeyset ToSerialized() const;
  
    // Clears all the fields set from the SerializedVaultKeyset.
    void ResetVaultKeyset();
  
    // This function serves as a factory method to return the authblock used in
    // authentication creation.
    std::unique_ptr<SyncAuthBlock> GetAuthBlockForCreation() const;
  
    // This function serves as a factory method to return the authblock used in
    // authentication derivation. The type of the AuthBlock is determined based on
    // |flags_|.which derived from vault keyset.
    std::unique_ptr<SyncAuthBlock> GetAuthBlockForDerivation();
  
    // This function decrypts a keyset that is encrypted with a VaultKeysetKey.
    //
    // Parameters
    //   serialized - The serialized vault keyset protobuf.
    //   vkk_data - Key data includes the VaultKeysetKey to decrypt the serialized
    // keyset.
    //   error (OUT) - The specific error code on failure.
    bool UnwrapVKKVaultKeyset(const SerializedVaultKeyset& serialized,
                              const KeyBlobs& vkk_data,
                              CryptoError* error);
  
    // This function decrypts a keyset that is encrypted with an scrypt derived
    // key.
    //
    // Parameters
    //   serialized - The serialized vault keyset protobuf.
    //   vkk_data - Key data that includes the scrypt derived keys.
    //   error (OUT) - The specific error code on failure.
    bool UnwrapScryptVaultKeyset(const SerializedVaultKeyset& serialized,
                                 const KeyBlobs& vkk_data,
                                 CryptoError* error);
  
    // This function encrypts a keyset with a VaultKeysetKey.
    //
    // Parameters
    //   key_blobs - Key bloc that stores VaultKeysetKey.
    bool WrapVaultKeysetWithAesDeprecated(const KeyBlobs& blobs);
  
    // This function encrypts a VaultKeyset with an scrypt derived key.
    //
    // Parameters
    //   key_blobs - Key blob that stores scrypt derived keys.
    bool WrapScryptVaultKeyset(const KeyBlobs& key_blobs);
  
    // This function consumes the Vault Keyset Key (VKK) and IV, and produces
    // the unwrapped secrets from the Vault Keyset.
    //
    // Parameters
    //   serialized - The serialized vault keyset protobuf.
    //   vkk_data - The VKK and the VKK IV.
    //   error (OUT) - The specific error code on failure.
    bool UnwrapVaultKeyset(const SerializedVaultKeyset& serialized,
                           const KeyBlobs& vkk_data,
                           CryptoError* error);
  
    // Decrypts an encrypted vault keyset which is obtained from the unwrapped
    // secrets returned from UnwrapVaultKeyset() using the key_blobs.
    //
    // Parameters
    //   key_blobs - KeyBlobs to decrypt serialized VaultKeyset.
    //   error(OUT) - The specific error code on failure.
    bool DecryptVaultKeysetEx(const KeyBlobs& key_blobs, CryptoError* error);
  
    // Decrypts an encrypted vault keyset which is obtained from the unwrapped
    // secrets returned from UnwrapVaultKeyset().
    //
    // Parameters
    //   vault_key - The passkey used to decrypt the keyset.
    //   locked_to_single_user - Whether the device has transitioned.
    //   into user-specific modality by extending PCR4 with a user-specific
    //   value.
    //   error(OUT) - The specific error code on failure.
    bool DecryptVaultKeyset(const brillo::SecureBlob& vault_key,
                            bool locked_to_single_user,
                            CryptoError* error);
  
    // Encrypts the vault keyset with the given passkey
    //
    // Parameters
    //   vault_key - The passkey used to encrypt the keyset.
    //   obfuscated_username - The value of username obfuscated. It's the same
    //                         value used as the folder name where the user data
    //                         is stored.
    //   auth_block_state - On success, the plaintext state needed to initialize
    //                      the auth block.
    bool EncryptVaultKeyset(const brillo::SecureBlob& vault_key,
                            const std::string& obfuscated_username,
                            AuthBlockState* auth_block_state);
  
    // These store run time state for the class.
    Platform* platform_;
    Crypto* crypto_;
    bool loaded_;
    bool encrypted_;
    base::FilePath source_file_;
  
    // The following data members are grouped into three categories. Each category
    // should be split into a separate object in the future.
  
    // Group 1. AuthBlockState. This is metadata used to derive the keys,
    // persisted as plaintext.
    int32_t flags_;
    // The salt used to derive the user input in auth block.
    brillo::SecureBlob auth_salt_;
    // The IV used to encrypt the encryption key.
    std::optional<brillo::SecureBlob> vkk_iv_;
    // legacy_index_ is the index of the keyset for the user. It is called legacy
    // due to previous plans to fully switch to label-based addressing, which,
    // unfortunately, wasn't followed through.
    // TODO(dlunev): rename it not to say legacy.
    int legacy_index_;
    bool auth_locked_;
    // This is used by the TPM AuthBlocks to make sure the keyset was sealed to
    // the TPM on this system. It's not a security check, but a diagnostic.
    std::optional<brillo::SecureBlob> tpm_public_key_hash_;
    // Passwords which are TPM backed, not PCR bound, and not run through scrypt
    // before the TPM operation, have a number of rounds to run the key derivation
    // function.
    std::optional<int32_t> password_rounds_;
    // An optional timestamp field.
    // TODO(b/205759690, dlunev): can be removed after a stepping stone release.
    std::optional<int64_t> last_activity_timestamp_;
    // Plaintet metadata describing the key.
    std::optional<KeyData> key_data_;
    // Used for the reset seed wrapping.
    std::optional<brillo::SecureBlob> reset_iv_;
    // The label for PinWeaver secrets.
    std::optional<uint64_t> le_label_;
    // IV for the file encryption key of PinWeaver credentials.
    std::optional<brillo::SecureBlob> le_fek_iv_;
    // IV for the chaps key wrapping of PinWeaver credentials.
    std::optional<brillo::SecureBlob> le_chaps_iv_;
    // Used with the resed seed to derive the reset secret. PinWeaver only.
    std::optional<brillo::SecureBlob> reset_salt_;
    // Specifies which version of fscrypt encryption policy this is used with.
    std::optional<int32_t> fscrypt_policy_version_;
  
    // Group 2. Wrapped stuff.
    // An encrypted copy of the VaultKeysetKeys struct, which holds important
    // fields such as a the file encryption key.
    brillo::SecureBlob wrapped_keyset_;
    // Wrapped copy of the key used to authenticate with the PKCS#11 service.
    std::optional<brillo::SecureBlob> wrapped_chaps_key_;
    // The VaultKeysetKey encrypted with the user's password and TPM.
    std::optional<brillo::SecureBlob> tpm_key_;
    // Used by the PCR bound AuthBlock where the TPM's PCR is extended with the
    // username.
    std::optional<brillo::SecureBlob> extended_tpm_key_;
    // The reset seed for LE credentials.
    std::optional<brillo::SecureBlob> wrapped_reset_seed_;
    // Information specific to the signature-challenge response protection. This
    // has plaintext metadata in it, but also the sealed secret, so it goes here.
    std::optional<SerializedVaultKeyset::SignatureChallengeInfo>
        signature_challenge_info_;
  
    // Group 3. Unwrapped secrets.
    // The file encryption key present in all VaultKeysets.
    brillo::SecureBlob fek_;
    // Randomly generated key identifier.
    brillo::SecureBlob fek_sig_;
    // Randomly generated salt for use with the file encryption key.
    brillo::SecureBlob fek_salt_;
    // The file name encryption key present in dircrypto, not fscrypt keysets.
    brillo::SecureBlob fnek_;
    // Randomly generated key identifier for the |fnek_|.
    brillo::SecureBlob fnek_sig_;
    // Randomly generated salt for use with the file name encryption key.
    brillo::SecureBlob fnek_salt_;
    // Unwrapped key used for PKCS#11 operations.
    brillo::SecureBlob chaps_key_;
    // The seed mixed with the salt to derive the reset secret.
    brillo::SecureBlob reset_seed_;
    // Used by LECredentials only.
    brillo::SecureBlob reset_secret_;
  
    // With the SerializedVaultKeyset properly abstracted by VaultKeyset, Crypto
    // should really be folded into VaultKeyset class. But this amount of
    // refactoring for legacy code is undesirable, so it is made a friend class.
    friend class Crypto;
  
    FRIEND_TEST_ALL_PREFIXES(CryptoTest, TpmStepTest);
    FRIEND_TEST_ALL_PREFIXES(CryptoTest, Tpm1_2_StepTest);
    FRIEND_TEST_ALL_PREFIXES(CryptoTest, TpmDecryptFailureTest);
    FRIEND_TEST_ALL_PREFIXES(CryptoTest, ScryptStepTest);
    FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, Decrypt);
    FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, Encrypt);
    FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, DecryptWithKeyBlobs);
    FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, EncryptWithKeyBlobs);
    FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, EncryptFail);
    FRIEND_TEST_ALL_PREFIXES(LeCredentialsManagerTest, EncryptTestReset);
    FRIEND_TEST_ALL_PREFIXES(VaultKeysetTest, GetEccAuthBlockStateTest);
    FRIEND_TEST_ALL_PREFIXES(VaultKeysetTest, EncryptionTest);
    FRIEND_TEST_ALL_PREFIXES(VaultKeysetTest, DecryptionTest);
    FRIEND_TEST_ALL_PREFIXES(VaultKeysetTest, LibScryptBackwardCompatibility);
    FRIEND_TEST_ALL_PREFIXES(KeysetManagementTest, AddInitialKeyset);
    FRIEND_TEST_ALL_PREFIXES(KeysetManagementTest, AddResetSeed);
    FRIEND_TEST_ALL_PREFIXES(KeysetManagementTest, AddWrappedResetSeed);
  };
  
  }  // namespace cryptohome
  
  #endif  // CRYPTOHOME_VAULT_KEYSET_H_
  