1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Use a proper PRNG for GTK askpass.

Coverity complained that it was wrong to use rand() in a security
context, and although in this case it's _very_ marginal, I can't
actually disagree that the choice of which light to light up to avoid
giving information about passphrase length is a security context.

So, no more rand(); instead we instantiate a shiny Fortuna PRNG
instance, seed it in more or less the usual way, and use that as an
overkill-level method of choosing which light to light up next.

(Acknowledging that this is a slightly unusual application and less
critical than most, I don't actually put the passphrase characters
themselves into the PRNG, and I don't use a random-seed file.)
This commit is contained in:
Simon Tatham 2019-05-05 20:22:36 +01:00
parent 4fb20b15f3
commit 03aeabfbea
3 changed files with 36 additions and 7 deletions

2
Recipe
View File

@ -376,7 +376,7 @@ pageant : [X] uxpgnt uxagentc aqsync pageant sshrsa sshpubk sshdes ARITH
+ sshmd5 version tree234 misc sshaes sshsha sshdss sshsh256 sshsh512
+ sshecc CONF uxsignal nocproxy nogss be_none x11fwd ux_x11 uxcons
+ gtkask gtkmisc nullplug logging UXMISC uxagentsock utils memory
+ sshauxcrypt sshhmac
+ sshauxcrypt sshhmac sshprng uxnoise
ptermapp : [XT] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore
+ uxsignal CHARSET uxpterm version time xpmpterm xpmptcfg

View File

@ -19,6 +19,8 @@
#include "gtkcompat.h"
#include "gtkmisc.h"
#include "putty.h"
#include "ssh.h"
#include "misc.h"
#define N_DRAWING_AREAS 3
@ -55,12 +57,39 @@ struct askpass_ctx {
int nattempts;
};
static prng *keypress_prng = NULL;
static void feed_keypress_prng(void *data, int size)
{
put_data(keypress_prng, data, size);
}
void random_add_noise(NoiseSourceId source, const void *noise, int length)
{
if (keypress_prng)
prng_add_entropy(keypress_prng, source, make_ptrlen(noise, length));
}
static void setup_keypress_prng(void)
{
keypress_prng = prng_new(&ssh_sha256);
prng_seed_begin(keypress_prng);
noise_get_heavy(feed_keypress_prng);
prng_seed_finish(keypress_prng);
}
static void cleanup_keypress_prng(void)
{
prng_free(keypress_prng);
}
static int choose_new_area(int prev_area)
{
uint8_t data[8];
prng_read(keypress_prng, data, 8);
uint64_t randval = GET_64BIT_MSB_FIRST(data);
int reduced = randval % (N_DRAWING_AREAS - 1);
return (prev_area + 1 + reduced) % N_DRAWING_AREAS;
}
static void visually_acknowledge_keypress(struct askpass_ctx *ctx)
{
int new_active;
new_active = rand() % (N_DRAWING_AREAS - 1);
if (new_active >= ctx->active_area)
new_active++;
int new_active = choose_new_area(ctx->active_area);
ctx->drawingareas[ctx->active_area].state = NOT_CURRENT;
gtk_widget_queue_draw(ctx->drawingareas[ctx->active_area].area);
ctx->drawingareas[new_active].state = CURRENT;
@ -546,7 +575,9 @@ char *gtk_askpass_main(const char *display, const char *wintitle,
*success = false;
return dupprintf("%s", err);
}
setup_keypress_prng();
gtk_main();
cleanup_keypress_prng();
gtk_askpass_cleanup(ctx);
if (ctx->passphrase) {
@ -582,7 +613,6 @@ int main(int argc, char **argv)
success = false;
ret = dupprintf("usage: %s <prompt text>", argv[0]);
} else {
srand(time(NULL));
ret = gtk_askpass_main(NULL, "Enter passphrase", argv[1], &success);
}

View File

@ -52,7 +52,6 @@ void uxsel_input_remove(uxsel_id *id) { }
*/
void random_save_seed(void) {}
void random_destroy_seed(void) {}
void noise_ultralight(NoiseSourceId id, unsigned long data) {}
char *platform_default_s(const char *name) { return NULL; }
bool platform_default_b(const char *name, bool def) { return def; }
int platform_default_i(const char *name, int def) { return def; }