Android 7.0 trở lên hỗ trợ mã hoá dựa trên tệp (FBE). FBE cho phép mã hoá nhiều tệp bằng nhiều khoá có thể mở khoá độc lập. Các khoá này được dùng để mã hoá cả nội dung tệp và tên tệp. Khi sử dụng FBE, 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ã hoá. Nói chung, thông tin này được gọi là siêu dữ liệu hệ thống tệp.
Android 9 ra mắt tính năng hỗ trợ tính năng mã hoá siêu dữ liệu. Với tính năng mã hoá siêu dữ liệu, một khoá duy nhất xuất hiện tại thời điểm khởi động sẽ mã hoá mọi nội dung không được FBE mã hoá. Khoá này được bảo vệ bằng Keymaster, và Keymaster lại được bảo vệ bằng tính năng xác minh quy trình khởi động.
Tính năng mã hoá siêu dữ liệu luôn được bật trên bộ nhớ có thể chuyển đổi bất cứ khi nào FBE được bật. Bạn cũng có thể bật tính năng mã hoá siêu dữ liệu 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ã hoá 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 tính năng mã hoá 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 động và bật tính năng mã hoá siêu dữ liệu trong tệp fstab của thiết bị.
Điều kiện tiên quyết
Bạn chỉ có thể thiết lập tính năng mã hoá siêu dữ liệu khi định dạng phân vùng dữ liệu lần đầu tiên. 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à OTA nên thay đổi.
Tính năng mã hoá siêu dữ liệu yêu cầu bạn phải bật mô-đun dm-default-key
trong hạt nhân. Trong Android 11 trở lên, dm-default-key
được các hạt nhân chung của Android hỗ trợ, phiên bản 4.14 trở lên. Phiên bản dm-default-key
này sử dụng khung mã hoá độc lập với phần cứng và nhà cung cấp có tên 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ã hoá nội tuyến (phần cứng mã hoá/giải mã dữ liệu trong khi dữ liệu đang trên đường đến/từ thiết bị lưu trữ) khi có. Nếu bạn không sử dụng phần cứng mã hoá nội tuyến, bạn cũng cần bật phương thức dự phòng cho API mã hoá của hạt nhân:
CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
Khi không sử dụng phần cứng mã hoá nội tuyến, bạn cũng nên bật mọi tính năng tăng tốc dựa trên CPU có sẵn như được đề xuất trong tài liệu về FBE.
Trong Android 10 trở xuống, nhân chung của Android không hỗ trợ dm-default-key
. Do đó, nhà cung cấp có thể triển khai dm-default-key
.
Thiết lập hệ thống tệp siêu dữ liệu
Vì không thể đọc nội dung nào trong phân vùng dữ liệu người dùng cho đến khi có khoá mã hoá siêu dữ liệu, nên bảng phân vùng phải dành riêng một phân vùng có tên là "phân vùng siêu dữ liệu" để lưu trữ các blob keymaster bảo vệ khoá này. Phân vùng siêu dữ liệu phải có dung lượng 16 MB.
fstab.hardware
phải bao gồm một mục nhập cho hệ thống tệp siêu dữ liệu nằm trên phân vùng đó có gắn cờ tại /metadata
, bao gồm cả cờ formattable
để đảm bảo định dạng tệp tại thời điểm 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; bạn nên sử dụng ext4. Ví dụ:
/dev/block/bootdevice/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable
Để đảm bảo điểm gắn /metadata
tồn tại, hãy thêm dòng sau vào BoardConfig-common.mk
:
BOARD_USES_METADATA_PARTITION := true
Thay đổi đối với trình tự khởi tạo
Khi sử dụng tính năng mã hoá siêu dữ liệu, vold
phải đang chạy trước khi /data
được gắn. Để đảm bảo rằng quá trình này bắt đầu sớm, hãy thêm
bản thơ 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ắng gắn /data
.
init.hardware.rc
phải chứa một lệnh mount_all
để tự gắn /data
trong khổ 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 tính năng mã hoá 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 fstab
cho userdata
. Ví dụ: dòng fstab đầy đủ có thể có dạ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ã hoá siêu dữ liệu trên bộ nhớ trong là AES-256-XTS. Bạn có thể ghi đè tuỳ chọn này bằng cách đặt tuỳ chọn metadata_encryption
, cũng trong cột fs_mgr_flags:
- Trên các thiết bị không có tính năng tăng tốc AES, bạn có thể bật mã hoá Adiantum bằng cách đặt
metadata_encryption=adiantum
. - Trên các thiết bị hỗ trợ khoá được gói bằng phần cứng, bạn có thể tạo khoá mã hoá siêu dữ liệu được gói bằng phần cứng bằng cách thiết lập
metadata_encryption=aes-256-xts:wrappedkey_v0
(hoặc tương đương vớimetadata_encryption=:wrappedkey_v0
, vìaes-256-xts
là thuật toán mặc định).
Vì giao diện hạt nhân đến dm-default-key
đã thay đổi trong Android 11, nên bạn cũng cần đảm bảo rằng bạn đã đặt giá trị chính xác cho PRODUCT_SHIPPING_API_LEVEL
trong device.mk
. Ví dụ: nếu thiết bị của bạn khởi chạy bằng Android 11 (API cấp 30), thì device.mk
phải chứa:
PRODUCT_SHIPPING_API_LEVEL := 30
Bạn cũng có thể thiết lập 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
Xác nhận kết quả
Để xác minh rằng tính năng mã hoá siêu dữ liệu đã được bật và đang hoạt động đúng cách, hãy chạy các chương trình kiểm thử được mô tả bên dưới. Ngoài ra, hãy lưu ý đến các vấn đề thường gặp được mô tả bên dưới.
Kiểm thử
Bắt đầu bằng cách chạy lệnh sau để xác minh rằng tính năng mã hoá siêu dữ liệu đã được bật trên bộ nhớ trong:
adb root
adb shell dmctl table userdata
Nội dung xuất sẽ 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 đè chế độ cài đặt mã hoá mặc định bằng cách đặt tuỳ chọn metadata_encryption
trong fstab
của thiết bị, thì kết quả sẽ hơi khác so với kết quả ở trên. Ví dụ: nếu bạn đã bật mã hoá 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 quá trình mã hoá 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 đề thường gặp
Trong lệnh gọi đến mount_all
, lệnh gọi đến phân vùng /data
đã mã hoá siêu dữ liệu, init
sẽ thực thi công cụ vdc. Công cụ vdc
kết nối với vold
qua binder
để thiết lập
thiết bị được mã hoá siêu dữ liệu và gắn kết phân vùng. Trong thời gian của lệnh gọi này, init
bị chặn và cố gắng đọc hoặc đặt khối thuộc tính init
cho đến khi mount_all
kết thúc.
Nếu ở giai đoạn này, bất kỳ phần nào trong 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ì các kết quả tắc nghẽn. Điều quan trọng là phải đảm bảo rằng vold
có thể hoàn tất việc đọc khoá, 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 đầy đủ khi mount_all
chạy, thì Keymaster sẽ không phản hồi vold
cho đến khi đọc một số thuộc tính nhất định từ init
, dẫn đến tình trạng tắc nghẽn như mô tả. Việc đặt exec_start wait_for_keymaster
phía trên lệnh gọi mount_all
có liên quan như đã đề ra sẽ đảm bảo rằng Keymaster sẽ chạy hoàn toàn trước, do đó giúp tránh tình trạng tắc nghẽn này.
Cấu hình trên bộ nhớ thích ứng
Kể từ Android 9, một hình thức mã hoá siêu dữ liệu luôn được bật trên bộ nhớ trong bất cứ khi nào FBE được bật, ngay cả khi tính năng mã hoá siêu dữ liệu chưa được bật trên bộ nhớ trong.
Trong AOSP, có hai cách triển khai mã hoá siêu dữ liệu trên bộ nhớ có thể áp dụng: một cách triển khai không dùng nữa dựa trên dm-crypt
và cách mới hơn dựa trên dm-default-key
. Để đảm bảo bạn đã chọn đúng phương thức triển khai cho thiết bị, hãy đảm bảo 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 bằng 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 để buộc sử dụng phương thức mã hoá siêu dữ liệu phương tiện 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 thức hiện tại
Trên các thiết bị chạy Android 11 trở lên, tính năng mã hoá siêu dữ liệu trên bộ nhớ có thể chuyển đổi sẽ sử dụng mô-đun hạt nhân dm-default-key
, giống như trên bộ nhớ trong. Hãy xem các điều kiện tiên quyết ở trên để biết các tuỳ chọn cấu hình hạt nhân cần bật. Xin lưu ý rằng phần cứng mã hoá cùng dòng hoạt động trên bộ nhớ trong của thiết bị có thể không có trên bộ nhớ có thể chuyển đổi, do đó, bạn có thể cần CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y
.
Theo mặc định, phương thức mã hoá siêu dữ liệu ổ đĩa dm-default-key
sử dụng thuật toán mã hoá AES-256-XTS với các lĩnh vực mã hoá 4096 byte. Bạn 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ư tuỳ chọn fstab metadata_encryption
được mô tả ở trên. Ví dụ: trên các thiết bị thiếu tính năng tăng tốc AES, bạn có thể bật tính năng mã hoá Adiantum bằng cách đặt ro.crypto.volume.metadata.encryption=adiantum
.
Phương thức cũ
Trên các thiết bị chạy Android 10 trở xuống, quá trình mã hoá siêu dữ liệu trên bộ nhớ có thể chấp nhận sẽ sử dụng mô-đun nhân dm-crypt
thay vì dm-default-key
:
CONFIG_DM_CRYPT=y
Không giống như phương thức dm-default-key
, phương thức dm-crypt
sẽ mã hoá nội dung tệp hai lần: một lần bằng khoá FBE và một lần bằng khoá mã hoá siêu dữ liệu. Phương thức mã hoá 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 việc mã hoá siêu dữ liệu, vì Android đảm bảo rằng các khoá FBE ít nhất cũng khó bị xâm phạm như khoá mã hoá siêu dữ liệu. Nhà cung cấp có thể tuỳ chỉnh hạt nhân để tránh quá trình mã hoá kép, cụ thể là bằng cách triển khai tuỳ chọn allow_encrypt_override
mà Android chuyển đến dm-crypt
khi thuộc tính hệ thống ro.crypto.allow_encrypt_override
được đặt thành true
.
Hạt nhân chung của Android không hỗ trợ các tuỳ chỉnh này.
Theo mặc định, phương thức mã hoá siêu dữ liệu của phương tiện dm-crypt
sử dụng thuật toán mã hoá AES-128-CBC với ESSIV và các phân đoạn mã hoá 512 byte. Bạn có thể ghi đè chế độ này bằng cách đặt các thuộc tính hệ thống sau (cũng được dùng cho FDE):
ro.crypto.fde_algorithm
chọn thuật toán mã hoá siêu dữ liệu. Các lựa chọn làaes-128-cbc
vàadiantum
. Bạn chỉ có thể sử dụng Adiantum 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 của ngành tiền mã hoá. Các lựa chọn là 512, 1024, 2048 và 4096. Đối với phương thức mã hoá Adiantum, hãy sử dụng 4096.