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

Add an extra HMAC constructor function.

This takes a plain ssh_hashalg, and constructs the most natural kind
of HMAC wrapper around it, taking its key length and output length
to be the hash's output length. In other words, it converts SHA-foo
into exactly the thing usually called HMAC-SHA-foo.

It does it by constructing a new ssh2_macalg vtable, and including it
in the same memory allocation as the actual hash object. That's the
first time in PuTTY I've done it this way.

Nothing yet uses this, but a new piece of code is about to.
This commit is contained in:
Simon Tatham 2024-04-01 08:45:21 +01:00
parent c96fb0f10a
commit dea3ddca05
2 changed files with 48 additions and 2 deletions

View File

@ -18,9 +18,10 @@ struct hmac_extra {
const char *suffix, *annotation;
};
static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher)
/* Most of hmac_new(). Takes the actual 'struct hmac' as a parameter,
* because sometimes it will have been allocated in a special way. */
static ssh2_mac *hmac_new_inner(struct hmac *ctx, const ssh2_macalg *alg)
{
struct hmac *ctx = snew(struct hmac);
const struct hmac_extra *extra = (const struct hmac_extra *)alg->extra;
ctx->h_outer = ssh_hash_new(extra->hashalg_base);
@ -64,6 +65,11 @@ static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher)
return &ctx->mac;
}
static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher)
{
return hmac_new_inner(snew(struct hmac), alg); /* cipher isn't needed */
}
static void hmac_free(ssh2_mac *mac)
{
struct hmac *ctx = container_of(mac, struct hmac, mac);
@ -277,3 +283,38 @@ const ssh2_macalg ssh_hmac_sha1_96_buggy = {
.keylen = 16,
.extra = &ssh_hmac_sha1_96_buggy_extra,
};
ssh2_mac *hmac_new_from_hash(const ssh_hashalg *hash)
{
/*
* Construct a custom ssh2_macalg, derived directly from the
* provided hash vtable. It's included in the same memory
* allocation as the struct hmac, so that it all gets freed
* together.
*/
struct alloc {
struct hmac hmac;
ssh2_macalg alg;
struct hmac_extra extra;
};
struct alloc *alloc = snew(struct alloc);
alloc->alg.new = hmac_new;
alloc->alg.free = hmac_free;
alloc->alg.setkey = hmac_key;
alloc->alg.start = hmac_start;
alloc->alg.genresult = hmac_genresult;
alloc->alg.next_message = nullmac_next_message;
alloc->alg.text_name = hmac_text_name;
alloc->alg.name = NULL;
alloc->alg.etm_name = NULL;
alloc->alg.len = hash->hlen;
alloc->alg.keylen = hash->hlen;
alloc->alg.extra = &alloc->extra;
alloc->extra.hashalg_base = hash;
alloc->extra.suffix = "";
alloc->extra.annotation = NULL;
return hmac_new_inner(&alloc->hmac, &alloc->alg);
}

5
ssh.h
View File

@ -762,6 +762,11 @@ void nullmac_next_message(ssh2_mac *m);
* string with a given key in the most obvious way. */
void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output);
/* Constructor that makes an HMAC object given just a MAC. This object
* will have empty 'name' and 'etm_name' fields, so it's not suitable
* for use in SSH. It's used as a subroutine in RFC 6979. */
ssh2_mac *hmac_new_from_hash(const ssh_hashalg *hash);
struct ssh_hash {
const ssh_hashalg *vt;
BinarySink_DELEGATE_IMPLEMENTATION;