Introduce a new utility function smemclr(), which memsets things to
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 22 Jul 2012 19:51:50 +0000 (19:51 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sun, 22 Jul 2012 19:51:50 +0000 (19:51 +0000)
zero but does it in such a way that over-clever compilers hopefully
won't helpfully optimise the call away if you do it just before
freeing something or letting it go out of scope. Use this for
(hopefully) every memset whose job is to destroy sensitive data that
might otherwise be left lying around in the process's memory.

git-svn-id: svn://svn.tartarus.org/sgt/putty@9586 cda61777-01e9-0310-a592-d414129be87e

21 files changed:
cmdgen.c
cmdline.c
import.c
misc.c
putty.h
ssh.c
sshaes.c
ssharcf.c
sshbn.c
sshdes.c
sshdss.c
sshmd5.c
sshpubk.c
sshrsa.c
sshsha.c
unix/gtkwin.c
windows/winmisc.c
windows/winpgen.c
windows/winpgnt.c
windows/winstuff.h
x11fwd.c

index 50f99f7..5b0e54d 100644 (file)
--- a/cmdgen.c
+++ b/cmdgen.c
@@ -667,7 +667,7 @@ int main(int argc, char **argv)
            return 1;
        }
        random_add_heavynoise(entropy, bits / 8);
-       memset(entropy, 0, bits/8);
+       smemclr(entropy, bits/8);
        sfree(entropy);
 
        if (keytype == DSA) {
@@ -860,7 +860,7 @@ int main(int argc, char **argv)
                return 1;
            }
            if (passphrase) {
-               memset(passphrase, 0, strlen(passphrase));
+               smemclr(passphrase, strlen(passphrase));
                sfree(passphrase);
            }
            passphrase = dupstr(p->prompts[0]->result);
@@ -1035,7 +1035,7 @@ int main(int argc, char **argv)
     }
 
     if (passphrase) {
-       memset(passphrase, 0, strlen(passphrase));
+       smemclr(passphrase, strlen(passphrase));
        sfree(passphrase);
     }
 
index 2c3b7ce..a4c9160 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -63,7 +63,7 @@ void cmdline_cleanup(void)
     int pri;
 
     if (cmdline_password) {
-       memset(cmdline_password, 0, strlen(cmdline_password));
+       smemclr(cmdline_password, strlen(cmdline_password));
        sfree(cmdline_password);
        cmdline_password = NULL;
     }
@@ -106,7 +106,7 @@ int cmdline_get_passwd_input(prompts_t *p, unsigned char *in, int inlen) {
        return 0;
 
     prompt_set_result(p->prompts[0], cmdline_password);
-    memset(cmdline_password, 0, strlen(cmdline_password));
+    smemclr(cmdline_password, strlen(cmdline_password));
     sfree(cmdline_password);
     cmdline_password = NULL;
     tried_once = 1;
@@ -368,7 +368,7 @@ int cmdline_process_param(char *p, char *value, int need_save, Conf *conf)
            /* Assuming that `value' is directly from argv, make a good faith
             * attempt to trample it, to stop it showing up in `ps' output
             * on Unix-like systems. Not guaranteed, of course. */
-           memset(value, 0, strlen(value));
+           smemclr(value, strlen(value));
        }
     }
 
index 55e3be2..05cfdc1 100644 (file)
--- a/import.c
+++ b/import.c
@@ -358,7 +358,7 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
        errmsg = "unrecognised key type";
        goto error;
     }
-    memset(line, 0, strlen(line));
+    smemclr(line, strlen(line));
     sfree(line);
     line = NULL;
 
@@ -442,13 +442,13 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
                     memcpy(ret->keyblob + ret->keyblob_len, out, len);
                     ret->keyblob_len += len;
 
-                    memset(out, 0, sizeof(out));
+                    smemclr(out, sizeof(out));
                 }
 
                p++;
            }
        }
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
@@ -463,23 +463,23 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
        goto error;
     }
 
-    memset(base64_bit, 0, sizeof(base64_bit));
+    smemclr(base64_bit, sizeof(base64_bit));
     if (errmsg_p) *errmsg_p = NULL;
     return ret;
 
     error:
     if (line) {
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
-    memset(base64_bit, 0, sizeof(base64_bit));
+    smemclr(base64_bit, sizeof(base64_bit));
     if (ret) {
        if (ret->keyblob) {
-            memset(ret->keyblob, 0, ret->keyblob_size);
+            smemclr(ret->keyblob, ret->keyblob_size);
             sfree(ret->keyblob);
         }
-        memset(ret, 0, sizeof(*ret));
+        smemclr(ret, sizeof(*ret));
        sfree(ret);
     }
     if (errmsg_p) *errmsg_p = errmsg;
@@ -494,9 +494,9 @@ int openssh_encrypted(const Filename *filename)
     if (!key)
        return 0;
     ret = key->encrypted;
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     return ret;
 }
@@ -564,8 +564,8 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
            aes_free_context(ctx);
        }
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
     }
 
     /*
@@ -698,12 +698,12 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
 
     error:
     if (blob) {
-        memset(blob, 0, blobsize);
+        smemclr(blob, blobsize);
         sfree(blob);
     }
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     if (errmsg_p) *errmsg_p = errmsg;
     return retval;
@@ -911,8 +911,8 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
         */
        des3_encrypt_pubkey_ossh(keybuf, iv, outblob, outlen);
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
     }
 
     /*
@@ -936,19 +936,19 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
 
     error:
     if (outblob) {
-        memset(outblob, 0, outlen);
+        smemclr(outblob, outlen);
         sfree(outblob);
     }
     if (spareblob) {
-        memset(spareblob, 0, sparelen);
+        smemclr(spareblob, sparelen);
         sfree(spareblob);
     }
     if (privblob) {
-        memset(privblob, 0, privlen);
+        smemclr(privblob, privlen);
         sfree(privblob);
     }
     if (pubblob) {
-        memset(pubblob, 0, publen);
+        smemclr(pubblob, publen);
         sfree(pubblob);
     }
     return ret;
@@ -1067,7 +1067,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
        errmsg = "file does not begin with ssh.com key header";
        goto error;
     }
-    memset(line, 0, strlen(line));
+    smemclr(line, strlen(line));
     sfree(line);
     line = NULL;
 
@@ -1112,7 +1112,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
                len += line2len - 1;
                assert(!line[len]);
 
-               memset(line2, 0, strlen(line2));
+               smemclr(line2, strlen(line2));
                sfree(line2);
                line2 = NULL;
             }
@@ -1158,7 +1158,7 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
                p++;
            }
        }
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
@@ -1173,16 +1173,16 @@ static struct sshcom_key *load_sshcom_key(const Filename *filename,
 
     error:
     if (line) {
-       memset(line, 0, strlen(line));
+       smemclr(line, strlen(line));
        sfree(line);
        line = NULL;
     }
     if (ret) {
        if (ret->keyblob) {
-            memset(ret->keyblob, 0, ret->keyblob_size);
+            smemclr(ret->keyblob, ret->keyblob_size);
             sfree(ret->keyblob);
         }
-        memset(ret, 0, sizeof(*ret));
+        smemclr(ret, sizeof(*ret));
        sfree(ret);
     }
     if (errmsg_p) *errmsg_p = errmsg;
@@ -1222,9 +1222,9 @@ int sshcom_encrypted(const Filename *filename, char **comment)
 
     done:
     *comment = dupstr(key->comment);
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     return answer;
 }
@@ -1390,8 +1390,8 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
        des3_decrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
                                 cipherlen);
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
 
         /*
          * Hereafter we return WRONG_PASSPHRASE for any parsing
@@ -1494,12 +1494,12 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
 
     error:
     if (blob) {
-        memset(blob, 0, blobsize);
+        smemclr(blob, blobsize);
         sfree(blob);
     }
-    memset(key->keyblob, 0, key->keyblob_size);
+    smemclr(key->keyblob, key->keyblob_size);
     sfree(key->keyblob);
-    memset(key, 0, sizeof(*key));
+    smemclr(key, sizeof(*key));
     sfree(key);
     if (errmsg_p) *errmsg_p = errmsg;
     return ret;
@@ -1664,8 +1664,8 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
        des3_encrypt_pubkey_ossh(keybuf, iv, (unsigned char *)ciphertext,
                                 cipherlen);
 
-        memset(&md5c, 0, sizeof(md5c));
-        memset(keybuf, 0, sizeof(keybuf));
+        smemclr(&md5c, sizeof(md5c));
+        smemclr(keybuf, sizeof(keybuf));
     }
 
     /*
@@ -1700,15 +1700,15 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
 
     error:
     if (outblob) {
-        memset(outblob, 0, outlen);
+        smemclr(outblob, outlen);
         sfree(outblob);
     }
     if (privblob) {
-        memset(privblob, 0, privlen);
+        smemclr(privblob, privlen);
         sfree(privblob);
     }
     if (pubblob) {
-        memset(pubblob, 0, publen);
+        smemclr(pubblob, publen);
         sfree(pubblob);
     }
     return ret;
diff --git a/misc.c b/misc.c
index 636ca9f..76e5fab 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -124,7 +124,7 @@ void prompt_ensure_result_size(prompt_t *pr, int newlen)
          */
         newbuf = snewn(newlen, char);
         memcpy(newbuf, pr->result, pr->resultsize);
-        memset(pr->result, '\0', pr->resultsize);
+        smemclr(pr->result, pr->resultsize);
         sfree(pr->result);
         pr->result = newbuf;
         pr->resultsize = newlen;
@@ -140,7 +140,7 @@ void free_prompts(prompts_t *p)
     size_t i;
     for (i=0; i < p->n_prompts; i++) {
        prompt_t *pr = p->prompts[i];
-       memset(pr->result, 0, pr->resultsize); /* burn the evidence */
+       smemclr(pr->result, pr->resultsize); /* burn the evidence */
        sfree(pr->result);
        sfree(pr->prompt);
        sfree(pr);
@@ -203,7 +203,7 @@ char *dupcat(const char *s1, ...)
 void burnstr(char *string)             /* sfree(str), only clear it first */
 {
     if (string) {
-        memset(string, 0, strlen(string));
+        smemclr(string, strlen(string));
         sfree(string);
     }
 }
@@ -685,3 +685,43 @@ char const *conf_dest(Conf *conf)
     else
        return conf_get_str(conf, CONF_host);
 }
+
+#ifndef PLATFORM_HAS_SMEMCLR
+/*
+ * Securely wipe memory.
+ *
+ * The actual wiping is no different from what memset would do: the
+ * point of 'securely' is to try to be sure over-clever compilers
+ * won't optimise away memsets on variables that are about to be freed
+ * or go out of scope. See
+ * https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/771-BSI.html
+ *
+ * Some platforms (e.g. Windows) may provide their own version of this
+ * function.
+ */
+void smemclr(void *b, size_t n) {
+    volatile char *vp;
+
+    if (b && n > 0) {
+        /*
+         * Zero out the memory.
+         */
+        memset(b, 0, n);
+
+        /*
+         * Perform a volatile access to the object, forcing the
+         * compiler to admit that the previous memset was important.
+         *
+         * This while loop should in practice run for zero iterations
+         * (since we know we just zeroed the object out), but in
+         * theory (as far as the compiler knows) it might range over
+         * the whole object. (If we had just written, say, '*vp =
+         * *vp;', a compiler could in principle have 'helpfully'
+         * optimised the memset into only zeroing out the first byte.
+         * This should be robust.)
+         */
+        vp = b;
+        while (*vp) vp++;
+    }
+}
+#endif
diff --git a/putty.h b/putty.h
index dcc80db..b32b0fa 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -1291,6 +1291,7 @@ int filename_serialise(const Filename *f, void *data);
 Filename *filename_deserialise(void *data, int maxsize, int *used);
 char *get_username(void);             /* return value needs freeing */
 char *get_random_data(int bytes);      /* used in cmdgen.c */
+void smemclr(void *b, size_t len);
 
 /*
  * Exports and imports from timing.c.
diff --git a/ssh.c b/ssh.c
index ef503bf..1f1a265 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -3849,7 +3849,7 @@ static int do_ssh1_login(Ssh ssh, unsigned char *in, int inlen,
                ret = loadrsakey(s->keyfile, &s->key, passphrase,
                                 &error);
                if (passphrase) {
-                   memset(passphrase, 0, strlen(passphrase));
+                   smemclr(passphrase, strlen(passphrase));
                    sfree(passphrase);
                }
                if (ret == 1) {
@@ -6294,7 +6294,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        assert(ssh->csmac->len <=
               ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
        ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);
-       memset(keyspace, 0, sizeof(keyspace));
+       smemclr(keyspace, sizeof(keyspace));
     }
 
     logeventf(ssh, "Initialised %.200s client->server encryption",
@@ -6360,7 +6360,7 @@ static int do_ssh2_transport(Ssh ssh, void *vin, int inlen,
        assert(ssh->scmac->len <=
               ssh->kex->hash->hlen * SSH2_MKKEY_ITERS);
        ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);
-       memset(keyspace, 0, sizeof(keyspace));
+       smemclr(keyspace, sizeof(keyspace));
     }
     logeventf(ssh, "Initialised %.200s server->client encryption",
              ssh->sccipher->text_name);
@@ -8151,7 +8151,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
                    key = ssh2_load_userkey(s->keyfile, passphrase, &error);
                    if (passphrase) {
                        /* burn the evidence */
-                       memset(passphrase, 0, strlen(passphrase));
+                       smemclr(passphrase, strlen(passphrase));
                        sfree(passphrase);
                    }
                    if (key == SSH2_WRONG_PASSPHRASE || key == NULL) {
@@ -8730,7 +8730,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
                             */
                            /* burn the evidence */
                            free_prompts(s->cur_prompt);
-                           memset(s->password, 0, strlen(s->password));
+                           smemclr(s->password, strlen(s->password));
                            sfree(s->password);
                            ssh_disconnect(ssh, NULL, "Unable to authenticate",
                                           SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER,
@@ -8746,7 +8746,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
                         * re-enter it if they louse up the new password.)
                         */
                        if (s->cur_prompt->prompts[0]->result[0]) {
-                           memset(s->password, 0, strlen(s->password));
+                           smemclr(s->password, strlen(s->password));
                                /* burn the evidence */
                            sfree(s->password);
                            s->password =
@@ -8813,7 +8813,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
                 * We don't need the old password any more, in any
                 * case. Burn the evidence.
                 */
-               memset(s->password, 0, strlen(s->password));
+               smemclr(s->password, strlen(s->password));
                sfree(s->password);
 
            } else {
index 2800e02..97935b7 100644 (file)
--- a/sshaes.c
+++ b/sshaes.c
@@ -1157,7 +1157,7 @@ void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
     aes_setup(&ctx, 16, key, 32);
     memset(ctx.iv, 0, sizeof(ctx.iv));
     aes_encrypt_cbc(blk, len, &ctx);
-    memset(&ctx, 0, sizeof(ctx));
+    smemclr(&ctx, sizeof(ctx));
 }
 
 void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
@@ -1166,7 +1166,7 @@ void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
     aes_setup(&ctx, 16, key, 32);
     memset(ctx.iv, 0, sizeof(ctx.iv));
     aes_decrypt_cbc(blk, len, &ctx);
-    memset(&ctx, 0, sizeof(ctx));
+    smemclr(&ctx, sizeof(ctx));
 }
 
 static const struct ssh2_cipher ssh_aes128_ctr = {
index 6bfbd89..06f235c 100644 (file)
--- a/ssharcf.c
+++ b/ssharcf.c
@@ -75,7 +75,7 @@ static void arcfour_stir(ArcfourContext *ctx)
     unsigned char *junk = snewn(1536, unsigned char);
     memset(junk, 0, 1536);
     arcfour_block(ctx, junk, 1536);
-    memset(junk, 0, 1536);
+    smemclr(junk, 1536);
     sfree(junk);
 }
 
diff --git a/sshbn.c b/sshbn.c
index 484c423..999817d 100644 (file)
--- a/sshbn.c
+++ b/sshbn.c
@@ -148,7 +148,7 @@ void freebn(Bignum b)
     /*
      * Burn the evidence, just in case.
      */
-    memset(b, 0, sizeof(b[0]) * (b[0] + 1));
+    smemclr(b, sizeof(b[0]) * (b[0] + 1));
     sfree(b);
 }
 
index b12a91d..03d2b3a 100644 (file)
--- a/sshdes.c
+++ b/sshdes.c
@@ -858,7 +858,7 @@ void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
     des_key_setup(GET_32BIT_MSB_FIRST(key),
                  GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]);
     des_3cbc_decrypt(blk, len, ourkeys);
-    memset(ourkeys, 0, sizeof(ourkeys));
+    smemclr(ourkeys, sizeof(ourkeys));
 }
 
 void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
@@ -871,7 +871,7 @@ void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
     des_key_setup(GET_32BIT_MSB_FIRST(key),
                  GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]);
     des_3cbc_encrypt(blk, len, ourkeys);
-    memset(ourkeys, 0, sizeof(ourkeys));
+    smemclr(ourkeys, sizeof(ourkeys));
 }
 
 void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
@@ -887,7 +887,7 @@ void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
     ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv);
     ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4);
     des_cbc3_decrypt(blk, len, ourkeys);
-    memset(ourkeys, 0, sizeof(ourkeys));
+    smemclr(ourkeys, sizeof(ourkeys));
 }
 
 void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
@@ -903,7 +903,7 @@ void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
     ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv);
     ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4);
     des_cbc3_encrypt(blk, len, ourkeys);
-    memset(ourkeys, 0, sizeof(ourkeys));
+    smemclr(ourkeys, sizeof(ourkeys));
 }
 
 static void des_keysetup_xdmauth(unsigned char *keydata, DESContext *dc)
index 7c95d11..6cf5830 100644 (file)
--- a/sshdss.c
+++ b/sshdss.c
@@ -20,7 +20,7 @@ static void sha_mpint(SHA_State * s, Bignum b)
        lenbuf[0] = bignum_byte(b, len);
        SHA_Bytes(s, lenbuf, 1);
     }
-    memset(lenbuf, 0, sizeof(lenbuf));
+    smemclr(lenbuf, sizeof(lenbuf));
 }
 
 static void sha512_mpint(SHA512_State * s, Bignum b)
@@ -34,7 +34,7 @@ static void sha512_mpint(SHA512_State * s, Bignum b)
        lenbuf[0] = bignum_byte(b, len);
        SHA512_Bytes(s, lenbuf, 1);
     }
-    memset(lenbuf, 0, sizeof(lenbuf));
+    smemclr(lenbuf, sizeof(lenbuf));
 }
 
 static void getstring(char **data, int *datalen, char **p, int *length)
@@ -575,7 +575,7 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
     SHA512_Bytes(&ss, digest, sizeof(digest));
     SHA512_Final(&ss, digest512);
 
-    memset(&ss, 0, sizeof(ss));
+    smemclr(&ss, sizeof(ss));
 
     /*
      * Now convert the result into a bignum, and reduce it mod q.
@@ -584,7 +584,7 @@ static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
     k = bigmod(proto_k, dss->q);
     freebn(proto_k);
 
-    memset(digest512, 0, sizeof(digest512));
+    smemclr(digest512, sizeof(digest512));
 
     /*
      * Now we have k, so just go ahead and compute the signature.
index 7112d40..e5187a6 100644 (file)
--- a/sshmd5.c
+++ b/sshmd5.c
@@ -249,7 +249,7 @@ void hmacmd5_key(void *handle, void const *keyv, int len)
     MD5Init(&keys[1]);
     MD5Update(&keys[1], foo, 64);
 
-    memset(foo, 0, 64);                       /* burn the evidence */
+    smemclr(foo, 64);                 /* burn the evidence */
 }
 
 static void hmacmd5_key_16(void *handle, unsigned char *key)
index 88ff179..c29d8a5 100644 (file)
--- a/sshpubk.c
+++ b/sshpubk.c
@@ -108,7 +108,7 @@ static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
        MD5Final(keybuf, &md5c);
        des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
-       memset(keybuf, 0, sizeof(keybuf));      /* burn the evidence */
+       smemclr(keybuf, sizeof(keybuf));        /* burn the evidence */
     }
 
     /*
@@ -150,7 +150,7 @@ static int loadrsakey_main(FILE * fp, struct RSAKey *key, int pub_only,
        ret = 1;
 
   end:
-    memset(buf, 0, sizeof(buf));       /* burn the evidence */
+    smemclr(buf, sizeof(buf));       /* burn the evidence */
     return ret;
 }
 
@@ -358,7 +358,7 @@ int saversakey(const Filename *filename, struct RSAKey *key, char *passphrase)
        MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));
        MD5Final(keybuf, &md5c);
        des3_encrypt_pubkey(keybuf, estart, p - estart);
-       memset(keybuf, 0, sizeof(keybuf));      /* burn the evidence */
+       smemclr(keybuf, sizeof(keybuf));        /* burn the evidence */
     }
 
     /*
@@ -794,14 +794,14 @@ struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
 
            hmac_sha1_simple(mackey, 20, macdata, maclen, binary);
 
-           memset(mackey, 0, sizeof(mackey));
-           memset(&s, 0, sizeof(s));
+           smemclr(mackey, sizeof(mackey));
+           smemclr(&s, sizeof(s));
        } else {
            SHA_Simple(macdata, maclen, binary);
        }
 
        if (free_macdata) {
-           memset(macdata, 0, maclen);
+           smemclr(macdata, maclen);
            sfree(macdata);
        }
 
@@ -1116,10 +1116,10 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
            SHA_Bytes(&s, passphrase, strlen(passphrase));
        SHA_Final(&s, mackey);
        hmac_sha1_simple(mackey, 20, macdata, maclen, priv_mac);
-       memset(macdata, 0, maclen);
+       smemclr(macdata, maclen);
        sfree(macdata);
-       memset(mackey, 0, sizeof(mackey));
-       memset(&s, 0, sizeof(s));
+       smemclr(mackey, sizeof(mackey));
+       smemclr(&s, sizeof(s));
     }
 
     if (passphrase) {
@@ -1139,8 +1139,8 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
        aes256_encrypt_pubkey(key, priv_blob_encrypted,
                              priv_encrypted_len);
 
-       memset(key, 0, sizeof(key));
-       memset(&s, 0, sizeof(s));
+       smemclr(key, sizeof(key));
+       smemclr(&s, sizeof(s));
     }
 
     fp = f_open(filename, "w", TRUE);
@@ -1160,7 +1160,7 @@ int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
     fclose(fp);
 
     sfree(pub_blob);
-    memset(priv_blob, 0, priv_blob_len);
+    smemclr(priv_blob, priv_blob_len);
     sfree(priv_blob);
     sfree(priv_blob_encrypted);
     return 1;
index 0c1b2ef..77a6bb2 100644 (file)
--- a/sshrsa.c
+++ b/sshrsa.c
@@ -110,7 +110,7 @@ static void sha512_mpint(SHA512_State * s, Bignum b)
        lenbuf[0] = bignum_byte(b, len);
        SHA512_Bytes(s, lenbuf, 1);
     }
-    memset(lenbuf, 0, sizeof(lenbuf));
+    smemclr(lenbuf, sizeof(lenbuf));
 }
 
 /*
index cbe9d78..3011351 100644 (file)
--- a/sshsha.c
+++ b/sshsha.c
@@ -253,7 +253,7 @@ static void sha1_key_internal(void *handle, unsigned char *key, int len)
     SHA_Init(&keys[1]);
     SHA_Bytes(&keys[1], foo, 64);
 
-    memset(foo, 0, 64);                       /* burn the evidence */
+    smemclr(foo, 64);                 /* burn the evidence */
 }
 
 static void sha1_key(void *handle, unsigned char *key)
index 03f2855..241aa6b 100644 (file)
@@ -3582,7 +3582,7 @@ int pt_main(int argc, char **argv)
     if (argc > 1 && !strncmp(argv[1], "---", 3)) {
        read_dupsession_data(inst, inst->conf, argv[1]);
        /* Splatter this argument so it doesn't clutter a ps listing */
-       memset(argv[1], 0, strlen(argv[1]));
+       smemclr(argv[1], strlen(argv[1]));
     } else {
        /* By default, we bring up the config dialog, rather than launching
         * a session. This gets set to TRUE if something happens to change
index f54e8a4..2166f45 100644 (file)
@@ -68,6 +68,14 @@ Filename *filename_deserialise(void *vdata, int maxsize, int *used)
     return filename_from_str(data);
 }
 
+/*
+ * Windows implementation of smemclr (see misc.c) using SecureZeroMemory.
+ */
+void smemclr(void *b, size_t n) {
+    if (b && n > 0)
+        SecureZeroMemory(b, n);
+}
+
 char *get_username(void)
 {
     DWORD namelen;
index c83d0d2..ffbeb1a 100644 (file)
@@ -958,7 +958,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
                 * Seed the entropy pool
                 */
                random_add_heavynoise(state->entropy, state->entropy_size);
-               memset(state->entropy, 0, state->entropy_size);
+               smemclr(state->entropy, state->entropy_size);
                sfree(state->entropy);
                state->collecting_entropy = FALSE;
 
index 291593e..21a69cc 100644 (file)
@@ -174,7 +174,7 @@ static void forget_passphrases(void)
 {
     while (count234(passphrases) > 0) {
        char *pp = index234(passphrases, 0);
-       memset(pp, 0, strlen(pp));
+       smemclr(pp, strlen(pp));
        delpos234(passphrases, 0);
        free(pp);
     }
@@ -968,7 +968,7 @@ static void answer_msg(void *msg)
            MD5Init(&md5c);
            MD5Update(&md5c, response_source, 48);
            MD5Final(response_md5, &md5c);
-           memset(response_source, 0, 48);     /* burn the evidence */
+           smemclr(response_source, 48);       /* burn the evidence */
            freebn(response);          /* and that evidence */
            freebn(challenge);         /* yes, and that evidence */
            freebn(reqkey.exponent);   /* and free some memory ... */
index df59631..d81515d 100644 (file)
@@ -75,6 +75,8 @@ struct FontSpec *fontspec_new(const char *name,
 #define BOXRESULT (DLGWINDOWEXTRA + sizeof(LONG_PTR))
 #define DF_END 0x0001
 
+#define PLATFORM_HAS_SMEMCLR /* inhibit cross-platform one in misc.c */
+
 /*
  * Dynamically linked functions. These come in two flavours:
  *
index 5b4f76c..1e04f54 100644 (file)
--- a/x11fwd.c
+++ b/x11fwd.c
@@ -264,10 +264,10 @@ void x11_free_display(struct X11Display *disp)
     sfree(disp->hostname);
     sfree(disp->unixsocketpath);
     if (disp->localauthdata)
-       memset(disp->localauthdata, 0, disp->localauthdatalen);
+       smemclr(disp->localauthdata, disp->localauthdatalen);
     sfree(disp->localauthdata);
     if (disp->remoteauthdata)
-       memset(disp->remoteauthdata, 0, disp->remoteauthdatalen);
+       smemclr(disp->remoteauthdata, disp->remoteauthdatalen);
     sfree(disp->remoteauthdata);
     sfree(disp->remoteauthprotoname);
     sfree(disp->remoteauthdatastring);
@@ -487,7 +487,7 @@ void x11_get_auth_from_authfile(struct X11Display *disp,
 
     done:
     fclose(authfp);
-    memset(buf, 0, 65537 * 4);
+    smemclr(buf, 65537 * 4);
     sfree(buf);
     sfree(ourhostname);
 }