How to configure Argon2d for commodity hardware? You may already have heard it: KeePass v2.35 has support for a new database format (KDBX4) which allows for the use of Argon2 (more precisely: Argon2d) as the password-based key derivation function (PBKDF).

However Argon2 has three independent parameters, called iteration count, memory usage and parallelism in the GUI. Furthermore it offers to measure how many iterations it can squeeze into one second. But if you "just" hit the button for this it's gonna use 1MB and a parellelism value of 2.

So my question: Is "just" adjusting the iteration count the best strategy to get the most security out of Argon2 or is there a better approach?



OK, so here's the more concrete situation for which the best strategy is searched: An x86 architecture PC, with basically unlimited amounts of RAM (let's just take 4GB+ as an approximation of unlimited), with a very limited number of parallel cores and with a very "tight" time budget of up to 1 second.
Now for the definition of the term "best": Given the above scenario the best strategy for parameter-selection is the one that allows for the biggest hurden on an GPU- / FPGA- / ASIC- based (in terms of the time-area-product) attacker while fitting the constraints.
As this is also intended as a ressource for persons without much of a crypto background, please keep possible strategies as concrete as possible.
The first thing to note is that KeePass uses Argon2d which is the Argon2-variant with data-dependent memory access.

Now it's best to (roughly) follow the guidelines lined out in the Argon2 specification (RFC draft):


Figure out the maximum number h of threads that can be initiated by each call to Argon2._ This means you should set the parallelism value to match your physical core count, ie 2 if you have a dual-core, 4 if you have a quad-core, ... You should double this value if you have (true) hyper-threading enabled on your CPU.
Optional: If you want to use the key-derivation on a lower power device (such as your phone), you need to figure out first how much RAM it has available during average use. This will be your upper limit for memory usage.
Optional: If you have less than 8GB of RAM on your machine, figure out how much is available during average use. The minimal value of this and the previous point will be the upper bound for memory.
Pick an iteration count between 1 and maybe 5. The higher you pick the harder it is for an attacker to reduce the memory required. Analysis suggests that low, single digit values are good, but going slightly higher should increase the penalty when trying to reduce memory usage. But do not higher this value indefinitely because while it would increase the penalties for reducing memory for an attacker, it could very well make the difference between you using 25MB and 500MB of memory and 500MB with "medium" penalties for reduction is likely going to be much worse for an attacker than 25MB with "high" penalties for reduction.
Figure out the actual memory usage parameter. To do this you pick a rather low value like 100MB or a tenth of your maximal budget and test how long it takes. If it takes not long enough increase the memory usage. The used time will roughly scale linear with the memory usage, that is, if you double the memory usage, you will get a doubled time. You want to tweak this time value to your liking, but about 1 second is recommended for disk-encryption or password databases.
If you hit the maximal memory budget, don't go over it (thinks will end badly), but rather increase the iteration count now. Also note here that the used time will scale linear with the iteration count, that is, double the iteration count and it will take about twice as long.


Overall your parameters should take maybe one second for the computation on your intended usage machine where you have to unlock the database often. 

So…

TL;DR:

Set the parallelism to your thread count (double the core count if you have hyperthreading), set the iteration count in the range 1-5 and set the memory usage as high as you can while staying within your time and memory budget.



thanks to axapaxa for pointing out that the thread count should be used.
thanks to Luis Casillas for pointing me to the RFC draft and making me improve this answer.