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

Windows PuTTYgen: configurable PPK save parameters.

The GUI key generator doesn't need a --reencrypt option, because you
can already just click Load and then Save without changing anything in
between. But it does need a dialog box with all the fiddly Argon2
settings in it, plus a setting to go back to PPK v2.
This commit is contained in:
Simon Tatham 2021-02-22 20:15:11 +00:00
parent 117cee8ea6
commit c10aff8a47
3 changed files with 207 additions and 1 deletions

13
windows/puttygen-rc.h Normal file
View File

@ -0,0 +1,13 @@
#define IDC_PPKVER_STATIC 100
#define IDC_PPKVER_2 101
#define IDC_PPKVER_3 102
#define IDC_ARGON2_MEM_STATIC 103
#define IDC_ARGON2_MEM 104
#define IDC_ARGON2_MEM_STATIC2 105
#define IDC_PPK_AUTO_STATIC 106
#define IDC_PPK_AUTO_YES 107
#define IDC_PPK_AUTO_NO 108
#define IDC_ARGON2_TIME_STATIC 109
#define IDC_ARGON2_TIME 110
#define IDC_ARGON2_PARALLEL_STATIC 111
#define IDC_ARGON2_PARALLEL 112

View File

@ -8,6 +8,7 @@
#define APPDESC "PuTTY SSH key generation utility" #define APPDESC "PuTTY SSH key generation utility"
#include "winhelp.rc2" #include "winhelp.rc2"
#include "puttygen-rc.h"
200 ICON "puttygen.ico" 200 ICON "puttygen.ico"
@ -53,6 +54,31 @@ BEGIN
EDITTEXT 1000, 10, 10, 306, 200, ES_READONLY | ES_MULTILINE | ES_LEFT, WS_EX_STATICEDGE EDITTEXT 1000, 10, 10, 306, 200, ES_READONLY | ES_MULTILINE | ES_LEFT, WS_EX_STATICEDGE
END END
215 DIALOG DISCARDABLE 0, 0, 240, 84
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTYgen: Private Key File Parameters"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "PPK file version:", IDC_PPKVER_STATIC, 5, 6, 115, 8
AUTORADIOBUTTON "2", IDC_PPKVER_2, 120, 5, 30, 10, WS_GROUP
AUTORADIOBUTTON "3", IDC_PPKVER_3, 150, 5, 30, 10
LTEXT "Memory to use for password hash:", IDC_ARGON2_MEM_STATIC,
5, 22, 115, 8
EDITTEXT IDC_ARGON2_MEM, 120, 20, 40, 12
LTEXT "Kb", IDC_ARGON2_MEM_STATIC2,
170, 22, 20, 8
LTEXT "Time to use for password hash:", IDC_ARGON2_TIME_STATIC,
5, 36, 115, 8
EDITTEXT IDC_ARGON2_TIME, 120, 34, 40, 12
AUTORADIOBUTTON "ms", IDC_PPK_AUTO_YES, 170, 35, 20, 10, WS_GROUP
AUTORADIOBUTTON "passes", IDC_PPK_AUTO_NO, 200, 35, 40, 10
LTEXT "Parallelism for password hash:", IDC_ARGON2_PARALLEL_STATIC,
5, 50, 115, 8
EDITTEXT IDC_ARGON2_PARALLEL, 120, 48, 60, 12
DEFPUSHBUTTON "O&K", IDOK, 70, 66, 40, 14
PUSHBUTTON "&Cancel", IDCANCEL, 130, 66, 40, 14
END
#include "version.rc2" #include "version.rc2"
#ifndef NO_MANIFESTS #ifndef NO_MANIFESTS

View File

@ -12,6 +12,7 @@
#include "sshkeygen.h" #include "sshkeygen.h"
#include "licence.h" #include "licence.h"
#include "winsecur.h" #include "winsecur.h"
#include "puttygen-rc.h"
#include <commctrl.h> #include <commctrl.h>
@ -260,6 +261,144 @@ static INT_PTR CALLBACK PassphraseProc(HWND hwnd, UINT msg,
return 0; return 0;
} }
static void try_get_dlg_item_uint32(HWND hwnd, int id, uint32_t *out)
{
char buf[128];
if (!GetDlgItemText(hwnd, id, buf, sizeof(buf)))
return;
if (!*buf)
return;
char *end;
unsigned long val = strtoul(buf, &end, 10);
if (*end)
return;
if ((val >> 16) >> 16)
return;
*out = val;
}
static ppk_save_parameters save_params;
struct PPKParams {
ppk_save_parameters params;
uint32_t time_passes, time_ms;
};
/*
* Dialog-box function for the passphrase box.
*/
static INT_PTR CALLBACK PPKParamsProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
struct PPKParams *pp;
char *buf;
if (msg == WM_INITDIALOG) {
pp = (struct PPKParams *)lParam;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pp);
} else {
pp = (struct PPKParams *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
switch (msg) {
case WM_INITDIALOG:
SetForegroundWindow(hwnd);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
/*
* Centre the window.
*/
{ /* centre the window */
RECT rs, rd;
HWND hw;
hw = GetDesktopWindow();
if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))
MoveWindow(hwnd,
(rs.right + rs.left + rd.left - rd.right) / 2,
(rs.bottom + rs.top + rd.top - rd.bottom) / 2,
rd.right - rd.left, rd.bottom - rd.top, true);
}
CheckRadioButton(hwnd, IDC_PPKVER_2, IDC_PPKVER_3,
IDC_PPKVER_2 + (pp->params.fmt_version - 2));
buf = dupprintf("%"PRIu32, pp->params.argon2_mem);
SetDlgItemText(hwnd, IDC_ARGON2_MEM, buf);
sfree(buf);
if (pp->params.argon2_passes_auto) {
CheckRadioButton(hwnd, IDC_PPK_AUTO_YES, IDC_PPK_AUTO_NO,
IDC_PPK_AUTO_YES);
buf = dupprintf("%"PRIu32, pp->time_ms);
SetDlgItemText(hwnd, IDC_ARGON2_TIME, buf);
sfree(buf);
} else {
CheckRadioButton(hwnd, IDC_PPK_AUTO_YES, IDC_PPK_AUTO_NO,
IDC_PPK_AUTO_NO);
buf = dupprintf("%"PRIu32, pp->time_passes);
SetDlgItemText(hwnd, IDC_ARGON2_TIME, buf);
sfree(buf);
}
buf = dupprintf("%"PRIu32, pp->params.argon2_parallelism);
SetDlgItemText(hwnd, IDC_ARGON2_PARALLEL, buf);
sfree(buf);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hwnd, 1);
return 0;
case IDCANCEL:
EndDialog(hwnd, 0);
return 0;
case IDC_PPKVER_2:
pp->params.fmt_version = 2;
return 0;
case IDC_PPKVER_3:
pp->params.fmt_version = 3;
return 0;
case IDC_ARGON2_MEM:
try_get_dlg_item_uint32(hwnd, IDC_ARGON2_MEM,
&pp->params.argon2_mem);
return 0;
case IDC_PPK_AUTO_YES:
pp->params.argon2_passes_auto = true;
buf = dupprintf("%"PRIu32, pp->time_ms);
SetDlgItemText(hwnd, IDC_ARGON2_TIME, buf);
sfree(buf);
return 0;
case IDC_PPK_AUTO_NO:
pp->params.argon2_passes_auto = false;
buf = dupprintf("%"PRIu32, pp->time_passes);
SetDlgItemText(hwnd, IDC_ARGON2_TIME, buf);
sfree(buf);
return 0;
case IDC_ARGON2_TIME:
try_get_dlg_item_uint32(hwnd, IDC_ARGON2_TIME,
pp->params.argon2_passes_auto ?
&pp->time_ms : &pp->time_passes);
return 0;
case IDC_ARGON2_PARALLEL:
try_get_dlg_item_uint32(hwnd, IDC_ARGON2_PARALLEL,
&pp->params.argon2_parallelism);
return 0;
}
return 0;
case WM_CLOSE:
EndDialog(hwnd, 0);
return 0;
}
return 0;
}
/* /*
* Prompt for a key file. Assumes the filename buffer is of size * Prompt for a key file. Assumes the filename buffer is of size
* FILENAME_MAX. * FILENAME_MAX.
@ -529,6 +668,7 @@ enum {
IDC_KEYSSH2ECDSA, IDC_KEYSSH2EDDSA, IDC_KEYSSH2ECDSA, IDC_KEYSSH2EDDSA,
IDC_PRIMEGEN_PROB, IDC_PRIMEGEN_MAURER_SIMPLE, IDC_PRIMEGEN_MAURER_COMPLEX, IDC_PRIMEGEN_PROB, IDC_PRIMEGEN_MAURER_SIMPLE, IDC_PRIMEGEN_MAURER_COMPLEX,
IDC_RSA_STRONG, IDC_RSA_STRONG,
IDC_PPK_PARAMS,
IDC_BITSSTATIC, IDC_BITS, IDC_BITSSTATIC, IDC_BITS,
IDC_ECCURVESTATIC, IDC_ECCURVE, IDC_ECCURVESTATIC, IDC_ECCURVE,
IDC_EDCURVESTATIC, IDC_EDCURVE, IDC_EDCURVESTATIC, IDC_EDCURVE,
@ -1006,6 +1146,9 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
AppendMenu(menu1, MF_SEPARATOR, 0, 0); AppendMenu(menu1, MF_SEPARATOR, 0, 0);
AppendMenu(menu1, MF_ENABLED, IDC_RSA_STRONG, AppendMenu(menu1, MF_ENABLED, IDC_RSA_STRONG,
"Use \"strong\" primes as RSA key factors"); "Use \"strong\" primes as RSA key factors");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
AppendMenu(menu1, MF_ENABLED, IDC_PPK_PARAMS,
"Parameters for saving key files...");
AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT_PTR) menu1, "&Key"); AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT_PTR) menu1, "&Key");
state->keymenu = menu1; state->keymenu = menu1;
@ -1214,6 +1357,28 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
ui_set_rsa_strong(hwnd, state, !state->rsa_strong); ui_set_rsa_strong(hwnd, state, !state->rsa_strong);
break; break;
} }
case IDC_PPK_PARAMS: {
struct PPKParams pp[1];
pp->params = save_params;
if (pp->params.argon2_passes_auto) {
pp->time_ms = pp->params.argon2_milliseconds;
pp->time_passes = 13;
} else {
pp->time_ms = 100;
pp->time_passes = pp->params.argon2_passes;
}
int dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(215),
NULL, PPKParamsProc, (LPARAM)pp);
if (dlgret) {
if (pp->params.argon2_passes_auto) {
pp->params.argon2_milliseconds = pp->time_ms;
} else {
pp->params.argon2_passes = pp->time_passes;
}
save_params = pp->params;
}
break;
}
case IDC_QUIT: case IDC_QUIT:
PostMessage(hwnd, WM_CLOSE, 0, 0); PostMessage(hwnd, WM_CLOSE, 0, 0);
break; break;
@ -1469,7 +1634,7 @@ static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
else else
ret = ppk_save_f(fn, &state->ssh2key, ret = ppk_save_f(fn, &state->ssh2key,
*passphrase ? passphrase : NULL, *passphrase ? passphrase : NULL,
&ppk_save_default_parameters); &save_params);
filename_free(fn); filename_free(fn);
} else { } else {
Filename *fn = filename_from_str(filename); Filename *fn = filename_from_str(filename);
@ -1748,6 +1913,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
} }
} }
save_params = ppk_save_default_parameters;
random_setup_special(); random_setup_special();
ret = DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK; ret = DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK;