1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-04-21 21:15:03 -05:00

Refactoring to prepare for extra public key types.

The OpenSSH key importer and exporter were structured in the
assumption that the strong commonality of format between OpenSSH RSA
and DSA keys would persist across all key types. Moved code around so
it's now clear that this is a peculiarity of those _particular_ two
key types which will not apply to others we add alongside them.

Also, a boolean 'is_dsa' in winpgen.c has been converted into a more
sensible key type enumeration, and the individually typed key pointers
have been piled on top of each other in a union.

This is a pure refactoring change which should have no functional
effect.
This commit is contained in:
Chris Staite 2014-11-01 09:14:19 +00:00 committed by Simon Tatham
parent a2b64dca47
commit df0ac30d46
2 changed files with 266 additions and 225 deletions

View File

@ -613,6 +613,7 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
else else
num_integers = 0; /* placate compiler warnings */ num_integers = 0; /* placate compiler warnings */
if (key->type == OSSH_RSA || key->type == OSSH_DSA) {
/* /*
* Space to create key blob in. * Space to create key blob in.
*/ */
@ -700,6 +701,10 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
goto error; goto error;
} }
} else {
assert(0 && "Bad key type from load_openssh_key");
}
retkey->comment = dupstr("imported-openssh-key"); retkey->comment = dupstr("imported-openssh-key");
errmsg = NULL; /* no error */ errmsg = NULL; /* no error */
retval = retkey; retval = retkey;
@ -739,9 +744,20 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
privblob = key->alg->private_blob(key->data, &privlen); privblob = key->alg->private_blob(key->data, &privlen);
spareblob = outblob = NULL; spareblob = outblob = NULL;
outblob = NULL;
len = 0;
/* /*
* Find the sequence of integers to be encoded into the OpenSSH * Encode the OpenSSH key blob, and also decide on the header
* key blob, and also decide on the header line. * line.
*/
if (key->alg == &ssh_rsa || key->alg == &ssh_dss) {
/*
* The RSA and DSS handlers share some code because the two
* key types have very similar ASN.1 representations, as a
* plain SEQUENCE of big integers. So we set up a list of
* bignums per key type and then construct the actual blob in
* common code after that.
*/ */
if (key->alg == &ssh_rsa) { if (key->alg == &ssh_rsa) {
int pos; int pos;
@ -801,7 +817,7 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
nnumbers = 9; nnumbers = 9;
header = "-----BEGIN RSA PRIVATE KEY-----\n"; header = "-----BEGIN RSA PRIVATE KEY-----\n";
footer = "-----END RSA PRIVATE KEY-----\n"; footer = "-----END RSA PRIVATE KEY-----\n";
} else if (key->alg == &ssh_dss) { } else { /* ssh-dss */
int pos; int pos;
struct mpint_pos p, q, g, y, x; struct mpint_pos p, q, g, y, x;
@ -829,9 +845,6 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
nnumbers = 6; nnumbers = 6;
header = "-----BEGIN DSA PRIVATE KEY-----\n"; header = "-----BEGIN DSA PRIVATE KEY-----\n";
footer = "-----END DSA PRIVATE KEY-----\n"; footer = "-----END DSA PRIVATE KEY-----\n";
} else {
assert(0); /* zoinks! */
exit(1); /* XXX: GCC doesn't understand assert() on some systems. */
} }
/* /*
@ -846,16 +859,11 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
seqlen = len; seqlen = len;
/* Now add on the SEQUENCE header. */ /* Now add on the SEQUENCE header. */
len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED); len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);
/* Round up to the cipher block size, ensuring we have at least one
* byte of padding (see below). */
outlen = len;
if (passphrase)
outlen = (outlen+8) &~ 7;
/* /*
* Now we know how big outblob needs to be. Allocate it. * Now we know how big outblob needs to be. Allocate it.
*/ */
outblob = snewn(outlen, unsigned char); outblob = snewn(len, unsigned char);
/* /*
* And write the data into it. * And write the data into it.
@ -867,6 +875,33 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
memcpy(outblob+pos, numbers[i].start, numbers[i].bytes); memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);
pos += numbers[i].bytes; pos += numbers[i].bytes;
} }
} else {
assert(0); /* zoinks! */
exit(1); /* XXX: GCC doesn't understand assert() on some systems. */
}
/*
* Encrypt the key.
*
* For the moment, we still encrypt our OpenSSH keys using
* old-style 3DES.
*/
if (passphrase) {
struct MD5Context md5c;
unsigned char keybuf[32];
/*
* Round up to the cipher block size, ensuring we have at
* least one byte of padding (see below).
*/
outlen = (len+8) &~ 7;
{
unsigned char *tmp = snewn(outlen, unsigned char);
memcpy(tmp, outblob, len);
smemclr(outblob, len);
sfree(outblob);
outblob = tmp;
}
/* /*
* Padding on OpenSSH keys is deterministic. The number of * Padding on OpenSSH keys is deterministic. The number of
@ -890,13 +925,6 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
outblob[pos++] = outlen - len; outblob[pos++] = outlen - len;
} }
/*
* Encrypt the key.
*
* For the moment, we still encrypt our OpenSSH keys using
* old-style 3DES.
*/
if (passphrase) {
/* /*
* Invent an iv. Then derive encryption key from passphrase * Invent an iv. Then derive encryption key from passphrase
* and iv/salt: * and iv/salt:
@ -906,9 +934,6 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
* - block C would be MD5(B || passphrase || iv) and so on * - block C would be MD5(B || passphrase || iv) and so on
* - encryption key is the first N bytes of A || B * - encryption key is the first N bytes of A || B
*/ */
struct MD5Context md5c;
unsigned char keybuf[32];
for (i = 0; i < 8; i++) iv[i] = random_byte(); for (i = 0; i < 8; i++) iv[i] = random_byte();
MD5Init(&md5c); MD5Init(&md5c);
@ -929,6 +954,12 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
smemclr(&md5c, sizeof(md5c)); smemclr(&md5c, sizeof(md5c));
smemclr(keybuf, sizeof(keybuf)); smemclr(keybuf, sizeof(keybuf));
} else {
/*
* If no encryption, the blob has exactly its original
* cleartext size.
*/
outlen = len;
} }
/* /*

View File

@ -315,6 +315,8 @@ static int CALLBACK AboutProc(HWND hwnd, UINT msg,
return 0; return 0;
} }
typedef enum {RSA, DSA, ECDSA} keytype;
/* /*
* Thread to generate a key. * Thread to generate a key.
*/ */
@ -322,10 +324,12 @@ struct rsa_key_thread_params {
HWND progressbar; /* notify this with progress */ HWND progressbar; /* notify this with progress */
HWND dialog; /* notify this on completion */ HWND dialog; /* notify this on completion */
int keysize; /* bits in key */ int keysize; /* bits in key */
int is_dsa; keytype keytype;
union {
struct RSAKey *key; struct RSAKey *key;
struct dss_key *dsskey; struct dss_key *dsskey;
}; };
};
static DWORD WINAPI generate_rsa_key_thread(void *param) static DWORD WINAPI generate_rsa_key_thread(void *param)
{ {
struct rsa_key_thread_params *params = struct rsa_key_thread_params *params =
@ -335,7 +339,7 @@ static DWORD WINAPI generate_rsa_key_thread(void *param)
progress_update(&prog, PROGFN_INITIALISE, 0, 0); progress_update(&prog, PROGFN_INITIALISE, 0, 0);
if (params->is_dsa) if (params->keytype == DSA)
dsa_generate(params->dsskey, params->keysize, progress_update, &prog); dsa_generate(params->dsskey, params->keysize, progress_update, &prog);
else else
rsa_generate(params->key, params->keysize, progress_update, &prog); rsa_generate(params->key, params->keysize, progress_update, &prog);
@ -352,12 +356,15 @@ struct MainDlgState {
int key_exists; int key_exists;
int entropy_got, entropy_required, entropy_size; int entropy_got, entropy_required, entropy_size;
int keysize; int keysize;
int ssh2, is_dsa; int ssh2;
keytype keytype;
char **commentptr; /* points to key.comment or ssh2key.comment */ char **commentptr; /* points to key.comment or ssh2key.comment */
struct ssh2_userkey ssh2key; struct ssh2_userkey ssh2key;
unsigned *entropy; unsigned *entropy;
union {
struct RSAKey key; struct RSAKey key;
struct dss_key dsskey; struct dss_key dsskey;
};
HMENU filemenu, keymenu, cvtmenu; HMENU filemenu, keymenu, cvtmenu;
}; };
@ -990,7 +997,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS); params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);
params->dialog = hwnd; params->dialog = hwnd;
params->keysize = state->keysize; params->keysize = state->keysize;
params->is_dsa = state->is_dsa; params->keytype = state->keytype;
params->key = &state->key; params->key = &state->key;
params->dsskey = &state->dsskey; params->dsskey = &state->dsskey;
@ -1070,7 +1077,10 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
state->keysize = DEFAULT_KEYSIZE; state->keysize = DEFAULT_KEYSIZE;
/* If we ever introduce a new key type, check it here! */ /* If we ever introduce a new key type, check it here! */
state->ssh2 = !IsDlgButtonChecked(hwnd, IDC_KEYSSH1); state->ssh2 = !IsDlgButtonChecked(hwnd, IDC_KEYSSH1);
state->is_dsa = IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA); state->keytype = RSA;
if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA)) {
state->keytype = DSA;
}
if (state->keysize < 256) { if (state->keysize < 256) {
int ret = MessageBox(hwnd, int ret = MessageBox(hwnd,
"PuTTYgen will not generate a key" "PuTTYgen will not generate a key"
@ -1276,7 +1286,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
MAKELPARAM(0, PROGRESSRANGE)); MAKELPARAM(0, PROGRESSRANGE));
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, PROGRESSRANGE, 0); SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, PROGRESSRANGE, 0);
if (state->ssh2) { if (state->ssh2) {
if (state->is_dsa) { if (state->keytype == DSA) {
state->ssh2key.data = &state->dsskey; state->ssh2key.data = &state->dsskey;
state->ssh2key.alg = &ssh_dss; state->ssh2key.alg = &ssh_dss;
} else { } else {
@ -1297,7 +1307,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
{ {
struct tm tm; struct tm tm;
tm = ltime(); tm = ltime();
if (state->is_dsa) if (state->keytype == DSA)
strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", &tm); strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", &tm);
else else
strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", &tm); strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", &tm);