Android 7.0 trở lên hỗ trợ mã hoá dựa trên tệp (FBE). FBE cho phép mã hoá các tệp khác nhau bằng các khoá khác nhau có thể được 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 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ã hoá. Nhìn chung, thông tin khác này được gọi là siêu dữ liệu hệ thống tệp.
Android 9 đã hỗ trợ 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 có trong thời gian 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 KeyMint (trước đây là Keymaster), và KeyMint 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ể sử dụng 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ị ra mắt cùng với 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 chế độ 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 chế độ 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 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à thứ mà OTA nên thay đổi.
Tính năng mã hoá siêu dữ liệu yêu cầu bạn bật mô-đun dm-default-key
trong nhân. Trong Android 11 trở lên, dm-default-key
được các 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 một khung mã hoá độ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ã 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ó thể. Nếu không sử dụng phần cứng mã hoá nội tuyến, bạn cũng cần bật chế độ dự phòng cho API mật mã của 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 FBE.
Trong Android 10 trở xuống, dm-default-key
không được nhân chung của Android hỗ trợ. Do đó, các nhà cung cấp phải triển khai dm-default-key
.
Thiết lập hệ thống tệp siêu dữ liệu
Vì không có dữ liệu nào trong phân vùng userdata có thể đọc được 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 riêng biệt có tên là phân vùng siêu dữ liệu để lưu trữ các blob KeyMint bảo vệ khoá này. Phân vùng siêu dữ liệu phải có kích thước 16 MB.
fstab.hardware
phải có một mục cho hệ thống tệp siêu dữ liệu nằm trên phân vùng đó, gắn hệ thống tệp đó tại /metadata
, bao gồm cả cờ formattable
để đảm bảo hệ thống tệp được định dạng tại thời gian 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; thay vào đó, 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 kết /metadata
tồn tại, hãy thêm dòng sau vào BoardConfig-common.mk
:
BOARD_USES_METADATA_PARTITION := true
Các thay đổi đối với trình tự khởi động
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 đoạn sau vào init.hardware.rc
:
# We need vold early for metadata encryption on early-fs start vold
KeyMint 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 chỉ dẫn mount_all
để gắn /data
vào khổ thơ on
late-fs
. Trước dòng này, hãy thêm chỉ thị để 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, hãy thêm keydirectory=/metadata/vold/metadata_encryption
vào cột fs_mgr_flags của mục 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ã 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 những thiết bị không có tính năng tăng tốc AES, bạn có thể bật phương thức mã hoá Adiantum bằng cách đặt
metadata_encryption=adiantum
. - Trên các thiết bị hỗ trợ khoá được bao bọc bằng phần cứng, bạn có thể tạo khoá mã hoá siêu dữ liệu đượ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 nhân với 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 chạy 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
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 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ì đầu ra sẽ hơi khác so với đầu ra ở trên. Ví dụ: nếu bạn bật hoạt động 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 này gắn phân vùng /data
được mã hoá bằng 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á bằng siêu dữ liệu và gắn phân vùng. Trong thời gian gọi này, init
sẽ 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
hoàn tất.
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 một thuộc tính, thì sẽ xảy ra tình trạng bế tắc. Điều quan trọng là phải đảm bảo rằng vold
có thể hoàn tất việc đọc các khoá, tương tác với KeyMint 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 KeyMint chưa khởi động hoàn toàn khi mount_all
chạy, thì KeyMint 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 chính xác tình trạng tắc nghẽn được mô tả. Việc đặt exec_start wait_for_keymaster
ở trên lệnh gọi mount_all
có liên quan như đã nêu đảm bảo rằng KeyMint đang chạy hoàn toàn trước và do đó tránh được 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ớ có thể sử dụng bất cứ khi nào FBE được bật, ngay cả khi tính năng mã hoá siêu dữ liệu không được bật trên bộ nhớ trong.
Trong AOSP, có 2 cách triển khai mã hoá siêu dữ liệu trên bộ nhớ có thể sử dụng: một cách đã không còn được dùng dựa trên dm-crypt
và một cách mới hơn dựa trên dm-default-key
. Để đảm bảo bạn chọn đúng cách triển khai cho thiết bị của mình, 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 bằng Android 11 (API cấp 30), thì device.mk
sẽ 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 âm lượng 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, hoạt động mã hoá siêu dữ liệu trên bộ nhớ có thể sử dụng sẽ dùng mô-đun 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 những lựa 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 dùng được trên bộ nhớ có thể sử dụng và do đó, 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 của ổ đĩa dm-default-key
sử dụng thuật toán mã hoá AES-256-XTS với các khu vực mã hoá 4096 byte. Bạn có thể ghi đè thuật toán này 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ùng cú pháp với tuỳ chọn metadata_encryption
fstab được mô tả ở trên. Ví dụ: trên những thiết bị không có tính năng tăng tốc AES, bạn có thể bật phương thức mã hoá Adiantum bằng cách đặt ro.crypto.volume.metadata.encryption=adiantum
.
Phương pháp cũ
Trên các thiết bị chạy Android 10 trở xuống, hoạt động mã hoá siêu dữ liệu trên bộ nhớ có thể sử dụng 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
khiến nội dung tệp được mã hoá 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. Việc mã hoá kép này làm giảm hiệu suất và không cần thiết để đạ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. Các nhà cung cấp có thể tuỳ chỉnh nhân để tránh mã hoá kép, đặc biệt là bằng cách triển khai lựa chọn allow_encrypt_override
mà Android truyền đến dm-crypt
khi thuộc tính hệ thống ro.crypto.allow_encrypt_override
được đặt thành true
.
Nhân chung của Android không hỗ trợ các chế độ tuỳ chỉnh này.
Theo mặc định, phương thức mã hoá siêu dữ liệu của ổ đĩa dm-crypt
sử dụng thuật toán mã hoá AES-128-CBC với ESSIV và các thành phầ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ể dùng Adiantum nếu thiết bị không có tính năng tăng tốc AES.ro.crypto.fde_sector_size
chọn kích thước của phân vùng mã hoá. Các lựa chọn là 512, 1024, 2048 và 4096. Đối với công nghệ mã hoá Adiantum, hãy dùng 4096.