Giống như hầu hết phần mềm mã hoá tệp và đĩa, phương thức mã hoá bộ nhớ của Android thường dựa vào các khoá mã hoá thô có trong bộ nhớ hệ thống để có thể thực hiện quá trình mã hoá. Ngay cả khi thực hiện mã hoá bằng phần cứng chuyên dụng thay vì bằng phần mềm, thì phần mềm thường vẫn cần quản lý khoá mã hoá thô.
Thường thì đây không phải là vấn đề vì các khoá sẽ không xuất hiện trong một cuộc tấn công ngoại tuyến, đây là loại tấn công chính mà bộ nhớ mã hoá nhằm mục đích bảo vệ. Tuy nhiên, mong muốn cung cấp tăng cường khả năng bảo vệ trước các loại tấn công khác, chẳng hạn như cold boot (khởi động nguội) các cuộc tấn công và cuộc tấn công trực tuyến mà trong đó kẻ tấn công có thể rò rỉ hệ thống mà không gây ảnh hưởng hoàn toàn đến thiết bị.
Để giải quyết vấn đề này, Android 11 đã ra mắt tính năng hỗ trợ dành cho khoá gói phần cứng (có hỗ trợ phần cứng). Khoá bọc phần cứng là khoá lưu trữ chỉ được xác định ở dạng thô để phần cứng chuyên dụng; phần mềm chỉ nhìn thấy và làm việc với các phím này được bọc (được mã hoá). Phần cứng này phải có khả năng tạo và nhập khoá lưu trữ, khoá lưu trữ gói ở dạng tạm thời và dài hạn, lấy từ khoá con, trực tiếp lập trình một khoá con thành một công cụ mã hoá cùng dòng, và trả về một khoá con riêng biệt cho phần mềm.
Lưu ý: Một công cụ mã hoá nội tuyến (hoặc công cụ mã hoá nội tuyến) phần cứng mã hoá) đề cập đến phần cứng mã hoá/giải mã dữ liệu trong khi ảnh đang được truyền đến/từ thiết bị lưu trữ. Thông thường, đây là máy chủ UFS hoặc eMMC bộ điều khiển triển khai các tiện ích Crypto được xác định bằng Quy cách của JEDEC.
Thiết kế
Phần này trình bày thiết kế của tính năng phím bọc phần cứng, bao gồm cần hỗ trợ phần cứng nào để làm việc này. Cuộc thảo luận này tập trung vào mã hoá dựa trên tệp (FBE), nhưng giải pháp này áp dụng cho siêu dữ liệu mã hoá.
Một cách để tránh cần đến khoá mã hoá thô trong bộ nhớ hệ thống là chỉ đặt chúng trong các ô khoá của một công cụ mã hoá cùng dòng. Tuy nhiên, việc này phương pháp tiếp cận này gặp phải một số vấn đề:
- Số lượng khoá mã hoá có thể vượt quá số lượng khe khoá.
- Công cụ mã hoá nội tuyến chỉ có thể dùng để mã hoá/giải mã toàn bộ khối dữ liệu trên ổ đĩa. Tuy nhiên, trong trường hợp của FBE, phần mềm vẫn cần phải có khả năng thực hiện công việc mật mã khác như mã hoá tên tệp và khoá dẫn xuất giá trị nhận dạng. Phần mềm vẫn cần truy cập vào các khoá FBE thô để làm công việc khác này.
Để tránh những sự cố này, khoá lưu trữ sẽ được chuyển thành khoá bọc phần cứng, là loại khoá mà chỉ có đối tượng mới có thể mở gói và sử dụng phần cứng chuyên dụng. Điều này cho phép hỗ trợ số lượng khoá không giới hạn. Trong Ngoài ra, hệ phân cấp khoá được sửa đổi và di chuyển một phần sang phần cứng này, cho phép trả về một khoá con cho phần mềm cho các tác vụ không thể sử dụng công cụ mã hoá cùng dòng.
Hệ phân cấp khoá
Bạn có thể lấy khoá từ các khoá khác bằng cách sử dụng KDF (hàm dẫn xuất khoá), chẳng hạn như HKDF, dẫn đến hệ thống phân cấp khoá.
Biểu đồ dưới đây mô tả hệ phân cấp khoá điển hình cho FBE khi khoá bọc phần cứng không được sử dụng:
Khoá lớp FBE là khoá mã hoá thô mà Android truyền sang Linux để mở khoá một tập hợp thư mục đã mã hoá cụ thể, chẳng hạn như bộ nhớ được mã hoá thông tin xác thực cho một người dùng Android cụ thể. (Trong kernel, đây là được gọi là khoá chính fscrypt.) Từ khoá này, hạt nhân suy ra các khoá con sau:
- Giá trị nhận dạng khoá. Giá trị này không được dùng để mã hoá mà là một giá trị được dùng để xác định khoá cho một tệp hoặc thư mục cụ thể được bảo vệ.
- Khoá mã hoá nội dung tệp
- Khoá mã hoá tên tệp
Ngược lại, biểu đồ dưới đây mô tả hệ phân cấp khoá của FBE khi khoá bọc phần cứng được dùng:
So với trường hợp trước, khoá đã được thêm một cấp bổ sung và khoá mã hoá nội dung tệp đã bị chuyển vị trí. Gốc nút vẫn đại diện cho khoá mà Android truyền sang Linux để mở khoá một tập hợp các thư mục đã mã hoá. Tuy nhiên, giờ đây khoá đó nằm ở dạng được gói tạm thời và để sử dụng, URL đó phải được truyền đến phần cứng chuyên dụng. Phần cứng này phải triển khai 2 giao diện lấy một khoá được gói tạm thời:
- Một giao diện để lấy
inline_encryption_key
và trực tiếp lập trình mã đó vào một ô khoá của công cụ mã hoá cùng dòng. Thao tác này cho phép tệp nội dung được mã hoá/giải mã mà không cần phần mềm có quyền truy cập vào dữ liệu thô . Trong các nhân phổ biến của Android, giao diện này tương ứng với Toán tửblk_crypto_ll_ops::keyslot_program
, phải là do trình điều khiển bộ nhớ triển khai. - Một giao diện để lấy và trả về
sw_secret
("phần mềm bí mật" -- còn được gọi là "bí mật thô" ở một số nơi), đây là chìa khoá Linux sử dụng để lấy các khoá con cho mọi thứ khác ngoài nội dung tệp mã hoá. Trong các nhân phổ biến của Android, giao diện này tương ứng với Toán tửblk_crypto_ll_ops::derive_sw_secret
, phải là do trình điều khiển bộ nhớ triển khai.
Để lấy inline_encryption_key
và sw_secret
từ
khoá lưu trữ thô, phần cứng phải sử dụng KDF được mã hoá mạnh. KDF này
phải tuân theo các phương pháp hay nhất về mật mã học; thiết bị phải có độ mạnh bảo mật là
tối thiểu 256 bit, tức là đủ cho mọi thuật toán được sử dụng sau này. Mã này cũng phải sử dụng
nhãn, ngữ cảnh và/hoặc chuỗi thông tin dành riêng cho ứng dụng riêng biệt khi
lấy từng loại khoá con để đảm bảo rằng các khoá con thu được
được tách biệt bằng mật mã, tức là việc biết về một trong số đó sẽ không cho thấy bất kỳ điều gì
khác. Không bắt buộc kéo giãn khoá vì khoá lưu trữ thô đã là
phím ngẫu nhiên thống nhất.
Về mặt kỹ thuật, bạn có thể sử dụng bất kỳ KDF nào đáp ứng các yêu cầu về bảo mật.
Tuy nhiên, đối với mục đích thử nghiệm, cần phải triển khai lại cùng một KDF trong
mã kiểm thử. Hiện tại, một KDF đã được xem xét và triển khai; có thể tìm thấy thiết bị đó
trong mã nguồn cho vts_kernel_encryption_test
.
Phần cứng nên sử dụng KDF này. KDF này sử dụng NIST SP 800-108 "KDF ở chế độ bộ đếm" với AES-256-CMAC làm PRF. Xin lưu ý rằng để tương thích, tất cả
các phần của thuật toán phải giống hệt nhau, bao gồm cả việc lựa chọn ngữ cảnh KDF
và nhãn cho từng khoá con.
Bao bọc phím
Để đáp ứng mục tiêu bảo mật của khoá bọc phần cứng, có 2 kiểu gói khoá được xác định:
- Gói tạm thời: phần cứng mã hoá khoá thô bằng cách sử dụng một khoá được tạo ngẫu nhiên mỗi lần khởi động và không được hiển thị trực tiếp bên ngoài phần cứng.
- Gói dài hạn: phần cứng mã hoá khoá thô bằng cách sử dụng một một khoá duy nhất, cố định được tích hợp sẵn trong phần cứng mà không trực tiếp bên ngoài phần cứng.
Tất cả các khoá được truyền tới nhân hệ điều hành Linux để mở khoá bộ nhớ đều tạm thời. Điều này đảm bảo rằng nếu kẻ tấn công có thể trích xuất khoá đang sử dụng trong bộ nhớ hệ thống thì không chỉ sử dụng được khoá đó ngoài thiết bị mà còn trên thiết bị sau khi khởi động lại.
Đồng thời, Android vẫn cần có khả năng lưu trữ phiên bản đã mã hoá phím trên ổ đĩa để có thể mở khoá ngay từ đầu. Dữ liệu thô khoá sẽ hoạt động cho mục đích này. Tuy nhiên, chúng ta nên không bao giờ có dữ liệu thô các khoá đều có trong bộ nhớ hệ thống để không ai có thể trích xuất sang được dùng bên ngoài thiết bị, ngay cả khi được trích xuất tại thời điểm khởi động. Vì lý do này, khái niệm là gói dài hạn được xác định.
Để hỗ trợ quản lý các khoá được gói theo hai cách khác nhau này, phần cứng phải triển khai các giao diện sau:
- Các giao diện để tạo và nhập khoá lưu trữ, trả lại chúng
gói dài hạn. Các giao diện này được truy cập gián tiếp thông qua
KeyMint và các thẻ này tương ứng với thẻ KeyMint
TAG_STORAGE_KEY
. Lệnh "generate" (tạo) khả năng đượcvold
dùng để tạo bộ nhớ mới các khoá để Android sử dụng, còn tuỳ chọn "nhập" khả năng được sử dụng bởivts_kernel_encryption_test
để nhập khoá kiểm thử. - Một giao diện để chuyển đổi khoá lưu trữ được gói trong thời gian dài thành
khoá lưu trữ tạm thời. Điều này tương ứng với
Phương thức KeyMint
convertStorageKeyToEphemeral
. Phương thức này được sử dụng bởi cảvold
vàvts_kernel_encryption_test
theo thứ tự để mở khoá bộ nhớ.
Thuật toán gói khoá là chi tiết triển khai, nhưng phải sử dụng AEAD mạnh như AES-256-GCM với IV ngẫu nhiên.
Yêu cầu thay đổi phần mềm
AOSP đã có khung cơ bản để hỗ trợ các khoá được gói phần cứng. Chiến dịch này
bao gồm tính năng hỗ trợ trong các thành phần không gian người dùng như vold
, cũng như
làm hỗ trợ nhân Linux trong blk-Crypto, fscrypt và
dm-default-key.
Tuy nhiên, bạn bắt buộc phải thực hiện một số thay đổi cụ thể về việc triển khai.
Các thay đổi của KeyMint
Phải sửa đổi quá trình triển khai KeyMint của thiết bị để hỗ trợ
TAG_STORAGE_KEY
và triển khai
convertStorageKeyToEphemeral
.
Trong Keymaster, exportKey
đã được dùng thay cho
convertStorageKeyToEphemeral
Thay đổi nhân hệ điều hành Linux
Bạn phải sửa đổi trình điều khiển nhân hệ điều hành Linux cho công cụ mã hoá cùng dòng của thiết bị để hỗ trợ các khoá được gói phần cứng.
Đối với các hạt nhân android14
trở lên,
thiết lập BLK_CRYPTO_KEY_TYPE_HW_WRAPPED
trong blk_crypto_profile::key_types_supported
,
tạo blk_crypto_ll_ops::keyslot_program
và blk_crypto_ll_ops::keyslot_evict
hỗ trợ lập trình/loại bỏ khoá được gói phần cứng,
và triển khai blk_crypto_ll_ops::derive_sw_secret
.
Đối với các hạt nhân android12
và android13
,
đặt BLK_CRYPTO_FEATURE_WRAPPED_KEYS
trong blk_keyslot_manager::features
,
tạo blk_ksm_ll_ops::keyslot_program
và blk_ksm_ll_ops::keyslot_evict
hỗ trợ lập trình/loại bỏ khoá được gói phần cứng,
và triển khai blk_ksm_ll_ops::derive_raw_secret
.
Đối với hạt nhân android11
,
thiết lập BLK_CRYPTO_FEATURE_WRAPPED_KEYS
trong keyslot_manager::features
,
tạo keyslot_mgmt_ll_ops::keyslot_program
và keyslot_mgmt_ll_ops::keyslot_evict
hỗ trợ lập trình/loại bỏ khoá được gói phần cứng,
và triển khai keyslot_mgmt_ll_ops::derive_raw_secret
.
Thử nghiệm
Mặc dù phương thức mã hoá bằng khoá bọc phần cứng khó kiểm tra hơn so với phương thức mã hoá
bằng các khoá tiêu chuẩn, bạn vẫn có thể kiểm tra bằng cách nhập khoá kiểm tra và
triển khai lại quy trình dẫn xuất khoá mà phần cứng thực hiện. Cách này được triển khai
trong vts_kernel_encryption_test
. Để chạy kiểm thử này,
chạy:
atest -v vts_kernel_encryption_test
Đọc nhật ký kiểm thử và xác minh rằng các trường hợp kiểm thử khoá được gói phần cứng (ví dụ:
FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy
và
DmDefaultKeyTest.TestHwWrappedKey
) không được bỏ qua do còn hỗ trợ
khi không phát hiện được khoá bao bọc phần cứng, vì kết quả kiểm tra vẫn sẽ
"đã vượt qua" trong trường hợp đó.
Đang bật
Khi tính năng hỗ trợ khoá bao bọc phần cứng của thiết bị hoạt động đúng cách, bạn có thể
thực hiện các thay đổi sau đối với tệp fstab
của thiết bị để
Android sử dụng công cụ này để mã hoá siêu dữ liệu và FBE:
- FBE: thêm cờ
wrappedkey_v0
vào Tham sốfileencryption
. Ví dụ: hãy sử dụngfileencryption=::inlinecrypt_optimized+wrappedkey_v0
. Cho để biết thêm chi tiết, hãy xem FBE . - Mã hoá siêu dữ liệu: thêm cờ
wrappedkey_v0
vào Tham sốmetadata_encryption
. Ví dụ: hãy sử dụngmetadata_encryption=:wrappedkey_v0
. Để biết thêm chi tiết, hãy xem siêu dữ liệu tài liệu mã hoá.