1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-12 08:43:53 -05:00

Centralised HMAC implementation.

This replaces all the separate HMAC-implementing wrappers in the
various source files implementing the underlying hashes.

The new HMAC code also correctly handles the case of a key longer than
the underlying hash's block length, by replacing it with its own hash.
This means I can reinstate the test vectors in RFC 6234 which exercise
that case, which I didn't add to cryptsuite before because they'd have
failed.

It also allows me to remove the ad-hoc code at the call site in
cproxy.c which turns out to have been doing the same thing - I think
that must have been the only call site where the question came up
(since MAC keys invented by the main SSH-2 BPP are always shorter than
that).
This commit is contained in:
Simon Tatham
2019-01-20 16:18:49 +00:00
parent d73f692eea
commit baff23cdd6
8 changed files with 251 additions and 361 deletions

114
sshmd5.c
View File

@ -273,117 +273,3 @@ static void md5_final(ssh_hash *hash, unsigned char *output)
const ssh_hashalg ssh_md5 = {
md5_new, md5_copy, md5_final, md5_free, 16, "MD5"
};
/* ----------------------------------------------------------------------
* The above is the MD5 algorithm itself. Now we implement the
* HMAC wrapper on it.
*
* Some of these functions are exported directly, because they are
* useful elsewhere (SOCKS5 CHAP authentication uses HMAC-MD5).
*/
struct hmacmd5_context {
struct MD5Context md5[3];
ssh2_mac mac;
};
struct hmacmd5_context *hmacmd5_make_context(void)
{
struct hmacmd5_context *ctx = snew(struct hmacmd5_context);
BinarySink_DELEGATE_INIT(&ctx->mac, &ctx->md5[2]);
return ctx;
}
static ssh2_mac *hmacmd5_ssh2_new(const ssh2_macalg *alg, ssh_cipher *cipher)
{
struct hmacmd5_context *ctx = hmacmd5_make_context();
ctx->mac.vt = alg;
return &ctx->mac;
}
void hmacmd5_free_context(struct hmacmd5_context *ctx)
{
smemclr(ctx, sizeof(*ctx));
sfree(ctx);
}
static void hmacmd5_ssh2_free(ssh2_mac *mac)
{
struct hmacmd5_context *ctx =
container_of(mac, struct hmacmd5_context, mac);
hmacmd5_free_context(ctx);
}
void hmacmd5_key(struct hmacmd5_context *ctx, void const *keyv, int len)
{
unsigned char foo[64];
unsigned char const *key = (unsigned char const *)keyv;
int i;
memset(foo, 0x36, 64);
for (i = 0; i < len && i < 64; i++)
foo[i] ^= key[i];
MD5Init(&ctx->md5[0]);
put_data(&ctx->md5[0], foo, 64);
memset(foo, 0x5C, 64);
for (i = 0; i < len && i < 64; i++)
foo[i] ^= key[i];
MD5Init(&ctx->md5[1]);
put_data(&ctx->md5[1], foo, 64);
smemclr(foo, 64); /* burn the evidence */
}
static void hmacmd5_ssh2_setkey(ssh2_mac *mac, ptrlen key)
{
struct hmacmd5_context *ctx =
container_of(mac, struct hmacmd5_context, mac);
hmacmd5_key(ctx, key.ptr, key.len);
}
static void hmacmd5_start(ssh2_mac *mac)
{
struct hmacmd5_context *ctx =
container_of(mac, struct hmacmd5_context, mac);
ctx->md5[2] = ctx->md5[0]; /* structure copy */
BinarySink_COPIED(&ctx->md5[2]);
}
static void hmacmd5_genresult(ssh2_mac *mac, unsigned char *hmac)
{
struct hmacmd5_context *ctx =
container_of(mac, struct hmacmd5_context, mac);
struct MD5Context s;
unsigned char intermediate[16];
s = ctx->md5[2]; /* structure copy */
BinarySink_COPIED(&s);
MD5Final(intermediate, &s);
s = ctx->md5[1]; /* structure copy */
BinarySink_COPIED(&s);
put_data(&s, intermediate, 16);
MD5Final(hmac, &s);
smemclr(intermediate, sizeof(intermediate));
}
void hmacmd5_do_hmac(struct hmacmd5_context *ctx,
const void *blk, int len, unsigned char *hmac)
{
ssh2_mac_start(&ctx->mac);
put_data(&ctx->mac, blk, len);
ssh2_mac_genresult(&ctx->mac, hmac);
}
static const char *hmacmd5_text_name(ssh2_mac *mac)
{
return "HMAC-MD5";
}
const ssh2_macalg ssh_hmac_md5 = {
hmacmd5_ssh2_new, hmacmd5_ssh2_free, hmacmd5_ssh2_setkey,
hmacmd5_start, hmacmd5_genresult, hmacmd5_text_name,
"hmac-md5", "hmac-md5-etm@openssh.com",
16, 16,
};