Hay varias otras publicaciones que hablan acerca de cómo agarrar una clave de un ram como
Mi pregunta es un poco diferente. Supongamos que tenemos la clave y, en una breve ventana, la utilizaremos para inicializar un cifrado (en este caso, ChaCha20) y luego borraremos la clave de la memoria (utilizando las mejores prácticas, memset, etc.) [* edit2]
Una vez que se inicializa el cifrado, ¿equivale eso a tener la clave en la memoria?
Específicamente, mirando el código de referencia ChaCha20: enlace
void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
Parece que uno simplemente necesita obtener la ubicación de la memoria apuntada por la entrada x- > leer como 48 bytes de datos desde ese punto, y lo tiene.
- ¿Esto es correcto?
- ¿Cómo se puede evitar esto en el software? (mejores prácticas)
EDITAR: veo que al menos la entrada [12] y la entrada [13] se ajustan a medida que se procesan los bytes ... y que el cifrado puede "buscarse" ajustando la entrada [8] y la entrada [9] (o al menos en salsa20, supongo que chacha20 es similar) ... por lo tanto, probablemente sería suficiente simplemente buscar una "ubicación" aleatoria, y cifrar algunos bytes de relleno aleatorios, al inicializar
- ¿Esto es correcto? ¿Mejoraría la defensa contra la obtención de la clave (o estado de inicialización)?
EDIT 2:
Creo que la clave se puede borrar de la memoria una vez que se inicializa el cifrado, ya que la implementación de referencia no la utiliza para descifrar ... ¿o me falta algo?
Ejemplo:
ECRYPT_init();
ECRYPT_keysetup(&ctx, MyKey, ECRYPT_MAXKEYSIZE, ECRYPT_MAXIVSIZE);
ECRYPT_ivsetup(&ctx, MyIv);
//notice neither MyKey nor MyIv are used here:
ECRYPT_decrypt_bytes(&ctx, ciphertext, plaintext, ciphertext_len);