Revision: 9256 https://osdn.net/projects/ttssh2/scm/svn/commits/9256 Author: nmaya Date: 2021-05-19 23:44:16 +0900 (Wed, 19 May 2021) Log Message: ----------- PuTTY private key format version 3 (PPK3) に対応した。 Argon2 の復号に The reference C implementation of Argon2 (https://github.com/P-H-C/phc-winner-argon2) を使用する。 Modified Paths: -------------- branches/4-stable/doc/convtext.bat branches/4-stable/doc/en/html/about/copyright.html branches/4-stable/doc/en/html/about/history.html branches/4-stable/doc/en/html/reference/develop.txt branches/4-stable/doc/ja/html/about/copyright.html branches/4-stable/doc/ja/html/about/history.html branches/4-stable/doc/ja/html/reference/develop.txt branches/4-stable/ttssh2/putty/libputty.c branches/4-stable/ttssh2/ttssh.v16.sln branches/4-stable/ttssh2/ttssh.v8.sln branches/4-stable/ttssh2/ttxssh/keyfiles.c branches/4-stable/ttssh2/ttxssh/keyfiles.h branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj Added Paths: ----------- branches/4-stable/libs/argon2/ branches/4-stable/ttssh2/argon2/ branches/4-stable/ttssh2/argon2/argon2.h branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj.filters branches/4-stable/ttssh2/argon2/argon2.v8.vcproj branches/4-stable/ttssh2/argon2/compat/ branches/4-stable/ttssh2/argon2/compat/stdint.h branches/4-stable/ttssh2/ttxssh/keyfiles-putty.c branches/4-stable/ttssh2/ttxssh/keyfiles-putty.h -------------- next part -------------- Modified: branches/4-stable/doc/convtext.bat =================================================================== --- branches/4-stable/doc/convtext.bat 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/convtext.bat 2021-05-19 14:44:16 UTC (rev 9256) @@ -16,6 +16,8 @@ %TOSJIS% -i ..\cygterm\COPYING -o %REF_J%\CygTerm+-LICENSE.txt -l unix %ZLIBCP% -i ..\libs\zlib\README -o %REF_E%\zlib-LICENSE.txt -l unix %ZLIBCP% -i ..\libs\zlib\README -o %REF_J%\zlib-LICENSE.txt -l unix +%ZLIBCP% -i ..\libs\argon2\LICENSE -o %REF_E%\argon2-LICENSE.txt -l unix +%ZLIBCP% -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: branches/4-stable/doc/en/html/about/copyright.html =================================================================== --- branches/4-stable/doc/en/html/about/copyright.html 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/en/html/about/copyright.html 2021-05-19 14:44:16 UTC (rev 9256) @@ -33,6 +33,7 @@ <li>OpenSSL ... <a href="../reference/OpenSSL-LICENSE.txt">Dual(both) license, OpenSSL License(Apache License 1.0) and SSLeay License(4-clause BSD license)</a></li> <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>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> @@ -164,6 +165,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: branches/4-stable/doc/en/html/about/history.html =================================================================== --- branches/4-stable/doc/en/html/about/history.html 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/en/html/about/history.html 2021-05-19 14:44:16 UTC (rev 9256) @@ -3281,6 +3281,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: branches/4-stable/doc/en/html/reference/develop.txt =================================================================== --- branches/4-stable/doc/en/html/reference/develop.txt 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/en/html/reference/develop.txt 2021-05-19 14:44:16 UTC (rev 9256) @@ -63,6 +63,7 @@ - zlib 1.2.11 (http://www.zlib.net/) - 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) +- The reference C implementation of Argon2 20190702 (https://github.com/P-H-C/phc-winner-argon2) * Notice for SVN committer @@ -136,7 +137,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. @@ -160,7 +161,10 @@ (3) Move 'libs' directory on the command prompt. And run buildSFMT.bat. (4) Modify version information in libs/SFMT/SFMT_version_for_teraterm.h if necessary. + 6. 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: branches/4-stable/doc/ja/html/about/copyright.html =================================================================== --- branches/4-stable/doc/ja/html/about/copyright.html 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/ja/html/about/copyright.html 2021-05-19 14:44:16 UTC (rev 9256) @@ -33,6 +33,7 @@ <li>OpenSSL ... <a href="../reference/OpenSSL-LICENSE.txt">OpenSSL License(Apache License 1.0) \x82\xC6 SSLeay License(\x8El\x8F\xF0\x8D\x80BSD\x83\x89\x83C\x83Z\x83\x93\x83X) \x82̃f\x83\x85\x83A\x83\x8B\x83\x89\x83C\x83Z\x83\x93\x83X(\x97\xBC\x95\xFB\x82\xAA\x93K\x97p\x82\xB3\x82\xEA\x82\xE9)</a></li> <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>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> @@ -157,6 +158,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: branches/4-stable/doc/ja/html/about/history.html =================================================================== --- branches/4-stable/doc/ja/html/about/history.html 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/ja/html/about/history.html 2021-05-19 14:44:16 UTC (rev 9256) @@ -3287,6 +3287,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: branches/4-stable/doc/ja/html/reference/develop.txt =================================================================== --- branches/4-stable/doc/ja/html/reference/develop.txt 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/doc/ja/html/reference/develop.txt 2021-05-19 14:44:16 UTC (rev 9256) @@ -65,6 +65,7 @@ - zlib 1.2.11 (http://www.zlib.net/) - 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) +- 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 @@ -141,7 +142,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 @@ -165,7 +167,11 @@ (3) \x83R\x83}\x83\x93\x83h\x83v\x83\x8D\x83\x93\x83v\x83g\x8Fォ\x82\xE7 libs \x83f\x83B\x83\x8C\x83N\x83g\x83\x8A\x82Ɉړ\xAE\x82\xB5\x81AbuildSFMT.bat \x82\xF0\x8E\xC0\x8Ds\x82\xB7\x82\xE9\x81B (4) \x95K\x97v\x82ɉ\x9E\x82\xB6\x82\xC4 libs/SFMT/SFMT_version_for_teraterm.h \x82̃o\x81[\x83W\x83\x87\x83\x93\x94ԍ\x86\x82\xF0\x8FC\x90\xB3\x82\xB7\x82\xE9\x81B + 6. 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\x89j Added: branches/4-stable/ttssh2/argon2/argon2.h =================================================================== --- branches/4-stable/ttssh2/argon2/argon2.h (rev 0) +++ branches/4-stable/ttssh2/argon2/argon2.h 2021-05-19 14:44:16 UTC (rev 9256) @@ -0,0 +1,443 @@ +/* + * Argon2 reference source code package - reference C implementations + * + * Copyright 2015 + * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves + * + * You may use this work under the terms of a Creative Commons CC0 1.0 + * License/Waiver or the Apache Public License 2.0, at your option. The terms of + * these licenses can be found at: + * + * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + * + * You should have received a copy of both of these licenses along with this + * software. If not, they may be obtained at the above URLs. + */ + +/* + * modified from original include/argon2.h + * - remove __declspec(dllexport) + */ + +#ifndef ARGON2_H +#define ARGON2_H + +#include <stdint.h> +#include <stddef.h> +#include <limits.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Symbols visibility control */ +#ifdef A2_VISCTL +#define ARGON2_PUBLIC __attribute__((visibility("default"))) +#define ARGON2_LOCAL __attribute__ ((visibility ("hidden"))) +#elif _MSC_VER +// #define ARGON2_PUBLIC __declspec(dllexport) +#define ARGON2_PUBLIC +#define ARGON2_LOCAL +#else +#define ARGON2_PUBLIC +#define ARGON2_LOCAL +#endif + +/* + * Argon2 input parameter restrictions + */ + +/* Minimum and maximum number of lanes (degree of parallelism) */ +#define ARGON2_MIN_LANES UINT32_C(1) +#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF) + +/* Minimum and maximum number of threads */ +#define ARGON2_MIN_THREADS UINT32_C(1) +#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF) + +/* Number of synchronization points between lanes per pass */ +#define ARGON2_SYNC_POINTS UINT32_C(4) + +/* Minimum and maximum digest size in bytes */ +#define ARGON2_MIN_OUTLEN UINT32_C(4) +#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */ +#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */ + +#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b)) +/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */ +#define ARGON2_MAX_MEMORY_BITS \ + ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1)) +#define ARGON2_MAX_MEMORY \ + ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS) + +/* Minimum and maximum number of passes */ +#define ARGON2_MIN_TIME UINT32_C(1) +#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum password length in bytes */ +#define ARGON2_MIN_PWD_LENGTH UINT32_C(0) +#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum associated data length in bytes */ +#define ARGON2_MIN_AD_LENGTH UINT32_C(0) +#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum salt length in bytes */ +#define ARGON2_MIN_SALT_LENGTH UINT32_C(8) +#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF) + +/* Minimum and maximum key length in bytes */ +#define ARGON2_MIN_SECRET UINT32_C(0) +#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF) + +/* Flags to determine which fields are securely wiped (default = no wipe). */ +#define ARGON2_DEFAULT_FLAGS UINT32_C(0) +#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0) +#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1) + +/* Global flag to determine if we are wiping internal memory buffers. This flag + * is defined in core.c and defaults to 1 (wipe internal memory). */ +extern int FLAG_clear_internal_memory; + +/* Error codes */ +typedef enum Argon2_ErrorCodes { + ARGON2_OK = 0, + + ARGON2_OUTPUT_PTR_NULL = -1, + + ARGON2_OUTPUT_TOO_SHORT = -2, + ARGON2_OUTPUT_TOO_LONG = -3, + + ARGON2_PWD_TOO_SHORT = -4, + ARGON2_PWD_TOO_LONG = -5, + + ARGON2_SALT_TOO_SHORT = -6, + ARGON2_SALT_TOO_LONG = -7, + + ARGON2_AD_TOO_SHORT = -8, + ARGON2_AD_TOO_LONG = -9, + + ARGON2_SECRET_TOO_SHORT = -10, + ARGON2_SECRET_TOO_LONG = -11, + + ARGON2_TIME_TOO_SMALL = -12, + ARGON2_TIME_TOO_LARGE = -13, + + ARGON2_MEMORY_TOO_LITTLE = -14, + ARGON2_MEMORY_TOO_MUCH = -15, + + ARGON2_LANES_TOO_FEW = -16, + ARGON2_LANES_TOO_MANY = -17, + + ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */ + ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */ + ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */ + ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */ + + ARGON2_MEMORY_ALLOCATION_ERROR = -22, + + ARGON2_FREE_MEMORY_CBK_NULL = -23, + ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24, + + ARGON2_INCORRECT_PARAMETER = -25, + ARGON2_INCORRECT_TYPE = -26, + + ARGON2_OUT_PTR_MISMATCH = -27, + + ARGON2_THREADS_TOO_FEW = -28, + ARGON2_THREADS_TOO_MANY = -29, + + ARGON2_MISSING_ARGS = -30, + + ARGON2_ENCODING_FAIL = -31, + + ARGON2_DECODING_FAIL = -32, + + ARGON2_THREAD_FAIL = -33, + + ARGON2_DECODING_LENGTH_FAIL = -34, + + ARGON2_VERIFY_MISMATCH = -35 +} argon2_error_codes; + +/* Memory allocator types --- for external allocation */ +typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate); +typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate); + +/* Argon2 external data structures */ + +/* + ***** + * Context: structure to hold Argon2 inputs: + * output array and its length, + * password and its length, + * salt and its length, + * secret and its length, + * associated data and its length, + * number of passes, amount of used memory (in KBytes, can be rounded up a bit) + * number of parallel threads that will be run. + * All the parameters above affect the output hash value. + * Additionally, two function pointers can be provided to allocate and + * deallocate the memory (if NULL, memory will be allocated internally). + * Also, three flags indicate whether to erase password, secret as soon as they + * are pre-hashed (and thus not needed anymore), and the entire memory + ***** + * Simplest situation: you have output array out[8], password is stored in + * pwd[32], salt is stored in salt[16], you do not have keys nor associated + * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with + * 4 parallel lanes. + * You want to erase the password, but you're OK with last pass not being + * erased. You want to use the default memory allocator. + * Then you initialize: + Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false) + */ +typedef struct Argon2_Context { + uint8_t *out; /* output array */ + uint32_t outlen; /* digest length */ + + uint8_t *pwd; /* password array */ + uint32_t pwdlen; /* password length */ + + uint8_t *salt; /* salt array */ + uint32_t saltlen; /* salt length */ + + uint8_t *secret; /* key array */ + uint32_t secretlen; /* key length */ + + uint8_t *ad; /* associated data array */ + uint32_t adlen; /* associated data length */ + + uint32_t t_cost; /* number of passes */ + uint32_t m_cost; /* amount of memory requested (KB) */ + uint32_t lanes; /* number of lanes */ + uint32_t threads; /* maximum number of threads */ + + uint32_t version; /* version number */ + + allocate_fptr allocate_cbk; /* pointer to memory allocator */ + deallocate_fptr free_cbk; /* pointer to memory deallocator */ + + uint32_t flags; /* array of bool options */ +} argon2_context; + +/* Argon2 primitive type */ +typedef enum Argon2_type { + Argon2_d = 0, + Argon2_i = 1, + Argon2_id = 2 +} argon2_type; + +/* Version of the algorithm */ +typedef enum Argon2_version { + ARGON2_VERSION_10 = 0x10, + ARGON2_VERSION_13 = 0x13, + ARGON2_VERSION_NUMBER = ARGON2_VERSION_13 +} argon2_version; + +/* + * Function that gives the string representation of an argon2_type. + * @param type The argon2_type that we want the string for + * @param uppercase Whether the string should have the first letter uppercase + * @return NULL if invalid type, otherwise the string representation. + */ +ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase); + +/* + * Function that performs memory-hard hashing with certain degree of parallelism + * @param context Pointer to the Argon2 internal structure + * @return Error code if smth is wrong, ARGON2_OK otherwise + */ +ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type); + +/** + * Hashes a password with Argon2i, producing an encoded hash + * @param t_cost Number of iterations + * @param m_cost Sets memory usage to m_cost kibibytes + * @param parallelism Number of threads and compute lanes + * @param pwd Pointer to password + * @param pwdlen Password size in bytes + * @param salt Pointer to salt + * @param saltlen Salt size in bytes + * @param hashlen Desired length of the hash in bytes + * @param encoded Buffer where to write the encoded hash + * @param encodedlen Size of the buffer (thus max size of the encoded hash) + * @pre Different parallelism levels will give different results + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); + +/** + * Hashes a password with Argon2i, producing a raw hash at @hash + * @param t_cost Number of iterations + * @param m_cost Sets memory usage to m_cost kibibytes + * @param parallelism Number of threads and compute lanes + * @param pwd Pointer to password + * @param pwdlen Password size in bytes + * @param salt Pointer to salt + * @param saltlen Salt size in bytes + * @param hash Buffer where to write the raw hash - updated by the function + * @param hashlen Desired length of the hash in bytes + * @pre Different parallelism levels will give different results + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); + +ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); + +ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); + +ARGON2_PUBLIC int argon2id_hash_encoded(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, + const void *pwd, const size_t pwdlen, + const void *salt, const size_t saltlen, + const size_t hashlen, char *encoded, + const size_t encodedlen); + +ARGON2_PUBLIC int argon2id_hash_raw(const uint32_t t_cost, + const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost, + const uint32_t parallelism, const void *pwd, + const size_t pwdlen, const void *salt, + const size_t saltlen, void *hash, + const size_t hashlen, char *encoded, + const size_t encodedlen, argon2_type type, + const uint32_t version); + +/** + * Verifies a password against an encoded string + * Encoded string is restricted as in validate_inputs() + * @param encoded String encoding parameters, salt, hash + * @param pwd Pointer to password + * @pre Returns ARGON2_OK if successful + */ +ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +ARGON2_PUBLIC int argon2id_verify(const char *encoded, const void *pwd, + const size_t pwdlen); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd, + const size_t pwdlen, argon2_type type); + +/** + * Argon2d: Version of Argon2 that picks memory blocks depending + * on the password and salt. Only for side-channel-free + * environment!! + ***** + * @param context Pointer to current Argon2 context + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2d_ctx(argon2_context *context); + +/** + * Argon2i: Version of Argon2 that picks memory blocks + * independent on the password and salt. Good for side-channels, + * but worse w.r.t. tradeoff attacks if only one pass is used. + ***** + * @param context Pointer to current Argon2 context + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2i_ctx(argon2_context *context); + +/** + * Argon2id: Version of Argon2 where the first half-pass over memory is + * password-independent, the rest are password-dependent (on the password and + * salt). OK against side channels (they reduce to 1/2-pass Argon2i), and + * better with w.r.t. tradeoff attacks (similar to Argon2d). + ***** + * @param context Pointer to current Argon2 context + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2id_ctx(argon2_context *context); + +/** + * Verify if a given password is correct for Argon2d hashing + * @param context Pointer to current Argon2 context + * @param hash The password hash to verify. The length of the hash is + * specified by the context outlen member + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash); + +/** + * Verify if a given password is correct for Argon2i hashing + * @param context Pointer to current Argon2 context + * @param hash The password hash to verify. The length of the hash is + * specified by the context outlen member + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash); + +/** + * Verify if a given password is correct for Argon2id hashing + * @param context Pointer to current Argon2 context + * @param hash The password hash to verify. The length of the hash is + * specified by the context outlen member + * @return Zero if successful, a non zero error code otherwise + */ +ARGON2_PUBLIC int argon2id_verify_ctx(argon2_context *context, + const char *hash); + +/* generic function underlying the above ones */ +ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash, + argon2_type type); + +/** + * Get the associated error message for given error code + * @return The error message associated with the given error code + */ +ARGON2_PUBLIC const char *argon2_error_message(int error_code); + +/** + * Returns the encoded hash length for the given input parameters + * @param t_cost Number of iterations + * @param m_cost Memory usage in kibibytes + * @param parallelism Number of threads; used to compute lanes + * @param saltlen Salt size in bytes + * @param hashlen Hash size in bytes + * @param type The argon2_type that we want the encoded length for + * @return The encoded hash length in bytes + */ +ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, + uint32_t parallelism, uint32_t saltlen, + uint32_t hashlen, argon2_type type); + +#if defined(__cplusplus) +} +#endif + +#endif Added: branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj =================================================================== --- branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj (rev 0) +++ branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj 2021-05-19 14:44:16 UTC (rev 9256) @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectName>argon2</ProjectName> + <ProjectGuid>{D33C59B8-E227-47D2-8F80-EDA3E28BF995}</ProjectGuid> + <RootNamespace>argon2</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>NotSet</CharacterSet> + <WholeProgramOptimization>false</WholeProgramOptimization> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>NotSet</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>16.0.31201.295</_ProjectFileVersion> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <OutDir>$(ProjectDir)$(Configuration)\</OutDir> + <IntDir>$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <OutDir>$(ProjectDir)$(Configuration)\</OutDir> + <IntDir>$(Configuration)\</IntDir> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)..\libs\argon2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)..\libs\argon2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + </ClCompile> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\..\libs\argon2\src\blake2\blake2-impl.h" /> + <ClInclude Include="..\..\libs\argon2\src\blake2\blake2.h" /> + <ClInclude Include="..\..\libs\argon2\src\blake2\blamka-round-opt.h" /> + <ClInclude Include="..\..\libs\argon2\src\blake2\blamka-round-ref.h" /> + <ClInclude Include="..\..\libs\argon2\src\core.h" /> + <ClInclude Include="..\..\libs\argon2\src\encoding.h" /> + <ClInclude Include="..\..\libs\argon2\src\ref.h" /> + <ClInclude Include="..\..\libs\argon2\src\thread.h" /> + <ClInclude Include="argon2.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\libs\argon2\src\argon2.c" /> + <ClCompile Include="..\..\libs\argon2\src\blake2\blake2b.c" /> + <ClCompile Include="..\..\libs\argon2\src\core.c" /> + <ClCompile Include="..\..\libs\argon2\src\encoding.c" /> + <ClCompile Include="..\..\libs\argon2\src\ref.c" /> + <ClCompile Include="..\..\libs\argon2\src\thread.c" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file Added: branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj.filters =================================================================== --- branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj.filters (rev 0) +++ branches/4-stable/ttssh2/argon2/argon2.v16.vcxproj.filters 2021-05-19 14:44:16 UTC (rev 9256) @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{ab6de084-0bb8-45ae-bf67-583bc1c7f28d}</UniqueIdentifier> + </Filter> + <Filter Include="Source File"> + <UniqueIdentifier>{7be7b0e1-cba8-4d3d-bbfd-a06bf605c2a9}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\libs\argon2\src\blake2\blake2-impl.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\blake2\blake2.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\blake2\blamka-round-opt.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\blake2\blamka-round-ref.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\core.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\encoding.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\ref.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\libs\argon2\src\thread.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="argon2.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\libs\argon2\src\argon2.c"> + <Filter>Source File</Filter> + </ClCompile> + <ClCompile Include="..\..\libs\argon2\src\blake2\blake2b.c"> + <Filter>Source File</Filter> + </ClCompile> + <ClCompile Include="..\..\libs\argon2\src\core.c"> + <Filter>Source File</Filter> + </ClCompile> + <ClCompile Include="..\..\libs\argon2\src\encoding.c"> + <Filter>Source File</Filter> + </ClCompile> + <ClCompile Include="..\..\libs\argon2\src\ref.c"> + <Filter>Source File</Filter> + </ClCompile> + <ClCompile Include="..\..\libs\argon2\src\thread.c"> + <Filter>Source File</Filter> + </ClCompile> + </ItemGroup> +</Project> \ No newline at end of file Added: branches/4-stable/ttssh2/argon2/argon2.v8.vcproj =================================================================== --- branches/4-stable/ttssh2/argon2/argon2.v8.vcproj (rev 0) +++ branches/4-stable/ttssh2/argon2/argon2.v8.vcproj 2021-05-19 14:44:16 UTC (rev 9256) @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="shift_jis"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="argon2" + ProjectGUID="{D33C59B8-E227-47D2-8F80-EDA3E28BF995}" + RootNamespace="argon2" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(ProjectDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="0" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="$(ProjectDir);$(ProjectDir)compat;$(SolutionDir)..\libs\argon2\src" + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE" + MinimalRebuild="false" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + WarningLevel="3" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(ProjectDir)$(ConfigurationName)" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="4" + CharacterSet="0" + WholeProgramOptimization="0" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(ProjectDir);$(ProjectDir)compat;$(SolutionDir)..\libs\argon2\src" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE" + RuntimeLibrary="0" + WarningLevel="3" + Detect64BitPortabilityProblems="false" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Header Files" + > + <File + RelativePath="..\..\libs\argon2\src\blake2\blake2-impl.h" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\blake2\blake2.h" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\blake2\blamka-round-ref.h" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\core.h" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\encoding.h" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\ref.h" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\thread.h" + > + </File> + </Filter> + <Filter + Name="Source File" + > + <File + RelativePath="..\..\libs\argon2\src\argon2.c" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\blake2\blake2b.c" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\core.c" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\encoding.c" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\ref.c" + > + </File> + <File + RelativePath="..\..\libs\argon2\src\thread.c" + > + </File> + </Filter> + <File + RelativePath="argon2.h" + > + </File> + <File + RelativePath="compat\stdint.h" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Added: branches/4-stable/ttssh2/argon2/compat/stdint.h =================================================================== --- branches/4-stable/ttssh2/argon2/compat/stdint.h (rev 0) +++ branches/4-stable/ttssh2/argon2/compat/stdint.h 2021-05-19 14:44:16 UTC (rev 9256) @@ -0,0 +1,17 @@ +/* + * Visual Studio 2008 or earlier doesn't have stdint.h + */ + +#if (_MSC_VER < 1300) + typedef unsigned char uint8_t; + typedef unsigned short uint32_t; +#else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; +#endif +typedef unsigned __int64 uint64_t; + +#define UINT32_MAX _UI32_MAX + +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 Modified: branches/4-stable/ttssh2/putty/libputty.c =================================================================== --- branches/4-stable/ttssh2/putty/libputty.c 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/putty/libputty.c 2021-05-19 14:44:16 UTC (rev 9256) @@ -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: branches/4-stable/ttssh2/ttssh.v16.sln =================================================================== --- branches/4-stable/ttssh2/ttssh.v16.sln 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttssh.v16.sln 2021-05-19 14:44:16 UTC (rev 9256) @@ -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: branches/4-stable/ttssh2/ttssh.v8.sln =================================================================== --- branches/4-stable/ttssh2/ttssh.v8.sln 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttssh.v8.sln 2021-05-19 14:44:16 UTC (rev 9256) @@ -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 Added: branches/4-stable/ttssh2/ttxssh/keyfiles-putty.c =================================================================== --- branches/4-stable/ttssh2/ttxssh/keyfiles-putty.c (rev 0) +++ branches/4-stable/ttssh2/ttxssh/keyfiles-putty.c 2021-05-19 14:44:16 UTC (rev 9256) @@ -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; +} Added: branches/4-stable/ttssh2/ttxssh/keyfiles-putty.h =================================================================== --- branches/4-stable/ttssh2/ttxssh/keyfiles-putty.h (rev 0) +++ branches/4-stable/ttssh2/ttxssh/keyfiles-putty.h 2021-05-19 14:44:16 UTC (rev 9256) @@ -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: branches/4-stable/ttssh2/ttxssh/keyfiles.c =================================================================== --- branches/4-stable/ttssh2/ttxssh/keyfiles.c 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttxssh/keyfiles.c 2021-05-19 14:44:16 UTC (rev 9256) @@ -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> @@ -729,7 +732,6 @@ * Private-Lines: 1 * Base64... * Private-MAC: Base16... - * Private-Hash: Base16... (PuTTY-User-Key-File-1) ??? * * for "ssh-rsa", it will be composed of * @@ -804,14 +806,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)); @@ -820,149 +824,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, ¶ms.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, ¶ms.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, ¶ms.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, + ¶ms); + + // 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); @@ -969,8 +1086,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); } @@ -977,116 +1094,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: @@ -1094,8 +1140,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); @@ -1143,8 +1189,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); @@ -1195,8 +1241,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) || @@ -1250,8 +1296,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); @@ -1281,47 +1327,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: branches/4-stable/ttssh2/ttxssh/keyfiles.h =================================================================== --- branches/4-stable/ttssh2/ttxssh/keyfiles.h 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttxssh/keyfiles.h 2021-05-19 14:44:16 UTC (rev 9256) @@ -90,6 +90,7 @@ {SSH2_KEYFILE_TYPE_OPENSSH, "-----BEGIN PRIVATE KEY-----"}, {SSH2_KEYFILE_TYPE_OPENSSH, "-----BEGIN OPENSSH PRIVATE KEY-----"}, {SSH2_KEYFILE_TYPE_PUTTY, "PuTTY-User-Key-File-2"}, + {SSH2_KEYFILE_TYPE_PUTTY, "PuTTY-User-Key-File-3"}, {SSH2_KEYFILE_TYPE_SECSH, "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"}, {SSH2_KEYFILE_TYPE_NONE, NULL}, Modified: branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj =================================================================== --- branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj 2021-05-19 14:44:16 UTC (rev 9256) @@ -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> @@ -177,6 +177,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" /> @@ -212,6 +213,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" /> @@ -234,6 +236,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: branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters =================================================================== --- branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttxssh/ttxssh.v16.vcxproj.filters 2021-05-19 14:44:16 UTC (rev 9256) @@ -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: branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj =================================================================== --- branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj 2021-05-19 14:11:26 UTC (rev 9255) +++ branches/4-stable/ttssh2/ttxssh/ttxssh.v8.vcproj 2021-05-19 14:44:16 UTC (rev 9256) @@ -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" @@ -312,6 +312,10 @@ > </File> <File + RelativePath="keyfiles-putty.h" + > + </File> + <File RelativePath="mac.h" > </File> @@ -488,6 +492,10 @@ > </File> <File + RelativePath="keyfiles-putty.c" + > + </File> + <File RelativePath="mac.c" > </File>