return 1;
}
random_add_heavynoise(entropy, bits / 8);
- memset(entropy, 0, bits/8);
+ smemclr(entropy, bits/8);
sfree(entropy);
if (keytype == DSA) {
return 1;
}
if (passphrase) {
- memset(passphrase, 0, strlen(passphrase));
+ smemclr(passphrase, strlen(passphrase));
sfree(passphrase);
}
passphrase = dupstr(p->prompts[0]->result);
}
if (passphrase) {
- memset(passphrase, 0, strlen(passphrase));
+ smemclr(passphrase, strlen(passphrase));
sfree(passphrase);
}
int pri;
if (cmdline_password) {
- memset(cmdline_password, 0, strlen(cmdline_password));
+ smemclr(cmdline_password, strlen(cmdline_password));
sfree(cmdline_password);
cmdline_password = NULL;
}
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;
/* 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));
}
}
errmsg = "unrecognised key type";
goto error;
}
- memset(line, 0, strlen(line));
+ smemclr(line, strlen(line));
sfree(line);
line = NULL;
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;
}
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;
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;
}
aes_free_context(ctx);
}
- memset(&md5c, 0, sizeof(md5c));
- memset(keybuf, 0, sizeof(keybuf));
+ smemclr(&md5c, sizeof(md5c));
+ smemclr(keybuf, sizeof(keybuf));
}
/*
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;
*/
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));
}
/*
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;
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;
len += line2len - 1;
assert(!line[len]);
- memset(line2, 0, strlen(line2));
+ smemclr(line2, strlen(line2));
sfree(line2);
line2 = NULL;
}
p++;
}
}
- memset(line, 0, strlen(line));
+ smemclr(line, strlen(line));
sfree(line);
line = NULL;
}
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;
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;
}
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
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;
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));
}
/*
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;
*/
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;
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);
void burnstr(char *string) /* sfree(str), only clear it first */
{
if (string) {
- memset(string, 0, strlen(string));
+ smemclr(string, strlen(string));
sfree(string);
}
}
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
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.
ret = loadrsakey(s->keyfile, &s->key, passphrase,
&error);
if (passphrase) {
- memset(passphrase, 0, strlen(passphrase));
+ smemclr(passphrase, strlen(passphrase));
sfree(passphrase);
}
if (ret == 1) {
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",
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);
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) {
*/
/* 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,
* 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 =
* 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 {
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)
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 = {
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);
}
/*
* 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);
}
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)
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,
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,
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)
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)
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)
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.
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.
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)
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 */
}
/*
ret = 1;
end:
- memset(buf, 0, sizeof(buf)); /* burn the evidence */
+ smemclr(buf, sizeof(buf)); /* burn the evidence */
return ret;
}
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 */
}
/*
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);
}
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) {
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);
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;
lenbuf[0] = bignum_byte(b, len);
SHA512_Bytes(s, lenbuf, 1);
}
- memset(lenbuf, 0, sizeof(lenbuf));
+ smemclr(lenbuf, sizeof(lenbuf));
}
/*
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)
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
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;
* 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;
{
while (count234(passphrases) > 0) {
char *pp = index234(passphrases, 0);
- memset(pp, 0, strlen(pp));
+ smemclr(pp, strlen(pp));
delpos234(passphrases, 0);
free(pp);
}
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 ... */
#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:
*
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);
done:
fclose(authfp);
- memset(buf, 0, 65537 * 4);
+ smemclr(buf, 65537 * 4);
sfree(buf);
sfree(ourhostname);
}