Fast Pair Service
The Fast Pair Provider shall implement the Fast Pair Service (UUID 0xFE2C),
which contains the following characteristics.
| Name | Encrypted | Permissions | UUID | Mandatory? |
|---|---|---|---|---|
| Model ID | No | Read | FE2C1233-8366-4814-8EB0-01DE32100BEA |
Mandatory |
| Key-based Pairing | No | Write and notify | FE2C1234-8366-4814-8EB0-01DE32100BEA |
Mandatory |
| Passkey | No | Write and notify | FE2C1235-8366-4814-8EB0-01DE32100BEA |
Mandatory |
| Account Key | No | Write | FE2C1236-8366-4814-8EB0-01DE32100BEA |
Mandatory |
| Additional Data | No | Write and notify | FE2C1237-8366-4814-8EB0-01DE32100BEA |
*C1 |
| Message Stream PSM | Yes | Read | FE2C1239-8366-4814-8EB0-01DE32100BEA |
*C2 |
| Additional Passkey | No | Read, write, and notify | FE2C123A-8366-4814-8EB0-01DE32100BEA |
*C3 |
| FP Device Action | No | Write and notify | FE2C123B-8366-4814-8EB0-01DE32100BEA |
*C4 |
Conditional mandatory
- C1: if the Provider supports the naming feature and does not implement the FP Device Action characteristic
- C2: if the Provider supports Message Stream: L2CAP
- C3: if the Provider has an Internal communication channel between components
- C4: if the Provider needs to exchange additional information during the pairing process, for example a Provider without an Internal communication channel between components
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
|
varies | Mandatory |
| 2 - 7 | uint48 |
Either:
|
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:
|
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:
|
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 (type 0x01). Encrypted to produce the Encrypted Response in Table 1.4.
| Octet | Data type | Description | Value |
|---|---|---|---|
| 0 | uint8 |
Message type | 0x02 = Key-based Pairing Extended Response |
| 1 | uint8 |
Flags
|
varies |
| 2 | uint8 |
Number of the Provider's addresses Valid values are 1 and 2. |
varies |
| 3 - 8 or 3 - 14 |
|
varies | |
| 9 - 15 or 15 | Random value (salt) | varies |
Table 1.3.2: Raw Response (type 0x02). 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:
|
| 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:
- Decrypt the account key using the shared secret generated from step 4 in the
procedure.
- For Providers that require bonding (common):
- 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.
- At this point, the shared secret (K in the procedure) won't be used again for this pairing. Any requests which come in encrypted with this key without restarting the procedure should be rejected.
- For Providers that require bonding (common):
- Verify that the decrypted value starts with
0x04or0xFF. If it does not, ignore this write and quit.- If value is
0x04:- Check whether the persisted Account Key list has space for the new value.
- If not, delete the least recently used value from the list.
- Add the new value to the list.
- If value is
0xFF:- Treat this as a temporary pairing session and perform no operation.
- This can happen with the Retroactively writing account key flow.
- Do not store the key, and do not use it in the Account Key list, encryption, or MAC calculations.
- Bond removal is triggered by a feature-specific event or timeout. For LE Audio Sharing, it is highly recommended to remove the BLE bond and link key 10 minutes after the temporary session disconnects.
- If value is
Account Keys in the list are used during Key-based Pairing.
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:
|
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:
- Generate cryptographically random 8 bytes for Nonce.
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
- AES key is the shared secret from step 4 in the procedure.
- clearBlock[i] is a 16-byte block starting from data[i * 16]. The last block can be less than 16 bytes.
Perform concat(encryptedBlock[0], encryptedBlock[1],...) to create the Encrypted Data.
Generate HMAC-SHA256 by
sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))where
- K is generated by concat(shared_secret, 48-byte ZEROs), the shared_secret is from step 4 in the procedure.
- opad is 64 bytes outer padding, consisting of repeated bytes valued
0x5C. - ipad is 64 bytes inner padding, consisting of repeated bytes valued
0x36.
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:
- Verify the integrity of the data by checking the first 8 bytes of HMAC-SHA256.
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
- encryptedBlock[i] is a 16-byte block start from encrypted_data[i * 16]. The last block can be less than 16 bytes.
- AES key is generated or identified from the handshake, e.g.
- 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.
- in naming flow 2, it is the account key.
Perform concat(clearBlock[0], clearBlock[1],...) to create the raw data.
Characteristic: Message Stream PSM
See BLE Device: Message Stream PSM
Characteristic: Additional Passkey
See BLE Device: Additional Passkey
Characteristic: FP Device Action
| Fast Pair Service characteristic | Encrypted | Permissions | UUID |
|---|---|---|---|
| FP Device Action | No | Write and notify | FE2C123B-8366-4814-8EB0-01DE32100BEA |
| 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 4.1: Data Packet, sent by the Provider to the Seeker as a notification, or by the Seeker to the Provider as a write.
| Octet | Data type | Description | Value |
|---|---|---|---|
| 0 - var | byte array |
Action Request | One of:
|
Table 4.2: Raw data. Decrypted from the encrypted data in Table 4.1 sent by the Seeker to the Provider as a write.
| Octet | Data type | Description | Value |
|---|---|---|---|
| 0 - var | byte array |
Action Response | One of:
|
Table 4.3: Raw data. Decrypted from the encrypted data in Table 4.1 sent by the Provider to the Seeker as a notification.
| Octet | Data type | Description | Value |
|---|---|---|---|
| 0 | uint8 |
Action ID | 0x01 |
| 1 - var | utf8s |
Personalized Name | varies |
Table 4.3.1: Personalized Name Format
| Octet | Data type | Description | Value |
|---|---|---|---|
| 0 | uint8 |
Action ID | 0x02 |
| 1 | uint8 |
Fast Pair Coordinated Set Member Type |
|
| 2 | uint8 |
Coordinated Set Size | component count |
| 3 | uint8 |
Set Identity Resolving Key Type | 0x01 (Plain Text SIRK) |
| 4 - 19 | uint128 |
Set Identity Resolving Key Value | 16-byte data, see Coordinated Set Identification Service |
Table 4.3.2: Coordinated Set Information Format
| Octet | Data type | Description | Value |
|---|---|---|---|
| 0 | uint8 |
Action ID | 0x03 |
| 1 - 2 | uint16 |
Device Features |
|
Table 4.3.3: Device Features Format
Fast Pair Operations
Two main operations are defined for this characteristic
- Fast Pair Read: read data from the Provider
- Seeker: Enable GATT Notification
- Provider: GATT notification registered
- Seeker: GATT Write Request, the raw data only contains
Action ID - Provider: GATT Write Response
- Provider: GATT Notify, the raw data contains
- Action ID
- Data for the Action ID
- Seeker: GATT Notification received
- Fast Pair Write: write data to the Provider
- Seeker: GATT Write Request, the raw data contains
- Action ID
- Data for the Action ID
- Provider: GATT Write response
- Seeker: GATT Write Request, the raw data contains
Fast Pair Read Supported Action ID
- 0x01 (Personalized name)
- 0x02 (Coordinated set information)
- 0x03 (Device features)
Fast Pair Write Supported Action ID
- 0x01 (Personalized name)
- For any other commands where a write request has an Action ID followed by data, the Provider shall respond with a GATT notification containing Invalid Request (0x81) as described in Table 4.3.
If the Provider does not understand an Action ID, it responds with a GATT notification containing Unsupported Request (0x80) as described in Table 4.3.
Crypto Algorithm
When a notify is requested, the Fast Pair Provider shall do the following:
- Generate cryptographically random 8 bytes for Nonce.
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
- AES key is the shared secret from step 4 in the procedure.
clearBlock[i]is a 16-byte block starting fromdata[i * 16]. The last block can be less than 16 bytes.
Perform
concat(encryptedBlock[0], encryptedBlock[1],...)to create the Encrypted Data.Generate HMAC-SHA256 by
sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))where
- K is generated by concat(shared_secret, 48-byte ZEROs), the shared_secret is from step 4 in the procedure.
- opad is 64 bytes outer padding, consisting of repeated bytes valued
0x5C. - ipad is 64 bytes inner padding, consisting of repeated bytes valued
0x36.
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:
- Verify the integrity of the data by checking the first 8 bytes of HMAC-SHA256.
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
encryptedBlock[i]is a 16-byte block starting fromencrypted_data[i * 16]. The last block can be less than 16 bytes.- AES key is generated or identified from the handshake, for example:
- 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.
- in naming flow 2, it is the account key.
Perform
concat(clearBlock[0], clearBlock[1],...)to create the raw data.
Device Information Service
The Fast Pair Provider should also support the Device Information Service
(UUID 0x180A). The Fast Pair Seeker uses the following characteristics.
| Name | Encrypted | Permissions | UUID |
|---|---|---|---|
| Firmware Revision | No | Read | 0x2A26 |
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:
status-updating: if the Provider is updating to a new firmware. Alternatively, the Provider could return the version of the staged firmware.
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.
The Provider should limit access to the Firmware Revision characteristic to prevent device tracking. Suggested restrictions:
- bonded devices should have access at any time
- any device should have access when the Provider is discoverable
If the Provider supports Find Hub, additional implementation is required. Refer to Find Hub Firmware updates for details.