Molto probabilmente 4294967295.
Nel file di origine dh.c
, il file di moduli viene aperto con fopen
e un ciclo di fgets
viene utilizzato per estrarre ogni riga. La riga corrente in elaborazione viene registrata in una variabile dichiarata come int linenum
. Ciò significa che è un intero con segno a 32 bit, in grado di rappresentare 2 32 valori possibili. Poiché è firmato, equivale a -2147483648 a 2147483647 (uno in meno perché 0 è ancora un numero ed è considerato positivo). Poiché inizia da 0 e incrementi, il valore massimo è quindi 2 32 / 2 - 1. Diventerà negativo se supera questo limite e si avvolge attorno.
C'è una certa conversione tra firmata e non firmata nel codice sorgente. int linenum
contiene il numero di righe, mentre int bestcount
ha il numero di linee adatte e viene passato a arc4random_uniform
, che genera un valore casuale compreso tra 0 e bestcount
. Il valore che accetta e il valore che restituisce non è firmato, ma è memorizzato in un altro intero con segno, which
. Questo numero intero viene utilizzato per specificare quale riga casuale deve essere utilizzata. Se il numero di righe supera quello che può contenere un intero a 32 bit, la scelta casuale del limite superiore della linea sarà più piccola, forse molto più piccola, rispetto al numero effettivo di linee.
Questa limitazione non è un problema nella pratica. La lunghezza massima di una linea è 4096 byte e 2 righe 32 (non - 1 perché la prima riga inizia da 0) di 4096 byte ciascuna dà una dimensione massima del file di 16 terabyte! Buona fortuna aspettando che openssl dhparam generi terabyte di moduli.
L'intera funzione nel codice sorgente, a partire da OpenSSH 7.5p1:
DH *
choose_dh(int min, int wantbits, int max)
{
FILE *f;
char line[4096];
int best, bestcount, which;
int linenum;
struct dhgroup dhg;
if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
logit("WARNING: could not open %s (%s), using fixed modulus",
_PATH_DH_MODULI, strerror(errno));
return (dh_new_group_fallback(max));
}
linenum = 0;
best = bestcount = 0;
while (fgets(line, sizeof(line), f)) {
linenum++;
if (!parse_prime(linenum, line, &dhg))
continue;
BN_clear_free(dhg.g);
BN_clear_free(dhg.p);
if (dhg.size > max || dhg.size < min)
continue;
if ((dhg.size > wantbits && dhg.size < best) ||
(dhg.size > best && best < wantbits)) {
best = dhg.size;
bestcount = 0;
}
if (dhg.size == best)
bestcount++;
}
rewind(f);
if (bestcount == 0) {
fclose(f);
logit("WARNING: no suitable primes in %s", _PATH_DH_MODULI);
return (dh_new_group_fallback(max));
}
linenum = 0;
which = arc4random_uniform(bestcount);
while (fgets(line, sizeof(line), f)) {
if (!parse_prime(linenum, line, &dhg))
continue;
if ((dhg.size > max || dhg.size < min) ||
dhg.size != best ||
linenum++ != which) {
BN_clear_free(dhg.g);
BN_clear_free(dhg.p);
continue;
}
break;
}
fclose(f);
if (linenum != which+1) {
logit("WARNING: line %d disappeared in %s, giving up",
which, _PATH_DH_MODULI);
return (dh_new_group_fallback(max));
}
return (dh_new_group(dhg.g, dhg.p));
}
Si noti che questo è tutto da una rapida occhiata al codice sorgente. Se ci sono altri problemi che possono verificarsi lungo la linea per motivi che non posso prevedere causati da un file di grandi dimensioni, il limite superiore potrebbe essere inferiore. Non vedo alcun motivo per pensare che sarebbe, però.