## Message Authentication Code

[Message streams](https://developers.google.com/nearby/fast-pair/specifications/extensions/messagestream#MessageStream "message stream") are used to configure Audio switch, see
[Audio switch messages](https://developers.google.com/nearby/fast-pair/specifications/extensions/sass#MacOfSassMessages "MAC of Audio switch Messages"). For these important configurations, the Provider needs
to ensure that the message is sent by GMSCore (Fast Pair module) and not any
other app on the Seeker.

> [!NOTE]
> **Note:** Google recommends implementing the [Cryptographic Test Cases](https://developers.google.com/nearby/fast-pair/specifications/appendix/cryptotestcases "Link to the Cryptographic Test Cases.") to ease verification of these requirements.

### Generate MAC (message authentication code)

FP Seeker adds a message authentication code for device configuration messages
using HMAC-SHA256. The MAC of the message consists of the first 8 bytes of:

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

where

1. *K* is generated by concat(account key, 48-byte ZEROs).
2. *message* is the additional data of Message stream.
3. *nonce* is generated by concat(session_nonce, message_nonce); session nonce and message nonce are defined in the following section.
4. *opad* is 64 bytes of outer padding, consisting of repeated bytes valued `0x5C`.
5. *ipad* is 64 bytes of inner padding, consisting of repeated bytes valued `0x36`.

### Session nonce and message nonce

To prevent a replay attack, the Provider needs to ensure that a nonce is not
repeated. Since maintaining clock or counter synchronization on both Provider
and Seeker is not straightforward, the Provider generates the session nonce
(per connection), which is shared with all messages during the connection,
while the Seeker generates the message nonce (per message), which is randomly
generated for each message. The nonce for generating the MAC of each message is
the combination of session nonce and message nonce, i.e.
concat(session_nonce, message_nonce).

We add a session nonce to the Device information event group:

| Message Group Name | Value |
|---|---|
| Device information event | 0x03 |

| Message Code Name | Value |
|---|---|
| Session nonce | 0x0A |

The session nonce should be generated and sent to the Seeker when Message Stream
connects:

| Octet | Data Type | Description | Value |
|---|---|---|---|
| 0 | uint8 | Device information event | 0x03 |
| 1 | uint8 | Session nonce | 0x0A |
| 2 - 3 | uint16 | Additional data length | 0x0008 |
| 4 - 11 |   | session nonce | *varies* |

To send a message when a MAC is required, the Seeker will send a message nonce
and the MAC together with the message.

| Octet | Data Type | Description | Value |
|---|---|---|---|
| 0 | uint8 | Message group | *varies* |
| 1 | uint8 | Message code | *varies* |
| 2 - 3 | uint16 | Additional data length(the additional data length + 16) | *varies* |
| 4 - n |   | Additional data | *varies* |
| n + 1 - n + 8 |   | Message nonce | *varies* |
| n + 9 - n + 16 |   | Message authentication code | *varies* |

### Verify MAC (message authentication code)

Upon receiving a message with the message authentication code, the Provider
shall verify it by using the same function as the generating function. That is,
the received MAC should be equal to the first 8 bytes of

     sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(section_nonce, message_nonce, message)))))

where:

1. *K* is generated by `concat(account key, 48-byte ZEROs)`, and the Provider shall traverse all stored account keys to verify the MAC.
2. *message* is the additional data (excluding message nonce and MAC) of the Message stream.

If the MAC is correct, then the Provider shall follow the instruction of the
message. Otherwise, the Provider shall send a NAK with the error reason, 0x3 -
not allowed due to incorrect message authentication code.