From 06e09f436f7fd784822ec29f66d37e60d01e24a4 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 12 Apr 2010 10:55:31 +0000 Subject: [PATCH] Support importing of new-style OpenSSH private keys (encrypted by AES rather than 3DES). git-svn-id: svn://svn.tartarus.org/sgt/putty@8916 cda61777-01e9-0310-a592-d414129be87e --- import.c | 45 ++++++++++++++++++++++++++++++++------------- ssh.h | 8 ++++++++ sshaes.c | 16 ++++++++-------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/import.c b/import.c index a3c24050..17bf65b9 100644 --- a/import.c +++ b/import.c @@ -308,9 +308,10 @@ static int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret) */ enum { OSSH_DSA, OSSH_RSA }; +enum { OSSH_ENC_3DES, OSSH_ENC_AES }; struct openssh_key { int type; - int encrypted; + int encrypted, encryption; char iv[32]; unsigned char *keyblob; int keyblob_len, keyblob_size; @@ -387,21 +388,29 @@ static struct openssh_key *load_openssh_key(const Filename *filename, if (!strcmp(p, "ENCRYPTED")) ret->encrypted = 1; } else if (!strcmp(line, "DEK-Info")) { - int i, j; - - if (strncmp(p, "DES-EDE3-CBC,", 13)) { - errmsg = "ciphers other than DES-EDE3-CBC not supported"; + int i, j, ivlen; + + if (!strncmp(p, "DES-EDE3-CBC,", 13)) { + ret->encryption = OSSH_ENC_3DES; + ivlen = 8; + } else if (!strncmp(p, "AES-128-CBC,", 12)) { + ret->encryption = OSSH_ENC_AES; + ivlen = 16; + } else { + errmsg = "unsupported cipher"; goto error; } - p += 13; - for (i = 0; i < 8; i++) { - if (1 != sscanf(p, "%2x", &j)) - break; + p = strchr(p, ',') + 1;/* always non-NULL, by above checks */ + for (i = 0; i < ivlen; i++) { + if (1 != sscanf(p, "%2x", &j)) { + errmsg = "expected more iv data in DEK-Info"; + goto error; + } ret->iv[i] = j; p += 2; } - if (i < 8) { - errmsg = "expected 16-digit iv in DEK-Info"; + if (*p) { + errmsg = "more iv data than expected in DEK-Info"; goto error; } } @@ -538,8 +547,18 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase, /* * Now decrypt the key blob. */ - des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv, - key->keyblob, key->keyblob_len); + if (key->encryption == OSSH_ENC_3DES) + des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv, + key->keyblob, key->keyblob_len); + else { + void *ctx; + assert(key->encryption == OSSH_ENC_AES); + ctx = aes_make_context(); + aes128_key(ctx, keybuf); + aes_iv(ctx, (unsigned char *)key->iv); + aes_ssh2_decrypt_blk(ctx, key->keyblob, key->keyblob_len); + aes_free_context(ctx); + } memset(&md5c, 0, sizeof(md5c)); memset(keybuf, 0, sizeof(keybuf)); diff --git a/ssh.h b/ssh.h index 2e9194fd..d17920c4 100644 --- a/ssh.h +++ b/ssh.h @@ -290,6 +290,14 @@ extern const struct ssh_mac ssh_hmac_sha1_buggy; extern const struct ssh_mac ssh_hmac_sha1_96; extern const struct ssh_mac ssh_hmac_sha1_96_buggy; +void *aes_make_context(void); +void aes_free_context(void *handle); +void aes128_key(void *handle, unsigned char *key); +void aes192_key(void *handle, unsigned char *key); +void aes256_key(void *handle, unsigned char *key); +void aes_iv(void *handle, unsigned char *iv); +void aes_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len); +void aes_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len); /* * PuTTY version number formatted as an SSH version string. diff --git a/sshaes.c b/sshaes.c index 44f8ac59..2800e021 100644 --- a/sshaes.c +++ b/sshaes.c @@ -1097,35 +1097,35 @@ static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx) memcpy(ctx->iv, iv, sizeof(iv)); } -static void *aes_make_context(void) +void *aes_make_context(void) { return snew(AESContext); } -static void aes_free_context(void *handle) +void aes_free_context(void *handle) { sfree(handle); } -static void aes128_key(void *handle, unsigned char *key) +void aes128_key(void *handle, unsigned char *key) { AESContext *ctx = (AESContext *)handle; aes_setup(ctx, 16, key, 16); } -static void aes192_key(void *handle, unsigned char *key) +void aes192_key(void *handle, unsigned char *key) { AESContext *ctx = (AESContext *)handle; aes_setup(ctx, 16, key, 24); } -static void aes256_key(void *handle, unsigned char *key) +void aes256_key(void *handle, unsigned char *key) { AESContext *ctx = (AESContext *)handle; aes_setup(ctx, 16, key, 32); } -static void aes_iv(void *handle, unsigned char *iv) +void aes_iv(void *handle, unsigned char *iv) { AESContext *ctx = (AESContext *)handle; int i; @@ -1133,13 +1133,13 @@ static void aes_iv(void *handle, unsigned char *iv) ctx->iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i); } -static void aes_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) +void aes_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) { AESContext *ctx = (AESContext *)handle; aes_encrypt_cbc(blk, len, ctx); } -static void aes_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) +void aes_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) { AESContext *ctx = (AESContext *)handle; aes_decrypt_cbc(blk, len, ctx); -- 2.11.0