2016-05-22 31 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; 
} 
相关问题