From 23159902a3ae593f9022578201125600a8da8de1 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 20 Feb 2013 23:30:55 +0000 Subject: [PATCH] Add support for HMAC-SHA-256 as an SSH-2 MAC algorithm ("hmac-sha2-256") as specified in RFC 6668. This is not so much because I think it's necessary, but because scrypt uses HMAC-SHA-256 and once we've got it we may as well use it. Code very closely derived from the HMAC-SHA-1 code. Tested against OpenSSH 5.9p1 Debian-5ubuntu1. git-svn-id: svn://svn.tartarus.org/sgt/putty@9759 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 2 +- ssh.h | 1 + sshsh256.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/ssh.c b/ssh.c index 66c84d16..6ee5528c 100644 --- a/ssh.c +++ b/ssh.c @@ -525,7 +525,7 @@ static void ssh_channel_destroy(struct ssh_channel *c); const static struct ssh_signkey *hostkey_algs[] = { &ssh_rsa, &ssh_dss }; const static struct ssh_mac *macs[] = { - &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5 + &ssh_hmac_sha256, &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5 }; const static struct ssh_mac *buggymacs[] = { &ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5 diff --git a/ssh.h b/ssh.h index c604554b..41ad305a 100644 --- a/ssh.h +++ b/ssh.h @@ -297,6 +297,7 @@ extern const struct ssh_mac ssh_hmac_sha1; extern const struct ssh_mac ssh_hmac_sha1_buggy; extern const struct ssh_mac ssh_hmac_sha1_96; extern const struct ssh_mac ssh_hmac_sha1_96_buggy; +extern const struct ssh_mac ssh_hmac_sha256; void *aes_make_context(void); void aes_free_context(void *handle); diff --git a/sshsh256.c b/sshsh256.c index ce6979ea..60c5217f 100644 --- a/sshsh256.c +++ b/sshsh256.c @@ -218,6 +218,116 @@ const struct ssh_hash ssh_sha256 = { sha256_init, sha256_bytes, sha256_final, 32, "SHA-256" }; +/* ---------------------------------------------------------------------- + * The above is the SHA-256 algorithm itself. Now we implement the + * HMAC wrapper on it. + */ + +static void *sha256_make_context(void) +{ + return snewn(3, SHA256_State); +} + +static void sha256_free_context(void *handle) +{ + sfree(handle); +} + +static void sha256_key_internal(void *handle, unsigned char *key, int len) +{ + SHA256_State *keys = (SHA256_State *)handle; + unsigned char foo[64]; + int i; + + memset(foo, 0x36, 64); + for (i = 0; i < len && i < 64; i++) + foo[i] ^= key[i]; + SHA256_Init(&keys[0]); + SHA256_Bytes(&keys[0], foo, 64); + + memset(foo, 0x5C, 64); + for (i = 0; i < len && i < 64; i++) + foo[i] ^= key[i]; + SHA256_Init(&keys[1]); + SHA256_Bytes(&keys[1], foo, 64); + + smemclr(foo, 64); /* burn the evidence */ +} + +static void sha256_key(void *handle, unsigned char *key) +{ + sha256_key_internal(handle, key, 32); +} + +static void hmacsha256_start(void *handle) +{ + SHA256_State *keys = (SHA256_State *)handle; + + keys[2] = keys[0]; /* structure copy */ +} + +static void hmacsha256_bytes(void *handle, unsigned char const *blk, int len) +{ + SHA256_State *keys = (SHA256_State *)handle; + SHA256_Bytes(&keys[2], (void *)blk, len); +} + +static void hmacsha256_genresult(void *handle, unsigned char *hmac) +{ + SHA256_State *keys = (SHA256_State *)handle; + SHA256_State s; + unsigned char intermediate[32]; + + s = keys[2]; /* structure copy */ + SHA256_Final(&s, intermediate); + s = keys[1]; /* structure copy */ + SHA256_Bytes(&s, intermediate, 32); + SHA256_Final(&s, hmac); +} + +static void sha256_do_hmac(void *handle, unsigned char *blk, int len, + unsigned long seq, unsigned char *hmac) +{ + unsigned char seqbuf[4]; + + PUT_32BIT_MSB_FIRST(seqbuf, seq); + hmacsha256_start(handle); + hmacsha256_bytes(handle, seqbuf, 4); + hmacsha256_bytes(handle, blk, len); + hmacsha256_genresult(handle, hmac); +} + +static void sha256_generate(void *handle, unsigned char *blk, int len, + unsigned long seq) +{ + sha256_do_hmac(handle, blk, len, seq, blk + len); +} + +static int hmacsha256_verresult(void *handle, unsigned char const *hmac) +{ + unsigned char correct[32]; + hmacsha256_genresult(handle, correct); + return !memcmp(correct, hmac, 32); +} + +static int sha256_verify(void *handle, unsigned char *blk, int len, + unsigned long seq) +{ + unsigned char correct[32]; + sha256_do_hmac(handle, blk, len, seq, correct); + return !memcmp(correct, blk + len, 32); +} + +const struct ssh_mac ssh_hmac_sha256 = { + sha256_make_context, sha256_free_context, sha256_key, + sha256_generate, sha256_verify, + hmacsha256_start, hmacsha256_bytes, + hmacsha256_genresult, hmacsha256_verresult, + "hmac-sha2-256", + 32, + "HMAC-SHA-256" +}; + #ifdef TEST #include -- 2.11.0