#include "putty.h"
#include "ssh.h"
+#include "licence.h"
#include <commctrl.h>
#define WM_DONEKEY (WM_APP + 1)
-#define DEFAULT_KEYSIZE 2048
+#define DEFAULT_KEY_BITS 2048
+#define DEFAULT_CURVE_INDEX 0
static char *cmdline_keyfile = NULL;
rd.right - rd.left, rd.bottom - rd.top, TRUE);
}
+ SetDlgItemText(hwnd, 1000, LICENCE_TEXT("\r\n\r\n"));
return 1;
case WM_COMMAND:
switch (LOWORD(wParam)) {
rd.right - rd.left, rd.bottom - rd.top, TRUE);
}
- SetDlgItemText(hwnd, 100, ver);
+ {
+ char *text = dupprintf
+ ("Pageant\r\n\r\n%s\r\n\r\n%s",
+ ver,
+ "\251 " SHORT_COPYRIGHT_DETAILS ". All rights reserved.");
+ SetDlgItemText(hwnd, 1000, text);
+ sfree(text);
+ }
return 1;
case WM_COMMAND:
switch (LOWORD(wParam)) {
struct rsa_key_thread_params {
HWND progressbar; /* notify this with progress */
HWND dialog; /* notify this on completion */
- int keysize; /* bits in key */
+ int key_bits; /* bits in key modulus (RSA, DSA) */
+ int curve_bits; /* bits in elliptic curve (ECDSA) */
keytype keytype;
union {
struct RSAKey *key;
progress_update(&prog, PROGFN_INITIALISE, 0, 0);
if (params->keytype == DSA)
- dsa_generate(params->dsskey, params->keysize, progress_update, &prog);
+ dsa_generate(params->dsskey, params->key_bits, progress_update, &prog);
else if (params->keytype == ECDSA)
- ec_generate(params->eckey, params->keysize, progress_update, &prog);
+ ec_generate(params->eckey, params->curve_bits, progress_update, &prog);
else if (params->keytype == ED25519)
- ec_edgenerate(params->eckey, params->keysize, progress_update, &prog);
+ ec_edgenerate(params->eckey, 256, progress_update, &prog);
else
- rsa_generate(params->key, params->keysize, progress_update, &prog);
+ rsa_generate(params->key, params->key_bits, progress_update, &prog);
PostMessage(params->dialog, WM_DONEKEY, 0, 0);
int generation_thread_exists;
int key_exists;
int entropy_got, entropy_required, entropy_size;
- int keysize;
+ int key_bits, curve_bits;
int ssh2;
keytype keytype;
char **commentptr; /* points to key.comment or ssh2key.comment */
IDC_TYPESTATIC, IDC_KEYSSH1, IDC_KEYSSH2RSA, IDC_KEYSSH2DSA,
IDC_KEYSSH2ECDSA, IDC_KEYSSH2ED25519,
IDC_BITSSTATIC, IDC_BITS,
+ IDC_CURVESTATIC, IDC_CURVE,
+ IDC_NOTHINGSTATIC,
IDC_ABOUT,
IDC_GIVEHELP,
IDC_IMPORT,
}
}
+/*
+ * Helper functions to set the key type, taking care of keeping the
+ * menu and radio button selections in sync and also showing/hiding
+ * the appropriate size/curve control for the current key type.
+ */
+void ui_update_key_type_ctrls(HWND hwnd)
+{
+ enum { BITS, CURVE, NOTHING } which;
+ static const int bits_ids[] = {
+ IDC_BITSSTATIC, IDC_BITS, 0
+ };
+ static const int curve_ids[] = {
+ IDC_CURVESTATIC, IDC_CURVE, 0
+ };
+ static const int nothing_ids[] = {
+ IDC_NOTHINGSTATIC, 0
+ };
+
+ if (IsDlgButtonChecked(hwnd, IDC_KEYSSH1) ||
+ IsDlgButtonChecked(hwnd, IDC_KEYSSH2RSA) ||
+ IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA)) {
+ which = BITS;
+ } else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ECDSA)) {
+ which = CURVE;
+ } else {
+ /* ED25519 implicitly only supports one curve */
+ which = NOTHING;
+ }
+
+ hidemany(hwnd, bits_ids, which != BITS);
+ hidemany(hwnd, curve_ids, which != CURVE);
+ hidemany(hwnd, nothing_ids, which != NOTHING);
+}
+void ui_set_key_type(HWND hwnd, struct MainDlgState *state, int button)
+{
+ CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2ED25519, button);
+ CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2ED25519,
+ button, MF_BYCOMMAND);
+ ui_update_key_type_ctrls(hwnd);
+}
+
void load_key_file(HWND hwnd, struct MainDlgState *state,
Filename *filename, int was_import_cmd)
{
{
struct ctlpos cp, cp2;
+ int ymax;
- /* Accelerators used: acglops1rbde */
+ /* Accelerators used: acglops1rbvde */
ctlposinit(&cp, hwnd, 4, 4, 4);
beginbox(&cp, "Key", IDC_BOX_KEY);
"ED&25519", IDC_KEYSSH2ED25519,
"SSH-&1 (RSA)", IDC_KEYSSH1,
NULL);
- staticedit(&cp, "Number of &bits in a generated key:",
+ cp2 = cp;
+ staticedit(&cp2, "Number of &bits in a generated key:",
IDC_BITSSTATIC, IDC_BITS, 20);
+ ymax = cp2.ypos;
+ cp2 = cp;
+ staticddl(&cp2, "Cur&ve to use for generating this key:",
+ IDC_CURVESTATIC, IDC_CURVE, 20);
+ SendDlgItemMessage(hwnd, IDC_CURVE, CB_RESETCONTENT, 0, 0);
+ {
+ int i, bits;
+ const struct ec_curve *curve;
+ const struct ssh_signkey *alg;
+
+ for (i = 0; i < n_ec_nist_curve_lengths; i++) {
+ bits = ec_nist_curve_lengths[i];
+ ec_nist_alg_and_curve_by_bits(bits, &curve, &alg);
+ SendDlgItemMessage(hwnd, IDC_CURVE, CB_ADDSTRING, 0,
+ (LPARAM)curve->textname);
+ }
+ }
+ ymax = ymax > cp2.ypos ? ymax : cp2.ypos;
+ cp2 = cp;
+ statictext(&cp2, "(nothing to configure for this key type)",
+ 1, IDC_NOTHINGSTATIC);
+ ymax = ymax > cp2.ypos ? ymax : cp2.ypos;
+ cp.ypos = ymax;
endbox(&cp);
}
- 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);
+ ui_set_key_type(hwnd, state, IDC_KEYSSH2RSA);
+ SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEY_BITS, FALSE);
+ SendDlgItemMessage(hwnd, IDC_CURVE, CB_SETCURSEL,
+ DEFAULT_CURVE_INDEX, 0);
/*
* Initially, hide the progress bar and the key display,
params = snew(struct rsa_key_thread_params);
params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);
params->dialog = hwnd;
- params->keysize = state->keysize;
+ params->key_bits = state->key_bits;
+ params->curve_bits = state->curve_bits;
params->keytype = state->keytype;
params->key = &state->key;
params->dsskey = &state->dsskey;
{
state = (struct MainDlgState *)
GetWindowLongPtr(hwnd, GWLP_USERDATA);
- if (!IsDlgButtonChecked(hwnd, LOWORD(wParam)))
- CheckRadioButton(hwnd,
- IDC_KEYSSH1, IDC_KEYSSH2ED25519,
- LOWORD(wParam));
- CheckMenuRadioItem(state->keymenu,
- IDC_KEYSSH1, IDC_KEYSSH2ED25519,
- LOWORD(wParam), MF_BYCOMMAND);
+ ui_set_key_type(hwnd, state, LOWORD(wParam));
}
break;
case IDC_QUIT:
(struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (!state->generation_thread_exists) {
BOOL ok;
- state->keysize = GetDlgItemInt(hwnd, IDC_BITS, &ok, FALSE);
+ state->key_bits = GetDlgItemInt(hwnd, IDC_BITS, &ok, FALSE);
if (!ok)
- state->keysize = DEFAULT_KEYSIZE;
+ state->key_bits = DEFAULT_KEY_BITS;
+ {
+ int curveindex = SendDlgItemMessage(hwnd, IDC_CURVE,
+ CB_GETCURSEL, 0, 0);
+ assert(curveindex >= 0);
+ assert(curveindex < n_ec_nist_curve_lengths);
+ state->curve_bits = ec_nist_curve_lengths[curveindex];
+ }
/* If we ever introduce a new key type, check it here! */
state->ssh2 = !IsDlgButtonChecked(hwnd, IDC_KEYSSH1);
state->keytype = RSA;
} else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ED25519)) {
state->keytype = ED25519;
}
- if (state->keysize < 256) {
- int ret = MessageBox(hwnd,
- "PuTTYgen will not generate a key"
- " smaller than 256 bits.\n"
- "Key length reset to 256. Continue?",
- "PuTTYgen Warning",
+ if ((state->keytype == RSA || state->keytype == DSA) &&
+ state->key_bits < 256) {
+ char *message = dupprintf
+ ("PuTTYgen will not generate a key smaller than 256"
+ " bits.\nKey length reset to default %d. Continue?",
+ DEFAULT_KEY_BITS);
+ int ret = MessageBox(hwnd, message, "PuTTYgen Warning",
MB_ICONWARNING | MB_OKCANCEL);
+ sfree(message);
if (ret != IDOK)
break;
- state->keysize = 256;
- SetDlgItemInt(hwnd, IDC_BITS, 256, FALSE);
+ state->key_bits = DEFAULT_KEY_BITS;
+ SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEY_BITS, 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);
- }
- if (state->keytype == ED25519 && state->keysize != 256) {
- int ret = MessageBox(hwnd,
- "Only 256 bit Edwards 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;
* so with 2 bits per mouse movement we expect 2
* bits every 2 words.
*/
- state->entropy_required = (state->keysize / 2) * 2;
+ if (state->keytype == RSA || state->keytype == DSA)
+ state->entropy_required = (state->key_bits / 2) * 2;
+ else if (state->keytype == ECDSA)
+ state->entropy_required = (state->curve_bits / 2) * 2;
+ else
+ state->entropy_required = 256;
+
state->entropy_got = 0;
state->entropy_size = (state->entropy_required *
sizeof(unsigned));