Android 7.0 trở lên hỗ trợ mã hóa dựa trên tệp (FBE). FBE cho phép mã hóa các tệp khác nhau bằng các khóa khác nhau có thể mở khóa độc lập. Các khóa này được sử dụng để mã hóa cả nội dung tệp và tên tệp. Khi FBE được sử dụng, các thông tin khác, chẳng hạn như bố cục thư mục, kích thước tệp, quyền và thời gian tạo/sửa đổi, sẽ không được mã hóa. Nói chung, thông tin khác này được gọi là siêu dữ liệu hệ thống tệp.
Android 9 đã giới thiệu hỗ trợ mã hóa siêu dữ liệu. Với mã hóa siêu dữ liệu, một khóa duy nhất xuất hiện tại thời điểm khởi động sẽ mã hóa bất kỳ nội dung nào không được mã hóa bởi FBE. Khóa này được bảo vệ bởi Keymaster, do đó được bảo vệ bởi khởi động đã xác minh.
Mã hóa siêu dữ liệu luôn được bật trên bộ lưu trữ có thể chấp nhận bất cứ khi nào FBE được bật. Mã hóa siêu dữ liệu cũng có thể được kích hoạt trên bộ nhớ trong. Các thiết bị chạy Android 11 trở lên phải bật tính năng mã hóa siêu dữ liệu trên bộ nhớ trong.
Triển khai trên bộ nhớ trong
Bạn có thể thiết lập mã hóa siêu dữ liệu trên bộ nhớ trong của thiết bị mới bằng cách thiết lập hệ thống tệp metadata
, thay đổi trình tự khởi tạo và bật mã hóa siêu dữ liệu trong tệp fstab của thiết bị.
điều kiện tiên quyết
Mã hóa siêu dữ liệu chỉ có thể được thiết lập khi phân vùng dữ liệu được định dạng lần đầu. Do đó, tính năng này chỉ dành cho các thiết bị mới; đây không phải là điều mà một OTA nên thay đổi.
Mã hóa siêu dữ liệu yêu cầu mô-đun dm-default-key
được bật trong kernel của bạn. Trong Android 11 trở lên, dm-default-key
được hỗ trợ bởi các nhân thông thường của Android, phiên bản 4.14 trở lên. Phiên bản dm-default-key
này sử dụng khung mã hóa độc lập với phần cứng và nhà cung cấp được gọi là blk-crypto .
Để bật dm-default-key
, hãy sử dụng:
CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y CONFIG_DM_DEFAULT_KEY=y
dm-default-key
sử dụng phần cứng mã hóa nội tuyến (phần cứng mã hóa/giải mã dữ liệu khi dữ liệu đang trên đường đến/từ thiết bị lưu trữ) khi khả dụng. Nếu bạn không sử dụng phần cứng mã hóa nội tuyến, bạn cũng cần kích hoạt dự phòng cho API mã hóa của nhân:
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
Khi không sử dụng phần cứng mã hóa nội tuyến, bạn cũng nên kích hoạt mọi khả năng tăng tốc dựa trên CPU có sẵn như được đề xuất trong tài liệu FBE .
Trong Android 10 trở xuống, dm-default-key
không được nhân chung của Android hỗ trợ. Do đó, tùy thuộc vào các nhà cung cấp để triển khai dm-default-key
.
Thiết lập hệ thống tệp siêu dữ liệu
Bởi vì không có gì trong phân vùng dữ liệu người dùng có thể được đọc cho đến khi có khóa mã hóa siêu dữ liệu, bảng phân vùng phải dành một phân vùng riêng gọi là "phân vùng siêu dữ liệu" để lưu trữ các đốm màu quản trị khóa bảo vệ khóa này. Phân vùng siêu dữ liệu phải là 16 MB.
fstab.hardware
phải bao gồm một mục cho hệ thống tệp siêu dữ liệu nằm trên phân vùng đó đang gắn nó tại /metadata
, bao gồm cờ formattable
để đảm bảo nó được định dạng khi khởi động. Hệ thống tệp f2fs không hoạt động trên các phân vùng nhỏ hơn; chúng tôi khuyên bạn nên sử dụng ext4 để thay thế. Ví dụ:
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable
Để đảm bảo tồn tại điểm gắn /metadata
, hãy thêm dòng sau vào BoardConfig-common.mk
:
BOARD_USES_METADATA_PARTITION := true
Thay đổi chuỗi init
Khi mã hóa siêu dữ liệu được sử dụng, vold
phải được chạy trước khi /data
được gắn kết. Để đảm bảo rằng nó được bắt đầu đủ sớm, hãy thêm đoạn mã sau vào init.hardware.rc
:
# We need vold early for metadata encryption on early-fs start vold
Keymaster phải đang chạy và sẵn sàng trước khi init cố gắn /data
.
init.hardware.rc
đã phải chứa lệnh mount_all
tự gắn /data
vào khổ thơ on late-fs
. Trước dòng này, hãy thêm lệnh để thực thi dịch vụ 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
Bật mã hóa siêu dữ liệu
Cuối cùng thêm keydirectory=/metadata/vold/metadata_encryption
vào cột fs_mgr_flags của mục nhập fstab
cho userdata
. Ví dụ: một dòng fstab đầy đủ có thể trông như sau:
/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
Theo mặc định, thuật toán mã hóa siêu dữ liệu trên bộ nhớ trong là AES-256-XTS. Điều này có thể được ghi đè bằng cách đặt tùy chọn metadata_encryption
, cũng trong cột fs_mgr_flags :
- Trên các thiết bị không có khả năng tăng tốc AES, mã hóa Adiantum có thể được bật bằng cách đặt
metadata_encryption=adiantum
. - Trên các thiết bị hỗ trợ khóa được bao bọc bằng phần cứng , khóa mã hóa siêu dữ liệu có thể được bao bọc bằng phần cứng bằng cách đặt
metadata_encryption=aes-256-xts:wrappedkey_v0
(hoặc tương đươngmetadata_encryption=:wrappedkey_v0
, vìaes-256-xts
là thuật toán mặc định).
Vì giao diện kernel thành dm-default-key
đã thay đổi trong Android 11, nên bạn cũng cần đảm bảo rằng bạn đã đặt đúng giá trị cho PRODUCT_SHIPPING_API_LEVEL
trong device.mk
. Ví dụ: nếu thiết bị của bạn khởi chạy với Android 11 (API cấp 30), thì device.mk
phải chứa:
PRODUCT_SHIPPING_API_LEVEL := 30
Bạn cũng có thể đặt thuộc tính hệ thống sau để buộc sử dụng API dm-default-key
mới bất kể cấp API vận chuyển:
PRODUCT_PROPERTY_OVERRIDES += \ ro.crypto.dm_default_key.options_format.version=2
Thẩm định
Để xác minh rằng mã hóa siêu dữ liệu đã được bật và đang hoạt động bình thường, hãy chạy các thử nghiệm được mô tả bên dưới. Ngoài ra, hãy chú ý đến các vấn đề phổ biến được mô tả dưới đây.
bài kiểm tra
Bắt đầu bằng cách chạy lệnh sau để xác minh rằng mã hóa siêu dữ liệu được bật trên bộ nhớ trong:
adb root
adb shell dmctl table userdata
Đầu ra phải tương tự như:
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
Nếu bạn ghi đè cài đặt mã hóa mặc định bằng cách đặt tùy chọn metadata_encryption
trong fstab
của thiết bị, thì đầu ra sẽ hơi khác so với ở trên. Ví dụ: nếu bạn đã bật mã hóa Adiantum thì trường thứ ba sẽ là xchacha12,aes-adiantum-plain64
thay vì aes-xts-plain64
.
Tiếp theo, hãy chạy vts_kernel_encryption_test để xác minh tính chính xác của mã hóa siêu dữ liệu và FBE:
atest vts_kernel_encryption_test
hoặc:
vts-tradefed run vts -m vts_kernel_encryption_test
Các vấn đề chung
Trong cuộc gọi đến mount_all
, gắn kết phân vùng /data
được mã hóa siêu dữ liệu, init
thực thi công cụ vdc. Công cụ vdc kết nối với vold
over binder
để thiết lập thiết bị được mã hóa siêu dữ liệu và gắn kết phân vùng. Trong suốt thời gian của cuộc gọi này, init
bị chặn và các nỗ lực đọc hoặc đặt thuộc tính init
sẽ bị chặn cho đến khi mount_all
kết thúc. Nếu ở giai đoạn này, bất kỳ phần nào của công việc của vold
bị chặn trực tiếp hoặc gián tiếp khi đọc hoặc thiết lập thuộc tính, thì bế tắc sẽ xảy ra. Điều quan trọng là đảm bảo rằng vold
có thể hoàn thành công việc đọc khóa, tương tác với Keymaster và gắn thư mục dữ liệu mà không cần tương tác thêm với init
.
Nếu Keymaster không được khởi động hoàn toàn khi mount_all
chạy, nó sẽ không phản hồi với vold
cho đến khi nó đọc một số thuộc tính nhất định từ init
, dẫn đến chính xác bế tắc được mô tả. Đặt exec_start wait_for_keymaster
phía trên lời gọi mount_all
có liên quan như đã đặt ra để đảm bảo rằng Keymaster đang chạy hoàn toàn trước và do đó tránh được bế tắc này.
Cấu hình trên bộ nhớ có thể chấp nhận
Kể từ Android 9, một dạng mã hóa siêu dữ liệu luôn được bật trên bộ lưu trữ có thể chấp nhận bất cứ khi nào FBE được bật, ngay cả khi mã hóa siêu dữ liệu không được bật trên bộ nhớ trong.
Trong AOSP, có hai triển khai mã hóa siêu dữ liệu trên bộ lưu trữ có thể chấp nhận: một triển khai không dùng nữa dựa trên dm-crypt
và một triển khai mới hơn dựa trên dm-default-key
. Để đảm bảo rằng triển khai chính xác được chọn cho thiết bị của bạn, hãy đảm bảo rằng bạn đã đặt đúng giá trị cho PRODUCT_SHIPPING_API_LEVEL
trong device.mk
. Ví dụ: nếu thiết bị của bạn khởi chạy với Android 11 (API cấp 30), thì device.mk
phải chứa:
PRODUCT_SHIPPING_API_LEVEL := 30
Bạn cũng có thể đặt các thuộc tính hệ thống sau để bắt buộc sử dụng phương pháp mã hóa siêu dữ liệu tập mới (và phiên bản chính sách FBE mặc định mới) bất kể cấp API vận chuyển:
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
phương pháp hiện tại
Trên các thiết bị chạy Android 11 trở lên, mã hóa siêu dữ liệu trên bộ nhớ có thể chấp nhận sử dụng mô-đun nhân dm-default-key
, giống như trên bộ nhớ trong. Xem các điều kiện tiên quyết ở trên để bật các tùy chọn cấu hình kernel. Lưu ý rằng phần cứng mã hóa nội tuyến hoạt động trên bộ nhớ trong của thiết bị có thể không khả dụng trên bộ nhớ có thể chấp nhận và do đó, CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
có thể được yêu cầu.
Theo mặc định, phương pháp mã hóa siêu dữ liệu ổ đĩa dm-default-key
sử dụng thuật toán mã hóa AES-256-XTS với các khu vực mật mã 4096 byte. Có thể ghi đè thuật toán bằng cách đặt thuộc tính hệ thống ro.crypto.volume.metadata.encryption
. Giá trị của thuộc tính này có cú pháp giống như tùy chọn fstab metadata_encryption
được mô tả ở trên. Ví dụ: trên các thiết bị không có khả năng tăng tốc AES, mã hóa Adiantum có thể được bật bằng cách đặt ro.crypto.volume.metadata.encryption=adiantum
.
phương pháp kế thừa
Trên các thiết bị chạy Android 10 trở xuống, mã hóa siêu dữ liệu trên bộ lưu trữ có thể chấp nhận sử dụng mô-đun hạt nhân dm-crypt
thay vì dm-default-key
:
CONFIG_DM_CRYPT=y
Không giống như phương pháp dm-default-key
, phương pháp dm-crypt
khiến nội dung tệp được mã hóa hai lần: một lần bằng khóa FBE và một lần bằng khóa mã hóa siêu dữ liệu. Mã hóa kép này làm giảm hiệu suất và không bắt buộc phải đạt được các mục tiêu bảo mật của mã hóa siêu dữ liệu, vì Android đảm bảo rằng các khóa FBE ít nhất cũng khó bị xâm phạm như khóa mã hóa siêu dữ liệu. Nhà cung cấp có thể thực hiện các tùy chỉnh kernel để tránh mã hóa kép, cụ thể là bằng cách triển khai tùy chọn allow_encrypt_override
mà Android sẽ chuyển sang dm-crypt
khi thuộc tính hệ thống ro.crypto.allow_encrypt_override
được đặt thành true
. Các tùy chỉnh này không được hỗ trợ bởi nhân chung của Android.
Theo mặc định, phương pháp mã hóa siêu dữ liệu ổ đĩa dm-crypt
sử dụng thuật toán mã hóa AES-128-CBC với ESSIV và các khu vực mật mã 512 byte. Điều này có thể được ghi đè bằng cách đặt các thuộc tính hệ thống sau (cũng được sử dụng cho FDE):
-
ro.crypto.fde_algorithm
chọn thuật toán mã hóa siêu dữ liệu. Các lựa chọn làaes-128-cbc
vàadiantum
. Adiantum chỉ có thể được sử dụng nếu thiết bị thiếu tính năng tăng tốc AES. -
ro.crypto.fde_sector_size
chọn kích thước khu vực tiền điện tử. Các lựa chọn là 512, 1024, 2048 và 4096. Đối với mã hóa Adiantum, hãy sử dụng 4096.