1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

[PM-3565] Enforce higher minimum KDF (#3304)

Extract KDF logic into a new Range class. Increase minimum iterations for PBKDF.
This commit is contained in:
Oscar Hinton
2023-12-05 17:21:46 +01:00
committed by GitHub
parent 26e6093c14
commit eedc96263a
10 changed files with 132 additions and 34 deletions

View File

@ -31,6 +31,45 @@ public static class Constants
public const string IdentityProvider = "bitwarden";
}
public static class AuthConstants
{
public static readonly RangeConstant PBKDF2_ITERATIONS = new(600_000, 2_000_000, 600_000);
public static readonly RangeConstant ARGON2_ITERATIONS = new(2, 10, 3);
public static readonly RangeConstant ARGON2_MEMORY = new(15, 1024, 64);
public static readonly RangeConstant ARGON2_PARALLELISM = new(1, 16, 4);
}
public class RangeConstant
{
public int Default { get; }
public int Min { get; }
public int Max { get; }
public RangeConstant(int min, int max, int defaultValue)
{
Default = defaultValue;
Min = min;
Max = max;
if (Min > Max)
{
throw new ArgumentOutOfRangeException($"{Min} is larger than {Max}.");
}
if (!InsideRange(defaultValue))
{
throw new ArgumentOutOfRangeException($"{Default} is outside allowed range of {Min}-{Max}.");
}
}
public bool InsideRange(int number)
{
return Min <= number && number <= Max;
}
}
public static class TokenPurposes
{
public const string LinkSso = "LinkSso";

View File

@ -10,23 +10,23 @@ public static class KdfSettingsValidator
switch (kdfType)
{
case KdfType.PBKDF2_SHA256:
if (kdfIterations < 5000 || kdfIterations > 2_000_000)
if (!AuthConstants.PBKDF2_ITERATIONS.InsideRange(kdfIterations))
{
yield return new ValidationResult("KDF iterations must be between 5000 and 2000000.");
yield return new ValidationResult($"KDF iterations must be between {AuthConstants.PBKDF2_ITERATIONS.Min} and {AuthConstants.PBKDF2_ITERATIONS.Max}.");
}
break;
case KdfType.Argon2id:
if (kdfIterations <= 0)
if (!AuthConstants.ARGON2_ITERATIONS.InsideRange(kdfIterations))
{
yield return new ValidationResult("Argon2 iterations must be greater than 0.");
yield return new ValidationResult($"Argon2 iterations must be between {AuthConstants.ARGON2_ITERATIONS.Min} and {AuthConstants.ARGON2_ITERATIONS.Max}.");
}
else if (!kdfMemory.HasValue || kdfMemory.Value < 15 || kdfMemory.Value > 1024)
else if (!kdfMemory.HasValue || !AuthConstants.ARGON2_MEMORY.InsideRange(kdfMemory.Value))
{
yield return new ValidationResult("Argon2 memory must be between 15mb and 1024mb.");
yield return new ValidationResult($"Argon2 memory must be between {AuthConstants.ARGON2_MEMORY.Min}mb and {AuthConstants.ARGON2_MEMORY.Max}mb.");
}
else if (!kdfParallelism.HasValue || kdfParallelism.Value < 1 || kdfParallelism.Value > 16)
else if (!kdfParallelism.HasValue || !AuthConstants.ARGON2_PARALLELISM.InsideRange(kdfParallelism.Value))
{
yield return new ValidationResult("Argon2 parallelism must be between 1 and 16.");
yield return new ValidationResult($"Argon2 parallelism must be between {AuthConstants.ARGON2_PARALLELISM.Min} and {AuthConstants.ARGON2_PARALLELISM.Max}.");
}
break;