Найти в Дзене
mamaich

Немного про keymaster на примере Яндекс IP камеры

Каждое устройство Яндекс содержит в себе приватный ключ RSA, который используется при регистрации устройства в умном доме, а также при ряде критичных, с точки зрения Яндекса, операций. При отправке подобных запросов, в заголовке запроса указывается серийный номер устройства, заголовок подписывается RSA ключом устройства, а сервер Яндекса по серийнику находит у себя публичную часть ключа и проверяет соответствует ли ей подпись. Именно поэтому не работают станции, в которые залили чужой дамп или стерли раздел с ключами - подпись не сходится. Как можно подсунуть чужой серийник не перепаивая процессор, я, по понятным причинам, описывать не буду (хотя это довольно просто), но про то, как создаются подписи расскажу. Взаимодействие с RSA ключом происходит не напрямую, а через механизм keymaster. В документации Android про keymaster написано довольно много и сложно, но, к счастью, вникать в нее не требуется, так как Яндекс при взаимодействии с серверами умного дома использует только три опера

Каждое устройство Яндекс содержит в себе приватный ключ RSA, который используется при регистрации устройства в умном доме, а также при ряде критичных, с точки зрения Яндекса, операций. При отправке подобных запросов, в заголовке запроса указывается серийный номер устройства, заголовок подписывается RSA ключом устройства, а сервер Яндекса по серийнику находит у себя публичную часть ключа и проверяет соответствует ли ей подпись. Именно поэтому не работают станции, в которые залили чужой дамп или стерли раздел с ключами - подпись не сходится.

Как можно подсунуть чужой серийник не перепаивая процессор, я, по понятным причинам, описывать не буду (хотя это довольно просто), но про то, как создаются подписи расскажу.

Взаимодействие с RSA ключом происходит не напрямую, а через механизм keymaster. В документации Android про keymaster написано довольно много и сложно, но, к счастью, вникать в нее не требуется, так как Яндекс при взаимодействии с серверами умного дома использует только три операции - подпись, расшифровку и экспорт публичного ключа.

На Linux устройствах, к которым относится IP камера, Яндекс нам любезно предоставляет утилиту keymaster_proxy_app (на самом деле это линк на maind):

Эта утилита принимает первым параметром имя сокета keymaster. Он может быть "/dev/keymaster_svc" (на старых станциях и на устройствах с Linux) или "/dev/socket/sign" (на YaOS). Второй параметр - операция: sign, decrypt, show-key. На современных устройствах команды upgrade-key, generate-key, force-generate-key не реализованы на стороне keymaster сервера и поэтому не работают. Говорят, они работали на первой станции и Лайте, но я сам не проверял.

Расскажу коротко про то, как самостоятельно повторить подпись запроса к серверам Яндекса. В качестве примера возьму запрос регистрации устройства в умном доме (о том, как перехватывать/подменять трафик устройств я писал ранее). Вот так выглядит запрос с моей IP камеры:

-2

Запрос содержит серийный номер и подписан с использованием RSA ключа из keymaster. Чтобы декодировать заголовок X-Quasar-Signature, необходимо сперва преобразовать его из url-encode в обычную текстовую строку. Например, это можно сделать онлайн:

-3

Полученную строку декодируем из base64, и получаем такой набор шестнадцатеричных байт:

-4

А теперь попробуем получить эти же байты самостоятельно.
Устройство подписывает только строку параметров запроса. В моем случае это всё, что идет после вопросительного знака (выделил жирным):

https://quasar.yandex.net/register?device_id=W0хххххххххххх&name=quasar&activation_code=697191053&firmware_version=0.306.1.11.3230930801.20250718.37&platform=mike&ts=1753442625

Создаем текстовый файл "tosign" с данной строкой:

никаких пробелов или переводов строки в конце файла!
никаких пробелов или переводов строки в конце файла!

После чего обрабатываем его утилитой keymaster_proxy_app.

/system/vendor/quasar/keymaster_proxy_app /dev/keymaster_svc sign tosign signed
-6

Смотрим содержимое файла signed - совпадает с тем что было выше:

-7

На устройствах с YaOS утилита keymaster_proxy_app отсутствует. Можно скопировать maind и все нужные библиотеки (я так делал) - но это довольно муторно, да и скорость работы утилиты оставляет желать лучшего. Поэтому я решил написать свой аналог keymaster_proxy_app.

Утилита реализует протокол взаимодействия с keymaster сервером на основании keymaster_proxy_client.proto, который можно сдампить из maind утилитой protodump. Сервер ожидает пакет такого вида:

dword: magic number (0x42fa851f в кодировке big endian)
dword: длина protobuf (тоже big endian)
dword: данные protobuf

Ответ приходит в аналогичном формате.

Код утилиты очень простой и содержит комментарии (спасибо ИИ, который его написал за меня), так что описывать его не вижу смысла.

По аналогии с клиентской частью я написал и свой keymaster сервер, который, на удивление, заработал. О нем, и о том, как я получил приватный RSA ключ с камеры, я напишу как-нибудь в другой раз.