From 66970c4258fc82b9cb558ccdeb2fbe79c7fe8ef4 Mon Sep 17 00:00:00 2001 From: Chris Staite Date: Sat, 1 Nov 2014 08:59:25 +0000 Subject: [PATCH] Provide SHA-384 and SHA-512 as hashes usable in SSH KEX. SHA-384 was previously not implemented at all, but is a trivial adjustment to SHA-512 (different starting constants, and truncate the output hash). Both are now exposed as 'ssh_hash' structures so that key exchange methods can ask for them. --- ssh.h | 7 ++++ sshsh512.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/ssh.h b/ssh.h index dc34052d..a73e9391 100644 --- a/ssh.h +++ b/ssh.h @@ -204,10 +204,15 @@ typedef struct { int blkused; uint32 len[4]; } SHA512_State; +#define SHA384_State SHA512_State void SHA512_Init(SHA512_State * s); void SHA512_Bytes(SHA512_State * s, const void *p, int len); void SHA512_Final(SHA512_State * s, unsigned char *output); void SHA512_Simple(const void *p, int len, unsigned char *output); +void SHA384_Init(SHA384_State * s); +#define SHA384_Bytes(s, p, len) SHA512_Bytes(s, p, len) +void SHA384_Final(SHA384_State * s, unsigned char *output); +void SHA384_Simple(const void *p, int len, unsigned char *output); struct ssh_cipher { void *(*make_context)(void); @@ -334,6 +339,8 @@ extern const struct ssh2_ciphers ssh2_blowfish; extern const struct ssh2_ciphers ssh2_arcfour; extern const struct ssh_hash ssh_sha1; extern const struct ssh_hash ssh_sha256; +extern const struct ssh_hash ssh_sha384; +extern const struct ssh_hash ssh_sha512; extern const struct ssh_kexes ssh_diffiehellman_group1; extern const struct ssh_kexes ssh_diffiehellman_group14; extern const struct ssh_kexes ssh_diffiehellman_gex; diff --git a/sshsh512.c b/sshsh512.c index 8d0b1ae3..cd2b296e 100644 --- a/sshsh512.c +++ b/sshsh512.c @@ -2,6 +2,8 @@ * SHA-512 algorithm as described at * * http://csrc.nist.gov/cryptval/shs.html + * + * Modifications made for SHA-384 also */ #include "ssh.h" @@ -61,6 +63,22 @@ static void SHA512_Core_Init(SHA512_State *s) { s->h[i] = iv[i]; } +static void SHA384_Core_Init(SHA512_State *s) { + static const uint64 iv[] = { + INIT(0xcbbb9d5d, 0xc1059ed8), + INIT(0x629a292a, 0x367cd507), + INIT(0x9159015a, 0x3070dd17), + INIT(0x152fecd8, 0xf70e5939), + INIT(0x67332667, 0xffc00b31), + INIT(0x8eb44a87, 0x68581511), + INIT(0xdb0c2e0d, 0x64f98fa7), + INIT(0x47b5481d, 0xbefa4fa4), + }; + int i; + for (i = 0; i < 8; i++) + s->h[i] = iv[i]; +} + static void SHA512_Block(SHA512_State *s, uint64 *block) { uint64 w[80]; uint64 a,b,c,d,e,f,g,h; @@ -175,6 +193,14 @@ void SHA512_Init(SHA512_State *s) { s->len[i] = 0; } +void SHA384_Init(SHA512_State *s) { + int i; + SHA384_Core_Init(s); + s->blkused = 0; + for (i = 0; i < 4; i++) + s->len[i] = 0; +} + void SHA512_Bytes(SHA512_State *s, const void *p, int len) { unsigned char *q = (unsigned char *)p; uint64 wordblock[16]; @@ -268,6 +294,12 @@ void SHA512_Final(SHA512_State *s, unsigned char *digest) { } } +void SHA384_Final(SHA512_State *s, unsigned char *digest) { + unsigned char biggerDigest[512 / 8]; + SHA512_Final(s, biggerDigest); + memcpy(digest, biggerDigest, 384 / 8); +} + void SHA512_Simple(const void *p, int len, unsigned char *output) { SHA512_State s; @@ -276,6 +308,67 @@ void SHA512_Simple(const void *p, int len, unsigned char *output) { SHA512_Final(&s, output); } +void SHA384_Simple(const void *p, int len, unsigned char *output) { + SHA512_State s; + + SHA384_Init(&s); + SHA512_Bytes(&s, p, len); + SHA384_Final(&s, output); +} + +/* + * Thin abstraction for things where hashes are pluggable. + */ + +static void *sha512_init(void) +{ + SHA512_State *s; + + s = snew(SHA512_State); + SHA512_Init(s); + return s; +} + +static void sha512_bytes(void *handle, void *p, int len) +{ + SHA512_State *s = handle; + + SHA512_Bytes(s, p, len); +} + +static void sha512_final(void *handle, unsigned char *output) +{ + SHA512_State *s = handle; + + SHA512_Final(s, output); + sfree(s); +} + +const struct ssh_hash ssh_sha512 = { + sha512_init, sha512_bytes, sha512_final, 64, "SHA-512" +}; + +static void *sha384_init(void) +{ + SHA512_State *s; + + s = snew(SHA512_State); + SHA384_Init(s); + return s; +} + +static void sha384_final(void *handle, unsigned char *output) +{ + SHA512_State *s = handle; + + SHA384_Final(s, output); + sfree(s); +} + +const struct ssh_hash ssh_sha384 = { + sha384_init, sha512_bytes, sha384_final, 48, "SHA-384" +}; + #ifdef TEST #include