]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winpgen.c
Elliptic-curve cryptography support.
[PuTTY.git] / windows / winpgen.c
index 9ec04b4b9a4ae42efc342452cd071a4080c7d39b..db47e60f8be7e2661302582d95dfeac29af6e27c 100644 (file)
@@ -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: