Characteristics

Service and Characteristics of the GATT Service

The Fast Pair Provider shall have the following GATT service.

Service UUID
Fast Pair Service 0xFE2C

This service shall have the following characteristics.

Custom Characteristics

Fast Pair Service characteristic Encrypted Permissions UUID
Model ID No Read FE2C1233-8366-4814-8EB0-01DE32100BEA
Key-based Pairing No Write and notify FE2C1234-8366-4814-8EB0-01DE32100BEA
Passkey No Write and notify FE2C1235-8366-4814-8EB0-01DE32100BEA
Account Key No Write FE2C1236-8366-4814-8EB0-01DE32100BEA
Old Fast Pair Service characteristic (target to be deprecated on 2021/1/1) Encrypted Permissions UUID
Model ID No Read 0x1233
Key-based Pairing No Write and notify 0x1234
Passkey No Write and notify 0x1235
Account Key No Write 0x1236

Standard Characteristics

Name Encrypted Permissions UUID
Firmware Revision No Read 0x2A26

Characteristic: Model ID

This characteristic allows the Seeker to read the model ID as needed, outside of when the device is [advertising in discoverable mode]. It should always return the following data:

Octet Data type Description Value
0 - 2 uint24 Model ID varies

Characteristic: Key-based Pairing

This characteristic controls the Key-based Pairing procedure. In this procedure, a certain level of trust is established by verifying that the Seeker and Provider are both in possession of a pre-shared key. The key is different in each case:

  • Case 1: The pre-shared key is based on the anti-spoofing public/private key pair, and the Seeker’s own public/private key pair which will change for each pairing attempt.

    • The Provider is in pairing mode.
    • The Seeker verifies that the Provider is in possession of the anti-spoofing private key.

    Note that when in pairing mode, the Provider may also of course pair in the usual way, for example, to pair with a device that does not support Fast Pair’s Key-based Pairing.

  • Case 2: The pre-shared key is one of the account keys.

    • The Provider is usually not in pairing mode. (But this is not a requirement—The Provider should support using an account key even when in pairing mode.)
    • The Seeker and Provider each verify that the other is in possession of the account key.

Since both cases are extremely similar, except for which pre-shared key is used, they are combined in Procedure.

Data Format

See Procedure for how each format is used.

Octet Data type Description Value Mandatory?
0 - 15 uint128 Encrypted Request varies Mandatory
16 - 79 Public Key varies Optional

Table 1.1: Encrypted Request, written to the characteristic by the Seeker.

Octet Data type Description Value Mandatory?
0 uint8 Message type 0x00 = Key-based Pairing Request Mandatory
1 uint8 Flags
  • Bit 0 (MSB): deprecated and ignored by Seeker.
  • Bit 1: 1 if the Seeker requests that the Provider shall initiate bonding, and this request contains the Seeker’s BR/EDR address. 0 otherwise.
  • Bit 2: 1 if the Seeker requests that the Provider shall notify the existing name. 0 otherwise.
  • Bit 3: 1 if this is for Retroactively writing account key. 0 otherwise.
  • Bits 4 - 7 are reserved for future use, and shall be ignored.
varies Mandatory
2 - 7 uint48 Either:
  • Provider’s current BLE address
  • Provider’s public address
varies Mandatory
8 - 13 uint48 Seeker’s BR/EDR Address varies Present only if Flags Bit 1 or 3 is set
n - 15 Random value (salt) varies Mandatory

Table 1.2.1: Raw Request (type 0x00). Decrypted from the Encrypted Request in Table 1.1.

Octet Data type Description Value Mandatory?
0 uint8 Message type 0x10 = Action Request Mandatory
1 uint8 Flags varies Mandatory
2 - 7 uint48 Either:
  • Provider’s current BLE address
  • Provider’s public address
varies Mandatory
8 uint8 Message group varies Mandatory if Flags Bit 0 is set
9 uint8 Message code varies Mandatory if Flags Bit 0 is set
10 uint8 Depends on Flags:
  • Bit 0 is set: Additional data length, less than 6
  • Bit 1 is set: Data ID
varies Mandatory if Flags Bit 0 or 1 is set
11 - n Additional data varies Optional
n - 15 Random value (salt) varies Mandatory

Table 1.2.2: Raw Request (type 0x10). Decrypted from the Encrypted Request in Table 1.1.

Octet Data type Description Value
0 uint8 Message type 0x01 = Key-based Pairing Response
1 - 6 uint48 Provider’s public (BR/EDR) address varies
7 - 15 Random value (salt) varies

Table 1.3: Raw Response. Encrypted to produce the Encrypted Response in Table 1.4.

Octet Data type Description Value
0 -15 uint128 Encrypted Response varies

Table 1.4: Encrypted Response, sent by the Provider to the Seeker via a notify.

Characteristic: Passkey

This characteristic is used during the Key-based Pairing procedure.

Octet Data type Description Value
0 - 15 uint128 Encrypted passkey block varies

Table 2.1: Encrypted Passkey Block. See Key-based Pairing procedure for usage.

Octet Data type Description Value
0 uint8 Message type One of:
  • 0x02 = Seeker’s Passkey
  • 0x03 = Provider’s Passkey
1 - 3 unit32 6-digit passkey varies
4 - 15 Random value (salt) varies

Table 2.2: Raw Passkey Block. Decrypted version of Table 2.1.

Characteristic: Account Key

After pairing, the Fast Pair Seeker will write an Account Key to the Fast Pair Provider.

Octet Data type Description Value
0 - 15 uint128 Account key (encrypted) varies

Upon getting a write request, the Fast Pair Provider shall do the following:

  1. Decrypt the account key using the shared secret generated from step 4 in the procedure.
    1. Before decrypting, verify that the shared secret was used to decrypt the passkey request from step 12. If this step has not passed using this secret, ignore this write and quit.
    2. At this point, the shared secret (K in the procedure) will not be used again for this pairing. Any requests which come in encrypted with this key without restarting the procedure should be rejected.
  2. Verify that the decrypted value starts with 0x04. If it does not, ignore this write and quit.
  3. Check whether the persisted Account Key list has space for the new value.
  4. If not, delete the least recently used value from the list.
  5. Add the new value to the list.

Account Keys in the list are used during Key-based Pairing.

Characteristic: Firmware Revision

This characteristic allows the Seeker to read the firmware revision of the Provider as needed. It should always return the following data:

Octet Data type Description Value
0 - var utf8s Firmware revision code varies

It should be encapsulated to a single utf8 string even if there is more than one firmware (e.g. 3 firmwares for left bud, right bud and case.) on the Provider. The Provider can also return the specific strings for special cases:

  1. status-updating: if the Provider is currently updating to a new firmware. Alternatively, the Provider could return the version of the staged firmware.

  2. status-abnormal: if the Provider is in an abnormal state. For example, it has malfunctioned because the firmware update failed. This value will cause the Seeker to show a message to let user know it has to be updated now.

Characteristic: Additional Data

This service shall have the following characteristic.

Fast Pair Service characteristic Encrypted Permissions UUID
Data No Write and notify FE2C1237-8366-4814-8EB0-01DE32100BEA
Old Fast Pair Service characteristic (target to be deprecated on 2021/1/1) Encrypted Permissions UUID
Data No Write and notify 0x1237

Before writing or notifying to this characteristic, there must be a handshake through characteristic FE2C1234-8366-4814-8EB0-01DE32100BEA to have a shared secret. AES-CTR will be used to encrypt data flowing through this characteristic, the algorithm of which is defined below. This mode is more secure across data that extends beyond a single 16-byte block. HMAC-SHA256 will be used to ensure data integrity, which is also defined below.

Octet Description Value
0 - 7 The first 8 bytes of HMAC-SHA256. varies
8 - 15 Nonce, used by AES-CTR encryption. varies
16 - var Encrypted data. varies

Table 3.1: Data Packet, sent by the Provider to the Seeker via a notify or sent by the Seeker to the Provider via a write.

Octet Data type Description Value
0 - var byte array Data varies, decode it according to the Data ID of Table 1.2.2:
  • 0x01(personalized name): utf8s

Table 3.2: Raw data. Decrypted from the encrypted data in Table 3.1.

When a notify is requested (e.g. request personalized name via Bit 2 in Table 1.2.1), the Fast Pair Provider shall do the following:

  1. Generate cryptographically random 8 bytes for Nonce.
  2. Encrypt the data using AES-CTR, where each 16-byte block is generated using

    encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
    

    where

    1. AES key is the shared secret from step 4 in the procedure.
    2. clearBlock[i] is a 16-byte block starting from data[i * 16]. The last block can be less than 16 bytes.
  3. Perform concat(encryptedBlock[0], encryptedBlock[1],...) to create the Encrypted Data.

  4. Generate HMAC-SHA256 by

    sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))
    

    where

    1. K is generated by concat(shared_secret, 48-byte ZEROs), the shared_secret is from step 4 in the procedure.
    2. opad is 64 bytes outer padding, consisting of repeated bytes valued 0x5C.
    3. ipad is 64 bytes inner padding, consisting of repeated bytes valued 0x36.
  5. Take the first 8 bytes from the HMAC-SHA256 as the prefix of the Data packet.

Upon getting a write request, the Fast Pair Provider shall do the following:

  1. Verify the integrity of the data by checking the first 8 bytes of HMAC-SHA256.
  2. Decrypt the encrypted Data using AES-CTR, where each block is generated using

    clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))
    

    where

    1. encryptedBlock[i] is a 16-byte block start from encrypted_data[i * 16]. The last block can be less than 16 bytes.
    2. AES key is generated or identified from the handshake, e.g.
      1. in naming flow 1, it is from ECDH, and it will not be used again for this pairing. Any requests which come in encrypted with this key without restarting the procedure should be rejected.
      2. in naming flow 2, it is the account key.
  3. Perform concat(clearBlock[0], clearBlock[1],...) to create the raw data.