// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Sync protocol datatype extension for nigori keys.

// If you change or add any fields in this file, update proto_visitors.h and
// potentially proto_enum_conversions.{h, cc}.

syntax = "proto2";

option java_multiple_files = true;
option java_package = "org.chromium.components.sync.protocol";

option optimize_for = LITE_RUNTIME;

package sync_pb;

import "components/sync/protocol/encryption.proto";

message NigoriKey {
  // Note that M78 and before rely on the name being populated, at least for
  // the main encrypted keybag within NigoriSpecifics.
  optional string deprecated_name = 1 [deprecated = true];
  optional bytes deprecated_user_key = 2 [deprecated = true];
  optional bytes encryption_key = 3;
  optional bytes mac_key = 4;
}

message CrossUserSharingPrivateKey {
  // The key version, used for key rotation.
  optional int32 version = 1;
  // Private key on Curve25519 (32 bytes).
  // Encryption: Hybrid Public Key Encryption (HPKE)
  // KEM: DHKEM_X25519_HKDF_SHA256
  // KDF: HKDF_SHA256
  // AEAD: CHACHA20_POLY1305
  optional bytes x25519_private_key = 2;
}

message CrossUserSharingPublicKey {
  // The key version, used for key rotation and consensus.
  optional int32 version = 1;
  // Public key on Curve25519 (32 bytes).
  // Encryption: Hybrid Public Key Encryption (HPKE)
  // KEM: DHKEM_X25519_HKDF_SHA256
  // KDF: HKDF_SHA256
  // AEAD: CHACHA20_POLY1305
  optional bytes x25519_public_key = 2;
}

message EncryptionKeys {
  // Used for encrypting data in the user's account.
  repeated NigoriKey key = 2;
  // Used for encrypting/authenticating using Public-private cryptography
  // primarily across user accounts, e.g. sharing invitations.
  repeated CrossUserSharingPrivateKey cross_user_sharing_private_key = 3;
}

// Deprecated: use EncryptionKeys instead.
message NigoriKeyBag {
  option deprecated = true;

  // Used for encrypting data in the user's account.
  repeated NigoriKey key = 2;
}

// Information about the experiment group to auto-upgrade users to trusted vault
// passphrase type.
message TrustedVaultAutoUpgradeExperimentGroup {
  // ID of cohort account belongs to. An integer within the range [1, 99].
  optional int32 cohort = 1;

  // Within each cohort, there are multiple experiment groups, and each group
  // has an associated type.
  enum Type {
    TYPE_UNSPECIFIED = 0;
    TREATMENT = 1;
    CONTROL = 2;
    VALIDATION = 3;
  }

  optional Type type = 2;

  // For each cohort and group type, there may be zero, one or more groups.
  // To support the case where two or more exists, the index below can be used.
  // This is primarily intended for validation groups.
  optional int32 type_index = 3;
}

// Properties of nigori sync object.
message NigoriSpecifics {
  // Encrypted proto of type EncryptionKeys.
  optional EncryptedData encryption_keybag = 1;
  // Once keystore migration is performed, we have to freeze the keybag so that
  // older clients (that don't support keystore encryption) do not attempt to
  // update the keybag.
  // Previously `using_explicit_passphrase`.
  optional bool keybag_is_frozen = 2;

  // Obsolete encryption fields. These were deprecated due to legacy versions
  // that understand their usage but did not perform encryption properly.
  reserved 3;
  reserved "deprecated_encrypt_bookmarks";
  reserved 4;
  reserved "deprecated_encrypt_preferences";
  reserved 5;
  reserved "deprecated_encrypt_autofill_profile";
  reserved 6;
  reserved "deprecated_encrypt_autofill";
  reserved 7;
  reserved "deprecated_encrypt_themes";
  reserved 8;
  reserved "deprecated_encrypt_typed_urls";
  reserved 9;
  reserved "deprecated_encrypt_extensions";
  reserved 10;
  reserved "deprecated_encrypt_sessions";
  reserved 11;
  reserved "deprecated_encrypt_apps";
  reserved 12;
  reserved "deprecated_encrypt_search_engines";
  reserved 13;
  reserved "encrypt_bookmarks";
  reserved 14;
  reserved "encrypt_preferences";
  reserved 15;
  reserved "encrypt_autofill_profile";
  reserved 16;
  reserved "encrypt_autofill";
  reserved 17;
  reserved "encrypt_themes";
  reserved 18;
  reserved "encrypt_typed_urls";
  reserved 19;
  reserved "encrypt_extensions";
  reserved 20;
  reserved "encrypt_sessions";
  reserved 21;
  reserved "encrypt_apps";
  reserved 22;
  reserved "encrypt_search_engines";

  // Deprecated on clients where tab sync is enabled by default.
  reserved 23;
  reserved "sync_tabs";

  // If true, all current and future datatypes will be encrypted.
  optional bool encrypt_everything = 24;

  // Obsolete encryption fields.
  reserved 25;
  reserved "encrypt_extension_settings";
  reserved 26;
  reserved "encrypt_app_notifications";
  reserved 27;
  reserved "encrypt_app_settings";

  // User device information. Contains information about each device that has a
  // sync-enabled Chrome browser connected to the user account.
  // This has been moved to the DeviceInfo message.
  reserved 28;
  reserved "deprecated_device_information";

  // Enable syncing favicons as part of tab sync.
  optional bool sync_tab_favicons = 29;

  // The state of the passphrase required to decrypt `encryption_keybag`.
  enum PassphraseType {
    // Proto enums should begin with an 'unknown' value for switch statements,
    // unknown fields, etc.
    UNKNOWN = 0;
    // Gaia-based encryption passphrase. Legacy.
    IMPLICIT_PASSPHRASE = 1;
    // Keystore key encryption passphrase. Uses `keystore_bootstrap` to
    // decrypt `encryption_keybag`.
    KEYSTORE_PASSPHRASE = 2;
    // Previous Gaia-based passphrase frozen and treated as a custom passphrase.
    FROZEN_IMPLICIT_PASSPHRASE = 3;
    // User provided custom passphrase.
    CUSTOM_PASSPHRASE = 4;
    // Encryption key provided by a trusted vault.
    TRUSTED_VAULT_PASSPHRASE = 5;
  }

  // An `int` field is used instead of enum PassphraseType so we can better
  // handle unknown values coming from later versions. Prior to M77, this was an
  // enum so old clients will assume IMPLICIT_PASSPHRASE for values greater than
  // 4.
  optional int32 passphrase_type = 30 [default = 1];

  // The keystore decryptor token blob. Encrypted with the keystore key, and
  // contains the encryption key used to decrypt `encryption_keybag`.
  // Only set if passphrase_state == KEYSTORE_PASSPHRASE.
  optional EncryptedData keystore_decryptor_token = 31;

  // The time (in milliseconds since Unix epoch) at which the keystore migration
  // was performed.
  optional int64 keystore_migration_time = 32;

  // The time (in milliseconds since Unix epoch) at which a custom passphrase
  // was set. Note: this field may not be set if the custom passphrase was
  // applied before this field was introduced.
  optional int64 custom_passphrase_time = 33;

  // Obsolete encryption fields.
  reserved 34;
  reserved "encrypt_dictionary";
  reserved 35;
  reserved 36;
  reserved 37;
  reserved "encrypt_articles";
  reserved 38;
  reserved "encrypt_app_list";
  reserved 39;
  reserved "encrypt_autofill_wallet_metadata";

  // Boolean indicating whether this node was originally missing a
  // `keystore_migration_time` field value, and was fixed on the server by
  // giving the field a value.
  // THIS FIELD SHOULD ONLY BE SET BY THE SERVER.
  optional bool server_only_was_missing_keystore_migration_time = 40;

  // Obsolete encryption fields.
  reserved 41;
  reserved "encrypt_arc_package";
  reserved 42;
  reserved "encrypt_printers";
  reserved 43;
  reserved "encrypt_reading_list";
  reserved 44;
  reserved "encrypt_mountain_shares";

  enum KeyDerivationMethod {
    // This comes from a <= M69 client, who does not know about the field
    // (but implicitly uses PBKDF2_HMAC_SHA1_1003).
    UNSPECIFIED = 0;
    // PBKDF2-HMAC-SHA1 with 1003 iterations and constant hardcoded salt. Was
    // implicitly used in <= M69.
    PBKDF2_HMAC_SHA1_1003 = 1;
    // scrypt with N = 2^13, r = 8, p = 11 and random salt. Was added in M70.
    SCRYPT_8192_8_11 = 2;
  }

  // ID of the method used to derive the encryption key from a custom
  // passphrase. Should be set only when `passphrase_type` is CUSTOM_PASSPHRASE
  // and only based on CustomPassphraseKeyDerivationMethod. This field has been
  // added in M70. All previous versions just ignore it, attempt to use
  // PBKDF2_HMAC_SHA1_1003 and, thus, reject any passphrase if a different
  // method has been used. The default corresponds to UNSPECIFIED. An `int`
  // field is used so we can detect unknown values coming from later versions.
  optional int32 custom_passphrase_key_derivation_method = 45 [default = 0];

  // Base64-encoded salt used for the derivation of the key from the custom
  // passphrase. Valid only if custom_passphrase_key_derivation_method ==
  // SCRYPT_8192_8_11, ignored in other cases.
  optional string custom_passphrase_key_derivation_salt = 46;

  // Obsolete encryption fields.
  reserved 47;
  reserved "encrypt_send_tab_to_self";
  reserved 48;
  reserved "encrypt_web_apps";
  reserved 49;
  reserved "encrypt_os_preferences";

  // Some debug-only fields for passphrase type TRUSTED_VAULT_PASSPHRASE.
  message TrustedVaultDebugInfo {
    // The time (in milliseconds since Unix epoch) at which the trusted vault
    // migration was performed.
    optional int64 migration_time = 1;

    // The version (aka key epoch) corresponding to the Nigori keybag.
    optional int32 key_version = 2;

    reserved 3, 4;

    // Experiment group assignment (if any) related to auto-upgrading users into
    // trusted vault passphrase.
    optional TrustedVaultAutoUpgradeExperimentGroup
        auto_upgrade_experiment_group = 5;

    // The time (in milliseconds since Unix epoch) last update of the auto
    // upgrade experiment group was made.
    optional int64
        auto_upgrade_experiment_group_modification_time_unix_epoch_millis = 6;
  }

  optional TrustedVaultDebugInfo trusted_vault_debug_info = 50;

  // Obsolete encryption fields.
  reserved 51;
  reserved "encrypt_workspace_desk";
  reserved 52;
  reserved "encrypt_printers_authorization_servers";

  // Current cross user sharing Public-key to expose in server registry
  // for sharing offers outside account boundary.
  optional CrossUserSharingPublicKey cross_user_sharing_public_key = 53;
}
