본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android] File-Based Encryption & Direct Boot mode

by 돼지왕 왕돼지 2019. 7. 8.
반응형



access de, ACTION_BOOT_COMPLETE, ACTION_LOCKED_BOOT_COMPLETED, ACTION_USER_UNLOCKED, adoptable storage, Android version, android:directBootAware, ce, ce de data migration, ce storage, CONTEXT, createDeviceProtectedStorageContext, Credential, Credential Encrypted storage, De, de context, de storage, Device Encrypted storage, dialer, direct boot api, direct boot enable, direct boot enable method, direct boot manifest, Direct Boot mode, direct boot user data clear, directBootAware, emulated direct boot, encryption aware, encryption aware app, encryption aware app test, encryption-aware app, example app, ext4, fbe, fbe enable, fbe version, fde, fde accessibility service, fde 암호화, file based encryption, File-Based Encryption, fsfs, full disk encryption, how to enable direct boot, input method, isUserUnlocked, LOCKED_BOOT_COMPLETED, moveDatabaseFrom, moveSharedPreferencesFrom, telephony service, traditional storage, unlock detect, unlock notify, usermanager, UserManager.isUserUnlocked, work challenge, work profile


-

Android 7.0 (NOS) 이상부터는 file-based encryption (이하 FBE) 를 지원한다.

FBE는 각각 다른 key 를 사용하여 각각 다른 파일들이 encrypt 될 수 있고, unlock 도 각각 될 수 있다. (DE 와 CE 를 각각 암호화하고, 각각의 접근범위를 설정한다.) ( 돼왕 : 무슨 말인지 전혀 모를텐데 뒤를 쭉 읽어보면 이해가 될 것이다. )


이 글에서는 새로운 단말에서 어떻게 FBE 를 enable 시킬 수 있는지, 어떻게 시스템 앱이 새로운 Direct Boot API 들의 장점을 최대한 활용할 수 있게 업데이트 되었는지, 그리고 유저에게 최상의 보안을 제공할 수 있는지를 알려준다.



-

Android 7.0~8.1 단말에서는 FBE 가 adoptable storage 와 함께 동작할 수 없다.

FBE 를 사용하는 단말에서는 new storage media(예를 들면 SD card) 는 반드시 traditional storage 로 사용되어야 한다.


Android 9 이상의 단말에서는 FBE 와 adoptable storage 를 동시에 사용할 수 있다.





Direct Boot


-

FBE 는 Android 7.0 (NOS) 부터 사용 가능한 새로운 기능으로,  Direct Boot 를 enable 시킬 수 있다.

Direct Boot 는 encrypted 단말이 lock screen 으로 바로 boot 하도록 할 수 있다. ( 돼왕 : 이것도 뒷 이야기를 읽어보면 감이 오는 내용 )



-

기존의 full-disk encryption (FDE) 를 사용하여 encrpyted 단말에서는, 어떤 data 에 접근을 허용하려면 유저가  비밀번호 등의 정보(credentials) 를 미리 제공해주어야 했다. 그렇지 않으면 단말은 모든 혹은 대부분의 기본 동작도 할 수 없었다.

에를 들어 alarm 이 울리지 않는다던지, 접근성(Accessibility) 서비스를 사용할 수 없다던지, 전화를 수신할 수 없다던지 등이며, 오직 긴급 통화 정도만 사용 가능했다.



-

FBE 와 새로운 API 들의 도입으로 앱들에게 제한된 context 내에서 operation 을 허락해 줄 수 있게 되었다.

이것은 user 가 crendentials 를 제공하기 전에 할 수 있으며, 이 와중에 private 한 개인 정보를 보호할 수 있다.



-

FBE 가 enable 된 단말에서는, 단말의 각 유저는 2개의 저장 공간을 앱에 제공할 수 있다.


Credential Encrypted (CE) storage

    기본 저장 공간이며, 유저가 단말을 unlock 했을 때만 접근 가능하다.


Device Encrypted (DE) storage

    Direct Boot mode 와 유저가 단말을 unlock 했을 때 모두 접근 가능하다.



-

CE 와 DE 의 구분은 더 안정적인데, 그 이유는 encryption 이 더 이상 boot time password 에만 의존하는 것이 아니기 때문에, 여러 유저가 한번에 보호될 수 있다. ( 돼왕 : Multi user 로 사용하는 경우에 대한 이야기로 보이는데, 자세한 건 skip 하자.. )



-

Direct Boot API 는 encryption-aware app 에게 이 영역을 접근할 수 있게 한다.

유저가 lock screen 의 credentials 에 처음으로 진입했을 때 또는 work profile 이 work challenge 를 제공했을 때, CE storage 가 unlock 되는데, 앱은 이 상황을 알림받기 위해 앱의 생명주기가 달라진다.

Android 7.0 단말에서는 반드시 FBE 를 구현했던 아니던 상관없이 새로운 API 와 생명주기를 지원해야 한다.

FBE 없이는 DE 와 CE storage 는 항상 unlocked state 가 된다.



-

Ext4 와 F2FS file system 에서의 완벽한 FBE 지원은 AOSP 에서 찾을 수 있고, 요구사항을 만족하는 단말에서는 enable 될 수 있다.

FBE 를 사용하기로 한 제조사에서는 이 기능을 SoC 하에서 최적화하는 방법을 찾길 바란다.



-

AOSP 안에서 모든 필요한 pkg 들은 direct-boot aware 하도록 업데이트 되었다.

하지만 단말 제조사가 이 앱들을 customize 한 버전을 사용한다면, 다음의 pkg 들은 최소한 direct-boot aware 해야 한다.

    Telephony Service & Dialer

    Lock screen 안에서 비밀번호 입력을 위한 Input method



-

이하 생략

돼왕 : FBE(File-based encryption), FDE(Full-disk encryption), Direct Boot, CE(Credential Encrypted), DE(Device Encrypted) 의 개념정도만 이해하면 될 것 같다.





Supporting Direct Boot mode


-

돼왕 : 위 내용을 감을 잡았다면 이부분부터는 이해가 조금 쉬워질 것이다.



-

Android 7.0 (NOS) 에서는, 기기의 전원이 켜져있지만, 유저가 단말을 unlock 하지 않은 경우 안전한 Direct Boot 모드로 동작한다.

Direct Boot mode 를 제공하기 위해 시스템에서는 data 에 대한 두가지 저장 공간을 제공한다.


Credential encrypted storage (CE) : Direct boot 모드에서는 쓸 수 없다.

Device encrypted storage (DE) : Direct boot 모드에서도 쓸 수 있다.



-

기본적으로 앱들은 Direct boot 모드에서 작동할 수 없다.

앱이 Direct Boot mode 에서도 동작하도록 하려면, 앱 컴포넌트를 이 모드에서 동작하도록 등록해야 한다.

앱이 Direct Boot mode 에서도 동작해야 하는 유즈 케이스는 아래와 같은 것들이 있겠다.

    알람 앱과 같이 스케줄 알람 기능

    SMS 앱과 같이 중요한 알림 제공

    Talkback 앱과 같이 접근성 서비스를 제공



-

만약 앱이 Direct Boot mode 일 때도 data access 를 하게 하려면, DE (device encrypted storage) 를 사용하게 하라.

DE 는 data 가 user 가 성공적으로 검증된 boot 를 했을 때만 사용 가능한 key 로 암호화 되어 있다.



-

PIN 이나 pwd 등의 User credentials 과 관련된 key 로 암호화되어야 하는 데이터가 있다면, CE (credential encrypted storage)를 사용하라.

CE 는 유저가 성공적으로 단말을 unlock 해야 (lock screen 을 unlock 해야) 사용 가능한 영역이며, 단말이 재시작되면 다시 lock 상태가 된다.


Direct Boot mode 의 해지는 부팅후 최초 1회에 한하며, 다시 lock screen 에 들어간다 해도 CE 영역을 쓸 수 있다.






Direct Boot 모드 동안 동작하도록 요청하기


-

앱은 Direct Boot mode 에서 동작하며, DE 영역에 접근하려면 시스템에 자신의 컴퍼넌트를 등록해야 한다.

시스템에 앱을 등록(마킹)하는 형태를 “encryption aware(암호 인지)” 라고 부른다.

컴포넌트를 암호 인지 상태로 만들려면 manifest 에 android:directBootAware attribute 를 써주면 된다.



-

암호 인지 컴포넌트는, 단말이 restart 되었을 때 시스템으로부터  ACTION_LOCKED_BOOT_COMPLETED broadcast 메시지를 받는다. 이 시점에 단말은 DE 에 접근 가능하며, 등록된 component 는 Direct Boot mode 에서 작업을 수행할 수 있다. 예를 들면 alarm scheduling 같은..



-

암호 인지 상태일 때, 단말이 재부팅되면 android.intent.action.LOCKED_BOOT_COMPLETED 를 받을 수 있다.



-

유저가 단말 lock 을 해지하면 (Direct boot mode 를 벗어나면), 모든 컴포넌트는 DE 영역과 CE 영역 모두에 접근할 수 있다.





Access DE


-

DE 에 접근하기 위해서는 Context.createDeviceProtectedStorageContext() 를 통해 두번째 Context instance 를 얻어야 한다.

모든 저장소 API 들의 호출은 이 context 를 사용해서 접근해야 한다.


아래 code snippet 을 참고하라.

val directBootContext: Context = appContext.createDeviceProtectedStorageContext()
// Access appDataFilename that lives in device encrypted storage

val inStream: InputStream = directBootContext.openFileInput(appDataFilename)
// Use inStream to read content...


-

DE 사용은 Direct Boot mode 에서 반드시 접근해야 하는 정보들에 한정해야 한다.

DE 를 일반적인 용도의 압호화 공간으로 사용하지 말아라.

private 한 유저 정보들 또는 암호화된 데이타는 Direct Boot mode 에서는 필요없다. CE 를 사용하라.





Get notified of user unlock


-

유저가 재부팅 후 디바이스 unlock 을 하면 (Direct boot mode 를 빠져나가면), 앱은 CE 영역을 접근하도록 바꿀 수 있고, user credential 에 의존하는 일반적인 시스템 서비스를 사용할 수 있다.


앱이 foreground process 들을 가지고 있어 즉각적인 notification 이 필요하다면  ACTION_USER_UNLOCKED 를 broadcast 를 받아 Direct boot mode 에서 unlock 됨을 인지할 수 있다.


앱이 background processes 만 사용하고 있어 delay 된 noti 를 받아도 된다면, ACTION_BOOT_COMPLETE 를 받으면 된다.



-

UserManager.isUserUnlocked() 를 통해 이 값을 능동적으로 확인할 수도 있다.





Migrate existing data


-

유저가 Direct Boot mode 를 사용하도록 설정한다면, CE 영역의 데이터 일부를 DE 에 옮겨야 할 수 있다.

Context.moveSharedPreferencesFrom 과 Context.moveDatabaseFrom() 을 사용해 preference 와 db data 를 CE 와 DE 사이에서 migrate 할 수 있다.



-

언제 data 를 migrate 할지는 알아서 정하면 된다.

pwd, auth token 등의 private 유저 정보를 DE 에 migrate 하는 것은 피해라.

몇몇 케이스에는 각각의 암호화된 저장공간에 각각 다른 set 의 data 를 저장해야 할 수도 있다.






Test your encryption aware app


-

너의 앱이 Direct Boot mode 에서 enable 되게 하려면 두가지 방법이 있다.

( 주의!!!! Direct Boot 를 enable 하면 단말에 있는 모든 user data 가 삭제된다. ) - (돼왕: 정말? 그래도 돼?)



-

Android 7.0 이상이 설치된 단말에서, 다음과 같이 하면 된다.


1. 개발자 옵션을 활성화 시킨다. 그 안에서 “Covert to file encryption” 을 선택한다.

2. adb 명령어로 처리한다.

$ adb reboot-bootloader

$ fastboot —wipe-and-use-fbe



-

emulated Direct Boot mode 도 가능하다.

Emulated mode 는 test 단말에서 수행하고, 오직 개발 기간동안에만 사용하는 것이 좋다. data 유실을초래할 수 있으므로.

emulated Direct Boot mode 를 enable 하기 위해서는 단말에 lock pattern 설정 시, No Thanks 를 선택하고, 다음 adb 명령을 수행한다.

$ adb shell sm set-emulate-fbe true


off 하기 위해서는 

$ adb shell sm set-emulate-fbe false





Additional code samples


-

https://github.com/googlesamples/android-DirectBoot/





기타 정보

http://blog.naver.com/PostView.nhn?blogId=malloc813&logNo=221400538169&parentCategoryNo=18&categoryNo=&viewDate=&isShowPopularPosts=true&from=search


-

FDE(Full-disk encryption) 에서 암호화는 두번 진행된다.

한번은 바뀌지 않는 key 를 기반으로, data 를 암호화하고, (이 key 는공장 초기화를 할 때까지 바뀌지 않는다.)

또 한번은 그 key 를 유저가 설정한 credential 을 통해 암호화한다.

이렇게 key 하나를 유지하고, 그 key 를 다시 암호화하는 이유는 유저의 credential 변화에 민첩하게 반응하기 위해서이다.

데이터 자체를 credential 기준으로 암호화하면, credential 이 바뀔 때마다 복호화 & 암호화가 재수행되어야 한다.



-

FDE 에서는 접근성 서비스가 enable 되어 있다면 FDE 가 작동하지 않는다고 봐도 된다.



-

FBE 에서는 이런 단점을 극복하기 위해 FBE(File-based encryption)이 추가되었으며, 인증 영역을 나누어 접근성 앱이 enable 되어도 DE 영역만 접근하도록 하여 데이터를 보호한다.



-

참고 자료들

https://source.android.com/security/encryption/file-based

https://developer.android.com/training/articles/direct-boot



끝.



반응형

댓글