1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-05-28 23:34:49 -05:00

sshhmac.c: stop freeing/remaking persistent ssh_hash objects.

The h_outer, h_inner and h_live hash objects in the HMAC
implementation are now no longer freed and reallocated all the time.
Instead, they're reinitialised in place using the new ssh_hash_reset
and ssh_hash_copyfrom API functions.

This is partly a performance optimisation (malloc and free take time),
but also, it should fix an intermittent failure in the side-channel
test system 'testsc', which seems to be happening because of those
free/malloc pairs not happening the same way in successive runs. (In
other words, this didn't reflect a genuine side-channel leakage in the
actual crypto, only a failure of experimental control in the test.)
This commit is contained in:
Simon Tatham 2019-12-15 11:58:33 +00:00
parent 156762fc02
commit 3fd334b5ca
2 changed files with 3 additions and 31 deletions

View File

@ -8,7 +8,6 @@
struct hmac {
const ssh_hashalg *hashalg;
ssh_hash *h_outer, *h_inner, *h_live;
bool keyed;
uint8_t *digest;
strbuf *text_name;
ssh2_mac mac;
@ -30,7 +29,6 @@ static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher)
ctx->hashalg = ssh_hash_alg(ctx->h_outer);
ctx->h_inner = ssh_hash_new(ctx->hashalg);
ctx->h_live = ssh_hash_new(ctx->hashalg);
ctx->keyed = false;
/*
* HMAC is not well defined as a wrapper on an absolutely general
@ -92,18 +90,6 @@ static void hmac_key(ssh2_mac *mac, ptrlen key)
size_t klen;
strbuf *sb = NULL;
if (ctx->keyed) {
/*
* If we've already been keyed, throw away the existing hash
* objects and make a fresh pair to put the new key in.
*/
ssh_hash_free(ctx->h_outer);
ssh_hash_free(ctx->h_inner);
ctx->h_outer = ssh_hash_new(ctx->hashalg);
ctx->h_inner = ssh_hash_new(ctx->hashalg);
}
ctx->keyed = true;
if (key.len > ctx->hashalg->blocklen) {
/*
* RFC 2104 section 2: if the key exceeds the block length of
@ -127,18 +113,13 @@ static void hmac_key(ssh2_mac *mac, ptrlen key)
klen = key.len;
}
if (ctx->h_outer)
ssh_hash_free(ctx->h_outer);
if (ctx->h_inner)
ssh_hash_free(ctx->h_inner);
ctx->h_outer = ssh_hash_new(ctx->hashalg);
ssh_hash_reset(ctx->h_outer);
for (size_t i = 0; i < klen; i++)
put_byte(ctx->h_outer, PAD_OUTER ^ kp[i]);
for (size_t i = klen; i < ctx->hashalg->blocklen; i++)
put_byte(ctx->h_outer, PAD_OUTER);
ctx->h_inner = ssh_hash_new(ctx->hashalg);
ssh_hash_reset(ctx->h_inner);
for (size_t i = 0; i < klen; i++)
put_byte(ctx->h_inner, PAD_INNER ^ kp[i]);
for (size_t i = klen; i < ctx->hashalg->blocklen; i++)
@ -151,10 +132,7 @@ static void hmac_key(ssh2_mac *mac, ptrlen key)
static void hmac_start(ssh2_mac *mac)
{
struct hmac *ctx = container_of(mac, struct hmac, mac);
ssh_hash_free(ctx->h_live);
ctx->h_live = ssh_hash_copy(ctx->h_inner);
BinarySink_DELEGATE_INIT(&ctx->mac, ctx->h_live);
ssh_hash_copyfrom(ctx->h_live, ctx->h_inner);
}
static void hmac_genresult(ssh2_mac *mac, unsigned char *output)

View File

@ -1320,12 +1320,6 @@ static void test_mac(const ssh2_macalg *malg)
size_t maclen = malg->len;
uint8_t *data = snewn(datalen + maclen, uint8_t);
/* Preliminarily key the MAC, to avoid the divergence of control
* flow in which hmac_key() avoids some free()s the first time
* through */
random_read(mkey, malg->keylen);
ssh2_mac_setkey(m, make_ptrlen(mkey, malg->keylen));
for (size_t i = 0; i < looplimit(16); i++) {
random_read(mkey, malg->keylen);
random_read(data, datalen);