mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-13 00:57:33 -05:00
Mitigation for VU#958563: When using a CBC-mode server-to-client cipher
under SSH-2, don't risk looking at the length field of an incoming packet until we've successfully MAC'ed the packet. This requires a change to the MAC mechanics so that we can calculate MACs incrementally, and output a MAC for the packet so far while still being able to add more data to the packet later. [originally from svn r8334]
This commit is contained in:
70
sshsha.c
70
sshsha.c
@ -227,7 +227,7 @@ const struct ssh_hash ssh_sha1 = {
|
||||
|
||||
static void *sha1_make_context(void)
|
||||
{
|
||||
return snewn(2, SHA_State);
|
||||
return snewn(3, SHA_State);
|
||||
}
|
||||
|
||||
static void sha1_free_context(void *handle)
|
||||
@ -266,33 +266,61 @@ static void sha1_key_buggy(void *handle, unsigned char *key)
|
||||
sha1_key_internal(handle, key, 16);
|
||||
}
|
||||
|
||||
static void sha1_do_hmac(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
static void hmacsha1_start(void *handle)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
|
||||
keys[2] = keys[0]; /* structure copy */
|
||||
}
|
||||
|
||||
static void hmacsha1_bytes(void *handle, unsigned char const *blk, int len)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
SHA_Bytes(&keys[2], (void *)blk, len);
|
||||
}
|
||||
|
||||
static void hmacsha1_genresult(void *handle, unsigned char *hmac)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
SHA_State s;
|
||||
unsigned char intermediate[20];
|
||||
|
||||
intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF);
|
||||
intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF);
|
||||
intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF);
|
||||
intermediate[3] = (unsigned char) ((seq) & 0xFF);
|
||||
|
||||
s = keys[0]; /* structure copy */
|
||||
SHA_Bytes(&s, intermediate, 4);
|
||||
SHA_Bytes(&s, blk, len);
|
||||
s = keys[2]; /* structure copy */
|
||||
SHA_Final(&s, intermediate);
|
||||
s = keys[1]; /* structure copy */
|
||||
SHA_Bytes(&s, intermediate, 20);
|
||||
SHA_Final(&s, hmac);
|
||||
}
|
||||
|
||||
static void sha1_do_hmac(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
{
|
||||
unsigned char seqbuf[4];
|
||||
|
||||
seqbuf[0] = (unsigned char) ((seq >> 24) & 0xFF);
|
||||
seqbuf[1] = (unsigned char) ((seq >> 16) & 0xFF);
|
||||
seqbuf[2] = (unsigned char) ((seq >> 8) & 0xFF);
|
||||
seqbuf[3] = (unsigned char) ((seq) & 0xFF);
|
||||
|
||||
hmacsha1_start(handle);
|
||||
hmacsha1_bytes(handle, seqbuf, 4);
|
||||
hmacsha1_bytes(handle, blk, len);
|
||||
hmacsha1_genresult(handle, hmac);
|
||||
}
|
||||
|
||||
static void sha1_generate(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
sha1_do_hmac(handle, blk, len, seq, blk + len);
|
||||
}
|
||||
|
||||
static int hmacsha1_verresult(void *handle, unsigned char const *hmac)
|
||||
{
|
||||
unsigned char correct[20];
|
||||
hmacsha1_genresult(handle, correct);
|
||||
return !memcmp(correct, hmac, 20);
|
||||
}
|
||||
|
||||
static int sha1_verify(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
@ -301,6 +329,13 @@ static int sha1_verify(void *handle, unsigned char *blk, int len,
|
||||
return !memcmp(correct, blk + len, 20);
|
||||
}
|
||||
|
||||
static void hmacsha1_96_genresult(void *handle, unsigned char *hmac)
|
||||
{
|
||||
unsigned char full[20];
|
||||
hmacsha1_genresult(handle, full);
|
||||
memcpy(hmac, full, 12);
|
||||
}
|
||||
|
||||
static void sha1_96_generate(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
@ -309,6 +344,13 @@ static void sha1_96_generate(void *handle, unsigned char *blk, int len,
|
||||
memcpy(blk + len, full, 12);
|
||||
}
|
||||
|
||||
static int hmacsha1_96_verresult(void *handle, unsigned char const *hmac)
|
||||
{
|
||||
unsigned char correct[20];
|
||||
hmacsha1_genresult(handle, correct);
|
||||
return !memcmp(correct, hmac, 12);
|
||||
}
|
||||
|
||||
static int sha1_96_verify(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
@ -333,6 +375,7 @@ void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
|
||||
const struct ssh_mac ssh_hmac_sha1 = {
|
||||
sha1_make_context, sha1_free_context, sha1_key,
|
||||
sha1_generate, sha1_verify,
|
||||
hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,
|
||||
"hmac-sha1",
|
||||
20,
|
||||
"HMAC-SHA1"
|
||||
@ -341,6 +384,8 @@ const struct ssh_mac ssh_hmac_sha1 = {
|
||||
const struct ssh_mac ssh_hmac_sha1_96 = {
|
||||
sha1_make_context, sha1_free_context, sha1_key,
|
||||
sha1_96_generate, sha1_96_verify,
|
||||
hmacsha1_start, hmacsha1_bytes,
|
||||
hmacsha1_96_genresult, hmacsha1_96_verresult,
|
||||
"hmac-sha1-96",
|
||||
12,
|
||||
"HMAC-SHA1-96"
|
||||
@ -349,6 +394,7 @@ const struct ssh_mac ssh_hmac_sha1_96 = {
|
||||
const struct ssh_mac ssh_hmac_sha1_buggy = {
|
||||
sha1_make_context, sha1_free_context, sha1_key_buggy,
|
||||
sha1_generate, sha1_verify,
|
||||
hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,
|
||||
"hmac-sha1",
|
||||
20,
|
||||
"bug-compatible HMAC-SHA1"
|
||||
@ -357,6 +403,8 @@ const struct ssh_mac ssh_hmac_sha1_buggy = {
|
||||
const struct ssh_mac ssh_hmac_sha1_96_buggy = {
|
||||
sha1_make_context, sha1_free_context, sha1_key_buggy,
|
||||
sha1_96_generate, sha1_96_verify,
|
||||
hmacsha1_start, hmacsha1_bytes,
|
||||
hmacsha1_96_genresult, hmacsha1_96_verresult,
|
||||
"hmac-sha1-96",
|
||||
12,
|
||||
"bug-compatible HMAC-SHA1-96"
|
||||
|
Reference in New Issue
Block a user