Cấu hình tích hợp:
Cấu hình Phiên bản Mô tả
Linux kernel 3.10.10 linux-3.10.10
Hệ điều hành Linux Mint Ubuntu based OS
Giải thuật băm SHA512 Giải thuật tính hàm băm
dữ liệu
Mô hình tích hợp:
Thông qua phân tích luồng thực thi ứng dụng từ usermode, luận văn thử nghiệm hai hướng tích hợp sau:
Xác minh chữ ký tại hàm do_execve_common: Trong lộ trình cơ chế fork-and- exec, cuối cùng kernel sẽ sử dụng hàm do_execve_common để thực hiện thực thi file tương ứng. Chúng ta sẽ thực hiện Xác minh chữ ký tại hàm này. Hàm được khai báo với prototype header như sau:
static int do_execve_common(const char *filename, struct user_arg_ptr argv, struct user_arg_ptr envp);
Trong đó:
51
- argv là cấu trúc chứa con trỏ các tham số truyền cho chương trình. - envp là cấu trúc chứa con trỏ các biến môi trường.
Hình 21 Xác minh chữ ký xử lý tại do_execve_common
Xác minh chữ ký được thực hiện tại hàm do_mmap_pgoff: Các mã thực thi muốn được nạp lên trên vùng nhớ đều phải qua hệ thống các hàm mmap để thực hiện ánh xạ các dữ liệu trên filesystem vào bộ nhớ trước khi các dữ liệu này được chuyển tới con trỏ thực thi. Tương tự như trên, chúng ta sẽ thực hiện Xác minh chữ ký tại hàm do_mmap_pgoff là hàm xử lý chính trong các thao tác ánh xạ dữ liệu lên vùng nhớ.
Khai báo prototype của hàm này như sau:
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff, unsigned long *populate);
52
- Con trỏ file là con trỏ tới cấu trúc file, chứa thông tin về chương trình được xử lý.
- Biến addr là địa chỉ để thực hiện ánh xạ.
- Biến length và pgoff chỉ định kích thước và vị trí offset trong file (được mô tả trong con trỏ file) được load vào vùng nhớ.
- Biến prot mô tả cơ chế bảo vệ bộ nhớ file cho việc ánh xạ bao gồm các giá trị sau: PROT_EXEC vùng nhớ có thể được thực thi; PROT_READ vùng nhớ chỉ đọc; PROT_WRITE vùng nhớ chỉ ghi; PROT_NONE vùng nhớ cấm truy cập.
- Biến flags mô tả thuộc tính chia sẻ vùng nhớ này với các tiến trình khác: MAP_SHARED vùng nhớ này được chia sẻ với các tiến trình khác; MAP_PRIVATE vùng nhớ không được chia sẻ, chỉ tiến trình tạo mới có quyền truy cập tới vùng nhớ này.
Hình 22 Xác minh chữ ký tại do_mmap_pgoff
53
Từ các phiên bản 2.5, linux kernel hỗ trợ ký và xác minh chữ ký trên các kernel module (Module Signing). Linux kernel ký vào các modules trong quá trình cài đặt và thực hiện Xác minh chữ ký mỗi khi các module này được nạp lên vùng nhớ.
Luận văn sẽ sử dụng lại script để ký lên các kernel module để ký vào các file thực thi. Script được đặt trong thư mục scripts trong mã nguồn linux kernel.
Hình 23 Đặc tả cấu trúc chữ ký
Khối thông tin đặc tả chữ ký được lưu ở cuối file gốc nên không làm thay đổi cấu trúc cũng như dữ liệu file thực thi. Khối thông tin đặc tả chữ ký bao gồm bốn trường theo thứ tự như sau:
54 Signer’s name: Định danh tên người ký.
KeyIdentifier: định danh key.
Signature data: dữ liệu chữ ký
Information block: khối thông tin chữ ký
Trong đó, khối thông tin chữ ký bao gồm những thông tin sau:
Table 1: Bảng mô tả các trường thông tin chữ ký
STT Tên trường Kích thước Mô tả
1 algo 8 bytes Giải thuật mã hóa public key sử dụng
2 hash 8 bytes Giải thuật băm sử dụng
3 id_type 8 bytes Kiểu định danh key
4 signer_len 8 bytes Độ dài chuỗi định danh người ký
5 key_id_len 8 bytes Độ dài định danh key
6 padding 24 bytes Dự trữ
7 sig_len 32 bytes Độ dài dữ liệu chữ ký
Độ dài khối thông tin chữ ký là cố định (96 bytes) nên dựa vào việc đọc và phân tích cấu trúc này trong file ta có thể có được đầy đủ thông tin về chữ ký mà file sử dụng.
55
Để phục vụ cho các thao tác xác minh chữ ký dưới kernelmode, luận văn thiết kế ba hàm chức năng chính tích hợp trực tiếp vào mã nguồn linux. Khai báo các hàm như sau:
int proc_verify_sig(const char* filename);
Mô tả Hàm thực hiện xác minh chữ ký trong file thực thi tương ứng với đường dẫn trong filename.
Đầu vào
filename - Con trỏ chuỗi chứa đường dẫn file. bool sha512_file(char * inFilename, int offset, char * oSha512);
Mô tả Hàm thực hiện tính giá trị băm SHA-512 cho một phần dữ liệu trong file đầu vào.
Đầu vào
inFilename Là con trỏ chứa đường dẫn file
offset Kích thước dữ liệu được tính băm tính từ đầu file. oSha512 Là con trỏ bộ đệm chứa giá trị băm SHA512 tính toán
được.
static struct public_key_signature *proc_make_digest(char * inFilename, int offset);
Đầu vào inFilename Là con trỏ chứa đường dẫn file.
56
trường signer’s name) trong file đầu vào tính từ đầu file.
Cài đặt tích hợp:
Xác minh chữ ký tại hàm do_execve_common:
Hàm do_execve_common được đặt tại fs/exec.c trong mã nguồn linux kernel, luận văn thực hiện cài đặt tích hợp xác minh chữ ký như sau:
static int do_execve_common(const char *filename, struct user_arg_ptr argv, struct user_arg_ptr envp) {
struct linux_binprm *bprm; struct file *file;
struct files_struct *displaced; bool clear_in_exec;
int retval;
const struct cred *cred = current_cred();
/* Check integrity for executable file */
if ((filename != NULL) && (strstr(filename, "tuantm_") != NULL)){ if (vrd_verify_signature(filename) != 0){
printk("\n[TuanTM] - %s is blocked for security policies!", filename); return -EPERM;
} else{
printk("\n[TuanTM] - %s is passed with verify integrity checking!", filename);
57 }
}
/* End of check integrity for executable file */
Xác minh chữ ký tại hàm do_mmap_pgoff:
Hàm do_mmap_pgoff được đặt tại mm/mmap.c trong mã nguồn linux kernel, luận văn thực hiện cài đặt tích hợp xác minh chữ ký như sau:
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff) {
char* pname; struct path p; char* tmp;
struct mm_struct * mm = current->mm; struct inode *inode;
vm_flags_t vm_flags;
… … …
inode = file ? file->f_path.dentry->d_inode : NULL;
if (file) {
//begin check library p = file->f_path;
58
tmp = (char*) __get_free_page(GFP_TEMPORARY); if (tmp) {
pname = d_path(&p, tmp, PAGE_SIZE); path_put(&p);
if ((strstr(pname, "tuantm_") != NULL) && (prot & PROT_EXEC)){
int ret = vrd_verify_signature(pname); if (ret != 0){
printk("\n[TuanTM-mmap] - %s is blocked for security policies!", pname);
return -EPERM; }
else{
printk("\n[TuanTM-mmap] - %s is passed to vrd_verify_signature with result %d", pname, ret);
} } }
free_page((unsigned long)tmp); //end check library
Cấu hình và dịch mã nguồn linux kernel
Sau khi tích hợp mã nguồn như tren, cấu hình menuconfig hoặc .config trong mã nguồn linux kernel để linux kernel hỗ trợ các tính năng module signing (các hàm API hỗ trợ các thao tác mã hóa và xác minh chữ ký dưới kernelmode):
59
Hình 1: Cấu hình bật MODULE_SIG trong menuconfig
Hay cấu hình trong file .config (trong thư mục gốc của mã nguồn linux):
CONFIG_MODULE_SIG=y
Sau đó tiến hành dịch mã nguồn linux kernel thành file nhị phân với câu lệnh:
tuan ~#sudo make –j16
Sau quá trình dịch hoàn tất, ta nhận được một nhân linux kernel mới được tích hợp giải pháp code signing được thiết kế.