Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.

Mã hóa siêu dữ liệu

Android 7.0 trở lên hỗ trợ mã hóa dựa trên tệp (FBE). FBE cho phép các tệp khác nhau được mã hóa bằng các khóa khác nhau có thể được 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, 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 có tại thời điểm khởi động sẽ mã hóa bất kỳ nội dung nào không được FBE mã hóa. Khóa này được bảo vệ bởi Keymaster, đến lượt nó được bảo vệ bằng khởi động đã xác minh.

Mã hóa 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. Mã hóa siêu dữ liệu cũng có thể được bật trên bộ nhớ trong. Các thiết bị chạy Android 11 trở lên phải được bật 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ự init 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 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.

Mã hóa siêu dữ liệu yêu cầu mô-đun dm-default-key được bật trong nhân của bạn. Trong Android 11 trở lên, dm-default-key được hỗ trợ bởi các hạt nhân chung của Android, phiên bản 4.14 trở lên. Phiên bản dm-default-key này sử dụng phần cứng và khung mã hóa độc lập với 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 đang trên đường đến / từ thiết bị lưu trữ) khi có sẵn. 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 bật dự phòng cho API mật mã của hạt 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 bật mọi khả năng tăng tốc dựa trên CPU như được khuyến nghị 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 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 biệt được 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à 16MB.

fstab.hardware phải bao gồm một mục nhập cho hệ thống tệp siêu dữ liệu sống trên phân vùng đó, gắn nó tại /metadata , bao gồm cả formattable định dạng để đảm bảo nó được định dạng 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; 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 đ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 chuỗi init

Khi mã hóa siêu dữ liệu được sử dụng, vold phải 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 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 mount /data .

init.hardware.rc nên đã chứa một mount_all để tự gắn /data trong khổ 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

Chuyển sang 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ị thiếu 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ởi phần cứng, khóa mã hóa siêu dữ liệu có thể được bao bọc bởi phần cứng bằng cách đặt metadata_encryption=aes-256-xts:wrappedkey_v0 (hoặc tương đương với metadata_encryption=:wrappedkey_v0 , vì aes-256-xts là thuật toán mặc định).

Vì giao diện hạt nhân thành dm-default-key đã thay đổi trong Android 11, 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 với Android 11 (API cấp 30), 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 là gì:

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 chính xác, hãy chạy các bài kiểm tra được mô tả bên dưới. Cũng lưu ý đến các vấn đề phổ biến được mô tả bên dướ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ì kết quả đầ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, chạy vts_kernel_encryption_test để xác minh tính đúng đắn 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 , nơi gắn kết phân vùng /data 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 khoảng 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 kết thúc mount_all . 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 trong việc đọc hoặc thiết lập thuộc tính, thì sẽ dẫn đến bế tắc. Điều quan trọng là phải đả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 các thuộc tính nhất định từ init , dẫn đến chính xác là deadlock được 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ư đã đặ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ể sử dụng

Kể từ Android 9, một dạng mã hóa 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 mã hóa siêu dữ liệu không được bật trên bộ nhớ trong.

Trong AOSP, có hai cách 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 cách 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 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 với Android 11 (API cấp 30), 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 pháp mã hóa siêu dữ liệu khối 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 là gì:

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ị khởi chạy Android 11 trở lên, mã hóa siêu dữ liệu trên bộ nhớ có thể sử dụng sử dụng mô-đun hạt 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 để kích hoạt các tùy chọn cấu hình hạt nhân nào. 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ể sử dụng 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 khối lượng lớn dm-default-key sử dụng thuật toán mã hóa AES-256-XTS với các ngành mật mã 4096 byte. Thuật toán có thể được ghi đè 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 tùy chọn fstab metadata_encryption được mô tả ở trên. Ví dụ: trên các thiết bị thiếu 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ị khởi chạy với Android 10 trở xuống, 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-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ã hóa hai lần: một lần với khóa FBE và một lần với 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 cần thiết để đạt đượ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 khóa FBE ít nhất khó bị xâm phạm như khóa mã hóa siêu dữ liệu. Các nhà cung cấp có thể thực hiện các tùy chỉnh hạt nhân để 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 đến 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 khối lượng dm-crypt sử dụng thuật toán mã hóa AES-128-CBC với ESSIV và các ngành 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-cbcadiantum . Adiantum chỉ có thể được sử dụng nếu thiết bị thiếu khả 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.