1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Separate key-type enum values for old and new OpenSSH keys.

It's all very well for these two different formats to share a type
code as long as we're only loading them and not saving, but as soon as
we need to save one or the other, we'll need different type codes
after all.

This commit introduces the openssh_new_write() function, but for the
moment, it always returns failure.
This commit is contained in:
Simon Tatham 2015-04-28 19:46:58 +01:00
parent 78b8bde7af
commit 79bbf37c9e
5 changed files with 93 additions and 35 deletions

View File

@ -160,6 +160,10 @@ void help(void)
" -O specify output type:\n"
" private output PuTTY private key format\n"
" private-openssh export OpenSSH private key\n"
" private-openssh-pem export OpenSSH private key "
"(force old PEM format)\n"
" private-openssh-new export OpenSSH private key "
"(force new format)\n"
" private-sshcom export ssh.com private key\n"
" public standard / ssh.com public key\n"
" public-openssh OpenSSH public key\n"
@ -267,7 +271,8 @@ int main(int argc, char **argv)
Filename *infilename = NULL, *outfilename = NULL;
enum { NOKEYGEN, RSA1, RSA2, DSA, ECDSA } keytype = NOKEYGEN;
char *outfile = NULL, *outfiletmp = NULL;
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH, SSHCOM } outtype = PRIVATE;
enum { PRIVATE, PUBLIC, PUBLICO, FP, OPENSSH_PEM,
OPENSSH_NEW, SSHCOM } outtype = PRIVATE;
int bits = 2048;
char *comment = NULL, *origcomment = NULL;
int change_passphrase = FALSE;
@ -460,8 +465,11 @@ int main(int argc, char **argv)
outtype = PRIVATE;
else if (!strcmp(p, "fingerprint"))
outtype = FP;
else if (!strcmp(p, "private-openssh"))
outtype = OPENSSH, sshver = 2;
else if (!strcmp(p, "private-openssh") ||
!strcmp(p, "private-openssh-pem"))
outtype = OPENSSH_PEM, sshver = 2;
else if (!strcmp(p, "private-openssh-new"))
outtype = OPENSSH_NEW, sshver = 2;
else if (!strcmp(p, "private-sshcom"))
outtype = SSHCOM, sshver = 2;
else {
@ -536,7 +544,8 @@ int main(int argc, char **argv)
* We must save the private part when generating a new key.
*/
if (keytype != NOKEYGEN &&
(outtype != PRIVATE && outtype != OPENSSH && outtype != SSHCOM)) {
(outtype != PRIVATE && outtype != OPENSSH_PEM &&
outtype != OPENSSH_NEW && outtype != SSHCOM)) {
fprintf(stderr, "puttygen: this would generate a new key but "
"discard the private part\n");
return 1;
@ -590,7 +599,8 @@ int main(int argc, char **argv)
break;
case SSH_KEYTYPE_SSH2:
case SSH_KEYTYPE_OPENSSH:
case SSH_KEYTYPE_OPENSSH_PEM:
case SSH_KEYTYPE_OPENSSH_NEW:
case SSH_KEYTYPE_SSHCOM:
if (sshver == 1) {
fprintf(stderr, "puttygen: conversion from SSH-2 to SSH-1 keys"
@ -614,7 +624,8 @@ int main(int argc, char **argv)
*/
if ((intype == SSH_KEYTYPE_SSH1 && outtype == PRIVATE) ||
(intype == SSH_KEYTYPE_SSH2 && outtype == PRIVATE) ||
(intype == SSH_KEYTYPE_OPENSSH && outtype == OPENSSH) ||
(intype == SSH_KEYTYPE_OPENSSH_PEM && outtype == OPENSSH_PEM) ||
(intype == SSH_KEYTYPE_OPENSSH_NEW && outtype == OPENSSH_NEW) ||
(intype == SSH_KEYTYPE_SSHCOM && outtype == SSHCOM)) {
if (!outfile) {
outfile = infile;
@ -632,7 +643,8 @@ int main(int argc, char **argv)
* Bomb out rather than automatically choosing to write
* a private key file to stdout.
*/
if (outtype==PRIVATE || outtype==OPENSSH || outtype==SSHCOM) {
if (outtype == PRIVATE || outtype == OPENSSH_PEM ||
outtype == OPENSSH_NEW || outtype == SSHCOM) {
fprintf(stderr, "puttygen: need to specify an output file\n");
return 1;
}
@ -645,8 +657,11 @@ int main(int argc, char **argv)
* out a private key format, or (b) the entire input key file
* is encrypted.
*/
if (outtype == PRIVATE || outtype == OPENSSH || outtype == SSHCOM ||
intype == SSH_KEYTYPE_OPENSSH || intype == SSH_KEYTYPE_SSHCOM)
if (outtype == PRIVATE || outtype == OPENSSH_PEM ||
outtype == OPENSSH_NEW || outtype == SSHCOM ||
intype == SSH_KEYTYPE_OPENSSH_PEM ||
intype == SSH_KEYTYPE_OPENSSH_NEW ||
intype == SSH_KEYTYPE_SSHCOM)
load_encrypted = TRUE;
else
load_encrypted = FALSE;
@ -831,7 +846,8 @@ int main(int argc, char **argv)
}
break;
case SSH_KEYTYPE_OPENSSH:
case SSH_KEYTYPE_OPENSSH_PEM:
case SSH_KEYTYPE_OPENSSH_NEW:
case SSH_KEYTYPE_SSHCOM:
ssh2key = import_ssh2(infilename, intype, passphrase, &error);
if (ssh2key) {
@ -1052,19 +1068,25 @@ int main(int argc, char **argv)
}
break;
case OPENSSH:
case OPENSSH_PEM:
case OPENSSH_NEW:
case SSHCOM:
assert(sshver == 2);
assert(ssh2key);
random_ref(); /* both foreign key types require randomness,
* for IV or padding */
switch (outtype) {
case OPENSSH:
real_outtype = SSH_KEYTYPE_OPENSSH;
case OPENSSH_PEM:
real_outtype = SSH_KEYTYPE_OPENSSH_PEM;
break;
case OPENSSH_NEW:
real_outtype = SSH_KEYTYPE_OPENSSH_NEW;
break;
case SSHCOM:
real_outtype = SSH_KEYTYPE_SSHCOM;
break;
default:
assert(0 && "control flow goof");
}
ret = export_ssh2(outfilename, real_outtype, ssh2key, passphrase);
if (!ret) {

View File

@ -15,8 +15,10 @@
int openssh_encrypted(const Filename *filename);
struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
const char **errmsg_p);
int openssh_write(const Filename *filename, struct ssh2_userkey *key,
char *passphrase);
int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
char *passphrase);
int openssh_new_write(const Filename *filename, struct ssh2_userkey *key,
char *passphrase);
int sshcom_encrypted(const Filename *filename, char **comment);
struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase,
@ -29,7 +31,9 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key,
*/
int import_possible(int type)
{
if (type == SSH_KEYTYPE_OPENSSH)
if (type == SSH_KEYTYPE_OPENSSH_PEM)
return 1;
if (type == SSH_KEYTYPE_OPENSSH_NEW)
return 1;
if (type == SSH_KEYTYPE_SSHCOM)
return 1;
@ -54,7 +58,7 @@ int import_target_type(int type)
*/
int import_encrypted(const Filename *filename, int type, char **comment)
{
if (type == SSH_KEYTYPE_OPENSSH) {
if (type == SSH_KEYTYPE_OPENSSH_PEM || type == SSH_KEYTYPE_OPENSSH_NEW) {
/* OpenSSH doesn't do key comments */
*comment = dupstr(filename_to_str(filename));
return openssh_encrypted(filename);
@ -80,7 +84,7 @@ int import_ssh1(const Filename *filename, int type,
struct ssh2_userkey *import_ssh2(const Filename *filename, int type,
char *passphrase, const char **errmsg_p)
{
if (type == SSH_KEYTYPE_OPENSSH)
if (type == SSH_KEYTYPE_OPENSSH_PEM || type == SSH_KEYTYPE_OPENSSH_NEW)
return openssh_read(filename, passphrase, errmsg_p);
if (type == SSH_KEYTYPE_SSHCOM)
return sshcom_read(filename, passphrase, errmsg_p);
@ -102,8 +106,10 @@ int export_ssh1(const Filename *filename, int type, struct RSAKey *key,
int export_ssh2(const Filename *filename, int type,
struct ssh2_userkey *key, char *passphrase)
{
if (type == SSH_KEYTYPE_OPENSSH)
return openssh_write(filename, key, passphrase);
if (type == SSH_KEYTYPE_OPENSSH_PEM)
return openssh_pem_write(filename, key, passphrase);
if (type == SSH_KEYTYPE_OPENSSH_NEW)
return openssh_new_write(filename, key, passphrase);
if (type == SSH_KEYTYPE_SSHCOM)
return sshcom_write(filename, key, passphrase);
return 0;
@ -305,6 +311,11 @@ static int ssh2_read_mpint(void *data, int len, struct mpint_pos *ret)
/* ----------------------------------------------------------------------
* Code to read and write OpenSSH private keys.
*
* These come in two more or less entirely different formats, except
* that the base64 wrapper is similar enough to handle with the same
* code. Accordingly, there's just one function to load OpenSSH keys
* in both formats, but separate functions to write the two formats.
*/
typedef enum {
@ -1263,8 +1274,8 @@ struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase,
return retval;
}
int openssh_write(const Filename *filename, struct ssh2_userkey *key,
char *passphrase)
int openssh_pem_write(const Filename *filename, struct ssh2_userkey *key,
char *passphrase)
{
unsigned char *pubblob, *privblob, *spareblob;
int publen, privlen, sparelen = 0;
@ -1626,6 +1637,12 @@ int openssh_write(const Filename *filename, struct ssh2_userkey *key,
return ret;
}
int openssh_new_write(const Filename *filename, struct ssh2_userkey *key,
char *passphrase)
{
return FALSE;
}
/* ----------------------------------------------------------------------
* Code to read ssh.com private keys.
*/

4
ssh.h
View File

@ -630,7 +630,9 @@ enum {
SSH_KEYTYPE_UNOPENABLE,
SSH_KEYTYPE_UNKNOWN,
SSH_KEYTYPE_SSH1, SSH_KEYTYPE_SSH2,
SSH_KEYTYPE_OPENSSH, SSH_KEYTYPE_SSHCOM
SSH_KEYTYPE_OPENSSH_PEM,
SSH_KEYTYPE_OPENSSH_NEW,
SSH_KEYTYPE_SSHCOM
};
int key_type(const Filename *filename);
char *key_type_to_str(int type);

View File

@ -1157,6 +1157,7 @@ int key_type(const Filename *filename)
char buf[32];
const char putty2_sig[] = "PuTTY-User-Key-File-";
const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";
const char openssh_new_sig[] = "-----BEGIN OPENSSH PRIVATE KEY";
const char openssh_sig[] = "-----BEGIN ";
int i;
@ -1173,8 +1174,10 @@ int key_type(const Filename *filename)
return SSH_KEYTYPE_SSH1;
if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))
return SSH_KEYTYPE_SSH2;
if (!memcmp(buf, openssh_new_sig, sizeof(openssh_new_sig)-1))
return SSH_KEYTYPE_OPENSSH_NEW;
if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))
return SSH_KEYTYPE_OPENSSH;
return SSH_KEYTYPE_OPENSSH_PEM;
if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))
return SSH_KEYTYPE_SSHCOM;
return SSH_KEYTYPE_UNKNOWN; /* unrecognised or EOF */
@ -1191,7 +1194,8 @@ char *key_type_to_str(int type)
case SSH_KEYTYPE_UNKNOWN: return "not a private key"; break;
case SSH_KEYTYPE_SSH1: return "SSH-1 private key"; break;
case SSH_KEYTYPE_SSH2: return "PuTTY SSH-2 private key"; break;
case SSH_KEYTYPE_OPENSSH: return "OpenSSH SSH-2 private key"; break;
case SSH_KEYTYPE_OPENSSH_PEM: return "OpenSSH SSH-2 private key (old PEM format)"; break;
case SSH_KEYTYPE_OPENSSH_NEW: return "OpenSSH SSH-2 private key (new format)"; break;
case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH-2 private key"; break;
default: return "INTERNAL ERROR"; break;
}

View File

@ -534,7 +534,9 @@ enum {
IDC_BITSSTATIC, IDC_BITS,
IDC_ABOUT,
IDC_GIVEHELP,
IDC_IMPORT, IDC_EXPORT_OPENSSH, IDC_EXPORT_SSHCOM
IDC_IMPORT,
IDC_EXPORT_OPENSSH_PEM, IDC_EXPORT_OPENSSH_NEW,
IDC_EXPORT_SSHCOM
};
static const int nokey_ids[] = { IDC_NOKEY, 0 };
@ -579,7 +581,9 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH,
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_PEM,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_NEW,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_SSHCOM,
MF_GRAYED|MF_BYCOMMAND);
@ -607,7 +611,9 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH,
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_PEM,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH_NEW,
MF_GRAYED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_EXPORT_SSHCOM,
MF_GRAYED|MF_BYCOMMAND);
@ -643,7 +649,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
#define do_export_menuitem(x,y) \
EnableMenuItem(state->cvtmenu, x, MF_BYCOMMAND | \
(import_target_type(y)==type?MF_ENABLED:MF_GRAYED))
do_export_menuitem(IDC_EXPORT_OPENSSH, SSH_KEYTYPE_OPENSSH);
do_export_menuitem(IDC_EXPORT_OPENSSH_PEM, SSH_KEYTYPE_OPENSSH_PEM);
do_export_menuitem(IDC_EXPORT_OPENSSH_NEW, SSH_KEYTYPE_OPENSSH_NEW);
do_export_menuitem(IDC_EXPORT_SSHCOM, SSH_KEYTYPE_SSHCOM);
#undef do_export_menuitem
break;
@ -883,8 +890,10 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_IMPORT, "&Import key");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH,
"Export &OpenSSH key");
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH_PEM,
"Export &OpenSSH key (old PEM format)");
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH_NEW,
"Export &OpenSSH key (new format)");
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_SSHCOM,
"Export &ssh.com key");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1,
@ -1161,7 +1170,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
}
break;
case IDC_SAVE:
case IDC_EXPORT_OPENSSH:
case IDC_EXPORT_OPENSSH_PEM:
case IDC_EXPORT_OPENSSH_NEW:
case IDC_EXPORT_SSHCOM:
if (HIWORD(wParam) != BN_CLICKED)
break;
@ -1177,8 +1187,10 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
else
realtype = SSH_KEYTYPE_SSH1;
if (LOWORD(wParam) == IDC_EXPORT_OPENSSH)
type = SSH_KEYTYPE_OPENSSH;
if (LOWORD(wParam) == IDC_EXPORT_OPENSSH_PEM)
type = SSH_KEYTYPE_OPENSSH_PEM;
else if (LOWORD(wParam) == IDC_EXPORT_OPENSSH_NEW)
type = SSH_KEYTYPE_OPENSSH_NEW;
else if (LOWORD(wParam) == IDC_EXPORT_SSHCOM)
type = SSH_KEYTYPE_SSHCOM;
else
@ -1453,7 +1465,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
case IDC_BITS:
topic = WINHELP_CTX_puttygen_bits; break;
case IDC_IMPORT:
case IDC_EXPORT_OPENSSH:
case IDC_EXPORT_OPENSSH_PEM:
case IDC_EXPORT_OPENSSH_NEW:
case IDC_EXPORT_SSHCOM:
topic = WINHELP_CTX_puttygen_conversions; break;
}