diff --git a/agent/agent.h b/agent/agent.h index cf50d9280..2b045f851 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -486,6 +486,7 @@ gpg_error_t agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey, char **passphrase_addr); /*-- protect.c --*/ +void set_s2k_calibration_time (unsigned int milliseconds); unsigned long get_calibrated_s2k_count (void); unsigned long get_standard_s2k_count (void); unsigned char get_standard_s2k_count_rfc4880 (void); diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 1fdc94d0f..ffd85d196 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -135,6 +135,7 @@ enum cmd_and_opt_values oDisableScdaemon, oDisableCheckOwnSocket, oS2KCount, + oS2KCalibration, oAutoExpandSecmem, oListenBacklog, @@ -253,6 +254,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oEnableExtendedKeyFormat, "enable-extended-key-format", "@"), ARGPARSE_s_u (oS2KCount, "s2k-count", "@"), + ARGPARSE_s_u (oS2KCalibration, "s2k-calibration", "@"), ARGPARSE_op_u (oAutoExpandSecmem, "auto-expand-secmem", "@"), @@ -834,6 +836,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) /* Note: When changing the next line, change also gpgconf_list. */ opt.ssh_fingerprint_digest = GCRY_MD_MD5; opt.s2k_count = 0; + set_s2k_calibration_time (0); /* Set to default. */ return 1; } @@ -929,6 +932,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.s2k_count = pargs->r.ret_ulong; break; + case oS2KCalibration: + set_s2k_calibration_time (pargs->r.ret_ulong); + break; + default: return 0; /* not handled */ } diff --git a/agent/protect.c b/agent/protect.c index 16ae715e1..134fbf2e6 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -71,6 +71,13 @@ static const struct { }; +/* The number of milliseconds we use in the S2K function and the + * calibrated count value. A count value of zero indicates that the + * calibration has not yet been done or needs to be done again. */ +static unsigned int s2k_calibration_time = AGENT_S2K_CALIBRATION; +static unsigned long s2k_calibrated_count; + + /* A helper object for time measurement. */ struct calibrate_time_s { @@ -175,11 +182,11 @@ calibrate_s2k_count (void) ms = calibrate_s2k_count_one (count); if (opt.verbose > 1) log_info ("S2K calibration: %lu -> %lums\n", count, ms); - if (ms > AGENT_S2K_CALIBRATION) + if (ms > s2k_calibration_time) break; } - count = (unsigned long)(((double)count / ms) * AGENT_S2K_CALIBRATION); + count = (unsigned long)(((double)count / ms) * s2k_calibration_time); count /= 1024; count *= 1024; if (count < 65536) @@ -195,18 +202,30 @@ calibrate_s2k_count (void) } +/* Set the calibration time. This may be called early at startup or + * at any time. Thus it should one set variables. */ +void +set_s2k_calibration_time (unsigned int milliseconds) +{ + if (!milliseconds) + milliseconds = AGENT_S2K_CALIBRATION; + else if (milliseconds > 60 * 1000) + milliseconds = 60 * 1000; /* Cap at 60 seconds. */ + s2k_calibration_time = milliseconds; + s2k_calibrated_count = 0; /* Force re-calibration. */ +} + + /* Return the calibrated S2K count. This is only public for the use * of the Assuan getinfo s2k_count_cal command. */ unsigned long get_calibrated_s2k_count (void) { - static unsigned long count; - - if (!count) - count = calibrate_s2k_count (); + if (!s2k_calibrated_count) + s2k_calibrated_count = calibrate_s2k_count (); /* Enforce a lower limit. */ - return count < 65536 ? 65536 : count; + return s2k_calibrated_count < 65536 ? 65536 : s2k_calibrated_count; } diff --git a/doc/gpg-agent.texi b/doc/gpg-agent.texi index bcce03329..3997d2046 100644 --- a/doc/gpg-agent.texi +++ b/doc/gpg-agent.texi @@ -669,12 +669,19 @@ For an heavy loaded gpg-agent with many concurrent connection this option avoids sign or decrypt errors due to out of secure memory error returns. +@item --s2k-calibration @var{milliseconds} +@opindex s2k-calibration +Change the default calibration time to @var{milliseconds}. The given +value is capped at 60 seconds; a value of 0 resets to the compiled-in +default. This option is re-read on a SIGHUP (or @code{gpgconf +--reload gpg-agent}) and the S2K count is then re-calibrated. + @item --s2k-count @var{n} @opindex s2k-count Specify the iteration count used to protect the passphrase. This option can be used to override the auto-calibration done by default. -The auto-calibration computes a count which requires 100ms to mangle -a given passphrase. +The auto-calibration computes a count which requires by default 100ms +to mangle a given passphrase. See also @option{--s2k-calibration}. To view the actually used iteration count and the milliseconds required for an S2K operation use: