Преглед изворни кода

PuTTY snapshot 76aa3f6f (Add more random-number noise collection calls - 2019-01-24)

Source commit: 8a123d14506c4509c6c95c3377ef8625dee71dfd
Martin Prikryl пре 6 година
родитељ
комит
f67d8c2822

+ 2 - 9
source/putty/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)

+ 6 - 0
source/putty/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

+ 6 - 1
source/putty/ssh.h

@@ -627,9 +627,12 @@ struct ssh2_macalg {
     void (*setkey)(ssh2_mac *, ptrlen key);
     void (*start)(ssh2_mac *);
     void (*genresult)(ssh2_mac *, unsigned char *);
+    const char *(*text_name)(ssh2_mac *);
     const char *name, *etm_name;
     int len, keylen;
-    const char *text_name;
+
+    /* Pointer to any extra data used by a particular implementation. */
+    const void *extra;
 };
 
 #define ssh2_mac_new(alg, cipher) ((alg)->new(alg, cipher))
@@ -637,6 +640,7 @@ struct ssh2_macalg {
 #define ssh2_mac_setkey(ctx, key) ((ctx)->vt->setkey(ctx, key))
 #define ssh2_mac_start(ctx) ((ctx)->vt->start(ctx))
 #define ssh2_mac_genresult(ctx, out) ((ctx)->vt->genresult(ctx, out))
+#define ssh2_mac_text_name(ctx) ((ctx)->vt->text_name(ctx))
 #define ssh2_mac_alg(ctx) ((ctx)->vt)
 
 /* Centralised 'methods' for ssh2_mac, defined in sshmac.c. These run
@@ -661,6 +665,7 @@ struct ssh_hashalg {
     void (*final)(ssh_hash *, unsigned char *); /* ALSO FREES THE ssh_hash! */
     void (*free)(ssh_hash *);
     int hlen; /* output length in bytes */
+    int blocklen; /* length of the hash's input block, or 0 for N/A */
     const char *text_name;
 };
 

+ 9 - 5
source/putty/ssh1login.c

@@ -51,7 +51,7 @@ struct ssh1_login_state {
     bool authed;
     RSAKey key;
     mp_int *challenge;
-    ptrlen comment;
+    strbuf *agent_comment;
     int dlgret;
     Filename *keyfile;
     RSAKey servkey, hostkey;
@@ -95,6 +95,7 @@ PacketProtocolLayer *ssh1_login_new(
     s->savedhost = dupstr(host);
     s->savedport = port;
     s->successor_layer = successor_layer;
+    s->agent_comment = strbuf_new();
     return &s->ppl;
 }
 
@@ -113,6 +114,7 @@ static void ssh1_login_free(PacketProtocolLayer *ppl)
     if (s->publickey_blob)
         strbuf_free(s->publickey_blob);
     sfree(s->publickey_comment);
+    strbuf_free(s->agent_comment);
     if (s->cur_prompt)
         free_prompts(s->cur_prompt);
     sfree(s->agent_response_to_free);
@@ -507,7 +509,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                     get_rsa_ssh1_pub(s->asrc, &s->key,
                                      RSA_SSH1_EXPONENT_FIRST);
                     end = s->asrc->pos;
-                    s->comment = get_string(s->asrc);
+                    s->agent_comment->len = 0;
+                    put_datapl(s->agent_comment, get_string(s->asrc));
                     if (get_err(s->asrc)) {
                         ppl_logevent("Pageant key list packet was truncated");
                         break;
@@ -570,7 +573,6 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                     s->ppl.bpp, SSH1_CMSG_AUTH_RSA_RESPONSE);
                                 put_data(pkt, ret + 5, 16);
                                 pq_push(s->ppl.out_pq, pkt);
-                                sfree((char *)ret);
                                 crMaybeWaitUntilV(
                                     (pktin = ssh1_login_pop(s))
                                     != NULL);
@@ -578,10 +580,12 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
                                     ppl_logevent("Pageant's response "
                                                  "accepted");
                                     if (flags & FLAG_VERBOSE) {
+                                        ptrlen comment = ptrlen_from_strbuf(
+                                            s->agent_comment);
                                         ppl_printf("Authenticated using RSA "
                                                    "key \"%.*s\" from "
-                                                   "agent\r\n", PTRLEN_PRINTF(
-                                                       s->comment));
+                                                   "agent\r\n",
+                                                   PTRLEN_PRINTF(comment));
                                     }
                                     s->authed = true;
                                 } else

+ 2 - 2
source/putty/ssh2bpp.c

@@ -140,7 +140,7 @@ void ssh2_bpp_new_outgoing_crypto(
         ssh2_mac_setkey(s->out.mac, make_ptrlen(mac_key, mac->keylen));
 
         bpp_logevent("Initialised %s outbound MAC algorithm%s%s",
-                     ssh2_mac_alg(s->out.mac)->text_name,
+                     ssh2_mac_text_name(s->out.mac),
                      etm_mode ? " (in ETM mode)" : "",
                      (s->out.cipher &&
                       ssh_cipher_alg(s->out.cipher)->required_mac ?
@@ -197,7 +197,7 @@ void ssh2_bpp_new_incoming_crypto(
         ssh2_mac_setkey(s->in.mac, make_ptrlen(mac_key, mac->keylen));
 
         bpp_logevent("Initialised %s inbound MAC algorithm%s%s",
-                     ssh2_mac_alg(s->in.mac)->text_name,
+                     ssh2_mac_text_name(s->in.mac),
                      etm_mode ? " (in ETM mode)" : "",
                      (s->in.cipher &&
                       ssh_cipher_alg(s->in.cipher)->required_mac ?

+ 22 - 17
source/putty/sshaes.c

@@ -103,37 +103,42 @@ struct aes_extra {
     const ssh_cipheralg *sw, *hw;
 };
 
-#define VTABLES(cid, pid, bits, name, encsuffix, decsuffix, setiv)      \
-    static void cid##_sw##encsuffix(ssh_cipher *, void *blk, int len); \
-    static void cid##_sw##decsuffix(ssh_cipher *, void *blk, int len); \
-    const ssh_cipheralg ssh_##cid##_sw = {                             \
+#define VTABLES_INNER(cid, pid, bits, name, encsuffix,                  \
+                      decsuffix, setiv, flags)                          \
+    static void cid##_sw##encsuffix(ssh_cipher *, void *blk, int len);  \
+    static void cid##_sw##decsuffix(ssh_cipher *, void *blk, int len);  \
+    const ssh_cipheralg ssh_##cid##_sw = {                              \
         aes_sw_new, aes_sw_free, aes_sw_##setiv, aes_sw_setkey,         \
         cid##_sw##encsuffix, cid##_sw##decsuffix, NULL, NULL,           \
-        pid, 16, bits, bits/8, 0, name " (unaccelerated)",              \
+        pid, 16, bits, bits/8, flags, name " (unaccelerated)",          \
         NULL, NULL };                                                   \
                                                                         \
-    static void cid##_hw##encsuffix(ssh_cipher *, void *blk, int len); \
-    static void cid##_hw##decsuffix(ssh_cipher *, void *blk, int len); \
-    const ssh_cipheralg ssh_##cid##_hw = {                             \
+    static void cid##_hw##encsuffix(ssh_cipher *, void *blk, int len);  \
+    static void cid##_hw##decsuffix(ssh_cipher *, void *blk, int len);  \
+    const ssh_cipheralg ssh_##cid##_hw = {                              \
         aes_hw_new, aes_hw_free, aes_hw_##setiv, aes_hw_setkey,         \
         cid##_hw##encsuffix, cid##_hw##decsuffix, NULL, NULL,           \
-        pid, 16, bits, bits/8, 0, name HW_NAME_SUFFIX,                  \
+        pid, 16, bits, bits/8, flags, name HW_NAME_SUFFIX,              \
         NULL, NULL };                                                   \
                                                                         \
     const struct aes_extra extra_##cid = {                              \
         &ssh_##cid##_sw, &ssh_##cid##_hw };                             \
                                                                         \
-    const ssh_cipheralg ssh_##cid = {                                  \
+    const ssh_cipheralg ssh_##cid = {                                   \
         aes_select, NULL, NULL, NULL, NULL, NULL, NULL, NULL,           \
-        pid, 16, bits, bits/8, 0, name " (dummy selector vtable)",      \
+        pid, 16, bits, bits/8, flags, name " (dummy selector vtable)",  \
         NULL, &extra_##cid };                                           \
 
-VTABLES(aes128_cbc, "aes128", 128, "AES-128 CBC", _encrypt,_decrypt,setiv_cbc)
-VTABLES(aes192_cbc, "aes192", 192, "AES-192 CBC", _encrypt,_decrypt,setiv_cbc)
-VTABLES(aes256_cbc, "aes256", 256, "AES-256 CBC", _encrypt,_decrypt,setiv_cbc)
-VTABLES(aes128_sdctr, "aes128-ctr", 128, "AES-128 SDCTR",,, setiv_sdctr)
-VTABLES(aes192_sdctr, "aes192-ctr", 192, "AES-192 SDCTR",,, setiv_sdctr)
-VTABLES(aes256_sdctr, "aes256-ctr", 256, "AES-256 SDCTR",,, setiv_sdctr)
+#define VTABLES(keylen)                                                 \
+    VTABLES_INNER(aes ## keylen ## _cbc, "aes" #keylen,                 \
+                  keylen, "AES-" #keylen " CBC", _encrypt, _decrypt,    \
+                  setiv_cbc, SSH_CIPHER_IS_CBC)                         \
+    VTABLES_INNER(aes ## keylen ## _sdctr, "aes" #keylen "-ctr",        \
+                  keylen, "AES-" #keylen " SDCTR",,, setiv_sdctr, 0)
+
+VTABLES(128)
+VTABLES(192)
+VTABLES(256)
 
 static const ssh_cipheralg ssh_rijndael_lysator = {
     /* Same as aes256_cbc, but with a different protocol ID */

+ 7 - 2
source/putty/sshccp.c

@@ -938,12 +938,17 @@ static void poly_genresult(ssh2_mac *mac, unsigned char *blk)
     poly1305_finalise(&ctx->mac, blk);
 }
 
+static const char *poly_text_name(ssh2_mac *mac)
+{
+    return "Poly1305";
+}
+
 const ssh2_macalg ssh2_poly1305 = {
     poly_ssh2_new, poly_ssh2_free, poly_setkey,
-    poly_start, poly_genresult,
+    poly_start, poly_genresult, poly_text_name,
 
     "", "", /* Not selectable individually, just part of ChaCha20-Poly1305 */
-    16, 0, "Poly1305"
+    16, 0,
 };
 
 static ssh_cipher *ccp_new(const ssh_cipheralg *alg)

+ 234 - 0
source/putty/sshhmac.c

@@ -0,0 +1,234 @@
+/*
+ * Implementation of HMAC (RFC 2104) for PuTTY, in a general form that
+ * can wrap any underlying hash function.
+ */
+
+#include "ssh.h"
+
+struct hmac {
+    const ssh_hashalg *hashalg;
+    ssh_hash *h_outer, *h_inner, *h_live;
+    bool keyed;
+    uint8_t *digest;
+    strbuf *text_name;
+    ssh2_mac mac;
+};
+
+struct hmac_extra {
+    const ssh_hashalg *hashalg_base;
+    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 = ssh_hash_new(extra->hashalg_base);
+    /* In case that hashalg was a selector vtable, we'll now switch to
+     * using whatever real one it selected, for all future purposes. */
+    ctx->hashalg = ssh_hash_alg(ctx->h_outer);
+    ctx->h_inner = ssh_hash_new(ctx->hashalg);
+    ctx->h_live = ssh_hash_new(ctx->hashalg);
+    ctx->keyed = false;
+
+    /*
+     * HMAC is not well defined as a wrapper on an absolutely general
+     * hash function; it expects that the function it's wrapping will
+     * consume data in fixed-size blocks, and it's partially defined
+     * in terms of that block size. So we insist that the hash we're
+     * given must have defined a meaningful block size.
+     */
+    assert(ctx->hashalg->blocklen);
+
+    ctx->digest = snewn(ctx->hashalg->hlen, uint8_t);
+
+    ctx->text_name = strbuf_new();
+    strbuf_catf(ctx->text_name, "HMAC-%s%s",
+                ctx->hashalg->text_name, extra->suffix);
+
+    ctx->mac.vt = alg;
+    BinarySink_DELEGATE_INIT(&ctx->mac, ctx->h_live);
+
+    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;
+
+    ssh_hash_free(ctx->h_outer);
+    ssh_hash_free(ctx->h_inner);
+    ssh_hash_free(ctx->h_live);
+    smemclr(ctx->digest, ctx->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 (ctx->keyed) {
+        /*
+         * If we've already been keyed, throw away the existing hash
+         * objects and make a fresh pair to put the new key in.
+         */
+        ssh_hash_free(ctx->h_outer);
+        ssh_hash_free(ctx->h_inner);
+        ctx->h_outer = ssh_hash_new(ctx->hashalg);
+        ctx->h_inner = ssh_hash_new(ctx->hashalg);
+    }
+    ctx->keyed = true;
+
+    if (key.len > ctx->hashalg->blocklen) {
+        /*
+         * 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, ctx->hashalg->hlen);
+
+        ssh_hash *htmp = ssh_hash_new(ctx->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(ctx->hashalg);
+    for (size_t i = 0; i < klen; i++)
+        put_byte(ctx->h_outer, PAD_OUTER ^ kp[i]);
+    for (size_t i = klen; i < ctx->hashalg->blocklen; i++)
+        put_byte(ctx->h_outer, PAD_OUTER);
+
+    ctx->h_inner = ssh_hash_new(ctx->hashalg);
+    for (size_t i = 0; i < klen; i++)
+        put_byte(ctx->h_inner, PAD_INNER ^ kp[i]);
+    for (size_t i = klen; i < ctx->hashalg->blocklen; 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);
+
+    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;
+    ssh_hash *htmp;
+
+    /* Leave h_live in place, so that the SSH-2 BPP can continue
+     * regenerating test results from different-length prefixes of the
+     * packet */
+    htmp = ssh_hash_copy(ctx->h_live);
+    ssh_hash_final(htmp, ctx->digest);
+
+    htmp = ssh_hash_copy(ctx->h_outer);
+    put_data(htmp, ctx->digest, ctx->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, ctx->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, "" };
+const ssh2_macalg ssh_hmac_sha256 = {
+    hmac_new, hmac_free, hmac_key,
+    hmac_start, hmac_genresult, hmac_text_name,
+    "hmac-sha2-256", "[email protected]",
+    32, 32, &ssh_hmac_sha256_extra,
+};
+
+const struct hmac_extra ssh_hmac_md5_extra = { &ssh_md5, "" };
+const ssh2_macalg ssh_hmac_md5 = {
+    hmac_new, hmac_free, hmac_key,
+    hmac_start, hmac_genresult, hmac_text_name,
+    "hmac-md5", "[email protected]",
+    16, 16, &ssh_hmac_md5_extra,
+};
+
+const struct hmac_extra ssh_hmac_sha1_extra = { &ssh_sha1, "" };
+
+const ssh2_macalg ssh_hmac_sha1 = {
+    hmac_new, hmac_free, hmac_key,
+    hmac_start, hmac_genresult, hmac_text_name,
+    "hmac-sha1", "[email protected]",
+    20, 20, &ssh_hmac_sha1_extra,
+};
+
+const struct hmac_extra ssh_hmac_sha1_96_extra = { &ssh_sha1, "-96" };
+
+const ssh2_macalg ssh_hmac_sha1_96 = {
+    hmac_new, hmac_free, hmac_key,
+    hmac_start, hmac_genresult, hmac_text_name,
+    "hmac-sha1-96", "[email protected]",
+    12, 20, &ssh_hmac_sha1_96_extra,
+};
+
+const struct hmac_extra ssh_hmac_sha1_buggy_extra = {
+    &ssh_sha1, " (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, "-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,
+};

+ 1 - 111
source/putty/sshmd5.c

@@ -271,115 +271,5 @@ 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);
-}
-
-const ssh2_macalg ssh_hmac_md5 = {
-    hmacmd5_ssh2_new, hmacmd5_ssh2_free, hmacmd5_ssh2_setkey,
-    hmacmd5_start, hmacmd5_genresult,
-    "hmac-md5", "[email protected]",
-    16, 16,
-    "HMAC-MD5"
+    md5_new, md5_copy, md5_final, md5_free, 16, 64, "MD5"
 };

+ 1 - 0
source/putty/sshpubk.c

@@ -553,6 +553,7 @@ static bool read_blob(FILE *fp, int nlines, BinarySink *bs)
 	}
 	sfree(line);
     }
+    sfree(blob);
     return true;
 }
 

+ 1 - 84
source/putty/sshsh256.c

@@ -252,90 +252,7 @@ static void sha256_final(ssh_hash *hash, unsigned char *output)
 }
 
 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);
-}
-
-const ssh2_macalg ssh_hmac_sha256 = {
-    hmacsha256_new, hmacsha256_free, hmacsha256_key,
-    hmacsha256_start, hmacsha256_genresult,
-    "hmac-sha2-256", "[email protected]",
-    32, 32,
-    "HMAC-SHA-256"
+    sha256_new, sha256_copy, sha256_final, sha256_free, 32, 64, "SHA-256"
 };
 
 #ifdef COMPILER_SUPPORTS_SHA_NI

+ 3 - 3
source/putty/sshsh512.c

@@ -13,7 +13,7 @@
 
 typedef struct {
     uint64_t h[8];
-    unsigned char block[128];
+    unsigned char block[BLKSIZE];
     int blkused;
     uint64_t lenhi, lenlo;
     BinarySink_IMPLEMENTATION;
@@ -343,7 +343,7 @@ static void sha512_final(ssh_hash *hash, unsigned char *output)
 }
 
 const ssh_hashalg ssh_sha512 = {
-    sha512_new, sha512_copy, sha512_final, sha512_free, 64, "SHA-512"
+    sha512_new, sha512_copy, sha512_final, sha512_free, 64, BLKSIZE, "SHA-512"
 };
 
 static ssh_hash *sha384_new(const ssh_hashalg *alg)
@@ -363,5 +363,5 @@ static void sha384_final(ssh_hash *hash, unsigned char *output)
 }
 
 const ssh_hashalg ssh_sha384 = {
-    sha384_new, sha512_copy, sha384_final, sha512_free, 48, "SHA-384"
+    sha384_new, sha512_copy, sha384_final, sha512_free, 48, BLKSIZE, "SHA-384"
 };

+ 1 - 124
source/putty/sshsha.c

@@ -281,130 +281,7 @@ static void sha1_final(ssh_hash *hash, unsigned char *output)
 }
 
 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);
-}
-
-const ssh2_macalg ssh_hmac_sha1 = {
-    hmacsha1_new, hmacsha1_free, hmacsha1_key,
-    hmacsha1_start, hmacsha1_genresult,
-    "hmac-sha1", "[email protected]",
-    20, 20,
-    "HMAC-SHA1"
-};
-
-const ssh2_macalg ssh_hmac_sha1_96 = {
-    hmacsha1_new, hmacsha1_free, hmacsha1_key,
-    hmacsha1_start, hmacsha1_genresult,
-    "hmac-sha1-96", "[email protected]",
-    12, 20,
-    "HMAC-SHA1-96"
-};
-
-const ssh2_macalg ssh_hmac_sha1_buggy = {
-    hmacsha1_new, hmacsha1_free, hmacsha1_key,
-    hmacsha1_start, hmacsha1_genresult,
-    "hmac-sha1", NULL,
-    20, 16,
-    "bug-compatible HMAC-SHA1"
-};
-
-const ssh2_macalg ssh_hmac_sha1_96_buggy = {
-    hmacsha1_new, hmacsha1_free, hmacsha1_key,
-    hmacsha1_start, hmacsha1_genresult,
-    "hmac-sha1-96", NULL,
-    12, 16,
-    "bug-compatible HMAC-SHA1-96"
+    sha1_new, sha1_copy, sha1_final, sha1_free, 20, 64, "SHA-1"
 };
 
 #ifdef COMPILER_SUPPORTS_SHA_NI

+ 1 - 0
source/putty/windows/winhandl.c

@@ -689,6 +689,7 @@ void handle_got_event(HANDLE event)
 	    h->u.o.sentdata(h, -h->u.o.writeerr);
 	} else {
 	    bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten);
+            noise_ultralight(h->u.o.lenwritten);
 	    h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data));
 	    handle_try_output(&h->u.o);
 	}