Google Fast Pair Service

Introduction

The Google Fast Pair Service (GFPS) utilizes Bluetooth Low Energy (BLE) to discover nearby Bluetooth devices without using significant phone battery, enabling “magical” scenarios based on device proximity.

Features

GFPS is initially aimed to facilitate pairing of audio sink devices, such as speakers, headphones and car kits, with as little user interaction required as possible. By implementing the following spec, Google will continue to release additional features that build upon it from the phone side. This includes:

  1. Displaying a notification when the device is in pairing mode to facilitate easy initial pairing.
  2. Associating the device with the user's account after the initial pairing has completed.
  3. Displaying a subsequent pairing notification when the device is turned on and nearby another phone, tablet, or desktop that the user owns so that the user does not have to know how to put the device back into pairing mode before pairing with their other devices.
  4. Associating a personalized name with the device.
  5. Displaying a message when there is a firmware update available.

Profile dependencies

The GFPS service implementation is compatible with the Bluetooth Core Specification v4.2 or later.

Octet order

Wherever a field consists of multiple bytes, the byte ordering is big-endian, that is, network byte order (most-significant octet to least-significant octet).

Note that while this is standard for bytes transferred over networks, it is different from the byte ordering for multi-byte fields in Bluetooth SIG specifications (for example, a service UUID in an advertisement is little-endian).

Configuration

Roles

The profile defines two roles: Fast Pair Seeker, and Fast Pair Provider. The Seeker is normally a phone, looking for a device to pair with. The Provider is a device that is advertising its presence and readiness to pair (e.g. a discoverable pair of headphones).

The Fast Pair Seeker shall use the GAP Central role. The Fast Pair Provider shall use the GAP Peripheral role.

Device discovery

To facilitate device discovery, the Fast Pair Provider shall advertise a payload indicating support for the Google Fast Pair Service (with data as described below). The Fast Pair Seeker shall periodically scan for and observe the presence of Fast Pair Provider advertising frames, and take action if interested.

Fast Pair Provider

Model Registration

All Provider models must be registered with Google before they will work with Fast Pair. After registration, Google will distribute a Model ID and Anti-Spoofing Public/Private Key Pair. The information provided during registration is used in the pairing suggestion presented to the user, and may be used in other UX.

Example pairing suggestion (subject to change)

For information about registering your device and getting the relevant Model ID and Anti-Spoofing keys, see the Nearby Devices documentation.

Transmit power

Provider devices should advertise at a low transmit power (TxPower) to limit exposure of the advertised device. However, the power shall be high enough such that the advertisement is visible by any phone at least 1 meter away.

To determine proximity, the Fast Pair Seeker must know the Fast Pair Provider’s transmit power. For the purposes of this profile, TxPower is defined as the received signal strength at source (0 meters), measured in dBm (this is the same way that Eddystone defines it).

This measured value shall be transmitted using one of these methods:

Included in the Advertisement Record
The device includes the Tx Power Level data type, ibid., § 1.5, in its advertisement.
Provided during model registration
The manufacturer provides Google with the transmit power, and the device model used to measure it, during Model Registration.
The device must keep its transmit power constant for all broadcasts when using this option so that distance measurements are accurate.

Keys

Anti-Spoofing Public/Private Key Pair

After model registration, along with the Model ID, Google will distribute a 256-bit Anti-Spoofing Private Key (an integer in [1,n–1] on the secp256r1 elliptic curve). This key shall be persisted on the Provider device, and ideally stored inside a Secure Element (SE). Note that a Secure Element is strongly recommended—in the absence of one, there is no guarantee that attackers could not spoof the provider role, because the private key could leak. This key leaking opens up the possibility of man in the middle attacks; therefore, if impersonation or abuse is detected, Fast Pair features that use this key may be disabled (for example, the "Tap to pair" notification when the Provider is in pairing mode).

The corresponding Anti-Spoofing Public Key is not currently used by the Provider. It is used by the Seeker, to encrypt a message to send to the Provider (see Key-based Pairing).

Account Key List

The Provider shall allocate space to store a persisted list of 128-bit Account Keys. Each Account Key allows the Provider to be recognized as belonging to a certain user account.

The list must be able to store at least five keys (that is, there must be at least 80 bytes of space dedicated to this list). Providers can optionally store more than this, they just must make sure that the keys will fit inside of their advertising packet. The exact number that can be stored will depend on how many free bytes are available in the advertising packet; see the Account Key Filter section for more information on determining how many bytes each key will take up. For example, to advertise 10 account keys, 15 bytes need to be available in the packet.

This list is initially empty, and must be cleared if the Provider is factory-reset (if the user clears its paired device list). The list is populated as described in the Account Key characteristic section.

BLE address

To prevent tracking, BLE advertising shall use the random resolvable private address (RPA). The address shall be rotated at minimum every 15 minutes while the device is actively advertising, and every time the state changes from not advertising to advertising. A randomized offset should be used to alter the address randomization interval.

Advertising: When discoverable

When the Provider device is BR/EDR discoverable (that is, in pairing mode), it shall advertise Fast Pair Model ID Data over BLE, and the BLE address shall not be rotated.

Advertising interval

The interval between advertisements should be no larger than 100ms (10Hz). A fast rate allows the Seeker to quickly find the Provider, even when scanning in low-power mode.

Advertising payload: Fast Pair Model ID Data

The advertisement shall contain the Service Data data type, ibid., § 1.11. The UUID shall be the Fast Pair Service UUID of 0xFE2C. The service data shall contain the following:

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

Each Provider model has a 24-bit model ID, which is provided by Google during Model Registration.

Advertising: When not discoverable

When not discoverable (that is, not in pairing mode), the Provider device shall advertise Fast Pair Account Data, using the following guidelines.

Advertising the account data allows Seekers nearby to recognize when a provider belongs to their account and initiate pairing without having to force the provider back into pairing mode first, which is a common cause for user complaint. Seekers will provide the opportunity for users to be able to ignore this broadcast in the case where they do not wait to pair with the provider or the broadcast is not relevant (for example, if they have already paired). Seekers will also filter out obviously bad broadcasts automatically, such as when the account data is misconfigured.

Advertising interval

The interval between advertisements should be at most 250ms (4Hz).

Advertising payload: Fast Pair Account Data

The advertisement shall contain the Service Data data type, Ibid., § 1.11. The UUID shall be the Fast Pair Service UUID of 0xFE2C. The service data shall contain the following:

Octet Data type Description Value
0 uint8 Flags 0x00
(all bits reserved for future use)
1 - varies Account Key Data varies
or 0x00 if the Account Key List is empty

The Account Key Data contains:

Octet Data type Description Value
0 uint8 Field length and type
0bLLLLTTTT
  • L = length of account key filter in bytes
  • T = type
0bLLLL0000
  • length = 0bLLLL = varies
  • type = 0b0000 (show UI indication) or 0b0010 (hide UI indication), Account Key Filter
1 - s Account Key Filter varies
s + 1 uint8 Field length and type
0bLLLLTTTT
  • L = length in bytes
  • T = type
0b00010001
  • length = 0b0001 = 1
  • type = 0b0001, Salt (see Rotation)
s + 2 uint8 Salt varies
Account Key Filter

The advertised Account Key Filter allows a Seeker to quickly check whether a Provider might possess a certain account key (with a low false-positive probability, on average much less than 0.5%), before further interactions. The Seeker may automatically connect and attempt to start the procedure when it sees a filter being broadcast with type 0, i.e. showing UI indication, that potentially contains one of its account keys, so as to reduce the rate of false positives further. In some situations, the Provider may want to be recognized by the Seeker while not ready for pairing. One example is that when buds get put back into case, we want to stop showing the subsequent pairing notification since that pairing could be rejected by the headset.

The Account Key Filter is a variable-length Bloom filter constructed as follows:

  1. Let n be the number of account keys (n >= 1) in the persisted Account Key list.
  2. Let s, the size of the filter in bytes, be (1.2*n + 3) truncated. For example, if 1 key is persisted, s = 4 bytes.
  3. Initialize the filter F as an array of s bytes, each set to 0.
  4. For each account key K in the persisted Account Key list:
    1. Produce a value V, where:
      1. The first 16 bytes are K
      2. The remaining bytes are the Salt (see Rotation).
    2. Hash V using SHA256, obtaining a 256-bit value H.
    3. Divide H into eight 32-bit unsigned integers, X = {X0, …, X7}.
    4. For each Xi:
      1. Let K be Xi modulo the number of bits in the filter, (s * 8).
      2. Get the byte in F at index (K / 8), rounded down.
      3. Within the byte, set the bit at index (K % 8) to 1.
      4. In other words:
        K = Xi % (s * 8)
        F[K/8] = F[K/8] | (1 << (K % 8))

Include the filter F as the Account Key Filter field, in the advertising data. Note that there is no "endianness" to this value, since there is no more or less significant byte—don’t alter the byte order.

Rotation

To reduce the ability to track devices by monitoring the Account Key Filter, the Account Key Filter shall be regenerated, with a new Salt, at least every 15 minutes while the device is actively advertising. However, note that if the device is connected over a BR/EDR link then the public address of one end of the link is being broadcast in the form of the channel access code, so privacy is limited.

Salt field

The salt is a random value that is appended to account keys when building the bloom filter. This salt should be regenerated every time the RPA is updated for the Provider to avoid tracking across address rotation.

To generate the Account Key Filter using the salt:

  1. Generate a random byte S.
  2. Use the byte S as the Salt in step 4(a).
  3. In the advertised Fast Pair Account Data, include the generated filter in the Account Key Filter field, and S in the Salt field.

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

ATT MTU Size Negotiation

An MTU value of 83 should be used whenever possible, but the default value of 23 is allowed.

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.

Procedure

Instead of immediately invoking any of the normal BR/EDR or BLE bonding procedures, the Seeker first enables Notifications on the Key-based Pairing characteristic, and then writes the data in Table 1.1 to it.

When handling a write request from a Fast Pair Seeker, the Fast Pair Provider shall do the following:

  1. If the optional Public Key field is present:
    1. If the device is not in pairing mode, ignore the write and exit.
    2. Otherwise:
      1. Use the received Public Key (a 64-byte point on the secp256r1 elliptic curve), the pre-installed Anti-Spoofing Private Key (also secp256r1), and the Elliptic-Curve Diffie-Hellman algorithm to generate a 256-bit AES key.
      2. Use SHA-256 to hash the 256-bit AES key.
      3. Take the first 128 bits of the result. This is the Anti-Spoofing AES Key, used in the next step.
  2. Using AES-128, attempt to decrypt the value. Since the value is a single 16-byte AES block, no IV or multi-block cipher mode is necessary.

    1. Which key to use:
      1. If an Anti-Spoofing AES Key was generated in step 1, use that key.
      2. Otherwise, try each key in the persisted Account Key List.
    2. If a key successfully decrypts the value, break, and continue to the next step.
    3. The value is decrypted successfully if the output matches the format in Table 1.2.1 or Table 1.2.2 (that is, if it contains either the Fast Pair Provider’s current BLE address, or the Fast Pair Provider’s public address).
    4. Note that at the end of the packet there is a salt attached. When possible, these salts should be tracked, and if the Provider receives a request containing an already used salt, the request should be ignored to prevent replay attacks.
    5. As an alternative to tracking salts, if the write includes the Provider’s private address, another way to prevent replay attacks is to bring forward the time of the next resolvable private address rotation so that the rotation occurs before the next Key-based Pairing write will be accepted.
  3. If no key could successfully decrypt the value, ignore the write and exit.

    1. Keep a count of these failures. When the failure count hits 10, fail all new requests immediately. Reset the failure count after 5 minutes, after power on, or after a success.
  4. Otherwise, save the successful key as K. Mark this K as usable for decrypting Passkey and Personalized name writes received on this LE link, but not other writes nor any writes on any other link. Start a timer to discard K after 10 seconds if pairing has not been started. Also discard K if this LE link disconnects.

  5. Produce the 16-byte Raw Response shown in Table 1.3, by concatenating the type and the Provider’s BR/EDR address, and then filling the remainder of the packet with a block of random bytes (that is, a salt).

  6. Encrypt the Raw Response with K to produce the 16-byte Encrypted Response shown in Table 1.4. Send this via a notify on the Key-based Pairing characteristic.

  7. If the Request’s Flags byte has bit 2 set to 1, notify Additional Data characteristic with personalized name.

  8. If the Request’s Flags byte has bit 1 set to 1:

    1. This indicates that the Seeker is requesting the Provider to initiate bonding to the Seeker’s BR/EDR address, which is present in bytes 8-13.
    2. Send a pairing request to the Seeker’s BR/EDR address. The pairing request must be as described below (“During pairing” step).
    3. Reason this is needed: Having the Provider initiate works around an issue on some devices.
  9. If the Request’s Flags byte has bit 1 set to 0:

    1. Wait up to 10 seconds for a pairing request. If none is received, exit.
    2. Note that this might be a BR/EDR request, from a different address (the Seeker’s public address, instead of its resolvable private address). We will re-verify during pairing that the requesting device is in possession of K.
  10. During pairing:

    1. When a pairing request/response packet is received from the Seeker: If the Device Capabilities in the request are NoInput/NoOutput, end pairing, to avoid using the Just Works pairing method.
    2. For the pairing request/response packet sent by the Provider: Set the Device Capabilities field to Display/YesNo and set Authentication Requirements to MITM Protection Required. This triggers the Numeric Comparison pairing method (also known as Passkey Confirmation on Android). We rely on this to confirm that the requesting device is in fact the Fast Pair Seeker, and that there is no man-in-the-middle. See examples.
    3. Reason this is needed: The Out-of-Band pairing method would be a better fit, but the platform does not expose it on all desired versions of Android.
  11. When confirmation of the passkey is needed, wait up to 10 seconds for a write to the Passkey characteristic.

    1. Normally, with this pairing method, the user would confirm that the passkeys displayed on each device’s screen are identical. Instead, only for this pairing, we transfer them over BLE, encrypted with the trusted pre-shared key.
    2. Note that this approach should not be taken for devices that have a screen or a keyboard as it makes a slight compromise on MITM protection. Fast Pair currently does not support those device types yet because of this.
    3. If the 10 second timer expires with a passkey being written, then discard K.
  12. When a value is written to the Passkey characteristic, this is the Encrypted Passkey Block. Decrypt it with K to yield a Raw Passkey Block, with format shown in Characteristic: Passkey > Table 2.2 (type = Seeker’s Passkey).

  13. If decryption fails, ignore the write and discard K.

  14. Otherwise, the Raw Passkey Block contains a 6-digit passkey PSeeker, which is the passkey that the Seeker expects.

  15. Compare PSeeker with our own expected passkey, PProvider.

    1. If the values are equal, reply “yes” to the confirmation.
    2. Otherwise, reply “no” to the confirmation, causing pairing to fail.
  16. Regardless of whether pairing failed, produce another Raw Passkey Block, with format shown in Characteristic: Passkey > Table 2.2, containing our own expected passkey, PProvider.

    1. Ensure the block has the correct type (Provider’s Passkey; see table).
    2. Note: Do not reuse the salt from the Passkey Block received from the Seeker. Generate a new random value.
  17. Encrypt the Raw Passkey Block with K, and send the resulting Encrypted Passkey Block via a notify on the Passkey characteristic.

  18. If the Seeker receives and decrypts the correct passkey P, the Seeker will also reply “yes” to the confirmation, and pairing will succeed.

    1. If the pairing succeeds, then mark K as usable for decrypting Account Key writes on this LE link, but not for any subsequent Passkey writes nor any writes on any other link. Start a timer to discard K after 10 seconds. Also discard K following any attempt to write an Account Key and, as per step 4, if the LE link disconnects.
    2. If the pairing fails, discard K.
  19. Switch the device capabilities field back to NoInput/NoOutput and Authentication Requirements to MITM Protection Not Required so that new pairings continue as expected.

Examples
Example 1: Successful pairing attempt (no man-in-the-middle).
Example 2: Failed pairing attempt, with a man-in-the-middle.

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 above 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 above) will not be used again for this pairing. Any requests which come in encrypted with this key without restarting the procedure above 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.

Extensions

Battery Notification

It is optional for tethered headphones.

When a Provider includes multiple components, it can be useful to notify the Seeker of the battery level for each component and remaining battery time (if known). One example of this would be when a headphone case is opened and the Seeker needs to know the battery for each individual bud and the case itself.

To accomplish this, a Provider can include additional information in the advertisement, built on top of the Fast Pair Account Data described in Advertising: When not discoverable above.

In addition to the Account Data, the Provider should include an additional field specifying the battery values and/or remaining battery time. The packet shall contain the following:

Octet Data type Description Value Mandatory?
0 uint8 Flags 0x00
(all bits reserved for future use)
Mandatory
1 - s Account Key Data Mandatory
s + 1 uint8 Battery level length and type
0bLLLLTTTT
  • L = Number of battery values
  • T = type
0bLLLLTTTT
  • length = 0b0011 = 3 battery values
  • type = 0b0011 (show UI indication) or 0b0100 (hide UI indication)
Optional
s + 2, s + 3, s + 4 uint8 Battery values
0bSVVVVVVV
  • S = status (charging or not charging)
  • V = value
  • The battery values should be ordered as left bud (s + 2), right bud (s + 3) and case (s + 4).
0bSVVVVVVV
  • status = 0b1 (charging) or 0b0 (not charging)
  • value = battery level ranging from 0 to 100 percent, 0bS1111111 for unknown.
Optional
n uint8 Battery remaining time length and type
0bLLLLTTTT
  • L = length
  • T = type
0bLLLLTTTT
  • length = 0b0001 or 0b0010, uint8 or uint16 for remaining time in minutes
  • type = 0b0101, remaining battery time
Optional
n + 1 - n + 2 uint16 Remaining battery time in minutes varies Optional

To prevent tampering, the Account Key Data above shall be slightly modified to include battery information when the battery values are included in the advertisement. Normally, when building the account key filter, a value V is produced by combining the account key with a salt. Instead, when battery information is also being advertised, the value V should be constructed as follows:

  1. Produce a value V, where:
    1. The first 16 bytes are K.
    2. The next bytes are the Salt (see Rotation).
    3. The remaining bytes are the battery information (from s + 1 to n+2 including the length and type bytes from the table above).

As noted in the battery length and type field above, the type can be either 0b0011 or 0b0100. Use 0b0011 when the Provider wants the Seeker to show an indication in the UI of the battery values; use 0b0100 when the Provider wants the Seeker to hide the indication if it is already showing. One common use case for this is to use 0b0011 when the case has opened and 0b0100 when buds have been removed from the case or it has been closed again.

To prevent tracking, the Provider should not include raw battery data in the advertisement all the time. It can instead be sent via RFCOMM when connected to a Seeker, see below.

Personalized Name

The Seeker can write a personalized name to the Provider during the first pairing and when the user edits the name on the Seeker side. The Provider shall allocate space, at least 64 bytes, to store the personalized name.

Writes to Additional Data characteristic with personalized name may happen in 2 flows:

  1. After initial pairing, the Seeker may write a personalized name to the Provider after writing the account key.
  2. After a user modifies the personalized name on the Seeker, the Seeker will write the new name to the Provider:
    1. handshake from step 1 to step 4 in the above procedure to identify each other and know which account key will be used for the encryption and decryption of the name. In Table 1.2.2:
      1. Set Message type to 0x10
      2. Set Flag Bit 1 to 1 to indicate it will be followed by Data characteristic.
      3. Set Data ID to 0x01 as personalized name.
    2. write the name to Data characteristic FE2C1237-8366-4814-8EB0-01DE32100BEA.

The Provider should notify to Additional Data characteristic with personalized name when it is requested via Bit 2 in Table 1.2.1.

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 Data ID:
  • 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 above 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 above 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 above 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.

Message Stream

Fast Pair supports an RFCOMM channel for Providers that wish to maintain a persistent connection to a device during operation. When the Provider connects to a supported Seeker, the Seeker will attempt to connect RFCOMM on the following channel:

df21fe2c-2515-4fdb-8886-f12c4d67927c

Once connected, messages can be exchanged in the following format:

Octet Data Type Description Mandatory?
0 uint8 Message group Mandatory
1 uint8 Message code Mandatory
2 - 3 uint16 Additional data length Mandatory
4 - n Additional data Optional

The additional data length and additional data fields should be big endian.

Silence Mode

Recent versions of Android support allowing a Provider to enter silence mode, meaning audio will no longer be routed to it while this mode is active. AVRCP commands will also be ignored during this time. When the Provider is disconnected, it automatically exits silence mode.

Silence mode can be enabled or disabled using the above message stream support by sending these parameters:

Message Group Name Value
Bluetooth event 0x01
Bluetooth Event Code Name Value
Enable silence mode 0x01
Disable silence mode 0x02

The additional data length for both cases is 0.

As an example, to enable silence mode, the Provider should send the following packet:

0x01010000

where,

  • The first byte (0x01) means this is a Bluetooth event command
  • The second byte (0x01) means to enable silence mode
  • The third and fourth bytes (0x0000) mean no additional data is included

One use case for silence mode is for on-head detection. When the Provider is removed from a user's head, silence mode could be enabled. Likewise, when the Provider is placed on a user's head, silence mode could be disabled.

Companion app events

Using the above message stream support, Providers can send events to their companion app when it is installed on the Seeker device. Note that if the companion app is not installed, these events will be dropped.

Message Group Name Value
Companion app event 0x02
Companion App Event Code Name Value
Log buffer full 0x01

Whenever a message is received by the Seeker with the companion app event group, it will be passed to the companion app registered for the Provider. Specifically, for the log buffer full event, companion apps should register a broadcast receiver that supports the com.google.android.gms.nearby.fastpair.ACTION_LOG_BUFFER_FULL action in their manifest.

Providers should use the log buffer full event to assist in optimizing log collection via their companion app on the Seeker side.

Device information

Providers can notify a Seeker about device information via the message stream.

Message Group Name Value
Device information event 0x03
Device Information Code Name Value
Model ID 0x01
BLE address updated 0x02
Battery updated 0x03
Remaining battery time 0x04
Active components request 0x05
Active components response 0x06
Capabilities 0x07
Platform type 0x08
Model ID

Model ID information (for Retroactively Writing AccountKey) should be sent to the Seeker when RFCOMM connects. For example, 0x03010003AABBCC would be:

  • 0x03: Device information event
  • 0x01: Model ID value
  • 0x0003: Additional data, length 3
  • 0xAABBCC: Additional data, model ID
BLE address

BLE address information (for Retroactively Writing AccountKey) , if available, should also be sent to the Seeker when RFCOMM connects and whenever the address is rotated. For example, 0x03020006AABBCCDDEEFF would be:

  • 0x03: Device information event
  • 0x02: BLE address value
  • 0x0006: Additional data, length 6
  • 0xAABBCCDDEEFF: Additional data, BLE address
Battery updated

For Providers that support battery notifications, battery information can also be sent via RFCOMM. When RFCOMM connects or the battery value changes, an update should be sent. The additional data section of the packet should contain identical data to bytes s + 2, s + 3, s + 4 when advertising battery data over BLE. For example,0x0303000357417F would be:

  • 0x03: Device information event
  • 0x03: Battery value
  • 0x0003: Additional data, length 3
  • 0x57417F: Additional data, battery values
    • 0x57: Left bud value, not charging, 87% battery
    • 0x41: Right bud value, not charging, 65% battery
    • 0x7F: Case value, not charging, unknown battery

Providers can also update remaining battery time (if known), For example, 0x03040001F0 would be:

  • 0x03: Device information event
  • 0x04: Remaining battery time
  • 0x0001: Additional data, length 1 (could be 2 for uint16 if needed.)
  • 0xF0: Additional data, remaining battery time in minutes, 240 minutes
Active components

Seekers may sometimes desire to know which components are currently active, meaning that an action can be taken on them (see Device actions). When the Provider receives a request containing the active components request code (0x05), a response should be returned within 1 second indicating the Provider's current state. The response will use the active components response code (0x06) and contain additional data indicating which components are available.

For a Provider with a single component, the additional data should be set to 0x00 if it is not available. An example of this might be a low power mode where media playback will not be performed. Otherwise, additional data should be set to 0x01.

For headsets with multiple components (for example, a left and right bud), each bit in the additional data represents whether that component is active. An example of an inactive component might be a bud which is in the case and not in use. Specifically for the left and right bud case:

  • 0x00 (0b00000000): Neither bud active
  • 0x01 (0b00000001): Right bud active, left inactive
  • 0x02 (0b00000010): Left bud active, right inactive
  • 0x03 (0b00000011): Both buds active
Capabilities

A Provider may sometimes wish to have knowledge of features that the Seeker which it is connected to supports. For this case, the Seeker will send a capabilities message to the Provider when it connects to provide this information.

The message will contain a list of bits signifying which features are available:

  • Bit 0: 1 if the companion app is installed, 0 otherwise
  • Bit 1: 1 if silence mode is supported, 0 otherwise
  • All other bits reserved for future use and should be set to 0

For example, a Seeker which does not have the companion app installed but does support silence mode would send 0x0307000102 upon connection:

  • 0x03: Device information event
  • 0x07: Capabilities value
  • 0x0001: Additional data, length 1
  • 0x02: Additional data, silence mode supported
Platform Type

Providers may want to perform differently based on the platform that they are connected to. Fast Pair is currently only performed through Android, but support may be expanded in the future.

The message will contain a first byte identifying platform type in the additional data:

Platform Name Value
Android 0x01

The second byte will be customized per platorm. In Android, it will refer to the SDK version. For example, Android Pie will have a value of 28 (0x1C).

Device action

Seekers can request that a Provider takes an action. If the action is supported by the Provider, it should be acknowledged and performed, otherwise it should be ignored.

Message Group Name Value
Device action event 0x04
Device Action Code Name Value
Ring 0x01
Ringing a device

One use case for these actions is the Seeker requesting the Provider to ring, for example when a user has lost the device and needs to locate it. When the ring action is received, the Provider should begin playing a preloaded sound file at a high enough volume that the user is able to locate it. It is recommended that the sound be ramped from a low volume to max volume over time. Ringing should continue until an additional action is received directing a stop, or a timeout value has passed.

Additional data will be included in the message to indicate whether the ringing should be started or stopped, which can be expanded to support Providers with multiple components (a left and right bud). In the first byte, bits will be set to 1 to request a ring to start or 0 to request a ring to stop.

For example, if the first byte of additional data is set to:

  • 0x00 (0b00000000): All components should stop ringing
  • 0x01 (0b00000001): Ring right, stop ringing left
  • 0x02 (0b00000010): Ring left, stop ringing right
  • 0x03 (0b00000011): Ring both left and right

On Providers which do not support individual ringing, only 1 bit should be considered:

  • 0x00 (0b00000000): Stop ringing
  • 0x01 (0b00000001): Start ringing

The second byte in additional data, if present, represents the timeout in seconds. This value should be used by the Provider to determine how long it should ring before silencing itself. Based off of the ring right example above and a timeout of 60 seconds, 0x013C would be passed as the additional data.

Syncing ringing status back to Seekers

Providers may want to notify a Seeker when it changes the ringing status, for example if a gesture causes the ringing to stop. The Seeker can then receive the message and update the UI if necessary.

The Provider should follow the same message format as defined in the example above. Seeker's will listen for this message and provide an acknowledgement when it is received.

Acknowledging an action

When an action is received, it should be acknowledged so that the Seeker knows whether or not the action was performed. If an acknowledgement is not received within 1 second of sending an action (or a negative-acknowledgement is received) the Seeker will assume the action is not currently supported.

Acknowledgements

Some message codes require an acknowledgement from the receiver. In this case, the receiver should send either an acknowledgement (ACK) or negative-acknoledgement (NAK) within 1 second of receiving the message.

Message Group Name Value
Acknowledgement 0xFF
Acknowledgement Code Name Value
ACK 0x01
NAK 0x02

Acknowledgments should be sent directly after message is received so that the sender can act accordingly. An acknowledgment should contain the message group and code for the message that it is referencing. For example, if the Provider receives a message containing the ring action (0x0401), it should acknowledge the action by sending back 0xFF0100020401 where:

  • 0xFF: ACK event
  • 0x01: ACK code
  • 0x0002: Additional data length
  • 0x0401: Additional data, the action message group and code

For a NAK, the reason should also be included as the first byte of additional data. Reasons include:

  • 0x00: Not supported
  • 0x01: Device busy
  • 0x02: Not allowed due to current state

From the previous example, if the ring were to be NAK'ed instead due to the Provider being busy with another task, the returned packet should be set to 0xFF020003010401.

Retroactively Writing Account Key

If a Seeker performs a pairing through the traditional way (for example, through Bluetooth settings) instead of through the Fast Pair entrypoint, there will be no account key written into the Provider. In this case, the user will not be able to see or use any of the Fast Pair features, despite owning a Fast Pair device. To let users be able to get the benefits of Fast Pair, the Provider shall allow the Seeker silently writing account key right after pairing has occurred.

  1. If the Provider is bonded without going through the Fast Pair flow, allow a new account key to be written through the Key-based Pairing method for up to one minute. Only accept one account key to be written during this time.
  2. After the RFCOMM channel is established, the Provider should send the Model ID and BLE address to the Seeker via Message Stream, the Seeker will build GATT connection and start Key-based Pairing procedure.
  3. If an Raw Request with Flags bit 3 set is received, the Provider should verify the bonded device's BR/EDR address is the same as what is included in the request. If not, reject the request.
  4. Because the devices are already bonded, Passkey verification (steps 11 - 20 in the procedure) will be skipped and the Seeker will directly write an account key to the Provider after a shared secret is established.

Appendix

Changelog

Revision Date Comment
01 Initial release of the Google Fast Pair Service.
02 11/15/18 Expand spec to include account based pairing functionality.
03 2/5/20 Expand spec to support advanced features beyond pairing. Add model ID characteristic, add optional battery notification extension, add personalized name, add message stream, add firmware revisions, add retroactively writing account key, removal of A2DP or HFP requirements.
04 7/28/20 Change to new GATT custom characteristics and indicate the deprecated date of the old values on 2021/1/1.

Test Cases

Provided below are tests that a provider’s implementation can run against to verify that many of the pieces are working as expected (specifically, there are cases for hashing, crypto and the bloom filter). Once these underlying tests are passing, implementation of the requests and responses in the procedure outlined above should be more straightforward.

SHA-256 Hashing

Input value:

0x11, 0x22, 0x33, 0x44, 0x55, 0x66

Hashed result:

0xBB, 0x00, 0x0D, 0xDD, 0x92, 0xA0, 0xA2, 0xA3, 0x46, 0xF0, 0xB5, 0x31,
0xF2, 0x78, 0xAF, 0x06, 0xE3, 0x70, 0xF8, 0x69, 0x32, 0xCC, 0xAF, 0xCC,
0xC8, 0x92, 0xD6, 0x8D, 0x35, 0x0F, 0x80, 0xF8

AES Encryption

Input value:

0xF3, 0x0F, 0x4E, 0x78, 0x6C, 0x59, 0xA7, 0xBB, 0xF3, 0x87, 0x3B, 0x5A,
0x49, 0xBA, 0x97, 0xEA

Secret key:

0xA0, 0xBA, 0xF0, 0xBB, 0x95, 0x1F, 0xF7, 0xB6, 0xCF, 0x5E, 0x3F, 0x45,
0x61, 0xC3, 0x32, 0x1D

Encrypted output:

0xAC, 0x9A, 0x16, 0xF0, 0x95, 0x3A, 0x3F, 0x22, 0x3D, 0xD1, 0x0C, 0xF5,
0x36, 0xE0, 0x9E, 0x9C

ECDH Key Exchange

Bob’s private key:

0x02, 0xB4, 0x37, 0xB0, 0xED, 0xD6, 0xBB, 0xD4, 0x29, 0x06, 0x4A, 0x4E,
0x52, 0x9F, 0xCB, 0xF1, 0xC4, 0x8D, 0x0D, 0x62, 0x49, 0x24, 0xD5, 0x92,
0x27, 0x4B, 0x7E, 0xD8, 0x11, 0x93, 0xD7, 0x63

Bob’s public key:

0xF7, 0xD4, 0x96, 0xA6, 0x2E, 0xCA, 0x41, 0x63, 0x51, 0x54, 0x0A, 0xA3,
0x43, 0xBC, 0x69, 0x0A, 0x61, 0x09, 0xF5, 0x51, 0x50, 0x06, 0x66, 0xB8,
0x3B, 0x12, 0x51, 0xFB, 0x84, 0xFA, 0x28, 0x60, 0x79, 0x5E, 0xBD, 0x63,
0xD3, 0xB8, 0x83, 0x6F, 0x44, 0xA9, 0xA3, 0xE2, 0x8B, 0xB3, 0x40, 0x17,
0xE0, 0x15, 0xF5, 0x97, 0x93, 0x05, 0xD8, 0x49, 0xFD, 0xF8, 0xDE, 0x10,
0x12, 0x3B, 0x61, 0xD2

Alice’s private key:

0xD7, 0x5E, 0x54, 0xC7, 0x7D, 0x76, 0x24, 0x89, 0xE5, 0x7C, 0xFA, 0x92,
0x37, 0x43, 0xF1, 0x67, 0x77, 0xA4, 0x28, 0x3D, 0x99, 0x80, 0x0B, 0xAC,
0x55, 0x58, 0x48, 0x38, 0x93, 0xE5, 0xB0, 0x6D

Alice’s public key:

0x36, 0xAC, 0x68, 0x2C, 0x50, 0x82, 0x15, 0x66, 0x8F, 0xBE, 0xFE, 0x24,
0x7D, 0x01, 0xD5, 0xEB, 0x96, 0xE6, 0x31, 0x8E, 0x85, 0x5B, 0x2D, 0x64,
0xB5, 0x19, 0x5D, 0x38, 0xEE, 0x7E, 0x37, 0xBE, 0x18, 0x38, 0xC0, 0xB9,
0x48, 0xC3, 0xF7, 0x55, 0x20, 0xE0, 0x7E, 0x70, 0xF0, 0x72, 0x91, 0x41,
0x9A, 0xCE, 0x2D, 0x28, 0x14, 0x3C, 0x5A, 0xDB, 0x2D, 0xBD, 0x98, 0xEE,
0x3C, 0x8E, 0x4F, 0xBF

Generated shared key (either Alice’s public + Bob’s private or Bob’s public + Alice’s private):

0x9D, 0xAD, 0xE4, 0xF8, 0x6A, 0xC3, 0x48, 0x8B, 0xBA, 0xC2, 0xAC, 0x34,
0xB5, 0xFE, 0x68, 0xA0, 0xEE, 0x5A, 0x67, 0x06, 0xF5, 0x43, 0xD9, 0x06,
0x1A, 0xD5, 0x78, 0x89, 0x49, 0x8A, 0xE6, 0xBA

AES Key from ECDH Shared Secret

This is step 1b in the procedure outlined above.

ECDH shared key:

0x9D, 0xAD, 0xE4, 0xF8, 0x6A, 0xC3, 0x48, 0x8B, 0xBA, 0xC2, 0xAC, 0x34,
0xB5, 0xFE, 0x68, 0xA0, 0xEE, 0x5A, 0x67, 0x06, 0xF5, 0x43, 0xD9, 0x06,
0x1A, 0xD5, 0x78, 0x89, 0x49, 0x8A, 0xE6, 0xBA

Generated AES key:

0xB0, 0x7F, 0x1F, 0x17, 0xC2, 0x36, 0xCB, 0xD3, 0x35, 0x23, 0xC5, 0x15,
0xF3, 0x50, 0xAE, 0x57

Bloom Filter

Random salt:

0xC7

First account key added to the filter (combine with the above random salt):

0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB,
0xCC, 0xDD, 0xEE, 0xFF

Resulting bloom filter:

0x0A, 0x42, 0x88, 0x10

Battery data (if it is contained in the advertisement):

0b00110011, // length = 3, show UI indication.
0b01000000, // left bud: not charging, battery level = 64.
0b01000000, // right bud: not charging, battery level = 64.
0b01000000  // case: not charging, battery level = 64.

Resulting bloom filter with battery data:

0x4A, 0x00, 0xF0, 0x00

Second account key added to the filter (combine with the above random salt):

0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66,
0x77, 0x77, 0x88, 0x88

Resulting bloom filter from both added account keys:

0x2F, 0xBA, 0x06, 0x42, 0x00

Battery data (if it is contained in the advertisement):

0b00110011, // length = 3, show UI indication.
0b01000000, // left bud: not charging, battery level = 64.
0b01000000, // right bud: not charging, battery level = 64.
0b01000000  // case: not charging, battery level = 64.

Resulting bloom filter from both added account keys with battery data:

0x10, 0x22, 0x56, 0xC0, 0x4D

Battery remaining time (if it is contained in the advertisement)

0b00010101, // length = 1, type = 0b0101.
0x1E,       // remaining battery time (in minutes) =  30 minutes.

Resulting bloom filter from both added account keys with battery data and remaining time:

0x32, 0xA0, 0x86, 0xB4, 0x1A

AES-CTR Encryption

Input data: "Someone's Google Headphone" with utf-8 encoding

0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F,
0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F,
0x6E, 0x65

Secret key:

0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF

Nonce:

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07

Expected encryption result:

0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14,
0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1,
0xE5, 0xC6

HMAC-SHA256

Input data:

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83,
0x73, 0x80, 0x52, 0xE4, 0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA,
0x44, 0xB9, 0xE5, 0x53, 0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6

Secret key:

0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF

Expected HMAC-SHA256 result:

0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x61, 0x8B, 0x7D, 0x87,
0x10, 0xD4, 0x41, 0x37, 0x09, 0xAB, 0x5D, 0xA2, 0x7C, 0xA2, 0x6A, 0x66,
0xF5, 0x2E, 0x5A, 0xD4, 0xE8, 0x20, 0x90, 0x52

Encode personalized name to additioal data packet

Input data: "Someone's Google Headphone" with utf-8 encoding

0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F,
0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F,
0x6E, 0x65

Secret key:

0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF

Nonce:

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07

Expected additional data packet:

0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4,
0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53,
0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6

Decode additional data packet to get personalized name

Input data:

0x55, 0xEC, 0x5E, 0x60, 0x55, 0xAF, 0x6E, 0x92, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0xEE, 0x4A, 0x24, 0x83, 0x73, 0x80, 0x52, 0xE4,
0x4E, 0x9B, 0x2A, 0x14, 0x5E, 0x5D, 0xDF, 0xAA, 0x44, 0xB9, 0xE5, 0x53,
0x6A, 0xF4, 0x38, 0xE1, 0xE5, 0xC6

Secret key:

0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF

Expected name: "Someone's Google Headphone" with utf-8 encoding

0x53, 0x6F, 0x6D, 0x65, 0x6F, 0x6E, 0x65, 0x27, 0x73, 0x20, 0x47, 0x6F,
0x6F, 0x67, 0x6C, 0x65, 0x20, 0x48, 0x65, 0x61, 0x64, 0x70, 0x68, 0x6F,
0x6E, 0x65