Actualmente estoy analizando el proceso de generación de entropía de un kernel de Linux de 64 bits durante el inicio del sistema (con fines educativos). El sistema está alojado como / en una máquina virtual (64 bits) (Xen domU). Para un análisis profundo, estoy siguiendo el estado de los parámetros de entrada relevantes, es decir, cómo se procesan. En la función add_interrupt_randomness
encontré algún código cuya intención no me queda clara: el manejo de cycles
(valor proporcionado por el contador de ciclos de CPU) y now
(jiffies). Ambos son valores de 64 bits sin firmar y se procesan de la siguiente manera:
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
Entonces, c_high
/ j_high
(__u32)
se asignan con los 32 bits superiores de cycles
/ now
y luego se asignan (después de XOR) al grupo de entropía rápida.
Por lo tanto, una variación máxima de los valores proporcionados por c_high
y j_high
debería ser deseable. Pero como c_high
y j_high
se basan en cycles
y now
/ jiffies, que son variables puramente incrementadas, hay muy poca / ninguna variación en los 32 bits superiores como los valores trazados revelan:
Valores en la llamada no. 1 de add_interrupt_randomness:
cycles:0xFFFEA432A6C2CB89 c_high:0xFFFEA432 now_jiffies:0x00000000FFFEDB0A j_high:0x00000000
Valores en la llamada no. 4265 * de add_interrupt_randomness:
cycles:0xFFFEA43FBA85B313 c_high:0xFFFEA43F now_jiffies:0x00000000FFFEE80C j_high:0x00000000
* (el inicio se completa en este punto)
Durante el inicio del sistema, add_interrupt_randomness
se llama 4265 veces. El valor de j_high
es constantemente 0x00000000
, el valor de c_high
incrementos de 0xFFFEA432
a 0xFFFEA43F
.
Entonces mi pregunta es: ¿por qué se procesan los 32 bits superiores en lugar de los inferiores, lo que proporcionaría más aleatoriedad?
Si está interesado: esta es la definición completa de add_interrupt_randomness
:
void add_interrupt_randomness(int irq, int irq_flags)
{
struct entropy_store *r;
struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
cycles_t cycles = random_get_entropy();
__u32 c_high, j_high;
__u64 ip;
unsigned long seed;
int credit = 0;
if (cycles == 0)
cycles = get_reg(fast_pool, regs);
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
fast_pool->pool[1] ^= now ^ c_high;
ip = regs ? instruction_pointer(regs) : _RET_IP_;
fast_pool->pool[2] ^= ip;
fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
get_reg(fast_pool, regs);
fast_mix(fast_pool);
add_interrupt_bench(cycles);
if (!crng_ready()) {
if ((fast_pool->count >= 64) &&
crng_fast_load((char *) fast_pool->pool,
sizeof(fast_pool->pool))) {
fast_pool->count = 0;
fast_pool->last = now;
}
return;
}
if ((fast_pool->count < 64) &&
!time_after(now, fast_pool->last + HZ))
return;
r = &input_pool;
if (!spin_trylock(&r->lock))
return;
fast_pool->last = now;
__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
/*
* If we have architectural seed generator, produce a seed and
* add it to the pool. For the sake of paranoia don't let the
* architectural seed generator dominate the input from the
* interrupt noise.
*/
if (arch_get_random_seed_long(&seed)) {
__mix_pool_bytes(r, &seed, sizeof(seed));
credit = 1;
}
spin_unlock(&r->lock);
fast_pool->count = 0;
/* award one bit for the contents of the fast pool */
credit_entropy_bits(r, credit + 1);
}
de: enlace