1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Support importing of new-style OpenSSH private keys (encrypted by

AES rather than 3DES).

[originally from svn r8916]
This commit is contained in:
Simon Tatham 2010-04-12 10:55:31 +00:00
parent 332f233503
commit 108791e15c
3 changed files with 47 additions and 20 deletions

View File

@ -308,9 +308,10 @@ static int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret)
*/ */
enum { OSSH_DSA, OSSH_RSA }; enum { OSSH_DSA, OSSH_RSA };
enum { OSSH_ENC_3DES, OSSH_ENC_AES };
struct openssh_key { struct openssh_key {
int type; int type;
int encrypted; int encrypted, encryption;
char iv[32]; char iv[32];
unsigned char *keyblob; unsigned char *keyblob;
int keyblob_len, keyblob_size; int keyblob_len, keyblob_size;
@ -387,21 +388,29 @@ static struct openssh_key *load_openssh_key(const Filename *filename,
if (!strcmp(p, "ENCRYPTED")) if (!strcmp(p, "ENCRYPTED"))
ret->encrypted = 1; ret->encrypted = 1;
} else if (!strcmp(line, "DEK-Info")) { } else if (!strcmp(line, "DEK-Info")) {
int i, j; int i, j, ivlen;
if (strncmp(p, "DES-EDE3-CBC,", 13)) { if (!strncmp(p, "DES-EDE3-CBC,", 13)) {
errmsg = "ciphers other than DES-EDE3-CBC not supported"; 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; goto error;
} }
p += 13; p = strchr(p, ',') + 1;/* always non-NULL, by above checks */
for (i = 0; i < 8; i++) { for (i = 0; i < ivlen; i++) {
if (1 != sscanf(p, "%2x", &j)) if (1 != sscanf(p, "%2x", &j)) {
break; errmsg = "expected more iv data in DEK-Info";
goto error;
}
ret->iv[i] = j; ret->iv[i] = j;
p += 2; p += 2;
} }
if (i < 8) { if (*p) {
errmsg = "expected 16-digit iv in DEK-Info"; errmsg = "more iv data than expected in DEK-Info";
goto error; goto error;
} }
} }
@ -538,8 +547,18 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
/* /*
* Now decrypt the key blob. * Now decrypt the key blob.
*/ */
des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv, if (key->encryption == OSSH_ENC_3DES)
key->keyblob, key->keyblob_len); 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(&md5c, 0, sizeof(md5c));
memset(keybuf, 0, sizeof(keybuf)); memset(keybuf, 0, sizeof(keybuf));

8
ssh.h
View File

@ -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;
extern const struct ssh_mac ssh_hmac_sha1_96_buggy; 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. * PuTTY version number formatted as an SSH version string.

View File

@ -1097,35 +1097,35 @@ static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx)
memcpy(ctx->iv, iv, sizeof(iv)); memcpy(ctx->iv, iv, sizeof(iv));
} }
static void *aes_make_context(void) void *aes_make_context(void)
{ {
return snew(AESContext); return snew(AESContext);
} }
static void aes_free_context(void *handle) void aes_free_context(void *handle)
{ {
sfree(handle); sfree(handle);
} }
static void aes128_key(void *handle, unsigned char *key) void aes128_key(void *handle, unsigned char *key)
{ {
AESContext *ctx = (AESContext *)handle; AESContext *ctx = (AESContext *)handle;
aes_setup(ctx, 16, key, 16); 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; AESContext *ctx = (AESContext *)handle;
aes_setup(ctx, 16, key, 24); 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; AESContext *ctx = (AESContext *)handle;
aes_setup(ctx, 16, key, 32); 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; AESContext *ctx = (AESContext *)handle;
int i; 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); 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; AESContext *ctx = (AESContext *)handle;
aes_encrypt_cbc(blk, len, ctx); 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; AESContext *ctx = (AESContext *)handle;
aes_decrypt_cbc(blk, len, ctx); aes_decrypt_cbc(blk, len, ctx);