Fix miscellaneous compiler warnings. Thanks to Jacob Nevins
[sgt/putty] / puttygen.c
index c633f5a..8577c6b 100644 (file)
@@ -5,10 +5,8 @@
 #include <windows.h>
 #include <commctrl.h>
 #include <time.h>
-#ifndef NO_SECURITY
-#include <aclapi.h>
-#endif
 #include <stdio.h>
+#include <stdlib.h>
 
 #define PUTTY_DO_GLOBALS
 
 
 #define WM_DONEKEY (WM_XUSER + 1)
 
-#define KEYSIZE 1024
-
-/*
- * TODO:
- *  - have some means of verifying passphrase changes against typos
- *  - prompt before overwriting an existing file
- *  - check the return value from saversakey()
- *  - test the generated keys for actual working-RSA-key-hood
- *  - variable key size
- */
+#define DEFAULT_KEYSIZE 1024
 
 /* ----------------------------------------------------------------------
  * Progress report code. This is really horrible :-)
@@ -237,6 +226,7 @@ static int CALLBACK AboutProc (HWND hwnd, UINT msg,
 struct rsa_key_thread_params {
     HWND progressbar;                  /* notify this with progress */
     HWND dialog;                       /* notify this on completion */
+    int keysize;                      /* bits in key */
     struct RSAKey *key;
     struct RSAAux *aux;
 };
@@ -246,7 +236,8 @@ static DWORD WINAPI generate_rsa_key_thread(void *param) {
     struct progress prog;
     prog.progbar = params->progressbar;
 
-    rsa_generate(params->key, params->aux, KEYSIZE, progress_update, &prog);
+    rsa_generate(params->key, params->aux,
+                params->keysize, progress_update, &prog);
 
     PostMessage(params->dialog, WM_DONEKEY, 0, 0);
 
@@ -259,6 +250,7 @@ struct MainDlgState {
     int generation_thread_exists;
     int key_exists;
     int entropy_got, entropy_required, entropy_size;
+    int keysize;
     unsigned *entropy;
     struct RSAKey key;
     struct RSAAux aux;
@@ -302,11 +294,14 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
         IDC_PKSTATIC, IDC_KEYDISPLAY,
         IDC_FPSTATIC, IDC_FINGERPRINT,
         IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
-        IDC_PASSPHRASESTATIC, IDC_PASSPHRASEEDIT,
+        IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
+        IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT,
         IDC_BOX_ACTIONS, IDC_BOXT_ACTIONS,
         IDC_GENSTATIC, IDC_GENERATE,
         IDC_LOADSTATIC, IDC_LOAD,
         IDC_SAVESTATIC, IDC_SAVE,
+        IDC_BOX_PARAMS, IDC_BOXT_PARAMS,
+        IDC_BITSSTATIC, IDC_BITS,
         IDC_ABOUT,
     };
     static const int nokey_ids[] = { IDC_NOKEY, 0 };
@@ -315,11 +310,12 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
         IDC_PKSTATIC, IDC_KEYDISPLAY,
         IDC_FPSTATIC, IDC_FINGERPRINT,
         IDC_COMMENTSTATIC, IDC_COMMENTEDIT,
-        IDC_PASSPHRASESTATIC, IDC_PASSPHRASEEDIT, 0 };
+        IDC_PASSPHRASE1STATIC, IDC_PASSPHRASE1EDIT,
+        IDC_PASSPHRASE2STATIC, IDC_PASSPHRASE2EDIT, 0 };
     static const char generating_msg[] =
         "Please wait while a key is generated...";
     static const char entropy_msg[] =
-        "Please move the mouse in this window to generate randomness";
+        "Please generate some randomness by moving the mouse over the blank area.";
     struct MainDlgState *state;
 
     switch (msg) {
@@ -331,6 +327,8 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
         {
             struct ctlpos cp, cp2;
 
+           /* Accelerators used: acglops */
+
             ctlposinit(&cp, hwnd, 10, 10, 10);
             bartitle(&cp, "Public and private key generation for PuTTY",
                     IDC_TITLE);
@@ -351,8 +349,10 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
             SendDlgItemMessage(hwnd, IDC_FINGERPRINT, EM_SETREADONLY, 1, 0);
             staticedit(&cp, "Key &comment:", IDC_COMMENTSTATIC,
                        IDC_COMMENTEDIT, 70);
-            staticpassedit(&cp, "Key p&assphrase:", IDC_PASSPHRASESTATIC,
-                           IDC_PASSPHRASEEDIT, 70);
+            staticpassedit(&cp, "Key p&assphrase:", IDC_PASSPHRASE1STATIC,
+                           IDC_PASSPHRASE1EDIT, 70);
+            staticpassedit(&cp, "C&onfirm passphrase:", IDC_PASSPHRASE2STATIC,
+                           IDC_PASSPHRASE2EDIT, 70);
             endbox(&cp);
             beginbox(&cp, "Actions",
                      IDC_BOX_ACTIONS, IDC_BOXT_ACTIONS);
@@ -363,7 +363,14 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
             staticbtn(&cp, "Save the generated key to a new file",
                       IDC_SAVESTATIC, "&Save", IDC_SAVE);
             endbox(&cp);
+            beginbox(&cp, "Parameters",
+                     IDC_BOX_PARAMS, IDC_BOXT_PARAMS);
+            staticedit(&cp, "Number of &bits in a generated key:",
+                      IDC_BITSSTATIC, IDC_BITS, 20);
+            endbox(&cp);
         }
+       SetDlgItemInt(hwnd, IDC_BITS, DEFAULT_KEYSIZE, FALSE);
+
         /*
          * Initially, hide the progress bar and the key display,
          * and show the no-key display. Also disable the Save
@@ -402,6 +409,7 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
                 params = malloc(sizeof(*params));
                 params->progressbar = GetDlgItem(hwnd, IDC_PROGRESS);
                 params->dialog = hwnd;
+               params->keysize = state->keysize;
                 params->key = &state->key;
                 params->aux = &state->aux;
 
@@ -452,19 +460,27 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
                 state->key_exists = FALSE;
                 SetDlgItemText(hwnd, IDC_GENERATING, entropy_msg);
                 state->collecting_entropy = TRUE;
+               {
+                   BOOL ok;
+                   state->keysize = GetDlgItemInt(hwnd, IDC_BITS,
+                                                  &ok, FALSE);
+                   if (!ok) state->keysize = DEFAULT_KEYSIZE;
+               }
 
                 /*
                  * My brief statistical tests on mouse movements
-                 * suggest that there are about 5 bits of
-                 * randomness in the x position, 5 in the y
+                 * suggest that there are about 2.5 bits of
+                 * randomness in the x position, 2.5 in the y
                  * position, and 1.7 in the message time, making
-                 * 11.7 bits of unpredictability per mouse
-                 * movement. However, other people have told me
-                 * it's far less than that, so I'm going to be
-                 * stupidly cautious and knock that down to a nice
-                 * round 4.
+                 * 5.7 bits of unpredictability per mouse movement.
+                 * However, other people have told me it's far less
+                 * than that, so I'm going to be stupidly cautious
+                 * and knock that down to a nice round 2. With this
+                 * method, we require two words per mouse movement,
+                 * so with 2 bits per mouse movement we expect 2
+                 * bits every 2 words.
                  */
-                state->entropy_required = (KEYSIZE / 4) * 2;
+                state->entropy_required = (state->keysize/2) * 2;
                 state->entropy_got = 0;
                 state->entropy_size = (state->entropy_required *
                                        sizeof(*state->entropy));
@@ -480,8 +496,18 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
             if (state->key_exists) {
                 char filename[FILENAME_MAX];
                 char passphrase[PASSPHRASE_MAXLEN];
-                GetDlgItemText(hwnd, IDC_PASSPHRASEEDIT,
-                               passphrase, sizeof(passphrase)-1);
+                char passphrase2[PASSPHRASE_MAXLEN];
+                GetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,
+                               passphrase, sizeof(passphrase));
+                GetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,
+                               passphrase2, sizeof(passphrase2));
+               if (strcmp(passphrase, passphrase2)) {
+                    MessageBox(hwnd,
+                              "The two passphrases given do not match.",
+                              "PuTTYgen Error",
+                              MB_OK | MB_ICONERROR);
+                   break;
+               }
                 if (!*passphrase) {
                     int ret;
                     ret = MessageBox(hwnd,
@@ -494,10 +520,25 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
                 }
                 if (prompt_keyfile(hwnd, "Save private key as:",
                                    filename, 1)) {
-                    /* FIXME: prompt before overwriting */
-                    saversakey(filename, &state->key, &state->aux,
-                               *passphrase ? passphrase : NULL);
-                    /* FIXME: check return value */
+                   int ret;
+                   FILE *fp = fopen(filename, "r");
+                   if (fp) {
+                       char buffer[FILENAME_MAX+80];
+                       fclose(fp);
+                       sprintf(buffer, "Overwrite existing file\n%.*s?",
+                               FILENAME_MAX, filename);
+                       ret = MessageBox(hwnd, buffer, "PuTTYgen Warning",
+                                        MB_YESNO | MB_ICONWARNING);
+                       if (ret != IDYES)
+                           break;
+                   }
+                    ret = saversakey(filename, &state->key, &state->aux,
+                                    *passphrase ? passphrase : NULL);
+                   if (ret <= 0) {
+                       MessageBox(hwnd, "Unable to save key file",
+                                  "PuTTYgen Error",
+                                  MB_OK | MB_ICONERROR);
+                   }
                 }
             }
             break;
@@ -551,7 +592,9 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
                          */
                         {
                             char buf[128];
-                            SetDlgItemText(hwnd, IDC_PASSPHRASEEDIT,
+                            SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT,
+                                           passphrase);
+                            SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT,
                                            passphrase);
                             SetDlgItemText(hwnd, IDC_COMMENTEDIT,
                                            state->key.comment);
@@ -619,7 +662,8 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
              * because we will warn (Are You Sure?) before allowing
              * the user to save an unprotected private key.
              */
-            SetDlgItemText(hwnd, IDC_PASSPHRASEEDIT, "");
+            SetDlgItemText(hwnd, IDC_PASSPHRASE1EDIT, "");
+            SetDlgItemText(hwnd, IDC_PASSPHRASE2EDIT, "");
             /*
              * Set the comment.
              */
@@ -657,6 +701,7 @@ static int CALLBACK MainDlgProc (HWND hwnd, UINT msg,
 }
 
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
+    InitCommonControls();
     hinst = inst;
     random_init();
     return DialogBox(hinst, MAKEINTRESOURCE(201), NULL, MainDlgProc) != IDOK;