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

Adopt the new hash API functions where they're useful.

This commit switches as many ssh_hash_free / ssh_hash_new pairs as
possible to reuse the previous hash object via ssh_hash_reset. Also a
few other cleanups: use the wrapper function hash_simple() where
possible, and I've also introduced ssh_hash_digest_nondestructive()
and switched to that where possible as well.
This commit is contained in:
Simon Tatham 2019-12-15 09:57:30 +00:00
parent 3fd334b5ca
commit 1344d4d1cd
12 changed files with 57 additions and 47 deletions

View File

@ -516,9 +516,9 @@ static void openssh_pem_derivekey(
h = ssh_hash_new(&ssh_md5);
put_datapl(h, passphrase);
put_data(h, iv, 8);
ssh_hash_final(h, keybuf);
ssh_hash_digest(h, keybuf);
h = ssh_hash_new(&ssh_md5);
ssh_hash_reset(h);
put_data(h, keybuf, 16);
put_datapl(h, passphrase);
put_data(h, iv, 8);
@ -1932,7 +1932,7 @@ static void sshcom_derivekey(ptrlen passphrase, uint8_t *keybuf)
h = ssh_hash_new(&ssh_md5);
put_datapl(h, passphrase);
ssh_hash_final(ssh_hash_copy(h), keybuf);
ssh_hash_digest_nondestructive(h, keybuf);
put_data(h, keybuf, 16);
ssh_hash_final(h, keybuf + 16);
}

7
ssh.h
View File

@ -748,6 +748,13 @@ static inline ssh_hash *ssh_hash_copyfrom(ssh_hash *dest, ssh_hash *src)
static inline void ssh_hash_final(ssh_hash *h, unsigned char *out)
{ h->vt->digest(h, out); h->vt->free(h); }
/* ssh_hash_digest_nondestructive generates a finalised hash from the
* given object without changing its state, so you can continue
* appending data to get a hash of an extended string. */
static inline void ssh_hash_digest_nondestructive(ssh_hash *h,
unsigned char *out)
{ ssh_hash_final(ssh_hash_copy(h), out); }
/* Handy macros for defining all those text-name fields at once */
#define HASHALG_NAMES_BARE(base) \
base, NULL, base

View File

@ -275,25 +275,25 @@ static void ssh2_mkkey(
put_data(h, H, hlen);
put_byte(h, chr);
put_data(h, s->session_id, s->session_id_len);
ssh_hash_final(h, key);
ssh_hash_digest(h, key);
/* Subsequent blocks of hlen bytes. */
if (keylen_padded > hlen) {
int offset;
h = ssh_hash_new(s->kex_alg->hash);
ssh_hash_reset(h);
if (!(s->ppl.remote_bugs & BUG_SSH2_DERIVEKEY))
put_mp_ssh2(h, K);
put_data(h, H, hlen);
for (offset = hlen; offset < keylen_padded; offset += hlen) {
put_data(h, key + offset - hlen, hlen);
ssh_hash *h2 = ssh_hash_copy(h);
ssh_hash_final(h2, key + offset);
ssh_hash_digest_nondestructive(h, key + offset);
}
ssh_hash_free(h);
}
ssh_hash_free(h);
}
/*

View File

@ -399,12 +399,12 @@ mp_int *dss_gen_k(const char *id_string, mp_int *modulus,
h = ssh_hash_new(&ssh_sha512);
put_asciz(h, id_string);
put_mp_ssh2(h, private_key);
ssh_hash_final(h, digest512);
ssh_hash_digest(h, digest512);
/*
* Now hash that digest plus the message hash.
*/
h = ssh_hash_new(&ssh_sha512);
ssh_hash_reset(h);
put_data(h, digest512, sizeof(digest512));
put_data(h, digest, digest_len);
ssh_hash_final(h, digest512);

View File

@ -98,11 +98,7 @@ static void hmac_key(ssh2_mac *mac, ptrlen key)
*/
sb = strbuf_new_nm();
strbuf_append(sb, ctx->hashalg->hlen);
ssh_hash *htmp = ssh_hash_new(ctx->hashalg);
put_datapl(htmp, key);
ssh_hash_final(htmp, sb->u);
hash_simple(ctx->hashalg, key, sb->u);
kp = sb->u;
klen = sb->len;
} else {
@ -140,11 +136,10 @@ static void hmac_genresult(ssh2_mac *mac, unsigned char *output)
struct hmac *ctx = container_of(mac, struct hmac, mac);
ssh_hash *htmp;
/* Leave h_live in place, so that the SSH-2 BPP can continue
* regenerating test results from different-length prefixes of the
* packet */
htmp = ssh_hash_copy(ctx->h_live);
ssh_hash_final(htmp, ctx->digest);
/* Leave h_live and h_outer in place, so that the SSH-2 BPP can
* continue regenerating test results from different-length
* prefixes of the packet */
ssh_hash_digest_nondestructive(ctx->h_live, ctx->digest);
htmp = ssh_hash_copy(ctx->h_outer);
put_data(htmp, ctx->digest, ctx->hashalg->hlen);

View File

@ -273,9 +273,9 @@ void prng_add_entropy(prng *pr, unsigned source_id, ptrlen data)
prngdebug("prng entropy reseed #%"PRIu32"\n", reseed_index);
for (size_t i = 0; i < NCOLLECTORS; i++) {
prngdebug("emptying collector %zu\n", i);
ssh_hash_final(pi->collectors[i], pi->pending_output);
ssh_hash_digest(pi->collectors[i], pi->pending_output);
put_data(&pi->Prng, pi->pending_output, pi->hashalg->hlen);
pi->collectors[i] = ssh_hash_new(pi->hashalg);
ssh_hash_reset(pi->collectors[i]);
if (reseed_index & 1)
break;
reseed_index >>= 1;

View File

@ -372,9 +372,7 @@ bool rsa_ssh1_savekey(const Filename *filename, RSAKey *key,
if (passphrase) {
unsigned char keybuf[16];
ssh_hash *h = ssh_hash_new(&ssh_md5);
put_data(h, passphrase, strlen(passphrase));
ssh_hash_final(h, keybuf);
hash_simple(&ssh_md5, ptrlen_from_asciz(passphrase), keybuf);
des3_encrypt_pubkey(keybuf, buf->u + estart, buf->len - estart);
smemclr(keybuf, sizeof(keybuf)); /* burn the evidence */
}
@ -591,8 +589,8 @@ static void ssh2_ppk_derivekey(ptrlen passphrase, uint8_t *key)
h = ssh_hash_new(&ssh_sha1);
put_uint32(h, 0);
put_datapl(h, passphrase);
ssh_hash_final(h, key + 0);
h = ssh_hash_new(&ssh_sha1);
ssh_hash_digest(h, key + 0);
ssh_hash_reset(h);
put_uint32(h, 1);
put_datapl(h, passphrase);
ssh_hash_final(h, key + 20);

View File

@ -832,16 +832,17 @@ static void oaep_mask(const ssh_hashalg *h, void *seed, int seedlen,
unsigned char *data = (unsigned char *)vdata;
unsigned count = 0;
ssh_hash *s = ssh_hash_new(h);
while (datalen > 0) {
int i, max = (datalen > h->hlen ? h->hlen : datalen);
ssh_hash *s;
unsigned char hash[MAX_HASH_LEN];
ssh_hash_reset(s);
assert(h->hlen <= MAX_HASH_LEN);
s = ssh_hash_new(h);
put_data(s, seed, seedlen);
put_uint32(s, count);
ssh_hash_final(s, hash);
ssh_hash_digest(s, hash);
count++;
for (i = 0; i < max; i++)
@ -850,6 +851,8 @@ static void oaep_mask(const ssh_hashalg *h, void *seed, int seedlen,
data += max;
datalen -= max;
}
ssh_hash_free(s);
}
strbuf *ssh_rsakex_encrypt(RSAKey *rsa, const ssh_hashalg *h, ptrlen in)
@ -907,10 +910,7 @@ strbuf *ssh_rsakex_encrypt(RSAKey *rsa, const ssh_hashalg *h, ptrlen in)
random_read(out + 1, HLEN);
/* At position 1+HLEN, the data block DB, consisting of: */
/* The hash of the label (we only support an empty label here) */
{
ssh_hash *s = ssh_hash_new(h);
ssh_hash_final(s, out + HLEN + 1);
}
hash_simple(h, PTRLEN_LITERAL(""), out + HLEN + 1);
/* A bunch of zero octets */
memset(out + 2*HLEN + 1, 0, outlen - (2*HLEN + 1));
/* A single 1 octet, followed by the input message data. */
@ -953,7 +953,6 @@ mp_int *ssh_rsakex_decrypt(
int outlen, i;
unsigned char *out;
unsigned char labelhash[64];
ssh_hash *hash;
BinarySource src[1];
const int HLEN = h->hlen;
@ -987,8 +986,7 @@ mp_int *ssh_rsakex_decrypt(
}
/* Check the label hash at position 1+HLEN */
assert(HLEN <= lenof(labelhash));
hash = ssh_hash_new(h);
ssh_hash_final(hash, labelhash);
hash_simple(h, PTRLEN_LITERAL(""), labelhash);
if (memcmp(out + HLEN + 1, labelhash, HLEN)) {
sfree(out);
return NULL;

View File

@ -623,6 +623,16 @@ mp_int *monty_modulus_wrapper(MontyContext *mc)
}
#define monty_modulus monty_modulus_wrapper
strbuf *ssh_hash_digest_wrapper(ssh_hash *h)
{
strbuf *sb = strbuf_new();
void *p = strbuf_append(sb, ssh_hash_alg(h)->hlen);
ssh_hash_digest(h, p);
return sb;
}
#undef ssh_hash_digest
#define ssh_hash_digest ssh_hash_digest_wrapper
strbuf *ssh_hash_final_wrapper(ssh_hash *h)
{
strbuf *sb = strbuf_new();

View File

@ -122,7 +122,9 @@ FUNC3(void, ecc_edwards_get_affine, val_epoint, out_val_mpint, out_val_mpint)
* API by the hash object also functioning as a BinarySink.
*/
FUNC1(opt_val_hash, ssh_hash_new, hashalg)
FUNC1(void, ssh_hash_reset, val_hash)
FUNC1(val_hash, ssh_hash_copy, val_hash)
FUNC1(val_string, ssh_hash_digest, val_hash)
FUNC1(val_string, ssh_hash_final, consumed_val_hash)
FUNC2(void, ssh_hash_update, val_hash, val_string_ptrlen)

View File

@ -104,6 +104,7 @@ static uint64_t random_counter = 0;
static const char *random_seedstr = NULL;
static uint8_t random_buf[MAX_HASH_LEN];
static size_t random_buf_limit = 0;
static ssh_hash *random_hash;
static void random_seed(const char *seedstr)
{
@ -118,12 +119,12 @@ void random_read(void *vbuf, size_t size)
uint8_t *buf = (uint8_t *)vbuf;
while (size-- > 0) {
if (random_buf_limit == 0) {
ssh_hash *h = ssh_hash_new(&ssh_sha256);
put_asciz(h, random_seedstr);
put_uint64(h, random_counter);
ssh_hash_reset(random_hash);
put_asciz(random_hash, random_seedstr);
put_uint64(random_hash, random_counter);
random_counter++;
random_buf_limit = ssh_hash_alg(h)->hlen;
ssh_hash_final(h, random_buf);
random_buf_limit = ssh_hash_alg(random_hash)->hlen;
ssh_hash_digest(random_hash, random_buf);
}
*buf++ = random_buf[random_buf_limit--];
}
@ -1395,6 +1396,7 @@ int main(int argc, char **argv)
bool test_names_given = false;
memset(tests_to_run, 1, sizeof(tests_to_run));
random_hash = ssh_hash_new(&ssh_sha256);
while (--argc > 0) {
char *p = *++argv;
@ -1555,6 +1557,8 @@ int main(int argc, char **argv)
}
}
ssh_hash_free(random_hash);
if (npass == nrun) {
printf("All tests passed\n");
return 0;

View File

@ -86,11 +86,7 @@ static char *obfuscate_name(const char *realname)
* We don't want to give away the length of the hostname either,
* so having got it back out of CryptProtectMemory we now hash it.
*/
{
ssh_hash *h = ssh_hash_new(&ssh_sha256);
put_string(h, cryptdata, cryptlen);
ssh_hash_final(h, digest);
}
hash_simple(&ssh_sha256, make_ptrlen(cryptdata, cryptlen), digest);
sfree(cryptdata);