Введение

Летом 2015 года перед нами, разработчиками «Кода безопасности», встала задача реализации защищенного хранилища под Android с шифрованием по стандартам, признанным российским законодательством. До этого у нас уже было решение на планшете, к которому имелись исходники Android. И это позволило нам выпустить обновленное ядерное шифрование (dm-crypt) под поддержку ГОСТ 89, добавить в /system/lib ГОСТ-библиотеки, пропатчить cryptofs подсистему демона vold. В итоге в нашем распоряжении оказалось решение, которое подходило лишь для определенной модели планшета, и не являлось универсальным. Узнав, что в Android версии 4.4 (API уровня 19) появился API, позволяющий осуществлять доступ к данным после регистрации и реализации своего кастомного DocumentsProvider, мы решили создать решение, использующее GOST-шифрование в userspace с использованием данного API, которое не зависело бы от модели устройства.
Для тех, кто заитересовался — добро пожаловать под кат.


Как в Android данные шифруются

Кратко опишу процесс шифрования Android-устройства. Активируется шифрование следующим образом: Settings > Security > Encrypt tablet/phone, реализуется средствами linux kernel > dev-mapper > dm-crypt. При активации данной функциональности устройство запросит пароль, а также попросит сохранить и зашифровать данные из /data (или просто удалит все данные по желанию пользователя). После перезагрузки устройства появится окно ввода пароля, в системных настройках переменная ro.crypto.state будет установлена в состояние encrypted.

Стандартное шифрование разделов в Android базируется на модели FDE (full-disk encryption). Модель является обычной подсистемой ядра Linux – device mapper и обеспечивает прозрачное шифрование. Доступ к данным (например, к разделу /data) предоставляется через виртуальное блочное устройство /dev/block/dm-0, которое каждый io-request шифрует или расшифровывает в режиме AES-CBC на 128-битном секторном ключе, который вычисляется от IV (инициализационного вектора).

image
Рис. 1: Логическая схема шифрования Android

На схеме представлена последовательность запроса Pin от ключевого контейнера и установки master-key через syscall ioctl в ядерную часть dm-crypt.

Access framework (SAF)

Для применения приложения в java-space мы используем Storage Access Framework (SAF), или платформу доступа к хранилищу. На сайте developer.android.com довольно подробно описаны все свойства и нюансы использования этой платформы, здесь мы отметим лишь основные моменты.

Итак, SAF появилась в Android версии 4.4 (API уровня 19) и она облегчает пользователям поиск и открытие документов, изображений и других файлов в хранилищах всех поставщиков. Стать поставщиком этих файлов мы можем, реализовав класс DocumentsProvider и использовав несколько его методов (об этом ниже).

Вся платформа SAF состоит из следующих элементов:

1) «Клиент» – приложение, которое хочет получить доступ к файлу или создать новый файл. Для всей Android-системы это возможно с помощью интентов с флагами ACTION_OPEN_DOCUMENT и ACTION_CREATE_DOCUMENT соответственно.
2) «Поставщик документов» – наше приложение, которое, как упоминалось выше, является подклассом класса DocumentsProvider и реализует доступ к файлам через API (об этом далее).
3) «Элемент выбора» – системный пользовательский интерфейс, обеспечивающий пользователям доступ к файлам всех поставщиков, удовлетворяющих критериям поиска.

Теперь подробнее. Поставщик документов предоставляет один или несколько корневых каталогов, являющихся отправными точками при обходе дерева документов. Каждый корневой каталог имеет уникальный идентификатор COLUMN_ROOT_ID и указывает на документ (каталог), представляющий содержимое на уровне ниже корневого. Корневые каталоги динамичны по своей конструкции, что обеспечивает поддержку различных вариантов использования: нескольких учетных записей, временных хранилищ на USB-накопителях, возможности входа/выхода в систему/из системы.

Каждый сервер хранилища показывает отдельные файлы и каталоги, ссылаясь на них с помощью уникального идентификатора COLUMN_DOCUMENT_ID (в нашем случае, это полный путь от корня файловой системы до самого файла). Идентификаторы документов должны быть уникальными и не меняться после присвоения, поскольку они используются для выдачи постоянных URI, не зависящих от перезагрузки устройства.

Документ – это либо открываемый файл (имеющий конкретный MIME-тип), либо каталог, содержащий другие документы (с MIME-типом MIME_TYPE_DIR). Каждый документ может иметь различные свойства, описываемые флагами COLUMN_FLAGS, такими как FLAG_SUPPORTS_WRITE, FLAG_SUPPORTS_DELETE и FLAG_SUPPORTS_THUMBNAIL.

image
Рис. 2: Модель данных поставщика документов

Модель данных поставщика документов основана на традиционной файловой иерархии. Однако физический способ хранения данных остается на усмотрение разработчика при условии, что к ним можно обращаться через API-интерфейс DocumentsProvider. Например, можно использовать для данных облачное хранилище на основе тегов.

Обратите внимание на следующий рисунок:
image
Рис. 3: Модель взаимодействия поставщика документов и клиента

На платформе SAF поставщики и клиенты не взаимодействуют напрямую. Клиент запрашивает разрешение на взаимодействие с файлами (на их чтение, редактирование, создание или удаление).

Взаимодействие начинается, когда приложение (в нашем примере – обрабатывающее фотографии) активирует намерение ACTION_OPEN_DOCUMENT или ACTION_CREATE_DOCUMENT. Намерение может включать в себя фильтры для уточнения критериев, например, «предоставить открываемые файлы с MIME-типом image».
Когда намерение срабатывает, системный элемент выбора переходит к каждому зарегистрированному поставщику и показывает пользователю корневые каталоги с контентом, соответствующим запросу. Элемент выбора предоставляет пользователю стандартный интерфейс, даже если поставщики документов значительно различаются.

В Android версии 4.3 и ниже приложение для получения файла от другого приложения должно активировать намерение, например, ACTION_PICK или ACTION_GET_CONTENT. После этого пользователь должен выбрать одно из приложений, а оно должно предоставить пользователю интерфейс, с помощью которого он сможет выбирать и получать файлы.

image
Рис. 4: Диалог выбора поставщика документов

image
Рис. 5: Диалог выбора получателя документа

Регистрация как document provider
Следующим шагом в разработке собственного поставщика документов является создание подкласса абстрактного класса DocumentsProvider. Как минимум необходимо реализовать следующие методы:

queryRoots ()
queryChildDocuments ()
queryDocument ()
OpenDocument ()

Реализация данных методов строго обязательна, однако для реализации полнофункционального приложения придется реализовать и другие. Подробности приводятся в описании класса DocumentsProvider.

JNI
Следующая логическая часть – это JNI-реализация прослойки между нашей реализацией SAF и открытой библиотекой файловой системы для встраиваемых систем FATFS. Последняя была пропатчена на чтение-запись на файл (в нашем случае он выступает томом) поблочно. Таким образом, на IO-запрос мы получаем номер сектора и количество секторов, отсюда можно вычислить IV и секторный ключ, а затем зашифровать и расшифровать конкретный блок на файле. В итоге у нас получается аналог dm-crypt в userspace.

image
Рис. 6: Проброс методов SAF в нативную часть и обратно

Далее мы реализовали методы для работы с томами и файлами. Для работы с томами используем следующие функции:

Java_com_securitycode_fatfslib_FatFs_createVolume (...);
Создает файл тома через библиотеку файловой системы и создает внутри этого файла пустую шифрованную FS.

image
Рис. 7: Создание защищенного хранилища

Java_com_securitycode_fatfslib_FatFs_getVolumeFreeSpace (...);
Передав в функцию определенный том, мы получаем количество свободного места в этом томе.

Java_com_securitycode_fatfslib_FatFs_mount (...);
При монтировании тома мы устанавливаем мастер-ключ, с помощью которого будет происходить шифрование-расшифрование блоков FS.

image
Рис.8: Монтирование защищенного хранилища

Java_com_securitycode_fatfslib_FatFs_unMount (...);
Очистка ресурсов и завершение операций ввода-вывода.

Для работы с файлами:

Java_com_securitycode_fatfslib_FatFs_createFile (...);
На нашей файловой системе создается объект пустого файла с заданными размером и типом (необходим для SAF).

Java_com_securitycode_fatfslib_FatFs_getFile (...);
Данная функция необходима для SAF-метода queryDocument (...).
В функции мы возвращаем id файла, его тип, корневой узел, содержащий текущий файл и имя файла.

Java_com_securitycode_fatfslib_FatFs_readFile (...);
В данной функции создается Java-stream, который используется в SAF и в качестве URI передается потребителю.

Java_com_securitycode_fatfslib_FatFs_writeFile (...);
Аналогично предыдущей функции, только в данном случае потребителем становимся мы.

image
Рис.9: Общий экран приложения

image
Рис.10: Содержимое хранилища

Заключение
В результате всех вышеперечисленных действий мы получили криптодиск с поддержкой ГОСТ-шифрования и электронной подписи в userspace.
Будем рады ответить на ваши вопросы и более подробно рассказать обо всех этапах проекта.

Источники:

1) Nikolay Elenkov. Android Security Internals, Chapter 10: Device Security.

2) Шифрование диска в Android
source.android.com/security/encryption

3) Documents Provider и SAF
developer.android.com/intl/ru/guide/topics/providers/document-provider.html

4) FatFs — Generic FAT File System Module
elm-chan.org/fsw/ff/00index_e.html

Комментарии (36)


  1. raiSadam
    30.03.2016 07:41

    Отличная статья. И на злобу дня, учитывая судебный иск к apple на взлом.
    Как на счет сертификации этого решения в контролирующих органах (ФСТЭК, МО или ФСБ)?


    1. IgnisFatuus
      30.03.2016 08:46

      В данный момент полным ходом идет сертификация других продуктов компании, для данного продукта сертификация тоже предусмотрена, но позже.


      1. Abir4eg
        30.03.2016 14:57

        А под какой класс планируете? КС1?
        Будет интересно ключи хранить где-нибудь на синеглазом Рутокене.


        1. IgnisFatuus
          30.03.2016 15:19

          С Рутокен-устройствами работаем сейчас в одном из проектов. Столкнулись с тем, что при включении, (говорю по памяти, точные цифры надо утчнять)- на многих девайсах Рутокен очень долго инициализирует связь/обмен ключами и прпр. Очень долго — это примерно от 40 секунд до 2 минут. В проекте, который описан в статье это может и не так критично -один раз инициализировал, получил ключи и работай (какое-то время), но есть некоторые use-case в которых это может доставлять пользователям существенные неудобства


  1. SannX
    30.03.2016 08:02

    Для инфо: вот тут описаны особенности FDE в Android разных версий и примеры взлома/брутфорса паролей/ПИНов. Например, в версии 4.4, если ПИН короткий (4 симв.), то взломать можно за 5 мин. Так что длина пароля имеет значение, а просто наличие шифрования не обеспечивает достаточную защиту.


  1. icoz
    30.03.2016 08:44

    Ссылка на исходники где? Или хотя бы сертификат регулятора?


    1. IgnisFatuus
      30.03.2016 08:50

      Во-первых продукт сейчас в бета-тестировании. Выкладывать его в таком виде немного преждевременно. Во-вторых комментарии выше я указал, что сертификация на данный продукт пока не начиналась (но есть в планах).


      1. kpoxxx
        30.03.2016 09:33

        А бета-тестером как стать? Или это внутреннее бета-тестирование?


        1. IgnisFatuus
          30.03.2016 09:36
          +1

          Сейчас проходит внутреннее тестирование, но в будущем возможно и открытое тестирование. По таким вопросам можно смело обращаться к нам через наш официальный сайт — что-нибудь придумаем!


  1. amarao
    30.03.2016 11:04
    -2

    Криптопродукт без открытых сырцов? Ну-ну.


    1. IgnisFatuus
      30.03.2016 11:32
      +1

      Цель статьи — рассказать о том как можно реализовать свой кастомный криптодиск в userspace. Как я уже упоминал — сейчас идет закрытый бета-тест. Повторюсь — если Вы хотите получить исходный код или поучаствовать в тестировании/опробовать продукт — добро пожаловать на наш официальный сайт — мы всегда охотно идем на сотрудничество.


    1. bonv
      30.03.2016 14:57
      +1

      А много Вы знаете криптопровайдеров с открытым кодом с поддержкой ГОСТ и сертифицированные ФСБ?


      1. amarao
        30.03.2016 15:14
        +1

        Каким образом сертификация ФСБ улучшает критографическую стойкость продукта?
        Есть два типа криптографии: чтобы защищать информацию, и чтобы пилить бабло. Первое подразумевает публичный аудит и надёжность, второе — сертификаты, сертификаты, сертификаты.


        1. bonv
          30.03.2016 15:44

          Каким образом сертификация ФСБ улучшает критографическую стойкость продукта?

          Я этого не утверждал.
          Сертификат дает право использовать это ПО для юридически значимого документооборота и не более.


        1. IgnisFatuus
          30.03.2016 15:56

          Не думаю, что сертификация ФСБ как-то негативно скажется на проекте с ГОСТ-шифрованием. Это даже будет плюс. Сертификат в купе с открытостью ГОСТ-алгоритмов как раз и обеспечивает безопасность.


        1. milabs
          31.03.2016 14:05

          Ну как бы, опыт OpenSSL говорит о том, что открытость и возможность аудита не являются критерием надёжности.


          1. amarao
            31.03.2016 15:57

            Как раз является. Потому что в другом софте оно бы так и осталось непопатченным и неотслеженным.
            Опенсорс не является панацеей от багов, но точно прикрывает "NSA sponsored random". Кстати, сертификация ФСБ вызывает у меня аналогичные вопросы — какие именно требования по наличию бэкдоров предъявляет ФСБ к сертифицируемым продуктам?


            1. milabs
              31.03.2016 18:19
              +1

              Это важный фактор, но не решающий. Так же, как и сертификация в ФСБ. Что значит — требования по "наличию бекдоров", поясните? Криптоалгоритмы открытые, есть желание изучать и искать закладки — пожалуйста. С другой стороны, в задачи сертификаторов входит проверка корректности применения этих самых алгоритмов, что на самом деле представляет собой бОльшую угрозу безопасности, чем те же самые невидимые бекдоры. Я считаю, что сертификация в ФСБ по СКЗИ имеет смысл, в отличии от сертификации ФСТЕК.


              1. amarao
                04.04.2016 12:33

                См Dual EC DRBG, с "закладочным" рандомом"
                А искать закладки куда комфортнее при открытых исходных текстах. Закрыли исходные тексты? Значит, не хотите, чтобы их кто-то читал.


                1. milabs
                  04.04.2016 12:36

                  Ну и много "закладок" нашли в OpenSSL?


                  1. amarao
                    04.04.2016 14:38

                    Ну, Dual EC DRBG нашли же.


                    1. milabs
                      04.04.2016 14:40

                      Ну так там же Сноуден поучаствовал. А что с хертблидом и компанией? Нет инсайда => не разоблачений? Эй, а как же опенсорс?))


                      1. amarao
                        04.04.2016 14:41

                        Нет, опасения высказывали много раньше, Сноуден просто подтвердил. Heartbleed был найден (по сырцам или по бинарному тестированию) — не знаю.


                        1. milabs
                          04.04.2016 14:44

                          Ну, знаете, высказать опасение не значит найти уязвимость. Я выскажу опасение, что задача дискретного логарифмирования, возможно, не такая уж вычислительно сложная. Такое опасение ставит под сомнение существующую криптографию на эллиптических кривых. Но что толку с моего опасения?


                          1. amarao
                            04.04.2016 14:57

                            Перевожу на русский язык: открывать исходный текст криптоалгоритмов не нужно. Верьте нам, мы там не xor'им.


                            1. milabs
                              04.04.2016 16:31

                              Тексты криптоалгоримов — это мизерная доля от общей кодовой базы продуктов. Открытость текстов не даст вам уверенности в том, что весь продукт безопасен. Ну убедитесь вы, что там не XOR. Ну и что? Так обвязка может всё шифрование на нет свести. Кстати, при сертификации в ФСБ как раз этот вопрос чаще всего и всплывает — реализация хорошая, только используется не правильно :-) Но вот эти 99,9% кода могу составлять "коммерческую тайну" и быть интеллектуальной собственностью компании. Что же теперь по вашей логике — весь код открывать?


                              1. amarao
                                04.04.2016 18:08

                                Тайна так тайна. Только не предлагайте остальным верить, что эта тайна делает что-то, кроме XOR'а, который очень стыдно показать и который потому и тайна, что стыдно.


                                1. milabs
                                  04.04.2016 18:41

                                  Ну как же, если есть сертификат ФСБ, то "верьте мне", там не XOR :-))))


                                  1. amarao
                                    04.04.2016 20:21

                                    Там есть сертификат, что есть то, что нужно ФСБ. А что нужно ФСБ знает только ФСБ, и уж точно это ортогонально интересам пользователя ПО.


                                    1. milabs
                                      04.04.2016 23:28

                                      Ну что вы за пользователя говорите. Вам нужна открытость — пользуйтесь PGP. Нужен ГОСТ в продакшене — пожалуйте под крыло ФСБ. И вот только не надо говорить, в развитых странах так не принято. И что требования регуляторов открытые для всех жедающих, вспоминая при этом пресловутые фипсы. Это верхушка айсберга, и очень хорошо, что подводную часть хоть как-то, но берегут)


              1. Flemon
                04.04.2016 16:24

                Может вы в курсе, каким именно образом проходят проверки в ФСБ при сертификации по СКЗИ? Как они это выполняют технически? Что за тесты они выполняют? Есть ли какое — то покрытие или еще что — то в этом духе.


                1. milabs
                  04.04.2016 16:33

                  Не, не в курсе.


                1. Kolyuchkin
                  07.04.2016 13:39

                  Если описать вкратце, то еще до процесса сертификации нужно согласовать ТЗ на изделие (СКЗИ, например) с соответствующими отделами ФСБ (в этом ТЗ отражены не только технические требования к изделию, но и специальные, в которых прописаны классы (уровни) защищенности и ФСБ-шные требования к изделию). Далее, после завершения разработки и испытаний изделия, наступает этап специальных и инженерно-криптографических исследований (в специализированной организации, имеющей соответствующую лицензию от ФСБ), результат которых и направляется в соответствующий отдел ФСБ. На основании этих результатов и выдается сертификат.
                  Короче, процесс этот не легкий.
                  Если Вы занимаетесь разработкой СКЗИ, то у вашей организации должны быть соответствующие лицензии и, соответственно, не должно возникать таких вопросов. Если же Вы спрашиваете из праздного любопытства, чтобы, например, убедиться в объективности сертификата ФСБ, то смогу Вас уверить (здесь уже субъективно), что СКЗИ с сертификатом ФСБ можно верить и доверять (при условии, что Вы соблюдаете правила пользования и условия эксплуатации).


                  1. Flemon
                    08.04.2016 01:14

                    Спасибо за ответ. Вопрос: что происходит на этапе специальных и инженерно-криптографических исследований?


                    1. Kolyuchkin
                      08.04.2016 09:46

                      Проверка на «правильность» реализации криптографических алгоритмов. Проверка на выполнение требований ТЗ, в особенности подраздела «Специальные требования». Проведение экспериментальных проверок.


                      1. Flemon
                        08.04.2016 11:17

                        Окей, спасибо за разъяснения.