2016-05-22 33 views
2

許多加密庫包括類似於下面的代碼片段:爲什麼大多數c編譯器不會優化此歸零代碼?

/* Implementation that should never be optimized out by the compiler */ 
static void optimize_proof_zeroize(void *v, size_t n) 
{ 
    volatile unsigned char *p = v; 
    while(n--) *p++ = 0; 
} 

但我幼稚的做法不下去的優化編譯器:

/* Naive zeroization implementation */ 
static void naive_zeroize(unsigned char *c, size_t n) 
{ 
    int i; 
    for(i = 0; i < n; i++) 
     c[i] = 0; 
} 

該代碼是用來釋放的前補零敏感數據記憶。由於緩衝區不再被使用,優化編譯器假定它們可以安全地從編譯後的代碼中移除zeriozation。

什麼阻止第一個實現被優化?

+4

你可能想了解更多關於【了'volatile'預選賽(http://en.cppreference.com/w/c/language/易失性)。 –

+1

我看不出任何原因,任何片段都會被優化掉。也許你可以[編輯]你的問題,包括一個你爲什麼認爲第二個片段必須被優化掉的描述。 –

回答

6

The key這裏的詞是volatile。當變量聲明爲volatile時,它告訴編譯器該變量可以在該程序之外修改/訪問(例如通過硬件),因此它會強制編譯器在每次引用該變量時都不要優化該變量並訪問內存。

它在加密中的用法通常是清除堆棧中的祕密(密鑰)(局部變量)。由於堆棧用於本地變量,因此常規代碼(如/* Naive zeroization implementation */)似乎對程序的其他變量/狀態沒有任何影響,因此編譯器可能(也可能會)優化該代碼。爲了防止它,使用volatile限定符,它使編譯器保留該代碼並將局部變量的內存容量歸零。

編輯

例子:

void decrypt(void* src, void* dest, crypto_stuff_t* params) 
{ 
    crypto_key_t decryption_key; // will hold the decryption key 
    .... 
    .... 
    // end of flow 
    // we want to zero the content of decryption_key, otherwise its value 
    // will remain on the stack 
    // this: 
    // decryption_key <-- 0; 
    // will be just optimized out by the compiler 
    // but this won't: 
    volatile uint8_t* key_ptr = (uint8_t*)&decryption_key; 
    int i; 
    for(i = 0; i < sizeof(crypto_key_t); i++) 
     key_ptr[i] = 0; 
} 
相關問題