From ee5c14220a9e2d3aeee34fa23db2e4ea1dcd32fb Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 13 May 2002 16:37:11 +0000 Subject: [PATCH] Be more careful about destroying sensitive data after private key load/store/import operations. git-svn-id: svn://svn.tartarus.org/sgt/putty@1673 cda61777-01e9-0310-a592-d414129be87e --- import.c | 105 ++++++++++++++++++++++++++++++++++++++++++--------------------- sshaes.c | 2 ++ sshdes.c | 4 +++ 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/import.c b/import.c index 19deb8c0..930b6c58 100644 --- a/import.c +++ b/import.c @@ -213,6 +213,8 @@ struct openssh_key *load_openssh_key(char *filename) char buffer[256]; char *errmsg, *p; int headers_done; + char base64_bit[4]; + int base64_chars = 0; ret = smalloc(sizeof(*ret)); ret->keyblob = NULL; @@ -287,32 +289,33 @@ struct openssh_key *load_openssh_key(char *filename) headers_done = 1; p = buffer; - while (isbase64(p[0]) && isbase64(p[1]) && - isbase64(p[2]) && isbase64(p[3])) { - int len; - unsigned char out[3]; + while (isbase64(*p)) { + base64_bit[base64_chars++] = *p; + if (base64_chars == 4) { + unsigned char out[3]; + int len; - len = base64_decode_atom(p, out); + base64_chars = 0; - if (len <= 0) { - errmsg = "Invalid base64 encoding"; - goto error; - } + len = base64_decode_atom(base64_bit, out); - if (ret->keyblob_len + len > ret->keyblob_size) { - ret->keyblob_size = ret->keyblob_len + len + 256; - ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size); - } + if (len <= 0) { + errmsg = "Invalid base64 encoding"; + goto error; + } + + if (ret->keyblob_len + len > ret->keyblob_size) { + ret->keyblob_size = ret->keyblob_len + len + 256; + ret->keyblob = srealloc(ret->keyblob, ret->keyblob_size); + } - memcpy(ret->keyblob + ret->keyblob_len, out, len); - ret->keyblob_len += len; + memcpy(ret->keyblob + ret->keyblob_len, out, len); + ret->keyblob_len += len; - p += 4; - } + memset(out, 0, sizeof(out)); + } - if (isbase64(*p)) { - errmsg = "base64 characters left at end of line"; - goto error; + p++; } } } @@ -327,11 +330,19 @@ struct openssh_key *load_openssh_key(char *filename) goto error; } + memset(buffer, 0, sizeof(buffer)); + memset(base64_bit, 0, sizeof(base64_bit)); return ret; error: + memset(buffer, 0, sizeof(buffer)); + memset(base64_bit, 0, sizeof(base64_bit)); if (ret) { - if (ret->keyblob) sfree(ret->keyblob); + if (ret->keyblob) { + memset(ret->keyblob, 0, ret->keyblob_size); + sfree(ret->keyblob); + } + memset(&ret, 0, sizeof(ret)); sfree(ret); } return NULL; @@ -345,7 +356,9 @@ int openssh_encrypted(char *filename) if (!key) return 0; ret = key->encrypted; + memset(key->keyblob, 0, key->keyblob_size); sfree(key->keyblob); + memset(&key, 0, sizeof(key)); sfree(key); return ret; } @@ -360,7 +373,7 @@ struct ssh2_userkey *openssh_read(char *filename, char *passphrase) struct ssh2_userkey *retval = NULL; char *errmsg; unsigned char *blob; - int blobptr, privptr; + int blobsize, blobptr, privptr; char *modptr; int modlen; @@ -395,6 +408,9 @@ struct ssh2_userkey *openssh_read(char *filename, char *passphrase) */ des3_decrypt_pubkey_ossh(keybuf, key->iv, key->keyblob, key->keyblob_len); + + memset(&md5c, 0, sizeof(md5c)); + memset(keybuf, 0, sizeof(keybuf)); } /* @@ -435,7 +451,8 @@ struct ssh2_userkey *openssh_read(char *filename, char *passphrase) /* * Space to create key blob in. */ - blob = smalloc(256+key->keyblob_len); + blobsize = 256+key->keyblob_len; + blob = smalloc(blobsize); PUT_32BIT(blob, 7); if (key->type == OSSH_DSA) memcpy(blob+4, "ssh-dss", 7); @@ -518,14 +535,17 @@ struct ssh2_userkey *openssh_read(char *filename, char *passphrase) } retkey->comment = dupstr("imported-openssh-key"); - if (blob) sfree(blob); - sfree(key->keyblob); - sfree(key); - return retkey; + errmsg = NULL; /* no error */ + retval = retkey; error: - if (blob) sfree(blob); + if (blob) { + memset(blob, 0, blobsize); + sfree(blob); + } + memset(key->keyblob, 0, key->keyblob_size); sfree(key->keyblob); + memset(&key, 0, sizeof(key)); sfree(key); return retval; } @@ -718,7 +738,11 @@ struct sshcom_key *load_sshcom_key(char *filename) error: if (ret) { - if (ret->keyblob) sfree(ret->keyblob); + if (ret->keyblob) { + memset(ret->keyblob, 0, ret->keyblob_size); + sfree(ret->keyblob); + } + memset(&ret, 0, sizeof(ret)); sfree(ret); } return NULL; @@ -757,7 +781,9 @@ int sshcom_encrypted(char *filename, char **comment) done: *comment = dupstr(key->comment); + memset(key->keyblob, 0, key->keyblob_size); sfree(key->keyblob); + memset(&key, 0, sizeof(key)); sfree(key); return answer; } @@ -802,7 +828,7 @@ struct ssh2_userkey *sshcom_read(char *filename, char *passphrase) struct ssh2_userkey *ret = NULL, *retkey; const struct ssh_signkey *alg; unsigned char *blob = NULL; - int publen, privlen; + int blobsize, publen, privlen; if (!key) return NULL; @@ -902,12 +928,17 @@ struct ssh2_userkey *sshcom_read(char *filename, char *passphrase) /* * Now decrypt the key blob. */ - memset(iv, 0, 8); + memset(iv, 0, sizeof(iv)); des3_decrypt_pubkey_ossh(keybuf, iv, ciphertext, cipherlen); + memset(&md5c, 0, sizeof(md5c)); + memset(keybuf, 0, sizeof(keybuf)); + /* * Hereafter we return WRONG_PASSPHRASE for any parsing - * error. (But not if we haven't just tried to decrypt it!) + * error. (But only if we've just tried to decrypt it! + * Returning WRONG_PASSPHRASE for an unencrypted key is + * automatic doom.) */ if (encrypted) ret = SSH2_WRONG_PASSPHRASE; @@ -929,7 +960,8 @@ struct ssh2_userkey *sshcom_read(char *filename, char *passphrase) * construct public and private blobs in our own format, and * end up feeding them to alg->createkey(). */ - blob = smalloc(cipherlen + 256); + blobsize = cipherlen + 256; + blob = smalloc(blobsize); privlen = 0; if (type == RSA) { struct mpint_pos n, e, d, u, p, q; @@ -1001,8 +1033,13 @@ struct ssh2_userkey *sshcom_read(char *filename, char *passphrase) ret = retkey; error: - if (blob) sfree(blob); + if (blob) { + memset(blob, 0, blobsize); + sfree(blob); + } + memset(key->keyblob, 0, key->keyblob_size); sfree(key->keyblob); + memset(&key, 0, sizeof(key)); sfree(key); return ret; } diff --git a/sshaes.c b/sshaes.c index f227c560..01dd04c2 100644 --- a/sshaes.c +++ b/sshaes.c @@ -1154,6 +1154,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)); } void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len) @@ -1162,6 +1163,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)); } static const struct ssh2_cipher ssh_aes128 = { diff --git a/sshdes.c b/sshdes.c index 265dc767..9cb9cfa6 100644 --- a/sshdes.c +++ b/sshdes.c @@ -840,6 +840,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, blk, len, ourkeys); + memset(ourkeys, 0, sizeof(ourkeys)); } void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len) @@ -852,6 +853,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, blk, len, ourkeys); + memset(ourkeys, 0, sizeof(ourkeys)); } void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, @@ -867,6 +869,7 @@ void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, ourkeys[0].div0 = GET_32BIT_MSB_FIRST(iv); ourkeys[0].div1 = GET_32BIT_MSB_FIRST(iv+4); des_cbc3_decrypt(blk, blk, len, ourkeys); + memset(ourkeys, 0, sizeof(ourkeys)); } void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, @@ -882,6 +885,7 @@ void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, ourkeys[0].eiv0 = GET_32BIT_MSB_FIRST(iv); ourkeys[0].eiv1 = GET_32BIT_MSB_FIRST(iv+4); des_cbc3_encrypt(blk, blk, len, ourkeys); + memset(ourkeys, 0, sizeof(ourkeys)); } static const struct ssh2_cipher ssh_3des_ssh2 = { -- 2.11.0