1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// 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;
// WebauthnCredentialSpecifics is an entity that backs a WebAuthn
// PublicKeyCredential. Since it contains the authenticator’s view of this
// object, it has a private key rather than a public key.
// (https://www.w3.org/TR/webauthn-2/#iface-pkcredential).
//
// Names of fields are taken from WebAuthn where possible. E.g.
// user.displayName in WebAuthn becomes user_display_name here.
//
// All fields are immutable after creation except for user_name and
// user_display_name, which may be updated by a user.
message WebauthnCredentialSpecifics {
// Sync's ID for this entity (sometimes called the client unique tag), 16
// random bytes. This value is used within Sync to identify this entity. The
// credential ID is not used because the (hashed) sync_id is exposed to the
// Sync server, and we don’t want Google to be able to map a credential ID to
// an account. Password entities construct this value from the concatenation
// of many fields and depend on the fact that the server only sees a hash of
// it. But the only high-entropy secret here is the private key, which will
// have different encryption in the future, and private keys are not the sort
// of data to copy into other fields. Therefore this independent value is
// provided to form the client's ID.
optional bytes sync_id = 1;
// The credential ID, 16 random bytes. This is a value surfaced in
// the WebAuthn API (https://www.w3.org/TR/webauthn-2/#credential-id).
optional bytes credential_id = 2;
// An RP ID is a WebAuthn concept:
// https://www.w3.org/TR/webauthn-2/#rp-id. It’s usually a domain name,
// although in non-Web contexts it can be a URL with a non-Web scheme.
optional string rp_id = 3;
// The user ID, which is also called a “user handle” in WebAuthn
// (https://www.w3.org/TR/webauthn-2/#user-handle), is an RP-specific
// identifier that is up to 64-bytes long. An authenticator conceptually only
// stores a single credential for a given (rp_id, user_id) pair, but there
// may be several credentials in Sync. They are prioritised using
// newly_shadowed_credential_ids and creation_time. See below.
//
// (We wish to be able to retain several entities for a single (rp_id,
// user_id) pair because there’s an edge case where we may wish to revert to
// an older entry and thus need to keep the older entry around in Sync. The
// revert could happen on a different device too.)
optional bytes user_id = 4;
// The id of credentials with the same (rp_id, user_id) that were
// shadowed by the creation of this entity.
//
// A credential is shadowed if one or more other credentials (from the same
// account, and with the same (rp_id, user_id)) include its credential_id in
// their list of shadowed IDs. Shadowed credentials are ignored when finding
// a credential to sign with. If there is more than one candidate remaining
// after filtering shadowed credentials then the most recently created (based
// on creation_time) is used.
//
// The reason for all this is that sites can replace a credential by creating
// another one with the same (rp_id, user_id) pair. However, we don't
// immediately know whether the WebAuthn response reached the website's
// server. Consider a user with a poor internet connection. Javascript in the
// site's origin triggers a credential creation that “overwrites” an existing
// credential, but the Javascript is unable to send the new public key to the
// website's server. The user is now locked out: the old credential has been
// over-written but the website's server doesn't know about the new one.
//
// Thus we wish to keep “overwritten” credentials around for a while to allow
// for some sort of recovery. In the simple case, a new credential shadows
// the single, previous old credential. We could depend on creation_time, but
// client clocks aren't always accurate, thus this field.
//
// In complicated cases two devices might race to replace a credential, in
// which case (after mutual syncing) two candidate credentials exist for the
// same (rp_id, user_id) pair because neither shadows the other. In this case
// we pick the newest based on `creation_time` but it's quite possible that
// some recovery will be needed because the website's server thinks the other
// one is correct.
//
// A generation counter isn't used because a single device might replace a
// series of credentials as it tries to update the website's server. But that
// doesn't mean that it should dominate a different device that replaced it
// only once, but later.
repeated bytes newly_shadowed_credential_ids = 5;
// The local time on the device when this credential was created. Given in
// milliseconds since the UNIX epoch. This is used to break ties between
// credentials. See newly_shadowed_credential_ids.
optional int64 creation_time = 6;
// The human-readable account identifier. Usually an email address. This is
// mutable.
// https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialentity-name
optional string user_name = 7;
// The human-readable name. Usually a legal name. This is mutable.
// https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialuserentity-displayname.
optional string user_display_name = 8;
// Reserving obsolete field.
reserved 10;
// Credentials may optionally be enabled for Secure Payment Confirmation[1] on
// third-party sites. This is opt-in at creation time.
//
// [1] https://www.w3.org/TR/secure-payment-confirmation/
optional bool third_party_payments_support = 11;
// Time when this passkey was last successfully asserted. Number of
// microseconds since 1601, aka Windows epoch. This mirrors the
// `date_last_used` field in PasswordSpecificsData.
optional int64 last_used_time_windows_epoch_micros = 13;
message Encrypted {
// The bytes of the private key, in PKCS#8 format.
optional bytes private_key = 1;
// The secret for implementing the hmac-secret extension
// https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#sctn-hmac-secret-extension
optional bytes hmac_secret = 2;
// The contents of the credential's credBlob.
// https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#sctn-credBlob-extension
optional bytes cred_blob = 3;
// The contents of the credential's largeBlob value(*). Unlike with security
// keys, largeBlob data is not stored in a single lump for all credentials,
// but as per-credential data. This data is presented to the authenticator
// over CTAP and thus has already had the required DEFLATE compression
// applied by the remote platform. The uncompressed size of this data is in
// the next field.
//
// (*) "large" with respect to embedded devices. Maximum length is 2KiB for
// Google Password Manager.
//
// https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#authenticatorLargeBlobs
optional bytes large_blob = 4;
// The claimed uncompressed size of the DEFLATE-compressed data in
// `large_blob`. This corresponds to the `origSize` field from the spec:
// https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#large-blob
optional uint64 large_blob_uncompressed_size = 5;
}
message SecurityDomainEncrypted {
// A serialized `Encrypted` message, encrypted with the device authorization
// key (see `device_authorization_key_version` for the key version).
optional bytes device_authorization_encrypted = 1;
}
// The "version" (sometimes called the epoch) of the key that `encrypted_data`
// is encrypted with. This allows trial decryption to be avoided when present.
optional int32 key_version = 14;
// The key version of the device authorization key that
// `device_authorization_encrypted` in `SecurityDomainEncrypted` is encrypted
// with.
optional int32 device_authorization_key_version = 18;
oneof encrypted_data {
// The bytes of the private key, encrypted with a feature-specific security
// domain.
bytes private_key = 9;
// A serialized, `Encrypted` message, encrypted with a feature-specific
// security domain.
bytes encrypted = 12;
// A serialized `SecurityDomainEncrypted` message, encrypted with a
// feature-specific security domain key.
bytes security_domain_encrypted = 19;
}
// `edited_by_user` is set to `true` the first time a user manually changes
// the credential's `user_name` or `user_display_name`.
optional bool edited_by_user = 15;
// `hidden` is set to `true` if the credential should not be shown on
// authentication surfaces, e.g. because a site marked it as obsolete.
optional bool hidden = 16;
// The local time on the device when this credential was hidden. Given in
// milliseconds since the UNIX epoch. This is used to permanently delete
// credentials after they've been hidden for a while.
optional int64 hidden_time = 17;
}
|