mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-06-30 19:12:48 -05:00
Elliptic-curve cryptography support.
This provides support for ECDSA public keys, for both hosts and users, and also ECDH key exchange. Supported curves are currently just the three NIST curves required by RFC 5656.
This commit is contained in:

committed by
Simon Tatham

parent
7d1c30cd50
commit
2bf8688355
@ -328,6 +328,7 @@ struct rsa_key_thread_params {
|
||||
union {
|
||||
struct RSAKey *key;
|
||||
struct dss_key *dsskey;
|
||||
struct ec_key *eckey;
|
||||
};
|
||||
};
|
||||
static DWORD WINAPI generate_rsa_key_thread(void *param)
|
||||
@ -341,6 +342,8 @@ static DWORD WINAPI generate_rsa_key_thread(void *param)
|
||||
|
||||
if (params->keytype == DSA)
|
||||
dsa_generate(params->dsskey, params->keysize, progress_update, &prog);
|
||||
else if (params->keytype == ECDSA)
|
||||
ec_generate(params->eckey, params->keysize, progress_update, &prog);
|
||||
else
|
||||
rsa_generate(params->key, params->keysize, progress_update, &prog);
|
||||
|
||||
@ -364,6 +367,7 @@ struct MainDlgState {
|
||||
union {
|
||||
struct RSAKey key;
|
||||
struct dss_key dsskey;
|
||||
struct ec_key eckey;
|
||||
};
|
||||
HMENU filemenu, keymenu, cvtmenu;
|
||||
};
|
||||
@ -526,6 +530,7 @@ enum {
|
||||
IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB,
|
||||
IDC_BOX_PARAMS,
|
||||
IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA,
|
||||
IDC_KEYSSH2ECDSA,
|
||||
IDC_BITSSTATIC, IDC_BITS,
|
||||
IDC_ABOUT,
|
||||
IDC_GIVEHELP,
|
||||
@ -562,6 +567,7 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ECDSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);
|
||||
EnableMenuItem(state->filemenu, IDC_LOAD, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->filemenu, IDC_SAVE, MF_GRAYED|MF_BYCOMMAND);
|
||||
@ -570,6 +576,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH1, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2RSA, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
|
||||
MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
@ -587,6 +595,7 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ECDSA), 0);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 0);
|
||||
EnableMenuItem(state->filemenu, IDC_LOAD, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->filemenu, IDC_SAVE, MF_GRAYED|MF_BYCOMMAND);
|
||||
@ -595,6 +604,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH1, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2RSA, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_GRAYED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_EXPORT_OPENSSH,
|
||||
MF_GRAYED|MF_BYCOMMAND);
|
||||
@ -612,6 +623,7 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH1), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2RSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2DSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_KEYSSH2ECDSA), 1);
|
||||
EnableWindow(GetDlgItem(hwnd, IDC_BITS), 1);
|
||||
EnableMenuItem(state->filemenu, IDC_LOAD, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->filemenu, IDC_SAVE, MF_ENABLED|MF_BYCOMMAND);
|
||||
@ -620,6 +632,8 @@ void ui_set_state(HWND hwnd, struct MainDlgState *state, int status)
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH1, MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2RSA,MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2DSA,MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->keymenu, IDC_KEYSSH2ECDSA,
|
||||
MF_ENABLED|MF_BYCOMMAND);
|
||||
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
|
||||
/*
|
||||
* Enable export menu items if and only if the key type
|
||||
@ -862,6 +876,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH1, "SSH-&1 key (RSA)");
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2RSA, "SSH-2 &RSA key");
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2DSA, "SSH-2 &DSA key");
|
||||
AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2ECDSA, "SSH-2 &ECDSA key");
|
||||
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Key");
|
||||
state->keymenu = menu1;
|
||||
|
||||
@ -940,13 +955,14 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 3,
|
||||
"SSH-&1 (RSA)", IDC_KEYSSH1,
|
||||
"SSH-2 &RSA", IDC_KEYSSH2RSA,
|
||||
"SSH-2 &DSA", IDC_KEYSSH2DSA, NULL);
|
||||
"SSH-2 &DSA", IDC_KEYSSH2DSA,
|
||||
"SSH-2 &ECDSA", IDC_KEYSSH2ECDSA, NULL);
|
||||
staticedit(&cp, "Number of &bits in a generated key:",
|
||||
IDC_BITSSTATIC, IDC_BITS, 20);
|
||||
endbox(&cp);
|
||||
}
|
||||
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA, IDC_KEYSSH2RSA);
|
||||
CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,
|
||||
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2ECDSA, IDC_KEYSSH2RSA);
|
||||
CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2ECDSA,
|
||||
IDC_KEYSSH2RSA, MF_BYCOMMAND);
|
||||
SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE);
|
||||
|
||||
@ -1018,6 +1034,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
case IDC_KEYSSH1:
|
||||
case IDC_KEYSSH2RSA:
|
||||
case IDC_KEYSSH2DSA:
|
||||
case IDC_KEYSSH2ECDSA:
|
||||
{
|
||||
state = (struct MainDlgState *)
|
||||
GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
@ -1026,6 +1043,11 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
LOWORD(wParam));
|
||||
CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,
|
||||
LOWORD(wParam), MF_BYCOMMAND);
|
||||
CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2ECDSA,
|
||||
LOWORD(wParam));
|
||||
CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1,
|
||||
IDC_KEYSSH2ECDSA,
|
||||
LOWORD(wParam), MF_BYCOMMAND);
|
||||
}
|
||||
break;
|
||||
case IDC_QUIT:
|
||||
@ -1080,6 +1102,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
state->keytype = RSA;
|
||||
if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA)) {
|
||||
state->keytype = DSA;
|
||||
} else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ECDSA)) {
|
||||
state->keytype = ECDSA;
|
||||
}
|
||||
if (state->keysize < 256) {
|
||||
int ret = MessageBox(hwnd,
|
||||
@ -1093,6 +1117,20 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
state->keysize = 256;
|
||||
SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);
|
||||
}
|
||||
if (state->keytype == ECDSA && !(state->keysize == 256 ||
|
||||
state->keysize == 384 ||
|
||||
state->keysize == 521)) {
|
||||
int ret = MessageBox(hwnd,
|
||||
"Only 256, 384 and 521 bit elliptic"
|
||||
" curves are supported.\n"
|
||||
"Key length reset to 256. Continue?",
|
||||
"PuTTYgen Warning",
|
||||
MB_ICONWARNING | MB_OKCANCEL);
|
||||
if (ret != IDOK)
|
||||
break;
|
||||
state->keysize = 256;
|
||||
SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);
|
||||
}
|
||||
ui_set_state(hwnd, state, 1);
|
||||
SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg);
|
||||
state->key_exists = FALSE;
|
||||
@ -1289,6 +1327,14 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
if (state->keytype == DSA) {
|
||||
state->ssh2key.data = &state->dsskey;
|
||||
state->ssh2key.alg = &ssh_dss;
|
||||
} else if (state->keytype == ECDSA) {
|
||||
state->ssh2key.data = &state->eckey;
|
||||
if (state->eckey.publicKey.curve->fieldBits == 256)
|
||||
state->ssh2key.alg = &ssh_ecdsa_nistp256;
|
||||
else if (state->eckey.publicKey.curve->fieldBits == 384)
|
||||
state->ssh2key.alg = &ssh_ecdsa_nistp384;
|
||||
else
|
||||
state->ssh2key.alg = &ssh_ecdsa_nistp521;
|
||||
} else {
|
||||
state->ssh2key.data = &state->key;
|
||||
state->ssh2key.alg = &ssh_rsa;
|
||||
@ -1309,6 +1355,8 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
tm = ltime();
|
||||
if (state->keytype == DSA)
|
||||
strftime(*state->commentptr, 30, "dsa-key-%Y%m%d", &tm);
|
||||
else if (state->keytype == ECDSA)
|
||||
strftime(*state->commentptr, 30, "ecdsa-key-%Y%m%d", &tm);
|
||||
else
|
||||
strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", &tm);
|
||||
}
|
||||
@ -1399,6 +1447,7 @@ static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
|
||||
case IDC_KEYSSH1:
|
||||
case IDC_KEYSSH2RSA:
|
||||
case IDC_KEYSSH2DSA:
|
||||
case IDC_KEYSSH2ECDSA:
|
||||
topic = WINHELP_CTX_puttygen_keytype; break;
|
||||
case IDC_BITSSTATIC:
|
||||
case IDC_BITS:
|
||||
|
@ -1141,6 +1141,12 @@ static void answer_msg(void *msg)
|
||||
key->alg = &ssh_rsa;
|
||||
else if (alglen == 7 && !memcmp(alg, "ssh-dss", 7))
|
||||
key->alg = &ssh_dss;
|
||||
else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp256", 19))
|
||||
key->alg = &ssh_ecdsa_nistp256;
|
||||
else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp384", 19))
|
||||
key->alg = &ssh_ecdsa_nistp384;
|
||||
else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp521", 19))
|
||||
key->alg = &ssh_ecdsa_nistp521;
|
||||
else {
|
||||
sfree(key);
|
||||
goto failure;
|
||||
|
Reference in New Issue
Block a user