mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-17 11:00:59 -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:
138
sshsha.c
138
sshsha.c
@ -284,144 +284,6 @@ const ssh_hashalg ssh_sha1 = {
|
||||
sha1_new, sha1_copy, sha1_final, sha1_free, 20, "SHA-1"
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* The above is the SHA-1 algorithm itself. Now we implement the
|
||||
* HMAC wrapper on it.
|
||||
*/
|
||||
|
||||
struct hmacsha1 {
|
||||
SHA_State sha[3];
|
||||
ssh2_mac mac;
|
||||
};
|
||||
|
||||
static ssh2_mac *hmacsha1_new(const ssh2_macalg *alg, ssh_cipher *cipher)
|
||||
{
|
||||
struct hmacsha1 *ctx = snew(struct hmacsha1);
|
||||
ctx->mac.vt = alg;
|
||||
BinarySink_DELEGATE_INIT(&ctx->mac, &ctx->sha[2]);
|
||||
return &ctx->mac;
|
||||
}
|
||||
|
||||
static void hmacsha1_free(ssh2_mac *mac)
|
||||
{
|
||||
struct hmacsha1 *ctx = container_of(mac, struct hmacsha1, mac);
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void sha1_key_internal(SHA_State *keys,
|
||||
const unsigned char *key, int len)
|
||||
{
|
||||
unsigned char foo[64];
|
||||
int i;
|
||||
|
||||
memset(foo, 0x36, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
SHA_Init(&keys[0]);
|
||||
put_data(&keys[0], foo, 64);
|
||||
|
||||
memset(foo, 0x5C, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
SHA_Init(&keys[1]);
|
||||
put_data(&keys[1], foo, 64);
|
||||
|
||||
smemclr(foo, 64); /* burn the evidence */
|
||||
}
|
||||
|
||||
static void hmacsha1_key(ssh2_mac *mac, ptrlen key)
|
||||
{
|
||||
struct hmacsha1 *ctx = container_of(mac, struct hmacsha1, mac);
|
||||
sha1_key_internal(ctx->sha, key.ptr, key.len);
|
||||
}
|
||||
|
||||
static void hmacsha1_start(ssh2_mac *mac)
|
||||
{
|
||||
struct hmacsha1 *ctx = container_of(mac, struct hmacsha1, mac);
|
||||
|
||||
ctx->sha[2] = ctx->sha[0]; /* structure copy */
|
||||
BinarySink_COPIED(&ctx->sha[2]);
|
||||
}
|
||||
|
||||
static void hmacsha1_genresult(ssh2_mac *mac, unsigned char *hmac)
|
||||
{
|
||||
struct hmacsha1 *ctx = container_of(mac, struct hmacsha1, mac);
|
||||
SHA_State s;
|
||||
unsigned char intermediate[20];
|
||||
|
||||
s = ctx->sha[2]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
SHA_Final(&s, intermediate);
|
||||
s = ctx->sha[1]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
put_data(&s, intermediate, 20);
|
||||
SHA_Final(&s, intermediate);
|
||||
memcpy(hmac, intermediate, ctx->mac.vt->len);
|
||||
smemclr(intermediate, sizeof(intermediate));
|
||||
}
|
||||
|
||||
void hmac_sha1_simple(const void *key, int keylen,
|
||||
const void *data, int datalen,
|
||||
unsigned char *output) {
|
||||
SHA_State states[2];
|
||||
unsigned char intermediate[20];
|
||||
|
||||
sha1_key_internal(states, key, keylen);
|
||||
put_data(&states[0], data, datalen);
|
||||
SHA_Final(&states[0], intermediate);
|
||||
|
||||
put_data(&states[1], intermediate, 20);
|
||||
SHA_Final(&states[1], output);
|
||||
}
|
||||
|
||||
struct hmacsha1_extra {
|
||||
const char *textname;
|
||||
};
|
||||
|
||||
static const char *hmacsha1_text_name(ssh2_mac *mac)
|
||||
{
|
||||
const struct hmacsha1_extra *extra =
|
||||
(const struct hmacsha1_extra *)mac->vt->extra;
|
||||
return extra->textname;
|
||||
}
|
||||
|
||||
const struct hmacsha1_extra ssh_hmac_sha1_extra = { "HMAC-SHA1" };
|
||||
const ssh2_macalg ssh_hmac_sha1 = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult, hmacsha1_text_name,
|
||||
"hmac-sha1", "hmac-sha1-etm@openssh.com",
|
||||
20, 20, &ssh_hmac_sha1_extra,
|
||||
};
|
||||
|
||||
const struct hmacsha1_extra ssh_hmac_sha1_96_extra = { "HMAC-SHA1-96" };
|
||||
const ssh2_macalg ssh_hmac_sha1_96 = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult, hmacsha1_text_name,
|
||||
"hmac-sha1-96", "hmac-sha1-96-etm@openssh.com",
|
||||
12, 20, &ssh_hmac_sha1_96_extra,
|
||||
};
|
||||
|
||||
const struct hmacsha1_extra ssh_hmac_sha1_buggy_extra = {
|
||||
"bug-compatible HMAC-SHA1",
|
||||
};
|
||||
const ssh2_macalg ssh_hmac_sha1_buggy = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult, hmacsha1_text_name,
|
||||
"hmac-sha1", NULL,
|
||||
20, 16, &ssh_hmac_sha1_buggy_extra,
|
||||
};
|
||||
|
||||
const struct hmacsha1_extra ssh_hmac_sha1_96_buggy_extra = {
|
||||
"bug-compatible HMAC-SHA1-96",
|
||||
};
|
||||
const ssh2_macalg ssh_hmac_sha1_96_buggy = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult, hmacsha1_text_name,
|
||||
"hmac-sha1-96", NULL,
|
||||
12, 16, &ssh_hmac_sha1_96_buggy_extra,
|
||||
};
|
||||
|
||||
#ifdef COMPILER_SUPPORTS_SHA_NI
|
||||
|
||||
#if defined _MSC_VER && defined _M_AMD64
|
||||
|
Reference in New Issue
Block a user