Triển khai dm-verity

Android 4.4 trở lên hỗ trợ tính năng Xác minh quy trình khởi động thông qua tuỳ chọn tính năng hạt nhân của tính năng ánh xạ thiết bị (dm-verity), mang lại tính minh bạch kiểm tra tính toàn vẹn của thiết bị khối. dm-verity giúp ngăn chặn các bộ công cụ gốc (rootkit) tồn tại lâu dài có thể giữ lại đặc quyền gốc và xâm phạm thiết bị. Tính năng này giúp người dùng Android chắc chắn rằng khi khởi động thiết bị, thiết bị đó sẽ ở trạng thái giống như lần sử dụng gần nhất.

Các ứng dụng có khả năng gây hại (PHA) có đặc quyền gốc có thể ẩn khỏi chương trình phát hiện vi phạm và tự che giấu. Phần mềm can thiệp vào hệ thống có thể làm được điều này vì thường có nhiều đặc quyền hơn so với trình phát hiện, cho phép phần mềm "nói dối" các chương trình phát hiện.

Tính năng dm-verity cho phép bạn xem một thiết bị khối, lớp bộ nhớ cơ bản của hệ thống tệp và xác định xem thiết bị đó có khớp với cấu hình dự kiến hay không. Phương thức này thực hiện việc này bằng cách sử dụng cây băm mật mã. Đối với mỗi khối (thường là 4k), có hàm băm SHA256.

Vì các giá trị băm được lưu trữ trong một cây trang, nên chỉ có băm "gốc" cấp cao nhất mới được tin cậy để xác minh phần còn lại của cây. Khả năng sửa đổi bất kỳ khối nào sẽ tương đương với việc phá vỡ hàm băm mật mã. Xem sơ đồ sau để xem mô tả cấu trúc này.

dm-verity-hash-table

Hình 1. Bảng băm dm-verity

Khoá công khai được đưa vào phân vùng khởi động và phải được nhà sản xuất thiết bị xác minh bên ngoài. Khoá đó được dùng để xác minh chữ ký cho hàm băm đó, đồng thời xác nhận phân vùng hệ thống của thiết bị được bảo vệ và không thay đổi.

Hoạt động

Tính năng bảo vệ dm-verity nằm trong nhân. Vì vậy, nếu phần mềm can thiệp vào hệ thống trước khi hạt nhân khởi động, thì phần mềm đó sẽ giữ lại quyền truy cập đó. Để giảm thiểu điều này hầu hết các nhà sản xuất đều xác minh nhân hệ điều hành bằng cách sử dụng khoá đã đốt cháy trong thiết bị. Bạn không thể thay đổi khoá đó sau khi thiết bị rời khỏi nhà máy.

Nhà sản xuất sử dụng khoá đó để xác minh chữ ký trên trình tải khởi động cấp đầu tiên, từ đó xác minh chữ ký trên các cấp tiếp theo, trình tải khởi động ứng dụng và cuối cùng là hạt nhân. Mỗi nhà sản xuất muốn tận dụng tính năng xác minh quy trình khởi động phải có một phương thức để xác minh tính toàn vẹn của hạt nhân. Giả sử hạt nhân đã được xác minh, hạt nhân hệ điều hành có thể xem xét một thiết bị khối và xác minh nó khi nó được gắn kết.

Một cách để xác minh thiết bị khối là trực tiếp băm nội dung của thiết bị đó rồi so sánh chúng thành một giá trị được lưu trữ. Tuy nhiên, việc cố gắng xác minh toàn bộ thiết bị khối có thể sẽ mất một khoảng thời gian dài và tiêu thụ nhiều năng lượng của thiết bị. Các thiết bị sẽ mất nhiều thời gian để khởi động và sau đó bị tiêu hao pin đáng kể trước khi sử dụng.

Thay vào đó, dm-verity xác minh từng khối riêng lẻ và chỉ khi mỗi khối đã truy cập. Khi đọc vào bộ nhớ, khối này được băm song song. Sau đó, hàm băm sẽ được xác minh lên cây. Và vì việc đọc khối là một thao tác tốn kém, nên độ trễ do quy trình xác minh cấp khối này gây ra là tương đối nhỏ.

Nếu không xác minh được, thiết bị sẽ tạo lỗi I/O cho biết không thể đọc khối. Có vẻ như hệ thống tệp đã bị hỏng, như dự kiến.

Các ứng dụng có thể chọn tiếp tục mà không có dữ liệu thu được, chẳng hạn như khi thì những kết quả đó không cần thiết đối với chức năng chính của ứng dụng. Tuy nhiên, nếu ứng dụng không thể tiếp tục khi không có dữ liệu, thì ứng dụng sẽ không hoạt động.

Sửa lỗi tiến

Android 7.0 trở lên cải thiện độ mạnh mẽ của dm-verity bằng tính năng sửa lỗi chuyển tiếp (FEC). Việc triển khai AOSP bắt đầu với phần tử chung Reed-Solomon và áp dụng một mã sửa lỗi có tên là xen kẽ để giảm mức hao tổn không gian và tăng số lượng khối bị lỗi có thể khôi phục được. Để biết thêm chi tiết về FEC, hãy xem Thực thi nghiêm ngặt quy trình Xác minh quy trình khởi động có sửa lỗi.

Triển khai

Tóm tắt

  1. Tạo hình ảnh hệ thống có định dạng ext4.
  2. Tạo cây băm cho hình ảnh đó.
  3. Tạo bảng dm-verity cho cây băm đó.
  4. Ký bảng dm-verity đó để tạo chữ ký bảng.
  5. Nhóm chữ ký trong bảng và bảng dm-verity vào siêu dữ liệu chính xác.
  6. Kết hợp hình ảnh hệ thống, siêu dữ liệu về tính xác thực và cây băm.

Hãy xem phần The Chromium Projects – Verified Boot (Dự án Chromium – Khởi động được xác minh) để biết nội dung mô tả chi tiết về cây băm và bảng dm-verity.

Tạo cây băm

Như đã mô tả trong phần giới thiệu, cây băm là phần không thể thiếu đối với dm-verity. Chiến lược phát hành đĩa đơn công cụ thiết lập mật mã sẽ tạo cây băm cho bạn. Ngoài ra, bạn có thể xác định một giá trị tương thích tại đây:

<your block device name> <your block device name> <block size> <block size> <image size in blocks> <image size in blocks + 8> <root hash> <salt>

Để tạo thành hàm băm, ảnh hệ thống được chia tại lớp 0 thành 4 khối, mỗi khối gán một hàm băm SHA256. Lớp 1 được tạo bằng cách chỉ kết hợp các hàm băm SHA256 đó vào các khối 4k, dẫn đến hình ảnh nhỏ hơn nhiều. Lớp 2 được tạo giống hệt nhau, với hàm băm SHA256 của Lớp 1.

Việc này được thực hiện cho đến khi các hàm băm SHA256 của lớp trước có thể vừa trong một chặn. Khi nhận được SHA256 của khối đó, bạn sẽ có hàm băm gốc của cây.

Kích thước của cây băm (và mức sử dụng dung lượng ổ đĩa tương ứng) thay đổi theo kích thước của phân vùng đã xác minh. Trong thực tế, kích thước của cây băm thường nhỏ, thường nhỏ hơn 30 MB.

Nếu có một khối trong lớp không được lấp đầy hoàn toàn theo cách tự nhiên bằng hàm băm của lớp trước, bạn nên thêm các số 0 vào khối đó để đạt được độ phân giải 4k dự kiến. Điều này cho bạn biết cây băm chưa bị xoá và thay vào đó được hoàn tất bằng dữ liệu trống.

Để tạo cây băm, hãy nối hàm băm lớp 2 với các hàm cho lớp đó 1, lớp 3 băm vào các băm của lớp 2, v.v. Viết tất cả những nội dung này ra đĩa. Xin lưu ý rằng lớp này không tham chiếu đến lớp 0 của hàm băm gốc.

Tóm lại, thuật toán chung để tạo cây băm như sau:

  1. Chọn một dữ liệu ngẫu nhiên (mã hoá thập lục phân).
  2. Huỷ nén hình ảnh hệ thống thành các khối 4k.
  3. Đối với mỗi khối, hãy lấy hàm băm SHA256 (có muối) của khối đó.
  4. Kết hợp các hàm băm này để tạo thành một cấp
  5. Đổ 0 vào cấp độ cho đến ranh giới khối 4k.
  6. Kết hợp cấp độ với cây băm.
  7. Lặp lại các bước từ 2 đến 6 sử dụng cấp độ trước đó làm nguồn cho các bước tiếp theo cho đến bạn chỉ có một hàm băm duy nhất.

Kết quả của việc này là một hàm băm duy nhất, là hàm băm gốc của bạn. Điều này và dữ liệu ngẫu nhiên của bạn được dùng trong quá trình tạo bảng lập bản đồ dm-verity.

Tạo bảng liên kết dm-verity

Tạo bảng ánh xạ dm-verity, bảng này xác định thiết bị khối (hoặc mục tiêu) cho hạt nhân và vị trí của cây băm (cùng một giá trị). Việc ánh xạ này được dùng để tạo và khởi động fstab. Bảng này cũng xác định kích thước của các khối và hash_start, vị trí bắt đầu của cây băm (cụ thể là số khối tính từ đầu hình ảnh).

Hãy xem cryptsetup để biết nội dung mô tả chi tiết về các trường trong bảng ánh xạ mục tiêu của Verity.

Ký bảng dm-verity

Ký bảng dm-verity để tạo chữ ký bảng. Khi xác minh một phân vùng, trước tiên, chữ ký bảng sẽ được xác thực. Việc này được thực hiện dựa trên một khoá trên hình ảnh khởi động ở một vị trí cố định. Các khoá thường được đưa vào hệ thống xây dựng của nhà sản xuất để tự động đưa vào các thiết bị ở một vị trí cố định.

Cách xác minh phân vùng bằng chữ ký và tổ hợp phím này:

  1. Thêm khoá RSA-2048 ở định dạng tương thích với libmincrypt vào phân vùng /boot tại /verity_key. Xác định vị trí của khoá dùng để xác minh cây băm.
  2. Trong thẻ fstab cho mục nhập có liên quan, hãy thêm verify cho các cờ fs_mgr.

Nhóm chữ ký trong bảng vào siêu dữ liệu

Nhóm chữ ký bảng và bảng dm-verity vào siêu dữ liệu xác thực. Toàn bộ khối siêu dữ liệu được tạo phiên bản để có thể mở rộng, chẳng hạn như thêm loại chữ ký thứ hai hoặc thay đổi một số thứ tự.

Để kiểm tra mức độ hợp lý, một số ma thuật được liên kết với mỗi bộ siêu dữ liệu của bảng giúp xác định bảng. Vì chiều dài được đưa vào tiêu đề hình ảnh hệ thống ext4, nên đây là cách để tìm siêu dữ liệu mà không cần biết nội dung của chính dữ liệu đó.

Điều này đảm bảo bạn chưa chọn xác minh một phân vùng chưa được xác minh. Nếu có, việc thiếu số kỳ diệu này sẽ khiến quá trình xác minh bị tạm dừng. Số này giống với 0xb001b001.

Các giá trị byte theo hệ thập lục phân là:

  • byte đầu tiên = b0
  • byte thứ hai = 01
  • byte thứ ba = b0
  • byte thứ tư = 01

Sơ đồ sau đây mô tả thông tin chi tiết về siêu dữ liệu của Verity:

<magic number>|<version>|<signature>|<table length>|<table>|<padding>
\-------------------------------------------------------------------/
\----------------------------------------------------------/   |
                            |                                  |
                            |                                 32K
                       block content

Bảng này mô tả các trường siêu dữ liệu đó.

Bảng 1. Xác minh các trường siêu dữ liệu

Trường Mục đích Kích thước Giá trị
số kỳ diệu được fs_mgr sử dụng để kiểm tra tính hợp lệ 4 byte 0xb001b001
version dùng để tạo phiên bản khối siêu dữ liệu 4 byte hiện là 0
Chữ ký chữ ký của bảng trong mẫu có đệm PKCS1.5 256 byte
chiều dài bảng độ dài của bảng dm-verity tính bằng byte 4 byte
bàn bảng dm-verity được mô tả ở trên byte có độ dài bảng
padding cấu trúc này có độ dài từ 0 đến 32k 0

Tối ưu hoá dm-verity

Để đạt được hiệu suất tốt nhất từ dm-verity, bạn nên:

  • Trong nhân, hãy bật NEON SHA-2 cho ARMv7 và các tiện ích SHA-2 cho ARMv8.
  • Thử nghiệm với các giá trị đọc trước và Preview_cluster để tìm ra cấu hình phù hợp nhất cho thiết bị của bạn.