Attualmente sto analizzando il processo di generazione entropica di un kernel Linux a 64 bit durante l'avvio del sistema (per scopi didattici). Il sistema è ospitato come / su una macchina virtuale (64 bit) (Xen domU). Per un'analisi approfondita, sto monitorando lo stato dei parametri di input rilevanti, ovvero come vengono elaborati. Nella funzione add_interrupt_randomness
ho trovato un codice la cui intenzione non mi è chiara: la gestione di cycles
(valore fornito dal contatore dei cicli della CPU) e now
(jiffies). Entrambi sono valori a 64 bit senza segno ed elaborati come segue:
c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
j_high = (sizeof(now) > 4) ? now >> 32 : 0;
fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
Così c_high
/ j_high
(__u32)
sono assegnati con il massimo 32 bit di cycles
/ now
e quindi assegnati (dopo XOR) al pool di entropia veloce.
Quindi una variazione massima dei valori forniti da c_high
e j_high
dovrebbe essere desiderabile ?. Ma poiché c_high
e j_high
sono basati su cycles
e now
/ jiffies, che sono variabili puramente incrementate, c'è una variazione molto piccola / nessuna nei 32 bit superiori come rivelano i valori tracciati:
Valori nella chiamata n. 1 di add_interrupt_randomness:
cycles:0xFFFEA432A6C2CB89 c_high:0xFFFEA432 now_jiffies:0x00000000FFFEDB0A j_high:0x00000000
Valori nella chiamata n. 4265 * di add_interrupt_randomness:
cycles:0xFFFEA43FBA85B313 c_high:0xFFFEA43F now_jiffies:0x00000000FFFEE80C j_high:0x00000000
* (l'avvio è completato a questo punto)
Durante l'avvio del sistema add_interrupt_randomness
è chiamato 4265 volte. Il valore di j_high
è costantemente 0x00000000
, il valore di c_high
incrementi da 0xFFFEA432
a 0xFFFEA43F
.
Quindi la mia domanda è: perché i 32 bit superiori vengono elaborati al posto di quelli più bassi, il che fornirebbe maggiore casualità?
Se interessati: questa è la definizione completa di 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);
}
da: link