#include <time.h>
#include <stdio.h>
#include <stdlib.h>
+#include <assert.h>
#define PUTTY_DO_GLOBALS
#include "putty.h"
#include "ssh.h"
+#include "licence.h"
+#include "winsecur.h"
#include <commctrl.h>
#define ICON_BIG 1
#endif
-#define WM_DONEKEY (WM_XUSER + 1)
+#define WM_DONEKEY (WM_APP + 1)
-#define DEFAULT_KEYSIZE 1024
+#define DEFAULT_KEY_BITS 2048
+#define DEFAULT_CURVE_INDEX 0
static char *cmdline_keyfile = NULL;
/*
* Print a modal (Really Bad) message box and perform a fatal exit.
*/
-void modalfatalbox(char *fmt, ...)
+void modalfatalbox(const char *fmt, ...)
{
va_list ap;
char *stuff;
exit(1);
}
+/*
+ * Print a non-fatal message box and do not exit.
+ */
+void nonfatal(const char *fmt, ...)
+{
+ va_list ap;
+ char *stuff;
+
+ va_start(ap, fmt);
+ stuff = dupvprintf(fmt, ap);
+ va_end(ap);
+ MessageBox(NULL, stuff, "PuTTYgen Error",
+ MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
+ sfree(stuff);
+}
+
/* ----------------------------------------------------------------------
* Progress report code. This is really horrible :-)
*/
}
}
-extern char ver[];
-
-#define PASSPHRASE_MAXLEN 512
+extern const char ver[];
struct PassphraseProcStruct {
- char *passphrase;
+ char **passphrase;
char *comment;
};
/*
* Dialog-box function for the passphrase box.
*/
-static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK PassphraseProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
- static char *passphrase = NULL;
+ static char **passphrase = NULL;
struct PassphraseProcStruct *p;
switch (msg) {
passphrase = p->passphrase;
if (p->comment)
SetDlgItemText(hwnd, 101, p->comment);
- *passphrase = 0;
- SetDlgItemText(hwnd, 102, passphrase);
+ burnstr(*passphrase);
+ *passphrase = dupstr("");
+ SetDlgItemText(hwnd, 102, *passphrase);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
return 0;
case 102: /* edit box */
if ((HIWORD(wParam) == EN_CHANGE) && passphrase) {
- GetDlgItemText(hwnd, 102, passphrase,
- PASSPHRASE_MAXLEN - 1);
- passphrase[PASSPHRASE_MAXLEN - 1] = '\0';
+ burnstr(*passphrase);
+ *passphrase = GetDlgItemText_alloc(hwnd, 102);
}
return 0;
}
/*
* Dialog-box function for the Licence box.
*/
-static int CALLBACK LicenceProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK LicenceProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg) {
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)) {
/*
* Dialog-box function for the About box.
*/
-static int CALLBACK AboutProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK AboutProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch (msg) {
rd.right - rd.left, rd.bottom - rd.top, TRUE);
}
- SetDlgItemText(hwnd, 100, ver);
+ {
+ char *text = dupprintf
+ ("PuTTYgen\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)) {
return 0;
}
+typedef enum {RSA, DSA, ECDSA, ED25519} keytype;
+
/*
* Thread to generate a key.
*/
struct rsa_key_thread_params {
HWND progressbar; /* notify this with progress */
HWND dialog; /* notify this on completion */
- int keysize; /* bits in key */
- int is_dsa;
- struct RSAKey *key;
- struct dss_key *dsskey;
+ int key_bits; /* bits in key modulus (RSA, DSA) */
+ int curve_bits; /* bits in elliptic curve (ECDSA) */
+ keytype keytype;
+ union {
+ struct RSAKey *key;
+ struct dss_key *dsskey;
+ struct ec_key *eckey;
+ };
};
-static DWORD WINAPI generate_rsa_key_thread(void *param)
+static DWORD WINAPI generate_key_thread(void *param)
{
struct rsa_key_thread_params *params =
(struct rsa_key_thread_params *) param;
progress_update(&prog, PROGFN_INITIALISE, 0, 0);
- if (params->is_dsa)
- dsa_generate(params->dsskey, params->keysize, progress_update, &prog);
+ if (params->keytype == DSA)
+ dsa_generate(params->dsskey, params->key_bits, progress_update, &prog);
+ else if (params->keytype == ECDSA)
+ ec_generate(params->eckey, params->curve_bits, progress_update, &prog);
+ else if (params->keytype == ED25519)
+ 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 ssh2, is_dsa;
+ int key_bits, curve_bits;
+ int ssh2;
+ keytype keytype;
char **commentptr; /* points to key.comment or ssh2key.comment */
struct ssh2_userkey ssh2key;
unsigned *entropy;
- struct RSAKey key;
- struct dss_key dsskey;
+ union {
+ struct RSAKey key;
+ struct dss_key dsskey;
+ struct ec_key eckey;
+ };
HMENU filemenu, keymenu, cvtmenu;
};
static void setupbigedit1(HWND hwnd, int id, int idstatic, struct RSAKey *key)
{
- char *buffer;
- char *dec1, *dec2;
-
- dec1 = bignum_decimal(key->exponent);
- dec2 = bignum_decimal(key->modulus);
- buffer = dupprintf("%d %s %s %s", bignum_bitcount(key->modulus),
- dec1, dec2, key->comment);
+ char *buffer = ssh1_pubkey_str(key);
SetDlgItemText(hwnd, id, buffer);
SetDlgItemText(hwnd, idstatic,
"&Public key for pasting into authorized_keys file:");
- sfree(dec1);
- sfree(dec2);
sfree(buffer);
}
static void setupbigedit2(HWND hwnd, int id, int idstatic,
struct ssh2_userkey *key)
{
- unsigned char *pub_blob;
- char *buffer, *p;
- int pub_len;
- int i;
-
- pub_blob = key->alg->public_blob(key->data, &pub_len);
- buffer = snewn(strlen(key->alg->name) + 4 * ((pub_len + 2) / 3) +
- strlen(key->comment) + 3, char);
- strcpy(buffer, key->alg->name);
- p = buffer + strlen(buffer);
- *p++ = ' ';
- i = 0;
- while (i < pub_len) {
- int n = (pub_len - i < 3 ? pub_len - i : 3);
- base64_encode_atom(pub_blob + i, n, p);
- i += n;
- p += 4;
- }
- *p++ = ' ';
- strcpy(p, key->comment);
+ char *buffer = ssh2_pubkey_openssh_str(key);
SetDlgItemText(hwnd, id, buffer);
SetDlgItemText(hwnd, idstatic, "&Public key for pasting into "
"OpenSSH authorized_keys file:");
- sfree(pub_blob);
sfree(buffer);
}
-static int save_ssh1_pubkey(char *filename, struct RSAKey *key)
-{
- char *dec1, *dec2;
- FILE *fp;
-
- dec1 = bignum_decimal(key->exponent);
- dec2 = bignum_decimal(key->modulus);
- fp = fopen(filename, "wb");
- if (!fp)
- return 0;
- fprintf(fp, "%d %s %s %s\n",
- bignum_bitcount(key->modulus), dec1, dec2, key->comment);
- fclose(fp);
- sfree(dec1);
- sfree(dec2);
- return 1;
-}
-
/*
* Warn about the obsolescent key file format.
*/
{
static const char mbtitle[] = "PuTTY Key File Warning";
static const char message[] =
- "You are loading an SSH 2 private key which has an\n"
+ "You are loading an SSH-2 private key which has an\n"
"old version of the file format. This means your key\n"
"file is not fully tamperproof. Future versions of\n"
"PuTTY may stop supporting this private key format,\n"
MessageBox(NULL, message, mbtitle, MB_OK);
}
-static int save_ssh2_pubkey(char *filename, struct ssh2_userkey *key)
-{
- unsigned char *pub_blob;
- char *p;
- int pub_len;
- int i, column;
- FILE *fp;
-
- pub_blob = key->alg->public_blob(key->data, &pub_len);
-
- fp = fopen(filename, "wb");
- if (!fp)
- return 0;
-
- fprintf(fp, "---- BEGIN SSH2 PUBLIC KEY ----\n");
-
- fprintf(fp, "Comment: \"");
- for (p = key->comment; *p; p++) {
- if (*p == '\\' || *p == '\"')
- fputc('\\', fp);
- fputc(*p, fp);
- }
- fprintf(fp, "\"\n");
-
- i = 0;
- column = 0;
- while (i < pub_len) {
- char buf[5];
- int n = (pub_len - i < 3 ? pub_len - i : 3);
- base64_encode_atom(pub_blob + i, n, buf);
- i += n;
- buf[4] = '\0';
- fputs(buf, fp);
- if (++column >= 16) {
- fputc('\n', fp);
- column = 0;
- }
- }
- if (column > 0)
- fputc('\n', fp);
-
- fprintf(fp, "---- END SSH2 PUBLIC KEY ----\n");
- fclose(fp);
- sfree(pub_blob);
- return 1;
-}
-
enum {
controlidstart = 100,
IDC_QUIT,
IDC_SAVESTATIC, IDC_SAVE, IDC_SAVEPUB,
IDC_BOX_PARAMS,
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, IDC_EXPORT_OPENSSH, IDC_EXPORT_SSHCOM
+ IDC_IMPORT,
+ IDC_EXPORT_OPENSSH_AUTO, IDC_EXPORT_OPENSSH_NEW,
+ IDC_EXPORT_SSHCOM
};
static const int nokey_ids[] = { IDC_NOKEY, 0 };
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_KEYSSH2ED25519), 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);
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->keymenu, IDC_KEYSSH2ED25519,
+ 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_AUTO,
+ 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);
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_KEYSSH2ED25519), 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);
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->keymenu, IDC_KEYSSH2ED25519,
+ 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_AUTO,
+ 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);
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_KEYSSH2ED25519), 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);
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->keymenu, IDC_KEYSSH2ED25519,
+ MF_ENABLED|MF_BYCOMMAND);
EnableMenuItem(state->cvtmenu, IDC_IMPORT, MF_ENABLED|MF_BYCOMMAND);
/*
* Enable export menu items if and only if the key type
#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_AUTO, SSH_KEYTYPE_OPENSSH_AUTO);
+ 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;
}
}
+/*
+ * 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)
+ Filename *filename, int was_import_cmd)
{
- char passphrase[PASSPHRASE_MAXLEN];
+ char *passphrase;
int needs_pass;
int type, realtype;
int ret;
const char *errmsg = NULL;
char *comment;
- struct PassphraseProcStruct pps;
struct RSAKey newkey1;
struct ssh2_userkey *newkey2 = NULL;
- type = realtype = key_type(&filename);
+ type = realtype = key_type(filename);
if (type != SSH_KEYTYPE_SSH1 &&
type != SSH_KEYTYPE_SSH2 &&
!import_possible(type)) {
char *msg = dupprintf("Couldn't load private key (%s)",
key_type_to_str(type));
- MessageBox(NULL, msg,
- "PuTTYgen Error", MB_OK | MB_ICONERROR);
+ message_box(msg, "PuTTYgen Error", MB_OK | MB_ICONERROR,
+ HELPCTXID(errors_cantloadkey));
sfree(msg);
return;
}
}
comment = NULL;
+ passphrase = NULL;
if (realtype == SSH_KEYTYPE_SSH1)
- needs_pass = rsakey_encrypted(&filename, &comment);
+ needs_pass = rsakey_encrypted(filename, &comment);
else if (realtype == SSH_KEYTYPE_SSH2)
- needs_pass =
- ssh2_userkey_encrypted(&filename, &comment);
+ needs_pass = ssh2_userkey_encrypted(filename, &comment);
else
- needs_pass = import_encrypted(&filename, realtype,
- &comment);
- pps.passphrase = passphrase;
- pps.comment = comment;
+ needs_pass = import_encrypted(filename, realtype, &comment);
do {
+ burnstr(passphrase);
+ passphrase = NULL;
+
if (needs_pass) {
int dlgret;
+ struct PassphraseProcStruct pps;
+ pps.passphrase = &passphrase;
+ pps.comment = comment;
dlgret = DialogBoxParam(hinst,
MAKEINTRESOURCE(210),
NULL, PassphraseProc,
- (LPARAM) & pps);
+ (LPARAM) &pps);
if (!dlgret) {
ret = -2;
break;
}
+ assert(passphrase != NULL);
} else
- *passphrase = '\0';
+ passphrase = dupstr("");
if (type == SSH_KEYTYPE_SSH1) {
if (realtype == type)
- ret = loadrsakey(&filename, &newkey1,
- passphrase, &errmsg);
+ ret = loadrsakey(filename, &newkey1, passphrase, &errmsg);
else
- ret = import_ssh1(&filename, realtype,
- &newkey1, passphrase, &errmsg);
+ ret = import_ssh1(filename, realtype, &newkey1,
+ passphrase, &errmsg);
} else {
if (realtype == type)
- newkey2 = ssh2_load_userkey(&filename,
- passphrase, &errmsg);
+ newkey2 = ssh2_load_userkey(filename, passphrase, &errmsg);
else
- newkey2 = import_ssh2(&filename, realtype,
- passphrase, &errmsg);
+ newkey2 = import_ssh2(filename, realtype, passphrase, &errmsg);
if (newkey2 == SSH2_WRONG_PASSPHRASE)
ret = -1;
else if (!newkey2)
sfree(comment);
if (ret == 0) {
char *msg = dupprintf("Couldn't load private key (%s)", errmsg);
- MessageBox(NULL, msg, "PuTTYgen Error", MB_OK | MB_ICONERROR);
+ message_box(msg, "PuTTYgen Error", MB_OK | MB_ICONERROR,
+ HELPCTXID(errors_cantloadkey));
sfree(msg);
} else if (ret == 1) {
/*
savecomment = state->ssh2key.comment;
state->ssh2key.comment = NULL;
- fp =
- state->ssh2key.alg->
- fingerprint(state->ssh2key.data);
+ fp = ssh2_fingerprint(state->ssh2key.alg, state->ssh2key.data);
state->ssh2key.comment = savecomment;
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
MB_OK | MB_ICONINFORMATION);
}
}
+ burnstr(passphrase);
}
/*
* Dialog-box function for the main PuTTYgen dialog box.
*/
-static int CALLBACK MainDlgProc(HWND hwnd, UINT msg,
+static INT_PTR CALLBACK MainDlgProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
static const char generating_msg[] =
switch (msg) {
case WM_INITDIALOG:
- if (help_path)
- SetWindowLong(hwnd, GWL_EXSTYLE,
- GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP);
+ if (has_help())
+ SetWindowLongPtr(hwnd, GWL_EXSTYLE,
+ GetWindowLongPtr(hwnd, GWL_EXSTYLE) |
+ WS_EX_CONTEXTHELP);
else {
/*
* If we add a Help button, this is where we destroy it
* if the help file isn't present.
*/
}
- requested_help = FALSE;
SendMessage(hwnd, WM_SETICON, (WPARAM) ICON_BIG,
(LPARAM) LoadIcon(hinst, MAKEINTRESOURCE(200)));
state->collecting_entropy = FALSE;
state->entropy = NULL;
state->key_exists = FALSE;
- SetWindowLong(hwnd, GWL_USERDATA, (LONG) state);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) state);
{
HMENU menu, menu1;
AppendMenu(menu1, MF_ENABLED, IDC_SAVE, "&Save private key");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
AppendMenu(menu1, MF_ENABLED, IDC_QUIT, "E&xit");
- AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&File");
+ AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT_PTR) menu1, "&File");
state->filemenu = menu1;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_GENERATE, "&Generate key pair");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
- AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH1, "SSH&1 key (RSA)");
- AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2RSA, "SSH2 &RSA key");
- AppendMenu(menu1, MF_ENABLED, IDC_KEYSSH2DSA, "SSH2 &DSA key");
- AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Key");
+ 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(menu1, MF_ENABLED, IDC_KEYSSH2ED25519, "SSH-2 ED&25519 key");
+ AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT_PTR) menu1, "&Key");
state->keymenu = menu1;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_IMPORT, "&Import key");
AppendMenu(menu1, MF_SEPARATOR, 0, 0);
- AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH,
+ AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH_AUTO,
"Export &OpenSSH key");
+ AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_OPENSSH_NEW,
+ "Export &OpenSSH key (force new file format)");
AppendMenu(menu1, MF_ENABLED, IDC_EXPORT_SSHCOM,
"Export &ssh.com key");
- AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1,
+ AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT_PTR) menu1,
"Con&versions");
state->cvtmenu = menu1;
menu1 = CreateMenu();
AppendMenu(menu1, MF_ENABLED, IDC_ABOUT, "&About");
- if (help_path)
+ if (has_help())
AppendMenu(menu1, MF_ENABLED, IDC_GIVEHELP, "&Help");
- AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT) menu1, "&Help");
+ AppendMenu(menu, MF_POPUP | MF_ENABLED, (UINT_PTR) menu1, "&Help");
SetMenu(hwnd, menu);
}
{
struct ctlpos cp, cp2;
+ int ymax;
- /* Accelerators used: acglops1rbd */
+ /* Accelerators used: acglops1rbvde */
ctlposinit(&cp, hwnd, 4, 4, 4);
beginbox(&cp, "Key", IDC_BOX_KEY);
"&Save private key", IDC_SAVE);
endbox(&cp);
beginbox(&cp, "Parameters", IDC_BOX_PARAMS);
- radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 3,
- "SSH&1 (RSA)", IDC_KEYSSH1,
- "SSH2 &RSA", IDC_KEYSSH2RSA,
- "SSH2 &DSA", IDC_KEYSSH2DSA, NULL);
- staticedit(&cp, "Number of &bits in a generated key:",
+ radioline(&cp, "Type of key to generate:", IDC_TYPESTATIC, 5,
+ "&RSA", IDC_KEYSSH2RSA,
+ "&DSA", IDC_KEYSSH2DSA,
+ "&ECDSA", IDC_KEYSSH2ECDSA,
+ "ED&25519", IDC_KEYSSH2ED25519,
+ "SSH-&1 (RSA)", IDC_KEYSSH1,
+ NULL);
+ 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_KEYSSH2DSA, IDC_KEYSSH2RSA);
- CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,
- 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,
/*
* Load a key file if one was provided on the command line.
*/
- if (cmdline_keyfile)
- load_key_file(hwnd, state, filename_from_str(cmdline_keyfile), 0);
+ if (cmdline_keyfile) {
+ Filename *fn = filename_from_str(cmdline_keyfile);
+ load_key_file(hwnd, state, fn, 0);
+ filename_free(fn);
+ }
return 1;
case WM_MOUSEMOVE:
- state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (state->collecting_entropy &&
state->entropy && state->entropy_got < state->entropy_required) {
state->entropy[state->entropy_got++] = lParam;
* Seed the entropy pool
*/
random_add_heavynoise(state->entropy, state->entropy_size);
- memset(state->entropy, 0, state->entropy_size);
+ smemclr(state->entropy, state->entropy_size);
sfree(state->entropy);
state->collecting_entropy = FALSE;
params = snew(struct rsa_key_thread_params);
params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);
params->dialog = hwnd;
- params->keysize = state->keysize;
- params->is_dsa = state->is_dsa;
+ params->key_bits = state->key_bits;
+ params->curve_bits = state->curve_bits;
+ params->keytype = state->keytype;
params->key = &state->key;
params->dsskey = &state->dsskey;
- if (!CreateThread(NULL, 0, generate_rsa_key_thread,
+ if (!CreateThread(NULL, 0, generate_key_thread,
params, 0, &threadid)) {
MessageBox(hwnd, "Out of thread resources",
"Key generation error",
case IDC_KEYSSH1:
case IDC_KEYSSH2RSA:
case IDC_KEYSSH2DSA:
+ case IDC_KEYSSH2ECDSA:
+ case IDC_KEYSSH2ED25519:
{
state = (struct MainDlgState *)
- GetWindowLong(hwnd, GWL_USERDATA);
- if (!IsDlgButtonChecked(hwnd, LOWORD(wParam)))
- CheckRadioButton(hwnd, IDC_KEYSSH1, IDC_KEYSSH2DSA,
- LOWORD(wParam));
- CheckMenuRadioItem(state->keymenu, IDC_KEYSSH1, IDC_KEYSSH2DSA,
- LOWORD(wParam), MF_BYCOMMAND);
+ GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ ui_set_key_type(hwnd, state, LOWORD(wParam));
}
break;
case IDC_QUIT:
case IDC_COMMENTEDIT:
if (HIWORD(wParam) == EN_CHANGE) {
state = (struct MainDlgState *)
- GetWindowLong(hwnd, GWL_USERDATA);
+ GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (state->key_exists) {
HWND editctl = GetDlgItem(hwnd, IDC_COMMENTEDIT);
int len = GetWindowTextLength(editctl);
case IDC_GIVEHELP:
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
- if (help_path) {
- WinHelp(hwnd, help_path, HELP_COMMAND,
- (DWORD)"JI(`',`puttygen.general')");
- requested_help = TRUE;
- }
+ launch_help(hwnd, WINHELP_CTX_puttygen_general);
}
return 0;
case IDC_GENERATE:
HIWORD(wParam) != BN_DOUBLECLICKED)
break;
state =
- (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ (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->is_dsa = IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA);
- 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",
+ state->keytype = RSA;
+ if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2DSA)) {
+ state->keytype = DSA;
+ } else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ECDSA)) {
+ state->keytype = ECDSA;
+ } else if (IsDlgButtonChecked(hwnd, IDC_KEYSSH2ED25519)) {
+ state->keytype = ED25519;
+ }
+
+ 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);
+ } else if ((state->keytype == RSA || state->keytype == DSA) &&
+ state->key_bits < DEFAULT_KEY_BITS) {
+ char *message = dupprintf
+ ("Keys shorter than %d bits are not recommended. "
+ "Really generate this key?", DEFAULT_KEY_BITS);
+ int ret = MessageBox(hwnd, message, "PuTTYgen Warning",
+ MB_ICONWARNING | MB_OKCANCEL);
+ sfree(message);
+ if (ret != IDOK)
+ break;
+ }
+
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));
}
break;
case IDC_SAVE:
- case IDC_EXPORT_OPENSSH:
+ case IDC_EXPORT_OPENSSH_AUTO:
+ case IDC_EXPORT_OPENSSH_NEW:
case IDC_EXPORT_SSHCOM:
if (HIWORD(wParam) != BN_CLICKED)
break;
state =
- (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (state->key_exists) {
char filename[FILENAME_MAX];
- char passphrase[PASSPHRASE_MAXLEN];
- char passphrase2[PASSPHRASE_MAXLEN];
+ char *passphrase, *passphrase2;
int type, realtype;
if (state->ssh2)
else
realtype = SSH_KEYTYPE_SSH1;
- if (LOWORD(wParam) == IDC_EXPORT_OPENSSH)
- type = SSH_KEYTYPE_OPENSSH;
+ if (LOWORD(wParam) == IDC_EXPORT_OPENSSH_AUTO)
+ type = SSH_KEYTYPE_OPENSSH_AUTO;
+ 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
if (type != realtype &&
import_target_type(type) != realtype) {
char msg[256];
- sprintf(msg, "Cannot export an SSH%d key in an SSH%d"
+ sprintf(msg, "Cannot export an SSH-%d key in an SSH-%d"
" format", (state->ssh2 ? 2 : 1),
(state->ssh2 ? 1 : 2));
MessageBox(hwnd, msg,
break;
}
- GetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,
- passphrase, sizeof(passphrase));
- GetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,
- passphrase2, sizeof(passphrase2));
+ passphrase = GetDlgItemText_alloc(hwnd, IDC_PASSPHRASE1EDIT);
+ passphrase2 = GetDlgItemText_alloc(hwnd, IDC_PASSPHRASE2EDIT);
if (strcmp(passphrase, passphrase2)) {
MessageBox(hwnd,
"The two passphrases given do not match.",
"PuTTYgen Error", MB_OK | MB_ICONERROR);
+ burnstr(passphrase);
+ burnstr(passphrase2);
break;
}
+ burnstr(passphrase2);
if (!*passphrase) {
int ret;
ret = MessageBox(hwnd,
"without a passphrase to protect it?",
"PuTTYgen Warning",
MB_YESNO | MB_ICONWARNING);
- if (ret != IDYES)
- break;
+ if (ret != IDYES) {
+ burnstr(passphrase);
+ break;
+ }
}
if (prompt_keyfile(hwnd, "Save private key as:",
filename, 1, (type == realtype))) {
ret = MessageBox(hwnd, buffer, "PuTTYgen Warning",
MB_YESNO | MB_ICONWARNING);
sfree(buffer);
- if (ret != IDYES)
+ if (ret != IDYES) {
+ burnstr(passphrase);
break;
+ }
}
if (state->ssh2) {
- Filename fn = filename_from_str(filename);
+ Filename *fn = filename_from_str(filename);
if (type != realtype)
- ret = export_ssh2(&fn, type, &state->ssh2key,
+ ret = export_ssh2(fn, type, &state->ssh2key,
*passphrase ? passphrase : NULL);
else
- ret = ssh2_save_userkey(&fn, &state->ssh2key,
+ ret = ssh2_save_userkey(fn, &state->ssh2key,
*passphrase ? passphrase :
NULL);
+ filename_free(fn);
} else {
- Filename fn = filename_from_str(filename);
+ Filename *fn = filename_from_str(filename);
if (type != realtype)
- ret = export_ssh1(&fn, type, &state->key,
+ ret = export_ssh1(fn, type, &state->key,
*passphrase ? passphrase : NULL);
else
- ret = saversakey(&fn, &state->key,
+ ret = saversakey(fn, &state->key,
*passphrase ? passphrase : NULL);
+ filename_free(fn);
}
if (ret <= 0) {
MessageBox(hwnd, "Unable to save key file",
"PuTTYgen Error", MB_OK | MB_ICONERROR);
}
}
+ burnstr(passphrase);
}
break;
case IDC_SAVEPUB:
if (HIWORD(wParam) != BN_CLICKED)
break;
state =
- (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (state->key_exists) {
char filename[FILENAME_MAX];
if (prompt_keyfile(hwnd, "Save public key as:",
if (ret != IDYES)
break;
}
- if (state->ssh2) {
- ret = save_ssh2_pubkey(filename, &state->ssh2key);
- } else {
- ret = save_ssh1_pubkey(filename, &state->key);
- }
- if (ret <= 0) {
- MessageBox(hwnd, "Unable to save key file",
- "PuTTYgen Error", MB_OK | MB_ICONERROR);
- }
+ fp = fopen(filename, "w");
+ if (!fp) {
+ MessageBox(hwnd, "Unable to open key file",
+ "PuTTYgen Error", MB_OK | MB_ICONERROR);
+ } else {
+ if (state->ssh2) {
+ int bloblen;
+ unsigned char *blob;
+ blob = state->ssh2key.alg->public_blob
+ (state->ssh2key.data, &bloblen);
+ ssh2_write_pubkey(fp, state->ssh2key.comment,
+ blob, bloblen,
+ SSH_KEYTYPE_SSH2_PUBLIC_RFC4716);
+ } else {
+ ssh1_write_pubkey(fp, &state->key);
+ }
+ if (fclose(fp) < 0) {
+ MessageBox(hwnd, "Unable to save key file",
+ "PuTTYgen Error", MB_OK | MB_ICONERROR);
+ }
+ }
}
}
break;
if (HIWORD(wParam) != BN_CLICKED)
break;
state =
- (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (!state->generation_thread_exists) {
char filename[FILENAME_MAX];
if (prompt_keyfile(hwnd, "Load private key:",
- filename, 0, LOWORD(wParam)==IDC_LOAD))
- load_key_file(hwnd, state, filename_from_str(filename),
- LOWORD(wParam) != IDC_LOAD);
+ filename, 0, LOWORD(wParam)==IDC_LOAD)) {
+ Filename *fn = filename_from_str(filename);
+ load_key_file(hwnd, state, fn, LOWORD(wParam) != IDC_LOAD);
+ filename_free(fn);
+ }
}
break;
}
return 0;
case WM_DONEKEY:
- state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
state->generation_thread_exists = FALSE;
state->key_exists = TRUE;
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETRANGE, 0,
MAKELPARAM(0, PROGRESSRANGE));
SendDlgItemMessage(hwnd, IDC_PROGRESS, PBM_SETPOS, PROGRESSRANGE, 0);
if (state->ssh2) {
- if (state->is_dsa) {
+ if (state->keytype == DSA) {
state->ssh2key.data = &state->dsskey;
state->ssh2key.alg = &ssh_dss;
+ } else if (state->keytype == ECDSA) {
+ state->ssh2key.data = &state->eckey;
+ state->ssh2key.alg = state->eckey.signalg;
+ } else if (state->keytype == ED25519) {
+ state->ssh2key.data = &state->eckey;
+ state->ssh2key.alg = &ssh_ecdsa_ed25519;
} else {
state->ssh2key.data = &state->key;
state->ssh2key.alg = &ssh_rsa;
{
struct tm tm;
tm = ltime();
- if (state->is_dsa)
+ 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 if (state->keytype == ED25519)
+ strftime(*state->commentptr, 30, "ed25519-key-%Y%m%d", &tm);
else
strftime(*state->commentptr, 30, "rsa-key-%Y%m%d", &tm);
}
*state->commentptr = NULL;
if (state->ssh2) {
char *fp;
- fp = state->ssh2key.alg->fingerprint(state->ssh2key.data);
+ fp = ssh2_fingerprint(state->ssh2key.alg, state->ssh2key.data);
SetDlgItemText(hwnd, IDC_FINGERPRINT, fp);
sfree(fp);
} else {
ui_set_state(hwnd, state, 2);
break;
case WM_HELP:
- if (help_path) {
+ {
int id = ((LPHELPINFO)lParam)->iCtrlId;
- char *topic = NULL;
+ const char *topic = NULL;
switch (id) {
case IDC_GENERATING:
case IDC_PROGRESS:
case IDC_GENSTATIC:
case IDC_GENERATE:
- topic = "puttygen.generate"; break;
+ topic = WINHELP_CTX_puttygen_generate; break;
case IDC_PKSTATIC:
case IDC_KEYDISPLAY:
- topic = "puttygen.pastekey"; break;
+ topic = WINHELP_CTX_puttygen_pastekey; break;
case IDC_FPSTATIC:
case IDC_FINGERPRINT:
- topic = "puttygen.fingerprint"; break;
+ topic = WINHELP_CTX_puttygen_fingerprint; break;
case IDC_COMMENTSTATIC:
case IDC_COMMENTEDIT:
- topic = "puttygen.comment"; break;
+ topic = WINHELP_CTX_puttygen_comment; break;
case IDC_PASSPHRASE1STATIC:
case IDC_PASSPHRASE1EDIT:
case IDC_PASSPHRASE2STATIC:
case IDC_PASSPHRASE2EDIT:
- topic = "puttygen.passphrase"; break;
+ topic = WINHELP_CTX_puttygen_passphrase; break;
case IDC_LOADSTATIC:
case IDC_LOAD:
- topic = "puttygen.load"; break;
+ topic = WINHELP_CTX_puttygen_load; break;
case IDC_SAVESTATIC:
case IDC_SAVE:
- topic = "puttygen.savepriv"; break;
+ topic = WINHELP_CTX_puttygen_savepriv; break;
case IDC_SAVEPUB:
- topic = "puttygen.savepub"; break;
+ topic = WINHELP_CTX_puttygen_savepub; break;
case IDC_TYPESTATIC:
case IDC_KEYSSH1:
case IDC_KEYSSH2RSA:
case IDC_KEYSSH2DSA:
- topic = "puttygen.keytype"; break;
+ case IDC_KEYSSH2ECDSA:
+ case IDC_KEYSSH2ED25519:
+ topic = WINHELP_CTX_puttygen_keytype; break;
case IDC_BITSSTATIC:
case IDC_BITS:
- topic = "puttygen.bits"; break;
+ topic = WINHELP_CTX_puttygen_bits; break;
case IDC_IMPORT:
- case IDC_EXPORT_OPENSSH:
+ case IDC_EXPORT_OPENSSH_AUTO:
+ case IDC_EXPORT_OPENSSH_NEW:
case IDC_EXPORT_SSHCOM:
- topic = "puttygen.conversions"; break;
+ topic = WINHELP_CTX_puttygen_conversions; break;
}
if (topic) {
- char *cmd = dupprintf("JI(`',`%s')", topic);
- WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
- sfree(cmd);
- requested_help = TRUE;
+ launch_help(hwnd, topic);
} else {
MessageBeep(0);
}
}
break;
case WM_CLOSE:
- state = (struct MainDlgState *) GetWindowLong(hwnd, GWL_USERDATA);
+ state = (struct MainDlgState *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
sfree(state);
- if (requested_help) {
- WinHelp(hwnd, help_path, HELP_QUIT, 0);
- requested_help = FALSE;
- }
+ quit_help(hwnd);
EndDialog(hwnd, 1);
return 0;
}
return 0;
}
-void cleanup_exit(int code) { exit(code); }
+void cleanup_exit(int code)
+{
+ shutdown_help();
+ exit(code);
+}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
{
int argc;
char **argv;
+ int ret;
+
+ InitCommonControls();
+ hinst = inst;
+ hwnd = NULL;
+
+ /*
+ * See if we can find our Help file.
+ */
+ init_help();
split_into_argv(cmdline, &argc, &argv, NULL);
if (argc > 0) {
- /*
- * Assume the first argument to be a private key file, and
- * attempt to load it.
- */
- cmdline_keyfile = argv[0];
+ if (!strcmp(argv[0], "-pgpfp")) {
+ pgp_fingerprints();
+ exit(1);
+ } else {
+ /*
+ * Assume the first argument to be a private key file, and
+ * attempt to load it.
+ */
+ cmdline_keyfile = argv[0];
+ }
}
- InitCommonControls();
- hinst = inst;
-
+#if !defined UNPROTECT && !defined NO_SECURITY
/*
- * See if we can find our Help file.
+ * Protect our process.
*/
{
- char b[2048], *p, *q, *r;
- FILE *fp;
- GetModuleFileName(NULL, b, sizeof(b) - 1);
- r = b;
- p = strrchr(b, '\\');
- if (p && p >= r) r = p+1;
- q = strrchr(b, ':');
- if (q && q >= r) r = q+1;
- strcpy(r, PUTTY_HELP_FILE);
- if ( (fp = fopen(b, "r")) != NULL) {
- help_path = dupstr(b);
- fclose(fp);
- } else
- help_path = NULL;
+ char *error = NULL;
+ if (!setprocessacl(error)) {
+ char *message = dupprintf("Could not restrict process ACL: %s",
+ error);
+ MessageBox(NULL, message, "PuTTYgen Warning",
+ MB_ICONWARNING | MB_OK);
+ sfree(message);
+ sfree(error);
+ }
}
+#endif
random_ref();
- return DialogBox(hinst, MAKEINTRESOURCE(201), NULL,
- MainDlgProc) != IDOK;
+ ret = DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK;
+
+ cleanup_exit(ret);
+ return ret; /* just in case optimiser complains */
}