mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-06-01 09:20:28 -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 {
|
struct hmac {
|
||||||
const ssh_hashalg *hashalg;
|
const ssh_hashalg *hashalg;
|
||||||
ssh_hash *h_outer, *h_inner, *h_live;
|
ssh_hash *h_outer, *h_inner, *h_live;
|
||||||
bool keyed;
|
|
||||||
uint8_t *digest;
|
uint8_t *digest;
|
||||||
strbuf *text_name;
|
strbuf *text_name;
|
||||||
ssh2_mac mac;
|
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->hashalg = ssh_hash_alg(ctx->h_outer);
|
||||||
ctx->h_inner = ssh_hash_new(ctx->hashalg);
|
ctx->h_inner = ssh_hash_new(ctx->hashalg);
|
||||||
ctx->h_live = 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
|
* 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;
|
size_t klen;
|
||||||
strbuf *sb = NULL;
|
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) {
|
if (key.len > ctx->hashalg->blocklen) {
|
||||||
/*
|
/*
|
||||||
* RFC 2104 section 2: if the key exceeds the block length of
|
* 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;
|
klen = key.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->h_outer)
|
ssh_hash_reset(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);
|
|
||||||
for (size_t i = 0; i < klen; i++)
|
for (size_t i = 0; i < klen; i++)
|
||||||
put_byte(ctx->h_outer, PAD_OUTER ^ kp[i]);
|
put_byte(ctx->h_outer, PAD_OUTER ^ kp[i]);
|
||||||
for (size_t i = klen; i < ctx->hashalg->blocklen; i++)
|
for (size_t i = klen; i < ctx->hashalg->blocklen; i++)
|
||||||
put_byte(ctx->h_outer, PAD_OUTER);
|
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++)
|
for (size_t i = 0; i < klen; i++)
|
||||||
put_byte(ctx->h_inner, PAD_INNER ^ kp[i]);
|
put_byte(ctx->h_inner, PAD_INNER ^ kp[i]);
|
||||||
for (size_t i = klen; i < ctx->hashalg->blocklen; 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)
|
static void hmac_start(ssh2_mac *mac)
|
||||||
{
|
{
|
||||||
struct hmac *ctx = container_of(mac, struct hmac, mac);
|
struct hmac *ctx = container_of(mac, struct hmac, mac);
|
||||||
|
ssh_hash_copyfrom(ctx->h_live, ctx->h_inner);
|
||||||
ssh_hash_free(ctx->h_live);
|
|
||||||
ctx->h_live = ssh_hash_copy(ctx->h_inner);
|
|
||||||
BinarySink_DELEGATE_INIT(&ctx->mac, ctx->h_live);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hmac_genresult(ssh2_mac *mac, unsigned char *output)
|
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;
|
size_t maclen = malg->len;
|
||||||
uint8_t *data = snewn(datalen + maclen, uint8_t);
|
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++) {
|
for (size_t i = 0; i < looplimit(16); i++) {
|
||||||
random_read(mkey, malg->keylen);
|
random_read(mkey, malg->keylen);
|
||||||
random_read(data, datalen);
|
random_read(data, datalen);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user