diff --git a/Recipe b/Recipe index e133c70a..4b35bd55 100644 --- a/Recipe +++ b/Recipe @@ -255,6 +255,7 @@ SSHCRYPTO = ARITH sshmd5 sshsha sshsh256 sshsh512 + sshrsa sshdss sshecc + sshdes sshblowf sshaes sshccp ssharcf + sshdh sshcrc sshcrcda sshauxcrypt + + sshhmac SSHCOMMON = sshcommon sshrand SSHCRYPTO + sshverstring + sshpubk sshzlib @@ -333,13 +334,13 @@ psftp : [C] psftp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC pageant : [G] winpgnt pageant sshrsa sshpubk sshdes ARITH sshmd5 version + tree234 MISC sshaes sshsha winsecur winpgntc aqsync sshdss sshsh256 + sshsh512 winutils sshecc winmisc winmiscs winhelp conf pageant.res - + sshauxcrypt LIBS + + sshauxcrypt sshhmac LIBS puttygen : [G] winpgen sshrsag sshdssg sshprime sshdes ARITH sshmd5 version + sshrand winnoise sshsha winstore MISC winctrls sshrsa sshdss winmisc + sshpubk sshaes sshsh256 sshsh512 IMPORT winutils puttygen.res + tree234 notiming winhelp winnojmp CONF LIBS wintime sshecc - + sshecdsag sshauxcrypt winsecur winmiscs + + sshecdsag sshauxcrypt sshhmac winsecur winmiscs pterm : [X] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore + uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg @@ -357,7 +358,7 @@ plink : [U] uxplink uxcons NONSSH UXSSH U_BE_ALL logging UXMISC uxsignal PUTTYGEN_UNIX = sshrsag sshdssg sshprime sshdes ARITH sshmd5 version + sshrand uxnoise sshsha MISC sshrsa sshdss uxcons uxstore uxmisc + sshpubk sshaes sshsh256 sshsh512 IMPORT puttygen.res time tree234 - + uxgen notiming CONF sshecc sshecdsag uxnogtk sshauxcrypt + + uxgen notiming CONF sshecc sshecdsag uxnogtk sshauxcrypt sshhmac puttygen : [U] cmdgen PUTTYGEN_UNIX cgtest : [UT] cgtest PUTTYGEN_UNIX @@ -368,7 +369,7 @@ pageant : [X] uxpgnt uxagentc aqsync pageant sshrsa sshpubk sshdes ARITH + sshmd5 version tree234 misc sshaes sshsha sshdss sshsh256 sshsh512 + sshecc CONF uxsignal nocproxy nogss be_none x11fwd ux_x11 uxcons + gtkask gtkmisc nullplug logging UXMISC uxagentsock utils memory - + sshauxcrypt + + sshauxcrypt sshhmac ptermapp : [XT] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore + uxsignal CHARSET uxpterm version time xpmpterm xpmptcfg diff --git a/cproxy.c b/cproxy.c index 5825f32e..0c2e62fe 100644 --- a/cproxy.c +++ b/cproxy.c @@ -18,15 +18,8 @@ static void hmacmd5_chap(const unsigned char *challenge, int challen, const char *passwd, unsigned char *response) { - ptrlen key = ptrlen_from_asciz(passwd); - unsigned char md5buf[16]; - - if (key.len > 64) { - hash_simple(&ssh_md5, key, md5buf); - key = make_ptrlen(md5buf, 16); - } - mac_simple(&ssh_hmac_md5, key, make_ptrlen(challenge, challen), response); - smemclr(md5buf, sizeof(md5buf)); + mac_simple(&ssh_hmac_md5, ptrlen_from_asciz(passwd), + make_ptrlen(challenge, challen), response); } void proxy_socks5_offerencryptedauth(BinarySink *bs) diff --git a/marshal.h b/marshal.h index 3c3467d2..6cb83851 100644 --- a/marshal.h +++ b/marshal.h @@ -31,10 +31,16 @@ struct BinarySink { * put 'BinarySink_DELEGATE_IMPLEMENTATION' in its declaration, and * when an instance is set up, use 'BinarySink_DELEGATE_INIT' to point * at the object it wants to delegate to. + * + * In such a delegated structure, you might sometimes want to have the + * delegation stop being valid (e.g. it might be delegating to an + * object that only sometimes exists). You can null out the delegate + * pointer using BinarySink_DELEGATE_CLEAR. */ #define BinarySink_DELEGATE_IMPLEMENTATION BinarySink *binarysink_ #define BinarySink_DELEGATE_INIT(obj, othersink) \ ((obj)->binarysink_ = BinarySink_UPCAST(othersink)) +#define BinarySink_DELEGATE_CLEAR(obj) ((obj)->binarysink_ = NULL) /* * The implementing type's write function will want to downcast its diff --git a/sshhmac.c b/sshhmac.c new file mode 100644 index 00000000..8f2577a6 --- /dev/null +++ b/sshhmac.c @@ -0,0 +1,210 @@ +/* + * Implementation of HMAC (RFC 2104) for PuTTY, in a general form that + * can wrap any underlying hash function. + */ + +#include "ssh.h" + +struct hmac { + ssh_hash *h_outer, *h_inner, *h_live; + uint8_t *digest; + strbuf *text_name; + ssh2_mac mac; +}; + +struct hmac_extra { + const ssh_hashalg *hashalg; + size_t blklen; + const char *suffix; +}; + +static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher) +{ + struct hmac *ctx = snew(struct hmac); + const struct hmac_extra *extra = (const struct hmac_extra *)alg->extra; + + ctx->h_outer = ctx->h_inner = ctx->h_live = NULL; + ctx->digest = snewn(extra->hashalg->hlen, uint8_t); + + ctx->text_name = strbuf_new(); + strbuf_catf(ctx->text_name, "HMAC-%s%s", + extra->hashalg->text_name, extra->suffix); + + ctx->mac.vt = alg; + BinarySink_DELEGATE_CLEAR(&ctx->mac); + + return &ctx->mac; +} + +static void hmac_free(ssh2_mac *mac) +{ + struct hmac *ctx = container_of(mac, struct hmac, mac); + const struct hmac_extra *extra = (const struct hmac_extra *)mac->vt->extra; + + if (ctx->h_outer) + ssh_hash_free(ctx->h_outer); + if (ctx->h_inner) + ssh_hash_free(ctx->h_inner); + if (ctx->h_live) + ssh_hash_free(ctx->h_live); + smemclr(ctx->digest, extra->hashalg->hlen); + sfree(ctx->digest); + strbuf_free(ctx->text_name); + + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); +} + +#define PAD_OUTER 0x5C +#define PAD_INNER 0x36 + +static void hmac_key(ssh2_mac *mac, ptrlen key) +{ + struct hmac *ctx = container_of(mac, struct hmac, mac); + const struct hmac_extra *extra = (const struct hmac_extra *)mac->vt->extra; + + const uint8_t *kp; + size_t klen; + strbuf *sb = NULL; + + if (key.len > extra->blklen) { + /* + * RFC 2104 section 2: if the key exceeds the block length of + * the underlying hash, then we start by hashing the key, and + * use that hash as the 'true' key for the HMAC construction. + */ + sb = strbuf_new(); + strbuf_append(sb, extra->hashalg->hlen); + + ssh_hash *htmp = ssh_hash_new(extra->hashalg); + put_datapl(htmp, key); + ssh_hash_final(htmp, sb->u); + + kp = sb->u; + klen = sb->len; + } else { + /* + * A short enough key is used as is. + */ + kp = (const uint8_t *)key.ptr; + klen = key.len; + } + + if (ctx->h_outer) + ssh_hash_free(ctx->h_outer); + if (ctx->h_inner) + ssh_hash_free(ctx->h_inner); + + ctx->h_outer = ssh_hash_new(extra->hashalg); + for (size_t i = 0; i < klen; i++) + put_byte(ctx->h_outer, PAD_OUTER ^ kp[i]); + for (size_t i = klen; i < extra->blklen; i++) + put_byte(ctx->h_outer, PAD_OUTER); + + ctx->h_inner = ssh_hash_new(extra->hashalg); + for (size_t i = 0; i < klen; i++) + put_byte(ctx->h_inner, PAD_INNER ^ kp[i]); + for (size_t i = klen; i < extra->blklen; i++) + put_byte(ctx->h_inner, PAD_INNER); + + if (sb) + strbuf_free(sb); +} + +static void hmac_start(ssh2_mac *mac) +{ + struct hmac *ctx = container_of(mac, struct hmac, mac); + + assert(ctx->h_outer); + if (ctx->h_live) + ssh_hash_free(ctx->h_live); + + ctx->h_live = ssh_hash_copy(ctx->h_inner); + BinarySink_DELEGATE_INIT(&ctx->mac, ctx->h_live); +} + +static void hmac_genresult(ssh2_mac *mac, unsigned char *output) +{ + struct hmac *ctx = container_of(mac, struct hmac, mac); + const struct hmac_extra *extra = (const struct hmac_extra *)mac->vt->extra; + + assert(ctx->h_live); + ssh_hash_final(ctx->h_live, ctx->digest); + + ctx->h_live = NULL; + BinarySink_DELEGATE_CLEAR(&ctx->mac); + + ssh_hash *htmp = ssh_hash_copy(ctx->h_outer); + put_data(htmp, ctx->digest, extra->hashalg->hlen); + ssh_hash_final(htmp, ctx->digest); + + /* + * Some instances of HMAC truncate the output hash, so instead of + * writing it directly to 'output' we wrote it to our own + * full-length buffer, and now we copy the required amount. + */ + memcpy(output, ctx->digest, mac->vt->len); + smemclr(ctx->digest, extra->hashalg->hlen); +} + +static const char *hmac_text_name(ssh2_mac *mac) +{ + struct hmac *ctx = container_of(mac, struct hmac, mac); + return ctx->text_name->s; +} + +const struct hmac_extra ssh_hmac_sha256_extra = { &ssh_sha256, 64, "" }; +const ssh2_macalg ssh_hmac_sha256 = { + hmac_new, hmac_free, hmac_key, + hmac_start, hmac_genresult, hmac_text_name, + "hmac-sha2-256", "hmac-sha2-256-etm@openssh.com", + 32, 32, &ssh_hmac_sha256_extra, +}; + +const struct hmac_extra ssh_hmac_md5_extra = { &ssh_md5, 64, "" }; +const ssh2_macalg ssh_hmac_md5 = { + hmac_new, hmac_free, hmac_key, + hmac_start, hmac_genresult, hmac_text_name, + "hmac-md5", "hmac-md5-etm@openssh.com", + 16, 16, &ssh_hmac_md5_extra, +}; + +const struct hmac_extra ssh_hmac_sha1_extra = { &ssh_sha1, 64, "" }; + +const ssh2_macalg ssh_hmac_sha1 = { + hmac_new, hmac_free, hmac_key, + hmac_start, hmac_genresult, hmac_text_name, + "hmac-sha1", "hmac-sha1-etm@openssh.com", + 20, 20, &ssh_hmac_sha1_extra, +}; + +const struct hmac_extra ssh_hmac_sha1_96_extra = { &ssh_sha1, 64, "-96" }; + +const ssh2_macalg ssh_hmac_sha1_96 = { + hmac_new, hmac_free, hmac_key, + hmac_start, hmac_genresult, hmac_text_name, + "hmac-sha1-96", "hmac-sha1-96-etm@openssh.com", + 12, 20, &ssh_hmac_sha1_96_extra, +}; + +const struct hmac_extra ssh_hmac_sha1_buggy_extra = { + &ssh_sha1, 64, " (bug-compatible)" +}; + +const ssh2_macalg ssh_hmac_sha1_buggy = { + hmac_new, hmac_free, hmac_key, + hmac_start, hmac_genresult, hmac_text_name, + "hmac-sha1", NULL, + 20, 16, &ssh_hmac_sha1_buggy_extra, +}; + +const struct hmac_extra ssh_hmac_sha1_96_buggy_extra = { + &ssh_sha1, 64, "-96 (bug-compatible)" +}; + +const ssh2_macalg ssh_hmac_sha1_96_buggy = { + hmac_new, hmac_free, hmac_key, + hmac_start, hmac_genresult, hmac_text_name, + "hmac-sha1-96", NULL, + 12, 16, &ssh_hmac_sha1_96_buggy_extra, +}; diff --git a/sshmd5.c b/sshmd5.c index 6f0974fc..4fcc906b 100644 --- a/sshmd5.c +++ b/sshmd5.c @@ -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, -}; diff --git a/sshsh256.c b/sshsh256.c index 2bb059f4..940726bd 100644 --- a/sshsh256.c +++ b/sshsh256.c @@ -255,93 +255,6 @@ const ssh_hashalg ssh_sha256 = { sha256_new, sha256_copy, sha256_final, sha256_free, 32, "SHA-256" }; -/* ---------------------------------------------------------------------- - * The above is the SHA-256 algorithm itself. Now we implement the - * HMAC wrapper on it. - */ - -struct hmacsha256 { - SHA256_State sha[3]; - ssh2_mac mac; -}; - -static ssh2_mac *hmacsha256_new(const ssh2_macalg *alg, ssh_cipher *cipher) -{ - struct hmacsha256 *ctx = snew(struct hmacsha256); - ctx->mac.vt = alg; - BinarySink_DELEGATE_INIT(&ctx->mac, &ctx->sha[2]); - return &ctx->mac; -} - -static void hmacsha256_free(ssh2_mac *mac) -{ - struct hmacsha256 *ctx = container_of(mac, struct hmacsha256, mac); - smemclr(ctx, sizeof(*ctx)); - sfree(ctx); -} - -static void sha256_key_internal(struct hmacsha256 *ctx, - 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]; - SHA256_Init(&ctx->sha[0]); - put_data(&ctx->sha[0], foo, 64); - - memset(foo, 0x5C, 64); - for (i = 0; i < len && i < 64; i++) - foo[i] ^= key[i]; - SHA256_Init(&ctx->sha[1]); - put_data(&ctx->sha[1], foo, 64); - - smemclr(foo, 64); /* burn the evidence */ -} - -static void hmacsha256_key(ssh2_mac *mac, ptrlen key) -{ - struct hmacsha256 *ctx = container_of(mac, struct hmacsha256, mac); - sha256_key_internal(ctx, key.ptr, key.len); -} - -static void hmacsha256_start(ssh2_mac *mac) -{ - struct hmacsha256 *ctx = container_of(mac, struct hmacsha256, mac); - - ctx->sha[2] = ctx->sha[0]; /* structure copy */ - BinarySink_COPIED(&ctx->sha[2]); -} - -static void hmacsha256_genresult(ssh2_mac *mac, unsigned char *hmac) -{ - struct hmacsha256 *ctx = container_of(mac, struct hmacsha256, mac); - SHA256_State s; - unsigned char intermediate[32]; - - s = ctx->sha[2]; /* structure copy */ - BinarySink_COPIED(&s); - SHA256_Final(&s, intermediate); - s = ctx->sha[1]; /* structure copy */ - BinarySink_COPIED(&s); - put_data(&s, intermediate, 32); - SHA256_Final(&s, hmac); -} - -static const char *hmacsha256_text_name(ssh2_mac *mac) -{ - return "HMAC-SHA-256"; -} - -const ssh2_macalg ssh_hmac_sha256 = { - hmacsha256_new, hmacsha256_free, hmacsha256_key, - hmacsha256_start, hmacsha256_genresult, hmacsha256_text_name, - "hmac-sha2-256", "hmac-sha2-256-etm@openssh.com", - 32, 32, -}; - #ifdef COMPILER_SUPPORTS_SHA_NI #if defined _MSC_VER && defined _M_AMD64 diff --git a/sshsha.c b/sshsha.c index 0976bdd0..9f4fb5c7 100644 --- a/sshsha.c +++ b/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 diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 7cb7a86f..f0512b35 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -1483,15 +1483,14 @@ class standard_test_vectors(MyTestBase): '77966b957a878e720584779a62825c18da26415e49a7176a894e7510fd1451f5')) def testHmacSHA(self): - # Test cases from RFC 6234 section 8.5, omitting the ones - # which have a long enough key to require hashing it first. - # (Our implementation doesn't support that, because it knows - # it only has to deal with a fixed key length.) - def vector(key, message, s1, s256): - self.assertEqualBin( - mac_str('hmac_sha1', key, message), unhex(s1)) - self.assertEqualBin( - mac_str('hmac_sha256', key, message), unhex(s256)) + # Test cases from RFC 6234 section 8.5. + def vector(key, message, s1=None, s256=None): + if s1 is not None: + self.assertEqualBin( + mac_str('hmac_sha1', key, message), unhex(s1)) + if s256 is not None: + self.assertEqualBin( + mac_str('hmac_sha256', key, message), unhex(s256)) vector( unhex("0b"*20), "Hi There", "b617318655057264e28bc0b6fb378c8ef146be00", @@ -1509,6 +1508,26 @@ class standard_test_vectors(MyTestBase): unhex("cd"*50), "4c9007f4026250c6bc8414f9bf50c86c2d7235da", "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b") + vector( + unhex("aa"*80), + "Test Using Larger Than Block-Size Key - Hash Key First", + s1="aa4ae5e15272d00e95705637ce8a3b55ed402112") + vector( + unhex("aa"*131), + "Test Using Larger Than Block-Size Key - Hash Key First", + s256="60e431591ee0b67f0d8a26aacbf5b77f" + "8e0bc6213728c5140546040f0ee37f54") + vector( + unhex("aa"*80), + "Test Using Larger Than Block-Size Key and " + "Larger Than One Block-Size Data", + s1="e8e99d0f45237d786d6bbaa7965c7808bbff1a91") + vector( + unhex("aa"*131), + "This is a test using a larger than block-size key and a " + "larger than block-size data. The key needs to be hashed " + "before being used by the HMAC algorithm.", + s256="9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713938A7F51535C3A35E2") def testEd25519(self): def vector(privkey, pubkey, message, signature):