Сомнительное, на мой взгляд, высказывание все же подкреплено нелегкой участью первой версии Surface RT и удивительной похожестью на него нового Surface 2. Однако, наша компания всегда в первую очередь шла на поводу клиентов.
Суть данной статьи, которая может показаться читателям Хабра немного провокационной, заключается в следующем: в конце 2013 года мы представляем новый продукт — электронный ключ Guardant Code micro для защиты приложений на Windows RT от пиратства. Кто-то, возможно, уже крутит пальцем у виска, но мы действительно предлагаем разработчикам серьезных (!) приложений под Windows RT защитить свой софт с помощью аппаратного ключа.
В статье вы узнаете:
- Зачем нам понадобилась Windows RT 8.1 и чем плоха первая Windows RT с точки зрения наших задач.
- Как вся эта конструкция работает.
- Как ограниченность архитектуры не позволила нам обеспечить поддержку электронного ключа в виде microSD-карты.
- … и какими костылями ее можно обойти.
Первый контакт
Еще до релиза Surface мы обсуждали возможность расширения списка наших целевых платформ на Windows RT. Все же определенная вера в Microsoft присутствовала, к тому же, у них есть деньги. С деньгами и правильным подходом раскрутить на рынке можно что угодно — хотя пока это у них не особо получается. При этом, Android тоже стал королем рынка смартфонов не за один день — так что время покажет правильность стратегии MS. В любом случае, мы раздобыли первую версию Surface еще год назад, пристально ее изучили и решили ничего не делать. Опасно лезть на несуществующий рынок с нашими продуктами — нужно было подождать результатов продаж Surface за пару кварталов и оценить интерес нашей категории клиентов.
Подождали, сделали выводы — и положили Surface в дальний ящик стола.
Такой статус проекта продержался до середины лета 2013 года, когда Microsoft [видимо от безысходности] решила дать толчок своему продукту и стала раздавать его практически бесплатно в сферу образования (я утрирую, конечно), а также сделала прайс-дроп для всех остальных. А в сфере образования, на самом деле, есть серьезные продукты и есть пиратство. Итак, вводные данные на июль 2013 года: есть «перспективная» платформа, есть заинтересованные клиенты, есть готовая база в виде проекта Guardant Mobile (ориентирован на Android с ключами microSD и USB). Приступаем к работе.
Неудачная попытка
Начали мы с нашего самого молодого и очень нишевого продукта: Guardant SD. Он представляет из себя карточку microSD с микроконтроллером (с аппаратным ускорением криптографии) и 4Гб памяти общего назначения. Эта вещь позволяет загружать в себя и исполнять на борту апплеты на Java с помощью весьма простого API. Архитектурно все очень похоже на наш ключ Guardant Code, и заточено под защиту приложений. Дорогих бизнес-приложений, например, «Мобильный официант» на Android-планшетах. Смысл такой: выносим важную часть Java-кода в апплет, встраиваем вызовы нашего API на место вырезанного кода — и все, часть кода теперь исполняется на карте, приложение помимо набора байтов получает некопируемый аппаратный артефакт и пиратству говорится решительное нет. Это работает на Android, Windows, Linux и мы пытались заставить это работать на Windows RT.
Не получилось. Подстава пришла из, скажем так, частичной ограниченности Windows RT.
Началось все с того, что замечательная, удобная и ориентированная на пользователя Windows RT категорически отказывается видеть файлы с флагом «скрытый». В принципе, зачем они нужны конкуренту айпада. Лирическое отступление: обмен с ключом происходит через обычный файл на карточке, который по умолчанию создается микроконтроллером в виде скрытого. Собственно, заставить Surface увидеть этот файл оказалось фактически невозможно.
Однако, в реальности это преодолимо. Если провести предпродажную подготовку карточки на любой другой платформе — можно насильно создать этот файл нескрытым, и микроконтроллер этот флаг не тронет. Конечно, первое же форматирование карты или удаление файла сделает ключ неработоспособным, но всегда можно заново этот файл создать.
Настоящая проблема пришла из другого места, хотя оно и рядом по сути. Происходило все так: мы спортировали основую часть кода (основу низкоуровневой библиотеки реализующей протокол обмена с карточкой), попытались послать в карточку APDU — и не можем продвинуться дальше первой команды. Ощущение, что микроконтроллер просто не хочет давать нам ответы. В общем, недолго нам пришлось рыться в интернете и терзать производителя микроконтроллера: в Windows RT обнаружилась неотключаемая буферизация чтения. Т. е. отправить в карточку запрос и зафлашить запись удается, а вот считать ответ нельзя — он его берет из буфера. Очевидно, Windows RT не может предположить, что файл на карточке может быть изменен изнутри ее, в нашем случае силами микроконтроллера. Сотня человеко-часов дорогостоящей разработки хотя и была практически спущена в унитаз, но позволила нам лучше изучить платформу.
Естественно, мы перерыли всю документацию и интернет, пообщались с представителями Microsoft, но получили линейкой по рукам и оставили этот проект — нельзя, так нельзя.
Однако, наши инженерные умы не готовы были сдаться так легко. Сложно было поверить, что не найдется пара костылей позволяющих обойти это ограничение. Они нашлись. Вот рецепт из двух шагов:
- Создаем на карточке файл для обмена размером 400 Мб.
- Заставляем микропрограмму писать ответы микроконтроллера последовательно, а не все время в начало файла.
И вот оно, ненадежное и кривое — но работающее решение. При таком размере файла Windows RT не решается кэшировать его на чтение полностью, а так как ответ все время пишется по новому адресу в файле обмена — то он прекрасно считывается. Медленно — в силу размера файла — но считывается.
Несмотря на найденное решение, оно не пошло в продакшн из-за следующих опасений:
- Значительное увеличение RAM в будущих Surface может позволить Windows RT все же закэшировать этот файл на чтение целиком (или хотя бы значительными частями);
- Мы отъедаем заметную часть из 4Гб флеш-памяти карточки (а слот для microSD в планшете единственный);
- Когда 400Мб кончатся, ответы надо зациклить и писать в начало файла — а там уже что-то может быть закэшировано;
- Работает все это довольно медленно.
Конечно, мы порадовались своей изобретательности, но решили попробовать адаптировать Guardant Code micro USB к планшету. Благо, USB-порт там гарантирован и микро-ключ особо не мешается.
Вторая неудачная попытка
Решив, что c USB-ключом мы на эти проблемы не натолкнемся, мы ринулись в бой. Перевели ключ в HID-режим, воткнули в планшет — ключ определился, светодиод горит. Можно начинать обмен данными.
Нас опять ждало разочарование. В WinRT API не нашлось ни единого способа послать что-то в кастомное USB устройство, даже несмотря на нашу честную поддержку HID. Microsoft, конечно, проектировало Windows RT в качестве закрытой экосистемы (операционка, железо, безальтернативный магазин приложений) — но это уже бессовестная закрытость.
К концу июля ситуация сложилась следующая: руки опускаются, наши устройства к Surface не адаптировать, пора говорить клиентам решительное и обоснованное «нет». И тут мы обращаем внимание на анонсированную Windows RT 8.1, и уже доступную Preview-версию.
Третья попытка, удачная
На Windows RT (в частности на Surface) реализован довольно принудительный Windows Update. Таким образом, можно предположить, что у большинства пользователей Surface (каким бы малым не казалось их число) обновление до 8.1 не заставит себя долго ждать. При этом, в новой версии нас ждал приятный сюрприз: поддержка работы с произвольными HID-устройствами. Как упоминалось ранее, наши современные электронные ключи могут работать как с проприетарным протоколом, требующим драйвера — так и в режиме HID. Работа без драйвера немного снижает скорость и защищенность обмена, но не создает никакой критичной ситуации. Так как для мобильных платформ мы поддерживаем только Code, защищенность все равно упирается в тот код, который клиент перенесет из приложения для исполнения его на борту ключа.
Процесс разработки для Windows 8.1 был предсказуемо успешным. Новые API от MS отрабатывали отлично даже в Preview версии, и мы не столкнулись ни с какими существенными сложностями. И наконец, с третьей попытки у нас появился продукт для защиты от пиратства на Windows RT.
Фактически, разработанная библиотека позволяет разбить приложение на две части:
- Приложение для Windows Store.
- Ключевая интеллектуальная часть, вынесенная в ключ Code (до 50 000 строк кода на С).
Вызов кода происходит единственной функцией CodeRun, с входным и выходным буфером и селектором (чтобы сделать switch внутри и выбрать для исполнения нужный фрагмент кода). Разумеется, можно создавать сколь угодно хитрую логику с помощью буферов для максимального затруднения анализа.
По сути, получаем две вещи «по цене одной»: при удачном выборе загружаемого кода имеем защиту от анализа и модификации (важный код внутри ключа), и, разумеется, получаем некопируемую сущность в виде аппаратного ключа, составляющую неотъемлемую часть приложения.
И несколько важных вещей напоследок:
- В манифест приложения нужно руками добавлять строки для разрешения работы с донглом;
- Даже самое безобидное обращение к ключу требует подтверждения через GUI-диалог, так что с библиотекой модульных тестов без GUI это даже не протестировать — будет исключение;
- Нельзя обращаться к ключу из основного потока программы.
На данной ноте свой рассказ про Windows RT и копирайт я заканчиваю. Насколько нужны и уместны аппаратные ключи защиты в конце 2013 года на еще не раскрутившейся платформе — покажет время. По меньшей мере MS смогла выручить $400 миллионов с продаж Surface в прошлом квартале, это уже хороший знак, особенно после списания $900 миллионов в позапрошлом.