[Ttssh2-commit] [9258] PuTTY private key format version 3 (PPK3) に対応

Zurück zum Archiv-Index
scmno****@osdn***** scmno****@osdn*****
2021年 5月 20日 (木) 00:39:46 JST


Revision: 9258
          https://osdn.net/projects/ttssh2/scm/svn/commits/9258
Author:   nmaya
Date:     2021-05-20 00:39:46 +0900 (Thu, 20 May 2021)
Log Message:
-----------
PuTTY private key format version 3 (PPK3) に対応

MF4-stable: r9256, r9257

Revision Links:
--------------
    https://osdn.net/projects/ttssh2/scm/svn/commits/9256
    https://osdn.net/projects/ttssh2/scm/svn/commits/9257

Modified Paths:
--------------
    trunk/doc/convtext.bat
    trunk/doc/en/html/about/copyright.html
    trunk/doc/en/html/about/history.html
    trunk/doc/en/html/reference/develop.txt
    trunk/doc/ja/html/about/copyright.html
    trunk/doc/ja/html/about/history.html
    trunk/doc/ja/html/reference/develop.txt
    trunk/ttssh2/putty/libputty.c
    trunk/ttssh2/ttssh.v16.sln
    trunk/ttssh2/ttssh.v8.sln
    trunk/ttssh2/ttxssh/keyfiles.c
    trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj
    trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters
    trunk/ttssh2/ttxssh/ttxssh.v8.vcproj

Added Paths:
-----------
    trunk/libs/argon2/
    trunk/ttssh2/argon2/
    trunk/ttssh2/ttxssh/keyfiles-putty.c
    trunk/ttssh2/ttxssh/keyfiles-putty.h

Property Changed:
----------------
    trunk/
    trunk/TTProxy/
    trunk/TTXKanjiMenu/
    trunk/TTXSamples/
    trunk/cygterm/
    trunk/teraterm/
    trunk/ttpmenu/

-------------- next part --------------
Index: trunk
===================================================================
--- trunk	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk
___________________________________________________________________
Modified: svn:mergeinfo
## -1,3 +1,4 ##
+/branches/4-stable:9256-9257
 /branches/drag_and_drop:7130,7139,7141,7143-7147
 /branches/flowctrl_dsrdtr:7825-7827
 /branches/move_code_script:9026-9185
Index: trunk/TTProxy
===================================================================
--- trunk/TTProxy	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/TTProxy	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk/TTProxy
___________________________________________________________________
Modified: svn:mergeinfo
## -1,3 +1,4 ##
+/branches/4-stable/TTProxy:9256-9257
 /branches/openssl_1_1_1_v2/TTProxy:7785-7786,7788-7808,7861-7863,7898,7900,7902-7903,7909,7924,7934,7954-7957,7959,7973,7975,7979-7980
 /branches/openssl_1_1_1_v3/TTProxy:8258
 /branches/ssh_chacha20poly1305/TTProxy:9209-9212,9217,9229,9248-9253
Index: trunk/TTXKanjiMenu
===================================================================
--- trunk/TTXKanjiMenu	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/TTXKanjiMenu	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk/TTXKanjiMenu
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/4-stable/TTXKanjiMenu:9256-9257
 /branches/ssh_chacha20poly1305/TTXKanjiMenu:9209-9212,9217,9229,9248-9253
 /branches/vs2015_warn/TTXKanjiMenu:6194-6285
\ No newline at end of property
Index: trunk/TTXSamples
===================================================================
--- trunk/TTXSamples	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/TTXSamples	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk/TTXSamples
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/4-stable/TTXSamples:9256-9257
 /branches/ssh_chacha20poly1305/TTXSamples:9209-9212,9217,9229,9248-9253
 /branches/vs2015_warn/TTXSamples:6194-6285
\ No newline at end of property
Index: trunk/cygterm
===================================================================
--- trunk/cygterm	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/cygterm	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk/cygterm
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/4-stable/cygterm:9256-9257
 /branches/openssl_1_1_1_v3/cygterm:8284
 /branches/ssh_chacha20poly1305/cygterm:9209-9212,9217,9229,9248-9253
\ No newline at end of property
Modified: trunk/doc/convtext.bat
===================================================================
--- trunk/doc/convtext.bat	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/convtext.bat	2021-05-19 15:39:46 UTC (rev 9258)
@@ -18,6 +18,8 @@
 %ZLIBCP% -i ..\libs\zlib\README         -o %REF_J%\zlib-LICENSE.txt      -l unix
 %TOSJIS% -i ..\libs\cJSON\LICENSE       -o %REF_J%\cJSON-LICENSE.txt     -l crlf
 %TOSJIS% -i ..\libs\cJSON\LICENSE       -o %REF_E%\cJSON-LICENSE.txt     -l crlf
+%TOSJIS% -i ..\libs\argon2\LICENSE      -o %REF_E%\argon2-LICENSE.txt    -l unix
+%TOSJIS% -i ..\libs\argon2\LICENSE      -o %REF_J%\argon2-LICENSE.txt    -l unix
 
 perl -C0 -pe "s/^\xef\xbb\xbf//" ja/html/reference/build_with_cmake.md | perl Markdown_1.0.1/Markdown.pl > ja/html/reference/build_with_cmake_utf8.html
 %TOSJIS% -i ja/html/reference/build_with_cmake_utf8.html -o ja/html/reference/build_with_cmake.html  -c utf8

Modified: trunk/doc/en/html/about/copyright.html
===================================================================
--- trunk/doc/en/html/about/copyright.html	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/en/html/about/copyright.html	2021-05-19 15:39:46 UTC (rev 9258)
@@ -34,6 +34,7 @@
   <li>zlib ... <a href="../reference/zlib-LICENSE.txt">zlib License</a></li>
   <li>PuTTY ... <a href="../reference/PuTTY-LICENSE.txt">MIT License</a></li>
   <li>cJSON ... <a href="../reference/cJSON-LICENSE.txt">MIT License</a> <a href="https://github.com/DaveGamble/cJSON">(github)</a></li>
+  <li>The reference C implementation of Argon2 ... <a href="../reference/argon2-LICENSE.txt">Creative Commons CC0 1.0 License/Waiver or the Apache License 2.0</a></li>
 </ul>
 
 
@@ -165,6 +166,8 @@
     This program uses the source code of OpenSSH.
   Copyright of PuTTY belongs to Simon Tatham. Please see <a href="../reference/PuTTY-LICENSE.txt">PuTTY-LICENSE.txt</a> for more information about license.
     This program uses the source code of PuTTY.
+  Copyright of The reference C implementation of Argon2 belongs to Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves. Please see <a href="../reference/Argon2-LICENSE.txt">Argon2-LICENSE.txt</a> for more information about license.
+    This program uses the source code of The reference C implementation of Argon2.
   Copyright of TTSSH icon file to Tatsuhiko Sakamoto.
 
   This program is provided "as is" without warranties of any kind, either expressed or 

Modified: trunk/doc/en/html/about/history.html
===================================================================
--- trunk/doc/en/html/about/history.html	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/en/html/about/history.html	2021-05-19 15:39:46 UTC (rev 9258)
@@ -3271,6 +3271,7 @@
   <li>Changes
     <ul>
       <li>added chach****@opens***** symmetric key cipher algorithm for SSH2 protocol.</li>
+      <li>added support for the PuTTY private key format version 3 (PPK3).</li>
     </ul>
   </li>
 

Modified: trunk/doc/en/html/reference/develop.txt
===================================================================
--- trunk/doc/en/html/reference/develop.txt	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/en/html/reference/develop.txt	2021-05-19 15:39:46 UTC (rev 9258)
@@ -82,6 +82,7 @@
 - PuTTY 0.70 (http://www.chiark.greenend.org.uk/~sgtatham/putty/)
 - SFMT 1.5.1 (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html)
 - cJSON 1.7.14 (https://github.com/DaveGamble/cJSON/)
+- The reference C implementation of Argon2 20190702 (https://github.com/P-H-C/phc-winner-argon2)
 
 
 * Notice for SVN committer
@@ -155,7 +156,7 @@
 
 * How to build Libraries
   1. PuTTY (used by TTSSH)
-     (1) Extract putty source into libs/putty directory.
+     (1) Extract PuTTY source into libs/putty directory.
 
   2. Oniguruma (used by Tera Term Macro)
      (1) Extract oniguruma source into libs/oniguruma directory.
@@ -182,7 +183,10 @@
   6. cJSON (used by TTXCheckUpdate plugin)
      (1) Extract cJSON source into libs/cJSON directory.
 
+  7. The reference C implementation of Argon2 (used by TTSSH)
+     (1) Extract argon2 source into libs/argon2 directory.
 
+
 * How to build Tera Term
   To build Tera Term source code is shown in the following step:
   And you should use Visual Studio 2005 Standard Edition later version to build Tera Term because Tera Term program links MFC library (Visual Studio 2005 Express Edition can't be used).

Modified: trunk/doc/ja/html/about/copyright.html
===================================================================
--- trunk/doc/ja/html/about/copyright.html	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/ja/html/about/copyright.html	2021-05-19 15:39:46 UTC (rev 9258)
@@ -34,6 +34,7 @@
   <li>zlib ... <a href="../reference/zlib-LICENSE.txt">zlib\x83\x89\x83C\x83Z\x83\x93\x83X</a></li>
   <li>PuTTY ... <a href="../reference/PuTTY-LICENSE.txt">MIT\x83\x89\x83C\x83Z\x83\x93\x83X</a></li>
   <li>cJSON ... <a href="../reference/cJSON-LICENSE.txt">MIT\x83\x89\x83C\x83Z\x83\x93\x83X</a> <a href="https://github.com/DaveGamble/cJSON">(github)</a></li>
+  <li>The reference C implementation of Argon2 ... <a href="../reference/argon2-LICENSE.txt">Creative Commons CC0 1.0 License/Waiver \x82܂\xBD\x82\xCD Apache License 2.0</a></li>
 </ul>
 
 
@@ -158,6 +159,8 @@
     \x96{\x83v\x83\x8D\x83O\x83\x89\x83\x80\x82́AOpenSSH\x82̃\\x81[\x83X\x83R\x81[\x83h\x82\xF0\x8Eg\x97p\x82\xB5\x82Ă\xA2\x82܂\xB7\x81B
   PuTTY\x82\xCDSimon Tatham\x8E\x81\x82̒\x98\x8D앨\x82ł\xB7\x81B\x83\x89\x83C\x83Z\x83\x93\x83X\x8F\xEE\x95\xF1\x82ɂ‚\xA2\x82Ă͓\xAF\x8D\xAB\x82\xCC<a href="../reference/PuTTY-LICENSE.txt">PuTTY-LICENCE.txt</a>\x82\xF0\x82\xB2\x97\x97\x89\xBA\x82\xB3\x82\xA2\x81B
     \x96{\x83v\x83\x8D\x83O\x83\x89\x83\x80\x82́APuTTY\x82̃\\x81[\x83X\x83R\x81[\x83h\x82\xF0\x8Eg\x97p\x82\xB5\x82Ă\xA2\x82܂\xB7\x81B
+  The reference C implementation of Argon2 \x82\xCD Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, Samuel Neves \x8Ae\x8E\x81\x82̒\x98\x8D앨\x82ł\xB7\x81B\x83\x89\x83C\x83Z\x83\x93\x83X\x8F\xEE\x95\xF1\x82ɂ‚\xA2\x82Ă͓\xAF\x8D\xAB\x82\xCC<a href="../reference/Argon2-LICENSE.txt">Argon2-LICENCE.txt</a>\x82\xF0\x82\xB2\x97\x97\x89\xBA\x82\xB3\x82\xA2\x81B
+    \x96{\x83v\x83\x8D\x83O\x83\x89\x83\x80\x82́AThe reference C implementation of Argon2 \x82̃\\x81[\x83X\x83R\x81[\x83h\x82\xF0\x8Eg\x97p\x82\xB5\x82Ă\xA2\x82܂\xB7\x81B
   TTSSH\x82Ɋւ\xB7\x82\xE9\x83p\x83b\x83`\x82̈ꕔ\x82͉i\x93c\x90^\x96\xE7\x82ɒ\x98\x8D쌠\x82\xAA\x82\xA0\x82\xE8\x82܂\xB7\x81B
   TTSSH\x82̃A\x83C\x83R\x83\x93\x82͍\xE2\x96{\x97\xB4\x95F\x8E\x81\x82ɒ\x98\x8D쌠\x82\xAA\x82\xA0\x82\xE8\x82܂\xB7\x81B
 

Modified: trunk/doc/ja/html/about/history.html
===================================================================
--- trunk/doc/ja/html/about/history.html	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/ja/html/about/history.html	2021-05-19 15:39:46 UTC (rev 9258)
@@ -3277,6 +3277,7 @@
   <li>\x95ύX
     <ul>
       <li>SSH2 \x82̋\xA4\x92ʌ\xAE\x88Í\x86\x95\xFB\x8E\xAE\x82\xC9 chach****@opens***** \x82\xF0\x92lj\xC1\x82\xB5\x82\xBD\x81B</li>
+      <li>PuTTY \x8C`\x8E\xAE\x82̔閧\x8C\xAE\x83t\x83H\x81[\x83}\x83b\x83g3 (PPK3) \x82ɑΉ\x9E\x82\xB5\x82\xBD\x81B</li>
     </ul>
   </li>
 

Modified: trunk/doc/ja/html/reference/develop.txt
===================================================================
--- trunk/doc/ja/html/reference/develop.txt	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/doc/ja/html/reference/develop.txt	2021-05-19 15:39:46 UTC (rev 9258)
@@ -75,6 +75,7 @@
 - PuTTY 0.70 (http://www.chiark.greenend.org.uk/~sgtatham/putty/)
 - SFMT 1.5.1 (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index-jp.html)
 - cJSON 1.7.14 (https://github.com/DaveGamble/cJSON/)
+- The reference C implementation of Argon2 20190702 (https://github.com/P-H-C/phc-winner-argon2)
 
 \x81\xA1 SVN \x83R\x83~\x83b\x83^\x81[\x82ւ̒\x8D\x88\xD3
 - SVN \x83\x8A\x83|\x83W\x83g\x83\x8A\x82͈\xEA\x94ʌ\xFC\x82\xAF\x82Ƃ͈Ⴂ\x81A\x88ȉ\xBA\x82̒ʂ\xE8\x82ł\xB7\x81B
@@ -150,7 +151,8 @@
 
 \x81\xA1 \x83\x89\x83C\x83u\x83\x89\x83\x8A\x82̃r\x83\x8B\x83h\x95\xFB\x96@
   1. PuTTY (used by TTSSH)
-     (1) putty \x82̃\\x81[\x83X\x82\xF0 libs/putty \x82̒\x86\x82ɓW\x8AJ\x82\xB7\x82\xE9\x81B
+     (1) PuTTY \x82̃\\x81[\x83X\x82\xF0 libs/putty \x82̒\x86\x82ɓW\x8AJ\x82\xB7\x82\xE9\x81B
+     * ttssh \x83\\x83\x8A\x83\x85\x81[\x83V\x83\x87\x83\x93\x94z\x89\xBA\x82\xCC putty \x83v\x83\x8D\x83W\x83F\x83N\x83g\x82ɂ\xE6\x82\xE8\x95K\x97v\x82ȋ@\x94\\x82݂̂\xAA\x90ÓI\x83\x89\x83C\x83u\x83\x89\x83\x8A\x89\xBB\x82\xB3\x82\xEA\x81Attxssh.dll \x82Ƀ\x8A\x83\x93\x83N\x82\xB3\x82\xEA\x82邽\x82߁A\x93W\x8AJ\x82\xB7\x82邾\x82\xAF\x82ł悢\x81B
 
   2. Oniguruma (used by Tera Term Macro)
      (1) oniguruma \x82̃\\x81[\x83X\x82\xF0 libs/oniguruma \x82̒\x86\x82ɓW\x8AJ\x82\xB7\x82\xE9\x81B
@@ -177,6 +179,11 @@
   6. cJSON (used by TTXCheckUpdate plugin)
      (1) cJSON \x82̃\\x81[\x83X\x82\xF0 libs/cJSON \x82̒\x86\x82ɓW\x8AJ\x82\xB7\x82\xE9\x81B
 
+  7. The reference C implementation of Argon2 (used by TTSSH)
+     (1) argon2 \x82̃\\x81[\x83X\x82\xF0 libs/argon2 \x82̒\x86\x82ɓW\x8AJ\x82\xB7\x82\xE9\x81B
+     * argon2 \x83\x8A\x83t\x83@\x83\x8C\x83\x93\x83X\x8E\xC0\x91\x95\x82ɂ͐ÓI\x83\x89\x83C\x83u\x83\x89\x83\x8A\x82𐶐\xAC\x82\xB7\x82\xE9\x83v\x83\x8D\x83W\x83F\x83N\x83g\x83t\x83@\x83C\x83\x8B\x82\xAA\x8A܂܂\xEA\x82Ă\xA2\x82Ȃ\xA2\x81Bttssh \x83\\x83\x8A\x83\x85\x81[\x83V\x83\x87\x83\x93\x94z\x89\xBA\x82\xCC argon2 \x83v\x83\x8D\x83W\x83F\x83N\x83g\x82ɂ\xE6\x82\xE8\x90ÓI\x83\x89\x83C\x83u\x83\x89\x83\x8A\x82\xAA\x90\xB6\x90\xAC\x82\xB3\x82\xEA\x81Attxssh.dll \x82Ƀ\x8A\x83\x93\x83N\x82\xB3\x82\xEA\x82邽\x82߁A\x93W\x8AJ\x82\xB7\x82邾\x82\xAF\x82ł悢\x81B
+
+
 \x81\xA1 Tera Term\x82̃r\x83\x8B\x83h\x95\xFB\x96@
   Tera Term\x82̃r\x83\x8B\x83h\x95\xFB\x96@\x82ɂ‚\xA2\x82Ĉȉ\xBA\x82Ɏ\xA6\x82\xB5\x82܂\xB7\x81B
   \x83r\x83\x8B\x83h\x82ɂ\xCDVisual Studio 2005 Standard Edition\x88ȏオ\x95K\x97v\x82ł\xB7\x81B\x81iVisual Studio 2005 Express Edition\x82͕s\x89j

Index: trunk/teraterm
===================================================================
--- trunk/teraterm	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/teraterm	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk/teraterm
___________________________________________________________________
Modified: svn:mergeinfo
## -1,3 +1,4 ##
+/branches/4-stable/teraterm:9256-9257
 /branches/drag_and_drop/teraterm:7130,7139,7141,7143-7147
 /branches/flowctrl_dsrdtr/teraterm:7825-7827
 /branches/move_code_script/teraterm:9026-9185
Index: trunk/ttpmenu
===================================================================
--- trunk/ttpmenu	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttpmenu	2021-05-19 15:39:46 UTC (rev 9258)

Property changes on: trunk/ttpmenu
___________________________________________________________________
Modified: svn:mergeinfo
## -1,2 +1,3 ##
+/branches/4-stable/ttpmenu:9256-9257
 /branches/ssh_chacha20poly1305/ttpmenu:9209-9212,9217,9229,9248-9253
 /branches/vs2015_warn/ttpmenu:6194-6285
\ No newline at end of property
Modified: trunk/ttssh2/putty/libputty.c
===================================================================
--- trunk/ttssh2/putty/libputty.c	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/putty/libputty.c	2021-05-19 15:39:46 UTC (rev 9258)
@@ -28,6 +28,16 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * putty \x83v\x83\x8D\x83W\x83F\x83N\x83g\x82\xCD
+ * - PuTTY \x82̃\\x81[\x83X\x83t\x83@\x83C\x83\x8B (\x83v\x83\x8D\x83W\x83F\x83N\x83g\x82ɓǂݍ\x9E\x82ރt\x83@\x83C\x83\x8B\x82͍ŏ\xAC\x8C\xC0)
+ * - libputty.c/h 
+ *   PuTTY \x82̋@\x94\\x82𗘗p\x82\xB7\x82\xE9\x83C\x83\x93\x83^\x81[\x83t\x83F\x81[\x83X
+ *   PuTTY \x82̃\\x81[\x83X\x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x95K\x97v\x82Ȋ֐\x94\x82݂̂\xF0\x83R\x83s\x81[
+ * \x82\xA9\x82\xE7\x90ÓI\x83\x89\x83C\x83u\x83\x89\x83\x8A libputty.lib \x82𐶐\xAC\x82\xB5\x81ATTXSSH \x82\xA9\x82烊\x83\x93\x83N\x82\xB3\x82\xEA\x82ė\x98\x97p\x82\xB3\x82\xEA\x82\xE9\x81B
+ * \x82\xBB\x82̂\xBD\x82߁ATTXSSH \x91\xA4\x82̒\xE8\x8B`\x82͎\x9D\x82\xBF\x8D\x9E\x82܂Ȃ\xA2\x81B
+ */
+
 #include <windows.h>
 #include <assert.h>
 

Modified: trunk/ttssh2/ttssh.v16.sln
===================================================================
--- trunk/ttssh2/ttssh.v16.sln	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/ttssh.v16.sln	2021-05-19 15:39:46 UTC (rev 9258)
@@ -1,5 +1,5 @@
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 16
+# Visual Studio Version 16
 VisualStudioVersion = 16.0.28803.156
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "matcher", "matcher\matcher.v16.vcxproj", "{C4B19BFB-8068-4EF2-A3A1-4EC4C40BE7F1}"
@@ -12,6 +12,8 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "puttyrev", "puttyrev\puttyrev.v16.vcxproj", "{61EB955F-2794-4607-860F-0AA296FA58BD}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "argon2", "argon2\argon2.v16.vcxproj", "{D33C59B8-E227-47D2-8F80-EDA3E28BF995}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -38,6 +40,10 @@
 		{61EB955F-2794-4607-860F-0AA296FA58BD}.Debug|Win32.Build.0 = Debug|Win32
 		{61EB955F-2794-4607-860F-0AA296FA58BD}.Release|Win32.ActiveCfg = Release|Win32
 		{61EB955F-2794-4607-860F-0AA296FA58BD}.Release|Win32.Build.0 = Release|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Debug|Win32.Build.0 = Debug|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Release|Win32.ActiveCfg = Release|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

Modified: trunk/ttssh2/ttssh.v8.sln
===================================================================
--- trunk/ttssh2/ttssh.v8.sln	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/ttssh.v8.sln	2021-05-19 15:39:46 UTC (rev 9258)
@@ -7,6 +7,7 @@
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ttxssh", "ttxssh\ttxssh.v8.vcproj", "{5638BB89-44E3-4D55-BA98-A01142B4223E}"
 	ProjectSection(ProjectDependencies) = postProject
 		{61EB955F-2794-4607-860F-0AA296FA58BD} = {61EB955F-2794-4607-860F-0AA296FA58BD}
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995} = {D33C59B8-E227-47D2-8F80-EDA3E28BF995}
 		{98CA1284-8F6C-4791-BF57-7E5FAD33744E} = {98CA1284-8F6C-4791-BF57-7E5FAD33744E}
 	EndProjectSection
 EndProject
@@ -14,6 +15,8 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "puttyrev", "puttyrev\puttyrev.v8.vcproj", "{61EB955F-2794-4607-860F-0AA296FA58BD}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "argon2", "argon2\argon2.v8.vcproj", "{D33C59B8-E227-47D2-8F80-EDA3E28BF995}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -40,6 +43,10 @@
 		{61EB955F-2794-4607-860F-0AA296FA58BD}.Debug|Win32.Build.0 = Debug|Win32
 		{61EB955F-2794-4607-860F-0AA296FA58BD}.Release|Win32.ActiveCfg = Release|Win32
 		{61EB955F-2794-4607-860F-0AA296FA58BD}.Release|Win32.Build.0 = Release|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Debug|Win32.ActiveCfg = Debug|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Debug|Win32.Build.0 = Debug|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Release|Win32.ActiveCfg = Release|Win32
+		{D33C59B8-E227-47D2-8F80-EDA3E28BF995}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

Copied: trunk/ttssh2/ttxssh/keyfiles-putty.c (from rev 9256, branches/4-stable/ttssh2/ttxssh/keyfiles-putty.c)
===================================================================
--- trunk/ttssh2/ttxssh/keyfiles-putty.c	                        (rev 0)
+++ trunk/ttssh2/ttxssh/keyfiles-putty.c	2021-05-19 15:39:46 UTC (rev 9258)
@@ -0,0 +1,354 @@
+/* Imported from PuTTY 0.74, 0.75, TeraTerm Project */
+
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ttxssh.h"
+#include "keyfiles-putty.h"
+
+// from sshpubk.c (ver 0.75)
+BOOL str_to_uint32_t(const char *s, uint32_t *out)
+{
+	char *endptr;
+	unsigned long converted = strtoul(s, &endptr, 10);
+	if (*s && !*endptr && converted <= ~(uint32_t)0) {
+		*out = converted;
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+
+// from sshpubk.c (ver 0.74)
+BOOL ppk_read_header(FILE * fp, char *header)
+{
+	int len = 39;
+	int c;
+
+	while (1) {
+		c = fgetc(fp);
+		if (c == '\n' || c == '\r' || c == EOF)
+			return FALSE;
+		if (c == ':') {
+			c = fgetc(fp);
+			if (c != ' ')
+				return FALSE;
+			*header = '\0';
+			return TRUE;
+		}
+		if (len == 0)
+			return FALSE;
+		*header++ = c;
+		len--;
+	}
+	return FALSE;
+}
+
+// from sshpubk.c (ver 0.74)
+char *ppk_read_body(FILE * fp)
+{
+	buffer_t *buf = buffer_init();
+
+	while (1) {
+		int c = fgetc(fp);
+		if (c == '\r' || c == '\n' || c == EOF) {
+			if (c != EOF) {
+				c = fgetc(fp);
+				if (c != '\r' && c != '\n')
+					ungetc(c, fp);
+			}
+			return buffer_ptr(buf);
+		}
+		buffer_put_char(buf, c);
+	}
+}
+
+// from sshpubk.c (ver 0.74), and modified
+// - use buffer_t insted of strbuf
+// - use OpenSSL function
+BOOL ppk_read_blob(FILE* fp, int nlines, buffer_t *blob)
+{
+	BIO *bmem, *b64, *chain;
+	int i, len;
+	char line[200], buf[100];
+
+	b64 = BIO_new(BIO_f_base64());
+	bmem = BIO_new(BIO_s_mem());
+	for (i=0; i<nlines && fgets(line, sizeof(line), fp)!=NULL; i++) {
+		BIO_write(bmem, line, strlen(line));
+	}
+	BIO_flush(bmem);
+	chain = BIO_push(b64, bmem);
+	BIO_set_mem_eof_return(chain, 0);
+	while ((len = BIO_read(chain, buf, sizeof(buf))) > 0) {
+		buffer_append(blob, buf, len);
+	}
+	BIO_free_all(chain);
+
+	return TRUE;
+}
+
+// from sshsha.c (ver 0.70), and modifled
+// - use OpenSSL function
+void hmac_sha1_simple(unsigned char *key, int keylen, void *data, int datalen,
+                      unsigned char *output)
+{
+	EVP_MD_CTX *ctx[2] = {0, 0};
+	unsigned char intermediate[20];
+	unsigned char foo[64];
+	const EVP_MD *md = EVP_sha1();
+	int i;
+	unsigned int len;
+
+	ctx[0] = EVP_MD_CTX_new();
+	if (ctx[0] == NULL) {
+		return;
+	}
+	ctx[1] = EVP_MD_CTX_new();
+	if (ctx[1] == NULL) {
+		EVP_MD_CTX_free(ctx[0]);
+		return;
+	}
+
+	memset(foo, 0x36, sizeof(foo));
+	for (i = 0; i < keylen && i < sizeof(foo); i++) {
+		foo[i] ^= key[i];
+	}
+	EVP_DigestInit(ctx[0], md);
+	EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
+
+	memset(foo, 0x5C, sizeof(foo));
+	for (i = 0; i < keylen && i < sizeof(foo); i++) {
+		foo[i] ^= key[i];
+	}
+	EVP_DigestInit(ctx[1], md);
+	EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
+
+	memset(foo, 0, sizeof(foo));
+
+	EVP_DigestUpdate(ctx[0], data, datalen);
+	EVP_DigestFinal(ctx[0], intermediate, &len);
+
+	EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
+	EVP_DigestFinal(ctx[1], output, &len);
+
+	EVP_MD_CTX_free(ctx[0]);
+	EVP_MD_CTX_free(ctx[1]);
+}
+
+void hmac_sha256_simple(unsigned char *key, int keylen, void *data, int datalen,
+                        unsigned char *output)
+{
+	EVP_MD_CTX *ctx[2] = {0, 0};
+	unsigned char intermediate[32];
+	unsigned char foo[64];
+	const EVP_MD *md = EVP_sha256();
+	int i;
+	unsigned int len;
+
+	ctx[0] = EVP_MD_CTX_new();
+	if (ctx[0] == NULL) {
+		return;
+	}
+	ctx[1] = EVP_MD_CTX_new();
+	if (ctx[1] == NULL) {
+		EVP_MD_CTX_free(ctx[0]);
+		return;
+	}
+
+	memset(foo, 0x36, sizeof(foo));
+	for (i = 0; i < keylen && i < sizeof(foo); i++) {
+		foo[i] ^= key[i];
+	}
+	EVP_DigestInit(ctx[0], md);
+	EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
+
+	memset(foo, 0x5C, sizeof(foo));
+	for (i = 0; i < keylen && i < sizeof(foo); i++) {
+		foo[i] ^= key[i];
+	}
+	EVP_DigestInit(ctx[1], md);
+	EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
+
+	memset(foo, 0, sizeof(foo));
+
+	EVP_DigestUpdate(ctx[0], data, datalen);
+	EVP_DigestFinal(ctx[0], intermediate, &len);
+
+	EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
+	EVP_DigestFinal(ctx[1], output, &len);
+
+	EVP_MD_CTX_free(ctx[0]);
+	EVP_MD_CTX_free(ctx[1]);
+}
+
+// from sshsha.c (ver 0.70) hmac_sha1_simple
+//      sshauxcrypt.c (ver 0.75) mac_simple, and modifled
+// - use OpenSSL function
+// - use EVP_MD instead of ssh2_macalg
+void mac_simple(const EVP_MD *md,
+                unsigned char *key, int keylen, void *data, int datalen,
+                unsigned char *output)
+{
+	EVP_MD_CTX *ctx[2] = {0, 0};
+	unsigned char intermediate[32]; // sha1: 160bit / sha256: 256bit
+	unsigned char foo[64]; // block size ... sha1: 512bit / sha256: 512bit
+	int i;
+	unsigned int len;
+
+	ctx[0] = EVP_MD_CTX_new();
+	if (ctx[0] == NULL) {
+		return;
+	}
+	ctx[1] = EVP_MD_CTX_new();
+	if (ctx[1] == NULL) {
+		EVP_MD_CTX_free(ctx[0]);
+		return;
+	}
+
+	memset(foo, 0x36, sizeof(foo));
+	for (i = 0; i < keylen && i < sizeof(foo); i++) {
+		foo[i] ^= key[i];
+	}
+	EVP_DigestInit(ctx[0], md);
+	EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
+
+	memset(foo, 0x5C, sizeof(foo));
+	for (i = 0; i < keylen && i < sizeof(foo); i++) {
+		foo[i] ^= key[i];
+	}
+	EVP_DigestInit(ctx[1], md);
+	EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
+
+	memset(foo, 0, sizeof(foo));
+
+	EVP_DigestUpdate(ctx[0], data, datalen);
+	EVP_DigestFinal(ctx[0], intermediate, &len);
+
+	EVP_DigestUpdate(ctx[1], intermediate, EVP_MD_size(md));
+	EVP_DigestFinal(ctx[1], output, &len);
+
+	EVP_MD_CTX_free(ctx[0]);
+	EVP_MD_CTX_free(ctx[1]);
+}
+
+// from sshpubk.c (ver 0.75), and modifled
+// - delete unnecessary paramters
+// - use char ** and int * instead of ptrlen
+// - use buffer_t instead of strbuf
+// - use OpenSSL function
+// - use argon2 function
+void ssh2_ppk_derive_keys(
+	unsigned fmt_version, const struct ssh2cipher* ciphertype,
+	unsigned char *passphrase, buffer_t *storage,
+	unsigned char **cipherkey, unsigned int *cipherkey_len,
+	unsigned char **cipheriv, unsigned int *cipheriv_len,
+	unsigned char **mackey, unsigned int *mackey_len,
+	ppk_argon2_parameters *params)
+{
+	size_t mac_keylen = 0;
+	u_int ivlen;
+	unsigned int cipherkey_offset = 0;
+
+	ivlen = (ciphertype->iv_len == 0) ? ciphertype->block_size : ciphertype->iv_len;
+
+	switch (fmt_version) {
+		case 3: {
+			uint32_t taglen;
+			unsigned char *tag;
+
+			if (ciphertype->key_len == 0) {
+				mac_keylen = 0;
+				break;
+			}
+			mac_keylen = 32;
+			taglen = ciphertype->key_len + ivlen + mac_keylen;
+			tag = (char *)malloc(taglen);
+
+			argon2_hash(params->argon2_passes, params->argon2_mem,
+			            params->argon2_parallelism,
+			            passphrase, strlen(passphrase),
+			            params->salt, params->saltlen,
+			            tag, taglen,
+			            NULL, 0,
+			            params->type, 0x13);
+			buffer_append(storage, tag, taglen);
+
+			free(tag);
+
+			break;
+		}
+		case 2: {
+			unsigned ctr;
+			const EVP_MD *md = EVP_sha1();
+			EVP_MD_CTX *ctx = NULL;
+			unsigned char u[4], buf[20]; // SHA1: 20byte
+			unsigned int i, len, cipherkey_write_byte = 0;
+
+			ctx = EVP_MD_CTX_new();
+
+			/* Counter-mode iteration to generate cipher key data. */
+			for (ctr = 0; ctr * 20 < ciphertype->key_len; ctr++) {
+				EVP_DigestInit(ctx, md);
+				set_uint32_MSBfirst(u, ctr);
+				EVP_DigestUpdate(ctx, u, 4);
+				EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
+				EVP_DigestFinal(ctx, buf, &len);
+				buffer_append(storage, buf, 20);
+				cipherkey_write_byte += 20;
+			}
+			// TTSSH \x82\xCC buffer_t \x82ɂ\xCD shrink \x82\xB7\x82\xE9\x8A֐\x94\x82\xAA\x82Ȃ\xA2\x82̂ŁA
+			// shrink \x82\xB9\x82\xB8\x82\xC9 40byte \x82̂\xA4\x82\xBF 32byte \x82\xBE\x82\xAF\x82\xF0\x8Eg\x82\xA4
+			cipherkey_offset = cipherkey_write_byte - ciphertype->key_len;
+
+			/* In this version of the format, the CBC IV was always all 0. */
+			for (i = 0; i < ivlen; i++) {
+				buffer_put_char(storage, 0);
+			}
+
+			/* Completely separate hash for the MAC key. */
+			EVP_DigestInit(ctx, md);
+			mac_keylen = EVP_MD_size(md); // SHA1: 20byte
+			EVP_DigestUpdate(ctx, "putty-private-key-file-mac-key", 30);
+			EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
+			EVP_DigestFinal(ctx, buf, &len);
+			buffer_append(storage, buf, mac_keylen);
+
+			EVP_MD_CTX_free(ctx);
+
+			break;
+		}
+	}
+
+	*cipherkey = storage->buf;
+	*cipherkey_len = ciphertype->key_len;
+	*cipheriv = storage->buf + ciphertype->key_len + cipherkey_offset;
+	*cipheriv_len = ivlen;
+	*mackey = storage->buf + ciphertype->key_len + cipherkey_offset + ivlen;
+	*mackey_len = mac_keylen;
+}

Copied: trunk/ttssh2/ttxssh/keyfiles-putty.h (from rev 9256, branches/4-stable/ttssh2/ttxssh/keyfiles-putty.h)
===================================================================
--- trunk/ttssh2/ttxssh/keyfiles-putty.h	                        (rev 0)
+++ trunk/ttssh2/ttxssh/keyfiles-putty.h	2021-05-19 15:39:46 UTC (rev 9258)
@@ -0,0 +1,64 @@
+/*
+ * (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __KEYFILES_PUTTY_H
+#define __KEYFILES_PUTTY_H
+
+#include "argon2.h"
+
+typedef struct ppk_argon2_parameters {
+	argon2_type type;
+	uint32_t argon2_mem;
+	uint32_t argon2_passes;
+	uint32_t argon2_parallelism;
+	const uint8_t *salt;
+	size_t saltlen;
+} ppk_argon2_parameters;
+
+BOOL str_to_uint32_t(const char *s, uint32_t *out);
+BOOL ppk_read_header(FILE * fp, char *header);
+char *ppk_read_body(FILE * fp);
+BOOL ppk_read_blob(FILE* fp, int nlines, buffer_t *blob);
+
+void hmac_sha1_simple(unsigned char *key, int keylen, void *data, int datalen,
+                      unsigned char *output);
+void hmac_sha256_simple(unsigned char *key, int keylen, void *data, int datalen,
+                        unsigned char *output);
+void mac_simple(const EVP_MD *md,
+                unsigned char *key, int keylen, void *data, int datalen,
+                unsigned char *output);
+
+void ssh2_ppk_derive_keys(
+	unsigned fmt_version, const struct ssh2cipher* ciphertype,
+	unsigned char *passphrase, buffer_t *storage,
+	unsigned char **cipherkey, unsigned int *cipherkey_len,
+	unsigned char **cipheriv, unsigned int *cipheriv_len,
+	unsigned char **mackey, unsigned int *mackey_len,
+	ppk_argon2_parameters *params);
+
+#endif /* __KEYFILES_PUTTY_H */

Modified: trunk/ttssh2/ttxssh/keyfiles.c
===================================================================
--- trunk/ttssh2/ttxssh/keyfiles.c	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/ttxssh/keyfiles.c	2021-05-19 15:39:46 UTC (rev 9258)
@@ -34,7 +34,10 @@
 
 #include "ttxssh.h"
 #include "keyfiles.h"
+#include "keyfiles-putty.h"
 #include "key.h"
+#include "hostkey.h"
+#include "argon2.h"
 
 #include <io.h>
 #include <fcntl.h>
@@ -746,7 +749,6 @@
  * Private-Lines: 1
  * Base64...
  * Private-MAC: Base16...
- * Private-Hash: Base16... (PuTTY-User-Key-File-1) ???
  * 
  * for "ssh-rsa", it will be composed of
  *
@@ -821,14 +823,16 @@
                                  char *errmsg,
                                  int errmsg_len)
 {
+	char header[40], *b = NULL, *encryption = NULL, *comment = NULL, *mac = NULL;
 	Key *result = NULL;
-	EVP_PKEY *pk = NULL;
-	unsigned long err = 0;
-	int i, len, len2;
-	char *encname = NULL, *comment = NULL, *private_mac = NULL;
-	buffer_t *pubkey = NULL, *prikey = NULL;
-	const struct ssh2cipher *cipher = NULL;
-	struct sshcipher_ctx *cc = NULL;
+	buffer_t *public_blob = NULL, *private_blob = NULL, *cipher_mac_keys_blob = NULL;
+	unsigned char *cipherkey = NULL, *cipheriv = NULL, *mackey = NULL;
+	unsigned int cipherkey_len, cipheriv_len, mackey_len;
+	buffer_t *passphrase_salt = buffer_init();
+	const struct ssh2cipher *ciphertype;
+	int lines, len;
+	ppk_argon2_parameters params;
+	unsigned fmt_version = 0;
 
 	result = (Key *)malloc(sizeof(Key));
 	ZeroMemory(result, sizeof(Key)); 
@@ -837,149 +841,262 @@
 	result->dsa = NULL;
 	result->ecdsa = NULL;
 
-	pubkey = buffer_init();
-	prikey = buffer_init();
+	// version and algorithm-name
+	if (!ppk_read_header(fp, header)) {
+		strncpy_s(errmsg, errmsg_len, "no header line found in key file", _TRUNCATE);
+		goto error;
+	}
+	if (0 == strcmp(header, "PuTTY-User-Key-File-3")) {
+		fmt_version = 3;
+	}
+	else if (0 == strcmp(header, "PuTTY-User-Key-File-2")) {
+		fmt_version = 2;
+	}
+	else if (0 == strcmp(header, "PuTTY-User-Key-File-1")) {
+		strncpy_s(errmsg, errmsg_len, "PuTTY key format too old", _TRUNCATE);
+		goto error;
+	}
+	else if (0 == strncmp(header, "PuTTY-User-Key-File-", 20)) {
+		strncpy_s(errmsg, errmsg_len, "PuTTY key format too new", _TRUNCATE);
+		goto error;
+	}
+	if ((b = ppk_read_body(fp)) == NULL) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if (0 == strcmp(b, "ssh-dss")) {
+		result->type = KEY_DSA;
+	}
+	else if (0 == strcmp(b, "ssh-rsa")) {
+		result->type = KEY_RSA;
+	}
+	else if (0 == strcmp(b, "ecdsa-sha2-nistp256")) {
+		result->type = KEY_ECDSA256;
+	}
+	else if (0 == strcmp(b, "ecdsa-sha2-nistp384")) {
+		result->type = KEY_ECDSA384;
+	}
+	else if (0 == strcmp(b, "ecdsa-sha2-nistp521")) {
+		result->type = KEY_ECDSA521;
+	}
+	else if (0 == strcmp(b, "ssh-ed25519")) {
+		result->type = KEY_ED25519;
+	}
+	else {
+		strncpy_s(errmsg, errmsg_len, "unsupported key algorithm", _TRUNCATE);
+		free(b);
+		goto error;
+	}
+	free(b);
 
-	// parse keyfile & decode blob
-	{
-	char line[200], buf[100];
-	BIO *bmem, *b64, *chain;
-	while (fgets(line, sizeof(line), fp) != NULL) {
-		if (strncmp(line, "PuTTY-User-Key-File-2: ", strlen("PuTTY-User-Key-File-2: ")) == 0) {
-			if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ssh-dss", strlen("ssh-dss")) == 0) {
-				result->type = KEY_DSA;
-			}
-			else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ssh-rsa", strlen("ssh-rsa")) == 0) {
-				result->type = KEY_RSA;
-			}
-			else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ecdsa-sha2-nistp256", strlen("ecdsa-sha2-nistp256")) == 0) {
-				result->type = KEY_ECDSA256;
-			}
-			else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ecdsa-sha2-nistp384", strlen("ecdsa-sha2-nistp384")) == 0) {
-				result->type = KEY_ECDSA384;
-			}
-			else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ecdsa-sha2-nistp521", strlen("ecdsa-sha2-nistp521")) == 0) {
-				result->type = KEY_ECDSA521;
-			}
-			else if (strncmp(line + strlen("PuTTY-User-Key-File-2: "), "ssh-ed25519", strlen("ssh-ed25519")) == 0) {
-				result->type = KEY_ED25519;
-			}
-			else {
-				strncpy_s(errmsg, errmsg_len, "not a PuTTY SSH-2 private key", _TRUNCATE);
-				goto error;
-			}
+	// encryption-type
+	if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Encryption")) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if ((encryption = ppk_read_body(fp)) == NULL) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if (strcmp(encryption, "aes256-cbc") == 0) {
+		ciphertype = get_cipher_by_name(encryption);
+	}
+	else if (strcmp(encryption, "none") == 0) {
+		ciphertype = get_cipher_by_name(encryption);
+	}
+	else {
+		strncpy_s(errmsg, errmsg_len, "unknown encryption type", _TRUNCATE);
+		goto error;
+	}
+
+	// key-comment-string
+	if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Comment")) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if ((comment = ppk_read_body(fp)) == NULL) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+
+	// public key
+	if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Public-Lines")) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if ((b = ppk_read_body(fp)) == NULL) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		free(b);
+		goto error;
+	}
+	lines = atoi(b);
+	free(b);
+	public_blob = buffer_init();
+	if (!ppk_read_blob(fp, lines, public_blob)) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+
+	if (fmt_version >= 3 && ciphertype->key_len != 0) {
+		size_t i;
+
+		// argon2-flavour
+		if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Key-Derivation")) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			goto error;
 		}
-		else if (strncmp(line, "Encryption: ", strlen("Encryption: ")) == 0) {
-			len = strlen(line + strlen("Encryption: "));
-			encname = (char *)malloc(len); // trim \n
-			strncpy_s(encname, len, line + strlen("Encryption: "), _TRUNCATE);
-			if (strcmp(encname, "aes256-cbc") == 0) {
-				// NOP
-			}
-			else if (strcmp(encname, "none") == 0) {
-				// NOP
-			}
-			else {
-				strncpy_s(errmsg, errmsg_len, "unknown encryption type", _TRUNCATE);
-				goto error;
-			}
+		if ((b = ppk_read_body(fp)) == NULL) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			free(b);
+			goto error;
 		}
-		else if (strncmp(line, "Comment: ", strlen("Comment: ")) == 0) {
-			len = strlen(line + strlen("Comment: "));
-			comment = (char *)malloc(len); // trim \n
-			strncpy_s(comment, len, line + strlen("Comment: "), _TRUNCATE);
+		if (!strcmp(b, "Argon2d")) {
+			params.type = Argon2_d;
 		}
-		else if (strncmp(line, "Private-MAC: ", strlen("Private-MAC: ")) == 0) {
-			len = strlen(line + strlen("Private-MAC: "));
-			private_mac = (char *)malloc(len); // trim \n
-			strncpy_s(private_mac, len, line + strlen("Private-MAC: "), _TRUNCATE);
+		else if (!strcmp(b, "Argon2i")) {
+			params.type = Argon2_i;
 		}
-		else if (strncmp(line, "Private-HASH: ", strlen("Private-HASH: ")) == 0) {
-			strncpy_s(errmsg, errmsg_len, "not a PuTTY SSH-2 private key", _TRUNCATE);
+		else if (!strcmp(b, "Argon2id")) {
+			params.type = Argon2_id;
+		}
+		else {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			free(b);
 			goto error;
 		}
-		else if (strncmp(line, "Public-Lines: ", strlen("Public-Lines: ")) == 0) {
-			len = atoi(line + strlen("Public-Lines: "));
-			b64 = BIO_new(BIO_f_base64());
-			bmem = BIO_new(BIO_s_mem());
-			for (i=0; i<len && fgets(line, sizeof(line), fp)!=NULL; i++) {
-				BIO_write(bmem, line, strlen(line));
-			}
-			BIO_flush(bmem);
-			chain = BIO_push(b64, bmem);
-			BIO_set_mem_eof_return(chain, 0);
-			while ((len2 = BIO_read(chain, buf, sizeof(buf))) > 0) {
-				buffer_append(pubkey, buf, len2);
-			}
-			BIO_free_all(chain);
+		free(b);
+
+		if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Argon2-Memory")) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			goto error;
 		}
-		else if (strncmp(line, "Private-Lines: ", strlen("Private-Lines: ")) == 0) {
-			len = atoi(line + strlen("Private-Lines: "));
-			b64 = BIO_new(BIO_f_base64());
-			bmem = BIO_new(BIO_s_mem());
-			for (i=0; i<len && fgets(line, sizeof(line), fp)!=NULL; i++) {
-				BIO_write(bmem, line, strlen(line));
-			}
-			BIO_flush(bmem);
-			chain = BIO_push(b64, bmem);
-			BIO_set_mem_eof_return(chain, 0);
-			while ((len2 = BIO_read(chain, buf, sizeof(buf))) > 0) {
-				buffer_append(prikey, buf, len2);
-			}
-			BIO_free_all(chain);
+		if ((b = ppk_read_body(fp)) == NULL) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			free(b);
+			goto error;
 		}
-		else {
-			strncpy_s(errmsg, errmsg_len, "not a PuTTY SSH-2 private key", _TRUNCATE);
+		if (!str_to_uint32_t(b, &params.argon2_mem)) {
+			free(b);
 			goto error;
 		}
-	}
-	}
+		free(b);
 
-	if (result->type == KEY_NONE || strlen(encname) == 0 || buffer_len(pubkey) == 0 || buffer_len(prikey) == 0) {
-		strncpy_s(errmsg, errmsg_len, "key file format error", _TRUNCATE);
-		goto error;
-	}
+		if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Argon2-Passes")) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			goto error;
+		}
+		if ((b = ppk_read_body(fp)) == NULL) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			free(b);
+			goto error;
+		}
+		if (!str_to_uint32_t(b, &params.argon2_passes)) {
+			free(b);
+			goto error;
+		}
+		free(b);
 
-	// decrypt prikey with aes256-cbc
-	if (strcmp(encname, "aes256-cbc") == 0) {
-		const EVP_MD *md = EVP_sha1();
-		EVP_MD_CTX *ctx = NULL;
-		unsigned char key[40], iv[32];
-		EVP_CIPHER_CTX *cipher_ctx = NULL;
-		char *decrypted = NULL;
-		int ret;
-
-		ctx = EVP_MD_CTX_new();
-		if (ctx == NULL) {
+		if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Argon2-Parallelism")) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
 			goto error;
 		}
+		if ((b = ppk_read_body(fp)) == NULL) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			free(b);
+			goto error;
+		}
+		if (!str_to_uint32_t(b, &params.argon2_parallelism)) {
+			free(b);
+			goto error;
+		}
+		free(b);
 
-		cipher_ctx = EVP_CIPHER_CTX_new();
-		if (cipher_ctx == NULL) {
-			EVP_MD_CTX_free(ctx);
+		if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Argon2-Salt")) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
 			goto error;
 		}
+		if ((b = ppk_read_body(fp)) == NULL) {
+			strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+			free(b);
+			goto error;
+		}
+		for (i = 0; b[i]; i += 2) {
+			if (isxdigit((unsigned char)b[i]) && b[i+1] &&
+			    isxdigit((unsigned char)b[i+1])) {
+				char s[3];
+				s[0] = b[i];
+				s[1] = b[i+1];
+				s[2] = '\0';
+				buffer_put_char(passphrase_salt, strtoul(s, NULL, 16));
+			}
+			else {
+				strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+				free(b);
+				goto error;
+			}
+		}
+		params.salt = buffer_ptr(passphrase_salt);
+		params.saltlen = buffer_len(passphrase_salt);
+		free(b);
+	}
 
-		EVP_DigestInit(ctx, md);
-		EVP_DigestUpdate(ctx, "\0\0\0\0", 4);
-		EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
-		EVP_DigestFinal(ctx, key, &len);
+	// private key
+	if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Private-Lines")) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if ((b = ppk_read_body(fp)) == NULL) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		free(b);
+		goto error;
+	}
+	lines = atoi(b);
+	free(b);
+	private_blob = buffer_init();
+	if (!ppk_read_blob(fp, lines, private_blob)) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
 
-		EVP_DigestInit(ctx, md);
-		EVP_DigestUpdate(ctx, "\0\0\0\1", 4);
-		EVP_DigestUpdate(ctx, passphrase, strlen(passphrase));
-		EVP_DigestFinal(ctx, key + 20, &len);
+	// hex-mac-data
+	if (!ppk_read_header(fp, header) || 0 != strcmp(header, "Private-MAC")) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
+	if ((mac = ppk_read_body(fp)) == NULL) {
+		strncpy_s(errmsg, errmsg_len, "file format error", _TRUNCATE);
+		goto error;
+	}
 
-		EVP_MD_CTX_free(ctx);
+	fclose(fp);
 
-		memset(iv, 0, sizeof(iv));
+	if (result->type == KEY_NONE || strlen(encryption) == 0 || buffer_len(public_blob) == 0 || buffer_len(private_blob) == 0) {
+		strncpy_s(errmsg, errmsg_len, "key file format error", _TRUNCATE);
+		goto error;
+	}
 
+	// derive key, iv, mackey
+	cipher_mac_keys_blob = buffer_init();
+	ssh2_ppk_derive_keys(fmt_version, ciphertype,
+	                     passphrase,
+	                     cipher_mac_keys_blob,
+	                     &cipherkey, &cipherkey_len,
+	                     &cipheriv, &cipheriv_len,
+	                     &mackey, &mackey_len,
+	                     &params);
+
+	// decrypt priate key with aes256-cbc
+	if (strcmp(encryption, "aes256-cbc") == 0) {
+		struct sshcipher_ctx *cc = NULL;
+		char *decrypted = NULL;
+		int ret;
+
 		// decrypt
-		cipher = get_cipher_by_name("aes256-cbc");
-		cipher_init_SSH2(&cc, cipher, key, 32, iv, 16, CIPHER_DECRYPT, pvar);
-		len = buffer_len(prikey);
+		ciphertype = get_cipher_by_name("aes256-cbc");
+		cipher_init_SSH2(&cc, ciphertype, cipherkey, 32, cipheriv, 16, CIPHER_DECRYPT, pvar);
+		len = buffer_len(private_blob);
 		decrypted = (char *)malloc(len);
-		ret = EVP_Cipher(cc->evp, decrypted, prikey->buf, len);
+		ret = EVP_Cipher(cc->evp, decrypted, private_blob->buf, len);
 		if (ret == 0) {
 			strncpy_s(errmsg, errmsg_len, "Key decrypt error", _TRUNCATE);
 			free(decrypted);
@@ -986,8 +1103,8 @@
 			cipher_free_SSH2(cc);
 			goto error;
 		}
-		buffer_clear(prikey);
-		buffer_append(prikey, decrypted, len);
+		buffer_clear(private_blob);
+		buffer_append(private_blob, decrypted, len);
 		free(decrypted);
 		cipher_free_SSH2(cc);
 	}
@@ -994,116 +1111,45 @@
 
 	// verity MAC
 	{
-	char realmac[41];
-	unsigned char binary[20];
-	buffer_t *macdata;
-
-	macdata = buffer_init();
-
-	len = strlen(get_ssh2_hostkey_type_name(result->type));
-	buffer_put_int(macdata, len);
-	buffer_append(macdata, get_ssh2_hostkey_type_name(result->type), len);
-	len = strlen(encname);
-	buffer_put_int(macdata, len);
-	buffer_append(macdata, encname, len);
-	len = strlen(comment);
-	buffer_put_int(macdata, len);
-	buffer_append(macdata, comment, len);
-	buffer_put_int(macdata, pubkey->len);
-	buffer_append(macdata, pubkey->buf, pubkey->len);
-	buffer_put_int(macdata, prikey->len);
-	buffer_append(macdata, prikey->buf, prikey->len);
-	
-	if (private_mac != NULL) {
-		unsigned char mackey[20];
-		char header[] = "putty-private-key-file-mac-key";
-		const EVP_MD *md = EVP_sha1();
-		EVP_MD_CTX *ctx = NULL;
-
-		ctx = EVP_MD_CTX_new();
-		if (ctx == NULL) {
-			goto error;
-		}
-
-		EVP_DigestInit(ctx, md);
-		EVP_DigestUpdate(ctx, header, sizeof(header)-1);
-		len = strlen(passphrase);
-		if (strcmp(encname, "aes256-cbc") == 0 && len > 0) {
-			EVP_DigestUpdate(ctx, passphrase, len);
-		}
-		EVP_DigestFinal(ctx, mackey, &len);
-		EVP_MD_CTX_free(ctx);
-
-		//hmac_sha1_simple(mackey, sizeof(mackey), macdata->buf, macdata->len, binary);
-		{
-		EVP_MD_CTX *ctx[2] = {0, 0};
-		unsigned char intermediate[20];
-		unsigned char foo[64];
+		unsigned char binary[32];
+		char realmac[sizeof(binary) * 2 + 1];
+		const EVP_MD *md;
+		buffer_t *macdata;
 		int i;
 
-		ctx[0] = EVP_MD_CTX_new();
-		if (ctx[0] == NULL) {
-			goto error;
-		}
-		ctx[1] = EVP_MD_CTX_new();
-		if (ctx[1] == NULL) {
-			EVP_MD_CTX_free(ctx[0]);
-			goto error;
-		}
+		macdata = buffer_init();
+		buffer_put_cstring(macdata, get_ssh2_hostkey_type_name(result->type));
+		buffer_put_cstring(macdata, encryption);
+		buffer_put_cstring(macdata, comment);
+		buffer_put_string(macdata, public_blob->buf, public_blob->len);
+		buffer_put_string(macdata, private_blob->buf, private_blob->len);
 
-		memset(foo, 0x36, sizeof(foo));
-		for (i = 0; i < sizeof(mackey) && i < sizeof(foo); i++) {
-			foo[i] ^= mackey[i];
+		if (fmt_version == 2) {
+			md = EVP_sha1();
 		}
-		EVP_DigestInit(ctx[0], md);
-		EVP_DigestUpdate(ctx[0], foo, sizeof(foo));
-
-		memset(foo, 0x5C, sizeof(foo));
-		for (i = 0; i < sizeof(mackey) && i < sizeof(foo); i++) {
-			foo[i] ^= mackey[i];
+		else {
+			md = EVP_sha256();
 		}
-		EVP_DigestInit(ctx[1], md);
-		EVP_DigestUpdate(ctx[1], foo, sizeof(foo));
+		mac_simple(md, (unsigned char *)mackey, mackey_len, macdata->buf, macdata->len, binary);
 
-		memset(foo, 0, sizeof(foo));
+		buffer_free(macdata);
 
-		EVP_DigestUpdate(ctx[0], macdata->buf, macdata->len);
-		EVP_DigestFinal(ctx[0], intermediate, &len);
-
-		EVP_DigestUpdate(ctx[1], intermediate, sizeof(intermediate));
-		EVP_DigestFinal(ctx[1], binary, &len);
-
-		EVP_MD_CTX_free(ctx[0]);
-		EVP_MD_CTX_free(ctx[1]);
+		for (i=0; i<EVP_MD_size(md); i++) {
+			sprintf(realmac + 2*i, "%02x", binary[i]);
 		}
 
-		memset(mackey, 0, sizeof(mackey));
-		
-	}
-	else {
-		strncpy_s(errmsg, errmsg_len, "key file format error", _TRUNCATE);
-		buffer_free(macdata);
-		goto error;
-	}
-
-	buffer_free(macdata);
-
-	for (i=0; i<20; i++) {
-		sprintf(realmac + 2*i, "%02x", binary[i]);
-	}
-
-	if (strcmp(private_mac, realmac) != 0) {
-		if (strcmp(encname, "aes256-cbc") == 0) {
-			strncpy_s(errmsg, errmsg_len, "wrong passphrase", _TRUNCATE);
-			*invalid_passphrase = TRUE;
-			goto error;
+		if (strcmp(mac, realmac) != 0) {
+			if (ciphertype->key_len > 0) {
+				strncpy_s(errmsg, errmsg_len, "wrong passphrase", _TRUNCATE);
+				*invalid_passphrase = TRUE;
+				goto error;
+			}
+			else {
+				strncpy_s(errmsg, errmsg_len, "MAC verify failed", _TRUNCATE);
+				goto error;
+			}
 		}
-		else {
-			strncpy_s(errmsg, errmsg_len, "MAC verify failed", _TRUNCATE);
-			goto error;
-		}
 	}
-	}
 
 	switch (result->type) {
 	case KEY_RSA:
@@ -1111,8 +1157,8 @@
 		char *pubkey_type, *pub, *pri;
 		BIGNUM *e, *n, *d, *iqmp, *p, *q;
 
-		pub = pubkey->buf;
-		pri = prikey->buf;
+		pub = public_blob->buf;
+		pri = private_blob->buf;
 		pubkey_type = buffer_get_string(&pub, NULL);
 		if (strcmp(pubkey_type, "ssh-rsa") != 0) {
 			strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
@@ -1160,8 +1206,8 @@
 		char *pubkey_type, *pub, *pri;
 		BIGNUM *p, *q, *g, *pub_key, *priv_key;
 
-		pub = pubkey->buf;
-		pri = prikey->buf;
+		pub = public_blob->buf;
+		pri = private_blob->buf;
 		pubkey_type = buffer_get_string(&pub, NULL);
 		if (strcmp(pubkey_type, "ssh-dss") != 0) {
 			strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
@@ -1212,8 +1258,8 @@
 		BIGNUM *exponent = NULL;
 		EC_POINT *q = NULL;
 
-		pub = pubkey->buf;
-		pri = prikey->buf;
+		pub = public_blob->buf;
+		pri = private_blob->buf;
 		pubkey_type = buffer_get_string(&pub, NULL);
 		if ((result->type == KEY_ECDSA256 && strcmp(pubkey_type, "ecdsa-sha2-nistp256") != 0) ||
 		    (result->type == KEY_ECDSA384 && strcmp(pubkey_type, "ecdsa-sha2-nistp384") != 0) ||
@@ -1267,8 +1313,8 @@
 		char *pubkey_type, *pub, *pri;
 		unsigned int pklen, sklen;
 		char *sk;
-		pub = pubkey->buf;
-		pri = prikey->buf;
+		pub = public_blob->buf;
+		pri = private_blob->buf;
 		pubkey_type = buffer_get_string(&pub, NULL);
 		if (strcmp(pubkey_type, "ssh-ed25519") != 0) {
 			strncpy_s(errmsg, errmsg_len, "key type error", _TRUNCATE);
@@ -1298,47 +1344,43 @@
 		break;
 	}
 
-	fclose(fp);
-
-	if (encname != NULL)
-		free(encname);
-
+	if (encryption != NULL)
+		free(encryption);
 	if (comment != NULL)
 		free(comment);
+	if (mac != NULL)
+		free(mac);
+	if (public_blob != NULL)
+		buffer_free(public_blob);
+	if (private_blob != NULL)
+		buffer_free(private_blob);
+	if (cipher_mac_keys_blob != NULL)
+		buffer_free(cipher_mac_keys_blob);
+	if (passphrase_salt != NULL)
+		buffer_free(passphrase_salt);
 
-	if (pubkey != NULL)
-		buffer_free(pubkey);
-
-	if (prikey != NULL)
-		buffer_free(prikey);
-
-	if (private_mac != NULL)
-		free(private_mac);
-
 	return (result);
 
 error:
 	if (result != NULL)
 		key_free(result);
-
 	if (fp != NULL)
 		fclose(fp);
-
-	if (encname != NULL)
-		free(encname);
-
+	if (encryption != NULL)
+		free(encryption);
 	if (comment != NULL)
 		free(comment);
+	if (mac != NULL)
+		free(mac);
+	if (public_blob != NULL)
+		buffer_free(public_blob);
+	if (private_blob != NULL)
+		buffer_free(private_blob);
+	if (cipher_mac_keys_blob != NULL)
+		buffer_free(cipher_mac_keys_blob);
+	if (passphrase_salt != NULL)
+		buffer_free(passphrase_salt);
 
-	if (pubkey != NULL)
-		buffer_free(pubkey);
-
-	if (prikey != NULL)
-		buffer_free(prikey);
-
-	if (private_mac != NULL)
-		free(private_mac);
-
 	return (NULL);
 }
 

Modified: trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj
===================================================================
--- trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj	2021-05-19 15:39:46 UTC (rev 9258)
@@ -65,7 +65,7 @@
     <ClCompile>
       <AdditionalOptions>/D"_CRT_SECURE_NO_DEPRECATE" %(AdditionalOptions)</AdditionalOptions>
       <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty;$(SolutionDir)argon2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRTDBG_MAP_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <FunctionLevelLinking>true</FunctionLevelLinking>
@@ -112,7 +112,7 @@
       <AdditionalOptions>/D"_CRT_SECURE_NO_DEPRECATE" %(AdditionalOptions)</AdditionalOptions>
       <Optimization>MaxSpeed</Optimization>
       <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
-      <AdditionalIncludeDirectories>$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty;$(SolutionDir)argon2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <StringPooling>true</StringPooling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
@@ -172,6 +172,7 @@
     <ClCompile Include="kex.c" />
     <ClCompile Include="key.c" />
     <ClCompile Include="keyfiles.c" />
+    <ClCompile Include="keyfiles-putty.c" />
     <ClCompile Include="mac.c" />
     <ClCompile Include="pkt.c" />
     <ClCompile Include="poly1305.c" />
@@ -211,6 +212,7 @@
     <ClInclude Include="kex.h" />
     <ClInclude Include="key.h" />
     <ClInclude Include="keyfiles.h" />
+    <ClInclude Include="keyfiles-putty.h" />
     <ClInclude Include="mac.h" />
     <ClInclude Include="pkt.h" />
     <ClInclude Include="poly1305.h" />
@@ -233,6 +235,10 @@
     <ResourceCompile Include="ttxssh.rc" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\argon2\argon2.v16.vcxproj">
+      <Project>{d33c59b8-e227-47d2-8f80-eda3e28bf995}</Project>
+      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+    </ProjectReference>
     <ProjectReference Include="..\puttyrev\puttyrev.v16.vcxproj">
       <Project>{61eb955f-2794-4607-860f-0aa296fa58bd}</Project>
       <ReferenceOutputAssembly>false</ReferenceOutputAssembly>

Modified: trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters
===================================================================
--- trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters	2021-05-19 15:39:46 UTC (rev 9258)
@@ -85,6 +85,9 @@
     <ClCompile Include="keyfiles.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="keyfiles-putty.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
     <ClCompile Include="mac.c">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -216,6 +219,9 @@
     <ClInclude Include="keyfiles.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="keyfiles-putty.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
     <ClInclude Include="mac.h">
       <Filter>Header Files</Filter>
     </ClInclude>

Modified: trunk/ttssh2/ttxssh/ttxssh.v8.vcproj
===================================================================
--- trunk/ttssh2/ttxssh/ttxssh.v8.vcproj	2021-05-19 15:09:48 UTC (rev 9257)
+++ trunk/ttssh2/ttxssh/ttxssh.v8.vcproj	2021-05-19 15:39:46 UTC (rev 9258)
@@ -48,7 +48,7 @@
 				Name="VCCLCompilerTool"
 				AdditionalOptions="/D"_CRT_SECURE_NO_DEPRECATE""
 				Optimization="0"
-				AdditionalIncludeDirectories="$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty"
+				AdditionalIncludeDirectories="$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty;$(SolutionDir)argon2;$(SolutionDir)argon2\compat"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRTDBG_MAP_ALLOC"
 				RuntimeLibrary="1"
 				EnableFunctionLevelLinking="true"
@@ -146,7 +146,7 @@
 				AdditionalOptions="/D"_CRT_SECURE_NO_DEPRECATE""
 				Optimization="2"
 				InlineFunctionExpansion="2"
-				AdditionalIncludeDirectories="$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty"
+				AdditionalIncludeDirectories="$(SolutionDir)..\teraterm\common;$(SolutionDir)..\libs\openssl\include;$(SolutionDir)..\teraterm\teraterm;$(SolutionDir)..\libs\zlib;$(SolutionDir)matcher;$(SolutionDir)putty;$(SolutionDir)argon2;$(SolutionDir)argon2\compat"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE"
 				StringPooling="true"
 				RuntimeLibrary="0"
@@ -324,6 +324,10 @@
 				>
 			</File>
 			<File
+				RelativePath="keyfiles-putty.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\teraterm\common\layer_for_unicode.h"
 				>
 			</File>
@@ -492,6 +496,10 @@
 				>
 			</File>
 			<File
+				RelativePath="keyfiles-putty.c"
+				>
+			</File>
+			<File
 				RelativePath="mac.c"
 				>
 			</File>


Ttssh2-commit メーリングリストの案内
Zurück zum Archiv-Index