| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Definitions for calls to the CryptAuth back-end. The DeviceSync service |
| // performs two main functions: |
| // (1) Enroll (i.e., register) the Chromebook with the CryptAuth server by |
| // providing information about the device. |
| // (2) Download metadata about other devices associated with the user's |
| // account. |
| // |
| // This file defines the protocol messages and enums used to perform these RPCs. |
| syntax = "proto2"; |
| |
| package cryptauth; |
| |
| option optimize_for = LITE_RUNTIME; |
| |
| // Basic device information used to classify the source of a request. |
| message DeviceClassifier { |
| // The Operating System version number on the device. |
| // (e.g., an android.os.Build.VERSION.SDK_INT) |
| optional int64 device_os_version_code = 14; |
| |
| // The software version number running on the device |
| // (e.g., GmsCore version code). |
| optional int64 device_software_version_code = 18; |
| |
| // Software package information if applicable |
| // (e.g., com.google.android.apps.authenticator2). |
| optional string device_software_package = 19; |
| |
| // Device type/platform. |
| // TODO(khorimoto): Change this to a string so it works with Apiary endpoints. |
| optional DeviceType device_type = 32 [default = UNKNOWN]; |
| } |
| |
| enum DeviceType { |
| UNKNOWN = 0; |
| ANDROIDOS = 1; |
| CHROME = 2; |
| IOS = 3; |
| BROWSER = 4; |
| } |
| |
| // MultiDevice features which may be supported and enabled on a device. |
| enum SoftwareFeature { |
| UNKNOWN_FEATURE = 0; |
| BETTER_TOGETHER_HOST = 1; |
| BETTER_TOGETHER_CLIENT = 2; |
| EASY_UNLOCK_HOST = 3; |
| EASY_UNLOCK_CLIENT = 4; |
| MAGIC_TETHER_HOST = 5; |
| MAGIC_TETHER_CLIENT = 6; |
| SMS_CONNECT_HOST = 7; |
| SMS_CONNECT_CLIENT = 8; |
| } |
| |
| // A seed used to feed an EID BLE advertisement for some time period. This |
| // key is specific to the device being targeted by the advertisement. |
| // Next ID: 4 |
| message BeaconSeed { |
| // The actual key bytes. |
| optional bytes data = 1; |
| |
| // The time at which this key becomes active. |
| optional int64 start_time_millis = 2; |
| |
| // The time at which this key becomes inactive. |
| optional int64 end_time_millis = 3; |
| } |
| |
| // Device information provided to external clients that need to sync |
| // device state. |
| message ExternalDeviceInfo { |
| // A cryptographic public key associated with the device. |
| // The format of this key is a serialized SecureMessage.GenericPublicKey |
| // for all GCM_V1 devices. |
| optional bytes public_key = 1; |
| |
| // A user friendly (human readable) name for this device. |
| optional string friendly_device_name = 2; |
| |
| // If available, the device's bluetooth MAC address |
| optional string bluetooth_address = 3; |
| |
| // Whether or not this device can be used as an unlock key |
| optional bool unlock_key = 4 [default = false]; |
| |
| // Whether or not this device can be unlocked |
| optional bool unlockable = 5 [default = false]; |
| |
| // The last time this device updated its info with the server. |
| optional int64 last_update_time_millis = 6; |
| |
| // Whether or not this device hardware supports providing a mobile hotspot. |
| optional bool mobile_hotspot_supported = 7 [default = false]; |
| |
| // The type of the device (e.g. Android vs iOS). |
| // TODO(khorimoto): Change this to a string so it works with Apiary endpoints. |
| optional DeviceType device_type = 8 [default = UNKNOWN]; |
| |
| // A list of seeds for EID BLE advertisements targeting this device. |
| repeated BeaconSeed beacon_seeds = 9; |
| |
| // Whether this device is an ARC++ device enrolled via gmscore. |
| optional bool arc_plus_plus = 10 [default = false]; |
| |
| // Whether this is a "Pixel Experience" phone. |
| optional bool pixel_phone = 11 [default = false]; |
| |
| // A list of multi-device software features supported by the device. |
| repeated string supported_software_features = 12; |
| |
| // A list of multi-device software features currently enabled (active) on the |
| // device. |
| repeated string enabled_software_features = 13; |
| } |
| |
| // Determine if the calling device is allowed to promote the SmartLock |
| // feature to the user and contact the user's authzen enrolled devices to make |
| // them update their enrollments and to check if they're reachable (we don't |
| // want to show a promotional popup if the user has no reachable devices). |
| message FindEligibleForPromotionRequest { |
| // The public key of the device that is asking us whether it should show |
| // promotional material. Required. |
| optional bytes promoter_public_key = 2; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 3; |
| } |
| |
| // Contains the authzen transaction id that the caller can use to check if |
| // there are reachable devices. |
| message FindEligibleForPromotionResponse { |
| // Whether the caller is allowed to show promotional material. |
| optional bool may_show_promo = 1; |
| } |
| |
| // Request for a list of devices that could be used as Unlock Keys, optionally |
| // requesting a callback over bluetooth (for proximity detection). |
| message FindEligibleUnlockDevicesRequest { |
| // A bluetooth MAC address to be contacted if a device that may be eligible |
| // for unlock is nearby. If set, a message will be pushed to all eligible |
| // unlock devices requesting that they contact the specified MAC address. If |
| // this field is left unset, no callback will be made, and no message will be |
| // pushed to the user's devices. |
| optional string callback_bluetooth_address = 2; |
| |
| // During setup, we call find and sendDeviceSyncTickle. If no devices are |
| // found, we call find again, in hopes that the tickle caused a state |
| // change that made some device eligible. This is the count for these |
| // retries (in practice, this will always be 0 or 1). |
| // Should always be set. |
| optional int32 retry_count = 3; |
| |
| // If present and positive, the devices must have been updated within this |
| // many milliseconds of the RPC in order to be considered eligible. |
| optional int64 max_last_update_time_delta_millis = 4; |
| |
| // If true, we will not examine the push connectivity status of devices |
| // when determining eligibility. |
| optional bool offline_allowed = 5 [default = false]; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 6; |
| |
| // The version of the setup protocol that the calling device expects to use. |
| optional int32 protocol_version = 7; |
| |
| // The feature for which eligibility should be checked. Note that this RPC is |
| // overloaded instead of adding new RPCs due to the ongoing V2 transition. |
| // See go/unified-better-together-cryptauth for more details. |
| optional string feature = 8 [default = "easyUnlockHost"]; |
| } |
| |
| // Response containing a list of devices that could be made Unlock Keys |
| message FindEligibleUnlockDevicesResponse { |
| // Devices that could be made Unlock Keys (even if they aren't enabled yet) |
| repeated ExternalDeviceInfo eligible_devices = 1; |
| |
| // Devices that cannot be made unlock keys, and reasons for this. This list |
| // will not contain any non-gms core devices, even though these are also not |
| // eligible to be unlock keys. |
| repeated IneligibleDevice ineligible_devices = 2; |
| } |
| |
| // Request to complete a device enrollment. |
| message FinishEnrollmentRequest { |
| // The enrollment session identifer from the <code>setup</code> response. |
| optional bytes enrollment_session_id = 2; |
| |
| // An encrypted payload containing enrollment information for the device. |
| optional bytes enrollment_message = 3; |
| |
| // A Diffie-Hellman public key for the device, to complete the key exchange. |
| optional bytes device_ephemeral_key = 4; |
| |
| // An integer encoding the reason this enrollment was invoked (triggered). |
| // See InvocationReason enum for definitions. |
| optional int32 invocation_reason = 11 [default = 0]; |
| |
| // How many retries of this operation have happened thus far. |
| optional int32 retry_count = 12 [default = 0]; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 13; |
| } |
| |
| // Response indicating whether a device enrollment completed successfully. |
| message FinishEnrollmentResponse { |
| // Status should be OK if the request was successful. |
| optional string status = 1; |
| |
| // A detailed error message if there was a failure. |
| optional string error_message = 2; |
| } |
| |
| // Device info uploaded during enrollment. |
| message GcmDeviceInfo { |
| // This field's name does not match the one in DeviceInfo for legacy reasons. |
| // Consider using long_device_id and device_type instead when enrolling |
| // non-android devices. |
| optional fixed64 android_device_id = 1; |
| |
| // Used for device_address of DeviceInfo field 2, but for GCM capable devices. |
| optional bytes gcm_registration_id = 102; |
| |
| // Used for device_address of DeviceInfo field 2, but for iOS devices. |
| optional bytes apn_registration_id = 202; |
| |
| // Has the user enabled the associated apn_registration_id for notifications. |
| optional bool apn_notification_enabled = 203 [default = false]; |
| |
| // Used for device_address of DeviceInfo field 2, a Bluetooth Mac address for |
| // the device (e.g., to be used with EasyUnlock). |
| optional string bluetooth_mac_address = 302; |
| |
| // SHA-256 hash of the device master key (from the key exchange). |
| // Differs from DeviceInfo field 3, which contains the actual master key. |
| optional bytes device_master_key_hash = 103; |
| |
| // A SecureMessage.EcP256PublicKey. |
| required bytes user_public_key = 4; |
| |
| // device's model name |
| // (e.g., an android.os.Build.MODEL or UIDevice.model). |
| optional string device_model = 7; |
| |
| // device's locale |
| optional string locale = 8; |
| |
| // The handle for user_public_key (and implicitly, a master key). |
| optional bytes key_handle = 9; |
| |
| // The initial counter value for the device, sent by the device. |
| optional int64 counter = 12 [default = 0]; |
| |
| // The Operating System version on the device |
| // (e.g., an android.os.Build.DISPLAY or UIDevice.systemVersion). |
| optional string device_os_version = 13; |
| |
| // The Operating System version number on the device |
| // (e.g., an android.os.Build.VERSION.SDK_INT). |
| optional int64 device_os_version_code = 14; |
| |
| // The Operating System release on the device |
| // (e.g., an android.os.Build.VERSION.RELEASE). |
| optional string device_os_release = 15; |
| |
| // The Operating System codename on the device |
| // (e.g., an android.os.Build.VERSION.CODENAME or UIDevice.systemName). |
| optional string device_os_codename = 16; |
| |
| // The software version running on the device |
| // (e.g., Authenticator app version string). |
| optional string device_software_version = 17; |
| |
| // The software version number running on the device |
| // (e.g., Authenticator app version code). |
| optional int64 device_software_version_code = 18; |
| |
| // Software package information if applicable |
| // (e.g., com.google.android.apps.authenticator2). |
| optional string device_software_package = 19; |
| |
| // Size of the display in thousandths of an inch (e.g., 7000 mils = 7 in). |
| optional int32 device_display_diagonal_mils = 22; |
| |
| // For Authzen capable devices, their Authzen protocol version. |
| optional int32 device_authzen_version = 24; |
| |
| // Not all devices have device identifiers that fit in 64 bits. |
| optional bytes long_device_id = 29; |
| |
| // The device manufacturer name |
| // (e.g., android.os.Build.MANUFACTURER). |
| optional string device_manufacturer = 31; |
| |
| // Used to indicate which type of device this is. |
| // TODO(khorimoto): Change this to a string so it works with Apiary endpoints. |
| optional DeviceType device_type = 32 [default = ANDROIDOS]; |
| |
| // Fields corresponding to screenlock type/features and hardware features |
| // should be numbered in the 400 range. |
| |
| // Is this device using a secure screenlock (e.g., pattern or pin unlock) |
| optional bool using_secure_screenlock = 400 [default = false]; |
| |
| // Is auto-unlocking the screenlock (e.g., when at "home") supported? |
| optional bool auto_unlock_screenlock_supported = 401 [default = false]; |
| |
| // Is auto-unlocking the screenlock (e.g., when at "home") enabled? |
| optional bool auto_unlock_screenlock_enabled = 402 [default = false]; |
| |
| // Does the device have a Bluetooth (classic) radio? |
| optional bool bluetooth_radio_supported = 403 [default = false]; |
| |
| // Is the Bluetooth (classic) radio on? |
| optional bool bluetooth_radio_enabled = 404 [default = false]; |
| |
| // Does the device hardware support a mobile data connection? |
| optional bool mobile_data_supported = 405 [default = false]; |
| |
| // Does the device support tethering? |
| optional bool tethering_supported = 406 [default = false]; |
| |
| // Does the device have a BLE radio? |
| optional bool ble_radio_supported = 407 [default = false]; |
| |
| // Is the device a "Pixel Experience" Android device? |
| optional bool pixel_experience = 408 [default = false]; |
| |
| // Is the device running in the ARC++ container on a chromebook? |
| optional bool arc_plus_plus = 409 [default = false]; |
| |
| // Is the value set in |using_secure_screenlock| reliable? On some Android |
| // devices, the platform API to get the screenlock state is not trustworthy. |
| // See b/32212161. |
| optional bool is_screenlock_state_flaky = 410 [default = false]; |
| |
| // A list of multi-device software features supported by the device. |
| repeated SoftwareFeature supported_software_features = 411; |
| |
| // Previously, field 412 referred to "enabled_software_features". However, |
| // this is not an intrinsic property of a device type, so this field has been |
| // removed. |
| |
| // The enrollment session id this is sent with |
| optional bytes enrollment_session_id = 1000; |
| |
| // A copy of the user's OAuth token |
| optional string oauth_token = 1001; |
| } |
| |
| message GcmMetadata { |
| required MessageType type = 1; |
| optional int32 version = 2 [default = 0]; |
| } |
| |
| // Request for a listing of a user's own devices. |
| message GetMyDevicesRequest { |
| // Return only devices that can act as EasyUnlock keys. |
| optional bool approved_for_unlock_required = 2; |
| |
| // Allow the returned list to be somewhat out of date (read will be faster). |
| optional bool allow_stale_read = 3 [default = false]; |
| |
| // An integer encoding the reason this request was invoked (triggered). |
| // See InvocationReason enum for definitions. |
| optional int32 invocation_reason = 4 [default = 0]; |
| |
| // How many retries of this operation have happened thus far. |
| optional int32 retry_count = 5 [default = 0]; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 6; |
| } |
| |
| // Response containing a listing of the users devices. |
| message GetMyDevicesResponse { |
| // A listing of all sync-able devices. |
| repeated ExternalDeviceInfo devices = 1; |
| } |
| |
| // Reasons why the server thinks a certain device is not eligible to be an |
| // EasyUnlock key. |
| enum IneligibilityReason { |
| UNKNOWN_INELIGIBILITY_REASON = 0; |
| |
| // The screen is larger than 6.9 inches (which most likely means this is |
| // a tablet). |
| SCREEN_TOO_LARGE = 1; |
| |
| // The device has reported that it does not support bluetooth. |
| BLUETOOTH_NOT_SUPPORTED = 2; |
| |
| // The devices last known credentials are no longer valid. |
| INVALID_CREDENTIALS = 3; |
| |
| // The device has reported that it does not support auto-unlocking. |
| AUTO_UNLOCKING_NOT_SUPPORTED = 4; |
| |
| // We think the device is offline. |
| DEVICE_OFFLINE = 5; |
| |
| // The database entry for this device was not updated in the last |
| // max_last_update_time_delta_millis (see FindEligibleUnlockDevicesRequest). |
| NO_RECENT_UPDATES = 6; |
| |
| // Operating system version is not accepted. |
| BAD_OS_VERSION = 7; |
| |
| // SmartLock client software version is not accepted. |
| BAD_DEVICE_SOFTWARE_VERSION = 8; |
| |
| // Feature is not in supported_software_features for this device. |
| FEATURE_UNSUPPORTED = 9; |
| } |
| |
| // A device that the server thinks is not eligible to be an unlock key, and the |
| // reason for this. |
| message IneligibleDevice { |
| // The device that is not eligible to be an unlock key. |
| optional ExternalDeviceInfo device = 1; |
| |
| // The reasons why the server thinks it is not an unlock key. |
| // NOTE: for now, this list of reasons will contain exactly one element. |
| // It is a repeated field because, in principle, there can be more than |
| // one reason that makes a device not eligible to be an unlock key, |
| // and we want to be able to add multiple reasons in the future. |
| repeated IneligibilityReason reasons = 2; |
| } |
| |
| // A list of "reasons" that can be provided for calling server-side APIs. |
| // This is particularly important for calls that can be triggered by different |
| // kinds of events. |
| // NOTE: Added INVOCATION_* prefix to enum names due to name conflict with |
| // preprocessor MACRO on Windows. |
| enum InvocationReason { |
| INVOCATION_REASON_UNKNOWN = 0; |
| // First run of the software package invoking this call. |
| INVOCATION_REASON_INITIALIZATION = 1; |
| // Ordinary periodic actions (e.g. monthly master key rotation). |
| INVOCATION_REASON_PERIODIC = 2; |
| // Slow-cycle periodic action (e.g. yearly keypair rotation???). |
| INVOCATION_REASON_SLOW_PERIODIC = 3; |
| // Fast-cycle periodic action (e.g. daily sync for Smart Lock users). |
| INVOCATION_REASON_FAST_PERIODIC = 4; |
| // Expired state (e.g. expired credentials, or cached entries) was detected. |
| INVOCATION_REASON_EXPIRATION = 5; |
| // An unexpected protocol failure occurred (so attempting to repair state). |
| INVOCATION_REASON_FAILURE_RECOVERY = 6; |
| // A new account has been added to the device. |
| INVOCATION_REASON_NEW_ACCOUNT = 7; |
| // An existing account on the device has been changed. |
| INVOCATION_REASON_CHANGED_ACCOUNT = 8; |
| // The user toggled the state of a feature (e.g. Smart Lock enabled via BT). |
| INVOCATION_REASON_FEATURE_TOGGLED = 9; |
| // A "push" from the server caused this action (e.g. a sync tickle). |
| INVOCATION_REASON_SERVER_INITIATED = 10; |
| // A local address change triggered this (e.g. GCM registration id changed). |
| INVOCATION_REASON_ADDRESS_CHANGE = 11; |
| // A software update has triggered this. |
| INVOCATION_REASON_SOFTWARE_UPDATE = 12; |
| // A manual action by the user triggered this (e.g. commands sent via adb). |
| INVOCATION_REASON_MANUAL = 13; |
| } |
| |
| // Note: This is the same enum as securegcm.Type in securegcm.proto in the |
| // server definitions. Renamed for clarity here. |
| enum MessageType { |
| ENROLLMENT = 0; |
| TICKLE = 1; |
| TX_REQUEST = 2; |
| TX_REPLY = 3; |
| TX_SYNC_REQUEST = 4; |
| TX_SYNC_RESPONSE = 5; |
| TX_PING = 6; |
| DEVICE_INFO_UPDATE = 7; |
| TX_CANCEL_REQUEST = 8; |
| PROXIMITYAUTH_PAIRING = 10; |
| GCMV1_IDENTITY_ASSERTION = 11; |
| |
| // Device-to-device communications are protected by an unauthenticated |
| // Diffie-Hellman exchange. The InitiatorHello message is simply the |
| // initiator's public DH key, and is not encoded as a SecureMessage, so |
| // it doesn't have a tag. |
| // The ResponderHello message (which is sent by the responder |
| // to the initiator), on the other hand, carries a payload that is protected |
| // by the derived shared key. It also contains the responder's |
| // public DH key. ResponderHelloAndPayload messages have the |
| // DEVICE_TO_DEVICE_RESPONDER_HELLO tag. |
| DEVICE_TO_DEVICE_RESPONDER_HELLO_PAYLOAD = 12; |
| |
| // Device-to-device communications are protected by an unauthenticated |
| // Diffie-Hellman exchange. Once the initiator and responder |
| // agree on a shared key (through Diffie-Hellman), they will use messages |
| // tagged with DEVICE_TO_DEVICE_MESSAGE to exchange data. |
| DEVICE_TO_DEVICE_MESSAGE = 13; |
| |
| // Notification to let a device know it should contact a nearby device. |
| DEVICE_PROXIMITY_CALLBACK = 14; |
| |
| // Device-to-device communications are protected by an unauthenticated |
| // Diffie-Hellman exchange. During device-to-device authentication, the first |
| // message from initiator (the challenge) is signed and put into the payload |
| // of the message sent back to the initiator. |
| UNLOCK_KEY_SIGNED_CHALLENGE = 15; |
| } |
| |
| // GCM tickles related to registration management. |
| enum RegistrationTickleType { |
| UNKNOWN_REGISTRATION_TICKLE_TYPE = 0; |
| |
| // Force a re-enrollment with the server. |
| FORCE_ENROLLMENT = 1; |
| |
| // Update enrollment information with the server. This could either be an |
| // authzen re-enrollment or a SyncTx. |
| UPDATE_ENROLLMENT = 2; |
| |
| // Devices that receive this should sync the user's list of devices. |
| DEVICES_SYNC = 3; |
| } |
| |
| // Requests to send a "tickle" requesting to sync all of a user's devices now |
| message SendDeviceSyncTickleRequest { |
| // The type of tickle. *_ENROLLMENT tickles will only be sent to |
| // android devices. DEVICES_SYNC will be sent to chromebooks and android |
| // devices. UNKNOWN_TICKLE_TYPE or absent will be treated as |
| // UPDATE_ENROLLMENT. |
| // This field will also determine GCM parameters, such as |
| // TTL and collapse token. |
| optional RegistrationTickleType tickle_type = 3; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 4; |
| } |
| |
| message SendDeviceSyncTickleResponse { |
| // empty for now. |
| } |
| |
| // Contains information needed to begin a device enrollment. |
| message SetupEnrollmentInfo { |
| // Type of protocol this setup information was requested for. |
| optional string type = 1; |
| |
| // A session identifier to be used for this enrollment session. |
| optional bytes enrollment_session_id = 2; |
| |
| // A Diffie-Hellman public key used to perform a key exchange during |
| // enrollment. |
| optional bytes server_ephemeral_key = 3; |
| } |
| |
| // Requests information needed to begin a device enrollment. |
| message SetupEnrollmentRequest { |
| // Deprecated. See <code>application_id</code>. |
| optional string origin = 2; |
| |
| // Type(s) of protocol supported by this enrolling device (e.g. "gcmV1"). |
| repeated string types = 3; |
| |
| // Indicates whether a legacy crypto suite must be used with this device. |
| optional bool use_legacy_crypto = 4; |
| |
| // A URL describing which application facets this enrollment can be used (see |
| // http://go/appid). |
| optional string application_id = 5; |
| |
| // An integer encoding the reason this enrollment was invoked (triggered). |
| // See InvocationReason enum for definitions. |
| optional int32 invocation_reason = 6 [default = 0]; |
| |
| // How many retries of this operation have happened thus far. |
| optional int32 retry_count = 7 [default = 0]; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 8; |
| } |
| |
| // Contains information needed to begin a device enrollment. |
| message SetupEnrollmentResponse { |
| // Should return OK if the request was well formed. |
| optional string status = 1; |
| |
| // Information for each of the requested protocol <code>type</code>s. |
| repeated SetupEnrollmentInfo infos = 2; |
| } |
| |
| // Used to enable or disable EasyUnlock features on a specified device, and also |
| // causes other devices to sync the new EasyUnlock state. |
| message ToggleEasyUnlockRequest { |
| // If true, Easy Unlock will be enabled for the device with public key equal |
| // to public_key. Otherwise, it will be disabled for that device. |
| optional bool enable = 1; |
| |
| // Encoded public key of the device to enable/disable (here you must use the |
| // same exact encoding that was sent during device enrollment). |
| optional bytes public_key = 2; |
| |
| // If true, EasyUnlock enabled state will be set to the value of "enable" for |
| // all of a user's devices. This is the same as calling the toggle RPC for |
| // every device. However, this removes the need for calling GetMyDevices, so |
| // it reduces network overhead. If this field is set "public_key" must not be |
| // set. NOTE: the case enable=true is not yet supported, so this option can |
| // only disable EasyUnlock for all devices. |
| optional bool apply_to_all = 3; |
| |
| // Information about the requesting device and its platform. |
| optional DeviceClassifier device_classifier = 4; |
| |
| // The feature for which enabled state should be toggled. Note that this RPC |
| // is overloaded instead of adding new RPCs due to the ongoing V2 transition. |
| // See go/unified-better-together-cryptauth for more details. |
| optional string feature = 5 [default = "easyUnlockHost"]; |
| |
| // True if enabling one device for this feature should disable all others on |
| // the account. |
| optional bool is_exclusive = 6 [default = true]; |
| } |
| |
| message ToggleEasyUnlockResponse { |
| // empty for now. |
| } |