메타데이터 암호화

Android 7.0 이상에서는 파일 기반 암호화(FBE)를 지원합니다. FBE를 사용하면 개별적으로 잠금 해제 가능한 여러 키를 사용하여 여러 파일을 암호화할 수 있습니다. 이러한 키는 파일 콘텐츠와 파일 이름을 암호화하는 데 사용됩니다. FBE를 사용하면 디렉터리 레이아웃, 파일 크기, 권한 및 생성/수정 시간과 같은 다른 정보는 암호화되지 않습니다. 이러한 다른 정보를 총칭하여 파일 시스템 메타데이터라고 합니다.

Android 9부터 메타데이터 암호화가 지원됩니다. 메타데이터 암호화를 사용하면 부팅 시 존재하는 단일 키로 FBE에서 암호화되지 않은 모든 콘텐츠를 암호화합니다. 이 키는 자체 검사 부팅에서 보호하는 Keymaster를 통해 보호됩니다.

메타데이터 암호화는 FBE가 사용 설정될 때마다 항상 어답터블 스토리지에서 사용 설정됩니다. 메타데이터 암호화는 내부 저장소에서도 사용 설정될 수 있습니다. Android 11 이상으로 출시된 기기에는 내부 저장소에 메타데이터 암호화가 사용 설정되어 있어야 합니다.

내부 저장소에서 구현

metadata 파일 시스템을 설정하고 init 순서를 변경하며 기기의 fstab 파일에서 메타데이터 암호화를 사용 설정하여 새 기기의 내부 저장소에 메타데이터 암호화를 설정할 수 있습니다.

기본 요건

메타데이터 암호화는 데이터 파티션이 처음 포맷될 때만 설정할 수 있습니다. 따라서 이 기능은 새 기기에만 사용할 수 있으며 OTA로 변경해야 하는 것이 아닙니다.

메타데이터 암호화를 사용하려면 커널에서 dm-default-key 모듈을 사용 설정해야 합니다. Android 11 이상에서는 Android 일반 커널 버전 4.14 이상에서 dm-default-key를 지원합니다. 이 dm-default-key 버전은 하드웨어 및 공급업체와는 무관한 blk-crypto라는 암호화 프레임워크를 사용합니다.

dm-default-key를 사용 설정하려면 다음을 사용하세요.

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_DM_DEFAULT_KEY=y

dm-default-key는 가능한 경우 인라인 암호화 하드웨어(저장소 기기와 데이터를 송수신하는 동안 데이터를 암호화/복호화하는 하드웨어)를 사용합니다. 인라인 암호화 하드웨어를 사용하지 않는다면 다음과 같이 커널의 암호화 API에 폴백을 사용 설정해야 합니다.

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

또한 인라인 암호화 하드웨어를 사용하지 않는 경우 FBE 문서에서 권장하는 대로 사용 가능한 CPU 기반 가속을 사용 설정해야 합니다.

Android 10 이하에서는 Android 일반 커널에서 dm-default-key를 지원하지 않습니다. 따라서 dm-default-key 구현은 공급업체가 결정합니다.

메타데이터 파일 시스템 설정

메타데이터 암호화 키가 존재할 때까지는 사용자 데이터 파티션의 어떠한 데이터도 읽을 수 없습니다. 따라서 파티션 테이블에서는 '메타데이터 파티션'이라는 별도의 파티션을 지정하여 이 키를 보호하는 Keymaster blob를 저장해야 합니다. 메타데이터 파티션은 16MB여야 합니다.

fstab.hardware는 부팅 시 포맷을 시행하는 formattable 플래그와 함께 /metadata로 메타데이터 파일 시스템을 마운트하는 파티션의 메타데이터 파일 시스템 항목을 포함해야 합니다. f2fs 파일 시스템은 작은 파티션에서 작동하지 않으므로 대신 ext4를 사용하는 것이 좋습니다. 예:

/dev/block/bootdevice/by-name/metadata              /metadata          ext4        noatime,nosuid,nodev,discard                          wait,check,formattable

/metadata 마운트 지점이 있도록 하려면 BoardConfig-common.mk에 다음 행을 추가합니다.

BOARD_USES_METADATA_PARTITION := true

init 순서 변경

메타데이터 암호화를 사용한다면 /data가 마운트되기 전에 vold가 실행되어야 합니다. 충분히 일찍 시작되도록 하려면 init.hardware.rc에 다음 스탠자를 추가합니다.

# We need vold early for metadata encryption
on early-fs
    start vold

init에서 /data 마운트를 시도하기 전에 Keymaster가 실행 및 준비되어 있어야 합니다.

init.hardware.rcon late-fs 스탠자에 /data 자체를 마운트하는 mount_all 지침을 이미 포함하고 있어야 합니다. 이 행 앞에 다음과 같이 wait_for_keymaster 서비스를 실행하는 지시어를 추가합니다.

on late-fs
   …
    # Wait for keymaster
    exec_start wait_for_keymaster

    # Mount RW partitions which need run fsck
    mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

메타데이터 암호화 전환

마지막으로 userdatafstab 항목에서 fs_mgr_flags 열에 keydirectory=/metadata/vold/metadata_encryption을 추가합니다. 예를 들어 전체 fstab 행은 다음과 같습니다.

/dev/block/bootdevice/by-name/userdata              /data              f2fs        noatime,nosuid,nodev,discard,inlinecrypt latemount,wait,check,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota,formattable

기본적으로 내부 저장소의 메타데이터 암호화 알고리즘은 AES-256-XTS입니다. 이는 다음과 같이 metadata_encryption 옵션을 설정하여 재정의할 수 있으며 fs_mgr_flags 열에서도 마찬가지입니다.

  • AES 가속이 없는 기기에서는 metadata_encryption=adiantum을 설정하여 Adiantum 암호화를 사용 설정할 수 있습니다.
  • 하드웨어 래핑 키를 지원하는 기기에서 metadata_encryption=aes-256-xts:wrappedkey_v0을 설정하여 메타데이터 암호화 키를 하드웨어 래핑 키로 만들 수 있습니다(또는 aes-256-xts가 기본 알고리즘이므로 이에 상응하는 metadata_encryption=:wrappedkey_v0 설정).

Android 11에서 dm-default-key로의 커널 인터페이스가 변경되었으므로 device.mk에서 PRODUCT_SHIPPING_API_LEVEL에 올바른 값을 설정했는지도 확인해야 합니다. 예를 들어 기기가 Android 11(API 수준 30)으로 출시되는 경우 device.mk에는 다음이 포함되어야 합니다.

PRODUCT_SHIPPING_API_LEVEL := 30

배송 API 수준에 관계없이 다음과 같은 시스템 속성을 설정하여 새 dm-default-key API를 강제로 사용할 수도 있습니다.

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.dm_default_key.options_format.version=2

유효성 검사

아래에 설명된 테스트를 실행하여 메타데이터 암호화를 사용 설정했고 올바르게 작동 중인지 확인합니다. 또한 아래의 일반적인 문제에도 유의하세요.

테스트

다음 명령어를 실행하여 내부 저장소에서 메타데이터 암호화가 사용 설정되어 있는지 확인하세요.

adb root
adb shell dmctl table userdata

출력은 다음과 비슷해야 합니다.

Targets in the device-mapper table for userdata:
0-4194304: default-key, aes-xts-plain64 - 0 252:2 0 3 allow_discards sector_size:4096 iv_large_sectors

기기의 fstab에서 metadata_encryption 옵션을 설정하여 기본 암호화 설정을 재정의했다면 출력이 위와 조금 달라집니다. 예를 들어 Adiantum 암호화를 사용 설정했다면 세 번째 필드는 aes-xts-plain64 대신 xchacha12,aes-adiantum-plain64가 됩니다.

그런 다음 vts_kernel_encryption_test를 실행하여 메타데이터 암호화와 FBE가 정확한지 확인합니다.

atest vts_kernel_encryption_test

또는:

vts-tradefed run vts -m vts_kernel_encryption_test

일반적인 문제

메타데이터로 암호화된 /data 파티션을 마운트하는 mount_all을 호출하는 동안 init는 vdc 도구를 실행합니다. vdc 도구는 binder를 통해 vold에 연결하여 메타데이터로 암호화할 기기를 설정하고 파티션을 마운트합니다. 이 호출이 실행되는 동안 init가 차단되며 init 속성을 읽거나 설정하려는 시도는 mount_all이 완료될 때까지 차단됩니다. 이 단계에서 vold 작업 일부가 속성을 읽거나 설정하는 중에 직간접적으로 차단된다면 교착 상태가 발생합니다. vold에서 키를 읽고 Keymaster와 상호작용하고 init와의 추가적인 상호작용 없이 데이터 디렉터리를 마운트하는 작업을 완료하도록 하는 것이 중요합니다.

mount_all이 실행될 때 Keymaster가 완전히 시작되지 않았다면 Keymaster는 init의 특정 속성을 읽을 때까지 vold에 응답하지 않으며 이로 인해 앞서 설명한 교착 상태가 발생합니다. 명시된 대로 관련 mount_all 호출 위에 exec_start wait_for_keymaster를 배치하면 Keymaster가 사전에 완전히 실행되므로 이러한 교착 상태가 발생하지 않습니다.

어답터블 스토리지의 구성

Android 9부터는 내부 저장소에서 메타데이터 암호화가 사용 설정되어 있지 않더라도 FBE가 사용 설정될 때마다 어답터블 스토리지에서 항상 메타데이터 암호화 양식이 사용 설정됩니다.

AOSP에는 어답터블 스토리지에 메타데이터 암호화가 두 가지로 구현되어 있습니다. dm-crypt를 기반으로 한 지원되지 않는 구현과 dm-default-key를 기반으로 한 새로운 구현입니다. 기기에 올바른 구현이 선택되도록 하려면 device.mk에서 PRODUCT_SHIPPING_API_LEVEL에 올바른 값을 설정해야 합니다. 예를 들어 기기가 Android 11(API 수준 30)으로 출시되는 경우 device.mk에는 다음이 포함되어야 합니다.

PRODUCT_SHIPPING_API_LEVEL := 30

배송 API 수준에 관계없이 다음과 같은 시스템 속성을 설정하여 새로운 볼륨 메타데이터 암호화 메서드 및 새로운 기본 FBE 정책 버전을 강제로 사용할 수도 있습니다.

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.volume.metadata.method=dm-default-key \
    ro.crypto.dm_default_key.options_format.version=2 \
    ro.crypto.volume.options=::v2

현재 메서드

Android 11 이상으로 출시되는 기기는 내부 저장소의 경우와 같이 어답터블 스토리지의 메타데이터 암호화에서 dm-default-key 커널 모듈을 사용합니다. 위의 기본 요건에서 사용 설정할 커널 구성 옵션을 확인하세요. 기기의 내부 저장소에서 작동하는 인라인 암호화 하드웨어는 어답터블 스토리지에서 사용할 수 없으므로 CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y가 필요할 수 있습니다.

기본적으로 dm-default-key 볼륨 메타데이터 암호화 메서드는 4,096바이트 암호화 섹터를 적용한 AES-256-XTS 암호화 알고리즘을 사용합니다. 알고리즘은 ro.crypto.volume.metadata.encryption 시스템 속성을 설정하여 재정의할 수 있습니다. 이 속성의 값에는 위에 설명된 metadata_encryption fstab 옵션과 동일한 구문이 있습니다. 예를 들어, AES 가속이 없는 기기에서는 ro.crypto.volume.metadata.encryption=adiantum을 설정하여 Adiantum 암호화를 사용 설정할 수 있습니다.

기존 메서드

Android 10 이하로 출시되는 기기는 어답터블 스토리지의 메타데이터 암호화에서 dm-default-key가 아닌 dm-crypt 커널 모듈을 사용합니다.

CONFIG_DM_CRYPT=y

dm-default-key 메서드와 달리 dm-crypt 메서드는 파일 콘텐츠를 두 번 암호화합니다. 즉, 한 번은 FBE 키로, 한 번은 메타데이터 암호화 키로 암호화합니다. Android에서 최소 메타데이터 암호화 키만큼 FBE 키의 안정성을 보장하므로 이러한 이중 암호화는 성능을 저해할 뿐 메타데이터 암호화의 보안 목표를 달성하는 데 필요하지 않습니다. 공급업체는 커널 맞춤설정을 통해 이중 암호화를 사용하지 않을 수 있으며 특히 시스템 속성인 ro.crypto.allow_encrypt_overridetrue로 설정될 때 Android에서 dm-crypt에 전달할 allow_encrypt_override 옵션을 구현하여 커널을 맞춤설정하면 됩니다. 이러한 맞춤설정은 Android 일반 커널에서 지원되지 않습니다.

기본적으로 dm-crypt 볼륨 메타데이터 암호화 메서드는 ESSIV 및 512바이트 암호화 섹터가 적용된 AES-128-CBC 암호화 알고리즘을 사용합니다. 이는 다음 시스템 속성(FDE에도 사용됨)을 설정하여 재정의할 수 있습니다.

  • ro.crypto.fde_algorithm은 메타데이터 암호화 알고리즘을 선택합니다. aes-128-cbcadiantum 중에서 선택할 수 있습니다. 기기에 AES 가속이 없는 경우에만 Adiantum을 사용할 수 있습니다.
  • ro.crypto.fde_sector_size는 암호화 섹터 크기를 선택합니다. 512, 1,024, 2,048, 4,096 중에서 선택할 수 있습니다. Adiantum 암호화에는 4,096을 사용합니다.