Muy probablemente 4294967295.
En el archivo fuente dh.c
, el archivo de módulo se abre con fopen
, y se usa un bucle fgets
para extraer cada línea. La línea actual que se procesa se registra en una variable declarada como int linenum
. Esto significa que es un entero con signo de 32 bits, capaz de representar 2 valores posibles de 32 . Dado que está firmado, esto equivale a -2147483648 a 2147483647 (uno menos porque 0 sigue siendo un número y se considera positivo). Dado que comienza en 0 e incrementa, el valor máximo es, por lo tanto, 2 32 / 2 - 1. Se convertirá en negativo si supera este límite y se envuelve.
Hay alguna conversión entre firmado y sin firmar en el código fuente. int linenum
contiene el número de líneas, mientras que int bestcount
tiene el número de líneas adecuadas y se pasa a arc4random_uniform
, que genera un valor aleatorio entre 0 y bestcount
. El valor que acepta y el valor que devuelve no está firmado, pero se almacena en otro entero con signo, which
. Ese entero se usa para especificar qué línea aleatoria se va a usar. Si el número de líneas supera lo que puede contener un entero de 32 bits, la elección aleatoria del límite superior de la línea será más pequeña, quizás mucho más pequeña, que el número real de líneas.
Esta limitación no es un problema en la práctica. ¡La longitud máxima de una línea es 4096 bytes y 2 líneas 32 (no - 1 porque la primera línea comienza en 0) de 4096 bytes cada una da un tamaño máximo de archivo de 16 terabytes! Buena suerte esperando a openssl dhparam para generar terabytes de módulos.
Toda la función en el código fuente, a partir de 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));
}
Tenga en cuenta que todo esto se debe a un rápido vistazo al código fuente. Si hay otros problemas que pueden ocurrir en la línea por razones que no puedo predecir causadas por un archivo grande, el límite superior puede ser menor. Sin embargo, no veo ninguna razón para pensar que sería.