Характеристики
Сервис быстрого подключения
У поставщика быстрого подключения должен быть следующий сервис GATT.
| Сервис | UUID |
|---|---|
| Сервис быстрого подключения | 0xFE2C |
Этот сервис должен иметь следующие характеристики.
| Характеристика сервиса быстрого подключения | Зашифровано | Разрешения | UUID |
|---|---|---|---|
| Идентификатор модели | Нет | Чтение | FE2C1233-8366-4814-8EB0-01DE32100BEA |
| Подключение на основе ключа | Нет | Написать и уведомить | FE2C1234-8366-4814-8EB0-01DE32100BEA |
| Ключ доступа | Нет | Написать и отправить уведомление | FE2C1235-8366-4814-8EB0-01DE32100BEA |
| Ключ аккаунта | Нет | Запись | FE2C1236-8366-4814-8EB0-01DE32100BEA |
Сервис информации об устройстве
Поставщик услуг быстрого подключения также должен поддерживать сервис информации об устройстве.
| Сервис | UUID |
|---|---|
| Сервис информации об устройстве | 0x180A |
Устройство, выполняющее поиск, использует следующие характеристики.
| Название | Зашифровано | Разрешения | UUID |
|---|---|---|---|
| Версия встроенного ПО | Нет | Чтение | 0x2A26 |
Характеристика: идентификатор модели
Эта характеристика позволяет Искателю считывать идентификатор модели по мере необходимости, а не только когда устройство передает данные в режиме обнаружения. Он всегда должен возвращать следующие данные:
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0–2 | uint24 |
Идентификатор модели | изменяется |
Характеристика: сопоставление на основе ключа
Эта характеристика управляет процедурой подключения на основе ключа. В этой процедуре определенный уровень доверия устанавливается путем проверки того, что и Искатель, и Поставщик владеют общим ключом. В каждом случае ключ будет разным:
Случай 1. Предварительно заданный ключ основан на паре открытого и закрытого ключей для защиты от спуфинга и собственной паре открытого и закрытого ключей искателя, которая будет меняться при каждой попытке подключения.
- Поставщик находится в режиме подключения.
- Запрашивающая сторона проверяет, есть ли у Поставщика закрытый ключ для защиты от спуфинга.
Обратите внимание, что в режиме подключения поставщик может также подключаться обычным способом, например к устройству, которое не поддерживает быстрое подключение на основе ключей.
Вариант 2. Общий ключ – это один из ключей аккаунта.
- Поставщик обычно не находится в режиме подключения. (Но это не является обязательным требованием. Поставщик должен поддерживать использование ключа аккаунта даже в режиме подключения.)
- Искатель и Поставщик проверяют, что у каждого из них есть ключ аккаунта.
Поскольку оба случая очень похожи, за исключением того, какой общий ключ используется, они объединены в процедуру.
Формат данных
Инструкции по использованию каждого формата.
| Октет | Тип данных | Описание | Значение | Обязательно? |
|---|---|---|---|---|
| 0–15 | uint128 |
Зашифрованный запрос | изменяется | Обязательно |
| 16–79 | Открытый ключ | изменяется | Необязательно |
Таблица 1.1. Зашифрованный запрос, записанный в характеристику искателем.
| Октет | Тип данных | Описание | Значение | Обязательно? |
|---|---|---|---|---|
| 0 | uint8 |
Тип сообщения | 0x00 – запрос на подключение на основе ключа. |
Обязательно |
| 1 | uint8 |
Flags
|
varies | Обязательно |
| 2–7 | uint48 |
Один из вариантов:
|
varies | Обязательно |
| 8–13 | uint48 |
Адрес BR/EDR искателя | varies | Присутствует, только если установлен бит 1 или 3 в поле Flags |
| n – 15 | Случайное значение (соль) | varies | Обязательно |
Таблица 1.2.1. Необработанный запрос (тип 0x00). расшифрованные из зашифрованного запроса в таблице 1.1.
| Октет | Тип данных | Описание | Значение | Обязательно? |
|---|---|---|---|---|
| 0 | uint8 |
Тип сообщения | 0x10 = запрос действия |
Обязательно |
| 1 | uint8 |
Flags
|
varies | Обязательно |
| 2–7 | uint48 |
Один из вариантов:
|
varies | Обязательно |
| 8 | uint8 |
Групповой чат | varies | Обязательный, если установлен флаг Bit 0 |
| 9 | uint8 |
Код сообщения | varies | Обязательно, если установлен бит 0 флагов. |
| 10 | uint8 |
Зависит от флагов:
|
varies | Обязательно, если установлен бит 0 или 1 флага. |
| 11 – n | Дополнительные данные | varies | Необязательно | |
| n – 15 | Случайное значение (соль) | varies | Обязательно |
Таблица 1.2.2. Необработанный запрос (тип 0x10). расшифрованные данные из зашифрованного запроса, указанного в таблице 1.1.
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0 | uint8 |
Тип сообщения | 0x01 – ответ на запрос о подключении на основе ключа. |
| 1–6 | uint48 |
Общедоступный адрес поставщика (BR/EDR) | varies |
| 7–15 | Случайное значение (соль) | varies |
Таблица 1.3. Необработанный ответ. Зашифрованный ответ, который должен быть создан в соответствии с таблицей 1.4.
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0–15 | uint128 |
Зашифрованный ответ | varies |
Таблица 1.4. Зашифрованный ответ, отправленный Поставщиком Искателю через уведомление.
Характеристика: ключ доступа
Эта характеристика используется во время установления связи на основе ключа.
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0–15 | uint128 |
Зашифрованный блок ключа доступа | varies |
Таблица 2.1. Блок зашифрованного ключа доступа. Инструкции по использованию приведены в разделе Подключение на основе ключа.
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0 | uint8 |
Тип сообщения | Один из вариантов:
|
| 1–3 | unit32 |
6-значный ключ доступа | varies |
| 4–15 | Случайное значение (соль) | varies |
Таблица 2.2. Блок необработанных ключей доступа. Расшифрованная версия таблицы 2.1.
Характеристика: ключ аккаунта
После подключения искатель быстрого подключения запишет ключ аккаунта в поставщик быстрого подключения.
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0–15 | uint128 |
Ключ аккаунта (зашифрованный) | varies |
При получении запроса на запись поставщик быстрого подключения должен выполнить следующие действия:
- Расшифруйте ключ аккаунта, используя секретный ключ, созданный на шаге 4 процедуры.
- Для поставщиков, которым требуется страхование ответственности (распространенный случай):
- Перед расшифровкой убедитесь, что для расшифровки запроса ключа доступа из шага 12 использовался общий секрет. Если этот шаг не пройден с использованием этого секрета, проигнорируйте запись и выйдите.
- На этом этапе общий секрет (K в процедуре) больше не будет использоваться для этой пары. Все запросы, зашифрованные этим ключом, должны отклоняться без перезапуска процедуры.
- Для поставщиков, которым требуется страхование ответственности (распространенный случай):
- Убедитесь, что расшифрованное значение начинается с
0x04или0xFF. Если нет, проигнорируйте эту запись и выйдите.- Если значение равно
0x04:- Проверьте, есть ли в сохраненном списке ключей аккаунта место для нового значения.
- Если нет, удалите из списка значение, которое использовалось раньше всех.
- Добавьте в список новое значение.
- Если значение равно
0xFF:- Рассматривайте это как временный сеанс подключения и не выполняйте никаких действий.
- Это может произойти при ретроактивной записи ключа аккаунта.
- Не храните ключ и не используйте его в списке ключей аккаунта, для шифрования или вычисления MAC.
- Удаление связи запускается событием, относящимся к определенной функции, или по истечении времени ожидания. При использовании функции передачи аудио LE настоятельно рекомендуется удалить связь BLE и ключ связи через 10 минут после отключения временного сеанса.
- Если значение равно
Ключи аккаунта из списка используются при создании пары на основе ключа.
Характеристика: версия встроенного ПО
Эта характеристика позволяет устройству Seeker при необходимости считывать версию встроенного ПО устройства Provider. Он должен возвращать следующие данные:
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0 – var | utf8s |
Код версии встроенного ПО | varies |
Она должна быть представлена в виде одной строки UTF-8, даже если у Поставщика несколько встроенных ПО (например, три встроенных ПО для левого наушника, правого наушника и чехла). Поставщик также может возвращать определенные строки для особых случаев:
status-updating – если поставщик в данный момент обновляет встроенное ПО. В качестве альтернативы поставщик может вернуть версию подготовленной прошивки.
status-abnormal – если поставщик находится в аномальном состоянии. Например, он неисправен, потому что не удалось обновить встроенное ПО. В этом случае Seeker покажет сообщение о том, что его нужно обновить.
Поставщик должен ограничить доступ к характеристике "Версия прошивки", чтобы предотвратить отслеживание устройства. Рекомендуемые ограничения:
- У связанных устройств должен быть доступ в любое время.
- любое устройство должно иметь доступ, когда поставщик виден;
Если поставщик поддерживает функцию "Найти на канале", необходимо выполнить дополнительные действия. Подробнее об обновлениях встроенного ПО Портала поиска…
Характеристика: дополнительные данные
Этот сервис должен иметь следующие характеристики.
| Характеристика сервиса быстрого подключения | Зашифровано | Разрешения | UUID |
|---|---|---|---|
| Данные | Нет | Написать и уведомить | FE2C1237-8366-4814-8EB0-01DE32100BEA |
| Старая характеристика сервиса быстрого подключения (планируется прекратить поддержку 1 января 2021 г.) | Зашифровано | Разрешения | UUID |
|---|---|---|---|
| Данные | Нет | Написать и уведомить | 0x1237 |
Прежде чем записывать или уведомлять об этой характеристике, необходимо выполнить рукопожатие через характеристику FE2C1234-8366-4814-8EB0-01DE32100BEA, чтобы получить общий секретный ключ. Для шифрования данных, передаваемых через эту характеристику, будет использоваться алгоритм AES-CTR, описанный ниже. Этот режим обеспечивает более высокий уровень безопасности для данных, размер которых превышает один 16-байтовый блок. Для обеспечения целостности данных будет использоваться алгоритм HMAC-SHA256.
| Октет | Описание | Значение |
|---|---|---|
| 0–7 | Первые 8 байт HMAC-SHA256. | varies |
| 8–15 | Nonce, используемый при шифровании AES-CTR. | varies |
| 16 – var | Зашифрованные данные. | varies |
Таблица 3.1. Пакет данных, отправленный Поставщиком Искателю с помощью уведомления или отправленный Искателем Поставщику с помощью записи.
| Октет | Тип данных | Описание | Значение |
|---|---|---|---|
| 0 – var | byte array |
Данные | varies, декодируйте его в соответствии с идентификатором данных из таблицы 1.2.2:
|
Таблица 3.2. Необработанные данные. Расшифровано из зашифрованных данных в таблице 3.1.
Когда запрашивается уведомление (например, запрос персонализированного имени через бит 2 в таблице 1.2.1), поставщик Быстрого подключения должен выполнить следующие действия:
- Сгенерируйте криптографически случайные 8 байт для одноразового кода.
Зашифруйте данные с помощью AES-CTR, где каждый 16-байтовый блок генерируется с помощью
encryptedBlock[i] = clearBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))где
- Ключ AES – это общий секретный ключ, полученный на шаге 4 процедуры.
- clearBlock[i] – это 16-байтный блок, начинающийся с data[i * 16]. Последний блок может быть меньше 16 байтов.
Выполните concat(encryptedBlock[0], encryptedBlock[1],…), чтобы создать зашифрованные данные.
Сгенерируйте HMAC-SHA256 с помощью
sha256(concat((K ^ opad), sha256(concat((K ^ ipad), concat(nonce, encrypted_data)))))где
- K создается с помощью функции concat(shared_secret, 48-byte ZEROs), где shared_secret – это секретный ключ, полученный на шаге 4 процедуры.
- opad – внешнее дополнение размером 64 байта, состоящее из повторяющихся байтов со значением
0x5C. - ipad – это внутренний отступ размером 64 байта, состоящий из повторяющихся байтов со значением
0x36.
Возьмите первые 8 байт из HMAC-SHA256 в качестве префикса пакета данных.
При получении запроса на запись поставщик быстрого подключения должен выполнить следующие действия:
- Проверьте целостность данных, используя первые 8 байт HMAC-SHA256.
Расшифруйте зашифрованные данные с помощью алгоритма AES-CTR, где каждый блок генерируется с помощью
clearBlock[i] = encryptedBlock[i] ^ AES(key, concat((uint8) i, 0x00000000000000, nonce))где
- encryptedBlock[i] – это 16-байтный блок, начинающийся с encrypted_data[i * 16]. Последний блок может быть меньше 16 байтов.
- Ключ AES генерируется или определяется на основе рукопожатия, например:
- В первом варианте он получен по протоколу ECDH и больше не будет использоваться для этого подключения. Все запросы, зашифрованные с помощью этого ключа без перезапуска процедуры, должны быть отклонены.
- в процессе именования 2 – ключ аккаунта.
Выполните concat(clearBlock[0], clearBlock[1],...), чтобы создать необработанные данные.