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:
parent
156762fc02
commit
3fd334b5ca
28
sshhmac.c
28
sshhmac.c
@ -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)
|
||||
|
6
testsc.c
6
testsc.c
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user