2012-11-08 34 views
9

Có một hệ điều hành Mac OS X tương đương với RtlSecureZeroMemory/SecureZeroMemory, một hàm có chức năng chặn một bộ nhớ, nhưng cuộc gọi sẽ không được tối ưu hóa bởi trình biên dịch?Mac OS X tương đương với SecureZeroMemory/RtlSecureZeroMemory?

+1

FWIW, nếu bạn đang sử dụng OpenSSL, nó cung cấp chức năng 'OPENSSL_cleanse', ghi đè an toàn một khối bộ nhớ với dữ liệu giả ngẫu nhiên. –

+3

Xét rằng OpenSSL đã làm (và AFAIK, ** vẫn **) sử dụng các đối tượng chưa được khởi tạo trên stack làm nguồn entropy, tôi sẽ ngần ngại sử dụng nó để bảo mật nghiêm túc như thế này ... Các tác giả không hiểu sử dụng an toàn C. (Vấn đề này gây ra sự mất mát đáng kể của entropy tạo ra các phím khi Debian cố định lỗi của họ.) –

+0

R, những gì bạn nói là không hoàn toàn đúng sự thật. Debian đã loại bỏ việc sử dụng biến ngăn xếp ** và ** một số nguồn entropy hợp lệ khác và những gì còn lại chỉ là pid tiến trình. Nó không phải lỗi của OpenSSL và sử dụng các biến không được khởi tạo như ** nguồn entropy ** bổ sung là hoàn toàn ổn. – virco

Trả lời

14

Viết chức năng riêng của bạn:

void secure_zero(void *s, size_t n) 
{ 
    volatile char *p = s; 

    while (n--) *p++ = 0; 
} 

EDIT: cho câu hỏi trong các ý kiến, tại sao không memset? Cuộc gọi hàm memset có thể được tối ưu hóa bởi trình biên dịch nếu đối tượng mảng không truy cập được.

Lưu ý rằng C11 thêm (không bắt buộc) chức năng memset_s và tiêu chuẩn đảm bảo cuộc gọi chức năng không thể được tối ưu hóa đi:

(C11, K.3.7.4.1p4) "[...] Không giống như memset , bất kỳ lời gọi nào đến hàm memset_s đều được đánh giá đúng theo các quy tắc của máy trừu tượng như được mô tả trong (5.1.2.3) .Đó là, bất kỳ lệnh gọi nào đến hàm memset_s đều cho rằng bộ nhớ được chỉ ra bởi s và n có thể truy cập được trong tương lai và do đó phải chứa các giá trị được chỉ ra bởi c. "

+0

dường như rất hài hòa và cồng kềnh. tại sao không nhớ? –

+4

@ Daij-Djan * tại sao không nhớ *: vì trình biên dịch có thể tối ưu hóa cuộc gọi nếu đối tượng mảng không được truy cập thêm. * có vẻ như được làm hài hòa và cồng kềnh *: đây là một cách cổ điển để viết một hàm 'memset' và tôi thấy nó thanh lịch và súc tích. – ouah

+0

Dowvoter (nếu không phải @ Daij-Djan), nhờ giải thích lý do bạn downvoted. – ouah

3

Có tương đương Mac OS X của RtlSecureZeroMemory/SecureZeroMemory, một chức năng mà zero một khối bộ nhớ, nhưng cuộc gọi sẽ không được tối ưu hóa đi bởi trình biên dịch?

Trong phiên bản C thời gian gần đây hơn, bạn có memset_s. Đảm bảo của nó không được tối ưu hóa đi.

#define __STDC_WANT_LIB_EXT1__ 1 
#include <string.h> 
errno_t memset_s(void * restrict s, rsize_t smax, int c, rsize_t n) 

OS X cũng bao gồm chức năng bzero. Nhưng bzero(3) man pageskhông nêu rõ trạng thái không tùy thuộc vào việc xóa bởi trình tối ưu hóa.

Tránh các thủ thuật với vòng loại volatile vì không thể di chuyển được. Nó hoạt động như mong đợi trên Windows, nhưng các GCC folks giải thích volatile để có nghĩa là bộ nhớ được hỗ trợ bởi phần cứng cho I/O. Vì vậy, bạn không được phép sử dụng volatile để chế ngự trình tối ưu hóa.


Đây là triển khai lắp ráp nội tuyến bạn có thể sử dụng. Oddly, __volatile__ trên báo cáo ASM và khối là OK. Nó hoạt động tốt trên OS X (đó là nơi nó được viết ban đầu).

// g++ -Og -g3 -m64 wipe.cpp -o wipe.exe 
// g++ -Og -g3 -m32 wipe.cpp -o wipe.exe  
// g++ -Os -g2 -S -m64 wipe.cpp -o wipe.exe.S 
// g++ -Os -g2 -S -m32 wipe.cpp -o wipe.exe.S 

#include <iostream> 
#include <iomanip> 
#include <string> 
using namespace std; 

int main(int argc, char* argv[]) 
{ 
    string s("Hello world"); 
    cout << "S: " << s << endl; 

    char* ptr = &s[0]; 
    size_t size = s.length(); 

    if(ptr && size) 
    { 
     /* Needed because we can't just say to GCC, */ 
     /* "give me a register that you choose". */ 
     void* dummy; 

     __asm__ __volatile__ 
     (
     "%=:\n\t"    /* generate a unique label for TOP */ 

#if (__WORDSIZE == 64) 
     "subq $1, %2\n\t"  /* 0-based index */ 
#elif (__WORDSIZE == 32) 
     "subl $1, %2\n\t"  /* 0-based index */ 
#elif (__WORDSIZE == 16) 
     "subw $1, %2\n\t"  /* 0-based index */ 
#else 
# error Unknown machine word size 
#endif 

     "lea (%1, %2), %0\n\t" /* calcualte ptr[idx] */ 
     "movb $0, (%0)\n\t"  /* 0 -> ptr[size - 1] .. ptr[0] */ 
     "jnz %=b\n\t"   /* Back to TOP if non-zero */ 

     : "=&r" (dummy) 
     : "r" (ptr), "r" (size) 
     : "0", "1", "2", "cc" 
     ); 
    } 

#if 0 
    cout.setf(ios::hex, ios::basefield); 
    cout.fill('0'); 

    for(size_t i = 0; i < s.length(); i++) 
     cout << "0x" << setw(2) << ((int)s[i] & 0xff) << " "; 

    cout << endl; 
#endif 

    cout << "S: " << s << endl; 

    return 0; 
} 
Các vấn đề liên quan